Update sesman authentication processing
Update sesman to cope with separate authentication/authorization (AA) and command processing. Also, internally users are now tracked by UID rather thn username. This addresses a problem found by some users using federated naming services (e.g. Active Directory) where the same user can be referred to in more than one way. See https://github.com/neutrinolabs/xrdp/issues/1823 The separation of AA in this way allows for multiple attempts to be made on one connection to get a password right. This addresses MaxLoginRetry not working (https://github.com/neutrinolabs/xrdp/issues/1739)
This commit is contained in:
parent
c5b6479985
commit
fd99653957
31
sesman/env.c
31
sesman/env.c
@ -92,27 +92,27 @@ env_check_password_file(const char *filename, const char *passwd)
|
||||
/******************************************************************************/
|
||||
/* its the responsibility of the caller to free passwd_file */
|
||||
int
|
||||
env_set_user(const char *username, char **passwd_file, int display,
|
||||
env_set_user(int uid, char **passwd_file, int display,
|
||||
const struct list *env_names, const struct list *env_values)
|
||||
{
|
||||
int error;
|
||||
int pw_uid;
|
||||
int pw_gid;
|
||||
int uid;
|
||||
int index;
|
||||
int len;
|
||||
char *name;
|
||||
char *value;
|
||||
char *pw_username;
|
||||
char *pw_shell;
|
||||
char *pw_dir;
|
||||
char text[256];
|
||||
char hostname[256];
|
||||
|
||||
pw_username = 0;
|
||||
pw_shell = 0;
|
||||
pw_dir = 0;
|
||||
|
||||
error = g_getuser_info_by_name(username, &pw_uid, &pw_gid, &pw_shell,
|
||||
&pw_dir, 0);
|
||||
error = g_getuser_info_by_uid(uid, &pw_username, &pw_gid, &pw_shell,
|
||||
&pw_dir, 0);
|
||||
|
||||
if (error == 0)
|
||||
{
|
||||
@ -124,7 +124,6 @@ env_set_user(const char *username, char **passwd_file, int display,
|
||||
|
||||
if (error == 0)
|
||||
{
|
||||
uid = pw_uid;
|
||||
error = g_setuid(uid);
|
||||
}
|
||||
|
||||
@ -135,8 +134,8 @@ env_set_user(const char *username, char **passwd_file, int display,
|
||||
g_clearenv();
|
||||
g_setenv("SHELL", pw_shell, 1);
|
||||
g_setenv("PATH", "/sbin:/bin:/usr/bin:/usr/local/bin", 1);
|
||||
g_setenv("USER", username, 1);
|
||||
g_setenv("LOGNAME", username, 1);
|
||||
g_setenv("USER", pw_username, 1);
|
||||
g_setenv("LOGNAME", pw_username, 1);
|
||||
g_sprintf(text, "%d", uid);
|
||||
g_setenv("UID", text, 1);
|
||||
g_setenv("HOME", pw_dir, 1);
|
||||
@ -182,14 +181,14 @@ env_set_user(const char *username, char **passwd_file, int display,
|
||||
}
|
||||
|
||||
len = g_snprintf(NULL, 0, "%s/.vnc/sesman_passwd-%s@%s:%d",
|
||||
pw_dir, username, hostname, display);
|
||||
pw_dir, pw_username, hostname, display);
|
||||
|
||||
*passwd_file = (char *) g_malloc(len + 1, 1);
|
||||
if (*passwd_file != NULL)
|
||||
{
|
||||
/* Try legacy names first, remove if found */
|
||||
g_sprintf(*passwd_file, "%s/.vnc/sesman_%s_passwd:%d",
|
||||
pw_dir, username, display);
|
||||
pw_dir, pw_username, display);
|
||||
if (g_file_exist(*passwd_file))
|
||||
{
|
||||
LOG(LOG_LEVEL_WARNING, "Removing old "
|
||||
@ -197,7 +196,7 @@ env_set_user(const char *username, char **passwd_file, int display,
|
||||
g_file_delete(*passwd_file);
|
||||
}
|
||||
g_sprintf(*passwd_file, "%s/.vnc/sesman_%s_passwd",
|
||||
pw_dir, username);
|
||||
pw_dir, pw_username);
|
||||
if (g_file_exist(*passwd_file))
|
||||
{
|
||||
LOG(LOG_LEVEL_WARNING, "Removing insecure "
|
||||
@ -205,18 +204,18 @@ env_set_user(const char *username, char **passwd_file, int display,
|
||||
g_file_delete(*passwd_file);
|
||||
}
|
||||
g_sprintf(*passwd_file, "%s/.vnc/sesman_passwd-%s@%s:%d",
|
||||
pw_dir, username, hostname, display);
|
||||
pw_dir, pw_username, hostname, display);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* we use auth_file_path as requested */
|
||||
len = g_snprintf(NULL, 0, g_cfg->auth_file_path, username);
|
||||
len = g_snprintf(NULL, 0, g_cfg->auth_file_path, pw_username);
|
||||
|
||||
*passwd_file = (char *) g_malloc(len + 1, 1);
|
||||
if (*passwd_file != NULL)
|
||||
{
|
||||
g_sprintf(*passwd_file, g_cfg->auth_file_path, username);
|
||||
g_sprintf(*passwd_file, g_cfg->auth_file_path, pw_username);
|
||||
}
|
||||
}
|
||||
|
||||
@ -226,6 +225,7 @@ env_set_user(const char *username, char **passwd_file, int display,
|
||||
}
|
||||
}
|
||||
|
||||
g_free(pw_username);
|
||||
g_free(pw_dir);
|
||||
g_free(pw_shell);
|
||||
}
|
||||
@ -233,8 +233,7 @@ env_set_user(const char *username, char **passwd_file, int display,
|
||||
else
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"error getting user info for user %s",
|
||||
username);
|
||||
"error getting user info for uid %d", uid);
|
||||
}
|
||||
|
||||
return error;
|
||||
|
@ -43,14 +43,14 @@ env_check_password_file(const char *filename, const char *password);
|
||||
/**
|
||||
*
|
||||
* @brief Sets user environment ($PATH, $HOME, $UID, and others)
|
||||
* @param username Username
|
||||
* @param uid user ID
|
||||
* @param passwd_file VNC password file
|
||||
* @param display The session display
|
||||
* @return 0 on success, g_getuser_info() error codes on error
|
||||
*
|
||||
*/
|
||||
int
|
||||
env_set_user(const char *username, char **passwd_file, int display,
|
||||
env_set_user(int uid, char **passwd_file, int display,
|
||||
const struct list *env_names, const struct list *env_values);
|
||||
|
||||
#endif
|
||||
|
@ -35,7 +35,10 @@
|
||||
#include "scp_process.h"
|
||||
#include "access.h"
|
||||
#include "auth.h"
|
||||
#include "os_calls.h"
|
||||
#include "session.h"
|
||||
#include "sesman.h"
|
||||
#include "string_calls.h"
|
||||
|
||||
/**************************************************************************//**
|
||||
* Logs an authentication failure message
|
||||
@ -58,142 +61,408 @@ log_authfail_message(const char *username, const char *ip_addr)
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
static int
|
||||
process_gateway_request(struct trans *trans)
|
||||
/**
|
||||
* Mode parameter for authenticate_and_authorize_connection()
|
||||
*/
|
||||
enum login_mode
|
||||
{
|
||||
int rv;
|
||||
const char *username;
|
||||
const char *password;
|
||||
const char *ip_addr;
|
||||
AM_SYSTEM,
|
||||
AM_UDS
|
||||
};
|
||||
|
||||
rv = scp_get_gateway_request(trans, &username, &password, &ip_addr);
|
||||
if (rv == 0)
|
||||
/**
|
||||
* Authenticate and authorize the connection
|
||||
*
|
||||
* @param sc Connection to sesman
|
||||
* @param login_mode Describes the type of login in use
|
||||
* @param uid UID 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
|
||||
*
|
||||
* @pre sc->auth_info, sc->username and sc->ip_addr must be 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
|
||||
authenticate_and_authorize_connection(struct sesman_con *sc,
|
||||
enum login_mode login_mode,
|
||||
int uid,
|
||||
const char *username,
|
||||
const char *password,
|
||||
const char *ip_addr)
|
||||
{
|
||||
enum scp_login_status status = E_SCP_LOGIN_GENERAL_ERROR;
|
||||
struct auth_info *auth_info = NULL;
|
||||
|
||||
/* Check preconditions */
|
||||
if (sc->auth_info != NULL || sc->username != NULL || sc->ip_addr != NULL)
|
||||
{
|
||||
int errorcode = 0;
|
||||
struct auth_info *auth_info;
|
||||
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);
|
||||
}
|
||||
|
||||
LOG(LOG_LEVEL_INFO, "Received authentication request for user: %s",
|
||||
username);
|
||||
|
||||
auth_info = auth_userpass(username, password, ip_addr, &errorcode);
|
||||
if (auth_info != NULL)
|
||||
{
|
||||
if (1 == access_login_allowed(username))
|
||||
if (status != E_SCP_LOGIN_OK)
|
||||
{
|
||||
/* the user is member of the correct groups. */
|
||||
LOG(LOG_LEVEL_INFO, "Access permitted for user: %s",
|
||||
username);
|
||||
/* This shouldn't happen */
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"Unexpected status return %d from auth call",
|
||||
(int)status);
|
||||
}
|
||||
else
|
||||
else if (!access_login_allowed(username))
|
||||
{
|
||||
/* all first 32 are reserved for PAM errors */
|
||||
errorcode = 32 + 3;
|
||||
status = E_SCP_LOGIN_NOT_AUTHORIZED;
|
||||
LOG(LOG_LEVEL_INFO, "Username okay but group problem for "
|
||||
"user: %s", username);
|
||||
}
|
||||
|
||||
/* If all is well, put the auth_info in the sesman connection
|
||||
* for later use. If not, remove the auth_info */
|
||||
if (status == E_SCP_LOGIN_OK)
|
||||
{
|
||||
char *dup_username = g_strdup(username);
|
||||
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",
|
||||
__func__);
|
||||
g_free(dup_username);
|
||||
g_free(dup_ip_addr);
|
||||
status = E_SCP_LOGIN_NO_MEMORY;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(LOG_LEVEL_INFO, "Access permitted for user: %s",
|
||||
username);
|
||||
sc->auth_info = auth_info;
|
||||
sc->uid = uid;
|
||||
sc->username = dup_username;
|
||||
sc->ip_addr = dup_ip_addr;
|
||||
}
|
||||
}
|
||||
|
||||
if (status != E_SCP_LOGIN_OK)
|
||||
{
|
||||
auth_end(auth_info);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
log_authfail_message(username, ip_addr);
|
||||
}
|
||||
rv = scp_send_gateway_response(trans, errorcode);
|
||||
auth_end(auth_info);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
static int
|
||||
process_set_peername_request(struct sesman_con *sc)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
static int
|
||||
process_create_session_request(struct trans *trans)
|
||||
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;
|
||||
int rv;
|
||||
int uid;
|
||||
int pid;
|
||||
char *username = NULL;
|
||||
int server_closed = 1;
|
||||
|
||||
rv = g_sck_get_peer_cred(sc->t->sck, &pid, &uid, NULL);
|
||||
if (rv != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_INFO,
|
||||
"Unable to get peer credentials for socket %d",
|
||||
(int)sc->t->sck);
|
||||
errorcode = E_SCP_LOGIN_GENERAL_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(LOG_LEVEL_INFO,
|
||||
"Received UDS login request from %s for UID: %d from PID: %d",
|
||||
sc->peername, uid, pid);
|
||||
|
||||
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_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
|
||||
{
|
||||
errorcode = authenticate_and_authorize_connection(
|
||||
sc, AM_UDS,
|
||||
uid, username,
|
||||
NULL, NULL);
|
||||
g_free(username);
|
||||
|
||||
if (errorcode == E_SCP_LOGIN_OK)
|
||||
{
|
||||
server_closed = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (server_closed)
|
||||
{
|
||||
/* Close the connection after returning from this callback */
|
||||
sc->close_requested = 1;
|
||||
}
|
||||
|
||||
return scp_send_login_response(sc->t, errorcode, server_closed);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
static int
|
||||
process_logout_request(struct sesman_con *sc)
|
||||
{
|
||||
if (sc->auth_info != NULL)
|
||||
{
|
||||
LOG(LOG_LEVEL_INFO, "Logging out %s from sesman", sc->username);
|
||||
auth_end(sc->auth_info);
|
||||
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;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
static int
|
||||
process_create_session_request(struct sesman_con *sc)
|
||||
{
|
||||
int rv;
|
||||
struct session_parameters sp;
|
||||
const char *password;
|
||||
struct guid guid;
|
||||
int display = 0;
|
||||
enum scp_screate_status status = E_SCP_SCREATE_OK;
|
||||
|
||||
guid_clear(&guid);
|
||||
int display = 0;
|
||||
|
||||
rv = scp_get_create_session_request(
|
||||
trans,
|
||||
&sp.username, &password,
|
||||
&sp.type, &sp.width, &sp.height, &sp.bpp,
|
||||
&sp.shell, &sp.directory, &sp.ip_addr);
|
||||
rv = scp_get_create_session_request(sc->t,
|
||||
&sp.type, &sp.width, &sp.height,
|
||||
&sp.bpp, &sp.shell, &sp.directory);
|
||||
|
||||
if (rv == 0)
|
||||
{
|
||||
struct auth_info *auth_info;
|
||||
struct session_item *s_item;
|
||||
int errorcode = 0;
|
||||
bool_t do_auth_end = 1;
|
||||
|
||||
LOG(LOG_LEVEL_INFO,
|
||||
"Received request to create %s session for user: %s",
|
||||
SCP_SESSION_TYPE_TO_STR(sp.type),
|
||||
sp.username);
|
||||
|
||||
auth_info = auth_userpass(sp.username, password, sp.ip_addr, &errorcode);
|
||||
if (auth_info != NULL)
|
||||
if (sc->auth_info == NULL)
|
||||
{
|
||||
s_item = session_get_bydata(&sp);
|
||||
status = E_SCP_SCREATE_NOT_LOGGED_IN;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(LOG_LEVEL_INFO,
|
||||
"Received request from %s to create a session for user %s",
|
||||
sc->peername, sc->username);
|
||||
|
||||
// Copy over the items we got from the login request,
|
||||
// but which we need to describe the session
|
||||
sp.uid = sc->uid;
|
||||
sp.ip_addr = sc->ip_addr; // Guaranteed to be non-NULL
|
||||
|
||||
struct session_item *s_item = session_get_bydata(&sp);
|
||||
if (s_item != 0)
|
||||
{
|
||||
// Found an existing session
|
||||
display = s_item->display;
|
||||
guid = s_item->guid;
|
||||
if (sp.ip_addr[0] != '\0')
|
||||
{
|
||||
LOG( LOG_LEVEL_INFO, "++ reconnected session: username %s, "
|
||||
"display :%d.0, session_pid %d, ip %s",
|
||||
sp.username, display, s_item->pid, sp.ip_addr);
|
||||
sc->username, display, s_item->pid, sp.ip_addr);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(LOG_LEVEL_INFO, "++ reconnected session: username %s, "
|
||||
"display :%d.0, session_pid %d", sp.username, display,
|
||||
s_item->pid);
|
||||
"display :%d.0, session_pid %d",
|
||||
sc->username, display, s_item->pid);
|
||||
}
|
||||
|
||||
session_reconnect(display, sp.username, auth_info);
|
||||
session_reconnect(display, sc->uid, sc->auth_info);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_DEVEL(LOG_LEVEL_DEBUG, "pre auth");
|
||||
|
||||
if (1 == access_login_allowed(sp.username))
|
||||
// Need to create a new session
|
||||
if (sp.ip_addr[0] != '\0')
|
||||
{
|
||||
if (sp.ip_addr[0] != '\0')
|
||||
{
|
||||
LOG(LOG_LEVEL_INFO,
|
||||
"++ created session (access granted): "
|
||||
"username %s, ip %s", sp.username, sp.ip_addr);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(LOG_LEVEL_INFO,
|
||||
"++ created session (access granted): "
|
||||
"username %s", sp.username);
|
||||
}
|
||||
LOG(LOG_LEVEL_INFO,
|
||||
"++ created session: username %s, ip %s",
|
||||
sc->username, sp.ip_addr);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(LOG_LEVEL_INFO,
|
||||
"++ created session: username %s", sc->username);
|
||||
}
|
||||
|
||||
display = session_start(auth_info, &sp, &guid);
|
||||
|
||||
/* if the session started up ok, auth_end will be called on
|
||||
sig child */
|
||||
do_auth_end = display == 0;
|
||||
// The new session will have a lifetime longer than
|
||||
// the sesman connection, and so needs to own
|
||||
// the auth_info struct.
|
||||
//
|
||||
// Copy the auth_info struct out of the connection and pass
|
||||
// it to the session
|
||||
struct auth_info *auth_info = sc->auth_info;
|
||||
sc->auth_info = NULL;
|
||||
status = session_start(auth_info, &sp, &display, &guid);
|
||||
if (status != E_SCP_SCREATE_OK)
|
||||
{
|
||||
// Close the auth session down as it can't be re-used.
|
||||
auth_end(auth_info);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
log_authfail_message(sp.username, sp.ip_addr);
|
||||
}
|
||||
|
||||
if (do_auth_end)
|
||||
{
|
||||
auth_end(auth_info);
|
||||
}
|
||||
/* Currently a create session request is the last thing on a
|
||||
* connection, and results in automatic closure */
|
||||
sc->close_requested = 1;
|
||||
|
||||
rv = scp_send_create_session_response(trans, errorcode, display, &guid);
|
||||
rv = scp_send_create_session_response(sc->t, status, display, &guid);
|
||||
}
|
||||
|
||||
return rv;
|
||||
@ -202,75 +471,99 @@ process_create_session_request(struct trans *trans)
|
||||
/******************************************************************************/
|
||||
|
||||
static int
|
||||
process_list_sessions_request(struct trans *trans)
|
||||
process_list_sessions_request(struct sesman_con *sc)
|
||||
{
|
||||
int rv;
|
||||
int rv = 0;
|
||||
|
||||
const char *username;
|
||||
const char *password;
|
||||
struct scp_session_info *info = NULL;
|
||||
unsigned int cnt = 0;
|
||||
unsigned int i;
|
||||
|
||||
rv = scp_get_list_sessions_request(trans, &username, &password);
|
||||
if (rv == 0)
|
||||
if (sc->auth_info == NULL)
|
||||
{
|
||||
rv = scp_send_list_sessions_response(sc->t,
|
||||
E_SCP_LS_NOT_LOGGED_IN,
|
||||
NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
enum scp_list_sessions_status status;
|
||||
int errorcode = 0;
|
||||
struct auth_info *auth_info;
|
||||
|
||||
LOG(LOG_LEVEL_INFO,
|
||||
"Received request to list sessions for user %s", username);
|
||||
"Received request from %s to list sessions for user %s",
|
||||
sc->peername, sc->username);
|
||||
|
||||
auth_info = auth_userpass(username, password, NULL, &errorcode);
|
||||
if (auth_info != NULL)
|
||||
{
|
||||
struct scp_session_info *info = NULL;
|
||||
unsigned int cnt = 0;
|
||||
unsigned int i;
|
||||
info = session_get_byuser(username, &cnt,
|
||||
SESMAN_SESSION_STATUS_ALL);
|
||||
info = session_get_byuid(sc->uid, &cnt,
|
||||
SESMAN_SESSION_STATUS_ALL);
|
||||
|
||||
for (i = 0; rv == 0 && i < cnt; ++i)
|
||||
{
|
||||
rv = scp_send_list_sessions_response(trans,
|
||||
E_SCP_LS_SESSION_INFO,
|
||||
&info[i]);
|
||||
}
|
||||
free_session_info_list(info, cnt);
|
||||
status = E_SCP_LS_END_OF_LIST;
|
||||
}
|
||||
else
|
||||
for (i = 0; rv == 0 && i < cnt; ++i)
|
||||
{
|
||||
status = E_SCP_LS_AUTHENTICATION_FAIL;
|
||||
rv = scp_send_list_sessions_response(sc->t,
|
||||
E_SCP_LS_SESSION_INFO,
|
||||
&info[i]);
|
||||
}
|
||||
auth_end(auth_info);
|
||||
free_session_info_list(info, cnt);
|
||||
|
||||
if (rv == 0)
|
||||
{
|
||||
rv = scp_send_list_sessions_response(trans, status, NULL);
|
||||
rv = scp_send_list_sessions_response(sc->t,
|
||||
E_SCP_LS_END_OF_LIST,
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
static int
|
||||
process_close_connection_request(struct sesman_con *sc)
|
||||
{
|
||||
int rv = 0;
|
||||
|
||||
LOG(LOG_LEVEL_INFO, "Received request to close connection from %s",
|
||||
sc->peername);
|
||||
|
||||
/* Expecting no more client messages. Close the connection
|
||||
* after returning from this callback */
|
||||
sc->close_requested = 1;
|
||||
return rv;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
int
|
||||
scp_process(struct trans *t)
|
||||
scp_process(struct sesman_con *sc)
|
||||
{
|
||||
enum scp_msg_code msgno;
|
||||
int rv = 0;
|
||||
|
||||
switch ((msgno = scp_msg_in_start(t)))
|
||||
switch ((msgno = scp_msg_in_start(sc->t)))
|
||||
{
|
||||
case E_SCP_GATEWAY_REQUEST:
|
||||
rv = process_gateway_request(t);
|
||||
case E_SCP_SET_PEERNAME_REQUEST:
|
||||
rv = process_set_peername_request(sc);
|
||||
break;
|
||||
|
||||
case E_SCP_SYS_LOGIN_REQUEST:
|
||||
rv = process_sys_login_request(sc);
|
||||
break;
|
||||
|
||||
case E_SCP_UDS_LOGIN_REQUEST:
|
||||
rv = process_uds_login_request(sc);
|
||||
break;
|
||||
|
||||
case E_SCP_LOGOUT_REQUEST:
|
||||
rv = process_logout_request(sc);
|
||||
break;
|
||||
|
||||
case E_SCP_CREATE_SESSION_REQUEST:
|
||||
rv = process_create_session_request(t);
|
||||
rv = process_create_session_request(sc);
|
||||
break;
|
||||
|
||||
case E_SCP_LIST_SESSIONS_REQUEST:
|
||||
rv = process_list_sessions_request(t);
|
||||
rv = process_list_sessions_request(sc);
|
||||
break;
|
||||
|
||||
case E_SCP_CLOSE_CONNECTION_REQUEST:
|
||||
rv = process_close_connection_request(sc);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -27,15 +27,15 @@
|
||||
#ifndef SCP_PROCESS_H
|
||||
#define SCP_PROCESS_H
|
||||
|
||||
struct trans;
|
||||
struct sesman_con;
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Processes an SCP message
|
||||
* @param t the connection trans
|
||||
* @param sc the sesman connection
|
||||
*
|
||||
*/
|
||||
int
|
||||
scp_process(struct trans *t);
|
||||
scp_process(struct sesman_con *sc);
|
||||
|
||||
#endif
|
||||
|
@ -33,6 +33,7 @@
|
||||
#include "arch.h"
|
||||
#include "sesman.h"
|
||||
|
||||
#include "auth.h"
|
||||
#include "config.h"
|
||||
#include "lock_uds.h"
|
||||
#include "os_calls.h"
|
||||
@ -123,9 +124,11 @@ alloc_connection(struct trans *t)
|
||||
{
|
||||
struct sesman_con *result;
|
||||
|
||||
if ((result = g_new(struct sesman_con, 1)) != NULL)
|
||||
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;
|
||||
@ -137,15 +140,40 @@ alloc_connection(struct trans *t)
|
||||
* 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)
|
||||
{
|
||||
trans_delete(sc->t);
|
||||
g_free(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;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/**
|
||||
@ -272,16 +300,23 @@ static int sesman_listen_test(struct config_sesman *cfg)
|
||||
|
||||
/******************************************************************************/
|
||||
int
|
||||
sesman_close_all(void)
|
||||
sesman_close_all(unsigned int flags)
|
||||
{
|
||||
int index;
|
||||
struct sesman_con *sc;
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "sesman_close_all:");
|
||||
|
||||
|
||||
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;
|
||||
@ -298,7 +333,8 @@ sesman_data_in(struct trans *self)
|
||||
|
||||
if (rv == 0 && available)
|
||||
{
|
||||
if ((rv = scp_process(self)) != 0)
|
||||
struct sesman_con *sc = (struct sesman_con *)self->callback_data;
|
||||
if ((rv = scp_process(sc)) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "sesman_data_in: scp_process_msg failed");
|
||||
}
|
||||
@ -324,7 +360,7 @@ sesman_listen_conn_in(struct trans *self, struct trans *new_self)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "sesman_data_in: No memory to allocate "
|
||||
"new connection");
|
||||
trans_delete(new_self);
|
||||
delete_connection(sc);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -546,20 +582,30 @@ sesman_main_loop(void)
|
||||
sig_sesman_reload_cfg();
|
||||
}
|
||||
|
||||
for (index = 0; index < g_con_list->count; index++)
|
||||
index = 0;
|
||||
while (index < g_con_list->count)
|
||||
{
|
||||
int remove_con = 0;
|
||||
scon = (struct sesman_con *)list_get_item(g_con_list, index);
|
||||
if (scon != NULL)
|
||||
if (trans_check_wait_objs(scon->t) != 0)
|
||||
{
|
||||
if (trans_check_wait_objs(scon->t) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "sesman_main_loop: "
|
||||
"trans_check_wait_objs failed, removing trans");
|
||||
delete_connection(scon);
|
||||
list_remove_item(g_con_list, index);
|
||||
index--;
|
||||
continue;
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -574,13 +620,9 @@ sesman_main_loop(void)
|
||||
}
|
||||
}
|
||||
}
|
||||
for (index = 0; index < g_con_list->count; index++)
|
||||
{
|
||||
scon = (struct sesman_con *) list_get_item(g_con_list, index);
|
||||
delete_connection(scon);
|
||||
}
|
||||
|
||||
sesman_close_all(SCA_CLOSE_AUTH_INFO);
|
||||
list_delete(g_con_list);
|
||||
sesman_delete_listening_transport();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -33,6 +33,13 @@
|
||||
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 */
|
||||
@ -42,6 +49,15 @@ extern tintptr g_term_event;
|
||||
extern tintptr g_sigchld_event;
|
||||
extern tintptr g_reload_event;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
@ -50,9 +66,14 @@ extern tintptr g_reload_event;
|
||||
*
|
||||
* This call will also release all trans and SCP_SESSION objects
|
||||
* held by sesman
|
||||
*
|
||||
* @param flags Set SCA_CLOSE_AUTH_INFO to close any open auth_info
|
||||
* objects. By default these are not cleared, and should
|
||||
* only be done so when exiting sesman.
|
||||
*/
|
||||
#define SCA_CLOSE_AUTH_INFO (1<<0)
|
||||
int
|
||||
sesman_close_all(void);
|
||||
sesman_close_all(unsigned int flags);
|
||||
|
||||
/*
|
||||
* Remove the listening transport
|
||||
|
150
sesman/session.c
150
sesman/session.c
@ -112,10 +112,10 @@ session_get_bydata(const struct session_parameters *sp)
|
||||
config_output_policy_string(policy, policy_str, sizeof(policy_str));
|
||||
|
||||
LOG(LOG_LEVEL_DEBUG,
|
||||
"%s: search policy=%s type=%s U=%s B=%d D=(%dx%d) I=%s",
|
||||
"%s: search policy=%s type=%s U=%d B=%d D=(%dx%d) I=%s",
|
||||
__func__,
|
||||
policy_str, SCP_SESSION_TYPE_TO_STR(sp->type),
|
||||
sp->username, sp->bpp, sp->width, sp->height,
|
||||
sp->uid, sp->bpp, sp->width, sp->height,
|
||||
sp->ip_addr);
|
||||
|
||||
/* 'Separate' policy never matches */
|
||||
@ -130,11 +130,11 @@ session_get_bydata(const struct session_parameters *sp)
|
||||
struct session_item *item = tmp->item;
|
||||
|
||||
LOG(LOG_LEVEL_DEBUG,
|
||||
"%s: try %p type=%s U=%s B=%d D=(%dx%d) I=%s",
|
||||
"%s: try %p type=%s U=%d B=%d D=(%dx%d) I=%s",
|
||||
__func__,
|
||||
item,
|
||||
SCP_SESSION_TYPE_TO_STR(item->type),
|
||||
item->name,
|
||||
item->uid,
|
||||
item->bpp,
|
||||
item->width, item->height,
|
||||
item->start_ip_addr);
|
||||
@ -145,11 +145,10 @@ session_get_bydata(const struct session_parameters *sp)
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((policy & SESMAN_CFG_SESS_POLICY_U) &&
|
||||
g_strncmp(sp->username, item->name, sizeof(item->name) - 1) != 0)
|
||||
if ((policy & SESMAN_CFG_SESS_POLICY_U) && sp->uid != item->uid)
|
||||
{
|
||||
LOG(LOG_LEVEL_DEBUG,
|
||||
"%s: Username doesn't match for 'U' policy", __func__);
|
||||
"%s: UID doesn't match for 'U' policy", __func__);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -408,7 +407,7 @@ wait_for_xserver(int display)
|
||||
|
||||
/******************************************************************************/
|
||||
static int
|
||||
session_start_chansrv(const char *username, int display)
|
||||
session_start_chansrv(int uid, int display)
|
||||
{
|
||||
struct list *chansrv_params;
|
||||
char exe_path[262];
|
||||
@ -430,7 +429,7 @@ session_start_chansrv(const char *username, int display)
|
||||
list_add_item(chansrv_params, (intptr_t) g_strdup(exe_path));
|
||||
list_add_item(chansrv_params, 0); /* mandatory */
|
||||
|
||||
env_set_user(username, 0, display,
|
||||
env_set_user(uid, 0, display,
|
||||
g_cfg->env_names,
|
||||
g_cfg->env_values);
|
||||
|
||||
@ -445,10 +444,38 @@ session_start_chansrv(const char *username, int display)
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/**
|
||||
* 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);
|
||||
|
||||
int
|
||||
if (rv == 0)
|
||||
{
|
||||
g_snprintf(uname, uname_len, "%s", ustr);
|
||||
g_free(ustr);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_snprintf(uname, uname_len, "<unknown>");
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
enum scp_screate_status
|
||||
session_start(struct auth_info *auth_info,
|
||||
const struct session_parameters *s,
|
||||
int *returned_display,
|
||||
struct guid *guid)
|
||||
{
|
||||
int display = 0;
|
||||
@ -457,6 +484,7 @@ session_start(struct auth_info *auth_info,
|
||||
char depth[32];
|
||||
char screen[32]; /* display number */
|
||||
char text[256];
|
||||
char username[256];
|
||||
char execvpparams[2048];
|
||||
char *xserver = NULL; /* absolute/relative path to Xorg/X11rdp/Xvnc */
|
||||
char *passwd_file;
|
||||
@ -476,12 +504,15 @@ session_start(struct auth_info *auth_info,
|
||||
|
||||
passwd_file = 0;
|
||||
|
||||
/* Get the username for display purposes */
|
||||
username_from_uid(s->uid, username, sizeof(username));
|
||||
|
||||
/* check to limit concurrent sessions */
|
||||
if (g_session_count >= g_cfg->sess.max_sessions)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "max concurrent session limit "
|
||||
"exceeded. login for user %s denied", s->username);
|
||||
return 0;
|
||||
"exceeded. login for user %s denied", username);
|
||||
return E_SCP_SCREATE_MAX_REACHED;
|
||||
}
|
||||
|
||||
temp = (struct session_chain *)g_malloc(sizeof(struct session_chain), 0);
|
||||
@ -489,8 +520,8 @@ session_start(struct auth_info *auth_info,
|
||||
if (temp == 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "Out of memory error: cannot create new session "
|
||||
"chain element - user %s", s->username);
|
||||
return 0;
|
||||
"chain element - user %s", username);
|
||||
return E_SCP_SCREATE_NO_MEMORY;
|
||||
}
|
||||
|
||||
temp->item = (struct session_item *)g_malloc(sizeof(struct session_item), 0);
|
||||
@ -499,8 +530,8 @@ session_start(struct auth_info *auth_info,
|
||||
{
|
||||
g_free(temp);
|
||||
LOG(LOG_LEVEL_ERROR, "Out of memory error: cannot create new session "
|
||||
"item - user %s", s->username);
|
||||
return 0;
|
||||
"item - user %s", username);
|
||||
return E_SCP_SCREATE_NO_MEMORY;
|
||||
}
|
||||
|
||||
display = session_get_avail_display_from_chain();
|
||||
@ -509,11 +540,12 @@ session_start(struct auth_info *auth_info,
|
||||
{
|
||||
g_free(temp->item);
|
||||
g_free(temp);
|
||||
return 0;
|
||||
return E_SCP_SCREATE_NO_DISPLAY;
|
||||
}
|
||||
|
||||
/* Create a GUID for the new session before we work */
|
||||
/* Create a GUID for the new session before we fork */
|
||||
*guid = guid_new();
|
||||
*returned_display = display;
|
||||
|
||||
pid = g_fork(); /* parent is fork from tcp accept,
|
||||
child forks X and wm, then becomes scp */
|
||||
@ -524,8 +556,12 @@ session_start(struct auth_info *auth_info,
|
||||
"[session start] (display %d): Failed to fork for scp with "
|
||||
"errno: %d, description: %s",
|
||||
display, g_get_errno(), g_get_strerror());
|
||||
g_free(temp->item);
|
||||
g_free(temp);
|
||||
return E_SCP_SCREATE_GENERAL_ERROR;
|
||||
}
|
||||
else if (pid == 0)
|
||||
|
||||
if (pid == 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_INFO,
|
||||
"[session start] (display %d): calling auth_start_session from pid %d",
|
||||
@ -547,16 +583,16 @@ session_start(struct auth_info *auth_info,
|
||||
|
||||
/* Set the secondary groups before starting the session to prevent
|
||||
* problems on PAM-based systems (see pam_setcred(3)) */
|
||||
if (g_initgroups(s->username) != 0)
|
||||
if (g_initgroups(username) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"Failed to initialise secondary groups for %s: %s",
|
||||
s->username, g_get_strerror());
|
||||
username, g_get_strerror());
|
||||
g_exit(1);
|
||||
}
|
||||
|
||||
sesman_close_all(0);
|
||||
auth_start_session(auth_info, display);
|
||||
sesman_close_all();
|
||||
g_sprintf(geometry, "%dx%d", s->width, s->height);
|
||||
g_sprintf(depth, "%d", s->bpp);
|
||||
g_sprintf(screen, ":%d", display);
|
||||
@ -588,11 +624,11 @@ session_start(struct auth_info *auth_info,
|
||||
display, g_getpid());
|
||||
}
|
||||
|
||||
if (g_setlogin(s->username) < 0)
|
||||
if (g_setlogin(username) < 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_WARNING,
|
||||
"[session start] (display %d): setlogin failed for user %s - pid %d",
|
||||
display, s->username, g_getpid());
|
||||
display, username, g_getpid());
|
||||
}
|
||||
}
|
||||
|
||||
@ -617,7 +653,7 @@ session_start(struct auth_info *auth_info,
|
||||
else if (window_manager_pid == 0)
|
||||
{
|
||||
wait_for_xserver(display);
|
||||
env_set_user(s->username,
|
||||
env_set_user(s->uid,
|
||||
0,
|
||||
display,
|
||||
g_cfg->env_names,
|
||||
@ -715,7 +751,7 @@ session_start(struct auth_info *auth_info,
|
||||
{
|
||||
if (s->type == SCP_SESSION_TYPE_XVNC)
|
||||
{
|
||||
env_set_user(s->username,
|
||||
env_set_user(s->uid,
|
||||
&passwd_file,
|
||||
display,
|
||||
g_cfg->env_names,
|
||||
@ -723,7 +759,7 @@ session_start(struct auth_info *auth_info,
|
||||
}
|
||||
else
|
||||
{
|
||||
env_set_user(s->username,
|
||||
env_set_user(s->uid,
|
||||
0,
|
||||
display,
|
||||
g_cfg->env_names,
|
||||
@ -901,11 +937,11 @@ session_start(struct auth_info *auth_info,
|
||||
struct exit_status chansrv_exit_status;
|
||||
|
||||
wait_for_xserver(display);
|
||||
chansrv_pid = session_start_chansrv(s->username, display);
|
||||
chansrv_pid = session_start_chansrv(s->uid, display);
|
||||
|
||||
LOG(LOG_LEVEL_INFO,
|
||||
"Session started successfully for user %s on display %d",
|
||||
s->username, display);
|
||||
username, display);
|
||||
|
||||
/* Monitor the amount of time we wait for the
|
||||
* window manager. This is approximately how long the window
|
||||
@ -939,10 +975,12 @@ session_start(struct auth_info *auth_info,
|
||||
window_manager_pid, display, wm_wait_time);
|
||||
}
|
||||
LOG(LOG_LEVEL_INFO,
|
||||
"Calling auth_stop_session and auth_end from pid %d",
|
||||
"Calling auth_stop_session from pid %d",
|
||||
g_getpid());
|
||||
auth_stop_session(auth_info);
|
||||
auth_end(auth_info);
|
||||
// auth_end() is called from the main process currently,
|
||||
// as this called auth_start()
|
||||
//auth_end(auth_info);
|
||||
|
||||
LOG(LOG_LEVEL_INFO,
|
||||
"Terminating X server (pid %d) on display %d",
|
||||
@ -978,8 +1016,8 @@ session_start(struct auth_info *auth_info,
|
||||
{
|
||||
LOG(LOG_LEVEL_INFO, "Starting session: session_pid %d, "
|
||||
"display :%d.0, width %d, height %d, bpp %d, client ip %s, "
|
||||
"user name %s",
|
||||
pid, display, s->width, s->height, s->bpp, s->ip_addr, s->username);
|
||||
"UID %d",
|
||||
pid, display, s->width, s->height, s->bpp, s->ip_addr, s->uid);
|
||||
temp->item->pid = pid;
|
||||
temp->item->display = display;
|
||||
temp->item->width = s->width;
|
||||
@ -988,7 +1026,7 @@ session_start(struct auth_info *auth_info,
|
||||
temp->item->auth_info = auth_info;
|
||||
g_strncpy(temp->item->start_ip_addr, s->ip_addr,
|
||||
sizeof(temp->item->start_ip_addr) - 1);
|
||||
g_strncpy(temp->item->name, s->username, 255);
|
||||
temp->item->uid = s->uid;
|
||||
temp->item->guid = *guid;
|
||||
|
||||
temp->item->start_time = g_time1();
|
||||
@ -1000,17 +1038,18 @@ session_start(struct auth_info *auth_info,
|
||||
g_sessions = temp;
|
||||
g_session_count++;
|
||||
|
||||
return display;
|
||||
return E_SCP_SCREATE_OK;
|
||||
}
|
||||
|
||||
/* Shouldn't get here */
|
||||
g_free(temp->item);
|
||||
g_free(temp);
|
||||
return display;
|
||||
return E_SCP_SCREATE_GENERAL_ERROR;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
int
|
||||
session_reconnect(int display, const char *username,
|
||||
session_reconnect(int display, int uid,
|
||||
struct auth_info *auth_info)
|
||||
{
|
||||
int pid;
|
||||
@ -1023,7 +1062,7 @@ session_reconnect(int display, const char *username,
|
||||
}
|
||||
else if (pid == 0)
|
||||
{
|
||||
env_set_user(username,
|
||||
env_set_user(uid,
|
||||
0,
|
||||
display,
|
||||
g_cfg->env_names,
|
||||
@ -1090,10 +1129,23 @@ session_kill(int pid)
|
||||
|
||||
if (tmp->item->pid == pid)
|
||||
{
|
||||
char username[256];
|
||||
username_from_uid(tmp->item->uid, username, sizeof(username));
|
||||
|
||||
/* deleting the session */
|
||||
if (tmp->item->auth_info != NULL)
|
||||
{
|
||||
LOG(LOG_LEVEL_INFO,
|
||||
"Calling auth_end for pid %d from pid %d",
|
||||
pid, g_getpid());
|
||||
auth_end(tmp->item->auth_info);
|
||||
tmp->item->auth_info = NULL;
|
||||
}
|
||||
LOG(LOG_LEVEL_INFO,
|
||||
"++ terminated session: username %s, display :%d.0, session_pid %d, ip %s",
|
||||
tmp->item->name, tmp->item->display, tmp->item->pid, tmp->item->start_ip_addr);
|
||||
"++ terminated session: UID %d (%s), display :%d.0, "
|
||||
"session_pid %d, ip %s",
|
||||
tmp->item->uid, username, tmp->item->display,
|
||||
tmp->item->pid, tmp->item->start_ip_addr);
|
||||
g_free(tmp->item);
|
||||
|
||||
if (prev == 0)
|
||||
@ -1186,7 +1238,7 @@ session_get_bypid(int pid)
|
||||
|
||||
/******************************************************************************/
|
||||
struct scp_session_info *
|
||||
session_get_byuser(const char *user, unsigned int *cnt, unsigned char flags)
|
||||
session_get_byuid(int uid, unsigned int *cnt, unsigned char flags)
|
||||
{
|
||||
struct session_chain *tmp;
|
||||
struct scp_session_info *sess;
|
||||
@ -1197,10 +1249,10 @@ session_get_byuser(const char *user, unsigned int *cnt, unsigned char flags)
|
||||
|
||||
tmp = g_sessions;
|
||||
|
||||
LOG(LOG_LEVEL_DEBUG, "searching for session by user: %s", user);
|
||||
LOG(LOG_LEVEL_DEBUG, "searching for session by UID: %d", uid);
|
||||
while (tmp != 0)
|
||||
{
|
||||
if ((NULL == user) || (!g_strncasecmp(user, tmp->item->name, 256)))
|
||||
if (uid == tmp->item->uid)
|
||||
{
|
||||
LOG(LOG_LEVEL_DEBUG, "session_get_byuser: status=%d, flags=%d, "
|
||||
"result=%d", (tmp->item->status), flags,
|
||||
@ -1236,8 +1288,7 @@ session_get_byuser(const char *user, unsigned int *cnt, unsigned char flags)
|
||||
|
||||
while (tmp != 0 && index < count)
|
||||
{
|
||||
/* #warning FIXME: we should get only disconnected sessions! */
|
||||
if ((NULL == user) || (!g_strncasecmp(user, tmp->item->name, 256)))
|
||||
if (uid == tmp->item->uid)
|
||||
{
|
||||
if ((tmp->item->status) & flags)
|
||||
{
|
||||
@ -1248,11 +1299,11 @@ session_get_byuser(const char *user, unsigned int *cnt, unsigned char flags)
|
||||
(sess[index]).width = tmp->item->width;
|
||||
(sess[index]).bpp = tmp->item->bpp;
|
||||
(sess[index]).start_time = tmp->item->start_time;
|
||||
(sess[index]).username = g_strdup(tmp->item->name);
|
||||
(sess[index]).uid = tmp->item->uid;
|
||||
(sess[index]).start_ip_addr = g_strdup(tmp->item->start_ip_addr);
|
||||
|
||||
if ((sess[index]).username == NULL ||
|
||||
(sess[index]).start_ip_addr == NULL)
|
||||
/* Check for string allocation failures */
|
||||
if ((sess[index]).start_ip_addr == NULL)
|
||||
{
|
||||
free_session_info_list(sess, *cnt);
|
||||
(*cnt) = 0;
|
||||
@ -1279,7 +1330,6 @@ free_session_info_list(struct scp_session_info *sesslist, unsigned int cnt)
|
||||
unsigned int i;
|
||||
for (i = 0 ; i < cnt ; ++i)
|
||||
{
|
||||
g_free(sesslist[i].username);
|
||||
g_free(sesslist[i].start_ip_addr);
|
||||
}
|
||||
}
|
||||
@ -1392,7 +1442,6 @@ clone_session_params(const struct session_parameters *sp)
|
||||
/* Allocate a single block of memory big enough for the structure and
|
||||
* all the strings it points to */
|
||||
unsigned int len = sizeof(*result);
|
||||
len += g_strlen(sp->username) + 1;
|
||||
len += g_strlen(sp->shell) + 1;
|
||||
len += g_strlen(sp->directory) + 1;
|
||||
len += g_strlen(sp->ip_addr) + 1;
|
||||
@ -1412,7 +1461,6 @@ clone_session_params(const struct session_parameters *sp)
|
||||
strptr += len;\
|
||||
}
|
||||
|
||||
COPY_STRING_MEMBER(sp->username, result->username);
|
||||
COPY_STRING_MEMBER(sp->shell, result->shell);
|
||||
COPY_STRING_MEMBER(sp->directory, result->directory);
|
||||
COPY_STRING_MEMBER(sp->ip_addr, result->ip_addr);
|
||||
|
@ -53,7 +53,7 @@ struct scp_session_info;
|
||||
|
||||
struct session_item
|
||||
{
|
||||
char name[256];
|
||||
int uid; /* UID of session */
|
||||
int pid; /* pid of sesman waiting for wm to end */
|
||||
int display;
|
||||
int width;
|
||||
@ -85,11 +85,11 @@ struct session_chain
|
||||
*/
|
||||
struct session_parameters
|
||||
{
|
||||
int uid;
|
||||
enum scp_session_type type;
|
||||
unsigned short height;
|
||||
unsigned short width;
|
||||
unsigned char bpp;
|
||||
const char *username;
|
||||
const char *shell;
|
||||
const char *directory;
|
||||
const char *ip_addr;
|
||||
@ -110,16 +110,17 @@ session_get_bydata(const struct session_parameters *params);
|
||||
/**
|
||||
*
|
||||
* @brief starts a session
|
||||
* @return 0 on error, display number if success
|
||||
*
|
||||
* @return Connection status.
|
||||
*/
|
||||
int
|
||||
enum scp_screate_status
|
||||
session_start(struct auth_info *auth_info,
|
||||
const struct session_parameters *params,
|
||||
int *display,
|
||||
struct guid *guid);
|
||||
|
||||
int
|
||||
session_reconnect(int display, const char *username,
|
||||
session_reconnect(int display, int uid,
|
||||
struct auth_info *auth_info);
|
||||
|
||||
/**
|
||||
@ -154,14 +155,14 @@ session_get_bypid(int pid);
|
||||
/**
|
||||
*
|
||||
* @brief retrieves session descriptions
|
||||
* @param user the user for the sessions
|
||||
* @param UID the UID for the descriptions
|
||||
* @return A block of session descriptions
|
||||
*
|
||||
* Pass the return result to free_session_info_list() after use
|
||||
*
|
||||
*/
|
||||
struct scp_session_info *
|
||||
session_get_byuser(const char *user, unsigned int *cnt, unsigned char flags);
|
||||
session_get_byuid(int uid, unsigned int *cnt, unsigned char flags);
|
||||
|
||||
/**
|
||||
*
|
||||
|
Loading…
Reference in New Issue
Block a user