Merge branch 'master' of github.com:FreeRDP/xrdp
This commit is contained in:
commit
608101fbca
@ -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)
|
||||
|
@ -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
147
common/rail.h
Normal 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
|
@ -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)
|
||||
{
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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
625
libxrdp/xrdp_orders_rail.c
Normal 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,
|
||||
¬ify_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;
|
||||
}
|
50
libxrdp/xrdp_orders_rail.h
Normal file
50
libxrdp/xrdp_orders_rail.h
Normal 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
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
@ -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)
|
||||
|
43
xrdp/xrdp.c
43
xrdp/xrdp.c
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
{
|
||||
|
@ -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
|
||||
|
423
xrdp/xrdp_mm.c
423
xrdp/xrdp_mm.c
@ -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);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user