From 0cddb71c7e75520c9d272697b8eb57dbc03ab296 Mon Sep 17 00:00:00 2001 From: Timothy Pearson Date: Wed, 16 May 2012 23:22:23 +0000 Subject: [PATCH] Add preliminary Raptor session management --- Makefile.am | 1 + configure.ac | 1 + raptorsmiface/Makefile.am | 34 ++ raptorsmiface/libraptorsmiface.c | 568 +++++++++++++++++++++++++++++++ raptorsmiface/libraptorsmiface.h | 34 ++ sesman/Makefile.am | 4 +- sesman/chansrv/Makefile.am | 2 + sesman/chansrv/chansrv.c | 41 ++- sesman/sesman.ini | 19 +- sesman/session.c | 53 ++- xrdp/Makefile.am | 4 +- xrdp/xrdp.ini | 67 ---- xrdp/xrdp_mm.c | 41 ++- xrdp/xrdp_types.h | 1 + 14 files changed, 775 insertions(+), 95 deletions(-) create mode 100644 raptorsmiface/Makefile.am create mode 100644 raptorsmiface/libraptorsmiface.c create mode 100644 raptorsmiface/libraptorsmiface.h diff --git a/Makefile.am b/Makefile.am index e8905c98..973da0e2 100644 --- a/Makefile.am +++ b/Makefile.am @@ -14,6 +14,7 @@ endif SUBDIRS = \ common \ + raptorsmiface \ vnc \ rdp \ xup \ diff --git a/configure.ac b/configure.ac index 7f4f5810..2c0810b7 100644 --- a/configure.ac +++ b/configure.ac @@ -174,6 +174,7 @@ localstatedir="/var"; fi AC_CONFIG_FILES([Makefile common/Makefile + raptorsmiface/Makefile vnc/Makefile rdp/Makefile libxrdp/Makefile diff --git a/raptorsmiface/Makefile.am b/raptorsmiface/Makefile.am new file mode 100644 index 00000000..acf3e233 --- /dev/null +++ b/raptorsmiface/Makefile.am @@ -0,0 +1,34 @@ +EXTRA_DIST = libraptorsmiface.h + +EXTRA_DEFINES = +EXTRA_INCLUDES = +EXTRA_LIBS = +EXTRA_FLAGS = + +if GOT_PREFIX +EXTRA_INCLUDES += -I$(prefix)/include +EXTRA_FLAGS += -L$(prefix)/lib -Wl,-rpath -Wl,$(prefix)/lib +endif + +AM_CFLAGS = \ + -DXRDP_CFG_PATH=\"${sysconfdir}/xrdp\" \ + -DXRDP_SBIN_PATH=\"${sbindir}\" \ + -DXRDP_SHARE_PATH=\"${datadir}/xrdp\" \ + -DXRDP_PID_PATH=\"${localstatedir}/run\" \ + $(EXTRA_DEFINES) + +INCLUDES = \ + -I$(top_srcdir)/common \ + $(EXTRA_INCLUDES) + +lib_LTLIBRARIES = \ + libraptorsmiface.la + +libraptorsmiface_la_SOURCES = \ + libraptorsmiface.c + +libraptorsmiface_la_LDFLAGS = \ + $(EXTRA_FLAGS) -lmysqlclient + +libraptorsmiface_la_LIBADD = \ + $(EXTRA_LIBS) diff --git a/raptorsmiface/libraptorsmiface.c b/raptorsmiface/libraptorsmiface.c new file mode 100644 index 00000000..4d3db02c --- /dev/null +++ b/raptorsmiface/libraptorsmiface.c @@ -0,0 +1,568 @@ +// (c) 2012 Timothy Pearson +// (c) 2012 Raptor Engineering +// ALL RIGHTS RESERVED + +#define _GNU_SOURCE + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include + +#include "libraptorsmiface.h" + +MYSQL *conn = 0; + +char *server = "localhost"; +char *user = "remotelab"; +char *password = "rlpass123"; /* set me first */ +char *database = "remotelab_sm"; + +void dprint(const char *fmt, ...) +{ + va_list argp; + va_start(argp, fmt); + +#if 0 + vprintf(fmt, argp); +#else + char debug[1024]; + vsprintf(debug, fmt, argp); + FILE *fp = fopen("/raptorsmiface.debug", "a"); + if (fp != NULL) + { + fputs(debug, fp); + fclose(fp); + } +#endif + + va_end(argp); +} + +void connect_if_needed() { + if (!conn) { + conn = mysql_init(NULL); + if (!mysql_real_connect(conn, server, user, password, database, 0, NULL, 0)) { + dprint("[ERROR] MySQL connection FAILED [%s]\n\r", mysql_error(conn)); + conn = 0; + } + } +} + +char* get_mysql_escaped_string(MYSQL *sqlcn, char* rawstr) { + unsigned int minlen = strlen(rawstr); + unsigned int maxlen = ((minlen*2)+1); + char* escstr = malloc(maxlen*sizeof(char)); + mysql_real_escape_string(sqlcn, escstr, rawstr, minlen); + return escstr; +} + +char* get_group_for_user(char* username) { + struct passwd* pwd; + pwd = getpwnam(username); + if (!pwd) { + return true; + } + gid_t groupid = pwd->pw_gid; + struct group* primarygroup; + primarygroup = getgrgid(groupid); + if (!primarygroup) { + return true; + } + + return strdup(primarygroup->gr_name); +} + +char raptor_sm_deallocate_session(char* username) { + MYSQL_RES *res; + MYSQL_ROW row; + MYSQL_RES *svr_res; + MYSQL_ROW svr_row; + MYSQL_RES *cnt_res; + MYSQL_ROW cnt_row; + char* query; + + connect_if_needed(); + if (!conn) { + return 1; + } + + // Remove the user from the system + char* safe_username = get_mysql_escaped_string(conn, username); + asprintf(&query, "DELETE FROM sessions WHERE username='%s'", safe_username); + free(safe_username); + if (mysql_query(conn, query)) { + // Server error + free(query); + return 2; + } + else { + free(query); + return 0; + } +} + +char* raptor_sm_allocate_session(char* username) { + MYSQL_RES *res; + MYSQL_ROW row; + MYSQL_RES *svr_res; + MYSQL_ROW svr_row; + MYSQL_RES *cnt_res; + MYSQL_ROW cnt_row; + char* query; + + connect_if_needed(); + if (!conn) { + return strdup("SQLERR001"); + } + + // Verify that this user is not already on the system + char* safe_username = get_mysql_escaped_string(conn, username); + asprintf(&query, "SELECT servername FROM sessions WHERE username='%s'", safe_username); + free(safe_username); + if (mysql_query(conn, query)) { + // Server error + free(query); + return strdup("SQLERR002"); + } + else { + free(query); + res = mysql_store_result(conn); + if ((row = mysql_fetch_row(res)) == NULL) { + // User is not on a system + // Find the least utilized node + if (mysql_query(conn, "SELECT name FROM servers")) { + // Server error + mysql_free_result(res); + return strdup("SQLERR003"); + } + else { + svr_res = mysql_store_result(conn); + char* bestserver = strdup(""); + int bestusage = INT_MAX; + while ((svr_row = mysql_fetch_row(svr_res)) != NULL) { + char* safe_servername = get_mysql_escaped_string(conn, svr_row[0]); + asprintf(&query, "SELECT username FROM sessions WHERE servername='%s'", safe_servername); + free(safe_servername); + if (mysql_query(conn, query)) { + // Server error + free(query); + free(bestserver); + mysql_free_result(res); + mysql_free_result(svr_res); + return strdup("SQLERR004"); + } + else { + free(query); + cnt_res = mysql_store_result(conn); + int usagecount = 0; + while ((cnt_row = mysql_fetch_row(cnt_res)) != NULL) { + usagecount++; + } + mysql_free_result(cnt_res); + if (usagecount < bestusage) { + free(bestserver); + bestserver = strdup(svr_row[0]); + bestusage = usagecount; + } + } + } + mysql_free_result(res); + mysql_free_result(svr_res); + + // Insert new information into the sessions database and set status to ALLOCATED + char* safe_servername = get_mysql_escaped_string(conn, bestserver); + char* safe_username = get_mysql_escaped_string(conn, username); + asprintf(&query, "INSERT INTO sessions (username, servername, state) VALUES ('%s', '%s', '%d')", safe_username, safe_servername, SM_STATUS_ALLOCATED); + free(safe_servername); + free(safe_username); + if (mysql_query(conn, query)) { + // Server error + free(query); + return strdup("SQLERR005"); + } + else { + free(query); + return strdup(bestserver); + } + } + } + else { + char* ret = strdup(row[0]); + mysql_free_result(res); + return ret; + } + } +} + +char* raptor_sm_get_ip_for_hostname(char* hostname, char* error) { + struct addrinfo hints, *res; + struct in_addr addr; + int err; + + memset(&hints, 0, sizeof(hints)); + hints.ai_socktype = SOCK_STREAM; + hints.ai_family = AF_INET; + + if ((err = getaddrinfo(hostname, NULL, &hints, &res)) != 0) { + if (error) *error = 1; + return strdup(""); + } + + addr.s_addr = ((struct sockaddr_in *)(res->ai_addr))->sin_addr.s_addr; + + char* ret = strdup(inet_ntoa(addr)); + freeaddrinfo(res); + if (error) *error = 0; + return ret; +} + +char* raptor_sm_get_hostname_for_username(char* username, bool create) { + MYSQL_RES *res; + MYSQL_ROW row; + char* query; + + connect_if_needed(); + if (!conn) { + return strdup("SQLERR100"); + } + + char* safe_username = get_mysql_escaped_string(conn, username); + asprintf(&query, "SELECT servername FROM sessions WHERE username='%s'", safe_username); + free(safe_username); + if (mysql_query(conn, query)) { + // Server error + free(query); + return strdup("SQLERR101"); + } + else { + free(query); + res = mysql_store_result(conn); + while ((row = mysql_fetch_row(res)) != NULL) { + char* ret = strdup(row[0]); + mysql_free_result(res); + return ret; + } + // Nothing in the DB + mysql_free_result(res); + if (create) { + // Try to allocate a new session on a node + return raptor_sm_allocate_session(username); + } + else { + return strdup(""); + } + } +} + +char* raptor_sm_get_ip_for_username(char* username, bool create) { + char* hostname = raptor_sm_get_hostname_for_username(username, create); + char err; + char* ip = raptor_sm_get_ip_for_hostname(hostname, &err); + if (err) { + raptor_sm_deallocate_session(username); + } + free(hostname); + return ip; +} + +bool raptor_sm_sesslimit_reached(char* username) { + MYSQL_RES *res; + MYSQL_ROW row; + char* query; + + connect_if_needed(); + if (!conn) { + return true; + } + + // Respect maximum session number for the group for this user + int sesslimit = 0; // Default to denying all sessions + + // Get group for user + char* groupname = get_group_for_user(username); + char* safe_groupname = get_mysql_escaped_string(conn, groupname); + free(groupname); + asprintf(&query, "SELECT sesslimit FROM groups WHERE groupname='%s'", safe_groupname); + free(safe_groupname); + if (mysql_query(conn, query)) { + // Server error + free(query); + return true; + } + else { + free(query); + res = mysql_store_result(conn); + row = mysql_fetch_row(res); + if (row[0]) { + sesslimit = atoi(row[0]); + } + mysql_free_result(res); + } + + // Figure out how many users are online from this group + int sesscount = 0; + asprintf(&query, "SELECT username FROM sessions WHERE state<>'%d'", SM_STATUS_ALLOCATED); + if (mysql_query(conn, query)) { + // Server error + free(query); + return true; + } + else { + free(query); + res = mysql_store_result(conn); + while ((row = mysql_fetch_row(res)) != NULL) { + if (row[0]) { + char* test_groupname = get_group_for_user(row[0]); + if (strcmp(groupname, test_groupname) == 0) { + sesscount++; + } + free(test_groupname); + } + } + mysql_free_result(res); + + if (sesscount < sesslimit) { + return false; + } + return true; + } + + // We should never end up here! + return true; +} + +pid_t raptor_sm_run_remote_server(char* username, char *const argv[]) { + MYSQL_RES *res; + MYSQL_ROW row; + char* query; + + connect_if_needed(); + if (!conn) { + return -1; + } + + // Respect maximum session number for the group for this user + if (raptor_sm_sesslimit_reached(username)) { + return -5; + } + + // Make sure a server is not already running for this user + // Return the existing PID if it is + char* safe_username = get_mysql_escaped_string(conn, username); + asprintf(&query, "SELECT pid FROM sessions WHERE username='%s' AND state<>'%d'", safe_username, SM_STATUS_ALLOCATED); + free(safe_username); + if (mysql_query(conn, query)) { + // Server error + free(query); + return -2; + } + else { + free(query); + res = mysql_store_result(conn); + while ((row = mysql_fetch_row(res)) != NULL) { + if (row[0]) { + int ret = atoi(row[0]); + if (ret >= 0) { + mysql_free_result(res); + return ret; + } + } + } + mysql_free_result(res); + } + + int i; + int n_commands; + + n_commands = 0; + while (argv[n_commands] != NULL) { + n_commands++; + } + + char* ipaddr = raptor_sm_get_ip_for_username(username, true); + + // This is HORRIBLY inefficient + char* command_string = strdup(""); + for (i=0; i + +#include + +typedef unsigned char bool; +#define true 1 +#define false 0 + +// SM_STATUS_ALLOCATED: Server is not yet started +// SM_STATUS_RUNNING: Server is up, but client is not connected +// SM_STATUS_CONNECTED: Server is up and client is connected +enum raptor_sm_status { + SM_STATUS_ALLOCATED, + SM_STATUS_RUNNING, + SM_STATUS_CONNECTED, + SM_STATUS_FORCEKILL +}; + +char* raptor_sm_get_ip_for_hostname(char* hostname, char* err); +char* raptor_sm_get_hostname_for_username(char* username, bool create); + +char* raptor_sm_get_ip_for_username(char* username, bool create); +pid_t raptor_sm_run_remote_server(char* username, char *const argv[]); +char* raptor_sm_server_started(char* username, pid_t pid, int display); +int raptor_sm_get_display_for_username(char* username); +void raptor_sm_wait_for_pid_exit(char* username, pid_t pid); +void raptor_sm_session_terminated(char* username); +int raptor_sm_get_new_unique_display(int mindisplay, int maxdisplay); +bool raptor_sm_sesslimit_reached(char* username); +char raptor_sm_set_session_state(int display, int state); \ No newline at end of file diff --git a/sesman/Makefile.am b/sesman/Makefile.am index e4b63eb4..ecfbf3bc 100644 --- a/sesman/Makefile.am +++ b/sesman/Makefile.am @@ -8,7 +8,8 @@ AM_CFLAGS = \ INCLUDES = \ -I$(top_srcdir)/common \ - -I$(top_srcdir)/sesman/libscp + -I$(top_srcdir)/sesman/libscp \ + -I$(top_srcdir)/raptorsmiface if SESMAN_NOPAM AUTH_C = verify_user.c @@ -49,6 +50,7 @@ xrdp_sesman_SOURCES = \ xrdp_sesman_LDADD = \ $(top_builddir)/common/libcommon.la \ $(top_builddir)/sesman/libscp/libscp.la \ + $(top_builddir)/raptorsmiface/libraptorsmiface.la \ $(AUTH_LIB) \ -lpthread diff --git a/sesman/chansrv/Makefile.am b/sesman/chansrv/Makefile.am index 9aa3ebe7..f83a7ab2 100644 --- a/sesman/chansrv/Makefile.am +++ b/sesman/chansrv/Makefile.am @@ -40,6 +40,7 @@ AM_CFLAGS = \ INCLUDES = \ -I$(top_srcdir)/common \ + -I$(top_srcdir)/raptorsmiface $(EXTRA_INCLUDES) sbin_PROGRAMS = \ @@ -66,5 +67,6 @@ xrdp_chansrv_LDFLAGS = \ xrdp_chansrv_LDADD = \ -L/usr/X11R6/lib \ $(top_builddir)/common/libcommon.la \ + $(top_builddir)/raptorsmiface/libraptorsmiface.la \ -lX11 -lXfixes -lXrandr \ $(EXTRA_LIBS) diff --git a/sesman/chansrv/chansrv.c b/sesman/chansrv/chansrv.c index a89957ba..45dc0bba 100644 --- a/sesman/chansrv/chansrv.c +++ b/sesman/chansrv/chansrv.c @@ -35,6 +35,8 @@ #include "chansrv_fuse.h" #include "drdynvc.h" +#include "libraptorsmiface.h" + static struct trans *g_lis_trans = 0; static struct trans *g_con_trans = 0; static struct trans *g_api_lis_trans = 0; @@ -221,6 +223,32 @@ g_is_term(void) return g_is_wait_obj_set(g_term_event); } +#if 0 +#include +#include +#include +void dprint(const char *fmt, ...) +{ + va_list argp; + va_start(argp, fmt); + char debug[1024]; + vsprintf(debug, fmt, argp); + FILE *fp = fopen("/chansrv.debug", "a"); + if (fp != NULL) + { + fputs(debug, fp); + fclose(fp); + } + va_end(argp); +} +#undef LOG +#define LOG(_a, _params) \ +{ \ + dprint _params; \ + dprint("\n"); \ +} +#endif + /*****************************************************************************/ /* add data to chan_item, on its way to the client */ /* returns error */ @@ -468,8 +496,14 @@ send_channel_data_response_message(void) static int APP_CC process_message_init(struct stream *s) { + int rv = 0; LOGM((LOG_LEVEL_DEBUG, "process_message_init:")); - return send_init_response_message(); + rv = send_init_response_message(); + if (!rv) + { + raptor_sm_set_session_state(g_display_num, SM_STATUS_CONNECTED); + } + return rv; } /*****************************************************************************/ @@ -1119,6 +1153,9 @@ channel_thread_loop(void *in_val) /* delete g_con_trans */ trans_delete(g_con_trans); g_con_trans = 0; + // Use the display number to mark session disconnected in the Raptor session management database + raptor_sm_set_session_state(g_display_num, SM_STATUS_RUNNING); + exit(0); // RAPTOR session management /* create new listener */ error = setup_listen(); @@ -1543,6 +1580,8 @@ main(int argc, char **argv) } } + // Use the display number to mark session disconnected in the Raptor session management database + raptor_sm_set_session_state(g_display_num, SM_STATUS_RUNNING); /* cleanup */ main_cleanup(); LOGM((LOG_LEVEL_INFO, "main: app exiting pid %d(0x%8.8x)", pid, pid)); diff --git a/sesman/sesman.ini b/sesman/sesman.ini index a58af383..bfd9506b 100644 --- a/sesman/sesman.ini +++ b/sesman/sesman.ini @@ -20,16 +20,7 @@ AlwaysGroupCheck = false # 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 +MaxSessions=1000000 KillDisconnected=0 ## IdleTimeLimit - when to disconnect idle sessions @@ -62,12 +53,18 @@ LogLevel=DEBUG EnableSyslog=1 SyslogLevel=DEBUG +#[X11rdp] +#param1=-bs +#param2=-ac +#param3=-nolisten +#param4=tcp +#param5=-uds + [X11rdp] param1=-bs param2=-ac param3=-nolisten param4=tcp -param5=-uds [Xvnc] param1=-bs diff --git a/sesman/session.c b/sesman/session.c index 091ce013..505817d9 100644 --- a/sesman/session.c +++ b/sesman/session.c @@ -30,6 +30,8 @@ #include //#include +#include "libraptorsmiface.h" + extern tbus g_sync_event; extern unsigned char g_fixedkey[8]; extern struct config_sesman *g_cfg; /* in sesman.c */ @@ -467,7 +469,21 @@ session_start_fork(int width, int height, int bpp, char *username, return 0; } - display = session_get_aval_display_from_chain(); + char session_was_already_running = 0; + int allocdisplay = raptor_sm_get_display_for_username(username); + if (allocdisplay >= 0) { + session_was_already_running = 1; + display = allocdisplay; + } + else { + int allocdisplay = raptor_sm_get_new_unique_display(g_cfg->sess.x11_display_offset, g_cfg->sess.max_sessions); + if (allocdisplay < 0) { + display = 0; + } + else { + display = allocdisplay; + } + } if (display == 0) { @@ -502,6 +518,12 @@ session_start_fork(int width, int height, int bpp, char *username, } else if (pampid == 0) /* child: X11/client */ { + env_set_user(username, 0, display, + g_cfg->session_variables1, + g_cfg->session_variables2); + if (session_was_already_running) { + g_exit(0); + } env_set_user(username, 0, display, g_cfg->session_variables1, g_cfg->session_variables2); @@ -676,6 +698,8 @@ session_start_fork(int width, int height, int bpp, char *username, list_add_item(xserver_params, (long)g_strdup(geometry)); list_add_item(xserver_params, (long)g_strdup("-depth")); list_add_item(xserver_params, (long)g_strdup(depth)); + list_add_item(xserver_params, (long)g_strdup("-reset")); + list_add_item(xserver_params, (long)g_strdup("-terminate")); /* additional parameters from sesman.ini file */ //config_read_xserver_params(SESMAN_SESSION_TYPE_XRDP, @@ -685,8 +709,31 @@ session_start_fork(int width, int height, int bpp, char *username, /* make sure it ends with a zero */ list_add_item(xserver_params, 0); pp1 = (char **)xserver_params->items; - log_message(LOG_LEVEL_INFO, "%s", dumpItemsToString(xserver_params, execvpparams, 2048)); - g_execvp("X11rdp", pp1); + log_message(LOG_LEVEL_INFO, "X11rdp start:%s", dumpItemsToString(xserver_params, execvpparams, 2048)); + + pid_t serverpid; + serverpid = raptor_sm_run_remote_server(username, pp1); + + if (serverpid >= 0) { + if (!session_was_already_running) { + char *friendlyscreen = g_strdup(screen); + friendlyscreen[0] = ' '; + raptor_sm_server_started(username, serverpid, atoi(friendlyscreen)); + g_free(friendlyscreen); + + // Wait for PID exit and remove information from the session database + raptor_sm_wait_for_pid_exit(username, serverpid); + raptor_sm_session_terminated(username); + } + } + else { + raptor_sm_session_terminated(username); + log_message(&(g_cfg->log), LOG_LEVEL_ALWAYS, "max concurrent session limit " + "exceeded in group. login for user %s denied", username); + g_exit(1); + } + + g_exit(0); } else { diff --git a/xrdp/Makefile.am b/xrdp/Makefile.am index 050cde77..32172831 100644 --- a/xrdp/Makefile.am +++ b/xrdp/Makefile.am @@ -27,6 +27,7 @@ INCLUDES = \ -I$(top_builddir) \ -I$(top_srcdir)/common \ -I$(top_srcdir)/libxrdp \ + -I$(top_srcdir)/raptorsmiface \ $(EXTRA_INCLUDES) sbin_PROGRAMS = \ @@ -50,7 +51,8 @@ xrdp_SOURCES = \ xrdp_LDADD = \ $(top_builddir)/common/libcommon.la \ - $(top_builddir)/libxrdp/libxrdp.la + $(top_builddir)/libxrdp/libxrdp.la \ + $(top_builddir)/raptorsmiface/libraptorsmiface.la xrdp_LDFLAGS = \ $(EXTRA_FLAGS) diff --git a/xrdp/xrdp.ini b/xrdp/xrdp.ini index 12387ce3..18678f9f 100644 --- a/xrdp/xrdp.ini +++ b/xrdp/xrdp.ini @@ -133,70 +133,3 @@ ip=127.0.0.1 port=-1 xserverbpp=24 code=10 - -[xrdp2] -name=sesman-Xvnc -lib=libvnc.so -username=ask -password=ask -ip=127.0.0.1 -port=-1 - -[xrdp3] -name=console -lib=libvnc.so -ip=127.0.0.1 -port=5900 -username=na -password=ask - -[xrdp4] -name=vnc-any -lib=libvnc.so -ip=ask -port=ask5900 -username=na -password=ask -#pamusername=asksame -#pampassword=asksame -#pamsessionmng=127.0.0.1 - -[xrdp5] -name=sesman-any -lib=libvnc.so -ip=ask -port=-1 -username=ask -password=ask - -[xrdp6] -name=rdp-any -lib=librdp.so -ip=ask -port=ask3389 - -[xrdp7] -name=neutrinordp-any -lib=libxrdpneutrinordp.so -ip=ask -port=ask3389 -username=ask -password=ask - -[Session manager] -name=Session manager -lib=libxup.so -username=ask -password=ask -ip=127.0.0.1 -port=-1 -xserverbpp=24 -code=20 - -# You can override the common channel settings for each session type -#channel.rdpdr=true -#channel.rdpsnd=true -#channel.drdynvc=true -#channel.cliprdr=true -#channel.rail=true -#channel.xrdpvr=true diff --git a/xrdp/xrdp_mm.c b/xrdp/xrdp_mm.c index 1054ba2e..a1f99ab9 100644 --- a/xrdp/xrdp_mm.c +++ b/xrdp/xrdp_mm.c @@ -30,6 +30,8 @@ #include "xrdp_encoder.h" +#include "libraptorsmiface.h" + #define LLOG_LEVEL 1 #define LLOGLN(_level, _args) \ do \ @@ -54,6 +56,7 @@ xrdp_mm_create(struct xrdp_wm *owner) self->login_names->auto_free = 1; self->login_values = list_create(); self->login_values->auto_free = 1; + self->login_username = 0; LLOGLN(10, ("xrdp_mm_create: bpp %d", self->wm->client_info->bpp)); /* go into jpeg codec mode if jpeg set, lan set */ @@ -192,6 +195,7 @@ xrdp_mm_send_login(struct xrdp_mm *self) if (g_strcasecmp(name, "username") == 0) { username = value; + self->login_username = g_strdup(username); } else if (g_strcasecmp(name, "password") == 0) { @@ -515,16 +519,30 @@ xrdp_mm_setup_mod2(struct xrdp_mm *self) } else if (self->code == 10 || self->code == 20) /* X11rdp/Xorg */ { - use_uds = 1; - - if (xrdp_mm_get_value(self, "ip", text, 255) == 0) - { - if (g_strcmp(text, "127.0.0.1") != 0) - { - use_uds = 0; - } + char* rsmip = raptor_sm_get_ip_for_username(self->login_username, true); + int allocdisplay = raptor_sm_get_display_for_username(self->login_username); + if ((raptor_sm_sesslimit_reached(self->login_username)) && (allocdisplay < 0)) { + g_snprintf(text, 255, "[LICENSE] Maximum concurrent session"); + xrdp_wm_log_msg(self->wm, text); + g_snprintf(text, 255, "[LICENSE] limit exceeded for group."); + xrdp_wm_log_msg(self->wm, text); + g_snprintf(text, 255, "[LICENSE] Login for user %s denied.", self->login_username); + xrdp_wm_log_msg(self->wm, text); + raptor_sm_session_terminated(self->login_username); + return 1; + } + else { + if (allocdisplay >= 0) { + self->display = allocdisplay; + } + self->mod->mod_set_param(self->mod, "ip", rsmip); + use_uds = 1; + if (g_strcmp(rsmip, "127.0.0.1") != 0) { + use_uds = 0; + } } + g_free(rsmip); if (use_uds) { g_snprintf(text, 255, "/tmp/.xrdp/xrdp_display_%d", self->display); @@ -566,7 +584,9 @@ xrdp_mm_setup_mod2(struct xrdp_mm *self) { name = (char *)list_get_item(self->login_names, i); value = (char *)list_get_item(self->login_values, i); - self->mod->mod_set_param(self->mod, name, value); + if (strcmp(name, "ip") != 0) { + self->mod->mod_set_param(self->mod, name, value); + } } /* connect */ @@ -1196,8 +1216,7 @@ xrdp_mm_process_login_response(struct xrdp_mm *self, struct stream *s) if (ok) { self->display = display; - g_snprintf(text, 255, "xrdp_mm_process_login_response: login successful " - "for display %d", display); + g_snprintf(text, 255, "login successful on display %d", display); xrdp_wm_log_msg(self->wm, text); if (xrdp_mm_setup_mod1(self) == 0) diff --git a/xrdp/xrdp_types.h b/xrdp/xrdp_types.h index 973b64e8..e68dc6a0 100644 --- a/xrdp/xrdp_types.h +++ b/xrdp/xrdp_types.h @@ -289,6 +289,7 @@ struct xrdp_mm int chan_trans_up; /* true once connected to chansrv */ int delete_chan_trans; /* boolean set when done with channel connection */ int usechansrv; /* true if chansrvport is set in xrdp.ini or using sesman */ + char* login_username; /* for codec mode operations */ int in_codec_mode;