From 1934c9ea00cb4cb35a2561273c8df8339c8023a1 Mon Sep 17 00:00:00 2001 From: Jay Sorg Date: Sun, 20 Apr 2014 00:42:19 -0700 Subject: [PATCH] sesman: more options for session lookup from Fredy Paquet --- common/os_calls.c | 21 +++++++++++++++ common/os_calls.h | 1 + docs/man/sesman.ini.5 | 25 ++++++++++++++++++ sesman/config.c | 43 ++++++++++++++++++++++++++++--- sesman/config.h | 28 ++++++++++++++++++++ sesman/scp_v0.c | 2 +- sesman/sesman.ini | 30 ++++++++++++++++++++++ sesman/session.c | 59 +++++++++++++++++++++++++++++++------------ sesman/session.h | 4 +-- 9 files changed, 190 insertions(+), 23 deletions(-) diff --git a/common/os_calls.c b/common/os_calls.c index 16b89201..1d3a71b1 100644 --- a/common/os_calls.c +++ b/common/os_calls.c @@ -2265,6 +2265,27 @@ g_strncmp(const char *c1, const char *c2, int len) return strncmp(c1, c2, len); } +/*****************************************************************************/ +/* compare up to delim */ +int APP_CC +g_strncmp_d(const char *s1, const char *s2, const char delim, int n) +{ + char c1; + char c2; + + while (n > 0) + { + c1 = *s1++; + c2 = *s2++; + if ((c1 == 0) || (c1 != c2) || (c1 == delim) || (c2 == delim)) + { + return c1 - c2; + } + n--; + } + return c1 - c2; +} + /*****************************************************************************/ int APP_CC g_strcasecmp(const char *c1, const char *c2) diff --git a/common/os_calls.h b/common/os_calls.h index 3afde05c..1805a6a1 100644 --- a/common/os_calls.h +++ b/common/os_calls.h @@ -115,6 +115,7 @@ 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 g_strncmp(const char* c1, const char* c2, int len); +int APP_CC g_strncmp_d(const char* c1, const char* c2, const char delim, int len); int APP_CC g_strcasecmp(const char* c1, const char* c2); int APP_CC g_strncasecmp(const char* c1, const char* c2, int len); int APP_CC g_atoi(const char* str); diff --git a/docs/man/sesman.ini.5 b/docs/man/sesman.ini.5 index 84beafb4..a1ba3a50 100644 --- a/docs/man/sesman.ini.5 +++ b/docs/man/sesman.ini.5 @@ -116,6 +116,31 @@ Sets the time(in seconds) limit before a disconnected session is killed. If set to \fI0\fR, automatic killing is disabled. .br +.TP +\fBPolicy\fR=\fI[Default|UBD|UBI|UBC|UBDI|UBDC]\fR +Session allocation policy. By Default, a new session is created +for the combination when using Xrdp, and +for the combination when using Xvnc. +This behaviour can be changed by setting session policy to: +.br + +.br +\fBUBD\fR - session per +.br +\fBUBI\fR - session per +.br +\fBUBC\fR - session per +.br +\fBUBDI\fR - session per +.br +\fBUBDC\fR - session per +.br + +.br +Note that the criteria can not be turned off +and will always be checkt when for Xvnc connections. +.br + .SH "SECURITY" The following parameters can be used in the \fB[Sessions]\fR section: diff --git a/sesman/config.c b/sesman/config.c index 897164af..8fa6e86a 100644 --- a/sesman/config.c +++ b/sesman/config.c @@ -337,6 +337,7 @@ config_read_sessions(int file, struct config_sessions *se, struct list *param_n, se->max_idle_time = 0; se->max_disc_time = 0; se->kill_disconnected = 0; + se->policy = SESMAN_CFG_SESS_POLICY_DFLT; file_read_section(file, SESMAN_CFG_SESSIONS, param_n, param_v); @@ -368,15 +369,49 @@ config_read_sessions(int file, struct config_sessions *se, struct list *param_n, { se->max_disc_time = g_atoi((char *)list_get_item(param_v, i)); } + + if (0 == g_strcasecmp(buf, SESMAN_CFG_SESS_POLICY_S)) + { + char *value = (char *)list_get_item(param_v, i); + if (0 == g_strcasecmp(value, SESMAN_CFG_SESS_POLICY_DFLT_S)) + { + se->policy = SESMAN_CFG_SESS_POLICY_DFLT; + } + else if (0 == g_strcasecmp(value, SESMAN_CFG_SESS_POLICY_UBD_S)) + { + se->policy = SESMAN_CFG_SESS_POLICY_UBD; + } + else if (0 == g_strcasecmp(value, SESMAN_CFG_SESS_POLICY_UBI_S)) + { + se->policy = SESMAN_CFG_SESS_POLICY_UBI; + } + else if (0 == g_strcasecmp(value, SESMAN_CFG_SESS_POLICY_UBC_S)) + { + se->policy = SESMAN_CFG_SESS_POLICY_UBC; + } + else if (0 == g_strcasecmp(value, SESMAN_CFG_SESS_POLICY_UBDI_S)) + { + se->policy = SESMAN_CFG_SESS_POLICY_UBDI; + } + else if (0 == g_strcasecmp(value, SESMAN_CFG_SESS_POLICY_UBDC_S)) + { + se->policy = SESMAN_CFG_SESS_POLICY_UBDC; + } + else /* silently ignore typos */ + { + se->policy = SESMAN_CFG_SESS_POLICY_DFLT; + } + } } - /* printing security config */ + /* printing session config */ g_printf("session configuration:\r\n"); g_printf("\tMaxSessions: %i\r\n", se->max_sessions); g_printf("\tX11DisplayOffset: %i\r\n", se->x11_display_offset); g_printf("\tKillDisconnected: %i\r\n", se->kill_disconnected); g_printf("\tIdleTimeLimit: %i\r\n", se->max_idle_time); g_printf("\tDisconnectedTimeLimit: %i\r\n", se->max_idle_time); + g_printf("\tPolicy: %i\r\n", se->policy); return 0; } @@ -413,7 +448,7 @@ config_read_rdp_params(int file, struct config_sesman *cs, struct list *param_n, /******************************************************************************/ int DEFAULT_CC -config_read_xorg_params(int file, struct config_sesman *cs, +config_read_xorg_params(int file, struct config_sesman *cs, struct list *param_n, struct list *param_v) { int i; @@ -427,7 +462,7 @@ config_read_xorg_params(int file, struct config_sesman *cs, for (i = 0; i < param_n->count; i++) { - list_add_item(cs->xorg_params, + list_add_item(cs->xorg_params, (long) g_strdup((char *) list_get_item(param_v, i))); } @@ -436,7 +471,7 @@ config_read_xorg_params(int file, struct config_sesman *cs, for (i = 0; i < cs->xorg_params->count; i++) { - g_printf("\tParameter %02d %s\r\n", + g_printf("\tParameter %02d %s\r\n", i, (char *) list_get_item(cs->xorg_params, i)); } diff --git a/sesman/config.h b/sesman/config.h index a9679e9a..31ac7256 100644 --- a/sesman/config.h +++ b/sesman/config.h @@ -65,6 +65,29 @@ #define SESMAN_CFG_SESS_IDLE_LIMIT "IdleTimeLimit" #define SESMAN_CFG_SESS_DISC_LIMIT "DisconnectedTimeLimit" +#define SESMAN_CFG_SESS_POLICY_S "Policy" +#define SESMAN_CFG_SESS_POLICY_DFLT_S "Default" +#define SESMAN_CFG_SESS_POLICY_UBD_S "UBD" +#define SESMAN_CFG_SESS_POLICY_UBI_S "UBI" +#define SESMAN_CFG_SESS_POLICY_UBC_S "UBC" +#define SESMAN_CFG_SESS_POLICY_UBDI_S "UBDI" +#define SESMAN_CFG_SESS_POLICY_UBDC_S "UBDC" + +enum SESMAN_CFG_SESS_POLICY_BITS { + SESMAN_CFG_SESS_POLICY_D = 0x01, + SESMAN_CFG_SESS_POLICY_I = 0x02, + SESMAN_CFG_SESS_POLICY_C = 0x04 +}; + +enum SESMAN_CFG_SESS_POLICY { + SESMAN_CFG_SESS_POLICY_DFLT = 0, + SESMAN_CFG_SESS_POLICY_UBD = SESMAN_CFG_SESS_POLICY_D, + SESMAN_CFG_SESS_POLICY_UBI = SESMAN_CFG_SESS_POLICY_I, + SESMAN_CFG_SESS_POLICY_UBC = SESMAN_CFG_SESS_POLICY_C, + SESMAN_CFG_SESS_POLICY_UBDI = SESMAN_CFG_SESS_POLICY_D | SESMAN_CFG_SESS_POLICY_I, + SESMAN_CFG_SESS_POLICY_UBDC = SESMAN_CFG_SESS_POLICY_D | SESMAN_CFG_SESS_POLICY_C +}; + /** * * @struct config_security @@ -135,6 +158,11 @@ struct config_sessions * @brief enables automatic killing of disconnected session */ int kill_disconnected; + /** + * @var policy + * @brief session allocation policy + */ + enum SESMAN_CFG_SESS_POLICY policy; }; /** diff --git a/sesman/scp_v0.c b/sesman/scp_v0.c index 9e7d9083..ce528d46 100644 --- a/sesman/scp_v0.c +++ b/sesman/scp_v0.c @@ -74,7 +74,7 @@ scp_v0_process(struct SCP_CONNECTION *c, struct SCP_SESSION *s) else if (data) { s_item = session_get_bydata(s->username, s->width, s->height, - s->bpp, s->type); + s->bpp, s->type, s->client_ip); if (s_item != 0) { diff --git a/sesman/sesman.ini b/sesman/sesman.ini index 1f58203e..4241bd32 100644 --- a/sesman/sesman.ini +++ b/sesman/sesman.ini @@ -15,17 +15,47 @@ TerminalServerAdmins=tsadmins AlwaysGroupCheck = false [Sessions] + +## X11DisplayOffset - x11 display number offset +# Type: integer +# Default: 10 X11DisplayOffset=10 + +## MaxSessions - maximum number of connections to an xrdp server +# Type: integer +# Default: 0 MaxSessions=50 + +## KillDisconnected - kill disconnected sessions +# Type: integer +# Default: 0 # if 1, true, or yes, kill session after 60 seconds KillDisconnected=0 + +## IdleTimeLimit - when to disconnect idle sessions +# Type: integer +# Default: 0 # if not zero, the seconds without mouse or keyboard input before disconnect # not complete yet IdleTimeLimit=0 + +## DisconnectedTimeLimit - when to kill idle sessions +# Type: integer +# Default: 0 # if not zero, the seconds before a disconnected session is killed # min 60 seconds DisconnectedTimeLimit=0 +## Policy - session allocation policy +# Type: enum [ "Default" | "UBD" | "UBI" | "UBC" | "UBDI" | "UBDC" ] +# Default: Xrdp: and Xvnc: +# "UBD" session per +# "UBI" session per +# "UBC" session per +# "UBDI" session per +# "UBDC" session per +Policy=Default + [Logging] LogFile=xrdp-sesman.log LogLevel=DEBUG diff --git a/sesman/session.c b/sesman/session.c index 6b50560f..b68ed3f4 100644 --- a/sesman/session.c +++ b/sesman/session.c @@ -90,9 +90,10 @@ dumpItemsToString(struct list *self, char *outstr, int len) /******************************************************************************/ struct session_item *DEFAULT_CC -session_get_bydata(char *name, int width, int height, int bpp, int type) +session_get_bydata(char *name, int width, int height, int bpp, int type, char *client_ip) { struct session_chain *tmp; + enum SESMAN_CFG_SESS_POLICY policy = g_cfg->sess.policy; /*THREAD-FIX require chain lock */ lock_chain_acquire(); @@ -104,6 +105,7 @@ session_get_bydata(char *name, int width, int height, int bpp, int type) { case SCP_SESSION_TYPE_XVNC: /* 0 */ type = SESMAN_SESSION_TYPE_XVNC; /* 2 */ + policy |= SESMAN_CFG_SESS_POLICY_D; /* Xvnc cannot resize */ break; case SCP_SESSION_TYPE_XRDP: /* 1 */ type = SESMAN_SESSION_TYPE_XRDP; /* 1 */ @@ -116,14 +118,36 @@ session_get_bydata(char *name, int width, int height, int bpp, int type) return 0; } +#if 0 + log_message(LOG_LEVEL_INFO, + "session_get_bydata: search policy %d U %s W %d H %d bpp %d T %d IP %s", + policy, name, width, height, bpp, type, client_ip); +#endif + while (tmp != 0) { +#if 0 + log_message(LOG_LEVEL_INFO, + "session_get_bydata: try %p U %s W %d H %d bpp %d T %d IP %s", + tmp->item, + tmp->item->name, + tmp->item->width, tmp->item->height, + tmp->item->bpp, tmp->item->type, + tmp->item->client_ip); +#endif + if (type == SESMAN_SESSION_TYPE_XRDP) { /* only name and bpp need to match for X11rdp, it can resize */ if (g_strncmp(name, tmp->item->name, 255) == 0 && - tmp->item->bpp == bpp && - tmp->item->type == type) + (!(policy & SESMAN_CFG_SESS_POLICY_D) || + (tmp->item->width == width && tmp->item->height == height)) && + (!(policy & SESMAN_CFG_SESS_POLICY_I) || + (g_strncmp_d(client_ip, tmp->item->client_ip, ':', 255) == 0)) && + (!(policy & SESMAN_CFG_SESS_POLICY_C) || + (g_strncmp(client_ip, tmp->item->client_ip, 255) == 0)) && + tmp->item->bpp == bpp && + tmp->item->type == type) { /*THREAD-FIX release chain lock */ lock_chain_release(); @@ -132,10 +156,13 @@ session_get_bydata(char *name, int width, int height, int bpp, int type) } if (g_strncmp(name, tmp->item->name, 255) == 0 && - tmp->item->width == width && - tmp->item->height == height && - tmp->item->bpp == bpp && - tmp->item->type == type) + (tmp->item->width == width && tmp->item->height == height) && + (!(policy & SESMAN_CFG_SESS_POLICY_I) || + (g_strncmp_d(client_ip, tmp->item->client_ip, ':', 255) == 0)) && + (!(policy & SESMAN_CFG_SESS_POLICY_C) || + (g_strncmp(client_ip, tmp->item->client_ip, 255) == 0)) && + tmp->item->bpp == bpp && + tmp->item->type == type) { /*THREAD-FIX release chain lock */ lock_chain_release(); @@ -577,11 +604,11 @@ session_start_fork(int width, int height, int bpp, char *username, g_snprintf(text, 255, "%d", g_cfg->sess.kill_disconnected); g_setenv("XRDP_SESMAN_KILL_DISCONNECTED", text, 1); - if (type == SESMAN_SESSION_TYPE_XORG) - { + if (type == SESMAN_SESSION_TYPE_XORG) + { xserver_params = list_create(); xserver_params->auto_free = 1; - + /* these are the must have parameters */ list_add_item(xserver_params, (long) g_strdup("/usr/bin/Xorg")); list_add_item(xserver_params, (long) g_strdup(screen)); @@ -599,18 +626,18 @@ session_start_fork(int width, int height, int bpp, char *username, /* some args are passed via env vars */ g_sprintf(geometry, "%d", width); g_setenv("XRDP_START_WIDTH", geometry, 1); - + g_sprintf(geometry, "%d", height); g_setenv("XRDP_START_HEIGHT", geometry, 1); - - /* fire up Xorg */ + + /* fire up Xorg */ g_execvp("/usr/bin/Xorg", pp1); - } + } else if (type == SESMAN_SESSION_TYPE_XVNC) { xserver_params = list_create(); xserver_params->auto_free = 1; - + /* these are the must have parameters */ list_add_item(xserver_params, (long)g_strdup("Xvnc")); list_add_item(xserver_params, (long)g_strdup(screen)); @@ -636,7 +663,7 @@ session_start_fork(int width, int height, int bpp, char *username, { xserver_params = list_create(); xserver_params->auto_free = 1; - + /* these are the must have parameters */ list_add_item(xserver_params, (long)g_strdup("X11rdp")); list_add_item(xserver_params, (long)g_strdup(screen)); diff --git a/sesman/session.h b/sesman/session.h index 185fa803..05e3b3a9 100644 --- a/sesman/session.h +++ b/sesman/session.h @@ -91,9 +91,9 @@ struct session_chain * */ struct session_item* DEFAULT_CC -session_get_bydata(char* name, int width, int height, int bpp, int type); +session_get_bydata(char* name, int width, int height, int bpp, int type, char *client_ip); #ifndef session_find_item - #define session_find_item(a, b, c, d, e) session_get_bydata(a, b, c, d, e); + #define session_find_item(a, b, c, d, e, f) session_get_bydata(a, b, c, d, e, f); #endif /**