new session list code

added support for new [sessions] configuration options
This commit is contained in:
ilsimo 2006-01-13 15:51:23 +00:00
parent fade58ba2b
commit 153b59ad84
7 changed files with 446 additions and 31 deletions

View File

@ -26,8 +26,6 @@
#include <sys/types.h> #include <sys/types.h>
#include <pwd.h> #include <pwd.h>
#include <grp.h> #include <grp.h>
//#include <unistd.h>
//#include <pwd.h>
extern struct config_sesman g_cfg; extern struct config_sesman g_cfg;
@ -76,7 +74,7 @@ access_login_allowed(char* user)
while (0!=groups->gr_mem[i]) while (0!=groups->gr_mem[i])
{ {
LOG_DBG("user: %s", 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++; i++;
} }

View File

@ -74,6 +74,9 @@ config_read(struct config_sesman* cfg)
/* read security config */ /* read security config */
config_read_security(fd, &(cfg->sec), param_n, param_v); config_read_security(fd, &(cfg->sec), param_n, param_v);
/* read session config */
config_read_sessions(fd, &(cfg->sess), param_n, param_v);
/* cleanup */ /* cleanup */
list_delete(sec); list_delete(sec);
list_delete(param_v); list_delete(param_v);
@ -206,6 +209,7 @@ config_read_security(int file, struct config_security* sc, struct list* param_n,
{ {
int i; int i;
char* buf; char* buf;
struct group* g;
list_clear(param_v); list_clear(param_v);
list_clear(param_n); list_clear(param_n);
@ -224,14 +228,22 @@ config_read_security(int file, struct config_security* sc, struct list* param_n,
sc->allow_root = text2bool((char*)list_get_item(param_v, i)); sc->allow_root = text2bool((char*)list_get_item(param_v, i));
} }
if (0 == g_strncasecmp(buf, SESMAN_CFG_SEC_USR_GROUP, 20)) if (0 == g_strncasecmp(buf, SESMAN_CFG_SEC_USR_GROUP, 20))
{
g=getgrnam((char*)list_get_item(param_v, i));
if (0!=g)
{ {
sc->ts_users_enable=1; sc->ts_users_enable=1;
sc->ts_users=(getgrnam((char*)list_get_item(param_v, i))->gr_gid); sc->ts_users=g->gr_gid;
}
} }
if (0 == g_strncasecmp(buf, SESMAN_CFG_SEC_ADM_GROUP, 20)) if (0 == g_strncasecmp(buf, SESMAN_CFG_SEC_ADM_GROUP, 20))
{
g=getgrnam((char*)list_get_item(param_v, i));
if (0!=g)
{ {
sc->ts_admins_enable=1; sc->ts_admins_enable=1;
sc->ts_admins=(getgrnam((char*)list_get_item(param_v, i))->gr_gid); 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; 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;
}

View File

@ -59,15 +59,12 @@
#define SESMAN_CFG_SESS_MAX "MaxSessions" #define SESMAN_CFG_SESS_MAX "MaxSessions"
#define SESMAN_CFG_SESS_KILL_DISC "KillDisconnected" #define SESMAN_CFG_SESS_KILL_DISC "KillDisconnected"
#define SESMAN_CFG_SESS_IDLE_LIMIT "IdleTimeLimit" #define SESMAN_CFG_SESS_IDLE_LIMIT "IdleTimeLimit"
#define SESMAN_CFG_SESS_DISC_LIMIT "DisconnectedTimeLimit"
/** /**
* *
* @struct config_sesman * @struct config_security
* @brief \t struct that contains \t sesman configuration * @brief \t struct that contains \t sesman access control 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 struct config_security
@ -91,6 +88,36 @@ struct config_security
gid_t ts_admins; 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 * @struct config_sesman
@ -133,6 +160,11 @@ struct config_sesman
* @brief Security configuration options \t struct * @brief Security configuration options \t struct
*/ */
struct config_security sec; 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 * @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 int DEFAULT_CC
config_read_security(int file, struct config_security* sc, struct list* param_n, struct list* param_v); 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 #endif

View File

@ -32,14 +32,25 @@
int g_sck; int g_sck;
int g_pid; int g_pid;
unsigned char g_fixedkey[8] = { 23, 82, 107, 6, 35, 78, 88, 7 }; unsigned char g_fixedkey[8] = { 23, 82, 107, 6, 35, 78, 88, 7 };
#ifdef OLDSESSION
struct session_item g_session_items[100]; /* sesman.h */ struct session_item g_session_items[100]; /* sesman.h */
extern int g_session_count;
#endif
struct config_sesman g_cfg; /* config.h */ struct config_sesman g_cfg; /* config.h */
/******************************************************************************/ /**
*
* trigger when a child process (a session) dies
*
* @param s received signal
*
*/
static void DEFAULT_CC static void DEFAULT_CC
cterm(int s) cterm(int s)
{ {
#ifdef OLDSESSION
int i; int i;
#endif
int pid; int pid;
if (g_getpid() != g_pid) if (g_getpid() != g_pid)
@ -49,13 +60,18 @@ cterm(int s)
pid = g_waitchild(); pid = g_waitchild();
if (pid > 0) if (pid > 0)
{ {
#ifdef OLDSESSION
for (i = 0; i < 100; i++) for (i = 0; i < 100; i++)
{ {
if (g_session_items[i].pid == pid) if (g_session_items[i].pid == pid)
{ {
g_memset(g_session_items + i, 0, sizeof(struct session_item)); 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; display = 0;
if (data) 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) if (s_item != 0)
{ {
display = s_item->display; display = s_item->display;
@ -325,7 +342,9 @@ main(int argc, char** argv)
} }
/* signal handling */ /* signal handling */
#ifdef OLDSESSION
g_memset(&g_session_items, 0, sizeof(g_session_items)); g_memset(&g_session_items, 0, sizeof(g_session_items));
#endif
g_pid = g_getpid(); g_pid = g_getpid();
g_signal(1, sig_sesman_reload_cfg); /* SIGHUP */ g_signal(1, sig_sesman_reload_cfg); /* SIGHUP */
g_signal(2, sig_sesman_shutdown); /* SIGINT */ g_signal(2, sig_sesman_shutdown); /* SIGINT */

View File

@ -4,14 +4,19 @@ EnableUserWindowManager=1
UserWindowManager=startwm.sh UserWindowManager=startwm.sh
DefaultWindowManager=startwm.sh DefaultWindowManager=startwm.sh
[Security]
AllowRootLogin=1
TerminalServerUsers=tsusers
TerminalServerAdmins=tsadmins
[Sessions]
MaxSessions=10
KillDisconnected=0
IdleTimeLimit=0
DisconnectedTimeLimit=0
[Logging] [Logging]
LogFile=/usr/local/xrdp/sesman.log LogFile=./sesman.log
LogLevel=DEBUG LogLevel=DEBUG
EnableSyslog=0 EnableSyslog=0
SyslogLevel=DEBUG SyslogLevel=DEBUG
[Security]
AllowRootLogin=1
#TerminalServerUsers=tsusers
#TerminalServerAdmins=tsadmins

View File

@ -21,16 +21,24 @@
*/ */
#include <stdlib.h>
#include "sesman.h" #include "sesman.h"
extern unsigned char g_fixedkey[8]; extern unsigned char g_fixedkey[8];
extern struct session_item g_session_items[100]; /* sesman.h */
extern struct config_sesman g_cfg; /* config.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 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; int i;
for (i = 0; i < 100; 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; 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; return 0;
} }
@ -73,10 +102,40 @@ session_start(int width, int height, int bpp, char* username, char* password,
char cur_dir[256]; char cur_dir[256];
char text[256]; char text[256];
char passwd_file[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); g_get_current_dir(cur_dir, 255);
display = 10; 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++; display++;
} }
@ -159,6 +218,7 @@ session_start(int width, int height, int bpp, char* username, char* password,
} }
else /* parent */ else /* parent */
{ {
#ifdef OLDSESSION
g_session_items[display].pid = pid; g_session_items[display].pid = pid;
g_strcpy(g_session_items[display].name, username); g_strcpy(g_session_items[display].name, username);
g_session_items[display].display = display; 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].height = height;
g_session_items[display].bpp = bpp; g_session_items[display].bpp = bpp;
g_session_items[display].data = data; 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); g_sleep(5000);
} }
return display; 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

View File

@ -24,6 +24,20 @@
#ifndef SESSION_H #ifndef SESSION_H
#define 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 struct session_item
{ {
char name[256]; char name[256];
@ -33,17 +47,70 @@ struct session_item
int height; int height;
int bpp; int bpp;
long data; 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_item* DEFAULT_CC {
session_find_item(char* name, int width, int height, int bpp); struct session_chain* next;
struct session_item* item;
};
/******************************************************************************/ /**
/* returns 0 if error else the display number the session was started on */ *
* finds a session matching the supplied parameters
*
* @return session data or 0
*
*/
struct session_item* DEFAULT_CC
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
/**
*
* starts a session
*
* @return 0 on error, display number if success
*
*/
int DEFAULT_CC int DEFAULT_CC
session_start(int width, int height, int bpp, char* username, char* password, session_start(int width, int height, int bpp, char* username, char* password,
long data); 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 #endif