From ffeda4fd0cf7e6c548da8d273c8a1b4b02ec98f3 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 | 29 ++ 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 | 21 +- sesman/session.c | 54 ++- xrdp/Makefile.am | 2 + xrdp/xrdp.ini | 71 ---- xrdp/xrdp_mm.c | 41 ++- xrdp/xrdp_types.h | 1 + 14 files changed, 769 insertions(+), 101 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 84a6eb47..7f1b95de 100644 --- a/Makefile.am +++ b/Makefile.am @@ -18,6 +18,7 @@ endif SUBDIRS = \ common \ + raptorsmiface \ vnc \ rdp \ xup \ diff --git a/configure.ac b/configure.ac index ac1d0ada..209c8da7 100644 --- a/configure.ac +++ b/configure.ac @@ -248,6 +248,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..2ec7442b --- /dev/null +++ b/raptorsmiface/Makefile.am @@ -0,0 +1,29 @@ +EXTRA_DIST = libraptorsmiface.h + +EXTRA_DEFINES = +EXTRA_INCLUDES = +EXTRA_LIBS = +EXTRA_FLAGS = + +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 68dba28e..f6c5930e 100644 --- a/sesman/Makefile.am +++ b/sesman/Makefile.am @@ -4,7 +4,8 @@ AM_CPPFLAGS = \ -DXRDP_SHARE_PATH=\"${datadir}/xrdp\" \ -DXRDP_PID_PATH=\"${localstatedir}/run\" \ -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 @@ -59,6 +60,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 c4cd1a3f..cbe265aa 100644 --- a/sesman/chansrv/Makefile.am +++ b/sesman/chansrv/Makefile.am @@ -25,6 +25,7 @@ AM_CPPFLAGS = \ -DXRDP_PID_PATH=\"${localstatedir}/run\" \ $(EXTRA_DEFINES) \ -I$(top_srcdir)/common \ + -I$(top_srcdir)/raptorsmiface $(EXTRA_INCLUDES) AM_CFLAGS = $(X_CFLAGS) @@ -70,5 +71,6 @@ xrdp_chansrv_LDFLAGS = \ xrdp_chansrv_LDADD = \ $(top_builddir)/common/libcommon.la \ + $(top_builddir)/raptorsmiface/libraptorsmiface.la \ $(X_PRE_LIBS) -lXfixes -lXrandr -lX11 $(X_EXTRA_LIBS) \ $(EXTRA_LIBS) diff --git a/sesman/chansrv/chansrv.c b/sesman/chansrv/chansrv.c index e3d2f5d2..918bb832 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; } /*****************************************************************************/ @@ -1137,6 +1171,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(); @@ -1587,6 +1624,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 3d090076..6b31456f 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 @@ -64,11 +55,11 @@ SyslogLevel=DEBUG [X11rdp] param0=X11rdp -param1=-bs -param2=-ac -param3=-nolisten -param4=tcp -param5=-uds +#param1=-bs +#param2=-ac +#param3=-nolisten +#param4=tcp +#param5=-uds [Xvnc] param0=Xvnc diff --git a/sesman/session.c b/sesman/session.c index 02bb6fa7..250c8baf 100644 --- a/sesman/session.c +++ b/sesman/session.c @@ -32,6 +32,11 @@ #include "sesman.h" #include "libscp_types.h" +#include +//#include + +#include "libraptorsmiface.h" + extern unsigned char g_fixedkey[8]; extern struct config_sesman *g_cfg; /* in sesman.c */ extern int g_sck; /* in sesman.c */ @@ -462,7 +467,21 @@ session_start_fork(int width, int height, int bpp, char *username, return 0; } - display = session_get_avail_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) { @@ -537,6 +556,12 @@ session_start_fork(int width, int height, int bpp, char *username, } else if (pampid == 0) { + 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); @@ -728,6 +753,8 @@ session_start_fork(int width, int height, int bpp, char *username, list_add_item(xserver_params, (tintptr)g_strdup(geometry)); list_add_item(xserver_params, (tintptr)g_strdup("-depth")); list_add_item(xserver_params, (tintptr)g_strdup(depth)); + list_add_item(xserver_params, (tintptr)g_strdup("-reset")); + list_add_item(xserver_params, (tintptr)g_strdup("-terminate")); /* additional parameters from sesman.ini file */ //config_read_xserver_params(SESMAN_SESSION_TYPE_XRDP, @@ -738,7 +765,30 @@ session_start_fork(int width, int height, int bpp, char *username, list_add_item(xserver_params, 0); pp1 = (char **)xserver_params->items; log_message(LOG_LEVEL_INFO, "%s", dumpItemsToString(xserver_params, execvpparams, 2048)); - g_execvp(xserver, pp1); + + 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 67ff4df8..328d379a 100644 --- a/xrdp/Makefile.am +++ b/xrdp/Makefile.am @@ -24,6 +24,7 @@ AM_CPPFLAGS = \ -I$(top_builddir) \ -I$(top_srcdir)/common \ -I$(top_srcdir)/libxrdp \ + -I$(top_srcdir)/raptorsmiface \ $(EXTRA_INCLUDES) sbin_PROGRAMS = \ @@ -51,6 +52,7 @@ xrdp_SOURCES = \ xrdp_LDADD = \ $(top_builddir)/common/libcommon.la \ $(top_builddir)/libxrdp/libxrdp.la \ + $(top_builddir)/raptorsmiface/libraptorsmiface.la \ $(EXTRA_LIBS) xrdp_LDFLAGS = \ diff --git a/xrdp/xrdp.ini b/xrdp/xrdp.ini index 34adb077..9cca9581 100644 --- a/xrdp/xrdp.ini +++ b/xrdp/xrdp.ini @@ -148,74 +148,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 -#delay_ms=2000 - -[xrdp3] -name=console -lib=libvnc.so -ip=127.0.0.1 -port=5900 -username=na -password=ask -#delay_ms=2000 - -[xrdp4] -name=vnc-any -lib=libvnc.so -ip=ask -port=ask5900 -username=na -password=ask -#pamusername=asksame -#pampassword=asksame -#pamsessionmng=127.0.0.1 -#delay_ms=2000 - -[xrdp5] -name=sesman-any -lib=libvnc.so -ip=ask -port=-1 -username=ask -password=ask -#delay_ms=2000 - -[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 94be7e4f..37b51ca3 100644 --- a/xrdp/xrdp_mm.c +++ b/xrdp/xrdp_mm.c @@ -39,6 +39,8 @@ #include "xrdp_encoder.h" +#include "libraptorsmiface.h" + #define LLOG_LEVEL 1 #define LLOGLN(_level, _args) \ do \ @@ -63,6 +65,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(0, ("xrdp_mm_create: bpp %d mcs_connection_type %d " "jpeg_codec_id %d v3_codec_id %d rfx_codec_id %d " @@ -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) { @@ -516,16 +520,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, XRDP_X11RDP_STR, self->display); @@ -567,7 +585,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 */ @@ -1203,8 +1223,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 4590d7a8..83599543 100644 --- a/xrdp/xrdp_types.h +++ b/xrdp/xrdp_types.h @@ -293,6 +293,7 @@ struct xrdp_mm int delete_chan_trans; /* boolean set when done with channel connection */ int usechansrv; /* true if chansrvport is set in xrdp.ini or using sesman */ struct xrdp_encoder *encoder; + char* login_username; }; struct xrdp_key_info