summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--common/os_calls.c126
-rw-r--r--common/os_calls.h4
-rw-r--r--common/rail.h147
-rw-r--r--common/trans.c2
-rw-r--r--common/trans.h2
-rw-r--r--common/xrdp_client_info.h6
-rw-r--r--freerdp1/xrdp-freerdp.c10
-rw-r--r--libxrdp/Makefile.am3
-rw-r--r--libxrdp/libxrdp.c29
-rw-r--r--libxrdp/libxrdp.h2
-rw-r--r--libxrdp/xrdp_channel.c14
-rw-r--r--libxrdp/xrdp_mcs.c27
-rw-r--r--libxrdp/xrdp_orders.c2
-rw-r--r--libxrdp/xrdp_orders_rail.c625
-rw-r--r--libxrdp/xrdp_orders_rail.h50
-rw-r--r--libxrdp/xrdp_rdp.c112
-rw-r--r--libxrdp/xrdp_sec.c19
-rw-r--r--rdp/rdp_sec.c8
-rw-r--r--sesman/chansrv/chansrv.c6
-rw-r--r--sesman/libscp/libscp_session.c3
-rw-r--r--sesman/libscp/libscp_types.h4
-rw-r--r--sesman/libscp/libscp_v0.c63
-rw-r--r--sesman/libscp/libscp_v0.h9
-rw-r--r--sesman/scp_v0.c46
-rw-r--r--xrdp/xrdp.c43
-rw-r--r--xrdp/xrdp.h4
-rw-r--r--xrdp/xrdp.ini18
-rw-r--r--xrdp/xrdp_listen.c74
-rw-r--r--xrdp/xrdp_login_wnd.c15
-rw-r--r--xrdp/xrdp_mm.c423
-rw-r--r--xrdp/xrdp_process.c2
-rw-r--r--xrdp/xrdp_types.h7
-rw-r--r--xrdp/xrdp_wm.c39
-rw-r--r--xrdp/xrdpwin.c2
34 files changed, 1824 insertions, 122 deletions
diff --git a/common/os_calls.c b/common/os_calls.c
index 4387f8f9..8b3e01dc 100644
--- a/common/os_calls.c
+++ b/common/os_calls.c
@@ -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)
diff --git a/common/os_calls.h b/common/os_calls.h
index ddcb59d8..41b221bf 100644
--- a/common/os_calls.h
+++ b/common/os_calls.h
@@ -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
diff --git a/common/rail.h b/common/rail.h
new file mode 100644
index 00000000..deed3a9e
--- /dev/null
+++ b/common/rail.h
@@ -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
diff --git a/common/trans.c b/common/trans.c
index 377b90ba..6b762d00 100644
--- a/common/trans.c
+++ b/common/trans.c
@@ -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)
{
diff --git a/common/trans.h b/common/trans.h
index bb0f42c0..8e8d942a 100644
--- a/common/trans.h
+++ b/common/trans.h
@@ -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
diff --git a/common/xrdp_client_info.h b/common/xrdp_client_info.h
index 7fe93c26..cdd77921 100644
--- a/common/xrdp_client_info.h
+++ b/common/xrdp_client_info.h
@@ -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
diff --git a/freerdp1/xrdp-freerdp.c b/freerdp1/xrdp-freerdp.c
index 45d1a18d..5c218724 100644
--- a/freerdp1/xrdp-freerdp.c
+++ b/freerdp1/xrdp-freerdp.c
@@ -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 */
diff --git a/libxrdp/Makefile.am b/libxrdp/Makefile.am
index 08fb7130..ad891bd8 100644
--- a/libxrdp/Makefile.am
+++ b/libxrdp/Makefile.am
@@ -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)
diff --git a/libxrdp/libxrdp.c b/libxrdp/libxrdp.c
index 5c228305..cafd63fb 100644
--- a/libxrdp/libxrdp.c
+++ b/libxrdp/libxrdp.c
@@ -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;
}
diff --git a/libxrdp/libxrdp.h b/libxrdp/libxrdp.h
index 7aae38b5..7792d157 100644
--- a/libxrdp/libxrdp.h
+++ b/libxrdp/libxrdp.h
@@ -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
diff --git a/libxrdp/xrdp_channel.c b/libxrdp/xrdp_channel.c
index 00497c35..092cefa4 100644
--- a/libxrdp/xrdp_channel.c
+++ b/libxrdp/xrdp_channel.c
@@ -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;
diff --git a/libxrdp/xrdp_mcs.c b/libxrdp/xrdp_mcs.c
index af65faf2..1a7a0411 100644
--- a/libxrdp/xrdp_mcs.c
+++ b/libxrdp/xrdp_mcs.c
@@ -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)
diff --git a/libxrdp/xrdp_orders.c b/libxrdp/xrdp_orders.c
index cff1324a..d068c39a 100644
--- a/libxrdp/xrdp_orders.c
+++ b/libxrdp/xrdp_orders.c
@@ -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;
diff --git a/libxrdp/xrdp_orders_rail.c b/libxrdp/xrdp_orders_rail.c
new file mode 100644
index 00000000..087cf42e
--- /dev/null
+++ b/libxrdp/xrdp_orders_rail.c
@@ -0,0 +1,625 @@
+/**
+ * xrdp: A Remote Desktop Protocol server.
+ *
+ * Copyright (C) Jay Sorg 2012
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "libxrdp.h"
+#include "rail.h"
+
+/* [MS-RDPERP]: Remote Desktop Protocol:
+ Remote Programs Virtual Channel Extension
+ http://msdn.microsoft.com/en-us/library/cc242568(v=prot.10) */
+
+/*****************************************************************************/
+/* RAIL */
+/* returns error */
+int APP_CC
+xrdp_orders_send_window_delete(struct xrdp_orders* self, int window_id)
+{
+ int order_size;
+ int order_flags;
+ int field_present_flags;
+
+ order_size = 11;
+ xrdp_orders_check(self, order_size);
+ self->order_count++;
+ order_flags = RDP_ORDER_SECONDARY;
+ order_flags |= 0xb << 2; /* type TS_ALTSEC_WINDOW */
+ out_uint8(self->out_s, order_flags);
+ /* orderSize (2 bytes) */
+ out_uint16_le(self->out_s, order_size);
+ /* FieldsPresentFlags (4 bytes) */
+ field_present_flags = WINDOW_ORDER_TYPE_WINDOW | WINDOW_ORDER_STATE_DELETED;
+ out_uint32_le(self->out_s, field_present_flags);
+ /* windowId (4 bytes) */
+ out_uint32_le(self->out_s, window_id);
+ return 0;
+}
+
+/*****************************************************************************/
+/* RAIL */
+/* returns error */
+/* flags can contain WINDOW_ORDER_STATE_NEW and/or
+ WINDOW_ORDER_FIELD_ICON_BIG */
+int APP_CC
+xrdp_orders_send_window_cached_icon(struct xrdp_orders* self,
+ int window_id, int cache_entry,
+ int cache_id, int flags)
+{
+ int order_size;
+ int order_flags;
+ int field_present_flags;
+
+ order_size = 14;
+ xrdp_orders_check(self, order_size);
+ self->order_count++;
+ order_flags = RDP_ORDER_SECONDARY;
+ order_flags |= 0xb << 2; /* type TS_ALTSEC_WINDOW */
+ out_uint8(self->out_s, order_flags);
+ /* orderSize (2 bytes) */
+ out_uint16_le(self->out_s, order_size);
+ /* FieldsPresentFlags (4 bytes) */
+ field_present_flags = flags | WINDOW_ORDER_TYPE_WINDOW |
+ WINDOW_ORDER_CACHED_ICON;
+ out_uint32_le(self->out_s, field_present_flags);
+ /* windowId (4 bytes) */
+ out_uint32_le(self->out_s, window_id);
+ /* CacheEntry (2 bytes) */
+ out_uint16_le(self->out_s, cache_entry);
+ /* CacheId (1 byte) */
+ out_uint8(self->out_s, cache_id);
+ return 0;
+}
+
+/*****************************************************************************/
+/* RAIL */
+/* returns error */
+static int APP_CC
+xrdp_orders_send_ts_icon(struct stream* s, int cache_entry, int cache_id,
+ struct rail_icon_info* icon_info)
+{
+ int use_cmap;
+
+ use_cmap = 0;
+ if ((icon_info->bpp == 1) || (icon_info->bpp == 2) || (icon_info->bpp == 4))
+ {
+ use_cmap = 1;
+ }
+
+ /* TS_ICON_INFO */
+ out_uint16_le(s, cache_entry);
+ out_uint8(s, cache_id);
+ out_uint8(s, icon_info->bpp);
+ out_uint16_le(s, icon_info->width);
+ out_uint16_le(s, icon_info->height);
+ if (use_cmap)
+ {
+ out_uint16_le(s, icon_info->cmap_bytes);
+ }
+ out_uint16_le(s, icon_info->mask_bytes);
+ out_uint16_le(s, icon_info->data_bytes);
+ out_uint8p(s, icon_info->mask, icon_info->mask_bytes);
+ if (use_cmap)
+ {
+ out_uint8p(s, icon_info->cmap, icon_info->cmap_bytes);
+ }
+ out_uint8p(s, icon_info->data, icon_info->data_bytes);
+ return 0;
+}
+
+/*****************************************************************************/
+/* RAIL */
+/* returns error */
+/* flags can contain WINDOW_ORDER_STATE_NEW and/or
+ WINDOW_ORDER_FIELD_ICON_BIG */
+int APP_CC
+xrdp_orders_send_window_icon(struct xrdp_orders* self,
+ int window_id, int cache_entry, int cache_id,
+ struct rail_icon_info* icon_info,
+ int flags)
+{
+ int order_size;
+ int order_flags;
+ int field_present_flags;
+ int use_cmap;
+
+ use_cmap = 0;
+ if ((icon_info->bpp == 1) || (icon_info->bpp == 2) || (icon_info->bpp == 4))
+ {
+ use_cmap = 1;
+ }
+ order_size = 23 + icon_info->mask_bytes + icon_info->data_bytes;
+ if (use_cmap)
+ {
+ order_size += icon_info->cmap_bytes + 2;
+ }
+ xrdp_orders_check(self, order_size);
+ self->order_count++;
+ order_flags = RDP_ORDER_SECONDARY;
+ order_flags |= 0xb << 2; /* type TS_ALTSEC_WINDOW */
+ out_uint8(self->out_s, order_flags);
+ /* orderSize (2 bytes) */
+ out_uint16_le(self->out_s, order_size);
+ /* FieldsPresentFlags (4 bytes) */
+ field_present_flags = flags | WINDOW_ORDER_TYPE_WINDOW |
+ WINDOW_ORDER_ICON;
+ out_uint32_le(self->out_s, field_present_flags);
+ /* windowId (4 bytes) */
+ out_uint32_le(self->out_s, window_id);
+
+ xrdp_orders_send_ts_icon(self->out_s, cache_entry, cache_id, icon_info);
+
+ return 0;
+}
+
+/*****************************************************************************/
+/* returns error */
+static int APP_CC
+xrdp_orders_send_as_unicode(struct stream* s, const char* text)
+{
+ int str_chars;
+ int index;
+ int i32;
+ twchar wdst[256];
+
+ str_chars = g_mbstowcs(wdst, text, 255);
+ if (str_chars > 0)
+ {
+ i32 = str_chars * 2;
+ out_uint16_le(s, i32);
+ for (index = 0; index < str_chars; index++)
+ {
+ i32 = wdst[index];
+ out_uint16_le(s, i32);
+ }
+ }
+ else
+ {
+ out_uint16_le(s, 0);
+ }
+ return 0;
+}
+
+/*****************************************************************************/
+/* RAIL */
+/* returns error */
+/* flags can contain WINDOW_ORDER_STATE_NEW */
+int APP_CC
+xrdp_orders_send_window_new_update(struct xrdp_orders* self, int window_id,
+ struct rail_window_state_order* window_state,
+ int flags)
+{
+ int order_size;
+ int order_flags;
+ int field_present_flags;
+ int num_chars;
+ int index;
+
+ order_size = 11;
+ field_present_flags = flags | WINDOW_ORDER_TYPE_WINDOW;
+ if (field_present_flags & WINDOW_ORDER_FIELD_OWNER)
+ {
+ /* ownerWindowId (4 bytes) */
+ order_size += 4;
+ }
+ if (field_present_flags & WINDOW_ORDER_FIELD_STYLE)
+ {
+ /* style (4 bytes) */
+ order_size += 4;
+ /* extendedStyle (4 bytes) */
+ order_size += 4;
+ }
+ if (field_present_flags & WINDOW_ORDER_FIELD_SHOW)
+ {
+ /* showState (1 byte) */
+ order_size += 1;
+ }
+ if (field_present_flags & WINDOW_ORDER_FIELD_TITLE)
+ {
+ /* titleInfo */
+ num_chars = g_mbstowcs(0, window_state->title_info, 0);
+ order_size += 2 * num_chars + 2;
+ }
+ if (field_present_flags & WINDOW_ORDER_FIELD_CLIENT_AREA_OFFSET)
+ {
+ /* clientOffsetX (4 bytes) */
+ order_size += 4;
+ /* clientOffsetY (4 bytes) */
+ order_size += 4;
+ }
+ if (field_present_flags & WINDOW_ORDER_FIELD_CLIENT_AREA_SIZE)
+ {
+ /* clientAreaWidth (4 bytes) */
+ order_size += 4;
+ /* clientAreaHeight (4 bytes) */
+ order_size += 4;
+ }
+ if (field_present_flags & WINDOW_ORDER_FIELD_RP_CONTENT)
+ {
+ /* RPContent (1 byte) */
+ order_size += 1;
+ }
+ if (field_present_flags & WINDOW_ORDER_FIELD_ROOT_PARENT)
+ {
+ /* rootParentHandle (4 bytes) */
+ order_size += 4;
+ }
+ if (field_present_flags & WINDOW_ORDER_FIELD_WND_OFFSET)
+ {
+ /* windowOffsetX (4 bytes) */
+ order_size += 4;
+ /* windowOffsetY (4 bytes) */
+ order_size += 4;
+ }
+ if (field_present_flags & WINDOW_ORDER_FIELD_WND_CLIENT_DELTA)
+ {
+ /* windowClientDeltaX (4 bytes) */
+ order_size += 4;
+ /* windowClientDeltaY (4 bytes) */
+ order_size += 4;
+ }
+ if (field_present_flags & WINDOW_ORDER_FIELD_WND_SIZE)
+ {
+ /* windowWidth (4 bytes) */
+ order_size += 4;
+ /* windowHeight (4 bytes) */
+ order_size += 4;
+ }
+ if (field_present_flags & WINDOW_ORDER_FIELD_WND_RECTS)
+ {
+ /* numWindowRects (2 bytes) */
+ order_size += 2;
+ order_size += 8 * window_state->num_window_rects;
+ }
+ if (field_present_flags & WINDOW_ORDER_FIELD_VIS_OFFSET)
+ {
+ /* visibleOffsetX (4 bytes) */
+ order_size += 4;
+ /* visibleOffsetY (4 bytes) */
+ order_size += 4;
+ }
+ if (field_present_flags & WINDOW_ORDER_FIELD_VISIBILITY)
+ {
+ /* numVisibilityRects (2 bytes) */
+ order_size += 2;
+ order_size += 8 * window_state->num_visibility_rects;
+ }
+
+ xrdp_orders_check(self, order_size);
+ self->order_count++;
+ order_flags = RDP_ORDER_SECONDARY;
+ order_flags |= 0xb << 2; /* type TS_ALTSEC_WINDOW */
+ out_uint8(self->out_s, order_flags);
+ /* orderSize (2 bytes) */
+ out_uint16_le(self->out_s, order_size);
+ /* FieldsPresentFlags (4 bytes) */
+ out_uint32_le(self->out_s, field_present_flags);
+ /* windowId (4 bytes) */
+ out_uint32_le(self->out_s, window_id);
+
+ if (field_present_flags & WINDOW_ORDER_FIELD_OWNER)
+ {
+ /* ownerWindowId (4 bytes) */
+ out_uint32_le(self->out_s, window_state->owner_window_id);
+ }
+ if (field_present_flags & WINDOW_ORDER_FIELD_STYLE)
+ {
+ /* style (4 bytes) */
+ out_uint32_le(self->out_s, window_state->style);
+ /* extendedStyle (4 bytes) */
+ out_uint32_le(self->out_s, window_state->extended_style);
+ }
+ if (field_present_flags & WINDOW_ORDER_FIELD_SHOW)
+ {
+ /* showState (1 byte) */
+ out_uint8(self->out_s, window_state->show_state);
+ }
+ if (field_present_flags & WINDOW_ORDER_FIELD_TITLE)
+ {
+ /* titleInfo */
+ xrdp_orders_send_as_unicode(self->out_s, window_state->title_info);
+ }
+ if (field_present_flags & WINDOW_ORDER_FIELD_CLIENT_AREA_OFFSET)
+ {
+ /* clientOffsetX (4 bytes) */
+ out_uint32_le(self->out_s, window_state->client_offset_x);
+ /* clientOffsetY (4 bytes) */
+ out_uint32_le(self->out_s, window_state->client_offset_y);
+ }
+ if (field_present_flags & WINDOW_ORDER_FIELD_CLIENT_AREA_SIZE)
+ {
+ /* clientAreaWidth (4 bytes) */
+ out_uint32_le(self->out_s, window_state->client_area_width);
+ /* clientAreaHeight (4 bytes) */
+ out_uint32_le(self->out_s, window_state->client_area_height);
+ }
+ if (field_present_flags & WINDOW_ORDER_FIELD_RP_CONTENT)
+ {
+ /* RPContent (1 byte) */
+ out_uint8(self->out_s, window_state->rp_content);
+ }
+ if (field_present_flags & WINDOW_ORDER_FIELD_ROOT_PARENT)
+ {
+ /* rootParentHandle (4 bytes) */
+ out_uint32_le(self->out_s, window_state->root_parent_handle);
+ }
+ if (field_present_flags & WINDOW_ORDER_FIELD_WND_OFFSET)
+ {
+ /* windowOffsetX (4 bytes) */
+ out_uint32_le(self->out_s, window_state->window_offset_x);
+ /* windowOffsetY (4 bytes) */
+ out_uint32_le(self->out_s, window_state->window_offset_y);
+ }
+ if (field_present_flags & WINDOW_ORDER_FIELD_WND_CLIENT_DELTA)
+ {
+ /* windowClientDeltaX (4 bytes) */
+ out_uint32_le(self->out_s, window_state->window_client_delta_x);
+ /* windowClientDeltaY (4 bytes) */
+ out_uint32_le(self->out_s, window_state->window_client_delta_y);
+ }
+ if (field_present_flags & WINDOW_ORDER_FIELD_WND_SIZE)
+ {
+ /* windowWidth (4 bytes) */
+ out_uint32_le(self->out_s, window_state->window_width);
+ /* windowHeight (4 bytes) */
+ out_uint32_le(self->out_s, window_state->window_height);
+ }
+ if (field_present_flags & WINDOW_ORDER_FIELD_WND_RECTS)
+ {
+ /* numWindowRects (2 bytes) */
+ out_uint16_le(self->out_s, window_state->num_window_rects);
+ for (index = 0; index < window_state->num_window_rects; index++)
+ {
+ out_uint16_le(self->out_s, window_state->window_rects[index].left);
+ out_uint16_le(self->out_s, window_state->window_rects[index].top);
+ out_uint16_le(self->out_s, window_state->window_rects[index].right);
+ out_uint16_le(self->out_s, window_state->window_rects[index].bottom);
+ }
+ }
+ if (field_present_flags & WINDOW_ORDER_FIELD_VIS_OFFSET)
+ {
+ /* visibleOffsetX (4 bytes) */
+ out_uint32_le(self->out_s, window_state->visible_offset_x);
+ /* visibleOffsetY (4 bytes) */
+ out_uint32_le(self->out_s, window_state->visible_offset_y);
+ }
+ if (field_present_flags & WINDOW_ORDER_FIELD_VISIBILITY)
+ {
+ /* numVisibilityRects (2 bytes) */
+ out_uint16_le(self->out_s, window_state->num_visibility_rects);
+ for (index = 0; index < window_state->num_visibility_rects; index++)
+ {
+ out_uint16_le(self->out_s, window_state->visibility_rects[index].left);
+ out_uint16_le(self->out_s, window_state->visibility_rects[index].top);
+ out_uint16_le(self->out_s, window_state->visibility_rects[index].right);
+ out_uint16_le(self->out_s, window_state->visibility_rects[index].bottom);
+ }
+ }
+
+ return 0;
+}
+
+/*****************************************************************************/
+/* RAIL */
+/* returns error */
+int APP_CC
+xrdp_orders_send_notify_delete(struct xrdp_orders* self, int window_id,
+ int notify_id)
+{
+ int order_size;
+ int order_flags;
+ int field_present_flags;
+
+ order_size = 15;
+ xrdp_orders_check(self, order_size);
+ self->order_count++;
+ order_flags = RDP_ORDER_SECONDARY;
+ order_flags |= 0xb << 2; /* type TS_ALTSEC_WINDOW */
+ out_uint8(self->out_s, order_flags);
+ /* orderSize (2 bytes) */
+ out_uint16_le(self->out_s, order_size);
+ /* FieldsPresentFlags (4 bytes) */
+ field_present_flags = WINDOW_ORDER_TYPE_NOTIFY | WINDOW_ORDER_STATE_DELETED;
+ out_uint32_le(self->out_s, field_present_flags);
+ /* windowId (4 bytes) */
+ out_uint32_le(self->out_s, window_id);
+ /* notifyIconId (4 bytes) */
+ out_uint32_le(self->out_s, notify_id);
+ return 0;
+}
+
+/*****************************************************************************/
+/* RAIL */
+/* returns error */
+/* flags can contain WINDOW_ORDER_STATE_NEW */
+int APP_CC
+xrdp_orders_send_notify_new_update(struct xrdp_orders* self,
+ int window_id, int notify_id,
+ struct rail_notify_state_order* notify_state,
+ int flags)
+{
+ int order_size;
+ int order_flags;
+ int field_present_flags;
+ int num_chars;
+ int use_cmap;
+
+ order_size = 15;
+ field_present_flags = flags | WINDOW_ORDER_TYPE_NOTIFY;
+ if (field_present_flags & WINDOW_ORDER_FIELD_NOTIFY_VERSION)
+ {
+ /* Version (4 bytes) */
+ order_size += 4;
+ }
+ if (field_present_flags & WINDOW_ORDER_FIELD_NOTIFY_TIP)
+ {
+ /* ToolTip (variable) UNICODE_STRING */
+ num_chars = g_mbstowcs(0, notify_state->tool_tip, 0);
+ order_size += 2 * num_chars + 2;
+ }
+ if (field_present_flags & WINDOW_ORDER_FIELD_NOTIFY_INFO_TIP)
+ {
+ /* InfoTip (variable) TS_NOTIFY_ICON_INFOTIP */
+ /* UNICODE_STRING */
+ num_chars = g_mbstowcs(0, notify_state->infotip.title, 0);
+ order_size += 2 * num_chars + 2;
+ /* UNICODE_STRING */
+ num_chars = g_mbstowcs(0, notify_state->infotip.text, 0);
+ order_size += 2 * num_chars + 2;
+ /* Timeout (4 bytes) */
+ /* InfoFlags (4 bytes) */
+ order_size += 8;
+ }
+ if (field_present_flags & WINDOW_ORDER_FIELD_NOTIFY_STATE)
+ {
+ /* State (4 bytes) */
+ order_size += 4;
+ }
+ if (field_present_flags & WINDOW_ORDER_ICON)
+ {
+ /* Icon (variable) */
+ use_cmap = 0;
+ if ((notify_state->icon_info.bpp == 1) || (notify_state->icon_info.bpp == 2) ||
+ (notify_state->icon_info.bpp == 4))
+ {
+ use_cmap = 1;
+ }
+ order_size += 12 + notify_state->icon_info.mask_bytes +
+ notify_state->icon_info.data_bytes;
+ if (use_cmap)
+ {
+ order_size += notify_state->icon_info.cmap_bytes + 2;
+ }
+ }
+ if (field_present_flags & WINDOW_ORDER_CACHED_ICON)
+ {
+ /* CachedIcon (3 bytes) */
+ order_size += 3;
+ }
+
+ xrdp_orders_check(self, order_size);
+ self->order_count++;
+ order_flags = RDP_ORDER_SECONDARY;
+ order_flags |= 0xb << 2; /* type TS_ALTSEC_WINDOW */
+ out_uint8(self->out_s, order_flags);
+ /* orderSize (2 bytes) */
+ out_uint16_le(self->out_s, order_size);
+ /* FieldsPresentFlags (4 bytes) */
+ out_uint32_le(self->out_s, field_present_flags);
+ /* windowId (4 bytes) */
+ out_uint32_le(self->out_s, window_id);
+ /* notifyIconId (4 bytes) */
+ out_uint32_le(self->out_s, notify_id);
+
+ if (field_present_flags & WINDOW_ORDER_FIELD_NOTIFY_VERSION)
+ {
+ /* Version (4 bytes) */
+ out_uint32_le(self->out_s, notify_state->version);
+ }
+ if (field_present_flags & WINDOW_ORDER_FIELD_NOTIFY_TIP)
+ {
+ /* ToolTip (variable) UNICODE_STRING */
+ xrdp_orders_send_as_unicode(self->out_s, notify_state->tool_tip);
+ }
+ if (field_present_flags & WINDOW_ORDER_FIELD_NOTIFY_INFO_TIP)
+ {
+ /* InfoTip (variable) TS_NOTIFY_ICON_INFOTIP */
+ out_uint32_le(self->out_s, notify_state->infotip.timeout);
+ out_uint32_le(self->out_s, notify_state->infotip.flags);
+ xrdp_orders_send_as_unicode(self->out_s, notify_state->infotip.text);
+ xrdp_orders_send_as_unicode(self->out_s, notify_state->infotip.title);
+ }
+ if (field_present_flags & WINDOW_ORDER_FIELD_NOTIFY_STATE)
+ {
+ /* State (4 bytes) */
+ out_uint32_le(self->out_s, notify_state->state);
+ }
+ if (field_present_flags & WINDOW_ORDER_ICON)
+ {
+ /* Icon (variable) */
+ xrdp_orders_send_ts_icon(self->out_s, notify_state->icon_cache_entry,
+ notify_state->icon_cache_id,
+ &notify_state->icon_info);
+ }
+ if (field_present_flags & WINDOW_ORDER_CACHED_ICON)
+ {
+ /* CacheEntry (2 bytes) */
+ out_uint16_le(self->out_s, notify_state->icon_cache_entry);
+ /* CacheId (1 byte) */
+ out_uint8(self->out_s, notify_state->icon_cache_id);
+ }
+
+ return 0;
+}
+
+/*****************************************************************************/
+/* RAIL */
+/* returns error */
+/* used for both Non-Monitored Desktop and Actively Monitored Desktop */
+int APP_CC
+xrdp_orders_send_monitored_desktop(struct xrdp_orders* self,
+ struct rail_monitored_desktop_order* mdo,
+ int flags)
+{
+ int order_size;
+ int order_flags;
+ int field_present_flags;
+ int index;
+
+ order_size = 7;
+ field_present_flags = flags | WINDOW_ORDER_TYPE_DESKTOP;
+
+ if (field_present_flags & WINDOW_ORDER_FIELD_DESKTOP_ACTIVE_WND)
+ {
+ /* ActiveWindowId (4 bytes) */
+ order_size += 4;
+ }
+ if (field_present_flags & WINDOW_ORDER_FIELD_DESKTOP_ZORDER)
+ {
+ /* NumWindowIds (1 byte) */
+ order_size += 1;
+ /* WindowIds (variable) */
+ order_size += mdo->num_window_ids * 4;
+ }
+
+ xrdp_orders_check(self, order_size);
+ self->order_count++;
+ order_flags = RDP_ORDER_SECONDARY;
+ order_flags |= 0xb << 2; /* type TS_ALTSEC_WINDOW */
+ out_uint8(self->out_s, order_flags);
+ /* orderSize (2 bytes) */
+ out_uint16_le(self->out_s, order_size);
+ /* FieldsPresentFlags (4 bytes) */
+ out_uint32_le(self->out_s, field_present_flags);
+
+ if (field_present_flags & WINDOW_ORDER_FIELD_DESKTOP_ACTIVE_WND)
+ {
+ /* ActiveWindowId (4 bytes) */
+ out_uint32_le(self->out_s, mdo->active_window_id);
+ }
+ if (field_present_flags & WINDOW_ORDER_FIELD_DESKTOP_ZORDER)
+ {
+ /* NumWindowIds (1 byte) */
+ out_uint8(self->out_s, mdo->num_window_ids);
+ /* WindowIds (variable) */
+ for (index = 0; index < mdo->num_window_ids; index++)
+ {
+ out_uint32_le(self->out_s, mdo->window_ids[index]);
+ }
+ }
+
+ return 0;
+}
diff --git a/libxrdp/xrdp_orders_rail.h b/libxrdp/xrdp_orders_rail.h
new file mode 100644
index 00000000..8f5b402f
--- /dev/null
+++ b/libxrdp/xrdp_orders_rail.h
@@ -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
diff --git a/libxrdp/xrdp_rdp.c b/libxrdp/xrdp_rdp.c
index fd163308..ba777092 100644
--- a/libxrdp/xrdp_rdp.c
+++ b/libxrdp/xrdp_rdp.c
@@ -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);
@@ -826,6 +865,49 @@ xrdp_process_offscreen_bmpcache(struct xrdp_rdp* self, struct stream* s,
}
/*****************************************************************************/
+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;
diff --git a/libxrdp/xrdp_sec.c b/libxrdp/xrdp_sec.c
index 952ff12f..381e8435 100644
--- a/libxrdp/xrdp_sec.c
+++ b/libxrdp/xrdp_sec.c
@@ -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);
diff --git a/rdp/rdp_sec.c b/rdp/rdp_sec.c
index e57c188d..5efab76e 100644
--- a/rdp/rdp_sec.c
+++ b/rdp/rdp_sec.c
@@ -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;
diff --git a/sesman/chansrv/chansrv.c b/sesman/chansrv/chansrv.c
index 1abeeca6..41176752 100644
--- a/sesman/chansrv/chansrv.c
+++ b/sesman/chansrv/chansrv.c
@@ -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);
diff --git a/sesman/libscp/libscp_session.c b/sesman/libscp/libscp_session.c
index 244f188a..3ed5070a 100644
--- a/sesman/libscp/libscp_session.c
+++ b/sesman/libscp/libscp_session.c
@@ -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);
diff --git a/sesman/libscp/libscp_types.h b/sesman/libscp/libscp_types.h
index 7a54545a..e6521741 100644
--- a/sesman/libscp/libscp_types.h
+++ b/sesman/libscp/libscp_types.h
@@ -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
diff --git a/sesman/libscp/libscp_v0.c b/sesman/libscp/libscp_v0.c
index 69dd4afa..f92383d4 100644
--- a/sesman/libscp/libscp_v0.c
+++ b/sesman/libscp/libscp_v0.c
@@ -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;
+}
diff --git a/sesman/libscp/libscp_v0.h b/sesman/libscp/libscp_v0.h
index 7c6fd4b2..92b835f0 100644
--- a/sesman/libscp/libscp_v0.h
+++ b/sesman/libscp/libscp_v0.h
@@ -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
diff --git a/sesman/scp_v0.c b/sesman/scp_v0.c
index e36aeaf6..b4e1a845 100644
--- a/sesman/scp_v0.c
+++ b/sesman/scp_v0.c
@@ -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)
diff --git a/xrdp/xrdp.c b/xrdp/xrdp.c
index 8fbbd8f7..ec019222 100644
--- a/xrdp/xrdp.c
+++ b/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);
diff --git a/xrdp/xrdp.h b/xrdp/xrdp.h
index 0bc4a24d..5ce2ee9b 100644
--- a/xrdp/xrdp.h
+++ b/xrdp/xrdp.h
@@ -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);
diff --git a/xrdp/xrdp.ini b/xrdp/xrdp.ini
index 7cab7000..47e93c99 100644
--- a/xrdp/xrdp.ini
+++ b/xrdp/xrdp.ini
@@ -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
diff --git a/xrdp/xrdp_listen.c b/xrdp/xrdp_listen.c
index 312ae5e4..c24a2e76 100644
--- a/xrdp/xrdp_listen.c
+++ b/xrdp/xrdp_listen.c
@@ -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 */
{
diff --git a/xrdp/xrdp_login_wnd.c b/xrdp/xrdp_login_wnd.c
index 0ea45b0e..69d3721f 100644
--- a/xrdp/xrdp_login_wnd.c
+++ b/xrdp/xrdp_login_wnd.c
@@ -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
diff --git a/xrdp/xrdp_mm.c b/xrdp/xrdp_mm.c
index ec19e008..8dfac0b9 100644
--- a/xrdp/xrdp_mm.c
+++ b/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);
}
/*****************************************************************************/
diff --git a/xrdp/xrdp_process.c b/xrdp/xrdp_process.c
index df69d057..7a88d524 100644
--- a/xrdp/xrdp_process.c
+++ b/xrdp/xrdp_process.c
@@ -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)
{
diff --git a/xrdp/xrdp_types.h b/xrdp/xrdp_types.h
index 0366fd83..059a0c83 100644
--- a/xrdp/xrdp_types.h
+++ b/xrdp/xrdp_types.h
@@ -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 */
diff --git a/xrdp/xrdp_wm.c b/xrdp/xrdp_wm.c
index 3f9d3c6e..7883d33e 100644
--- a/xrdp/xrdp_wm.c
+++ b/xrdp/xrdp_wm.c
@@ -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,
+ if (self->mm->usechansrv)
+ {
+ rv = xrdp_mm_process_channel_data(self->mm, param1, param2,
param3, param4);
- }
- else
- {
- if (self->mm->mod->mod_event != 0)
+ }
+ else
{
- rv = self->mm->mod->mod_event(self->mm->mod, 0x5555, param1, param2,
+ 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;
diff --git a/xrdp/xrdpwin.c b/xrdp/xrdpwin.c
index d2c2d0f3..849f7112 100644
--- a/xrdp/xrdpwin.c
+++ b/xrdp/xrdpwin.c
@@ -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)