summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--common/os_calls.c21
-rw-r--r--common/os_calls.h1
-rw-r--r--docs/man/sesman.ini.525
-rw-r--r--sesman/config.c43
-rw-r--r--sesman/config.h28
-rw-r--r--sesman/scp_v0.c2
-rw-r--r--sesman/sesman.ini30
-rw-r--r--sesman/session.c59
-rw-r--r--sesman/session.h4
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
@@ -2266,6 +2266,27 @@ g_strncmp(const char *c1, const char *c2, int 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 <User,BitPerPixel> when using Xrdp, and
+for the combination <User,BitPerPixel,DisplaySize> when using Xvnc.
+This behaviour can be changed by setting session policy to:
+.br
+
+.br
+\fBUBD\fR - session per <User,BitPerPixel,DisplaySize>
+.br
+\fBUBI\fR - session per <User,BitPerPixel,IPAddr>
+.br
+\fBUBC\fR - session per <User,BitPerPixel,Connection>
+.br
+\fBUBDI\fR - session per <User,BitPerPixel,DisplaySize,IPAddr>
+.br
+\fBUBDC\fR - session per <User,BitPerPixel,DisplaySize,Connection>
+.br
+
+.br
+Note that the criteria <User,BitPerPixel> can not be turned off
+and <DisplaySize> 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:<User,BitPerPixel> and Xvnc:<User,BitPerPixel,DisplaySize>
+# "UBD" session per <User,BitPerPixel,DisplaySize>
+# "UBI" session per <User,BitPerPixel,IPAddr>
+# "UBC" session per <User,BitPerPixel,Connection>
+# "UBDI" session per <User,BitPerPixel,DisplaySize,IPAddr>
+# "UBDC" session per <User,BitPerPixel,DisplaySize,Connection>
+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
/**