Rework sesman with new files
This commit is contained in:
parent
3895954b75
commit
74cd7d1837
@ -16,8 +16,10 @@ sbin_PROGRAMS = \
|
|||||||
xrdp-sesman
|
xrdp-sesman
|
||||||
|
|
||||||
xrdp_sesman_SOURCES = \
|
xrdp_sesman_SOURCES = \
|
||||||
env.c \
|
eicp_process.c \
|
||||||
env.h \
|
eicp_process.h \
|
||||||
|
ercp_process.c \
|
||||||
|
ercp_process.h \
|
||||||
lock_uds.c \
|
lock_uds.c \
|
||||||
lock_uds.h \
|
lock_uds.h \
|
||||||
pre_session_list.c \
|
pre_session_list.c \
|
||||||
@ -28,16 +30,10 @@ xrdp_sesman_SOURCES = \
|
|||||||
sesman.h \
|
sesman.h \
|
||||||
sesexec_control.c \
|
sesexec_control.c \
|
||||||
sesexec_control.h \
|
sesexec_control.h \
|
||||||
session.c \
|
|
||||||
session.h \
|
|
||||||
session_list.c \
|
session_list.c \
|
||||||
session_list.h \
|
session_list.h \
|
||||||
sig.c \
|
sig.c \
|
||||||
sig.h \
|
sig.h
|
||||||
xauth.c \
|
|
||||||
xauth.h \
|
|
||||||
xwait.c \
|
|
||||||
xwait.h
|
|
||||||
|
|
||||||
xrdp_sesman_LDADD = \
|
xrdp_sesman_LDADD = \
|
||||||
$(top_builddir)/sesman/libsesman/libsesman.la \
|
$(top_builddir)/sesman/libsesman/libsesman.la \
|
||||||
|
@ -30,106 +30,149 @@
|
|||||||
|
|
||||||
#include "trans.h"
|
#include "trans.h"
|
||||||
#include "os_calls.h"
|
#include "os_calls.h"
|
||||||
|
#include "eicp.h"
|
||||||
|
#include "ercp.h"
|
||||||
#include "scp.h"
|
#include "scp.h"
|
||||||
#include "sesman_config.h"
|
|
||||||
|
|
||||||
#include "scp_process.h"
|
#include "scp_process.h"
|
||||||
|
#include "sesman.h"
|
||||||
#include "sesman_access.h"
|
#include "sesman_access.h"
|
||||||
#include "sesman_auth.h"
|
#include "sesman_auth.h"
|
||||||
#include "guid.h"
|
#include "sesman_config.h"
|
||||||
#include "os_calls.h"
|
#include "os_calls.h"
|
||||||
|
#include "pre_session_list.h"
|
||||||
#include "session_list.h"
|
#include "session_list.h"
|
||||||
#include "session.h"
|
#include "sesexec_control.h"
|
||||||
#include "sesman.h"
|
|
||||||
#include "string_calls.h"
|
#include "string_calls.h"
|
||||||
|
|
||||||
/**************************************************************************//**
|
/******************************************************************************/
|
||||||
* Logs an authentication failure message
|
|
||||||
*
|
static int
|
||||||
* @param username Username
|
process_set_peername_request(struct pre_session_item *psi)
|
||||||
* @param ip_addr IP address, if known
|
|
||||||
*
|
|
||||||
* The message is intended for use by fail2ban. Make changes with care.
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
log_authfail_message(const char *username, const char *ip_addr)
|
|
||||||
{
|
{
|
||||||
if (ip_addr == NULL || ip_addr[0] == '\0')
|
int rv;
|
||||||
|
const char *peername;
|
||||||
|
|
||||||
|
rv = scp_get_set_peername_request(psi->client_trans, &peername);
|
||||||
|
if (rv == 0)
|
||||||
{
|
{
|
||||||
ip_addr = "unknown";
|
if (pre_session_list_set_peername(psi, peername) != 0)
|
||||||
|
{
|
||||||
|
LOG(LOG_LEVEL_WARNING,
|
||||||
|
"Failed to set connection peername from %s to %s",
|
||||||
|
psi->peername, peername);
|
||||||
}
|
}
|
||||||
LOG(LOG_LEVEL_INFO, "AUTHFAIL: user=%s ip=%s time=%d",
|
}
|
||||||
username, ip_addr, g_time1());
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
static int
|
||||||
|
process_sys_login_request(struct pre_session_item *psi)
|
||||||
|
{
|
||||||
|
int rv;
|
||||||
|
const char *username;
|
||||||
|
const char *password;
|
||||||
|
const char *ip_addr;
|
||||||
|
int send_client_reply = 1;
|
||||||
|
|
||||||
|
rv = scp_get_sys_login_request(psi->client_trans, &username,
|
||||||
|
&password, &ip_addr);
|
||||||
|
if (rv == 0)
|
||||||
|
{
|
||||||
|
enum scp_login_status errorcode;
|
||||||
|
|
||||||
|
LOG(LOG_LEVEL_INFO,
|
||||||
|
"Received system login request from %s for user: %s IP: %s",
|
||||||
|
psi->peername, username, ip_addr);
|
||||||
|
|
||||||
|
if (psi->login_state != E_PS_LOGIN_NOT_LOGGED_IN)
|
||||||
|
{
|
||||||
|
errorcode = E_SCP_LOGIN_ALREADY_LOGGED_IN;
|
||||||
|
LOG(LOG_LEVEL_ERROR, "Connection is already logged in for %s",
|
||||||
|
psi->username);
|
||||||
|
}
|
||||||
|
else if ((psi->username = g_strdup(username)) == NULL)
|
||||||
|
{
|
||||||
|
errorcode = E_SCP_LOGIN_NO_MEMORY;
|
||||||
|
LOG(LOG_LEVEL_ERROR, "Memory allocation failure logging in %s",
|
||||||
|
username);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Create a sesexec process to handle the login
|
||||||
|
*
|
||||||
|
* We won't check for the user being valid here, as this might
|
||||||
|
* lead to information leakage */
|
||||||
|
if (sesexec_start(psi) != 0)
|
||||||
|
{
|
||||||
|
LOG(LOG_LEVEL_ERROR,
|
||||||
|
"Can't start sesexec to authenticate user");
|
||||||
|
errorcode = E_SCP_LOGIN_GENERAL_ERROR;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int eicp_stat;
|
||||||
|
eicp_stat = eicp_send_sys_login_request(psi->sesexec_trans,
|
||||||
|
username,
|
||||||
|
password,
|
||||||
|
ip_addr,
|
||||||
|
psi->client_trans->sck);
|
||||||
|
if (eicp_stat != 0)
|
||||||
|
{
|
||||||
|
LOG(LOG_LEVEL_ERROR,
|
||||||
|
"Can't ask sesexec to authenticate user");
|
||||||
|
errorcode = E_SCP_LOGIN_GENERAL_ERROR;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* We've handed over responsibility for the
|
||||||
|
* SCP communication */
|
||||||
|
send_client_reply = 0;
|
||||||
|
psi->dispatcher_action = E_PSD_REMOVE_CLIENT_TRANS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (send_client_reply)
|
||||||
|
{
|
||||||
|
/* We only get here if something has gone
|
||||||
|
* wrong with the handover to sesexec */
|
||||||
|
rv = scp_send_login_response(psi->client_trans, errorcode, 1);
|
||||||
|
psi->dispatcher_action = E_PSD_TERMINATE_PRE_SESSION;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mode parameter for authenticate_and_authorize_connection()
|
* Authenticate and authorize a UDS connection
|
||||||
*/
|
|
||||||
enum login_mode
|
|
||||||
{
|
|
||||||
AM_SYSTEM,
|
|
||||||
AM_UDS
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Authenticate and authorize the connection
|
|
||||||
*
|
*
|
||||||
* @param sc Connection to sesman
|
* @param psi Connection to sesman
|
||||||
* @param login_mode Describes the type of login in use
|
|
||||||
* @param uid UID for user
|
* @param uid UID for user
|
||||||
* @param username Name for user
|
* @param username Name for user
|
||||||
* @param password Password (AM_SYSTEM) or NULL.
|
|
||||||
* @param ip_addr Remote IP address (AM_SYSTEM) or NULL.
|
|
||||||
* @return Status for the operation
|
* @return Status for the operation
|
||||||
*
|
*
|
||||||
* @pre sc->auth_info, sc->username and sc->ip_addr must be NULL
|
* @post If E_SCP_LOGIN_OK is returned, psi->username is non-NULL
|
||||||
*
|
|
||||||
* @post If E_SCP_LOGIN_OK is returned, sc->auth_info is non-NULL
|
|
||||||
* @post If E_SCP_LOGIN_OK is returned, sc->username is non-NULL
|
|
||||||
* @post If E_SCP_LOGIN_OK is returned, sc->ip_addr is non-NULL
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
static enum scp_login_status
|
static enum scp_login_status
|
||||||
authenticate_and_authorize_connection(struct sesman_con *sc,
|
authenticate_and_authorize_uds_connection(struct pre_session_item *psi,
|
||||||
enum login_mode login_mode,
|
|
||||||
int uid,
|
int uid,
|
||||||
const char *username,
|
const char *username)
|
||||||
const char *password,
|
|
||||||
const char *ip_addr)
|
|
||||||
{
|
{
|
||||||
enum scp_login_status status = E_SCP_LOGIN_GENERAL_ERROR;
|
enum scp_login_status status = E_SCP_LOGIN_GENERAL_ERROR;
|
||||||
struct auth_info *auth_info = NULL;
|
struct auth_info *auth_info = auth_uds(username, &status);
|
||||||
|
|
||||||
/* Check preconditions */
|
|
||||||
if (sc->auth_info != NULL || sc->username != NULL || sc->ip_addr != NULL)
|
|
||||||
{
|
|
||||||
LOG(LOG_LEVEL_ERROR,
|
|
||||||
"Internal error - connection already logged in");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
switch (login_mode)
|
|
||||||
{
|
|
||||||
case AM_SYSTEM:
|
|
||||||
auth_info = auth_userpass(username, password, ip_addr, &status);
|
|
||||||
break;
|
|
||||||
case AM_UDS:
|
|
||||||
auth_info = auth_uds(username, &status);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
LOG(LOG_LEVEL_ERROR, "%s called with invalid mode %d",
|
|
||||||
__func__, (int)login_mode);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (auth_info != NULL)
|
if (auth_info != NULL)
|
||||||
{
|
{
|
||||||
if (status != E_SCP_LOGIN_OK)
|
if (status != E_SCP_LOGIN_OK)
|
||||||
{
|
{
|
||||||
/* This shouldn't happen */
|
/* This shouldn't happen */
|
||||||
LOG(LOG_LEVEL_ERROR,
|
LOG(LOG_LEVEL_ERROR,
|
||||||
"Unexpected status return %d from auth call",
|
"Unexpected status return %d from auth_uds call",
|
||||||
(int)status);
|
(int)status);
|
||||||
}
|
}
|
||||||
else if (!access_login_allowed(&g_cfg->sec, username))
|
else if (!access_login_allowed(&g_cfg->sec, username))
|
||||||
@ -139,39 +182,29 @@ authenticate_and_authorize_connection(struct sesman_con *sc,
|
|||||||
"user: %s", username);
|
"user: %s", username);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If all is well, put the auth_info in the sesman connection
|
/* If all is well, add info to the sesman connection for later use */
|
||||||
* for later use. If not, remove the auth_info */
|
|
||||||
if (status == E_SCP_LOGIN_OK)
|
if (status == E_SCP_LOGIN_OK)
|
||||||
{
|
{
|
||||||
char *dup_username = g_strdup(username);
|
if ((psi->username = g_strdup(username)) == NULL)
|
||||||
char *dup_ip_addr =
|
|
||||||
(ip_addr == NULL) ? g_strdup("") : g_strdup(ip_addr);
|
|
||||||
|
|
||||||
if (dup_username == NULL || dup_ip_addr == NULL)
|
|
||||||
{
|
{
|
||||||
LOG(LOG_LEVEL_ERROR, "%s : Memory allocation failed",
|
LOG(LOG_LEVEL_ERROR, "%s : Memory allocation failed",
|
||||||
__func__);
|
__func__);
|
||||||
g_free(dup_username);
|
g_free(psi->username);
|
||||||
g_free(dup_ip_addr);
|
psi->username = NULL;
|
||||||
status = E_SCP_LOGIN_NO_MEMORY;
|
status = E_SCP_LOGIN_NO_MEMORY;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LOG(LOG_LEVEL_INFO, "Access permitted for user=%s uid=%d",
|
LOG(LOG_LEVEL_INFO, "Access permitted for user: %s",
|
||||||
username, uid);
|
username);
|
||||||
sc->auth_info = auth_info;
|
psi->login_state = E_PS_LOGIN_UDS;
|
||||||
sc->uid = uid;
|
psi->uid = uid;
|
||||||
sc->username = dup_username;
|
psi->start_ip_addr[0] = '\0';
|
||||||
sc->ip_addr = dup_ip_addr;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status != E_SCP_LOGIN_OK)
|
|
||||||
{
|
|
||||||
auth_end(auth_info);
|
auth_end(auth_info);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
@ -179,191 +212,7 @@ authenticate_and_authorize_connection(struct sesman_con *sc,
|
|||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
static int
|
static int
|
||||||
process_set_peername_request(struct sesman_con *sc)
|
process_uds_login_request(struct pre_session_item *psi)
|
||||||
{
|
|
||||||
int rv;
|
|
||||||
const char *peername;
|
|
||||||
|
|
||||||
rv = scp_get_set_peername_request(sc->t, &peername);
|
|
||||||
if (rv == 0)
|
|
||||||
{
|
|
||||||
if (sesman_set_connection_peername(sc, peername) != 0)
|
|
||||||
{
|
|
||||||
LOG(LOG_LEVEL_WARNING,
|
|
||||||
"Failed to set connection peername from %s to %s",
|
|
||||||
sc->peername, peername);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
/**
|
|
||||||
* Allocates a chain item and starts the session
|
|
||||||
*/
|
|
||||||
static enum scp_screate_status
|
|
||||||
allocate_and_start_session(struct auth_info *auth_info,
|
|
||||||
const char *username,
|
|
||||||
const char *ip_addr,
|
|
||||||
const struct session_parameters *params)
|
|
||||||
{
|
|
||||||
int pid = 0;
|
|
||||||
enum scp_screate_status status;
|
|
||||||
struct session_item *si;
|
|
||||||
|
|
||||||
/* check to limit concurrent sessions */
|
|
||||||
if (session_list_get_count() >= (unsigned int)g_cfg->sess.max_sessions)
|
|
||||||
{
|
|
||||||
LOG(LOG_LEVEL_ERROR, "max concurrent session limit "
|
|
||||||
"exceeded. login for user %s denied", username);
|
|
||||||
return E_SCP_SCREATE_MAX_REACHED;
|
|
||||||
}
|
|
||||||
|
|
||||||
si = session_new();
|
|
||||||
if (si == NULL)
|
|
||||||
{
|
|
||||||
LOG(LOG_LEVEL_ERROR, "Out of memory error: cannot create new session "
|
|
||||||
"element - user %s", username);
|
|
||||||
return E_SCP_SCREATE_NO_MEMORY;
|
|
||||||
}
|
|
||||||
|
|
||||||
status = session_start(auth_info, params, &pid);
|
|
||||||
if (status == E_SCP_SCREATE_OK)
|
|
||||||
{
|
|
||||||
if (ip_addr[0] != '\0')
|
|
||||||
{
|
|
||||||
LOG(LOG_LEVEL_INFO, "++ created session: username %s, ip %s",
|
|
||||||
username, ip_addr);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LOG(LOG_LEVEL_INFO, "++ created session: username %s", username);
|
|
||||||
}
|
|
||||||
|
|
||||||
si->pid = pid;
|
|
||||||
si->display = params->display;
|
|
||||||
si->width = params->width;
|
|
||||||
si->height = params->height;
|
|
||||||
si->bpp = params->bpp;
|
|
||||||
si->auth_info = auth_info;
|
|
||||||
g_strncpy(si->start_ip_addr, ip_addr,
|
|
||||||
sizeof(si->start_ip_addr) - 1);
|
|
||||||
si->uid = params->uid;
|
|
||||||
si->guid = params->guid;
|
|
||||||
|
|
||||||
si->start_time = g_time1();
|
|
||||||
|
|
||||||
si->type = params->type;
|
|
||||||
si->status = SESMAN_SESSION_STATUS_ACTIVE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Remove session item from the list
|
|
||||||
session_list_kill(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
|
|
||||||
static int
|
|
||||||
process_sys_login_request(struct sesman_con *sc)
|
|
||||||
{
|
|
||||||
int rv;
|
|
||||||
const char *supplied_username;
|
|
||||||
const char *password;
|
|
||||||
const char *ip_addr;
|
|
||||||
|
|
||||||
rv = scp_get_sys_login_request(sc->t, &supplied_username,
|
|
||||||
&password, &ip_addr);
|
|
||||||
if (rv == 0)
|
|
||||||
{
|
|
||||||
enum scp_login_status errorcode;
|
|
||||||
int server_closed = 1;
|
|
||||||
int uid;
|
|
||||||
char *username = NULL;
|
|
||||||
|
|
||||||
LOG(LOG_LEVEL_INFO,
|
|
||||||
"Received system login request from %s for user: %s IP: %s",
|
|
||||||
sc->peername, supplied_username, ip_addr);
|
|
||||||
|
|
||||||
if (sc->auth_info != NULL)
|
|
||||||
{
|
|
||||||
errorcode = E_SCP_LOGIN_ALREADY_LOGGED_IN;
|
|
||||||
LOG(LOG_LEVEL_ERROR, "Connection is already logged in for %s",
|
|
||||||
sc->username);
|
|
||||||
}
|
|
||||||
else if (g_getuser_info_by_name(supplied_username,
|
|
||||||
&uid, NULL, NULL, NULL, NULL) != 0)
|
|
||||||
{
|
|
||||||
/* we can't get a UID for the user */
|
|
||||||
errorcode = E_SCP_LOGIN_NOT_AUTHENTICATED;
|
|
||||||
LOG(LOG_LEVEL_ERROR, "Can't get UID for user %s",
|
|
||||||
supplied_username);
|
|
||||||
log_authfail_message(username, ip_addr);
|
|
||||||
}
|
|
||||||
else if (g_getuser_info_by_uid(uid,
|
|
||||||
&username, NULL, NULL, NULL, NULL) != 0)
|
|
||||||
{
|
|
||||||
errorcode = E_SCP_LOGIN_GENERAL_ERROR;
|
|
||||||
LOG(LOG_LEVEL_ERROR, "Can't reverse lookup UID %d", uid);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (g_strcmp(supplied_username, username) != 0)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* If using a federated naming service (e.g. AD), the
|
|
||||||
* username supplied may not match that name mapped to by
|
|
||||||
* the UID. We will generate a warning in this instance so
|
|
||||||
* the user can see what is being used within sesman
|
|
||||||
*/
|
|
||||||
LOG(LOG_LEVEL_WARNING,
|
|
||||||
"Using username %s for the session (from UID %d)",
|
|
||||||
username, uid);
|
|
||||||
}
|
|
||||||
|
|
||||||
errorcode = authenticate_and_authorize_connection(
|
|
||||||
sc, AM_SYSTEM,
|
|
||||||
uid, username,
|
|
||||||
password, ip_addr);
|
|
||||||
if (errorcode == E_SCP_LOGIN_OK)
|
|
||||||
{
|
|
||||||
server_closed = 0;
|
|
||||||
}
|
|
||||||
else if (errorcode == E_SCP_LOGIN_NOT_AUTHENTICATED)
|
|
||||||
{
|
|
||||||
log_authfail_message(username, ip_addr);
|
|
||||||
if (sc->auth_retry_count > 0)
|
|
||||||
{
|
|
||||||
/* Password problem? Invite the user to retry */
|
|
||||||
server_closed = 0;
|
|
||||||
--sc->auth_retry_count;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
g_free(username);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (server_closed)
|
|
||||||
{
|
|
||||||
/* Expecting no more client messages. Close the connection
|
|
||||||
* after returning from this callback */
|
|
||||||
sc->close_requested = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
rv = scp_send_login_response(sc->t, errorcode, server_closed);
|
|
||||||
}
|
|
||||||
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
|
|
||||||
static int
|
|
||||||
process_uds_login_request(struct sesman_con *sc)
|
|
||||||
{
|
{
|
||||||
enum scp_login_status errorcode;
|
enum scp_login_status errorcode;
|
||||||
int rv;
|
int rv;
|
||||||
@ -372,25 +221,25 @@ process_uds_login_request(struct sesman_con *sc)
|
|||||||
char *username = NULL;
|
char *username = NULL;
|
||||||
int server_closed = 1;
|
int server_closed = 1;
|
||||||
|
|
||||||
rv = g_sck_get_peer_cred(sc->t->sck, &pid, &uid, NULL);
|
rv = g_sck_get_peer_cred(psi->client_trans->sck, &pid, &uid, NULL);
|
||||||
if (rv != 0)
|
if (rv != 0)
|
||||||
{
|
{
|
||||||
LOG(LOG_LEVEL_INFO,
|
LOG(LOG_LEVEL_INFO,
|
||||||
"Unable to get peer credentials for socket %d",
|
"Unable to get peer credentials for socket %d",
|
||||||
(int)sc->t->sck);
|
(int)psi->client_trans->sck);
|
||||||
errorcode = E_SCP_LOGIN_GENERAL_ERROR;
|
errorcode = E_SCP_LOGIN_GENERAL_ERROR;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LOG(LOG_LEVEL_INFO,
|
LOG(LOG_LEVEL_INFO,
|
||||||
"Received UDS login request from %s for UID: %d from PID: %d",
|
"Received UDS login request from %s for UID: %d from PID: %d",
|
||||||
sc->peername, uid, pid);
|
psi->peername, uid, pid);
|
||||||
|
|
||||||
if (sc->auth_info != NULL)
|
if (psi->login_state != E_PS_LOGIN_NOT_LOGGED_IN)
|
||||||
{
|
{
|
||||||
errorcode = E_SCP_LOGIN_ALREADY_LOGGED_IN;
|
errorcode = E_SCP_LOGIN_ALREADY_LOGGED_IN;
|
||||||
LOG(LOG_LEVEL_ERROR, "Connection is already logged in for %s",
|
LOG(LOG_LEVEL_ERROR, "Connection is already logged in for %s",
|
||||||
sc->username);
|
psi->username);
|
||||||
}
|
}
|
||||||
else if (g_getuser_info_by_uid(uid, &username,
|
else if (g_getuser_info_by_uid(uid, &username,
|
||||||
NULL, NULL, NULL, NULL) != 0)
|
NULL, NULL, NULL, NULL) != 0)
|
||||||
@ -400,10 +249,8 @@ process_uds_login_request(struct sesman_con *sc)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
errorcode = authenticate_and_authorize_connection(
|
errorcode = authenticate_and_authorize_uds_connection(
|
||||||
sc, AM_UDS,
|
psi, uid, username);
|
||||||
uid, username,
|
|
||||||
NULL, NULL);
|
|
||||||
g_free(username);
|
g_free(username);
|
||||||
|
|
||||||
if (errorcode == E_SCP_LOGIN_OK)
|
if (errorcode == E_SCP_LOGIN_OK)
|
||||||
@ -416,27 +263,40 @@ process_uds_login_request(struct sesman_con *sc)
|
|||||||
if (server_closed)
|
if (server_closed)
|
||||||
{
|
{
|
||||||
/* Close the connection after returning from this callback */
|
/* Close the connection after returning from this callback */
|
||||||
sc->close_requested = 1;
|
psi->dispatcher_action = E_PSD_TERMINATE_PRE_SESSION;
|
||||||
}
|
}
|
||||||
|
|
||||||
return scp_send_login_response(sc->t, errorcode, server_closed);
|
return scp_send_login_response(psi->client_trans, errorcode, server_closed);
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
static void
|
||||||
|
logout_pre_session(struct pre_session_item *psi)
|
||||||
|
{
|
||||||
|
if (psi->login_state != E_PS_LOGIN_NOT_LOGGED_IN)
|
||||||
|
{
|
||||||
|
(void)eicp_send_logout_request(psi->sesexec_trans);
|
||||||
|
trans_delete(psi->sesexec_trans);
|
||||||
|
psi->sesexec_trans = NULL;
|
||||||
|
psi->uid = (uid_t) -1;
|
||||||
|
g_free(psi->username);
|
||||||
|
psi->username = NULL;
|
||||||
|
psi->start_ip_addr[0] = '\0';
|
||||||
|
|
||||||
|
psi->login_state = E_PS_LOGIN_NOT_LOGGED_IN;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
static int
|
static int
|
||||||
process_logout_request(struct sesman_con *sc)
|
process_logout_request(struct pre_session_item *psi)
|
||||||
{
|
{
|
||||||
if (sc->auth_info != NULL)
|
if (psi->login_state != E_PS_LOGIN_NOT_LOGGED_IN)
|
||||||
{
|
{
|
||||||
LOG(LOG_LEVEL_INFO, "Logging out %s from sesman", sc->username);
|
LOG(LOG_LEVEL_INFO, "Logging out %s from sesman", psi->username);
|
||||||
auth_end(sc->auth_info);
|
logout_pre_session(psi);
|
||||||
sc->auth_info = NULL;
|
|
||||||
sc->uid = -1;
|
|
||||||
g_free(sc->username);
|
|
||||||
sc->username = NULL;
|
|
||||||
g_free(sc->ip_addr);
|
|
||||||
sc->ip_addr = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -445,117 +305,146 @@ process_logout_request(struct sesman_con *sc)
|
|||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
static int
|
static int
|
||||||
process_create_session_request(struct sesman_con *sc)
|
process_create_session_request(struct pre_session_item *psi)
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
// Parameters for a new session (if required). Filled in as
|
/* Client parameters describing new session*/
|
||||||
// we go along.
|
enum scp_session_type type;
|
||||||
struct session_parameters sp = {0};
|
unsigned short width;
|
||||||
const char *shellptr;
|
unsigned short height;
|
||||||
const char *dirptr;
|
unsigned char bpp;
|
||||||
|
const char *shell;
|
||||||
|
const char *directory;
|
||||||
|
|
||||||
|
struct guid guid;
|
||||||
|
int display = 0;
|
||||||
|
struct session_item *s_item = NULL;
|
||||||
|
int send_client_reply = 1;
|
||||||
|
|
||||||
enum scp_screate_status status = E_SCP_SCREATE_OK;
|
enum scp_screate_status status = E_SCP_SCREATE_OK;
|
||||||
|
|
||||||
int display = 0;
|
rv = scp_get_create_session_request(psi->client_trans,
|
||||||
struct guid guid;
|
&type, &width, &height,
|
||||||
|
&bpp, &shell, &directory);
|
||||||
guid_clear(&guid);
|
|
||||||
|
|
||||||
rv = scp_get_create_session_request(sc->t,
|
|
||||||
&sp.type, &sp.width, &sp.height,
|
|
||||||
&sp.bpp, &shellptr, &dirptr);
|
|
||||||
|
|
||||||
if (rv == 0)
|
if (rv == 0)
|
||||||
{
|
{
|
||||||
if (sc->auth_info == NULL)
|
if (psi->login_state == E_PS_LOGIN_NOT_LOGGED_IN)
|
||||||
{
|
{
|
||||||
status = E_SCP_SCREATE_NOT_LOGGED_IN;
|
status = E_SCP_SCREATE_NOT_LOGGED_IN;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LOG(LOG_LEVEL_INFO,
|
LOG(LOG_LEVEL_INFO,
|
||||||
"Received request from %s to create a session for user %s"
|
"Received request from %s to create a session for user %s",
|
||||||
" type=%s"
|
psi->peername, psi->username);
|
||||||
" geometry=%dx%d, bpp=%d, shell=\"%s\", dir=\"%s\"",
|
|
||||||
sc->peername, sc->username,
|
|
||||||
SCP_SESSION_TYPE_TO_STR(sp.type),
|
|
||||||
sp.width, sp.height, sp.bpp, shellptr, dirptr);
|
|
||||||
|
|
||||||
struct session_item *s_item =
|
s_item = session_list_get_bydata(psi->uid, type, width, height,
|
||||||
session_list_get_bydata(sc->uid, sp.type, sp.width, sp.height,
|
bpp, psi->start_ip_addr);
|
||||||
sp.bpp, sc->ip_addr);
|
if (s_item != NULL)
|
||||||
if (s_item != 0)
|
|
||||||
{
|
{
|
||||||
// Found an existing session
|
// Found an existing session
|
||||||
if (sc->ip_addr[0] != '\0')
|
display = s_item->display;
|
||||||
|
guid = s_item->guid;
|
||||||
|
|
||||||
|
// Tell the existing session to run the reconnect script.
|
||||||
|
// We ignore errors at this level, as any comms errors
|
||||||
|
// will be picked up in the main loop
|
||||||
|
(void)ercp_send_session_reconnect_event(s_item->sesexec_trans);
|
||||||
|
|
||||||
|
if (psi->start_ip_addr[0] != '\0')
|
||||||
{
|
{
|
||||||
LOG( LOG_LEVEL_INFO, "++ reconnected session: username %s, "
|
LOG( LOG_LEVEL_INFO, "++ reconnected session: username %s, "
|
||||||
"display :%d.0, session_pid %d, ip %s",
|
"display :%d.0, session_pid %d, ip %s",
|
||||||
sc->username, s_item->display, s_item->pid,
|
psi->username, display,
|
||||||
sc->ip_addr);
|
s_item->sesexec_pid, psi->start_ip_addr);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LOG(LOG_LEVEL_INFO, "++ reconnected session: username %s, "
|
LOG(LOG_LEVEL_INFO, "++ reconnected session: username %s, "
|
||||||
"display :%d.0, session_pid %d",
|
"display :%d.0, session_pid %d",
|
||||||
sc->username, s_item->display, s_item->pid);
|
psi->username, display, s_item->sesexec_pid);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get values for response to SCP client
|
// If we created an authentication process for this SCP
|
||||||
display = s_item->display;
|
// connection, close it gracefully
|
||||||
guid = s_item->guid;
|
logout_pre_session(psi);
|
||||||
|
|
||||||
session_reconnect(s_item->display, sc->uid, sc->auth_info);
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
// Need to create a new session
|
// Need to create a new session
|
||||||
//
|
else if (g_cfg->sess.max_sessions > 0 &&
|
||||||
// Get the rest of the parameters for the session
|
session_list_get_count() >= g_cfg->sess.max_sessions)
|
||||||
guid = guid_new();
|
{
|
||||||
display = session_list_get_available_display();
|
status = E_SCP_SCREATE_MAX_REACHED;
|
||||||
|
}
|
||||||
sp.display = display;
|
else if ((display = session_list_get_available_display()) < 0)
|
||||||
sp.uid = sc->uid;
|
|
||||||
sp.guid = guid;
|
|
||||||
// These need to be copied so they are available
|
|
||||||
// when the sub-process closes all the connections
|
|
||||||
g_snprintf(sp.shell, sizeof(sp.shell), "%s", shellptr);
|
|
||||||
g_snprintf(sp.directory, sizeof(sp.directory), "%s", dirptr);
|
|
||||||
|
|
||||||
if (display == 0)
|
|
||||||
{
|
{
|
||||||
status = E_SCP_SCREATE_NO_DISPLAY;
|
status = E_SCP_SCREATE_NO_DISPLAY;
|
||||||
}
|
}
|
||||||
|
// Create an entry on the session list for the new session
|
||||||
|
else if ((s_item = session_list_new()) == NULL)
|
||||||
|
{
|
||||||
|
status = E_SCP_SCREATE_NO_MEMORY;
|
||||||
|
}
|
||||||
|
// Create a sesexec process if we don't have one (UDS login)
|
||||||
|
else if (psi->sesexec_trans == NULL && sesexec_start(psi) != 0)
|
||||||
|
{
|
||||||
|
LOG(LOG_LEVEL_ERROR,
|
||||||
|
"Can't start sesexec to authenticate user");
|
||||||
|
status = E_SCP_SCREATE_GENERAL_ERROR;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// The new session will have a lifetime longer than
|
// Pass the session create request to sesexec
|
||||||
// the sesman connection, and so needs to own
|
int eicp_stat;
|
||||||
// the auth_info struct.
|
eicp_stat = eicp_send_create_session_request(
|
||||||
//
|
psi->sesexec_trans,
|
||||||
// Copy the auth_info struct out of the connection and pass
|
psi->client_trans->sck,
|
||||||
// it to the session
|
display,
|
||||||
struct auth_info *auth_info = sc->auth_info;
|
type, width, height,
|
||||||
sc->auth_info = NULL;
|
bpp, shell, directory);
|
||||||
|
|
||||||
status = allocate_and_start_session(auth_info,
|
if (eicp_stat != 0)
|
||||||
sc->username,
|
|
||||||
sc->ip_addr,
|
|
||||||
&sp);
|
|
||||||
if (status != E_SCP_SCREATE_OK)
|
|
||||||
{
|
{
|
||||||
// Close the auth session down as it can't be re-used.
|
LOG(LOG_LEVEL_ERROR,
|
||||||
auth_end(auth_info);
|
"Can't ask sesexec to authenticate user");
|
||||||
|
status = E_SCP_SCREATE_GENERAL_ERROR;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// We've handed over responsibility for the
|
||||||
|
// SCP communication
|
||||||
|
send_client_reply = 0;
|
||||||
|
|
||||||
|
// Further comms from sesexec comes over the ERCP
|
||||||
|
// protocol
|
||||||
|
ercp_trans_from_eicp_trans(psi->sesexec_trans,
|
||||||
|
sesman_ercp_data_in,
|
||||||
|
(void *)s_item);
|
||||||
|
|
||||||
|
// Move the transport over to the session list item
|
||||||
|
s_item->sesexec_trans = psi->sesexec_trans;
|
||||||
|
s_item->sesexec_pid = psi->sesexec_pid;
|
||||||
|
psi->sesexec_trans = NULL;
|
||||||
|
psi->sesexec_pid = 0;
|
||||||
|
|
||||||
|
// Add the display to the session item so we don't try
|
||||||
|
// to allocate it to another session
|
||||||
|
s_item->display = display;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Currently a create session request is the last thing on a
|
// Currently a create session request is the last thing on a
|
||||||
* connection, and results in automatic closure */
|
// connection, and results in automatic closure
|
||||||
sc->close_requested = 1;
|
//
|
||||||
|
// We may have passed the client_trans over to sesexec. If so,
|
||||||
rv = scp_send_create_session_response(sc->t, status,
|
// we can't send a reply here.
|
||||||
display, &guid);
|
psi->dispatcher_action = E_PSD_TERMINATE_PRE_SESSION;
|
||||||
|
if (send_client_reply)
|
||||||
|
{
|
||||||
|
rv = scp_send_create_session_response(psi->client_trans,
|
||||||
|
status, display, &guid);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return rv;
|
return rv;
|
||||||
@ -564,7 +453,7 @@ process_create_session_request(struct sesman_con *sc)
|
|||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
static int
|
static int
|
||||||
process_list_sessions_request(struct sesman_con *sc)
|
process_list_sessions_request(struct pre_session_item *psi)
|
||||||
{
|
{
|
||||||
int rv = 0;
|
int rv = 0;
|
||||||
|
|
||||||
@ -572,9 +461,9 @@ process_list_sessions_request(struct sesman_con *sc)
|
|||||||
unsigned int cnt = 0;
|
unsigned int cnt = 0;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
if (sc->auth_info == NULL)
|
if (psi->login_state == E_PS_LOGIN_NOT_LOGGED_IN)
|
||||||
{
|
{
|
||||||
rv = scp_send_list_sessions_response(sc->t,
|
rv = scp_send_list_sessions_response(psi->client_trans,
|
||||||
E_SCP_LS_NOT_LOGGED_IN,
|
E_SCP_LS_NOT_LOGGED_IN,
|
||||||
NULL);
|
NULL);
|
||||||
}
|
}
|
||||||
@ -582,14 +471,13 @@ process_list_sessions_request(struct sesman_con *sc)
|
|||||||
{
|
{
|
||||||
LOG(LOG_LEVEL_INFO,
|
LOG(LOG_LEVEL_INFO,
|
||||||
"Received request from %s to list sessions for user %s",
|
"Received request from %s to list sessions for user %s",
|
||||||
sc->peername, sc->username);
|
psi->peername, psi->username);
|
||||||
|
|
||||||
info = session_list_get_byuid(sc->uid, &cnt,
|
info = session_list_get_byuid(psi->uid, &cnt, 0);
|
||||||
SESMAN_SESSION_STATUS_ALL);
|
|
||||||
|
|
||||||
for (i = 0; rv == 0 && i < cnt; ++i)
|
for (i = 0; rv == 0 && i < cnt; ++i)
|
||||||
{
|
{
|
||||||
rv = scp_send_list_sessions_response(sc->t,
|
rv = scp_send_list_sessions_response(psi->client_trans,
|
||||||
E_SCP_LS_SESSION_INFO,
|
E_SCP_LS_SESSION_INFO,
|
||||||
&info[i]);
|
&info[i]);
|
||||||
}
|
}
|
||||||
@ -597,7 +485,7 @@ process_list_sessions_request(struct sesman_con *sc)
|
|||||||
|
|
||||||
if (rv == 0)
|
if (rv == 0)
|
||||||
{
|
{
|
||||||
rv = scp_send_list_sessions_response(sc->t,
|
rv = scp_send_list_sessions_response(psi->client_trans,
|
||||||
E_SCP_LS_END_OF_LIST,
|
E_SCP_LS_END_OF_LIST,
|
||||||
NULL);
|
NULL);
|
||||||
}
|
}
|
||||||
@ -609,54 +497,54 @@ process_list_sessions_request(struct sesman_con *sc)
|
|||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
static int
|
static int
|
||||||
process_close_connection_request(struct sesman_con *sc)
|
process_close_connection_request(struct pre_session_item *psi)
|
||||||
{
|
{
|
||||||
int rv = 0;
|
int rv = 0;
|
||||||
|
|
||||||
LOG(LOG_LEVEL_INFO, "Received request to close connection from %s",
|
LOG(LOG_LEVEL_INFO, "Received request to close connection from %s",
|
||||||
sc->peername);
|
psi->peername);
|
||||||
|
|
||||||
/* Expecting no more client messages. Close the connection
|
/* Expecting no more client messages. Close the connection
|
||||||
* after returning from this callback */
|
* after returning from this callback */
|
||||||
sc->close_requested = 1;
|
psi->dispatcher_action = E_PSD_TERMINATE_PRE_SESSION;
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
int
|
int
|
||||||
scp_process(struct sesman_con *sc)
|
scp_process(struct pre_session_item *psi)
|
||||||
{
|
{
|
||||||
enum scp_msg_code msgno;
|
enum scp_msg_code msgno;
|
||||||
int rv = 0;
|
int rv = 0;
|
||||||
|
|
||||||
switch ((msgno = scp_msg_in_get_msgno(sc->t)))
|
switch ((msgno = scp_msg_in_get_msgno(psi->client_trans)))
|
||||||
{
|
{
|
||||||
case E_SCP_SET_PEERNAME_REQUEST:
|
case E_SCP_SET_PEERNAME_REQUEST:
|
||||||
rv = process_set_peername_request(sc);
|
rv = process_set_peername_request(psi);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case E_SCP_SYS_LOGIN_REQUEST:
|
case E_SCP_SYS_LOGIN_REQUEST:
|
||||||
rv = process_sys_login_request(sc);
|
rv = process_sys_login_request(psi);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case E_SCP_UDS_LOGIN_REQUEST:
|
case E_SCP_UDS_LOGIN_REQUEST:
|
||||||
rv = process_uds_login_request(sc);
|
rv = process_uds_login_request(psi);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case E_SCP_LOGOUT_REQUEST:
|
case E_SCP_LOGOUT_REQUEST:
|
||||||
rv = process_logout_request(sc);
|
rv = process_logout_request(psi);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case E_SCP_CREATE_SESSION_REQUEST:
|
case E_SCP_CREATE_SESSION_REQUEST:
|
||||||
rv = process_create_session_request(sc);
|
rv = process_create_session_request(psi);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case E_SCP_LIST_SESSIONS_REQUEST:
|
case E_SCP_LIST_SESSIONS_REQUEST:
|
||||||
rv = process_list_sessions_request(sc);
|
rv = process_list_sessions_request(psi);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case E_SCP_CLOSE_CONNECTION_REQUEST:
|
case E_SCP_CLOSE_CONNECTION_REQUEST:
|
||||||
rv = process_close_connection_request(sc);
|
rv = process_close_connection_request(psi);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -668,3 +556,4 @@ scp_process(struct sesman_con *sc)
|
|||||||
}
|
}
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@
|
|||||||
#ifndef SCP_PROCESS_H
|
#ifndef SCP_PROCESS_H
|
||||||
#define SCP_PROCESS_H
|
#define SCP_PROCESS_H
|
||||||
|
|
||||||
struct sesman_con;
|
struct pre_session_item;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@ -36,6 +36,6 @@ struct sesman_con;
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
scp_process(struct sesman_con *sc);
|
scp_process(struct pre_session_item *sc);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
334
sesman/sesman.c
334
sesman/sesman.c
@ -35,23 +35,26 @@
|
|||||||
|
|
||||||
#include "sesman_auth.h"
|
#include "sesman_auth.h"
|
||||||
#include "sesman_config.h"
|
#include "sesman_config.h"
|
||||||
|
#include "eicp.h"
|
||||||
|
#include "eicp_process.h"
|
||||||
|
#include "ercp.h"
|
||||||
|
#include "ercp_process.h"
|
||||||
|
#include "pre_session_list.h"
|
||||||
#include "session_list.h"
|
#include "session_list.h"
|
||||||
#include "lock_uds.h"
|
#include "lock_uds.h"
|
||||||
#include "os_calls.h"
|
#include "os_calls.h"
|
||||||
#include "scp.h"
|
#include "scp.h"
|
||||||
#include "scp_process.h"
|
#include "scp_process.h"
|
||||||
|
#include "sesexec_control.h"
|
||||||
#include "sig.h"
|
#include "sig.h"
|
||||||
#include "string_calls.h"
|
#include "string_calls.h"
|
||||||
#include "trans.h"
|
#include "trans.h"
|
||||||
#include "xrdp_configure_options.h"
|
#include "xrdp_configure_options.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Maximum number of short-lived connections to sesman
|
* Maximum number of pre-session items
|
||||||
*
|
|
||||||
* At the moment, all connections to sesman are short-lived. This may change
|
|
||||||
* in the future
|
|
||||||
*/
|
*/
|
||||||
#define MAX_SHORT_LIVED_CONNECTIONS 16
|
#define MAX_PRE_SESSION_ITEMS 16
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Define the mode of operation of the program
|
* Define the mode of operation of the program
|
||||||
@ -74,7 +77,6 @@ struct sesman_startup_params
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct config_sesman *g_cfg;
|
struct config_sesman *g_cfg;
|
||||||
unsigned char g_fixedkey[8] = { 23, 82, 107, 6, 35, 78, 88, 7 };
|
|
||||||
static tintptr g_term_event = 0;
|
static tintptr g_term_event = 0;
|
||||||
static tintptr g_sigchld_event = 0;
|
static tintptr g_sigchld_event = 0;
|
||||||
static tintptr g_reload_event = 0;
|
static tintptr g_reload_event = 0;
|
||||||
@ -114,68 +116,6 @@ static int nocase_matches(const char *candidate, ...)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Allocates a sesman_con struct
|
|
||||||
*
|
|
||||||
* @param trans Pointer to newly-allocated transport
|
|
||||||
* @return struct sesman_con pointer
|
|
||||||
*/
|
|
||||||
static struct sesman_con *
|
|
||||||
alloc_connection(struct trans *t)
|
|
||||||
{
|
|
||||||
struct sesman_con *result;
|
|
||||||
|
|
||||||
if ((result = g_new0(struct sesman_con, 1)) != NULL)
|
|
||||||
{
|
|
||||||
g_snprintf(result->peername, sizeof(result->peername), "%s", "unknown");
|
|
||||||
result->t = t;
|
|
||||||
result->auth_retry_count = g_cfg->sec.login_retry;
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Deletes a sesman_con struct, freeing resources
|
|
||||||
*
|
|
||||||
* After this call, the passed-in pointer is invalid and must not be
|
|
||||||
* referenced.
|
|
||||||
*
|
|
||||||
* Any auth_info struct found in the sesman_con is also deallocated.
|
|
||||||
*
|
|
||||||
* @param sc struct to de-allocate
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
delete_connection(struct sesman_con *sc)
|
|
||||||
{
|
|
||||||
if (sc != NULL)
|
|
||||||
{
|
|
||||||
trans_delete(sc->t);
|
|
||||||
if (sc->auth_info != NULL)
|
|
||||||
{
|
|
||||||
auth_end(sc->auth_info);
|
|
||||||
}
|
|
||||||
g_free(sc->username);
|
|
||||||
g_free(sc->ip_addr);
|
|
||||||
g_free(sc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
|
||||||
int
|
|
||||||
sesman_set_connection_peername(struct sesman_con *sc, const char *name)
|
|
||||||
{
|
|
||||||
int rv = 1;
|
|
||||||
|
|
||||||
if (sc != NULL && name != NULL)
|
|
||||||
{
|
|
||||||
g_snprintf(sc->peername, sizeof(sc->peername), "%s", name);
|
|
||||||
rv = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@ -301,40 +241,25 @@ static int sesman_listen_test(struct config_sesman *cfg)
|
|||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
int
|
int
|
||||||
sesman_close_all(unsigned int flags)
|
sesman_close_all(void)
|
||||||
{
|
{
|
||||||
int index;
|
|
||||||
struct sesman_con *sc;
|
|
||||||
|
|
||||||
LOG_DEVEL(LOG_LEVEL_TRACE, "sesman_close_all:");
|
LOG_DEVEL(LOG_LEVEL_TRACE, "sesman_close_all:");
|
||||||
|
|
||||||
|
pre_session_list_cleanup();
|
||||||
|
session_list_cleanup();
|
||||||
|
|
||||||
|
g_delete_wait_obj(g_reload_event);
|
||||||
|
g_delete_wait_obj(g_sigchld_event);
|
||||||
|
g_delete_wait_obj(g_term_event);
|
||||||
|
|
||||||
sesman_delete_listening_transport();
|
sesman_delete_listening_transport();
|
||||||
for (index = 0; index < g_con_list->count; index++)
|
|
||||||
{
|
|
||||||
sc = (struct sesman_con *) list_get_item(g_con_list, index);
|
|
||||||
if (sc != NULL && (flags & SCA_CLOSE_AUTH_INFO) == 0)
|
|
||||||
{
|
|
||||||
// Prevent delete_connection() closing the auth_info down
|
|
||||||
sc->auth_info = NULL;
|
|
||||||
}
|
|
||||||
delete_connection(sc);
|
|
||||||
}
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
void
|
int
|
||||||
sesman_delete_wait_objects(void)
|
sesman_scp_data_in(struct trans *self)
|
||||||
{
|
|
||||||
g_delete_wait_obj(g_reload_event);
|
|
||||||
g_delete_wait_obj(g_sigchld_event);
|
|
||||||
g_delete_wait_obj(g_term_event);
|
|
||||||
}
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
static int
|
|
||||||
sesman_data_in(struct trans *self)
|
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
int available;
|
int available;
|
||||||
@ -343,8 +268,10 @@ sesman_data_in(struct trans *self)
|
|||||||
|
|
||||||
if (rv == 0 && available)
|
if (rv == 0 && available)
|
||||||
{
|
{
|
||||||
struct sesman_con *sc = (struct sesman_con *)self->callback_data;
|
struct pre_session_item *psi;
|
||||||
if ((rv = scp_process(sc)) != 0)
|
psi = (struct pre_session_item *)self->callback_data;
|
||||||
|
|
||||||
|
if ((rv = scp_process(psi)) != 0)
|
||||||
{
|
{
|
||||||
LOG(LOG_LEVEL_ERROR, "sesman_data_in: scp_process_msg failed");
|
LOG(LOG_LEVEL_ERROR, "sesman_data_in: scp_process_msg failed");
|
||||||
}
|
}
|
||||||
@ -358,30 +285,79 @@ sesman_data_in(struct trans *self)
|
|||||||
static int
|
static int
|
||||||
sesman_listen_conn_in(struct trans *self, struct trans *new_self)
|
sesman_listen_conn_in(struct trans *self, struct trans *new_self)
|
||||||
{
|
{
|
||||||
struct sesman_con *sc;
|
struct pre_session_item *psi;
|
||||||
if (g_con_list->count >= MAX_SHORT_LIVED_CONNECTIONS)
|
if (pre_session_list_get_count() >= MAX_PRE_SESSION_ITEMS)
|
||||||
{
|
{
|
||||||
LOG(LOG_LEVEL_ERROR, "sesman_data_in: error, too many "
|
LOG(LOG_LEVEL_ERROR, "sesman_listen_conn_in: error, too many "
|
||||||
"connections, rejecting");
|
"connections, rejecting");
|
||||||
trans_delete(new_self);
|
trans_delete(new_self);
|
||||||
}
|
}
|
||||||
else if ((sc = alloc_connection(new_self)) == NULL ||
|
else if ((psi = pre_session_list_new()) == NULL)
|
||||||
scp_init_trans(new_self) != 0)
|
|
||||||
{
|
{
|
||||||
LOG(LOG_LEVEL_ERROR, "sesman_data_in: No memory to allocate "
|
LOG(LOG_LEVEL_ERROR, "sesman_data_in: No memory to allocate "
|
||||||
"new connection");
|
"new connection");
|
||||||
delete_connection(sc);
|
trans_delete(new_self);
|
||||||
|
}
|
||||||
|
else if (scp_init_trans(new_self) != 0)
|
||||||
|
{
|
||||||
|
LOG(LOG_LEVEL_ERROR, "sesman_data_in: Can't init SCP connection");
|
||||||
|
trans_delete(new_self);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
new_self->callback_data = (void *)sc;
|
new_self->callback_data = (void *)psi;
|
||||||
new_self->trans_data_in = sesman_data_in;
|
new_self->trans_data_in = sesman_scp_data_in;
|
||||||
list_add_item(g_con_list, (intptr_t) sc);
|
psi->client_trans = new_self;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
int
|
||||||
|
sesman_eicp_data_in(struct trans *self)
|
||||||
|
{
|
||||||
|
int rv;
|
||||||
|
int available;
|
||||||
|
|
||||||
|
rv = eicp_msg_in_check_available(self, &available);
|
||||||
|
|
||||||
|
if (rv == 0 && available)
|
||||||
|
{
|
||||||
|
struct pre_session_item *psi;
|
||||||
|
psi = (struct pre_session_item *)self->callback_data;
|
||||||
|
if ((rv = eicp_process(psi)) != 0)
|
||||||
|
{
|
||||||
|
LOG(LOG_LEVEL_ERROR, "sesman_eicp_data_in: eicp_process_msg failed");
|
||||||
|
}
|
||||||
|
eicp_msg_in_reset(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
int
|
||||||
|
sesman_ercp_data_in(struct trans *self)
|
||||||
|
{
|
||||||
|
int rv;
|
||||||
|
int available;
|
||||||
|
|
||||||
|
rv = ercp_msg_in_check_available(self, &available);
|
||||||
|
|
||||||
|
if (rv == 0 && available)
|
||||||
|
{
|
||||||
|
struct session_item *si = (struct session_item *)self->callback_data;
|
||||||
|
if ((rv = ercp_process(si)) != 0)
|
||||||
|
{
|
||||||
|
LOG(LOG_LEVEL_ERROR, "sesman_ercp_data_in: ercp_process_msg failed");
|
||||||
|
}
|
||||||
|
ercp_msg_in_reset(self);
|
||||||
|
}
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
/**
|
/**
|
||||||
* Informs the main loop a termination signal has been received
|
* Informs the main loop a termination signal has been received
|
||||||
@ -396,9 +372,21 @@ set_term_event(int sig)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/* No-op signal handler.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
sig_no_op(int sig)
|
||||||
|
{
|
||||||
|
/* no-op */
|
||||||
|
}
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
/**
|
/**
|
||||||
* Informs the main loop a SIGCHLD has been received
|
* Catch a SIGCHLD and ignore the main loop
|
||||||
|
*
|
||||||
|
* In theory we could use waitpid() in the signal handler, but that
|
||||||
|
* would prevent us adding any logging
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
set_sigchld_event(int sig)
|
set_sigchld_event(int sig)
|
||||||
@ -438,7 +426,7 @@ sesman_delete_listening_transport(void)
|
|||||||
}
|
}
|
||||||
g_list_trans = NULL;
|
g_list_trans = NULL;
|
||||||
|
|
||||||
unlock_uds(g_list_trans_lock);
|
unlock_uds(g_list_trans_lock); // Won't unlock anything for a child process
|
||||||
g_list_trans_lock = NULL;
|
g_list_trans_lock = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -489,6 +477,13 @@ sesman_create_listening_transport(const struct config_sesman *cfg)
|
|||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
int
|
||||||
|
sesman_is_term(void)
|
||||||
|
{
|
||||||
|
return g_is_wait_obj_set(g_term_event);
|
||||||
|
}
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@ -500,12 +495,7 @@ sesman_main_loop(void)
|
|||||||
{
|
{
|
||||||
int error;
|
int error;
|
||||||
int robjs_count;
|
int robjs_count;
|
||||||
int wobjs_count;
|
intptr_t robjs[1024];
|
||||||
int timeout;
|
|
||||||
int index;
|
|
||||||
intptr_t robjs[32];
|
|
||||||
intptr_t wobjs[32];
|
|
||||||
struct sesman_con *scon;
|
|
||||||
|
|
||||||
g_con_list = list_create();
|
g_con_list = list_create();
|
||||||
if (g_con_list == NULL)
|
if (g_con_list == NULL)
|
||||||
@ -525,47 +515,41 @@ sesman_main_loop(void)
|
|||||||
error = 0;
|
error = 0;
|
||||||
while (!error)
|
while (!error)
|
||||||
{
|
{
|
||||||
timeout = -1;
|
|
||||||
robjs_count = 0;
|
robjs_count = 0;
|
||||||
robjs[robjs_count++] = g_term_event;
|
robjs[robjs_count++] = g_term_event;
|
||||||
robjs[robjs_count++] = g_sigchld_event;
|
robjs[robjs_count++] = g_sigchld_event;
|
||||||
robjs[robjs_count++] = g_reload_event;
|
robjs[robjs_count++] = g_reload_event;
|
||||||
wobjs_count = 0;
|
|
||||||
for (index = 0; index < g_con_list->count; index++)
|
|
||||||
{
|
|
||||||
scon = (struct sesman_con *)list_get_item(g_con_list, index);
|
|
||||||
if (scon != NULL)
|
|
||||||
{
|
|
||||||
error = trans_get_wait_objs_rw(scon->t,
|
|
||||||
robjs, &robjs_count,
|
|
||||||
wobjs, &wobjs_count, &timeout);
|
|
||||||
if (error != 0)
|
|
||||||
{
|
|
||||||
LOG(LOG_LEVEL_ERROR, "sesman_main_loop: "
|
|
||||||
"trans_get_wait_objs_rw failed");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (error != 0)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (g_list_trans != NULL)
|
if (g_list_trans != NULL)
|
||||||
{
|
{
|
||||||
/* g_list_trans might be NULL on a reconfigure if sesman
|
/* g_list_trans might be NULL on a reconfigure if sesman
|
||||||
* is unable to listen again */
|
* is unable to listen again */
|
||||||
error = trans_get_wait_objs_rw(g_list_trans, robjs, &robjs_count,
|
error = trans_get_wait_objs(g_list_trans, robjs, &robjs_count);
|
||||||
wobjs, &wobjs_count, &timeout);
|
|
||||||
if (error != 0)
|
if (error != 0)
|
||||||
{
|
{
|
||||||
LOG(LOG_LEVEL_ERROR, "sesman_main_loop: "
|
LOG(LOG_LEVEL_ERROR, "sesman_main_loop: "
|
||||||
"trans_get_wait_objs_rw failed");
|
"trans_get_wait_objs failed");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (g_obj_wait(robjs, robjs_count, wobjs, wobjs_count, timeout) != 0)
|
error = pre_session_list_get_wait_objs(robjs, &robjs_count);
|
||||||
|
if (error != 0)
|
||||||
|
{
|
||||||
|
LOG(LOG_LEVEL_ERROR, "sesman_main_loop: "
|
||||||
|
"pre_session_list_get_wait_objs failed");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
error = session_list_get_wait_objs(robjs, &robjs_count);
|
||||||
|
if (error != 0)
|
||||||
|
{
|
||||||
|
LOG(LOG_LEVEL_ERROR, "sesman_main_loop: "
|
||||||
|
"session_list_get_wait_objs failed");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (g_obj_wait(robjs, robjs_count, NULL, 0, -1) != 0)
|
||||||
{
|
{
|
||||||
/* should not get here */
|
/* should not get here */
|
||||||
LOG(LOG_LEVEL_WARNING, "sesman_main_loop: "
|
LOG(LOG_LEVEL_WARNING, "sesman_main_loop: "
|
||||||
@ -580,10 +564,14 @@ sesman_main_loop(void)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (g_is_wait_obj_set(g_sigchld_event)) /* A child has exited */
|
if (g_is_wait_obj_set(g_sigchld_event)) /* term */
|
||||||
{
|
{
|
||||||
g_reset_wait_obj(g_sigchld_event);
|
g_reset_wait_obj(g_sigchld_event);
|
||||||
sig_sesman_session_end();
|
// Prevent any zombies from hanging around
|
||||||
|
while (g_waitchild(NULL) > 0)
|
||||||
|
{
|
||||||
|
;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (g_is_wait_obj_set(g_reload_event)) /* We're asked to reload */
|
if (g_is_wait_obj_set(g_reload_event)) /* We're asked to reload */
|
||||||
@ -592,33 +580,6 @@ sesman_main_loop(void)
|
|||||||
sig_sesman_reload_cfg();
|
sig_sesman_reload_cfg();
|
||||||
}
|
}
|
||||||
|
|
||||||
index = 0;
|
|
||||||
while (index < g_con_list->count)
|
|
||||||
{
|
|
||||||
int remove_con = 0;
|
|
||||||
scon = (struct sesman_con *)list_get_item(g_con_list, index);
|
|
||||||
if (trans_check_wait_objs(scon->t) != 0)
|
|
||||||
{
|
|
||||||
LOG(LOG_LEVEL_ERROR, "sesman_main_loop: "
|
|
||||||
"trans_check_wait_objs failed, removing trans");
|
|
||||||
remove_con = 1;
|
|
||||||
}
|
|
||||||
else if (scon->close_requested)
|
|
||||||
{
|
|
||||||
remove_con = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (remove_con)
|
|
||||||
{
|
|
||||||
delete_connection(scon);
|
|
||||||
list_remove_item(g_con_list, index);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
++index;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (g_list_trans != NULL)
|
if (g_list_trans != NULL)
|
||||||
{
|
{
|
||||||
error = trans_check_wait_objs(g_list_trans);
|
error = trans_check_wait_objs(g_list_trans);
|
||||||
@ -629,11 +590,25 @@ sesman_main_loop(void)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
error = pre_session_list_check_wait_objs();
|
||||||
|
if (error != 0)
|
||||||
|
{
|
||||||
|
LOG(LOG_LEVEL_ERROR, "sesman_main_loop: "
|
||||||
|
"pre_session_list_check_wait_objs failed");
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
sesman_close_all(SCA_CLOSE_AUTH_INFO);
|
error = session_list_check_wait_objs();
|
||||||
list_delete(g_con_list);
|
if (error != 0)
|
||||||
return 0;
|
{
|
||||||
|
LOG(LOG_LEVEL_ERROR, "sesman_main_loop: "
|
||||||
|
"session_list_check_wait_objs failed");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
@ -642,7 +617,7 @@ print_version(void)
|
|||||||
{
|
{
|
||||||
g_writeln("xrdp-sesman %s", PACKAGE_VERSION);
|
g_writeln("xrdp-sesman %s", PACKAGE_VERSION);
|
||||||
g_writeln(" The xrdp session manager");
|
g_writeln(" The xrdp session manager");
|
||||||
g_writeln(" Copyright (C) 2004-2020 Jay Sorg, "
|
g_writeln(" Copyright (C) 2004-2023 Jay Sorg, "
|
||||||
"Neutrino Labs, and all contributors.");
|
"Neutrino Labs, and all contributors.");
|
||||||
g_writeln(" See https://github.com/neutrinolabs/xrdp for more information.");
|
g_writeln(" See https://github.com/neutrinolabs/xrdp for more information.");
|
||||||
g_writeln("%s", "");
|
g_writeln("%s", "");
|
||||||
@ -715,16 +690,14 @@ main(int argc, char **argv)
|
|||||||
enum logReturns log_error;
|
enum logReturns log_error;
|
||||||
char text[256];
|
char text[256];
|
||||||
char pid_file[256];
|
char pid_file[256];
|
||||||
char default_sesman_ini[256];
|
|
||||||
struct sesman_startup_params startup_params = {0};
|
struct sesman_startup_params startup_params = {0};
|
||||||
int errored_argc;
|
int errored_argc;
|
||||||
int daemon;
|
int daemon;
|
||||||
|
|
||||||
g_init("xrdp-sesman");
|
g_init("xrdp-sesman");
|
||||||
g_snprintf(pid_file, 255, "%s/xrdp-sesman.pid", XRDP_PID_PATH);
|
g_snprintf(pid_file, 255, "%s/xrdp-sesman.pid", XRDP_PID_PATH);
|
||||||
g_snprintf(default_sesman_ini, 255, "%s/sesman.ini", XRDP_CFG_PATH);
|
|
||||||
|
|
||||||
startup_params.sesman_ini = default_sesman_ini;
|
startup_params.sesman_ini = DEFAULT_SESMAN_INI;
|
||||||
|
|
||||||
errored_argc = sesman_process_params(argc, argv, &startup_params);
|
errored_argc = sesman_process_params(argc, argv, &startup_params);
|
||||||
if (errored_argc > 0)
|
if (errored_argc > 0)
|
||||||
@ -922,10 +895,11 @@ main(int argc, char **argv)
|
|||||||
g_snprintf(text, 255, "xrdp_sesman_%8.8x_reload", g_pid);
|
g_snprintf(text, 255, "xrdp_sesman_%8.8x_reload", g_pid);
|
||||||
g_reload_event = g_create_wait_obj(text);
|
g_reload_event = g_create_wait_obj(text);
|
||||||
|
|
||||||
g_signal_hang_up(set_reload_event); /* SIGHUP */
|
|
||||||
g_signal_user_interrupt(set_term_event); /* SIGINT */
|
g_signal_user_interrupt(set_term_event); /* SIGINT */
|
||||||
g_signal_terminate(set_term_event); /* SIGTERM */
|
g_signal_terminate(set_term_event); /* SIGTERM */
|
||||||
|
g_signal_pipe(sig_no_op); /* SIGPIPE */
|
||||||
g_signal_child_stop(set_sigchld_event); /* SIGCHLD */
|
g_signal_child_stop(set_sigchld_event); /* SIGCHLD */
|
||||||
|
g_signal_hang_up(set_reload_event); /* SIGHUP */
|
||||||
|
|
||||||
if (daemon)
|
if (daemon)
|
||||||
{
|
{
|
||||||
@ -967,11 +941,10 @@ main(int argc, char **argv)
|
|||||||
g_chmod_hex("/tmp/.X11-unix", 0x1777);
|
g_chmod_hex("/tmp/.X11-unix", 0x1777);
|
||||||
}
|
}
|
||||||
|
|
||||||
error = session_module_init();
|
if ((error = pre_session_list_init(MAX_PRE_SESSION_ITEMS)) == 0 &&
|
||||||
if (error == 0)
|
(error = session_list_init()) == 0)
|
||||||
{
|
{
|
||||||
error = sesman_main_loop();
|
error = sesman_main_loop();
|
||||||
session_module_cleanup();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* clean up PID file on exit */
|
/* clean up PID file on exit */
|
||||||
@ -980,12 +953,9 @@ main(int argc, char **argv)
|
|||||||
g_file_delete(pid_file);
|
g_file_delete(pid_file);
|
||||||
}
|
}
|
||||||
|
|
||||||
sesman_delete_wait_objects();
|
sesman_close_all();
|
||||||
|
|
||||||
if (!daemon)
|
|
||||||
{
|
|
||||||
log_end();
|
log_end();
|
||||||
}
|
|
||||||
|
|
||||||
config_free(g_cfg);
|
config_free(g_cfg);
|
||||||
g_deinit();
|
g_deinit();
|
||||||
|
@ -27,33 +27,11 @@
|
|||||||
#ifndef SESMAN_H
|
#ifndef SESMAN_H
|
||||||
#define SESMAN_H
|
#define SESMAN_H
|
||||||
|
|
||||||
/**
|
struct config_sesman;
|
||||||
* Type for managing sesman connections from xrdp (etc)
|
struct trans;
|
||||||
*/
|
|
||||||
struct sesman_con
|
|
||||||
{
|
|
||||||
struct trans *t;
|
|
||||||
char peername[15 + 1]; /* Name of peer, if known, for logging */
|
|
||||||
int close_requested; /* Set to close the connection normally */
|
|
||||||
unsigned int auth_retry_count;
|
|
||||||
struct auth_info *auth_info; /* non-NULL for an authenticated connection */
|
|
||||||
int uid; /* User */
|
|
||||||
char *username; /* Username from UID (at time of logon) */
|
|
||||||
char *ip_addr; /* Connecting IP address */
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Globals */
|
/* Globals */
|
||||||
extern struct config_sesman *g_cfg;
|
extern struct config_sesman *g_cfg;
|
||||||
extern unsigned char g_fixedkey[8];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the peername of a connection
|
|
||||||
*
|
|
||||||
* @param name Name to set
|
|
||||||
* @result 0 for success
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
sesman_set_connection_peername(struct sesman_con *sc, const char *name);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Close all file descriptors used by sesman.
|
* Close all file descriptors used by sesman.
|
||||||
@ -61,24 +39,13 @@ sesman_set_connection_peername(struct sesman_con *sc, const char *name);
|
|||||||
* This is generally used after forking, to make sure the
|
* This is generally used after forking, to make sure the
|
||||||
* file descriptors used by the main process are not disturbed
|
* file descriptors used by the main process are not disturbed
|
||||||
*
|
*
|
||||||
* This call will also release all trans and SCP_SESSION objects
|
* This call will also :-
|
||||||
* held by sesman
|
* - release all trans objects held by sesman
|
||||||
*
|
* - Delete sesman wait objects
|
||||||
* @param flags Set SCA_CLOSE_AUTH_INFO to close any open auth_info
|
* - Call sesman_delete_listening_transport()
|
||||||
* objects. By default these are not cleared, and should
|
|
||||||
* only be done so when exiting sesman.
|
|
||||||
*/
|
*/
|
||||||
#define SCA_CLOSE_AUTH_INFO (1<<0)
|
|
||||||
int
|
int
|
||||||
sesman_close_all(unsigned int flags);
|
sesman_close_all(void);
|
||||||
|
|
||||||
/**
|
|
||||||
* Delete sesman wait objects.
|
|
||||||
*
|
|
||||||
* Call after forking so we don't break sesman's wait objects
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
sesman_delete_wait_objects(void);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Remove the listening transport
|
* Remove the listening transport
|
||||||
@ -96,4 +63,28 @@ sesman_delete_listening_transport(void);
|
|||||||
int
|
int
|
||||||
sesman_create_listening_transport(const struct config_sesman *cfg);
|
sesman_create_listening_transport(const struct config_sesman *cfg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback to process incoming SCP data
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
sesman_scp_data_in(struct trans *self);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback to process incoming EICP data
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
sesman_eicp_data_in(struct trans *self);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Callback to process incoming ERCP data
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
sesman_ercp_data_in(struct trans *self);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check for termination
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
sesman_is_term(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -33,11 +33,16 @@
|
|||||||
#include "config_ac.h"
|
#include "config_ac.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_SYS_PRCTL_H
|
||||||
|
#include <sys/prctl.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "arch.h"
|
#include "arch.h"
|
||||||
#include "session_list.h"
|
#include "session_list.h"
|
||||||
|
#include "trans.h"
|
||||||
|
|
||||||
#include "sesman_auth.h"
|
|
||||||
#include "sesman_config.h"
|
#include "sesman_config.h"
|
||||||
|
#include "list.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "os_calls.h"
|
#include "os_calls.h"
|
||||||
#include "sesman.h"
|
#include "sesman.h"
|
||||||
@ -48,12 +53,12 @@ static struct list *g_session_list = NULL;
|
|||||||
|
|
||||||
#define SESSION_IN_USE(si) \
|
#define SESSION_IN_USE(si) \
|
||||||
((si) != NULL && \
|
((si) != NULL && \
|
||||||
(si)->display >= 0 && \
|
(si)->sesexec_trans != NULL && \
|
||||||
(si)->pid > 0)
|
(si)->sesexec_trans->status == TRANS_STATUS_UP)
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
int
|
int
|
||||||
session_module_init(void)
|
session_list_init(void)
|
||||||
{
|
{
|
||||||
int rv = 1;
|
int rv = 1;
|
||||||
if (g_session_list == NULL)
|
if (g_session_list == NULL)
|
||||||
@ -88,9 +93,9 @@ free_session(struct session_item *si)
|
|||||||
{
|
{
|
||||||
if (si != NULL)
|
if (si != NULL)
|
||||||
{
|
{
|
||||||
if (si->auth_info != NULL)
|
if (si->sesexec_trans != NULL)
|
||||||
{
|
{
|
||||||
auth_end(si->auth_info);
|
trans_delete(si->sesexec_trans);
|
||||||
}
|
}
|
||||||
g_free(si);
|
g_free(si);
|
||||||
}
|
}
|
||||||
@ -98,7 +103,7 @@ free_session(struct session_item *si)
|
|||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
void
|
void
|
||||||
session_module_cleanup(void)
|
session_list_cleanup(void)
|
||||||
{
|
{
|
||||||
if (g_session_list != NULL)
|
if (g_session_list != NULL)
|
||||||
{
|
{
|
||||||
@ -123,13 +128,12 @@ session_list_get_count(void)
|
|||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
struct session_item *
|
struct session_item *
|
||||||
session_new(void)
|
session_list_new(void)
|
||||||
{
|
{
|
||||||
struct session_item *result = g_new0(struct session_item, 1);
|
struct session_item *result = g_new0(struct session_item, 1);
|
||||||
if (result != NULL)
|
if (result != NULL)
|
||||||
{
|
{
|
||||||
result->pid = -1;
|
result->state = E_SESSION_STARTING;
|
||||||
result->display = -1;
|
|
||||||
if (!list_add_item(g_session_list, (tintptr)result))
|
if (!list_add_item(g_session_list, (tintptr)result))
|
||||||
{
|
{
|
||||||
g_free(result);
|
g_free(result);
|
||||||
@ -401,7 +405,7 @@ session_list_get_bydata(uid_t uid,
|
|||||||
si,
|
si,
|
||||||
SCP_SESSION_TYPE_TO_STR(si->type),
|
SCP_SESSION_TYPE_TO_STR(si->type),
|
||||||
si->uid, si->bpp,
|
si->uid, si->bpp,
|
||||||
si->width, si->height,
|
si->start_width, si->start_height,
|
||||||
si->start_ip_addr);
|
si->start_ip_addr);
|
||||||
|
|
||||||
if (si->type != type)
|
if (si->type != type)
|
||||||
@ -410,7 +414,7 @@ session_list_get_bydata(uid_t uid,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((policy & SESMAN_CFG_SESS_POLICY_U) && (int)uid != si->uid)
|
if ((policy & SESMAN_CFG_SESS_POLICY_U) && uid != si->uid)
|
||||||
{
|
{
|
||||||
LOG(LOG_LEVEL_DEBUG,
|
LOG(LOG_LEVEL_DEBUG,
|
||||||
"%s: UID doesn't match for 'U' policy", __func__);
|
"%s: UID doesn't match for 'U' policy", __func__);
|
||||||
@ -425,7 +429,8 @@ session_list_get_bydata(uid_t uid,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ((policy & SESMAN_CFG_SESS_POLICY_D) &&
|
if ((policy & SESMAN_CFG_SESS_POLICY_D) &&
|
||||||
(si->width != width || si->height != height))
|
(si->start_width != width ||
|
||||||
|
si->start_height != height))
|
||||||
{
|
{
|
||||||
LOG(LOG_LEVEL_DEBUG,
|
LOG(LOG_LEVEL_DEBUG,
|
||||||
"%s: Dimensions don't match for 'D' policy", __func__);
|
"%s: Dimensions don't match for 'D' policy", __func__);
|
||||||
@ -449,98 +454,9 @@ session_list_get_bydata(uid_t uid,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
/**
|
|
||||||
* Convert a UID to a username
|
|
||||||
*
|
|
||||||
* @param uid UID
|
|
||||||
* @param uname pointer to output buffer
|
|
||||||
* @param uname_len Length of output buffer
|
|
||||||
* @return 0 for success.
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
username_from_uid(int uid, char *uname, int uname_len)
|
|
||||||
{
|
|
||||||
char *ustr;
|
|
||||||
int rv = g_getuser_info_by_uid(uid, &ustr, NULL, NULL, NULL, NULL);
|
|
||||||
|
|
||||||
if (rv == 0)
|
|
||||||
{
|
|
||||||
g_snprintf(uname, uname_len, "%s", ustr);
|
|
||||||
g_free(ustr);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
g_snprintf(uname, uname_len, "<unknown>");
|
|
||||||
}
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
enum session_kill_status
|
|
||||||
session_list_kill(int pid)
|
|
||||||
{
|
|
||||||
int i = 0;
|
|
||||||
enum session_kill_status status = SESMAN_SESSION_KILL_NOTFOUND;
|
|
||||||
|
|
||||||
while (i < g_session_list->count)
|
|
||||||
{
|
|
||||||
struct session_item *si;
|
|
||||||
si = (struct session_item *)list_get_item(g_session_list, i);
|
|
||||||
if (si->pid == pid)
|
|
||||||
{
|
|
||||||
status = SESMAN_SESSION_KILL_OK;
|
|
||||||
if (pid > 0)
|
|
||||||
{
|
|
||||||
char username[256];
|
|
||||||
username_from_uid(si->uid, username, sizeof(username));
|
|
||||||
|
|
||||||
/* Log the deletion */
|
|
||||||
if (si->auth_info != NULL)
|
|
||||||
{
|
|
||||||
LOG(LOG_LEVEL_INFO,
|
|
||||||
"Calling auth_end for pid %d from pid %d",
|
|
||||||
pid, g_getpid());
|
|
||||||
}
|
|
||||||
|
|
||||||
LOG(LOG_LEVEL_INFO,
|
|
||||||
"++ terminated session: UID %d (%s), display :%d.0, "
|
|
||||||
"session_pid %d, ip %s",
|
|
||||||
si->uid, username, si->display,
|
|
||||||
si->pid, si->start_ip_addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
free_session(si);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
++i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
void
|
|
||||||
session_list_sigkill_all(void)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0 ; i < g_session_list->count ; ++i)
|
|
||||||
{
|
|
||||||
struct session_item *si;
|
|
||||||
si = (struct session_item *)list_get_item(g_session_list, i);
|
|
||||||
if (si->pid > 0)
|
|
||||||
{
|
|
||||||
g_sigterm(si->pid);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
struct scp_session_info *
|
struct scp_session_info *
|
||||||
session_list_get_byuid(int uid, unsigned int *cnt, unsigned char flags)
|
session_list_get_byuid(uid_t uid, unsigned int *cnt, unsigned int flags)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
struct scp_session_info *sess;
|
struct scp_session_info *sess;
|
||||||
@ -549,11 +465,13 @@ session_list_get_byuid(int uid, unsigned int *cnt, unsigned char flags)
|
|||||||
|
|
||||||
count = 0;
|
count = 0;
|
||||||
|
|
||||||
|
LOG(LOG_LEVEL_DEBUG, "searching for session by UID: %d", uid);
|
||||||
|
|
||||||
for (i = 0 ; i < g_session_list->count ; ++i)
|
for (i = 0 ; i < g_session_list->count ; ++i)
|
||||||
{
|
{
|
||||||
const struct session_item *si;
|
const struct session_item *si;
|
||||||
si = (const struct session_item *)list_get_item(g_session_list, i);
|
si = (const struct session_item *)list_get_item(g_session_list, i);
|
||||||
if (SESSION_IN_USE(si) && uid == si->uid && (si->status & flags) != 0)
|
if (SESSION_IN_USE(si) && uid == si->uid)
|
||||||
{
|
{
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
@ -579,13 +497,14 @@ session_list_get_byuid(int uid, unsigned int *cnt, unsigned char flags)
|
|||||||
{
|
{
|
||||||
const struct session_item *si;
|
const struct session_item *si;
|
||||||
si = (const struct session_item *)list_get_item(g_session_list, i);
|
si = (const struct session_item *)list_get_item(g_session_list, i);
|
||||||
if (SESSION_IN_USE(si) && uid == si->uid && (si->status & flags) != 0)
|
|
||||||
|
if (SESSION_IN_USE(si) && uid == si->uid)
|
||||||
{
|
{
|
||||||
(sess[index]).sid = si->pid;
|
(sess[index]).sid = si->sesexec_pid;
|
||||||
(sess[index]).display = si->display;
|
(sess[index]).display = si->display;
|
||||||
(sess[index]).type = si->type;
|
(sess[index]).type = si->type;
|
||||||
(sess[index]).height = si->height;
|
(sess[index]).height = si->start_height;
|
||||||
(sess[index]).width = si->width;
|
(sess[index]).width = si->start_width;
|
||||||
(sess[index]).bpp = si->bpp;
|
(sess[index]).bpp = si->bpp;
|
||||||
(sess[index]).start_time = si->start_time;
|
(sess[index]).start_time = si->start_time;
|
||||||
(sess[index]).uid = si->uid;
|
(sess[index]).uid = si->uid;
|
||||||
@ -621,3 +540,56 @@ free_session_info_list(struct scp_session_info *sesslist, unsigned int cnt)
|
|||||||
|
|
||||||
g_free(sesslist);
|
g_free(sesslist);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
int
|
||||||
|
session_list_get_wait_objs(tbus robjs[], int *robjs_count)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0 ; i < g_session_list->count; ++i)
|
||||||
|
{
|
||||||
|
const struct session_item *si;
|
||||||
|
si = (const struct session_item *)list_get_item(g_session_list, i);
|
||||||
|
if (SESSION_IN_USE(si))
|
||||||
|
{
|
||||||
|
robjs[(*robjs_count)++] = si->sesexec_trans->sck;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
int
|
||||||
|
session_list_check_wait_objs(void)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0 ; i < g_session_list->count; ++i)
|
||||||
|
{
|
||||||
|
struct session_item *si;
|
||||||
|
si = (struct session_item *)list_get_item(g_session_list, i);
|
||||||
|
if (SESSION_IN_USE(si))
|
||||||
|
{
|
||||||
|
if (trans_check_wait_objs(si->sesexec_trans) != 0)
|
||||||
|
{
|
||||||
|
LOG(LOG_LEVEL_ERROR, "sesman_check_wait_objs: "
|
||||||
|
"trans_check_wait_objs failed, removing trans");
|
||||||
|
si->sesexec_trans->status = TRANS_STATUS_DOWN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SESSION_IN_USE(si))
|
||||||
|
{
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
free_session(si);
|
||||||
|
list_remove_item(g_session_list, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/**
|
/**
|
||||||
* xrdp: A Remote Desktop Protocol server.
|
* xrdp: A Remote Desktop Protocol server.
|
||||||
*
|
*
|
||||||
* Copyright (C) Jay Sorg 2004-2013
|
* Copyright (C) Jay Sorg 2004-2023
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@ -28,53 +28,44 @@
|
|||||||
#ifndef SESSION_LIST_H
|
#ifndef SESSION_LIST_H
|
||||||
#define SESSION_LIST_H
|
#define SESSION_LIST_H
|
||||||
|
|
||||||
#include <time.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
#include "guid.h"
|
#include "guid.h"
|
||||||
#include "scp_application_types.h"
|
#include "scp_application_types.h"
|
||||||
#include "xrdp_constants.h"
|
#include "xrdp_constants.h"
|
||||||
|
|
||||||
struct session_parameters;
|
enum session_state
|
||||||
|
|
||||||
#define SESMAN_SESSION_STATUS_ACTIVE 0x01
|
|
||||||
#define SESMAN_SESSION_STATUS_IDLE 0x02
|
|
||||||
#define SESMAN_SESSION_STATUS_DISCONNECTED 0x04
|
|
||||||
/* future expansion
|
|
||||||
#define SESMAN_SESSION_STATUS_REMCONTROL 0x08
|
|
||||||
*/
|
|
||||||
#define SESMAN_SESSION_STATUS_ALL 0xFF
|
|
||||||
|
|
||||||
enum session_kill_status
|
|
||||||
{
|
{
|
||||||
SESMAN_SESSION_KILL_OK = 0,
|
/**
|
||||||
SESMAN_SESSION_KILL_NOTFOUND
|
* Session definition is little more than a sesexec process. We're
|
||||||
|
* waiting for more details of the session from sesexec */
|
||||||
|
E_SESSION_STARTING,
|
||||||
|
/** Session is fully active */
|
||||||
|
E_SESSION_RUNNING
|
||||||
};
|
};
|
||||||
|
|
||||||
struct scp_session_info;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Object describing a session
|
* Object describing a session
|
||||||
|
*
|
||||||
|
* Unless otherwide noted, fields are only valid if
|
||||||
|
* the status is E_SESSION_RUNNING
|
||||||
*/
|
*/
|
||||||
struct session_item
|
struct session_item
|
||||||
{
|
{
|
||||||
int uid; /* UID of session */
|
enum session_state state;
|
||||||
int pid; /* pid of sesman waiting for wm to end */
|
struct trans *sesexec_trans; // trans for sesexec process. Always valid.
|
||||||
|
pid_t sesexec_pid; // pid for sesexec process. Always valid
|
||||||
|
/**
|
||||||
|
* May be valid if known when the session is starting, otherwise -1 */
|
||||||
int display;
|
int display;
|
||||||
int width;
|
uid_t uid;
|
||||||
int height;
|
|
||||||
int bpp;
|
|
||||||
struct auth_info *auth_info;
|
|
||||||
|
|
||||||
/* status info */
|
|
||||||
unsigned char status;
|
|
||||||
enum scp_session_type type;
|
enum scp_session_type type;
|
||||||
|
unsigned short start_width;
|
||||||
/* time data */
|
unsigned short start_height;
|
||||||
time_t start_time;
|
unsigned char bpp;
|
||||||
// struct session_date disconnect_time; // Currently unused
|
|
||||||
// struct session_date idle_time; // Currently unused
|
|
||||||
char start_ip_addr[MAX_PEER_ADDRSTRLEN];
|
|
||||||
struct guid guid;
|
struct guid guid;
|
||||||
|
char start_ip_addr[MAX_PEER_ADDRSTRLEN];
|
||||||
|
time_t start_time;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -84,13 +75,13 @@ struct session_item
|
|||||||
* Errors are logged
|
* Errors are logged
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
session_module_init(void);
|
session_list_init(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clean up the module on program exit
|
* Clean up the module on program exit
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
session_module_cleanup(void);
|
session_list_cleanup(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the number of sessions currently active
|
* Returns the number of sessions currently active
|
||||||
@ -100,24 +91,27 @@ unsigned int
|
|||||||
session_list_get_count(void);
|
session_list_get_count(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allocates a new session
|
* Allocates a new session on the list
|
||||||
*
|
*
|
||||||
* The PID and display for the allocated session will be -1 and all other
|
* state will be E_SESSION_STARTING. Other data must be filled in by
|
||||||
* fields will be blank
|
* the caller as appropriate.
|
||||||
*
|
*
|
||||||
* @return pointer to new session object or NULL for no memory
|
* @return pointer to new session object or NULL for no memory
|
||||||
*
|
*
|
||||||
* After allocating the session successfully, you must initialise the
|
* After allocating the session, you must initialise the sesexec_trans field
|
||||||
* PID and display fields with valid numbers.
|
* with a valid transport.
|
||||||
*
|
*
|
||||||
* If you allocate a session and want to remove it due to other problems,
|
* The session is removed by session_check_wait_objs() when the transport
|
||||||
* use session_kill_pid(-1);
|
* goes down (or wasn't allocated in the first place).
|
||||||
*/
|
*/
|
||||||
struct session_item *
|
struct session_item *
|
||||||
session_new(void);
|
session_list_new(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the next available display
|
* Get the next available display
|
||||||
|
*
|
||||||
|
* The display isn't reserved until the caller has allocated a new session
|
||||||
|
* (with session_list_new()) and put the new display in it.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
session_list_get_available_display(void);
|
session_list_get_available_display(void);
|
||||||
@ -136,35 +130,18 @@ session_list_get_bydata(uid_t uid,
|
|||||||
unsigned char bpp,
|
unsigned char bpp,
|
||||||
const char *ip_addr);
|
const char *ip_addr);
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @brief kills a session
|
|
||||||
* @param pid the pid of the session to be killed
|
|
||||||
* @return
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
enum session_kill_status
|
|
||||||
session_list_kill(int pid);
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @brief sends sigkill to all sessions
|
|
||||||
* @return
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
session_list_sigkill_all(void);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief retrieves session descriptions
|
* @brief retrieves session descriptions
|
||||||
* @param UID the UID for the descriptions
|
* @param uid the UID for the descriptions
|
||||||
|
* @param[out] cnt The number of sessions returned
|
||||||
|
* @param flags Future expansion
|
||||||
* @return A block of session descriptions
|
* @return A block of session descriptions
|
||||||
*
|
*
|
||||||
* Pass the return result to free_session_info_list() after use
|
* Pass the return result to free_session_info_list() after use
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
struct scp_session_info *
|
struct scp_session_info *
|
||||||
session_list_get_byuid(int uid, unsigned int *cnt, unsigned char flags);
|
session_list_get_byuid(uid_t uid, unsigned int *cnt, unsigned int flags);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@ -175,4 +152,21 @@ session_list_get_byuid(int uid, unsigned int *cnt, unsigned char flags);
|
|||||||
void
|
void
|
||||||
free_session_info_list(struct scp_session_info *sesslist, unsigned int cnt);
|
free_session_info_list(struct scp_session_info *sesslist, unsigned int cnt);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the wait objs for the session list module
|
||||||
|
* @param @robjs Objects array to update
|
||||||
|
* @param robjs_count Elements in robjs (by reference)
|
||||||
|
* @return 0 for success
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
session_list_get_wait_objs(tbus robjs[], int *robjs_count);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Check the wait objs for the session list module
|
||||||
|
* @return 0 for success
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
session_list_check_wait_objs(void);
|
||||||
|
|
||||||
#endif // SESSION_LIST_H
|
#endif // SESSION_LIST_H
|
||||||
|
21
sesman/sig.c
21
sesman/sig.c
@ -95,24 +95,3 @@ sig_sesman_reload_cfg(void)
|
|||||||
|
|
||||||
LOG(LOG_LEVEL_INFO, "configuration reloaded, log subsystem restarted");
|
LOG(LOG_LEVEL_INFO, "configuration reloaded, log subsystem restarted");
|
||||||
}
|
}
|
||||||
|
|
||||||
/******************************************************************************/
|
|
||||||
void
|
|
||||||
sig_sesman_session_end(void)
|
|
||||||
{
|
|
||||||
int pid;
|
|
||||||
|
|
||||||
LOG(LOG_LEVEL_DEBUG, "receiving SIGCHLD");
|
|
||||||
do
|
|
||||||
{
|
|
||||||
pid = g_waitchild(NULL);
|
|
||||||
|
|
||||||
if (pid > 0)
|
|
||||||
{
|
|
||||||
LOG(LOG_LEVEL_INFO, "Process %d has exited", pid);
|
|
||||||
|
|
||||||
session_list_kill(pid);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
while (pid > 0);
|
|
||||||
}
|
|
||||||
|
@ -35,12 +35,4 @@
|
|||||||
void
|
void
|
||||||
sig_sesman_reload_cfg(void);
|
sig_sesman_reload_cfg(void);
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @brief SIGCHLD handling code
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
sig_sesman_session_end(void);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user