From 153b59ad8447d47d4a241e0f63307b096585172b Mon Sep 17 00:00:00 2001 From: ilsimo Date: Fri, 13 Jan 2006 15:51:23 +0000 Subject: [PATCH] new session list code added support for new [sessions] configuration options --- sesman/access.c | 4 +- sesman/config.c | 69 +++++++++++++- sesman/config.h | 58 ++++++++++-- sesman/sesman.c | 23 ++++- sesman/sesman.ini | 19 ++-- sesman/session.c | 227 +++++++++++++++++++++++++++++++++++++++++++++- sesman/session.h | 75 ++++++++++++++- 7 files changed, 445 insertions(+), 30 deletions(-) diff --git a/sesman/access.c b/sesman/access.c index 594120d6..96750c3f 100644 --- a/sesman/access.c +++ b/sesman/access.c @@ -26,8 +26,6 @@ #include #include #include -//#include -//#include extern struct config_sesman g_cfg; @@ -76,7 +74,7 @@ access_login_allowed(char* user) while (0!=groups->gr_mem[i]) { LOG_DBG("user: %s", groups->gr_mem[i]); - if (0==strcmp(groups->gr_mem[i], user)) return 1; + if (0==g_strcmp(groups->gr_mem[i], user)) return 1; i++; } diff --git a/sesman/config.c b/sesman/config.c index d96bb45a..5dd0d748 100644 --- a/sesman/config.c +++ b/sesman/config.c @@ -74,6 +74,9 @@ config_read(struct config_sesman* cfg) /* read security config */ config_read_security(fd, &(cfg->sec), param_n, param_v); + /* read session config */ + config_read_sessions(fd, &(cfg->sess), param_n, param_v); + /* cleanup */ list_delete(sec); list_delete(param_v); @@ -206,6 +209,7 @@ config_read_security(int file, struct config_security* sc, struct list* param_n, { int i; char* buf; + struct group* g; list_clear(param_v); list_clear(param_n); @@ -225,13 +229,21 @@ config_read_security(int file, struct config_security* sc, struct list* param_n, } if (0 == g_strncasecmp(buf, SESMAN_CFG_SEC_USR_GROUP, 20)) { - sc->ts_users_enable=1; - sc->ts_users=(getgrnam((char*)list_get_item(param_v, i))->gr_gid); + g=getgrnam((char*)list_get_item(param_v, i)); + if (0!=g) + { + sc->ts_users_enable=1; + sc->ts_users=g->gr_gid; + } } if (0 == g_strncasecmp(buf, SESMAN_CFG_SEC_ADM_GROUP, 20)) { - sc->ts_admins_enable=1; - sc->ts_admins=(getgrnam((char*)list_get_item(param_v, i))->gr_gid); + g=getgrnam((char*)list_get_item(param_v, i)); + if (0!=g) + { + sc->ts_admins_enable=1; + sc->ts_admins=g->gr_gid; + } } } @@ -258,3 +270,52 @@ config_read_security(int file, struct config_security* sc, struct list* param_n, return 0; } +/******************************************************************************/ +int DEFAULT_CC +config_read_sessions(int file, struct config_sessions* se, struct list* param_n, + struct list* param_v) +{ + int i; + char* buf; + + list_clear(param_v); + list_clear(param_n); + + /* setting defaults */ + se->max_sessions=0; + se->max_idle_time=0; + se->max_disc_time=0; + se->kill_disconnected=0; + + file_read_section(file, SESMAN_CFG_SESSIONS, param_n, param_v); + for (i = 0; i < param_n->count; i++) + { + buf = (char*)list_get_item(param_n, i); + if (0 == g_strncasecmp(buf, SESMAN_CFG_SESS_MAX, 20)) + { + se->max_sessions = g_atoi((char*)list_get_item(param_v, i)); + } + if (0 == g_strncasecmp(buf, SESMAN_CFG_SESS_KILL_DISC, 20)) + { + se->kill_disconnected = text2bool((char*)list_get_item(param_v, i)); + } + if (0 == g_strncasecmp(buf, SESMAN_CFG_SESS_IDLE_LIMIT, 20)) + { + se->max_idle_time=g_atoi((char*)list_get_item(param_v, i)); + } + if (0 == g_strncasecmp(buf, SESMAN_CFG_SESS_DISC_LIMIT, 20)) + { + se->max_disc_time=g_atoi((char*)list_get_item(param_v, i)); + } + } + + /* printing security config */ + g_printf("session configuration:\r\n"); + g_printf("\tMaxSessions: %i\r\n", se->max_sessions); + 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); + + return 0; +} + diff --git a/sesman/config.h b/sesman/config.h index c73d35da..6f66d579 100644 --- a/sesman/config.h +++ b/sesman/config.h @@ -59,15 +59,12 @@ #define SESMAN_CFG_SESS_MAX "MaxSessions" #define SESMAN_CFG_SESS_KILL_DISC "KillDisconnected" #define SESMAN_CFG_SESS_IDLE_LIMIT "IdleTimeLimit" +#define SESMAN_CFG_SESS_DISC_LIMIT "DisconnectedTimeLimit" /** * - * @struct config_sesman - * @brief \t struct that contains \t sesman configuration - * - * This \t struct contains all of \t sesman configuration parameters\n - * Every parameter in \t [globals] is a member of this struct, other - * sections options are embedded in this \t struct as member structures + * @struct config_security + * @brief \t struct that contains \t sesman access control configuration * */ struct config_security @@ -91,6 +88,36 @@ struct config_security gid_t ts_admins; }; +/** + * + * @struct config_sessions + * @brief \t struct that contains \t sesman session handling configuration + * + */ +struct config_sessions +{ + /** + * @var max_sessions + * @brief maximum number of allowed sessions. 0 for unlimited + */ + int max_sessions; + /** + * @var max_idle_time + * @brief maximum idle time for each session + */ + int max_idle_time; + /** + * @var max_disc_time + * @brief maximum disconnected time for each session + */ + int max_disc_time; + /** + * @var kill_disconnected + * @brief enables automatic killing of disconnected session + */ + int kill_disconnected; +}; + /** * * @struct config_sesman @@ -133,6 +160,11 @@ struct config_sesman * @brief Security configuration options \t struct */ struct config_security sec; + /** + * @var sess + * @brief Session configuration options \t struct + */ + struct config_sessions sess; }; /** @@ -173,7 +205,7 @@ config_read_logging(int file, struct log_config* lc, struct list* param_n, struc /** * - * @brief Reads sesman [iSecurity] configuration section + * @brief Reads sesman [Security] configuration section * * @param cfg pointer to configuration object to be replaced * @@ -183,4 +215,16 @@ config_read_logging(int file, struct log_config* lc, struct list* param_n, struc int DEFAULT_CC config_read_security(int file, struct config_security* sc, struct list* param_n, struct list* param_v); +/** + * + * @brief Reads sesman [Sessions] configuration section + * + * @param cfg pointer to configuration object to be replaced + * + * @return 0 on success, 1 on failure + * + */ +int DEFAULT_CC +config_read_sessions(int file, struct config_sessions* ss, struct list* param_n, struct list* param_v); + #endif diff --git a/sesman/sesman.c b/sesman/sesman.c index 30cbd44f..5fbbdb6f 100644 --- a/sesman/sesman.c +++ b/sesman/sesman.c @@ -32,14 +32,25 @@ int g_sck; int g_pid; unsigned char g_fixedkey[8] = { 23, 82, 107, 6, 35, 78, 88, 7 }; +#ifdef OLDSESSION struct session_item g_session_items[100]; /* sesman.h */ +extern int g_session_count; +#endif struct config_sesman g_cfg; /* config.h */ -/******************************************************************************/ +/** + * + * trigger when a child process (a session) dies + * + * @param s received signal + * + */ static void DEFAULT_CC cterm(int s) { +#ifdef OLDSESSION int i; +#endif int pid; if (g_getpid() != g_pid) @@ -49,13 +60,18 @@ cterm(int s) pid = g_waitchild(); if (pid > 0) { +#ifdef OLDSESSION for (i = 0; i < 100; i++) { if (g_session_items[i].pid == pid) { g_memset(g_session_items + i, 0, sizeof(struct session_item)); + g_session_count--; } } +#else + session_kill(pid); +#endif } } @@ -133,7 +149,8 @@ sesman_main_loop() display = 0; if (data) { - s_item = session_find_item(user, width, height, bpp); + //s_item = session_find_item(user, width, height, bpp); + s_item = session_get_bydata(user, width, height, bpp); if (s_item != 0) { display = s_item->display; @@ -325,7 +342,9 @@ main(int argc, char** argv) } /* signal handling */ +#ifdef OLDSESSION g_memset(&g_session_items, 0, sizeof(g_session_items)); +#endif g_pid = g_getpid(); g_signal(1, sig_sesman_reload_cfg); /* SIGHUP */ g_signal(2, sig_sesman_shutdown); /* SIGINT */ diff --git a/sesman/sesman.ini b/sesman/sesman.ini index 7f98e5e1..4c5f5a18 100644 --- a/sesman/sesman.ini +++ b/sesman/sesman.ini @@ -4,14 +4,19 @@ EnableUserWindowManager=1 UserWindowManager=startwm.sh DefaultWindowManager=startwm.sh +[Security] +AllowRootLogin=1 +TerminalServerUsers=tsusers +TerminalServerAdmins=tsadmins + +[Sessions] +MaxSessions=10 +KillDisconnected=0 +IdleTimeLimit=0 +DisconnectedTimeLimit=0 + [Logging] -LogFile=/usr/local/xrdp/sesman.log +LogFile=./sesman.log LogLevel=DEBUG EnableSyslog=0 SyslogLevel=DEBUG - -[Security] -AllowRootLogin=1 -#TerminalServerUsers=tsusers -#TerminalServerAdmins=tsadmins - diff --git a/sesman/session.c b/sesman/session.c index b02dec69..826e4036 100644 --- a/sesman/session.c +++ b/sesman/session.c @@ -21,16 +21,24 @@ */ +#include + #include "sesman.h" extern unsigned char g_fixedkey[8]; -extern struct session_item g_session_items[100]; /* sesman.h */ extern struct config_sesman g_cfg; /* config.h */ +#ifdef OLDSESSION +extern struct session_item g_session_items[100]; /* sesman.h */ +#else +struct session_chain* g_sessions; +#endif +int g_session_count; /******************************************************************************/ struct session_item* DEFAULT_CC -session_find_item(char* name, int width, int height, int bpp) +session_get_bydata(char* name, int width, int height, int bpp) { +#ifdef OLDSESSION int i; for (i = 0; i < 100; i++) @@ -43,6 +51,27 @@ session_find_item(char* name, int width, int height, int bpp) return g_session_items + i; } } +#else + struct session_chain* tmp; + + /*THREAD-FIX require chain lock */ + tmp=g_sessions; + + while (tmp != 0) + { + if (g_strncmp(name, tmp->item->name, 255) == 0 && + tmp->item->width == width && + tmp->item->height == height && + tmp->item->bpp == bpp) + { + /*THREAD-FIX release chain lock */ + return tmp->item; + } + tmp=tmp->next; + } + + /*THREAD-FIX release chain lock */ +#endif return 0; } @@ -73,10 +102,40 @@ session_start(int width, int height, int bpp, char* username, char* password, char cur_dir[256]; char text[256]; char passwd_file[256]; +#ifndef OLDSESSION + struct session_chain* temp; +#endif + + /*THREAD-FIX lock to control g_session_count*/ + /* check to limit concurrent sessions */ + if (g_session_count >= g_cfg.sess.max_sessions) + { + log_message(LOG_LEVEL_INFO, "max concurrent session limit exceeded. login for user %s denied", username); + return 0; + } + +#ifndef OLDSESSION + temp=malloc(sizeof(struct session_chain)); + if (temp == 0) + { + log_message(LOG_LEVEL_ERROR, "cannot create new chain element - user %s", username); + return 0; + } + temp->item = malloc(sizeof(struct session_item)); + if (temp->item == 0) + { + free(temp); + log_message(LOG_LEVEL_ERROR, "cannot create new session item - user %s", username); + return 0; + } +#endif g_get_current_dir(cur_dir, 255); display = 10; - while (x_server_running(display) && display < 50) + /*while (x_server_running(display) && display < 50)*/ + /* we search for a free display up to max_sessions */ + /* we should need no more displays than this */ + while (x_server_running(display) && (display <= g_cfg.sess.max_sessions)) { display++; } @@ -159,6 +218,7 @@ session_start(int width, int height, int bpp, char* username, char* password, } else /* parent */ { +#ifdef OLDSESSION g_session_items[display].pid = pid; g_strcpy(g_session_items[display].name, username); g_session_items[display].display = display; @@ -166,8 +226,169 @@ session_start(int width, int height, int bpp, char* username, char* password, g_session_items[display].height = height; g_session_items[display].bpp = bpp; g_session_items[display].data = data; + + g_session_items[display].connect_time=g_time1(); + g_session_items[display].disconnect_time=(time_t) 0; + g_session_items[display].idle_time=(time_t) 0; + + g_session_items[display].type=SESMAN_SESSION_TYPE_XVNC; + g_session_items[display].status=SESMAN_SESSION_STATUS_ACTIVE; + + g_session_count++; +#else + temp->item->pid=pid; + temp->item->display=display; + temp->item->width=width; + temp->item->height=height; + temp->item->bpp=bpp; + temp->item->data=data; + g_strncpy(temp->item->name, username, 255); + + temp->item->connect_time=g_time1(); + temp->item->disconnect_time=(time_t) 0; + temp->item->idle_time=(time_t) 0; + + temp->item->type=SESMAN_SESSION_TYPE_XVNC; + temp->item->status=SESMAN_SESSION_STATUS_ACTIVE; + + /*THREAD-FIX lock the chain*/ + temp->next=g_sessions; + g_sessions=temp; + g_session_count++; + /*THERAD-FIX free the chain*/ +#endif g_sleep(5000); } return display; } +/* +SESMAN_SESSION_TYPE_XRDP 1 +SESMAN_SESSION_TYPE_XVNC 2 + +SESMAN_SESSION_STATUS_ACTIVE 1 +SESMAN_SESSION_STATUS_IDLE 2 +SESMAN_SESSION_STATUS_DISCONNECTED 3 + +struct session_item +{ + char name[256]; + int pid; + int display; + int width; + int height; + int bpp; + long data; + + / * + unsigned char status; + unsigned char type; + * / + + / * + time_t connect_time; + time_t disconnect_time; + time_t idle_time; + * / +}; + +struct session_chain +{ + struct session_chain* next; + struct session_item* item; +}; +*/ + +#ifndef OLDSESSION + +/******************************************************************************/ +int DEFAULT_CC +session_kill(int pid) +{ + struct session_chain* tmp; + struct session_chain* prev; + + /*THREAD-FIX require chain lock */ + tmp=g_sessions; + prev=0; + + while (tmp != 0) + { + if (tmp->item == 0) + { + log_message(LOG_LEVEL_ERROR, "session descriptor for pid %d is null!", pid); + if (prev == 0) + { + /* prev does no exist, so it's the first element - so we set g_sessions */ + g_sessions = tmp->next; + } + else + { + prev->next = tmp->next; + } + /*THREAD-FIX release chain lock */ + return SESMAN_SESSION_KILL_NULLITEM; + } + + if (tmp->item->pid == pid) + { + /* deleting the session */ + log_message(LOG_LEVEL_INFO, "session %d - user %s - terminated", tmp->item->pid, tmp->item->name); + free(tmp->item); + if (prev == 0) + { + /* prev does no exist, so it's the first element - so we set g_sessions */ + g_sessions = tmp->next; + } + else + { + prev->next = tmp->next; + } + free(tmp); + g_session_count--; + /*THREAD-FIX release chain lock */ + return SESMAN_SESSION_KILL_OK; + } + + /* go on */ + prev = tmp; + tmp=tmp->next; + } + + /*THREAD-FIX release chain lock */ + return SESMAN_SESSION_KILL_NOTFOUND; +} + +/******************************************************************************/ +struct session_item* DEFAULT_CC +session_get_bypid(int pid) +{ + struct session_chain* tmp; + + /*THREAD-FIX require chain lock */ + tmp=g_sessions; + while (tmp != 0) + { + if (tmp->item == 0) + { + log_message(LOG_LEVEL_ERROR, "session descriptor for pid %d is null!", pid); + /*THREAD-FIX release chain lock */ + return 0; + } + + if (tmp->item->pid == pid) + { + /*THREAD-FIX release chain lock */ + return tmp->item; + } + + /* go on */ + tmp=tmp->next; + } + + /*THREAD-FIX release chain lock */ + return 0; +} + +#endif + diff --git a/sesman/session.h b/sesman/session.h index c8615c05..5d677911 100644 --- a/sesman/session.h +++ b/sesman/session.h @@ -24,6 +24,20 @@ #ifndef SESSION_H #define SESSION_H +#define SESMAN_SESSION_TYPE_XRDP 1 +#define SESMAN_SESSION_TYPE_XVNC 2 + +#define SESMAN_SESSION_STATUS_ACTIVE 1 +#define SESMAN_SESSION_STATUS_IDLE 2 +#define SESMAN_SESSION_STATUS_DISCONNECTED 3 +/* future expansion +#define SESMAN_SESSION_STATUS_REMCONTROL 4 +*/ + +#define SESMAN_SESSION_KILL_OK 0 +#define SESMAN_SESSION_KILL_NULLITEM 1 +#define SESMAN_SESSION_KILL_NOTFOUND 2 + struct session_item { char name[256]; @@ -33,17 +47,70 @@ struct session_item int height; int bpp; long data; + + /* status info */ + unsigned char status; + unsigned char type; + + /* time data */ + time_t connect_time; + time_t disconnect_time; + time_t idle_time; }; -/******************************************************************************/ +struct session_chain +{ + struct session_chain* next; + struct session_item* item; +}; + +/** + * + * finds a session matching the supplied parameters + * + * @return session data or 0 + * + */ struct session_item* DEFAULT_CC -session_find_item(char* name, int width, int height, int bpp); +session_get_bydata(char* name, int width, int height, int bpp); +#ifndef session_find_item + #define session_find_item(a, b, c, d) session_get_bydata(a, b, c, d); +#endif -/******************************************************************************/ -/* returns 0 if error else the display number the session was started on */ +/** + * + * starts a session + * + * @return 0 on error, display number if success + * + */ int DEFAULT_CC session_start(int width, int height, int bpp, char* username, char* password, long data); +/** + * + * kills a session + * + * @param the id of the session to be killed + * + * @return + * + */ +int DEFAULT_CC +session_kill(int pid); + +/** + * + * retrieves a session's descriptor + * + * @param pid the session pid + * + * @return a pointer to the session descriptor on success, NULL otherwise + * + */ +struct session_item* DEFAULT_CC +session_get_bypid(int pid); + #endif