Merge branch 'master' of github.com:FreeRDP/xrdp

This commit is contained in:
Jay Sorg 2012-06-21 21:36:03 -07:00
commit 608101fbca
34 changed files with 1825 additions and 123 deletions

View File

@ -325,9 +325,11 @@ g_getchar(void)
}
/*****************************************************************************/
/*Returns 0 on success*/
int APP_CC
g_tcp_set_no_delay(int sck)
{
int ret = 1 ; /*error*/
#if defined(_WIN32)
int option_value;
int option_len;
@ -345,11 +347,55 @@ g_tcp_set_no_delay(int sck)
{
option_value = 1;
option_len = sizeof(option_value);
setsockopt(sck, IPPROTO_TCP, TCP_NODELAY, (char*)&option_value,
option_len);
if(setsockopt(sck, IPPROTO_TCP, TCP_NODELAY, (char*)&option_value,
option_len)==0)
{
ret = 0 ; /* success */
}
}
}
return 0;
else
{
g_writeln("Error getting tcp_nodelay");
}
return ret;
}
/*****************************************************************************/
/*Returns 0 on success*/
int APP_CC
g_tcp_set_keepalive(int sck)
{
int ret = 1 ; /*error*/
#if defined(_WIN32)
int option_value;
int option_len;
#else
int option_value;
unsigned int option_len;
#endif
option_len = sizeof(option_value);
/* SOL_TCP IPPROTO_TCP */
if (getsockopt(sck, SOL_SOCKET, SO_KEEPALIVE, (char*)&option_value,
&option_len) == 0)
{
if (option_value == 0)
{
option_value = 1;
option_len = sizeof(option_value);
if(setsockopt(sck, SOL_SOCKET, SO_KEEPALIVE, (char*)&option_value,
option_len)==0)
{
ret = 0 ; /* success */
}
}
}
else
{
g_writeln("Error getting tcp_keepalive");
}
return ret;
}
/*****************************************************************************/
@ -1077,29 +1123,44 @@ g_obj_wait(tbus* read_objs, int rcount, tbus* write_objs, int wcount,
ptime = &time;
}
FD_ZERO(&rfds);
FD_ZERO(&wfds);
for (i = 0; i < rcount; i++)
{
sck = (int)(read_objs[i]);
if (sck > 0) {
FD_SET(sck, &rfds);
if (sck > max)
{
max = sck;
FD_ZERO(&wfds);
/*Find the highest descriptor number in read_obj */
if(read_objs!=NULL){
for (i = 0; i < rcount; i++)
{
sck = (int)(read_objs[i]);
if (sck > 0) {
FD_SET(sck, &rfds);
if (sck > max)
{
max = sck; /*max holds the highest socket/descriptor number */
}
}
}
}
for (i = 0; i < wcount; i++)
else if(rcount>0)
{
sck = (int)(write_objs[i]);
if (sck > 0) {
FD_SET(sck, &wfds);
if (sck > max)
{
max = sck;
g_writeln("Programming error read_objs is null");
return 1; /*error*/
}
if(write_objs!=NULL){
for (i = 0; i < wcount; i++)
{
sck = (int)(write_objs[i]);
if (sck > 0) {
FD_SET(sck, &wfds);
if (sck > max)
{
max = sck; /*max holds the highest socket/descriptor number */
}
}
}
}
else if(wcount>0)
{
g_writeln("Programming error write_objs is null");
return 1; /*error*/
}
res = select(max + 1, &rfds, &wfds, 0, ptime);
if (res < 0)
{
@ -1111,7 +1172,7 @@ g_obj_wait(tbus* read_objs, int rcount, tbus* write_objs, int wcount,
{
return 0;
}
return 1;
return 1; /*error*/
}
return 0;
#endif
@ -1576,7 +1637,32 @@ g_strdup(const char* in)
}
return p;
}
/*****************************************************************************/
/* if in = 0, return 0 else return newly alloced copy of input string
* if the input string is larger than maxlen the returned string will be
* truncated. All strings returned will include null termination*/
char* APP_CC
g_strndup(const char* in, const unsigned int maxlen)
{
int len;
char* p;
if (in == 0)
{
return 0;
}
len = g_strlen(in);
if(len>maxlen)
{
len = maxlen-1 ;
}
p = (char*)g_malloc(len + 2, 0);
if (p != NULL)
{
g_strncpy(p, in,len+1);
}
return p;
}
/*****************************************************************************/
int APP_CC
g_strcmp(const char* c1, const char* c2)

View File

@ -64,6 +64,8 @@ g_getchar(void);
int APP_CC
g_tcp_set_no_delay(int sck);
int APP_CC
g_tcp_set_keepalive(int sck);
int APP_CC
g_tcp_socket(void);
int APP_CC
g_tcp_local_socket(void);
@ -178,6 +180,8 @@ char* APP_CC
g_strcat(char* dest, const char* src);
char* APP_CC
g_strdup(const char* in);
char* APP_CC
g_strndup(const char* in, const unsigned int maxlen);
int APP_CC
g_strcmp(const char* c1, const char* c2);
int APP_CC

147
common/rail.h Normal file
View File

@ -0,0 +1,147 @@
/**
* xrdp: A Remote Desktop Protocol server.
*
* Copyright (C) Jay Sorg 2012
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#if !defined(_RAIL_H)
#define _RAIL_H
/*
ORDER_TYPE_WINDOW
WINDOW_ORDER_TYPE_WINDOW
WINDOW_ORDER_ICON
WINDOW_ORDER_CACHED_ICON
WINDOW_ORDER_STATE_DELETED
WINDOW_ORDER_STATE_NEW on
WINDOW_ORDER_STATE_NEW off
WINDOW_ORDER_TYPE_NOTIFY
WINDOW_ORDER_STATE_DELETED
WINDOW_ORDER_STATE_NEW on
WINDOW_ORDER_STATE_NEW off
WINDOW_ORDER_TYPE_DESKTOP
WINDOW_ORDER_FIELD_DESKTOP_NONE on
WINDOW_ORDER_FIELD_DESKTOP_NONE off
*/
/* Window Order Header Flags */
#define WINDOW_ORDER_TYPE_WINDOW 0x01000000
#define WINDOW_ORDER_TYPE_NOTIFY 0x02000000
#define WINDOW_ORDER_TYPE_DESKTOP 0x04000000
#define WINDOW_ORDER_STATE_NEW 0x10000000
#define WINDOW_ORDER_STATE_DELETED 0x20000000
#define WINDOW_ORDER_FIELD_OWNER 0x00000002
#define WINDOW_ORDER_FIELD_STYLE 0x00000008
#define WINDOW_ORDER_FIELD_SHOW 0x00000010
#define WINDOW_ORDER_FIELD_TITLE 0x00000004
#define WINDOW_ORDER_FIELD_CLIENT_AREA_OFFSET 0x00004000
#define WINDOW_ORDER_FIELD_CLIENT_AREA_SIZE 0x00010000
#define WINDOW_ORDER_FIELD_RP_CONTENT 0x00020000
#define WINDOW_ORDER_FIELD_ROOT_PARENT 0x00040000
#define WINDOW_ORDER_FIELD_WND_OFFSET 0x00000800
#define WINDOW_ORDER_FIELD_WND_CLIENT_DELTA 0x00008000
#define WINDOW_ORDER_FIELD_WND_SIZE 0x00000400
#define WINDOW_ORDER_FIELD_WND_RECTS 0x00000100
#define WINDOW_ORDER_FIELD_VIS_OFFSET 0x00001000
#define WINDOW_ORDER_FIELD_VISIBILITY 0x00000200
#define WINDOW_ORDER_FIELD_ICON_BIG 0x00002000
#define WINDOW_ORDER_ICON 0x40000000
#define WINDOW_ORDER_CACHED_ICON 0x80000000
#define WINDOW_ORDER_FIELD_NOTIFY_VERSION 0x00000008
#define WINDOW_ORDER_FIELD_NOTIFY_TIP 0x00000001
#define WINDOW_ORDER_FIELD_NOTIFY_INFO_TIP 0x00000002
#define WINDOW_ORDER_FIELD_NOTIFY_STATE 0x00000004
#define WINDOW_ORDER_FIELD_DESKTOP_NONE 0x00000001
#define WINDOW_ORDER_FIELD_DESKTOP_HOOKED 0x00000002
#define WINDOW_ORDER_FIELD_DESKTOP_ARC_COMPLETED 0x00000004
#define WINDOW_ORDER_FIELD_DESKTOP_ARC_BEGAN 0x00000008
#define WINDOW_ORDER_FIELD_DESKTOP_ZORDER 0x00000010
#define WINDOW_ORDER_FIELD_DESKTOP_ACTIVE_WND 0x00000020
struct rail_icon_info
{
int bpp;
int width;
int height;
int cmap_bytes;
int mask_bytes;
int data_bytes;
char* mask;
char* cmap;
char* data;
};
struct rail_window_rect
{
short left;
short top;
short right;
short bottom;
};
struct rail_notify_icon_infotip
{
int timeout;
int flags;
char* text;
char* title;
};
struct rail_window_state_order
{
int owner_window_id;
int style;
int extended_style;
int show_state;
char* title_info;
int client_offset_x;
int client_offset_y;
int client_area_width;
int client_area_height;
int rp_content;
int root_parent_handle;
int window_offset_x;
int window_offset_y;
int window_client_delta_x;
int window_client_delta_y;
int window_width;
int window_height;
int num_window_rects;
struct rail_window_rect* window_rects;
int visible_offset_x;
int visible_offset_y;
int num_visibility_rects;
struct rail_window_rect* visibility_rects;
};
struct rail_notify_state_order
{
int version;
char* tool_tip;
struct rail_notify_icon_infotip infotip;
int state;
int icon_cache_entry;
int icon_cache_id;
struct rail_icon_info icon_info;
};
struct rail_monitored_desktop_order
{
int active_window_id;
int num_window_ids;
int* window_ids;
};
#endif

View File

@ -69,7 +69,7 @@ trans_delete(struct trans* self)
/*****************************************************************************/
int APP_CC
trans_get_wait_objs(struct trans* self, tbus* objs, int* count, int* timeout)
trans_get_wait_objs(struct trans* self, tbus* objs, int* count)
{
if (self == 0)
{

View File

@ -64,7 +64,7 @@ trans_create(int mode, int in_size, int out_size);
void APP_CC
trans_delete(struct trans* self);
int APP_CC
trans_get_wait_objs(struct trans* self, tbus* objs, int* count, int* timeout);
trans_get_wait_objs(struct trans* self, tbus* objs, int* count);
int APP_CC
trans_check_wait_objs(struct trans* self);
int APP_CC

View File

@ -74,6 +74,12 @@ struct xrdp_client_info
int offscreen_cache_size;
int offscreen_cache_entries;
int rfx;
/* CAPSETTYPE_RAIL */
int rail_support_level;
/* CAPSETTYPE_WINDOW */
int wnd_support_level;
int wnd_num_icon_caches;
int wnd_num_icon_cache_entries;
};
#endif

View File

@ -962,7 +962,7 @@ static void DEFAULT_CC
lfreerdp_pointer_system(rdpContext* context,
POINTER_SYSTEM_UPDATE* pointer_system)
{
LLOGLN(0, ("lfreerdp_pointer_system:"));
LLOGLN(0, ("lfreerdp_pointer_system: - no code here"));
}
/******************************************************************************/
@ -1379,7 +1379,13 @@ mod_exit(struct mod* mod)
{
return 0;
}
if(mod->inst == NULL)
{
LLOGLN(0, ("mod_exit - null pointer for inst:"));
g_free(mod);
return 0 ;
}
freerdp_disconnect(mod->inst);
if ((mod->vmaj == 1) && (mod->vmin == 0) && (mod->vrev == 1))
{
/* this version has a bug with double free in freerdp_free */

View File

@ -50,7 +50,8 @@ libxrdp_la_SOURCES = \
xrdp_sec.c \
xrdp_tcp.c \
xrdp_bitmap_compress.c \
xrdp_jpeg_compress.c
xrdp_jpeg_compress.c \
xrdp_orders_rail.c
libxrdp_la_LDFLAGS = \
$(EXTRA_FLAGS)

View File

@ -75,10 +75,12 @@ libxrdp_process_data(struct xrdp_session* session)
int rv;
int code;
int term;
int dead_lock_counter;
term = 0;
cont = 1;
rv = 0;
dead_lock_counter = 0 ;
while ((cont || !session->up_and_running) && !term)
{
if (session->is_term != 0)
@ -102,6 +104,7 @@ libxrdp_process_data(struct xrdp_session* session)
session->up_and_running = 0;
break;
case 0:
dead_lock_counter ++ ;
break;
case RDP_PDU_CONFIRM_ACTIVE: /* 3 */
xrdp_rdp_process_confirm_active((struct xrdp_rdp*)session->rdp,
@ -118,7 +121,16 @@ libxrdp_process_data(struct xrdp_session* session)
break;
default:
g_writeln("unknown in libxrdp_process_data");
dead_lock_counter ++ ;
break;
}
if(dead_lock_counter>100000)
{
/*This situation can happen and this is a workaround*/
cont = 0 ;
g_writeln("Serious programming error we were locked in a deadly loop") ;
g_writeln("remaining :%d",session->s->end-session->s->next_packet);
session->s->next_packet = 0;
}
if (cont)
{
@ -616,7 +628,10 @@ libxrdp_reset(struct xrdp_session* session,
}
/* process till up and running */
session->up_and_running = 0;
libxrdp_process_data(session);
if(libxrdp_process_data(session)!=0)
{
g_writeln("non handled error from libxrdp_process_data");
}
return 0;
}
@ -658,6 +673,11 @@ libxrdp_query_channel(struct xrdp_session* session, int index,
rdp = (struct xrdp_rdp*)session->rdp;
mcs = rdp->sec_layer->mcs_layer;
if(mcs->channel_list==NULL)
{
g_writeln("libxrdp_query_channel - No channel initialized");
return 1 ;
}
count = mcs->channel_list->count;
if (index < 0 || index >= count)
{
@ -668,6 +688,7 @@ libxrdp_query_channel(struct xrdp_session* session, int index,
if (channel_item == 0)
{
/* this should not happen */
g_writeln("libxrdp_query_channel - channel item is 0");
return 1;
}
if (channel_name != 0)
@ -695,6 +716,11 @@ libxrdp_get_channel_id(struct xrdp_session* session, char* name)
rdp = (struct xrdp_rdp*)session->rdp;
mcs = rdp->sec_layer->mcs_layer;
if(mcs->channel_list==NULL)
{
g_writeln("libxrdp_get_channel_id No channel initialized");
return -1 ;
}
count = mcs->channel_list->count;
for (index = 0; index < count; index++)
{
@ -737,6 +763,7 @@ libxrdp_send_to_channel(struct xrdp_session* session, int channel_id,
s_mark_end(s);
if (xrdp_channel_send(chan, s, channel_id, total_data_len, flags) != 0)
{
g_writeln("Debug - data NOT sent to channel");
free_stream(s);
return 1;
}

View File

@ -325,6 +325,8 @@ xrdp_orders_send(struct xrdp_orders* self);
int APP_CC
xrdp_orders_force_send(struct xrdp_orders* self);
int APP_CC
xrdp_orders_check(struct xrdp_orders* self, int max_size);
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

View File

@ -35,7 +35,11 @@ static struct mcs_channel_item* APP_CC
xrdp_channel_get_item(struct xrdp_channel* self, int channel_id)
{
struct mcs_channel_item* channel;
if(self->mcs_layer->channel_list==NULL)
{
g_writeln("xrdp_channel_get_item - No channel initialized");
return NULL ;
}
channel = (struct mcs_channel_item*)
list_get_item(self->mcs_layer->channel_list, channel_id);
return channel;
@ -62,6 +66,7 @@ xrdp_channel_delete(struct xrdp_channel* self)
{
return;
}
g_memset(self,0,sizeof(struct xrdp_channel));
g_free(self);
}
@ -88,8 +93,9 @@ xrdp_channel_send(struct xrdp_channel* self, struct stream* s, int channel_id,
struct mcs_channel_item* channel;
channel = xrdp_channel_get_item(self, channel_id);
if (channel == 0)
if (channel == NULL)
{
g_writeln("xrdp_channel_send - no such channel");
return 1;
}
s_pop_layer(s, channel_hdr);
@ -101,6 +107,7 @@ xrdp_channel_send(struct xrdp_channel* self, struct stream* s, int channel_id,
out_uint32_le(s, flags);
if (xrdp_sec_send(self->sec_layer, s, channel->chanid) != 0)
{
g_writeln("xrdp_channel_send - failure sending data");
return 1;
}
return 0;
@ -159,13 +166,14 @@ xrdp_channel_process(struct xrdp_channel* self, struct stream* s,
int channel_id;
struct mcs_channel_item* channel;
/* this assumes that the channels are in order of chanid(mcs channel id)
but they should be, see xrdp_sec_process_mcs_data_channels
the first channel should be MCS_GLOBAL_CHANNEL + 1, second
one should be MCS_GLOBAL_CHANNEL + 2, and so on */
channel_id = (chanid - MCS_GLOBAL_CHANNEL) - 1;
channel = xrdp_channel_get_item(self, channel_id);
if (channel == 0)
if (channel == NULL)
{
g_writeln("xrdp_channel_process, channel not found");
return 1;

View File

@ -65,11 +65,15 @@ xrdp_mcs_delete(struct xrdp_mcs* self)
}
list_delete(self->channel_list);
xrdp_iso_delete(self->iso_layer);
/* make sure we get null pointer exception if struct is used again. */
DEBUG(("xrdp_mcs_delete processed"))
g_memset(self,0,sizeof(struct xrdp_mcs)) ;
g_free(self);
}
/*****************************************************************************/
/* returns error */
/* This function sends channel join confirm*/
/* returns error = 1 ok = 0*/
static int APP_CC
xrdp_mcs_send_cjcf(struct xrdp_mcs* self, int userid, int chanid)
{
@ -87,7 +91,7 @@ xrdp_mcs_send_cjcf(struct xrdp_mcs* self, int userid, int chanid)
out_uint8(s, (MCS_CJCF << 2) | 2);
out_uint8(s, 0);
out_uint16_be(s, userid);
out_uint16_be(s, chanid);
out_uint16_be(s, chanid); /* TODO Explain why we send this two times */
out_uint16_be(s, chanid);
s_mark_end(s);
if (xrdp_iso_send(self->iso_layer, s) != 0)
@ -122,20 +126,33 @@ xrdp_mcs_recv(struct xrdp_mcs* self, struct stream* s, int* chan)
}
in_uint8(s, opcode);
appid = opcode >> 2;
if (appid == MCS_DPUM)
if (appid == MCS_DPUM) /* Disconnect Provider Ultimatum */
{
g_writeln("received Disconnect Provider Ultimatum");
DEBUG((" out xrdp_mcs_recv appid != MCS_DPUM"));
return 1;
}
/* this is channels getting added from the client */
if (appid == MCS_CJRQ)
{
g_writeln("channel join request received");
in_uint16_be(s, userid);
in_uint16_be(s, chanid);
DEBUG((" adding channel %4.4x", chanid));
xrdp_mcs_send_cjcf(self, userid, chanid);
DEBUG(("xrdp_mcs_recv adding channel %4.4x", chanid));
if(xrdp_mcs_send_cjcf(self, userid, chanid)!=0)
{
g_writeln("Non handled error from xrdp_mcs_send_cjcf") ;
}
continue;
}
if(appid==MCS_SDRQ || appid==MCS_SDIN)
{
break ;
}
else
{
g_writeln("Recieved an unhandled appid:%d",appid);
}
break;
}
if (appid != MCS_SDRQ)

View File

@ -152,7 +152,7 @@ xrdp_orders_force_send(struct xrdp_orders* self)
/* check if the current order will fit in packet size of 16384, if not */
/* send what we got and init a new one */
/* returns error */
static int APP_CC
int APP_CC
xrdp_orders_check(struct xrdp_orders* self, int max_size)
{
int size;

625
libxrdp/xrdp_orders_rail.c Normal file
View File

@ -0,0 +1,625 @@
/**
* xrdp: A Remote Desktop Protocol server.
*
* Copyright (C) Jay Sorg 2012
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "libxrdp.h"
#include "rail.h"
/* [MS-RDPERP]: Remote Desktop Protocol:
Remote Programs Virtual Channel Extension
http://msdn.microsoft.com/en-us/library/cc242568(v=prot.10) */
/*****************************************************************************/
/* RAIL */
/* returns error */
int APP_CC
xrdp_orders_send_window_delete(struct xrdp_orders* self, int window_id)
{
int order_size;
int order_flags;
int field_present_flags;
order_size = 11;
xrdp_orders_check(self, order_size);
self->order_count++;
order_flags = RDP_ORDER_SECONDARY;
order_flags |= 0xb << 2; /* type TS_ALTSEC_WINDOW */
out_uint8(self->out_s, order_flags);
/* orderSize (2 bytes) */
out_uint16_le(self->out_s, order_size);
/* FieldsPresentFlags (4 bytes) */
field_present_flags = WINDOW_ORDER_TYPE_WINDOW | WINDOW_ORDER_STATE_DELETED;
out_uint32_le(self->out_s, field_present_flags);
/* windowId (4 bytes) */
out_uint32_le(self->out_s, window_id);
return 0;
}
/*****************************************************************************/
/* RAIL */
/* returns error */
/* flags can contain WINDOW_ORDER_STATE_NEW and/or
WINDOW_ORDER_FIELD_ICON_BIG */
int APP_CC
xrdp_orders_send_window_cached_icon(struct xrdp_orders* self,
int window_id, int cache_entry,
int cache_id, int flags)
{
int order_size;
int order_flags;
int field_present_flags;
order_size = 14;
xrdp_orders_check(self, order_size);
self->order_count++;
order_flags = RDP_ORDER_SECONDARY;
order_flags |= 0xb << 2; /* type TS_ALTSEC_WINDOW */
out_uint8(self->out_s, order_flags);
/* orderSize (2 bytes) */
out_uint16_le(self->out_s, order_size);
/* FieldsPresentFlags (4 bytes) */
field_present_flags = flags | WINDOW_ORDER_TYPE_WINDOW |
WINDOW_ORDER_CACHED_ICON;
out_uint32_le(self->out_s, field_present_flags);
/* windowId (4 bytes) */
out_uint32_le(self->out_s, window_id);
/* CacheEntry (2 bytes) */
out_uint16_le(self->out_s, cache_entry);
/* CacheId (1 byte) */
out_uint8(self->out_s, cache_id);
return 0;
}
/*****************************************************************************/
/* RAIL */
/* returns error */
static int APP_CC
xrdp_orders_send_ts_icon(struct stream* s, int cache_entry, int cache_id,
struct rail_icon_info* icon_info)
{
int use_cmap;
use_cmap = 0;
if ((icon_info->bpp == 1) || (icon_info->bpp == 2) || (icon_info->bpp == 4))
{
use_cmap = 1;
}
/* TS_ICON_INFO */
out_uint16_le(s, cache_entry);
out_uint8(s, cache_id);
out_uint8(s, icon_info->bpp);
out_uint16_le(s, icon_info->width);
out_uint16_le(s, icon_info->height);
if (use_cmap)
{
out_uint16_le(s, icon_info->cmap_bytes);
}
out_uint16_le(s, icon_info->mask_bytes);
out_uint16_le(s, icon_info->data_bytes);
out_uint8p(s, icon_info->mask, icon_info->mask_bytes);
if (use_cmap)
{
out_uint8p(s, icon_info->cmap, icon_info->cmap_bytes);
}
out_uint8p(s, icon_info->data, icon_info->data_bytes);
return 0;
}
/*****************************************************************************/
/* RAIL */
/* returns error */
/* flags can contain WINDOW_ORDER_STATE_NEW and/or
WINDOW_ORDER_FIELD_ICON_BIG */
int APP_CC
xrdp_orders_send_window_icon(struct xrdp_orders* self,
int window_id, int cache_entry, int cache_id,
struct rail_icon_info* icon_info,
int flags)
{
int order_size;
int order_flags;
int field_present_flags;
int use_cmap;
use_cmap = 0;
if ((icon_info->bpp == 1) || (icon_info->bpp == 2) || (icon_info->bpp == 4))
{
use_cmap = 1;
}
order_size = 23 + icon_info->mask_bytes + icon_info->data_bytes;
if (use_cmap)
{
order_size += icon_info->cmap_bytes + 2;
}
xrdp_orders_check(self, order_size);
self->order_count++;
order_flags = RDP_ORDER_SECONDARY;
order_flags |= 0xb << 2; /* type TS_ALTSEC_WINDOW */
out_uint8(self->out_s, order_flags);
/* orderSize (2 bytes) */
out_uint16_le(self->out_s, order_size);
/* FieldsPresentFlags (4 bytes) */
field_present_flags = flags | WINDOW_ORDER_TYPE_WINDOW |
WINDOW_ORDER_ICON;
out_uint32_le(self->out_s, field_present_flags);
/* windowId (4 bytes) */
out_uint32_le(self->out_s, window_id);
xrdp_orders_send_ts_icon(self->out_s, cache_entry, cache_id, icon_info);
return 0;
}
/*****************************************************************************/
/* returns error */
static int APP_CC
xrdp_orders_send_as_unicode(struct stream* s, const char* text)
{
int str_chars;
int index;
int i32;
twchar wdst[256];
str_chars = g_mbstowcs(wdst, text, 255);
if (str_chars > 0)
{
i32 = str_chars * 2;
out_uint16_le(s, i32);
for (index = 0; index < str_chars; index++)
{
i32 = wdst[index];
out_uint16_le(s, i32);
}
}
else
{
out_uint16_le(s, 0);
}
return 0;
}
/*****************************************************************************/
/* RAIL */
/* returns error */
/* flags can contain WINDOW_ORDER_STATE_NEW */
int APP_CC
xrdp_orders_send_window_new_update(struct xrdp_orders* self, int window_id,
struct rail_window_state_order* window_state,
int flags)
{
int order_size;
int order_flags;
int field_present_flags;
int num_chars;
int index;
order_size = 11;
field_present_flags = flags | WINDOW_ORDER_TYPE_WINDOW;
if (field_present_flags & WINDOW_ORDER_FIELD_OWNER)
{
/* ownerWindowId (4 bytes) */
order_size += 4;
}
if (field_present_flags & WINDOW_ORDER_FIELD_STYLE)
{
/* style (4 bytes) */
order_size += 4;
/* extendedStyle (4 bytes) */
order_size += 4;
}
if (field_present_flags & WINDOW_ORDER_FIELD_SHOW)
{
/* showState (1 byte) */
order_size += 1;
}
if (field_present_flags & WINDOW_ORDER_FIELD_TITLE)
{
/* titleInfo */
num_chars = g_mbstowcs(0, window_state->title_info, 0);
order_size += 2 * num_chars + 2;
}
if (field_present_flags & WINDOW_ORDER_FIELD_CLIENT_AREA_OFFSET)
{
/* clientOffsetX (4 bytes) */
order_size += 4;
/* clientOffsetY (4 bytes) */
order_size += 4;
}
if (field_present_flags & WINDOW_ORDER_FIELD_CLIENT_AREA_SIZE)
{
/* clientAreaWidth (4 bytes) */
order_size += 4;
/* clientAreaHeight (4 bytes) */
order_size += 4;
}
if (field_present_flags & WINDOW_ORDER_FIELD_RP_CONTENT)
{
/* RPContent (1 byte) */
order_size += 1;
}
if (field_present_flags & WINDOW_ORDER_FIELD_ROOT_PARENT)
{
/* rootParentHandle (4 bytes) */
order_size += 4;
}
if (field_present_flags & WINDOW_ORDER_FIELD_WND_OFFSET)
{
/* windowOffsetX (4 bytes) */
order_size += 4;
/* windowOffsetY (4 bytes) */
order_size += 4;
}
if (field_present_flags & WINDOW_ORDER_FIELD_WND_CLIENT_DELTA)
{
/* windowClientDeltaX (4 bytes) */
order_size += 4;
/* windowClientDeltaY (4 bytes) */
order_size += 4;
}
if (field_present_flags & WINDOW_ORDER_FIELD_WND_SIZE)
{
/* windowWidth (4 bytes) */
order_size += 4;
/* windowHeight (4 bytes) */
order_size += 4;
}
if (field_present_flags & WINDOW_ORDER_FIELD_WND_RECTS)
{
/* numWindowRects (2 bytes) */
order_size += 2;
order_size += 8 * window_state->num_window_rects;
}
if (field_present_flags & WINDOW_ORDER_FIELD_VIS_OFFSET)
{
/* visibleOffsetX (4 bytes) */
order_size += 4;
/* visibleOffsetY (4 bytes) */
order_size += 4;
}
if (field_present_flags & WINDOW_ORDER_FIELD_VISIBILITY)
{
/* numVisibilityRects (2 bytes) */
order_size += 2;
order_size += 8 * window_state->num_visibility_rects;
}
xrdp_orders_check(self, order_size);
self->order_count++;
order_flags = RDP_ORDER_SECONDARY;
order_flags |= 0xb << 2; /* type TS_ALTSEC_WINDOW */
out_uint8(self->out_s, order_flags);
/* orderSize (2 bytes) */
out_uint16_le(self->out_s, order_size);
/* FieldsPresentFlags (4 bytes) */
out_uint32_le(self->out_s, field_present_flags);
/* windowId (4 bytes) */
out_uint32_le(self->out_s, window_id);
if (field_present_flags & WINDOW_ORDER_FIELD_OWNER)
{
/* ownerWindowId (4 bytes) */
out_uint32_le(self->out_s, window_state->owner_window_id);
}
if (field_present_flags & WINDOW_ORDER_FIELD_STYLE)
{
/* style (4 bytes) */
out_uint32_le(self->out_s, window_state->style);
/* extendedStyle (4 bytes) */
out_uint32_le(self->out_s, window_state->extended_style);
}
if (field_present_flags & WINDOW_ORDER_FIELD_SHOW)
{
/* showState (1 byte) */
out_uint8(self->out_s, window_state->show_state);
}
if (field_present_flags & WINDOW_ORDER_FIELD_TITLE)
{
/* titleInfo */
xrdp_orders_send_as_unicode(self->out_s, window_state->title_info);
}
if (field_present_flags & WINDOW_ORDER_FIELD_CLIENT_AREA_OFFSET)
{
/* clientOffsetX (4 bytes) */
out_uint32_le(self->out_s, window_state->client_offset_x);
/* clientOffsetY (4 bytes) */
out_uint32_le(self->out_s, window_state->client_offset_y);
}
if (field_present_flags & WINDOW_ORDER_FIELD_CLIENT_AREA_SIZE)
{
/* clientAreaWidth (4 bytes) */
out_uint32_le(self->out_s, window_state->client_area_width);
/* clientAreaHeight (4 bytes) */
out_uint32_le(self->out_s, window_state->client_area_height);
}
if (field_present_flags & WINDOW_ORDER_FIELD_RP_CONTENT)
{
/* RPContent (1 byte) */
out_uint8(self->out_s, window_state->rp_content);
}
if (field_present_flags & WINDOW_ORDER_FIELD_ROOT_PARENT)
{
/* rootParentHandle (4 bytes) */
out_uint32_le(self->out_s, window_state->root_parent_handle);
}
if (field_present_flags & WINDOW_ORDER_FIELD_WND_OFFSET)
{
/* windowOffsetX (4 bytes) */
out_uint32_le(self->out_s, window_state->window_offset_x);
/* windowOffsetY (4 bytes) */
out_uint32_le(self->out_s, window_state->window_offset_y);
}
if (field_present_flags & WINDOW_ORDER_FIELD_WND_CLIENT_DELTA)
{
/* windowClientDeltaX (4 bytes) */
out_uint32_le(self->out_s, window_state->window_client_delta_x);
/* windowClientDeltaY (4 bytes) */
out_uint32_le(self->out_s, window_state->window_client_delta_y);
}
if (field_present_flags & WINDOW_ORDER_FIELD_WND_SIZE)
{
/* windowWidth (4 bytes) */
out_uint32_le(self->out_s, window_state->window_width);
/* windowHeight (4 bytes) */
out_uint32_le(self->out_s, window_state->window_height);
}
if (field_present_flags & WINDOW_ORDER_FIELD_WND_RECTS)
{
/* numWindowRects (2 bytes) */
out_uint16_le(self->out_s, window_state->num_window_rects);
for (index = 0; index < window_state->num_window_rects; index++)
{
out_uint16_le(self->out_s, window_state->window_rects[index].left);
out_uint16_le(self->out_s, window_state->window_rects[index].top);
out_uint16_le(self->out_s, window_state->window_rects[index].right);
out_uint16_le(self->out_s, window_state->window_rects[index].bottom);
}
}
if (field_present_flags & WINDOW_ORDER_FIELD_VIS_OFFSET)
{
/* visibleOffsetX (4 bytes) */
out_uint32_le(self->out_s, window_state->visible_offset_x);
/* visibleOffsetY (4 bytes) */
out_uint32_le(self->out_s, window_state->visible_offset_y);
}
if (field_present_flags & WINDOW_ORDER_FIELD_VISIBILITY)
{
/* numVisibilityRects (2 bytes) */
out_uint16_le(self->out_s, window_state->num_visibility_rects);
for (index = 0; index < window_state->num_visibility_rects; index++)
{
out_uint16_le(self->out_s, window_state->visibility_rects[index].left);
out_uint16_le(self->out_s, window_state->visibility_rects[index].top);
out_uint16_le(self->out_s, window_state->visibility_rects[index].right);
out_uint16_le(self->out_s, window_state->visibility_rects[index].bottom);
}
}
return 0;
}
/*****************************************************************************/
/* RAIL */
/* returns error */
int APP_CC
xrdp_orders_send_notify_delete(struct xrdp_orders* self, int window_id,
int notify_id)
{
int order_size;
int order_flags;
int field_present_flags;
order_size = 15;
xrdp_orders_check(self, order_size);
self->order_count++;
order_flags = RDP_ORDER_SECONDARY;
order_flags |= 0xb << 2; /* type TS_ALTSEC_WINDOW */
out_uint8(self->out_s, order_flags);
/* orderSize (2 bytes) */
out_uint16_le(self->out_s, order_size);
/* FieldsPresentFlags (4 bytes) */
field_present_flags = WINDOW_ORDER_TYPE_NOTIFY | WINDOW_ORDER_STATE_DELETED;
out_uint32_le(self->out_s, field_present_flags);
/* windowId (4 bytes) */
out_uint32_le(self->out_s, window_id);
/* notifyIconId (4 bytes) */
out_uint32_le(self->out_s, notify_id);
return 0;
}
/*****************************************************************************/
/* RAIL */
/* returns error */
/* flags can contain WINDOW_ORDER_STATE_NEW */
int APP_CC
xrdp_orders_send_notify_new_update(struct xrdp_orders* self,
int window_id, int notify_id,
struct rail_notify_state_order* notify_state,
int flags)
{
int order_size;
int order_flags;
int field_present_flags;
int num_chars;
int use_cmap;
order_size = 15;
field_present_flags = flags | WINDOW_ORDER_TYPE_NOTIFY;
if (field_present_flags & WINDOW_ORDER_FIELD_NOTIFY_VERSION)
{
/* Version (4 bytes) */
order_size += 4;
}
if (field_present_flags & WINDOW_ORDER_FIELD_NOTIFY_TIP)
{
/* ToolTip (variable) UNICODE_STRING */
num_chars = g_mbstowcs(0, notify_state->tool_tip, 0);
order_size += 2 * num_chars + 2;
}
if (field_present_flags & WINDOW_ORDER_FIELD_NOTIFY_INFO_TIP)
{
/* InfoTip (variable) TS_NOTIFY_ICON_INFOTIP */
/* UNICODE_STRING */
num_chars = g_mbstowcs(0, notify_state->infotip.title, 0);
order_size += 2 * num_chars + 2;
/* UNICODE_STRING */
num_chars = g_mbstowcs(0, notify_state->infotip.text, 0);
order_size += 2 * num_chars + 2;
/* Timeout (4 bytes) */
/* InfoFlags (4 bytes) */
order_size += 8;
}
if (field_present_flags & WINDOW_ORDER_FIELD_NOTIFY_STATE)
{
/* State (4 bytes) */
order_size += 4;
}
if (field_present_flags & WINDOW_ORDER_ICON)
{
/* Icon (variable) */
use_cmap = 0;
if ((notify_state->icon_info.bpp == 1) || (notify_state->icon_info.bpp == 2) ||
(notify_state->icon_info.bpp == 4))
{
use_cmap = 1;
}
order_size += 12 + notify_state->icon_info.mask_bytes +
notify_state->icon_info.data_bytes;
if (use_cmap)
{
order_size += notify_state->icon_info.cmap_bytes + 2;
}
}
if (field_present_flags & WINDOW_ORDER_CACHED_ICON)
{
/* CachedIcon (3 bytes) */
order_size += 3;
}
xrdp_orders_check(self, order_size);
self->order_count++;
order_flags = RDP_ORDER_SECONDARY;
order_flags |= 0xb << 2; /* type TS_ALTSEC_WINDOW */
out_uint8(self->out_s, order_flags);
/* orderSize (2 bytes) */
out_uint16_le(self->out_s, order_size);
/* FieldsPresentFlags (4 bytes) */
out_uint32_le(self->out_s, field_present_flags);
/* windowId (4 bytes) */
out_uint32_le(self->out_s, window_id);
/* notifyIconId (4 bytes) */
out_uint32_le(self->out_s, notify_id);
if (field_present_flags & WINDOW_ORDER_FIELD_NOTIFY_VERSION)
{
/* Version (4 bytes) */
out_uint32_le(self->out_s, notify_state->version);
}
if (field_present_flags & WINDOW_ORDER_FIELD_NOTIFY_TIP)
{
/* ToolTip (variable) UNICODE_STRING */
xrdp_orders_send_as_unicode(self->out_s, notify_state->tool_tip);
}
if (field_present_flags & WINDOW_ORDER_FIELD_NOTIFY_INFO_TIP)
{
/* InfoTip (variable) TS_NOTIFY_ICON_INFOTIP */
out_uint32_le(self->out_s, notify_state->infotip.timeout);
out_uint32_le(self->out_s, notify_state->infotip.flags);
xrdp_orders_send_as_unicode(self->out_s, notify_state->infotip.text);
xrdp_orders_send_as_unicode(self->out_s, notify_state->infotip.title);
}
if (field_present_flags & WINDOW_ORDER_FIELD_NOTIFY_STATE)
{
/* State (4 bytes) */
out_uint32_le(self->out_s, notify_state->state);
}
if (field_present_flags & WINDOW_ORDER_ICON)
{
/* Icon (variable) */
xrdp_orders_send_ts_icon(self->out_s, notify_state->icon_cache_entry,
notify_state->icon_cache_id,
&notify_state->icon_info);
}
if (field_present_flags & WINDOW_ORDER_CACHED_ICON)
{
/* CacheEntry (2 bytes) */
out_uint16_le(self->out_s, notify_state->icon_cache_entry);
/* CacheId (1 byte) */
out_uint8(self->out_s, notify_state->icon_cache_id);
}
return 0;
}
/*****************************************************************************/
/* RAIL */
/* returns error */
/* used for both Non-Monitored Desktop and Actively Monitored Desktop */
int APP_CC
xrdp_orders_send_monitored_desktop(struct xrdp_orders* self,
struct rail_monitored_desktop_order* mdo,
int flags)
{
int order_size;
int order_flags;
int field_present_flags;
int index;
order_size = 7;
field_present_flags = flags | WINDOW_ORDER_TYPE_DESKTOP;
if (field_present_flags & WINDOW_ORDER_FIELD_DESKTOP_ACTIVE_WND)
{
/* ActiveWindowId (4 bytes) */
order_size += 4;
}
if (field_present_flags & WINDOW_ORDER_FIELD_DESKTOP_ZORDER)
{
/* NumWindowIds (1 byte) */
order_size += 1;
/* WindowIds (variable) */
order_size += mdo->num_window_ids * 4;
}
xrdp_orders_check(self, order_size);
self->order_count++;
order_flags = RDP_ORDER_SECONDARY;
order_flags |= 0xb << 2; /* type TS_ALTSEC_WINDOW */
out_uint8(self->out_s, order_flags);
/* orderSize (2 bytes) */
out_uint16_le(self->out_s, order_size);
/* FieldsPresentFlags (4 bytes) */
out_uint32_le(self->out_s, field_present_flags);
if (field_present_flags & WINDOW_ORDER_FIELD_DESKTOP_ACTIVE_WND)
{
/* ActiveWindowId (4 bytes) */
out_uint32_le(self->out_s, mdo->active_window_id);
}
if (field_present_flags & WINDOW_ORDER_FIELD_DESKTOP_ZORDER)
{
/* NumWindowIds (1 byte) */
out_uint8(self->out_s, mdo->num_window_ids);
/* WindowIds (variable) */
for (index = 0; index < mdo->num_window_ids; index++)
{
out_uint32_le(self->out_s, mdo->window_ids[index]);
}
}
return 0;
}

View File

@ -0,0 +1,50 @@
/**
* xrdp: A Remote Desktop Protocol server.
*
* Copyright (C) Jay Sorg 2012
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#if !defined(_XRDP_ORDERS_RAIL_H)
#define _XRDP_ORDERS_RAIL_H
int APP_CC
xrdp_orders_send_window_delete(struct xrdp_orders* self, int window_id);
int APP_CC
xrdp_orders_send_window_cached_icon(struct xrdp_orders* self,
int window_id, int cache_entry,
int cache_id, int flags);
int APP_CC
xrdp_orders_send_window_icon(struct xrdp_orders* self,
int window_id, int cache_entry, int cache_id,
struct rail_icon_info* icon_info,
int flags);
int APP_CC
xrdp_orders_send_window_new_update(struct xrdp_orders* self, int window_id,
struct rail_window_state_order* window_state,
int flags);
int APP_CC
xrdp_orders_send_notify_delete(struct xrdp_orders* self, int window_id,
int notify_id);
int APP_CC
xrdp_orders_send_notify_new_update(struct xrdp_orders* self,
int window_id, int notify_id,
struct rail_notify_state_order* notify_state,
int flags);
int APP_CC
xrdp_orders_send_monitored_desktop(struct xrdp_orders* self,
struct rail_monitored_desktop_order* mdo,
int flags);
#endif

View File

@ -113,13 +113,25 @@ xrdp_rdp_read_config(struct xrdp_client_info* client_info)
{
client_info->crypt_level = 3;
}
else
{
g_writeln("Warning: Your configured crypt level is"
"undefined 'high' will be used");
client_info->crypt_level = 3;
}
}
else if (g_strcasecmp(item, "channel_code") == 0)
{
if (g_strcasecmp(value, "1") == 0)
if ((g_strcasecmp(value, "yes") == 0) ||
(g_strcasecmp(value, "1") == 0) ||
(g_strcasecmp(value, "true") == 0))
{
client_info->channel_code = 1;
}
else
{
g_writeln("Info: All channels are disabled");
}
}
else if (g_strcasecmp(item, "max_bpp") == 0)
{
@ -223,7 +235,7 @@ xrdp_rdp_recv(struct xrdp_rdp* self, struct stream* s, int* code)
{
s->next_packet = 0;
*code = -1;
DEBUG(("out xrdp_rdp_recv"));
DEBUG(("out (1) xrdp_rdp_recv"));
return 0;
}
if (error != 0)
@ -235,35 +247,47 @@ xrdp_rdp_recv(struct xrdp_rdp* self, struct stream* s, int* code)
{
if (chan > MCS_GLOBAL_CHANNEL)
{
xrdp_channel_process(self->sec_layer->chan_layer, s, chan);
if(xrdp_channel_process(self->sec_layer->chan_layer, s, chan)!=0)
{
g_writeln("xrdp_channel_process returned unhandled error") ;
}
}
else
{
g_writeln("Wrong channel Id to be handled by xrdp_channel_process %d",chan);
}
s->next_packet = 0;
*code = 0;
DEBUG(("out xrdp_rdp_recv"));
DEBUG(("out (2) xrdp_rdp_recv"));
return 0;
}
s->next_packet = s->p;
}
else
{
DEBUG(("xrdp_rdp_recv stream not touched"))
s->p = s->next_packet;
}
if (!s_check_rem(s, 6))
{
s->next_packet = 0;
*code = 0;
DEBUG(("out xrdp_rdp_recv"));
DEBUG(("out (3) xrdp_rdp_recv"));
len = (int)(s->end - s->p);
g_writeln("xrdp_rdp_recv: bad RDP packet, length [%d]", len);
return 0;
}
in_uint16_le(s, len);
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"));
return 0;
else
{
in_uint16_le(s, len);
/*g_writeln("New len received : %d next packet: %d s_end: %d",len,s->next_packet,s->end); */
in_uint16_le(s, pdu_code);
*code = pdu_code & 0xf;
in_uint8s(s, 2); /* mcs user id */
s->next_packet += len;
DEBUG(("out (4) xrdp_rdp_recv"));
return 0;
}
}
/*****************************************************************************/
@ -620,6 +644,21 @@ xrdp_rdp_send_demand_active(struct xrdp_rdp* self)
out_uint8(s, 1);
out_uint8s(s, 83);
/* Remote Programs Capability Set */
caps_count++;
out_uint16_le(s, 0x0017); /* CAPSETTYPE_RAIL */
out_uint16_le(s, 8);
out_uint32_le(s, 3); /* TS_RAIL_LEVEL_SUPPORTED
TS_RAIL_LEVEL_DOCKED_LANGBAR_SUPPORTED */
/* Window List Capability Set */
caps_count++;
out_uint16_le(s, 0x0018); /* CAPSETTYPE_WINDOW */
out_uint16_le(s, 11);
out_uint32_le(s, 2); /* TS_WINDOW_LEVEL_SUPPORTED_EX */
out_uint8(s, 3); /* NumIconCaches */
out_uint16_le(s, 12); /* NumIconCacheEntries */
out_uint8s(s, 4); /* pad */
s_mark_end(s);
@ -825,6 +864,49 @@ xrdp_process_offscreen_bmpcache(struct xrdp_rdp* self, struct stream* s,
return 0;
}
/*****************************************************************************/
static int APP_CC
xrdp_process_capset_rail(struct xrdp_rdp* self, struct stream* s, int len)
{
int i32;
if (len - 4 < 4)
{
g_writeln("xrdp_process_capset_rail: bad len");
return 1;
}
in_uint32_le(s, i32);
self->client_info.rail_support_level = i32;
g_writeln("xrdp_process_capset_rail: rail_support_level %d",
self->client_info.rail_support_level);
return 0;
}
/*****************************************************************************/
static int APP_CC
xrdp_process_capset_window(struct xrdp_rdp* self, struct stream* s, int len)
{
int i32;
if (len - 4 < 7)
{
g_writeln("xrdp_process_capset_window: bad len");
return 1;
}
in_uint32_le(s, i32);
self->client_info.wnd_support_level = i32;
in_uint8(s, i32);
self->client_info.wnd_num_icon_caches = i32;
in_uint16_le(s, i32);
self->client_info.wnd_num_icon_cache_entries = i32;
g_writeln("xrdp_process_capset_window wnd_support_level %d "
"wnd_num_icon_caches %d wnd_num_icon_cache_entries %d",
self->client_info.wnd_support_level,
self->client_info.wnd_num_icon_caches,
self->client_info.wnd_num_icon_cache_entries);
return 0;
}
/*****************************************************************************/
int APP_CC
xrdp_rdp_process_confirm_active(struct xrdp_rdp* self, struct stream* s)
@ -915,6 +997,12 @@ xrdp_rdp_process_confirm_active(struct xrdp_rdp* self, struct stream* s)
case 22: /* 22 */
DEBUG(("--22"));
break;
case 0x0017: /* 23 CAPSETTYPE_RAIL */
xrdp_process_capset_rail(self, s, len);
break;
case 0x0018: /* 24 CAPSETTYPE_WINDOW */
xrdp_process_capset_window(self, s, len);
break;
case 26: /* 26 */
DEBUG(("--26"));
break;

View File

@ -148,9 +148,20 @@ xrdp_sec_create(struct xrdp_rdp* owner, struct trans* trans, int crypt_level,
self->rc4_key_size = 2;
self->crypt_level = 3;
break;
default:
g_writeln("Fatal : Illegal crypt_level");
break ;
}
self->channel_code = channel_code;
if(self->decrypt_rc4_info!=NULL)
{
g_writeln("xrdp_sec_create - decrypt_rc4_info already created !!!");
}
self->decrypt_rc4_info = ssl_rc4_info_create();
if(self->encrypt_rc4_info!=NULL)
{
g_writeln("xrdp_sec_create - encrypt_rc4_info already created !!!");
}
self->encrypt_rc4_info = ssl_rc4_info_create();
self->mcs_layer = xrdp_mcs_create(self, trans, &self->client_mcs_data,
&self->server_mcs_data);
@ -165,14 +176,17 @@ xrdp_sec_delete(struct xrdp_sec* self)
{
if (self == 0)
{
g_writeln("xrdp_sec_delete: indata is null");
return;
}
xrdp_channel_delete(self->chan_layer);
xrdp_mcs_delete(self->mcs_layer);
ssl_rc4_info_delete(self->decrypt_rc4_info);
ssl_rc4_info_delete(self->encrypt_rc4_info);
ssl_rc4_info_delete(self->decrypt_rc4_info); /* TODO clear all data */
ssl_rc4_info_delete(self->encrypt_rc4_info); /* TODO clear all data */
g_free(self->client_mcs_data.data);
g_free(self->server_mcs_data.data);
/* Crypto information must always be cleared */
g_memset(self,0,sizeof(struct xrdp_sec));
g_free(self);
}
@ -722,6 +736,7 @@ xrdp_sec_process_mcs_data_channels(struct xrdp_sec* self, struct stream* s)
/* this is an option set in xrdp.ini */
if (self->channel_code != 1) /* are channels on? */
{
g_writeln("Processing channel data from client - The channel is off");
return 0;
}
in_uint32_le(s, num_channels);

View File

@ -46,7 +46,15 @@ rdp_sec_create(struct rdp_rdp* owner)
init_stream(self->server_mcs_data, 8192);
self->mcs_layer = rdp_mcs_create(self, self->client_mcs_data,
self->server_mcs_data);
if(self->decrypt_rc4_info!=NULL)
{
g_writeln("rdp_sec_create - decrypt_rc4_info already created !!!");
}
self->decrypt_rc4_info = ssl_rc4_info_create();
if(self->encrypt_rc4_info!=NULL)
{
g_writeln("rdp_sec_create - encrypt_rc4_info already created !!!");
}
self->encrypt_rc4_info = ssl_rc4_info_create();
self->lic_layer = rdp_lic_create(self);
return self;

View File

@ -448,7 +448,7 @@ channel_thread_loop(void* in_val)
num_objs = 0;
objs[num_objs] = g_term_event;
num_objs++;
trans_get_wait_objs(g_lis_trans, objs, &num_objs, &timeout);
trans_get_wait_objs(g_lis_trans, objs, &num_objs);
while (g_obj_wait(objs, num_objs, 0, 0, timeout) == 0)
{
if (g_is_wait_obj_set(g_term_event))
@ -493,8 +493,8 @@ channel_thread_loop(void* in_val)
num_objs = 0;
objs[num_objs] = g_term_event;
num_objs++;
trans_get_wait_objs(g_lis_trans, objs, &num_objs, &timeout);
trans_get_wait_objs(g_con_trans, objs, &num_objs, &timeout);
trans_get_wait_objs(g_lis_trans, objs, &num_objs);
trans_get_wait_objs(g_con_trans, objs, &num_objs);
clipboard_get_wait_objs(objs, &num_objs, &timeout);
sound_get_wait_objs(objs, &num_objs, &timeout);
dev_redir_get_wait_objs(objs, &num_objs, &timeout);

View File

@ -60,6 +60,9 @@ scp_session_set_type(struct SCP_SESSION* s, tui8 type)
case SCP_SESSION_TYPE_XRDP:
s->type = SCP_SESSION_TYPE_XRDP;
break;
case SCP_GW_AUTHENTICATION:
s->type = SCP_GW_AUTHENTICATION;
break;
case SCP_SESSION_TYPE_MANAGE:
s->type = SCP_SESSION_TYPE_MANAGE;
s->mng = (struct SCP_MNG_DATA*)g_malloc(sizeof(struct SCP_MNG_DATA), 1);

View File

@ -42,6 +42,10 @@
#define SCP_SESSION_TYPE_XVNC 0x00
#define SCP_SESSION_TYPE_XRDP 0x01
#define SCP_SESSION_TYPE_MANAGE 0x02
/* SCP_GW_AUTHENTICATION can be used when XRDP + sesman act as a gateway
* XRDP sends this command to let sesman verify if the user is allowed
* to use the gateway */
#define SCP_GW_AUTHENTICATION 0x04
#define SCP_ADDRESS_TYPE_IPV4 0x00
#define SCP_ADDRESS_TYPE_IPV6 0x01

View File

@ -277,6 +277,42 @@ scp_v0s_accept(struct SCP_CONNECTION* c, struct SCP_SESSION** s, int skipVchk)
}
}
}
if (code == SCP_GW_AUTHENTICATION)
{
/* g_writeln("Command is SCP_GW_AUTHENTICATION"); */
session = scp_session_create();
if (0 == session)
{
/* until syslog merge log_message(s_log, LOG_LEVEL_WARNING, "[v0:%d] connection aborted: network error", __LINE__);*/
return SCP_SERVER_STATE_INTERNAL_ERR;
}
scp_session_set_version(session, version);
scp_session_set_type(session, SCP_GW_AUTHENTICATION);
/* reading username */
in_uint16_be(c->in_s, sz);
buf[sz]='\0';
in_uint8a(c->in_s, buf, sz);
/* g_writeln("Received user name: %s",buf); */
if (0 != scp_session_set_username(session, buf))
{
scp_session_destroy(session);
/* until syslog merge log_message(s_log, LOG_LEVEL_WARNING, "[v0:%d] connection aborted: error setting username", __LINE__);*/
return SCP_SERVER_STATE_INTERNAL_ERR;
}
/* reading password */
in_uint16_be(c->in_s, sz);
buf[sz]='\0';
in_uint8a(c->in_s, buf, sz);
/* g_writeln("Received password: %s",buf); */
if (0 != scp_session_set_password(session, buf))
{
scp_session_destroy(session);
/* until syslog merge log_message(s_log, LOG_LEVEL_WARNING, "[v0:%d] connection aborted: error setting password", __LINE__); */
return SCP_SERVER_STATE_INTERNAL_ERR;
}
}
else
{
log_message(LOG_LEVEL_WARNING, "[v0:%d] connection aborted: sequence error", __LINE__);
@ -315,8 +351,8 @@ scp_v0s_deny_connection(struct SCP_CONNECTION* c)
out_uint32_be(c->out_s, 0); /* version */
out_uint32_be(c->out_s, 14); /* size */
out_uint16_be(c->out_s, 3); /* cmd */
out_uint16_be(c->out_s, 0); /* data */
out_uint16_be(c->out_s, 0); /* data */
out_uint16_be(c->out_s, 0); /* data = 0 - means NOT ok*/
out_uint16_be(c->out_s, 0); /* reserved for display number*/
s_mark_end(c->out_s);
if (0 != scp_tcp_force_send(c->in_sck, c->out_s->data, c->out_s->end - c->out_s->data))
@ -328,3 +364,26 @@ scp_v0s_deny_connection(struct SCP_CONNECTION* c)
LOG_DBG("[v0:%d] connection terminated (denied)", __LINE__);
return SCP_SERVER_STATE_OK;
}
/******************************************************************************/
enum SCP_SERVER_STATES_E
scp_v0s_replyauthentication(struct SCP_CONNECTION* c, unsigned short int value)
{
out_uint32_be(c->out_s, 0); /* version */
out_uint32_be(c->out_s, 14); /* size */
/* cmd SCP_GW_AUTHENTICATION means authentication reply */
out_uint16_be(c->out_s, SCP_GW_AUTHENTICATION);
out_uint16_be(c->out_s, value); /* reply code */
out_uint16_be(c->out_s, 0); /* dummy data */
s_mark_end(c->out_s);
/* g_writeln("Total number of bytes that will be sent %d",c->out_s->end - c->out_s->data);*/
if (0 != scp_tcp_force_send(c->in_sck, c->out_s->data, c->out_s->end - c->out_s->data))
{
/* until syslog merge log_message(s_log, LOG_LEVEL_WARNING, "[v0:%d] connection aborted: network error", __LINE__); */
return SCP_SERVER_STATE_NETWORK_ERR;
}
/* until syslog merge LOG_DBG(s_log, "[v0:%d] connection terminated (scp_v0s_deny_authentication)", __LINE__);*/
return SCP_SERVER_STATE_OK;
}

View File

@ -73,5 +73,14 @@ scp_v0s_allow_connection(struct SCP_CONNECTION* c, SCP_DISPLAY d);
enum SCP_SERVER_STATES_E
scp_v0s_deny_connection(struct SCP_CONNECTION* c);
/**
* @brief send reply to an authentication request
* @param c connection descriptor
* @param value the reply code 0 means ok
* @return
*/
enum SCP_SERVER_STATES_E
scp_v0s_replyauthentication(struct SCP_CONNECTION* c, unsigned short int value);
#endif

View File

@ -38,20 +38,52 @@ scp_v0_process(struct SCP_CONNECTION* c, struct SCP_SESSION* s)
struct session_item* s_item;
data = auth_userpass(s->username, s->password);
if (data)
if(s->type==SCP_GW_AUTHENTICATION)
{
/* this is just authentication in a gateway situation */
/* g_writeln("SCP_GW_AUTHENTICATION message received"); */
if(data)
{
if (1 == access_login_allowed(s->username))
{
/* the user is member of the correct groups. */
scp_v0s_replyauthentication(c,0);
log_message( LOG_LEVEL_INFO,"Access permitted for user: %s",
s->username);
/* g_writeln("Connection allowed"); */
}
else
{
scp_v0s_replyauthentication(c,3);
log_message( LOG_LEVEL_INFO,"Username okey but group problem for user: %s",
s->username);
/* g_writeln("user password ok, but group problem"); */
}
}
else
{
/* g_writeln("username or password error"); */
log_message( LOG_LEVEL_INFO,"Username or password error for user: %s",
s->username);
scp_v0s_replyauthentication(c,2);
}
auth_end(data);
}
else if (data)
{
s_item = session_get_bydata(s->username, s->width, s->height, s->bpp, s->type);
if (s_item != 0)
{
display = s_item->display;
if (0 != s->client_ip)
{
log_message( LOG_LEVEL_INFO, "++ reconnected session: username %s, display :%d.0, session_pid %d, ip %s", s->username, display, s_item->pid, s->client_ip);
log_message( LOG_LEVEL_INFO, "++ reconnected session: username %s, display :%d.0, "
"session_pid %d, ip %s", s->username, display, s_item->pid, s->client_ip);
}
else
{
log_message(LOG_LEVEL_INFO, "++ reconnected session: username %s, display :%d.0, session_pid %d", s->username, display, s_item->pid);
log_message(LOG_LEVEL_INFO, "++ reconnected session: username %s, display :%d.0, "
"session_pid %d", s->username, display, s_item->pid);
}
auth_end(data);
/* don't set data to null here */
@ -63,11 +95,13 @@ scp_v0_process(struct SCP_CONNECTION* c, struct SCP_SESSION* s)
{
if (0 != s->client_ip)
{
log_message(LOG_LEVEL_INFO, "++ created session (access granted): username %s, ip %s", s->username, s->client_ip);
log_message(LOG_LEVEL_INFO, "++ created session (access granted): "
"username %s, ip %s", s->username, s->client_ip);
}
else
{
log_message(LOG_LEVEL_INFO, "++ created session (access granted): username %s", s->username);
log_message(LOG_LEVEL_INFO, "++ created session (access granted): "
"username %s", s->username);
}
if (SCP_SESSION_TYPE_XVNC == s->type)

View File

@ -23,6 +23,8 @@
#include "xrdp.h"
#include "log.h"
#define THREAD_WAITING 100
static struct xrdp_listen* g_listen = 0;
static long g_threadid = 0; /* main threadid */
@ -38,6 +40,9 @@ static long g_sync_param2 = 0;
static long (*g_sync_func)(long param1, long param2);
/*****************************************************************************/
/* This function is used to run a function from the main thread.
Sync_func is the function pointer that will run from main thread
The function can have two long in parameters and must return long */
long APP_CC
g_xrdp_sync(long (*sync_func)(long param1, long param2), long sync_param1,
long sync_param2)
@ -45,32 +50,46 @@ g_xrdp_sync(long (*sync_func)(long param1, long param2), long sync_param1,
long sync_result;
int sync_command;
/* If the function is called from the main thread, the function can
* be called directly. g_threadid= main thread ID*/
if (tc_threadid_equal(tc_get_threadid(), g_threadid))
{
/* this is the main thread, call the function directly */
/* in fork mode, this always happens too */
sync_result = sync_func(sync_param1, sync_param2);
/*g_writeln("g_xrdp_sync processed IN main thread -> continue");*/
}
else
{
/* All threads have to wait here until the main thread
* process the function. g_process_waiting_function() is called
* from the listening thread. g_process_waiting_function() process the function*/
tc_mutex_lock(g_sync1_mutex);
tc_mutex_lock(g_sync_mutex);
g_sync_param1 = sync_param1;
g_sync_param2 = sync_param2;
g_sync_func = sync_func;
g_sync_command = 100;
/* set a value THREAD_WAITING so the g_process_waiting_function function
* know if any function must be processed */
g_sync_command = THREAD_WAITING;
tc_mutex_unlock(g_sync_mutex);
g_set_wait_obj(g_sync_event);
/* set this event so that the main thread know if
* g_process_waiting_function() must be called */
g_set_wait_obj(g_sync_event);
do
{
g_sleep(100);
tc_mutex_lock(g_sync_mutex);
sync_command = g_sync_command;
/* load new value from global to see if the g_process_waiting_function()
* function has processed the function */
sync_command = g_sync_command;
sync_result = g_sync_result;
tc_mutex_unlock(g_sync_mutex);
}
while (sync_command != 0);
while (sync_command != 0); /* loop until g_process_waiting_function()
* has processed the request*/
tc_mutex_unlock(g_sync1_mutex);
/*g_writeln("g_xrdp_sync processed BY main thread -> continue");*/
}
return sync_result;
}
@ -160,15 +179,17 @@ pipe_sig(int sig_num)
}
/*****************************************************************************/
/*Some function must be called from the main thread.
if g_sync_command==THREAD_WAITING a function is waiting to be processed*/
void APP_CC
g_loop(void)
g_process_waiting_function(void)
{
tc_mutex_lock(g_sync_mutex);
if (g_sync_command != 0)
{
if (g_sync_func != 0)
{
if (g_sync_command == 100)
if (g_sync_command == THREAD_WAITING)
{
g_sync_result = g_sync_func(g_sync_param1, g_sync_param2);
}
@ -490,13 +511,17 @@ main(int argc, char** argv)
pid = g_getpid();
g_snprintf(text, 255, "xrdp_%8.8x_main_term", pid);
g_term_event = g_create_wait_obj(text);
g_snprintf(text, 255, "xrdp_%8.8x_main_sync", pid);
g_sync_event = g_create_wait_obj(text);
if (g_term_event == 0)
{
g_writeln("error creating g_term_event");
}
g_listen->startup_params = startup_params;
g_snprintf(text, 255, "xrdp_%8.8x_main_sync", pid);
g_sync_event = g_create_wait_obj(text);
if (g_sync_event == 0)
{
g_writeln("error creating g_sync_event");
}
g_listen->startup_params = startup_params;
xrdp_listen_main_loop(g_listen);
xrdp_listen_delete(g_listen);
tc_mutex_delete(g_sync_mutex);

View File

@ -52,7 +52,7 @@ g_get_term_event(void);
tbus APP_CC
g_get_sync_event(void);
void APP_CC
g_loop(void);
g_process_waiting_function(void);
/* xrdp_cache.c */
struct xrdp_cache* APP_CC
@ -417,6 +417,8 @@ server_draw_text(struct xrdp_mod* mod, int font,
int x, int y, char* data, int data_len);
int DEFAULT_CC
server_reset(struct xrdp_mod* mod, int width, int height, int bpp);
int DEFAULT_CC
is_channel_allowed(struct xrdp_wm* wm, int channel_id);
int DEFAULT_CC
server_query_channel(struct xrdp_mod* mod, int index, char* channel_name,
int* channel_flags);

View File

@ -7,6 +7,12 @@ crypt_level=low
channel_code=1
max_bpp=24
fork=yes
# regulate if the listening socket use socket option tcp_nodelay
# no buffering will be performed in the TCP stack
tcp_nodelay=yes
# regulate if the listening socket use socket option keepalive
# if the network connection disappear without close messages the connection will be closed
tcp_keepalive=yes
#black=000000
#grey=d6d3ce
#dark_grey=808080
@ -26,6 +32,15 @@ EnableSyslog=1
SyslogLevel=DEBUG
# LogLevel and SysLogLevel could by any of: core, error, warning, info or debug
[channels]
# Channel names not listed here will be blocket by XRDP.
# You can block any channel by setting its value to false.
# IMPORTANT! All channels are not supported in all use
# cases even if you set all values to true.
rdpdr=true
rdpsnd=true
drdynvc=true
cliprdr=true
[xrdp1]
name=sesman-Xvnc
@ -50,6 +65,9 @@ ip=ask
port=ask5900
username=na
password=ask
#pamusername=asksame
#pampassword=asksame
#pamsessionmng=127.0.0.1
[xrdp4]
name=sesman-any

View File

@ -37,6 +37,10 @@ xrdp_listen_create_pro_done(struct xrdp_listen* self)
pid = g_getpid();
g_snprintf(text, 255, "xrdp_%8.8x_listen_pro_done_event", pid);
self->pro_done_event = g_create_wait_obj(text);
if(self->pro_done_event == 0)
{
g_writeln("Failure creating pro_done_event");
}
return 0;
}
@ -130,6 +134,7 @@ xrdp_process_run(void* in_val)
static int
xrdp_listen_get_port_address(char* port, int port_bytes,
char* address, int address_bytes,
int *tcp_nodelay, int *tcp_keepalive,
struct xrdp_startup_params* startup_param)
{
int fd;
@ -147,6 +152,8 @@ xrdp_listen_get_port_address(char* port, int port_bytes,
/* see if port or address is in xrdp.ini file */
g_snprintf(cfg_file, 255, "%s/xrdp.ini", XRDP_CFG_PATH);
fd = g_file_open(cfg_file);
*tcp_nodelay = 0 ;
*tcp_keepalive = 0 ;
if (fd > 0)
{
names = list_create();
@ -185,6 +192,28 @@ xrdp_listen_get_port_address(char* port, int port_bytes,
startup_param->fork = 1;
}
}
if (g_strcasecmp(val, "tcp_nodelay") == 0)
{
val = (char*)list_get_item(values, index);
if ((g_strcasecmp(val, "yes") == 0) ||
(g_strcasecmp(val, "on") == 0) ||
(g_strcasecmp(val, "true") == 0) ||
(g_atoi(val) != 0))
{
*tcp_nodelay = 1 ;
}
}
if (g_strcasecmp(val, "tcp_keepalive") == 0)
{
val = (char*)list_get_item(values, index);
if ((g_strcasecmp(val, "yes") == 0) ||
(g_strcasecmp(val, "on") == 0) ||
(g_strcasecmp(val, "true") == 0) ||
(g_atoi(val) != 0))
{
*tcp_keepalive = 1 ;
}
}
}
}
}
@ -279,22 +308,40 @@ xrdp_listen_main_loop(struct xrdp_listen* self)
tbus term_obj;
tbus sync_obj;
tbus done_obj;
int tcp_nodelay;
int tcp_keepalive;
self->status = 1;
if (xrdp_listen_get_port_address(port, sizeof(port),
address, sizeof(address),
&tcp_nodelay, &tcp_keepalive,
self->startup_params) != 0)
{
g_writeln("xrdp_listen_main_loop: xrdp_listen_get_port failed");
self->status = -1;
return 1;
}
/*Create socket*/
error = trans_listen_address(self->listen_trans, port, address);
if (error == 0)
{
if(tcp_nodelay)
{
if(g_tcp_set_no_delay(self->listen_trans->sck))
{
g_writeln("Error setting tcp_nodelay");
}
}
if(tcp_keepalive)
{
if(g_tcp_set_keepalive(self->listen_trans->sck))
{
g_writeln("Error setting tcp_keepalive");
}
}
self->listen_trans->trans_conn_in = xrdp_listen_conn_in;
self->listen_trans->callback_data = self;
term_obj = g_get_term_event();
term_obj = g_get_term_event(); /*Global termination event */
sync_obj = g_get_sync_event();
done_obj = self->pro_done_event;
cont = 1;
@ -306,31 +353,33 @@ xrdp_listen_main_loop(struct xrdp_listen* self)
robjs[robjs_count++] = sync_obj;
robjs[robjs_count++] = done_obj;
timeout = -1;
if (trans_get_wait_objs(self->listen_trans, robjs, &robjs_count,
&timeout) != 0)
if (trans_get_wait_objs(self->listen_trans, robjs, &robjs_count) != 0)
{
g_writeln("Listening socket is in wrong state we terminate listener") ;
break;
}
/* wait */
/* wait - timeout -1 means wait indefinitely*/
if (g_obj_wait(robjs, robjs_count, 0, 0, timeout) != 0)
{
/* error, should not get here */
g_sleep(100);
}
if (g_is_wait_obj_set(term_obj)) /* term */
if (g_is_wait_obj_set(term_obj)) /* termination called */
{
break;
}
if (g_is_wait_obj_set(sync_obj)) /* sync */
if (g_is_wait_obj_set(sync_obj)) /* some function must be processed by this thread */
{
g_reset_wait_obj(sync_obj);
g_loop();
g_process_waiting_function(); /* run the function */
}
if (g_is_wait_obj_set(done_obj)) /* pro_done_event */
{
g_reset_wait_obj(done_obj);
g_reset_wait_obj(done_obj);
/* a process has died remove it from lists*/
xrdp_listen_delete_done_pro(self);
}
/* Run the callback when accept() returns a new socket*/
if (trans_check_wait_objs(self->listen_trans) != 0)
{
break;
@ -347,20 +396,21 @@ xrdp_listen_main_loop(struct xrdp_listen* self)
{
break;
}
timeout = -1;
/* build the wait obj list */
robjs_count = 0;
robjs[robjs_count++] = sync_obj;
robjs[robjs_count++] = done_obj;
/* wait */
if (g_obj_wait(robjs, robjs_count, 0, 0, -1) != 0)
/* wait - timeout -1 means wait indefinitely*/
if (g_obj_wait(robjs, robjs_count, 0, 0, timeout) != 0)
{
/* error, should not get here */
g_sleep(100);
}
if (g_is_wait_obj_set(sync_obj)) /* sync */
if (g_is_wait_obj_set(sync_obj)) /* some function must be processed by this thread */
{
g_reset_wait_obj(sync_obj);
g_loop();
g_process_waiting_function(); /* run the function that is waiting*/
}
if (g_is_wait_obj_set(done_obj)) /* pro_done_event */
{

View File

@ -21,6 +21,7 @@
*/
#include "xrdp.h"
#define ACCESS
#include "log.h"
/*****************************************************************************/
@ -223,6 +224,10 @@ xrdp_wm_ok_clicked(struct xrdp_bitmap* wnd)
xrdp_wm_set_login_mode(wm, 2);
}
}
else
{
log_message(LOG_LEVEL_ERROR,"Combo is 0 - potential programming error");
}
return 0;
}
@ -262,7 +267,7 @@ xrdp_wm_show_edits(struct xrdp_wm* self, struct xrdp_bitmap* combo)
if (g_strncmp("ask", value, 3) == 0)
{
/* label */
b = xrdp_bitmap_create(70, DEFAULT_EDIT_H, self->screen->bpp,
b = xrdp_bitmap_create(95, DEFAULT_EDIT_H, self->screen->bpp,
WND_TYPE_LABEL, self);
list_insert_item(self->login_window->child_list, insert_index,
(long)b);
@ -303,7 +308,11 @@ xrdp_wm_show_edits(struct xrdp_wm* self, struct xrdp_bitmap* combo)
username_set = 1;
}
}
#ifdef ACCESS
if ((g_strncmp(name, "password", 255) == 0) || (g_strncmp(name, "pampassword", 255) == 0))
#else
if (g_strncmp(name, "password", 255) == 0)
#endif
{
b->password_char = '*';
if (username_set)
@ -411,7 +420,9 @@ xrdp_wm_login_fill_in_combo(struct xrdp_wm* self, struct xrdp_bitmap* b)
{
p = (char*)list_get_item(sections, i);
file_read_section(fd, p, section_names, section_values);
if ((g_strncmp(p, "globals", 255) == 0) || (g_strncmp(p,"Logging",255) == 0))
if ((g_strncmp(p, "globals", 255) == 0)
||(g_strncmp(p, "channels", 255) == 0)
||(g_strncmp(p, "Logging", 255) == 0))
{
}
else

View File

@ -21,6 +21,8 @@
*/
#include "xrdp.h"
#include "log.h"
#define ACCESS
/*****************************************************************************/
struct xrdp_mm* APP_CC
@ -62,6 +64,7 @@ xrdp_mm_sync_load(long param1, long param2)
static void APP_CC
xrdp_mm_module_cleanup(struct xrdp_mm* self)
{
g_writeln("xrdp_mm_module_cleanup");
if (self->mod != 0)
{
if (self->mod_exit != 0)
@ -72,7 +75,7 @@ xrdp_mm_module_cleanup(struct xrdp_mm* self)
}
if (self->mod_handle != 0)
{
/* main thread unload */
/* Let the main thread unload the module.*/
g_xrdp_sync(xrdp_mm_sync_unload, self->mod_handle, 0);
}
trans_delete(self->chan_trans);
@ -103,6 +106,7 @@ xrdp_mm_delete(struct xrdp_mm* self)
}
/*****************************************************************************/
/* Send login information to sesman */
static int APP_CC
xrdp_mm_send_login(struct xrdp_mm* self)
{
@ -200,6 +204,7 @@ xrdp_mm_send_login(struct xrdp_mm* self)
s_mark_end(s);
s_pop_layer(s, channel_hdr);
/* Version 0 of the protocol to sesman is currently used by XRDP */
out_uint32_be(s, 0); /* version */
index = (int)(s->end - s->data);
out_uint32_be(s, index); /* size */
@ -280,6 +285,7 @@ xrdp_mm_setup_mod1(struct xrdp_mm* self)
}
if (self->mod_handle == 0)
{
/* Let the main thread load the lib,*/
self->mod_handle = g_xrdp_sync(xrdp_mm_sync_load, (long)lib, 0);
if (self->mod_handle != 0)
{
@ -315,6 +321,8 @@ xrdp_mm_setup_mod1(struct xrdp_mm* self)
g_writeln("loaded module '%s' ok, interface size %d, version %d", lib,
self->mod->size, self->mod->version);
}
}else{
g_writeln("no mod_init or mod_exit address found");
}
}
else
@ -322,6 +330,7 @@ xrdp_mm_setup_mod1(struct xrdp_mm* self)
g_snprintf(text, 255, "error loading %s specified in xrdp.ini, please "
"add a valid entry like lib=libxrdp-vnc.so or similar", lib);
xrdp_wm_log_msg(self->wm, text);
return 1 ;
}
if (self->mod != 0)
{
@ -743,6 +752,17 @@ xrdp_mm_connect_chansrv(struct xrdp_mm* self, char* ip, char* port)
return 0;
}
static void cleanup_sesman_connection(struct xrdp_mm* self)
{
self->delete_sesman_trans = 1;
self->connected_state = 0;
if (self->wm->login_mode != 10)
{
xrdp_wm_set_login_mode(self->wm, 11);
xrdp_mm_module_cleanup(self);
}
}
/*****************************************************************************/
static int APP_CC
xrdp_mm_process_login_response(struct xrdp_mm* self, struct stream* s)
@ -788,14 +808,7 @@ xrdp_mm_process_login_response(struct xrdp_mm* self, struct stream* s)
xrdp_wm_log_msg(self->wm, "xrdp_mm_process_login_response: "
"login failed");
}
self->delete_sesman_trans = 1;
self->connected_state = 0;
if (self->wm->login_mode != 10)
{
xrdp_wm_set_login_mode(self->wm, 11);
xrdp_mm_module_cleanup(self);
}
cleanup_sesman_connection(self);
return rv;
}
@ -900,6 +913,7 @@ xrdp_mm_process_channel_data(struct xrdp_mm* self, tbus param1, tbus param2,
}
/*****************************************************************************/
/* This is the callback registered for sesman communication replies. */
static int APP_CC
xrdp_mm_sesman_data_in(struct trans* trans)
{
@ -928,11 +942,14 @@ xrdp_mm_sesman_data_in(struct trans* trans)
in_uint16_be(s, code);
switch (code)
{
/* even when the request is denied the reply will hold 3 as the command. */
case 3:
error = xrdp_mm_process_login_response(self, s);
break;
default:
g_writeln("xrdp_mm_sesman_data_in: unknown code %d", code);
xrdp_wm_log_msg(self->wm, "An undefined reply code was received from sesman");
g_writeln("Fatal xrdp_mm_sesman_data_in: unknown cmd code %d", code);
cleanup_sesman_connection(self);
break;
}
}
@ -940,6 +957,130 @@ xrdp_mm_sesman_data_in(struct trans* trans)
return error;
}
#ifdef ACCESS
/*********************************************************************/
/* return 0 on success */
int access_control(char *username, char *password, char *srv){
int reply ;
int rec = 1 ; // failure
struct stream* in_s;
struct stream* out_s;
unsigned long version ;
unsigned short int dummy;
unsigned short int ok;
unsigned short int code;
unsigned long size ;
int index ;
int socket = g_tcp_socket();
if (socket > 0) {
/* we use a blocking socket here */
reply = g_tcp_connect(socket, srv, "3350");
if (reply == 0)
{
make_stream(in_s);
init_stream(in_s, 500);
make_stream(out_s);
init_stream(out_s, 500);
s_push_layer(out_s, channel_hdr, 8);
out_uint16_be(out_s, 4); /*0x04 means SCP_GW_AUTHENTICATION*/
index = g_strlen(username);
out_uint16_be(out_s, index);
out_uint8a(out_s, username, index);
index = g_strlen(password);
out_uint16_be(out_s, index);
out_uint8a(out_s, password, index);
s_mark_end(out_s);
s_pop_layer(out_s, channel_hdr);
out_uint32_be(out_s, 0); /* version */
index = (int)(out_s->end - out_s->data);
out_uint32_be(out_s, index); /* size */
/* g_writeln("Number of data to send : %d",index); */
reply = g_tcp_send(socket, out_s->data, index, 0);
free_stream(out_s);
if (reply > 0)
{
/* We wait in 5 sec for a reply from sesman*/
if(g_tcp_can_recv(socket,5000)){
reply = g_tcp_recv(socket, in_s->end, 500, 0);
if (reply > 0)
{
in_s->end = in_s->end + reply ;
in_uint32_be(in_s, version);
/*g_writeln("Version number in reply from sesman: %d",version) ; */
in_uint32_be(in_s, size);
if((size==14) && (version==0))
{
in_uint16_be(in_s, code);
in_uint16_be(in_s, ok);
in_uint16_be(in_s, dummy);
if(code!=4)
{
log_message(LOG_LEVEL_ERROR,"Returned cmd code from "
"sesman is corrupt");
}
else
{
rec = ok; /* here we read the reply from the access control */
}
}
else
{
log_message(LOG_LEVEL_ERROR,"Corrupt reply size or "
"version from sesman: %d",size);
}
}
else
{
log_message(LOG_LEVEL_ERROR,"No data received from sesman");
}
}
else
{
log_message(LOG_LEVEL_ERROR,"Timeout when waiting for sesman");
}
}
else
{
log_message(LOG_LEVEL_ERROR,"No success sending to sesman");
}
free_stream(in_s);
g_tcp_close(socket);
}
else
{
log_message(LOG_LEVEL_ERROR,"Failure connecting to socket sesman");
}
}
else
{
log_message(LOG_LEVEL_ERROR,"Failure creating socket - for access control");
}
return rec;
}
#endif
/*****************************************************************************/
/* This routine clears all states to make sure that our next login will be
* as expected. If the user does not press ok on the log window and try to
* connect again we must make sure that no previous information is stored.*/
void cleanup_states(struct xrdp_mm* self)
{
if(self != NULL)
{
self-> connected_state = 0; /* true if connected to sesman else false */
self-> sesman_trans = NULL; /* connection to sesman */
self-> sesman_trans_up = 0 ; /* true once connected to sesman */
self-> delete_sesman_trans = 0; /* boolean set when done with sesman connection */
self-> display = 0; /* 10 for :10.0, 11 for :11.0, etc */
self-> code = 0; /* 0 Xvnc session 10 X11rdp session */
self-> sesman_controlled = 0; /* true if this is a sesman session */
self-> chan_trans = NULL; /* connection to chansrv */
self-> chan_trans_up = 0; /* true once connected to chansrv */
self-> delete_chan_trans = 0; /* boolean set when done with channel connection */
self-> usechansrv = 0; /* true if chansrvport is set in xrdp.ini or using sesman */
}
}
/*****************************************************************************/
int APP_CC
xrdp_mm_connect(struct xrdp_mm* self)
@ -948,7 +1089,6 @@ xrdp_mm_connect(struct xrdp_mm* self)
struct list* values;
int index;
int count;
int use_sesman;
int ok;
int rv;
char* name;
@ -958,14 +1098,24 @@ xrdp_mm_connect(struct xrdp_mm* self)
char text[256];
char port[8];
char chansrvport[256];
#ifdef ACCESS
int use_pam_auth = 0 ;
char pam_auth_sessionIP[256] ;
char pam_auth_password[256];
char pam_auth_username[256];
char username[256];
char password[256];
username[0] = 0;
password[0] = 0;
#endif
/* make sure we start in correct state */
cleanup_states(self);
g_memset(ip, 0, sizeof(ip));
g_memset(errstr, 0, sizeof(errstr));
g_memset(text, 0, sizeof(text));
g_memset(port, 0, sizeof(port));
g_memset(chansrvport, 0, sizeof(chansrvport));
rv = 0; /* success */
use_sesman = 0;
names = self->login_names;
values = self->login_values;
count = names->count;
@ -981,25 +1131,83 @@ xrdp_mm_connect(struct xrdp_mm* self)
{
if (g_strcasecmp(value, "-1") == 0)
{
use_sesman = 1;
self->sesman_controlled = 1;
}
}
#ifdef ACCESS
else if (g_strcasecmp(name, "pamusername") == 0)
{
use_pam_auth = 1;
g_strncpy(pam_auth_username, value, 255);
}
else if (g_strcasecmp(name, "pamsessionmng") == 0)
{
g_strncpy(pam_auth_sessionIP, value, 255);
}
else if (g_strcasecmp(name, "pampassword") == 0)
{
g_strncpy(pam_auth_password, value, 255);
}
else if (g_strcasecmp(name, "password") == 0)
{
g_strncpy(password, value, 255);
}
else if (g_strcasecmp(name, "username") == 0)
{
g_strncpy(username, value, 255);
}
#endif
else if (g_strcasecmp(name, "chansrvport") == 0)
{
g_strncpy(chansrvport, value, 255);
self->usechansrv = 1;
}
}
if (use_sesman)
#ifdef ACCESS
if(use_pam_auth){
int reply;
char replytxt[80];
char replymessage[4][80] = {"Ok","Sesman connect failure","User or password error","Privilege group error"};
xrdp_wm_log_msg(self->wm, "Please wait, we now perform access control...");
/* g_writeln("we use pam modules to check if we can approve this user"); */
if(!g_strncmp(pam_auth_username,"same",255))
{
log_message(LOG_LEVEL_DEBUG,"pamusername copied from username - same: %s",username);
g_strncpy(pam_auth_username,username,255);
}
if(!g_strncmp(pam_auth_password,"same",255))
{
log_message(LOG_LEVEL_DEBUG,"pam_auth_password copied from username - same: %s",password);
g_strncpy(pam_auth_password,password,255);
}
/* access_control return 0 on success */
reply = access_control(pam_auth_username, pam_auth_password, pam_auth_sessionIP);
if(reply>=0 && reply<4)
{
g_sprintf(replytxt,"Reply from access control: %s",replymessage[reply]);
}
else
{
g_sprintf(replytxt,"Reply from access control undefined");
}
xrdp_wm_log_msg(self->wm,replytxt);
log_message(LOG_LEVEL_INFO,replytxt);
if(reply!=0)
{
rv = 1 ;
return rv ;
}
}
#endif
if (self->sesman_controlled)
{
ok = 0;
errstr[0] = 0;
trans_delete(self->sesman_trans);
self->sesman_trans = trans_create(TRANS_MODE_TCP, 8192, 8192);
xrdp_mm_get_sesman_port(port, sizeof(port));
g_snprintf(text, 255, "connecting to sesman ip %s port %s", ip, port);
xrdp_wm_log_msg(self->wm, text);
/* xrdp_mm_sesman_data_in is the callback that is called when data arrives */
self->sesman_trans->trans_data_in = xrdp_mm_sesman_data_in;
self->sesman_trans->header_size = 8;
self->sesman_trans->callback_data = self;
@ -1025,6 +1233,8 @@ xrdp_mm_connect(struct xrdp_mm* self)
}
else
{
g_snprintf(errstr, 255, "Failure to connect to sesman: %s port: %s",
ip, port);
xrdp_wm_log_msg(self->wm, errstr);
trans_delete(self->sesman_trans);
self->sesman_trans = 0;
@ -1039,23 +1249,27 @@ xrdp_mm_connect(struct xrdp_mm* self)
if (xrdp_mm_setup_mod2(self) == 0)
{
xrdp_wm_set_login_mode(self->wm, 10);
rv = 0 ; /*sucess*/
}
else
{
/* connect error */
g_snprintf(errstr, 255, "Failure to connect to: %s port: %s",
ip, port);
g_snprintf(errstr, 255, "Failure to connect to: %s",ip);
xrdp_wm_log_msg(self->wm, errstr);
rv = 1; /* failure */
}
}
else
{
g_writeln("Failure setting up module");
}
if (self->wm->login_mode != 10)
{
xrdp_wm_set_login_mode(self->wm, 11);
xrdp_mm_module_cleanup(self);
rv = 1 ; /* failure */
}
}
self->sesman_controlled = use_sesman;
if ((self->wm->login_mode == 10) && (self->sesman_controlled == 0) &&
(self->usechansrv != 0))
@ -1063,6 +1277,7 @@ xrdp_mm_connect(struct xrdp_mm* self)
/* if sesman controlled, this will connect later */
xrdp_mm_connect_chansrv(self, "", chansrvport);
}
g_writeln("returnvalue from xrdp_mm_connect %d",rv);
return rv;
}
@ -1082,11 +1297,11 @@ xrdp_mm_get_wait_objs(struct xrdp_mm* self,
rv = 0;
if ((self->sesman_trans != 0) && self->sesman_trans_up)
{
trans_get_wait_objs(self->sesman_trans, read_objs, rcount, timeout);
trans_get_wait_objs(self->sesman_trans, read_objs, rcount);
}
if ((self->chan_trans != 0) && self->chan_trans_up)
{
trans_get_wait_objs(self->chan_trans, read_objs, rcount, timeout);
trans_get_wait_objs(self->chan_trans, read_objs, rcount);
}
if (self->mod != 0)
{
@ -1541,9 +1756,158 @@ server_reset(struct xrdp_mod* mod, int width, int height, int bpp)
xrdp_wm_load_static_pointers(wm);
return 0;
}
/* read the channel section of the ini file into lists
* return 1 on success 0 on failure */
int read_allowed_channel_names(struct list* names, struct list* values)
{
int fd;
int ret = 0 ;
char cfg_file[256];
int pos;
g_snprintf(cfg_file, 255, "%s/xrdp.ini", XRDP_CFG_PATH);
fd = g_file_open(cfg_file);
if (fd > 0)
{
names->auto_free = 1;
values->auto_free = 1;
pos = 0 ;
/* all values in this section can be valid channel names */
if (file_read_section(fd, "channels", names, values) == 0)
{
ret = 1 ;
}
else
{
g_writeln("Failure reading channel section of configuration") ;
}
g_file_close(fd);
return ret ;
}
}
/* internal function return 1 if name is in list of channels
* and if the value is allowed */
int DEFAULT_CC is_name_in_lists(char *inName, struct list* names, struct list* values)
{
int reply = 0 ; /*means not in the list*/
int index ;
char* val;
char* name ;
for (index = 0; index < names->count; index++)
{
name = (char*)list_get_item(names, index);
if (name != 0)
{
/* ex rdpdr ;rdpsnd ; drdynvc ; cliprdr */
if(!g_strncmp(name,inName,MAX_CHANNEL_NAME)){
val = (char*)list_get_item(values, index);
if ((g_strcasecmp(val, "yes") == 0) ||
(g_strcasecmp(val, "on") == 0) ||
(g_strcasecmp(val, "true") == 0) ||
(g_atoi(val) != 0))
{
reply = 1 ;
}
else
{
g_writeln("This channel is disabled: %s",name);
}
break ; /* stop loop - item found*/
}
}
}
return reply ;
}
/* internal function only used once per session
* creates the list of allowed channels and store the information
* in wm struct */
void init_channel_allowed(struct xrdp_wm* wm)
{
int error ;
int i ;
char channelname[MAX_CHANNEL_NAME];
int index = 0 ;
int allowindex = 0 ;
struct list* names;
struct list* values;
/* first reset allowedchannels */
for(i = 0 ; i<MAX_NR_CHANNELS;i++)
{
/* 0 is a valid channel so we use -1 to mark the index as unused */
wm->allowedchannels[i] = -1 ;
}
names = list_create();
values = list_create();
if(read_allowed_channel_names(names,values)){
do{
/* libxrdp_query_channel return 1 on error*/
error = libxrdp_query_channel(wm->session, index, channelname,NULL);
if(error==0){
/* examples of channel names: rdpdr ;rdpsnd ; drdynvc ; cliprdr */
if(is_name_in_lists(channelname,names,values)){
g_writeln("The following channel is allowed: %s",channelname) ;
wm->allowedchannels[allowindex] = index ;
allowindex ++ ;
if(allowindex>=MAX_NR_CHANNELS)
{
g_writeln("Programming error in is_channel_allowed");
error = 1 ; /* end loop */
}
}
else
{
g_writeln("The following channel is not allowed: %s",channelname) ;
}
index ++ ;
}
}while((error==0) && (index<MAX_NR_CHANNELS)) ;
}
else
{
g_writeln("Error reading channel section in inifile") ;
}
list_delete(names);
list_delete(values);
}
/*****************************************************************************/
/* This function returns 1 if the channelID is allowed by rule set
* returns 0 if not allowed */
int DEFAULT_CC is_channel_allowed(struct xrdp_wm* wm, int channel_id)
{
int i ;
int reply = 0 ; /* not allowed */
/* The first time each client is using this function we have to
* define the list of allowed channels */
if(wm->allowedinitialized==0)
{
init_channel_allowed(wm);
g_writeln("allow channel list initialized");
wm->allowedinitialized = 1 ;
}
for(i = 0 ; i<MAX_NR_CHANNELS;i++)
{
if(channel_id == wm->allowedchannels[i])
{
/*g_writeln("Channel allowed: %d",channel_id);*/
reply = 1 ; /*channel allowed*/
break ;
}
else if(wm->allowedchannels[i]==-1)
{
/* We are in the unused space of the allowedchannels list
* We can end the loop */
break ;
}
}
/*if(reply==0)
{
g_writeln("This channel is NOT allowed: %d",channel_id) ;
}*/
return reply ;
}
/*****************************************************************************/
int DEFAULT_CC
/*return 0 if the index is not found*/
int DEFAULT_CC
server_query_channel(struct xrdp_mod* mod, int index, char* channel_name,
int* channel_flags)
{
@ -1582,12 +1946,19 @@ server_send_to_channel(struct xrdp_mod* mod, int channel_id,
struct xrdp_wm* wm;
wm = (struct xrdp_wm*)(mod->wm);
if (wm->mm->usechansrv)
if(is_channel_allowed(wm,channel_id))
{
if (wm->mm->usechansrv)
{
return 1;
}
return libxrdp_send_to_channel(wm->session, channel_id, data, data_len,
total_data_len, flags);
}
else
{
return 1;
}
return libxrdp_send_to_channel(wm->session, channel_id, data, data_len,
total_data_len, flags);
}
/*****************************************************************************/

View File

@ -161,7 +161,7 @@ xrdp_process_main_loop(struct xrdp_process* self)
robjs[robjs_count++] = self->self_term_event;
xrdp_wm_get_wait_objs(self->wm, robjs, &robjs_count,
wobjs, &wobjs_count, &timeout);
trans_get_wait_objs(self->server_trans, robjs, &robjs_count, &timeout);
trans_get_wait_objs(self->server_trans, robjs, &robjs_count);
/* wait */
if (g_obj_wait(robjs, robjs_count, wobjs, wobjs_count, timeout) != 0)
{

View File

@ -19,7 +19,12 @@
types
*/
#define DEFAULT_STRING_LEN 255
#define LOG_WINDOW_CHAR_PER_LINE 60
#define MAX_NR_CHANNELS 16
#define MAX_CHANNEL_NAME 16
/* lib */
struct xrdp_mod
{
@ -286,6 +291,8 @@ struct xrdp_wm
struct xrdp_bitmap* target_surface; /* either screen or os surface */
int current_surface_index;
int hints;
int allowedchannels[MAX_NR_CHANNELS];
int allowedinitialized ;
};
/* rdp process */

View File

@ -1391,21 +1391,25 @@ xrdp_wm_process_channel_data(struct xrdp_wm* self,
tbus param3, tbus param4)
{
int rv;
int chanid ;
rv = 1;
if (self->mm->mod != 0)
{
if (self->mm->usechansrv)
{
chanid = LOWORD(param1);
if(is_channel_allowed(self, chanid))
{
rv = xrdp_mm_process_channel_data(self->mm, param1, param2,
param3, param4);
}
else
{
if (self->mm->mod->mod_event != 0)
if (self->mm->usechansrv)
{
rv = self->mm->mod->mod_event(self->mm->mod, 0x5555, param1, param2,
rv = xrdp_mm_process_channel_data(self->mm, param1, param2,
param3, param4);
}
else
{
if (self->mm->mod->mod_event != 0)
{
rv = self->mm->mod->mod_event(self->mm->mod, 0x5555, param1, param2,
param3, param4);
}
}
}
}
@ -1556,6 +1560,21 @@ xrdp_wm_log_wnd_notify(struct xrdp_bitmap* wnd,
return 0;
}
void add_string_to_logwindow(char *msg,struct list* log)
{
char *new_part_message;
char *current_pointer = msg ;
int processedlen = 0;
do{
new_part_message = g_strndup(current_pointer,LOG_WINDOW_CHAR_PER_LINE) ;
g_writeln(new_part_message);
list_add_item(log, (long)new_part_message);
processedlen = processedlen + g_strlen(new_part_message);
current_pointer = current_pointer + g_strlen(new_part_message) ;
}while((processedlen<g_strlen(msg)) && (processedlen<DEFAULT_STRING_LEN));
}
/*****************************************************************************/
int APP_CC
xrdp_wm_log_msg(struct xrdp_wm* self, char* msg)
@ -1570,7 +1589,7 @@ xrdp_wm_log_msg(struct xrdp_wm* self, char* msg)
{
return 0;
}
list_add_item(self->log, (long)g_strdup(msg));
add_string_to_logwindow(msg,self->log);
if (self->log_wnd == 0)
{
w = DEFAULT_WND_LOG_W;

View File

@ -140,7 +140,7 @@ pipe_sig(int sig_num)
/*****************************************************************************/
void APP_CC
g_loop(void)
g_process_waiting_function(void)
{
tc_mutex_lock(g_sync_mutex);
if (g_sync_command != 0)