diff options
-rw-r--r-- | xrdp/xrdp.h | 2 | ||||
-rw-r--r-- | xrdp/xrdp.ini | 9 | ||||
-rw-r--r-- | xrdp/xrdp_login_wnd.c | 4 | ||||
-rw-r--r-- | xrdp/xrdp_mm.c | 164 | ||||
-rw-r--r-- | xrdp/xrdp_types.h | 5 | ||||
-rw-r--r-- | xrdp/xrdp_wm.c | 22 |
6 files changed, 192 insertions, 14 deletions
diff --git a/xrdp/xrdp.h b/xrdp/xrdp.h index 2ef81659..5ce2ee9b 100644 --- a/xrdp/xrdp.h +++ b/xrdp/xrdp.h @@ -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 20b2be3f..0bf1350c 100644 --- a/xrdp/xrdp.ini +++ b/xrdp/xrdp.ini @@ -32,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 diff --git a/xrdp/xrdp_login_wnd.c b/xrdp/xrdp_login_wnd.c index 0ea45b0e..d10094a0 100644 --- a/xrdp/xrdp_login_wnd.c +++ b/xrdp/xrdp_login_wnd.c @@ -411,7 +411,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 4060fd86..e25567fa 100644 --- a/xrdp/xrdp_mm.c +++ b/xrdp/xrdp_mm.c @@ -1552,9 +1552,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) { @@ -1593,12 +1742,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_types.h b/xrdp/xrdp_types.h index 1e833d16..059a0c83 100644 --- a/xrdp/xrdp_types.h +++ b/xrdp/xrdp_types.h @@ -22,6 +22,9 @@ #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 { @@ -288,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 c486f67b..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); + } } } } |