Move sesman to new SCP interface

This commit is contained in:
matt335672 2022-02-14 09:16:42 +00:00
parent 6cf053c9df
commit c0cb03801c
15 changed files with 522 additions and 1115 deletions

View File

@ -9,7 +9,7 @@ AM_CPPFLAGS = \
-DXRDP_PID_PATH=\"${localstatedir}/run\" \ -DXRDP_PID_PATH=\"${localstatedir}/run\" \
-DXRDP_SOCKET_PATH=\"${socketdir}\" \ -DXRDP_SOCKET_PATH=\"${socketdir}\" \
-I$(top_srcdir)/common \ -I$(top_srcdir)/common \
-I$(top_srcdir)/sesman/libscp -I$(top_srcdir)/libipm
if SESMAN_BSD if SESMAN_BSD
AUTH_C = verify_user_bsd.c AUTH_C = verify_user_bsd.c
@ -45,14 +45,8 @@ xrdp_sesman_SOURCES = \
config.h \ config.h \
env.c \ env.c \
env.h \ env.h \
scp.c \ scp_process.c \
scp.h \ scp_process.h \
scp_v0.c \
scp_v0.h \
scp_v1.c \
scp_v1.h \
scp_v1_mng.c \
scp_v1_mng.h \
sesman.c \ sesman.c \
sesman.h \ sesman.h \
session.c \ session.c \
@ -64,8 +58,8 @@ xrdp_sesman_SOURCES = \
$(AUTH_C) $(AUTH_C)
xrdp_sesman_LDADD = \ xrdp_sesman_LDADD = \
$(top_builddir)/libipm/libipm.la \
$(top_builddir)/common/libcommon.la \ $(top_builddir)/common/libcommon.la \
$(top_builddir)/sesman/libscp/libscp.la \
$(AUTH_LIB) \ $(AUTH_LIB) \
-lpthread -lpthread
@ -90,6 +84,5 @@ dist_sesmansysconf_SCRIPTS = \
reconnectwm.sh reconnectwm.sh
SUBDIRS = \ SUBDIRS = \
libscp \
tools \ tools \
chansrv chansrv

View File

@ -7,60 +7,5 @@
** internal, and may change for even minor releases. ** ** internal, and may change for even minor releases. **
************************************************************ ************************************************************
The SCP protocol is layered on top of libipm, which is in
message header ../libipm. See ../libipm/scp.h for the interface messages to xrdp-sesman
version 4 - version, 0 or 1
size 4 - size of PDU including header
cmdset 2 - 0
version 0
cmdset 2 bytes
0 - Xvnc client to server
3 - response to 0, 10, or 20 server to client
4 - SCP_GW_AUTHENTICATION client to server
10 - X11rdp client to server
20 - Xorg client to server
version 1
cmdset 2 bytes
0 - SCP_COMMAND_SET_DEFAULT
1 - SCP_COMMAND_SET_MANAGE
2 - SCP_COMMAND_SET_RSR
SCP_COMMAND_SET_DEFAULT
cmd 2 bytes
1 - main client to server
3 - password request server to client
4 - password reply client to server
30 - connect new session
40 - list all sessions server to client
41 - list all sessions response client to server
42 - list all sessions server to client
43 - list all sessions response client to server
44 - list all sessions response client to server
45 - client to server
46 - reconnect session
0xFFFF - SCP_CMD_CONN_ERROR
SCP_COMMAND_SET_MANAGE
cmd 2 bytes
1 - manager login
2 - SCP_CMD_MNG_LOGIN_ALLOW
v0
scp_process scp.c
scp_vXs_accept libscp_vX.c
scp_v0s_accept libscp_v0.c
scp_v0_process scp_v0.c
session_start session.c
v1
scp_process scp.c
scp_vXs_accept libscp_vX.c
scp_v1s_accept libscp_v1s.c
scp_v1s_mng_accept libscp_v1s_mng.c
scp_v1_process scp_v1.c
scp_v1s_request_password libscp_v1s.c
or
scp_v1_mng_process scp_v1_mng.c

View File

@ -1,88 +0,0 @@
/**
* xrdp: A Remote Desktop Protocol server.
*
* Copyright (C) Jay Sorg 2004-2015
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
*
* @file scp.c
* @brief scp (sesman control protocol) common code
* scp (sesman control protocol) common code
* This code controls which version is being used and starts the
* appropriate process
* @author Jay Sorg, Simone Fedele
*
*/
#if defined(HAVE_CONFIG_H)
#include <config_ac.h>
#endif
#include "sesman.h"
/******************************************************************************/
enum SCP_SERVER_STATES_E
scp_process(struct trans *t, struct SCP_SESSION *sdata)
{
enum SCP_SERVER_STATES_E result = scp_vXs_accept(t, sdata);
switch (result)
{
case SCP_SERVER_STATE_OK:
if (sdata->version == 0)
{
/* starts processing an scp v0 connection */
LOG_DEVEL(LOG_LEVEL_DEBUG, "accept ok, go on with scp v0");
result = scp_v0_process(t, sdata);
}
else
{
LOG_DEVEL(LOG_LEVEL_DEBUG, "accept ok, go on with scp v1");
result = scp_v1_process(t, sdata);
}
break;
case SCP_SERVER_STATE_START_MANAGE:
/* starting a management session */
LOG(LOG_LEVEL_INFO,
"starting a sesman management session...");
result = scp_v1_mng_process_msg(t, sdata);
break;
case SCP_SERVER_STATE_VERSION_ERR:
case SCP_SERVER_STATE_SIZE_ERR:
/* an unknown scp version was requested, or the message sizes
are inconsistent. Shut down the connection and log the
fact */
LOG(LOG_LEVEL_WARNING,
"protocol violation. connection refused.");
break;
case SCP_SERVER_STATE_NETWORK_ERR:
LOG(LOG_LEVEL_WARNING, "libscp network error.");
break;
case SCP_SERVER_STATE_SEQUENCE_ERR:
LOG(LOG_LEVEL_WARNING, "libscp sequence error.");
break;
case SCP_SERVER_STATE_INTERNAL_ERR:
/* internal error occurred (eg. malloc() error, ecc.) */
LOG(LOG_LEVEL_ERROR, "libscp internal error occurred.");
break;
default:
LOG(LOG_LEVEL_ALWAYS, "unknown return from scp_vXs_accept()");
result = SCP_SERVER_STATE_INTERNAL_ERR;
break;
}
return result;
}

View File

@ -1,45 +0,0 @@
/**
* xrdp: A Remote Desktop Protocol server.
*
* Copyright (C) Jay Sorg 2004-2013
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
*
* @file scp.h
* @brief scp (sesman control protocol) common definitions
* @author Simone Fedele
*
*/
#ifndef SCP_H
#define SCP_H
#include "scp_v0.h"
#include "scp_v1.h"
#include "scp_v1_mng.h"
/**
*
* @brief Starts a an scp protocol thread.
* Starts a an scp protocol thread.
* But does only version control....
* @param atrans the connection trans
*
*/
enum SCP_SERVER_STATES_E
scp_process(struct trans *t, struct SCP_SESSION *s);
#endif

277
sesman/scp_process.c Normal file
View File

@ -0,0 +1,277 @@
/**
* xrdp: A Remote Desktop Protocol server.
*
* Copyright (C) Jay Sorg 2004-2015
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
*
* @file scp.c
* @brief scp (sesman control protocol) handler function
* @author Jay Sorg, Simone Fedele
*
*/
#if defined(HAVE_CONFIG_H)
#include <config_ac.h>
#endif
#include "trans.h"
#include "os_calls.h"
#include "scp.h"
#include "scp_process.h"
#include "access.h"
#include "auth.h"
#include "session.h"
/******************************************************************************/
static int
process_gateway_request(struct trans *trans)
{
int rv;
const char *username;
const char *password;
if ((rv = scp_get_gateway_request(trans, &username, &password)) == 0)
{
int errorcode = 0;
tbus data;
LOG(LOG_LEVEL_INFO, "Received authentication request for user: %s",
username);
data = auth_userpass(username, password, &errorcode);
if (data)
{
if (1 == access_login_allowed(username))
{
/* the user is member of the correct groups. */
LOG(LOG_LEVEL_INFO, "Access permitted for user: %s",
username);
}
else
{
/* all first 32 are reserved for PAM errors */
errorcode = 32 + 3;
LOG(LOG_LEVEL_INFO, "Username okay but group problem for "
"user: %s", username);
}
}
else
{
/* g_writeln("username or password error"); */
LOG(LOG_LEVEL_INFO, "Username or password error for user: %s",
username);
}
rv = scp_send_gateway_response(trans, errorcode);
auth_end(data);
}
return rv;
}
/******************************************************************************/
static int
process_create_session_request(struct trans *trans)
{
int rv;
struct session_parameters sp;
const char *password;
struct guid guid;
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.connection_description);
if (rv == 0)
{
tbus data;
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);
data = auth_userpass(sp.username, password, &errorcode);
if (data)
{
s_item = session_get_bydata(&sp);
if (s_item != 0)
{
display = s_item->display;
guid = s_item->guid;
if (sp.connection_description[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.connection_description);
}
else
{
LOG(LOG_LEVEL_INFO, "++ reconnected session: username %s, "
"display :%d.0, session_pid %d", sp.username, display,
s_item->pid);
}
session_reconnect(display, sp.username, data);
}
else
{
LOG_DEVEL(LOG_LEVEL_DEBUG, "pre auth");
if (1 == access_login_allowed(sp.username))
{
if (sp.connection_description[0] != '\0')
{
LOG(LOG_LEVEL_INFO,
"++ created session (access granted): "
"username %s, ip %s", sp.username,
sp.connection_description);
}
else
{
LOG(LOG_LEVEL_INFO,
"++ created session (access granted): "
"username %s", sp.username);
}
display = session_start(data, &sp, &guid);
/* if the session started up ok, auth_end will be called on
sig child */
do_auth_end = display == 0;
}
}
}
else
{
char ip[64];
g_get_ip_from_description(sp.connection_description,
ip, sizeof(ip));
/*
* The message is intended for use by fail2ban, so for
* future-proofing we only log the IP address rather than the
* connection description */
LOG(LOG_LEVEL_INFO,
"AUTHFAIL: user=%s ip=%s time=%d",
sp.username, ip, g_time1());
}
if (do_auth_end)
{
auth_end(data);
}
rv = scp_send_create_session_response(trans, errorcode, display, &guid);
}
return rv;
}
/******************************************************************************/
static int
process_list_sessions_request(struct trans *trans)
{
int rv;
const char *username;
const char *password;
rv = scp_get_list_sessions_request(trans, &username, &password);
if (rv == 0)
{
enum scp_list_sessions_status status;
int errorcode = 0;
tbus data;
LOG(LOG_LEVEL_INFO,
"Received request to list sessions for user %s", username);
data = auth_userpass(username, password, &errorcode);
if (data)
{
struct scp_session_info *info = NULL;
unsigned int cnt = 0;
unsigned int i;
info = session_get_byuser(username, &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
{
status = E_SCP_LS_AUTHENTICATION_FAIL;
}
auth_end(data);
if (rv == 0)
{
rv = scp_send_list_sessions_response(trans, status, NULL);
}
}
return rv;
}
/******************************************************************************/
int
scp_process(struct trans *t)
{
enum scp_msg_code msgno;
int rv = 0;
switch ((msgno = scp_msg_in_start(t)))
{
case E_SCP_GATEWAY_REQUEST:
rv = process_gateway_request(t);
break;
case E_SCP_CREATE_SESSION_REQUEST:
rv = process_create_session_request(t);
break;
case E_SCP_LIST_SESSIONS_REQUEST:
rv = process_list_sessions_request(t);
break;
default:
{
char buff[64];
scp_msgno_to_str(msgno, buff, sizeof(buff));
LOG(LOG_LEVEL_ERROR, "Ignored SCP message %s", buff);
}
}
return rv;
}

View File

@ -18,18 +18,24 @@
/** /**
* *
* @file scp_v0.h * @file scp_process.h
* @brief scp version 0 declarations * @brief scp (sesman control protocol) handler function
* @author Simone Fedele * @author Simone Fedele
* *
*/ */
#ifndef SCP_V0_H #ifndef SCP_PROCESS_H
#define SCP_V0_H #define SCP_PROCESS_H
#include "libscp.h" struct trans;
enum SCP_SERVER_STATES_E /**
scp_v0_process(struct trans *t, struct SCP_SESSION *s); *
* @brief Processes an SCP message
* @param t the connection trans
*
*/
int
scp_process(struct trans *t);
#endif #endif

View File

@ -1,174 +0,0 @@
/**
* xrdp: A Remote Desktop Protocol server.
*
* Copyright (C) Jay Sorg 2004-2015
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
*
* @file scp_v0.c
* @brief scp version 0 implementation
* @author Jay Sorg, Simone Fedele
*
*/
#if defined(HAVE_CONFIG_H)
#include <config_ac.h>
#endif
#include "sesman.h"
/******************************************************************************/
enum SCP_SERVER_STATES_E
scp_v0_process(struct trans *t, struct SCP_SESSION *s)
{
int display = 0;
tbus data;
struct session_item *s_item;
int errorcode = 0;
bool_t do_auth_end = 1;
data = auth_userpass(s->username, s->password, &errorcode);
if (s->type == SCP_GW_AUTHENTICATION)
{
/* this is just authentication in a gateway situation */
/* g_writeln("SCP_GW_AUTHENTICATION message received"); */
if (data)
{
if (1 == access_login_allowed(s->username))
{
/* the user is member of the correct groups. */
scp_v0s_replyauthentication(t, errorcode);
LOG(LOG_LEVEL_INFO, "Access permitted for user: %s",
s->username);
/* g_writeln("Connection allowed"); */
}
else
{
scp_v0s_replyauthentication(t, 32 + 3); /* all first 32 are reserved for PAM errors */
LOG(LOG_LEVEL_INFO, "Username okay but group problem for "
"user: %s", s->username);
/* g_writeln("user password ok, but group problem"); */
}
}
else
{
/* g_writeln("username or password error"); */
LOG(LOG_LEVEL_INFO, "Username or password error for user: %s",
s->username);
scp_v0s_replyauthentication(t, errorcode);
}
}
else if (data)
{
s_item = session_get_bydata(s->username, s->width, s->height,
s->bpp, s->type, s->connection_description);
if (s_item != 0)
{
display = s_item->display;
s->guid = s_item->guid;
if (0 != s->connection_description)
{
LOG( LOG_LEVEL_INFO, "++ reconnected session: username %s, "
"display :%d.0, session_pid %d, ip %s",
s->username, display, s_item->pid,
s->connection_description);
}
else
{
LOG(LOG_LEVEL_INFO, "++ reconnected session: username %s, "
"display :%d.0, session_pid %d", s->username, display,
s_item->pid);
}
session_reconnect(display, s->username, data);
}
else
{
LOG_DEVEL(LOG_LEVEL_DEBUG, "pre auth");
if (1 == access_login_allowed(s->username))
{
struct guid guid = guid_new();
scp_session_set_guid(s, &guid);
if (0 != s->connection_description)
{
LOG(LOG_LEVEL_INFO, "++ created session (access granted): "
"username %s, ip %s", s->username, s->connection_description);
}
else
{
LOG(LOG_LEVEL_INFO, "++ created session (access granted): "
"username %s", s->username);
}
if (SCP_SESSION_TYPE_XVNC == s->type)
{
LOG( LOG_LEVEL_INFO, "starting Xvnc session...");
display = session_start(data, SESMAN_SESSION_TYPE_XVNC, s);
}
else if (SCP_SESSION_TYPE_XRDP == s->type)
{
LOG(LOG_LEVEL_INFO, "starting X11rdp session...");
display = session_start(data, SESMAN_SESSION_TYPE_XRDP, s);
}
else if (SCP_SESSION_TYPE_XORG == s->type)
{
/* type is SCP_SESSION_TYPE_XORG */
LOG(LOG_LEVEL_INFO, "starting Xorg session...");
display = session_start(data, SESMAN_SESSION_TYPE_XORG, s);
}
/* if the session started up ok, auth_end will be called on
sig child */
do_auth_end = display == 0;
}
else
{
display = 0;
}
}
if (display == 0)
{
scp_v0s_deny_connection(t);
}
else
{
scp_v0s_allow_connection(t, display, &s->guid);
}
}
else
{
char ip[64];
g_get_ip_from_description(s->connection_description, ip, sizeof(ip));
/*
* The message is intended for use by fail2ban, so for
* future-proofing we only log the IP address rather than the
* connection description */
LOG(LOG_LEVEL_INFO,
"AUTHFAIL: user=%s ip=%s time=%d",
s->username, ip, g_time1());
scp_v0s_deny_connection(t);
}
if (do_auth_end)
{
auth_end(data);
}
return SCP_SERVER_STATE_END;
}

View File

@ -1,307 +0,0 @@
/**
* xrdp: A Remote Desktop Protocol server.
*
* Copyright (C) Jay Sorg 2004-2015
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
*
* @file scp_v1.c
* @brief scp version 1 implementation
* @author Jay Sorg, Simone Fedele
*
*/
#if defined(HAVE_CONFIG_H)
#include <config_ac.h>
#endif
#include "sesman.h"
//#include "libscp_types.h"
#include "libscp.h"
static void
parseCommonStates(enum SCP_SERVER_STATES_E e, const char *f);
/******************************************************************************/
static enum SCP_SERVER_STATES_E
scp_v1_process1(struct trans *t, struct SCP_SESSION *s)
{
int display = 0;
int scount;
long data;
enum SCP_SERVER_STATES_E e;
struct SCP_DISCONNECTED_SESSION *slist;
bool_t do_auth_end = 1;
if (s->retries == 0)
{
/* First time in */
s->retries = g_cfg->sec.login_retry;
s->current_try = s->retries;
}
data = auth_userpass(s->username, s->password, NULL);
if (data == 0)
{
if ((s->retries == 0) || (s->current_try > 0))
{
e = scp_v1s_request_password(t, s, "Wrong username and/or "
"password");
switch (e)
{
case SCP_SERVER_STATE_OK:
/* one try less */
if (s->current_try > 0)
{
s->current_try--;
}
break;
default:
/* we check the other errors */
parseCommonStates(e, "scp_v1s_list_sessions()");
break;
}
}
else
{
char ip[64];
g_get_ip_from_description(s->connection_description,
ip, sizeof(ip));
/*
* The message is intended for use by fail2ban, so for
* future-proofing we only log the IP address rather than the
* connection description */
LOG(LOG_LEVEL_INFO,
"AUTHFAIL: user=%s ip=%s time=%d",
s->username, ip, g_time1());
scp_v1s_deny_connection(t, "Login failed");
return SCP_SERVER_STATE_END;
}
return SCP_SERVER_STATE_OK;
}
/* testing if login is allowed*/
if (0 == access_login_allowed(s->username))
{
scp_v1s_deny_connection(t, "Access to Terminal Server not allowed.");
LOG(LOG_LEVEL_INFO, "User %s not allowed on TS. "
"Connection terminated", s->username);
return SCP_SERVER_STATE_END;
}
//check if we need password change
/* list disconnected sessions */
slist = session_get_byuser(s->username, &scount,
SESMAN_SESSION_STATUS_DISCONNECTED);
if (scount == 0)
{
/* no disconnected sessions - start a new one */
LOG(LOG_LEVEL_DEBUG, "No disconnected sessions for this user "
"- we create a new one");
if (0 != s->connection_description)
{
LOG(LOG_LEVEL_INFO, "++ created session (access granted): "
"username %s, ip %s", s->username, s->connection_description);
}
else
{
LOG(LOG_LEVEL_INFO, "++ created session (access granted): "
"username %s", s->username);
}
if (SCP_SESSION_TYPE_XVNC == s->type)
{
LOG(LOG_LEVEL_INFO, "starting Xvnc session...");
display = session_start(data, SESMAN_SESSION_TYPE_XVNC, s);
}
else if (SCP_SESSION_TYPE_XRDP == s->type)
{
LOG(LOG_LEVEL_INFO, "starting X11rdp session...");
display = session_start(data, SESMAN_SESSION_TYPE_XRDP, s);
}
else if (SCP_SESSION_TYPE_XORG == s->type)
{
LOG(LOG_LEVEL_INFO, "starting Xorg session...");
display = session_start(data, SESMAN_SESSION_TYPE_XORG, s);
}
/* if the session started up ok, auth_end will be called on
sig child */
do_auth_end = display == 0;
e = scp_v1s_connect_new_session(t, display);
switch (e)
{
case SCP_SERVER_STATE_OK:
/* all ok, we got new username and password */
break;
default:
/* we check the other errors */
parseCommonStates(e, "scp_v1s_connect_new_session()");
break;
}
}
else
{
e = scp_v1s_list_sessions40(t);
}
/* cleanup */
if (do_auth_end)
{
auth_end(data);
}
g_free(slist);
return SCP_SERVER_STATE_OK;
}
/******************************************************************************/
static enum SCP_SERVER_STATES_E
scp_v1_process4(struct trans *t, struct SCP_SESSION *s)
{
return SCP_SERVER_STATE_OK;
}
/******************************************************************************/
static enum SCP_SERVER_STATES_E
scp_v1_process41(struct trans *t, struct SCP_SESSION *s)
{
int scount;
enum SCP_SERVER_STATES_E e;
struct SCP_DISCONNECTED_SESSION *slist;
/* list disconnected sessions */
slist = session_get_byuser(s->username, &scount,
SESMAN_SESSION_STATUS_DISCONNECTED);
if (scount == 0)
{
/* */
return SCP_SERVER_STATE_END;
}
e = scp_v1s_list_sessions42(t, scount, slist);
if (SCP_SERVER_STATE_OK != e)
{
LOG(LOG_LEVEL_WARNING, "scp_v1s_list_sessions42 failed");
}
return SCP_SERVER_STATE_OK;
}
/******************************************************************************/
static enum SCP_SERVER_STATES_E
scp_v1_process43(struct trans *t, struct SCP_SESSION *s)
{
struct session_item *sitem;
enum SCP_SERVER_STATES_E e;
int display;
sitem = session_get_bypid(s->return_sid);
if (0 == sitem)
{
e = scp_v1s_connection_error(t, "Internal error");
LOG(LOG_LEVEL_INFO, "No session exists with PID %d", s->return_sid);
}
else
{
display = sitem->display;
e = scp_v1s_reconnect_session(t, display);
if (SCP_SERVER_STATE_OK != e)
{
LOG(LOG_LEVEL_ERROR, "scp_v1s_reconnect_session failed");
}
if (0 != s->connection_description)
{
LOG(LOG_LEVEL_INFO, "++ reconnected session: username %s, display :%d.0, session_pid %d, ip %s", s->username, display, sitem->pid, s->connection_description);
}
else
{
LOG(LOG_LEVEL_INFO, "++ reconnected session: username %s, display :%d.0, session_pid %d", s->username, display, sitem->pid);
}
g_free(sitem);
}
return e;
}
/******************************************************************************/
static enum SCP_SERVER_STATES_E
scp_v1_process44(struct trans *t, struct SCP_SESSION *s)
{
return SCP_SERVER_STATE_OK;
}
/******************************************************************************/
static enum SCP_SERVER_STATES_E
scp_v1_process45(struct trans *t, struct SCP_SESSION *s)
{
return SCP_SERVER_STATE_OK;
}
/******************************************************************************/
enum SCP_SERVER_STATES_E
scp_v1_process(struct trans *t, struct SCP_SESSION *s)
{
; /* astyle 3.1 needs this, or the switch is badly formatted */
switch (s->current_cmd)
{
case SCP_CMD_LOGIN:
return scp_v1_process1(t, s);
case SCP_CMD_RESEND_CREDS:
return scp_v1_process4(t, s);
case SCP_CMD_GET_SESSION_LIST:
return scp_v1_process41(t, s);
case SCP_CMD_SELECT_SESSION:
return scp_v1_process43(t, s);
case SCP_CMD_SELECT_SESSION_CANCEL:
return scp_v1_process44(t, s);
case SCP_CMD_FORCE_NEW_CONN:
return scp_v1_process45(t, s);
}
return SCP_SERVER_STATE_END;
}
static void
parseCommonStates(enum SCP_SERVER_STATES_E e, const char *f)
{
switch (e)
{
case SCP_SERVER_STATE_VERSION_ERR:
LOG(LOG_LEVEL_WARNING, "version error");
case SCP_SERVER_STATE_SIZE_ERR:
/* an unknown scp version was requested, so we shut down the */
/* connection (and log the fact) */
LOG(LOG_LEVEL_WARNING,
"protocol violation. connection closed.");
break;
case SCP_SERVER_STATE_NETWORK_ERR:
LOG(LOG_LEVEL_WARNING, "libscp network error.");
break;
case SCP_SERVER_STATE_SEQUENCE_ERR:
LOG(LOG_LEVEL_WARNING, "libscp sequence error.");
break;
case SCP_SERVER_STATE_INTERNAL_ERR:
/* internal error occurred (eg. malloc() error, ecc.) */
LOG(LOG_LEVEL_ERROR, "libscp internal error occurred.");
break;
default:
/* dummy: scp_v1s_request_password won't generate any other */
/* error other than the ones before */
LOG(LOG_LEVEL_ALWAYS, "unknown return from %s", f);
break;
}
}

View File

@ -1,41 +0,0 @@
/**
* xrdp: A Remote Desktop Protocol server.
*
* Copyright (C) Jay Sorg 2004-2013
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
*
* @file scp_v1.h
* @brief scp version 1 declarations
* @author Simone Fedele
*
*/
#ifndef SCP_V1_H
#define SCP_V1_H
/**
*
* @brief processes the stream using scp version 1
* @param in_sck connection socket
* @param in_s input stream
* @param out_s output stream
*
*/
enum SCP_SERVER_STATES_E
scp_v1_process(struct trans *t, struct SCP_SESSION *s);
#endif

View File

@ -1,134 +0,0 @@
/**
* xrdp: A Remote Desktop Protocol server.
*
* Copyright (C) Jay Sorg 2004-2013
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
*
* @file scp_v1_mng.c
* @brief scp version 1 implementation - management
* @author Jay Sorg, Simone Fedele
*
*/
#if defined(HAVE_CONFIG_H)
#include <config_ac.h>
#endif
#include "sesman.h"
#include "libscp.h"
static void parseCommonStates(enum SCP_SERVER_STATES_E e, const char *f);
/******************************************************************************/
enum SCP_SERVER_STATES_E
scp_v1_mng_process_msg(struct trans *atrans, struct SCP_SESSION *s)
{
long data;
enum SCP_SERVER_STATES_E e;
struct SCP_DISCONNECTED_SESSION *slist = 0;
int scount;
int end = 0;
data = auth_userpass(s->username, s->password, NULL);
/*LOG_DEVEL(LOG_LEVEL_DEBUG, "user: %s\npass: %s", s->username, s->password);*/
if (!data)
{
scp_v1s_mng_deny_connection(atrans, "Login failed");
LOG(LOG_LEVEL_INFO,
"[MNG] Login failed for user %s. Connection terminated", s->username);
auth_end(data);
return SCP_SERVER_STATE_END;
}
/* testing if login is allowed */
if (0 == access_login_mng_allowed(s->username))
{
scp_v1s_mng_deny_connection(atrans, "Access to Terminal Server not allowed.");
LOG(LOG_LEVEL_INFO,
"[MNG] User %s not allowed on TS. Connection terminated", s->username);
auth_end(data);
return SCP_SERVER_STATE_END;
}
e = scp_v1s_mng_allow_connection(atrans, s);
end = 1;
while (end)
{
switch (e)
{
case SCP_SERVER_STATE_MNG_ACTION:
LOG(LOG_LEVEL_INFO, "Connection cancelled after session listing");
break;
case SCP_SERVER_STATE_MNG_LISTREQ:
/* list disconnected sessions */
slist = session_get_byuser(NULL, &scount, SESMAN_SESSION_STATUS_ALL);
LOG_DEVEL(LOG_LEVEL_DEBUG, "sessions on TS: %d (slist: %p)", scount, slist);
if (0 == slist)
{
LOG(LOG_LEVEL_INFO, "No sessions on Terminal Server");
}
e = scp_v1s_mng_list_sessions(atrans, s, scount, slist);
g_free(slist);
break;
default:
/* we check the other errors */
parseCommonStates(e, "scp_v1s_mng_list_sessions()");
end = 0;
break;
}
}
/* cleanup */
auth_end(data);
return SCP_SERVER_STATE_END;
}
static void parseCommonStates(enum SCP_SERVER_STATES_E e, const char *f)
{
switch (e)
{
case SCP_SERVER_STATE_VERSION_ERR:
LOG(LOG_LEVEL_WARNING, "version error");
case SCP_SERVER_STATE_SIZE_ERR:
/* an unknown scp version was requested, so we shut down the */
/* connection (and log the fact) */
LOG(LOG_LEVEL_WARNING,
"protocol violation. connection closed.");
break;
case SCP_SERVER_STATE_NETWORK_ERR:
LOG(LOG_LEVEL_WARNING, "libscp network error.");
break;
case SCP_SERVER_STATE_SEQUENCE_ERR:
LOG(LOG_LEVEL_WARNING, "libscp sequence error.");
break;
case SCP_SERVER_STATE_INTERNAL_ERR:
/* internal error occurred (eg. malloc() error, ecc.) */
LOG(LOG_LEVEL_ERROR, "libscp internal error occurred.");
break;
default:
/* dummy: scp_v1s_request_password won't generate any other */
/* error other than the ones before */
LOG(LOG_LEVEL_ALWAYS, "unknown return from %s", f);
break;
}
}

View File

@ -1,40 +0,0 @@
/**
* xrdp: A Remote Desktop Protocol server.
*
* Copyright (C) Jay Sorg 2004-2013
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
*
* @file scp_v1.h
* @brief scp version 1 declarations - management
* @author Simone Fedele
*
*/
#ifndef SCP_V1_MNG_H
#define SCP_V1_MNG_H
/**
*
* @brief processes the stream using scp version 1
* @param atrans incoming transport
* @param s incoming session details
*
*/
enum SCP_SERVER_STATES_E
scp_v1_mng_process_msg(struct trans *atrans, struct SCP_SESSION *s);
#endif

View File

@ -33,6 +33,9 @@
#include "sesman.h" #include "sesman.h"
#include "xrdp_configure_options.h" #include "xrdp_configure_options.h"
#include "string_calls.h" #include "string_calls.h"
#include "trans.h"
#include "scp_process.h"
/** /**
* Maximum number of short-lived connections to sesman * Maximum number of short-lived connections to sesman
@ -64,7 +67,6 @@ tintptr g_reload_event = 0;
struct sesman_con struct sesman_con
{ {
struct trans *t; struct trans *t;
struct SCP_SESSION *s;
}; };
static struct trans *g_list_trans; static struct trans *g_list_trans;
@ -108,22 +110,10 @@ static struct sesman_con *
alloc_connection(struct trans *t) alloc_connection(struct trans *t)
{ {
struct sesman_con *result; struct sesman_con *result;
struct SCP_SESSION *s;
if ((result = g_new(struct sesman_con, 1)) != NULL) if ((result = g_new(struct sesman_con, 1)) != NULL)
{ {
if ((s = scp_session_create()) != NULL) result->t = t;
{
result->t = t;
result->s = s;
/* Ensure we can find the connection easily from a callback */
t->callback_data = (void *)result;
}
else
{
g_free(result);
result = NULL;
}
} }
return result; return result;
@ -141,7 +131,6 @@ static void
delete_connection(struct sesman_con *sc) delete_connection(struct sesman_con *sc)
{ {
trans_delete(sc->t); trans_delete(sc->t);
scp_session_destroy(sc->s);
g_free(sc); g_free(sc);
} }
@ -232,7 +221,7 @@ static int sesman_listen_test(struct config_sesman *cfg)
LOG(LOG_LEVEL_DEBUG, "Testing if xrdp-sesman can listen on %s port %s.", LOG(LOG_LEVEL_DEBUG, "Testing if xrdp-sesman can listen on %s port %s.",
cfg->listen_address, cfg->listen_port); cfg->listen_address, cfg->listen_port);
g_tcp_set_non_blocking(sck); g_tcp_set_non_blocking(sck);
error = scp_tcp_bind(sck, cfg->listen_address, cfg->listen_port); error = g_tcp_bind_address(sck, cfg->listen_port, cfg->listen_address);
if (error == 0) if (error == 0)
{ {
/* try to listen */ /* try to listen */
@ -277,39 +266,21 @@ sesman_close_all(void)
static int static int
sesman_data_in(struct trans *self) sesman_data_in(struct trans *self)
{ {
#define HEADER_SIZE 8 int rv;
int version; int available;
int size;
if (self->extra_flags == 0) rv = scp_msg_in_check_available(self, &available);
if (rv == 0 && available)
{ {
in_uint32_be(self->in_s, version); if ((rv = scp_process(self)) != 0)
in_uint32_be(self->in_s, size);
if (size < HEADER_SIZE || size > self->in_s->size)
{
LOG(LOG_LEVEL_ERROR, "sesman_data_in: bad message size %d", size);
return 1;
}
self->header_size = size;
self->extra_flags = 1;
}
else
{
/* process message */
struct sesman_con *sc = (struct sesman_con *)self->callback_data;
self->in_s->p = self->in_s->data;
if (scp_process(self, sc->s) != SCP_SERVER_STATE_OK)
{ {
LOG(LOG_LEVEL_ERROR, "sesman_data_in: scp_process_msg failed"); LOG(LOG_LEVEL_ERROR, "sesman_data_in: scp_process_msg failed");
return 1;
} }
/* reset for next message */ scp_msg_in_reset(self);
self->header_size = HEADER_SIZE;
self->extra_flags = 0;
init_stream(self->in_s, 0); /* Reset input stream pointers */
} }
return 0;
#undef HEADER_SIZE return rv;
} }
/******************************************************************************/ /******************************************************************************/
@ -323,7 +294,8 @@ sesman_listen_conn_in(struct trans *self, struct trans *new_self)
"connections, rejecting"); "connections, rejecting");
trans_delete(new_self); trans_delete(new_self);
} }
else if ((sc = alloc_connection(new_self)) == NULL) else if ((sc = alloc_connection(new_self)) == 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");
@ -331,10 +303,8 @@ sesman_listen_conn_in(struct trans *self, struct trans *new_self)
} }
else else
{ {
new_self->header_size = 8; new_self->callback_data = (void *)sc;
new_self->trans_data_in = sesman_data_in; new_self->trans_data_in = sesman_data_in;
new_self->no_stream_init_on_data_in = 1;
new_self->extra_flags = 0;
list_add_item(g_con_list, (intptr_t) sc); list_add_item(g_con_list, (intptr_t) sc);
} }
@ -775,10 +745,6 @@ main(int argc, char **argv)
} }
} }
/* libscp initialization */
scp_init();
if (daemon) if (daemon)
{ {
/* start of daemonizing code */ /* start of daemonizing code */

View File

@ -39,8 +39,6 @@
#include "access.h" #include "access.h"
#include "scp.h" #include "scp.h"
#include "libscp.h"
/* Globals */ /* Globals */
extern struct config_sesman *g_cfg; extern struct config_sesman *g_cfg;
extern unsigned char g_fixedkey[8]; extern unsigned char g_fixedkey[8];

View File

@ -38,7 +38,6 @@
#endif #endif
#include "sesman.h" #include "sesman.h"
#include "libscp_types.h"
#include "xauth.h" #include "xauth.h"
#include "xrdp_sockets.h" #include "xrdp_sockets.h"
#include "string_calls.h" #include "string_calls.h"
@ -87,58 +86,38 @@ dumpItemsToString(struct list *self, char *outstr, int len)
/******************************************************************************/ /******************************************************************************/
struct session_item * struct session_item *
session_get_bydata(const char *name, int width, int height, int bpp, int type, session_get_bydata(const struct session_parameters *sp)
const char *connection_description)
{ {
struct session_chain *tmp; struct session_chain *tmp;
enum SESMAN_CFG_SESS_POLICY policy = g_cfg->sess.policy; enum SESMAN_CFG_SESS_POLICY policy = g_cfg->sess.policy;
char ip[64]; char ip[64];
char tmp_ip[64];
tmp = g_sessions;
/* convert from SCP_SESSION_TYPE namespace to SESMAN_SESSION_TYPE namespace */
switch (type)
{
case SCP_SESSION_TYPE_XVNC: /* 0 */
type = SESMAN_SESSION_TYPE_XVNC; /* 2 */
break;
case SCP_SESSION_TYPE_XRDP: /* 1 */
type = SESMAN_SESSION_TYPE_XRDP; /* 1 */
break;
case SCP_SESSION_TYPE_XORG:
type = SESMAN_SESSION_TYPE_XORG;
break;
default:
return 0;
}
if ((policy & SESMAN_CFG_SESS_POLICY_I) != 0) if ((policy & SESMAN_CFG_SESS_POLICY_I) != 0)
{ {
/* We'll need to compare on IP addresses */ /* We'll need to compare on IP addresses */
g_get_ip_from_description(connection_description, ip, sizeof(ip)); g_get_ip_from_description(sp->connection_description,
ip, sizeof(ip));
} }
else else
{ {
ip[0] = '\0'; ip[0] = '\0';
tmp_ip[0] = '\0';
} }
LOG(LOG_LEVEL_DEBUG, LOG(LOG_LEVEL_DEBUG,
"session_get_bydata: search policy %d U %s W %d H %d bpp %d T %d IP %s", "session_get_bydata: search policy %d U %s W %d H %d bpp %d T %d IP %s",
policy, name, width, height, bpp, type, connection_description); policy, sp->username, sp->width, sp->height, sp->bpp,
sp->type, sp->connection_description);
while (tmp != 0) for (tmp = g_sessions ; tmp != 0 ; tmp = tmp->next)
{ {
char tmp_ip[64];
if ((policy & SESMAN_CFG_SESS_POLICY_I) != 0) if ((policy & SESMAN_CFG_SESS_POLICY_I) != 0)
{ {
g_get_ip_from_description(tmp->item->connection_description, g_get_ip_from_description(tmp->item->connection_description,
tmp_ip, sizeof (tmp_ip)); tmp_ip, sizeof (tmp_ip));
} }
else
{
tmp_ip[0] = '\0';
}
LOG(LOG_LEVEL_DEBUG, LOG(LOG_LEVEL_DEBUG,
"session_get_bydata: try %p U %s W %d H %d bpp %d T %d IP %s", "session_get_bydata: try %p U %s W %d H %d bpp %d T %d IP %s",
@ -148,20 +127,39 @@ session_get_bydata(const char *name, int width, int height, int bpp, int type,
tmp->item->bpp, tmp->item->type, tmp->item->bpp, tmp->item->type,
tmp->item->connection_description); tmp->item->connection_description);
if (g_strncmp(name, tmp->item->name, 255) == 0 && if (g_strncmp(sp->username, tmp->item->name, 255) != 0 ||
(!(policy & SESMAN_CFG_SESS_POLICY_D) || tmp->item->bpp != sp->bpp ||
(tmp->item->width == width && tmp->item->height == height)) && tmp->item->type != sp->type)
(!(policy & SESMAN_CFG_SESS_POLICY_I) ||
(g_strcmp(ip, tmp_ip) == 0)) &&
(!(policy & SESMAN_CFG_SESS_POLICY_C) ||
(g_strncmp(connection_description, tmp->item->connection_description, 255) == 0)) &&
tmp->item->bpp == bpp &&
tmp->item->type == type)
{ {
return tmp->item; LOG(LOG_LEVEL_DEBUG,
"session_get_bydata: Basic parameters don't match");
continue;
} }
tmp = tmp->next; if ((policy & SESMAN_CFG_SESS_POLICY_D) &&
(tmp->item->width != sp->width || tmp->item->height != sp->height))
{
LOG(LOG_LEVEL_DEBUG,
"session_get_bydata: Dimensions don't match for 'D' policy");
continue;
}
if ((policy & SESMAN_CFG_SESS_POLICY_I) && g_strcmp(ip, tmp_ip) != 0)
{
LOG(LOG_LEVEL_DEBUG,
"session_get_bydata: IPs don't match for 'I' policy");
continue;
}
if ((policy & SESMAN_CFG_SESS_POLICY_C) &&
g_strncmp(sp->connection_description, tmp->item->connection_description, 255) != 0)
{
LOG(LOG_LEVEL_DEBUG,
"session_get_bydata: connections don't match for 'C' policy");
}
LOG(LOG_LEVEL_DEBUG, "session_get_bydata: Got match");
return tmp->item;
} }
return 0; return 0;
@ -390,7 +388,7 @@ wait_for_xserver(int display)
/******************************************************************************/ /******************************************************************************/
static int static int
session_start_chansrv(char *username, int display) session_start_chansrv(const char *username, int display)
{ {
struct list *chansrv_params; struct list *chansrv_params;
char exe_path[262]; char exe_path[262];
@ -427,9 +425,11 @@ session_start_chansrv(char *username, int display)
} }
/******************************************************************************/ /******************************************************************************/
/* called with the main thread */
static int int
session_start_fork(tbus data, tui8 type, struct SCP_SESSION *s) session_start(long data,
const struct session_parameters *s,
struct guid *guid)
{ {
int display = 0; int display = 0;
int pid = 0; int pid = 0;
@ -443,16 +443,12 @@ session_start_fork(tbus data, tui8 type, struct SCP_SESSION *s)
char **pp1 = (char **)NULL; char **pp1 = (char **)NULL;
struct session_chain *temp = (struct session_chain *)NULL; struct session_chain *temp = (struct session_chain *)NULL;
struct list *xserver_params = (struct list *)NULL; struct list *xserver_params = (struct list *)NULL;
struct tm stime;
time_t ltime;
char authfile[256]; /* The filename for storing xauth informations */ char authfile[256]; /* The filename for storing xauth informations */
int chansrv_pid; int chansrv_pid;
int display_pid; int display_pid;
int window_manager_pid; int window_manager_pid;
/* initialize (zero out) local variables: */ /* initialize (zero out) local variables: */
g_memset(&ltime, 0, sizeof(time_t));
g_memset(&stime, 0, sizeof(struct tm));
g_memset(geometry, 0, sizeof(char) * 32); g_memset(geometry, 0, sizeof(char) * 32);
g_memset(depth, 0, sizeof(char) * 32); g_memset(depth, 0, sizeof(char) * 32);
g_memset(screen, 0, sizeof(char) * 32); g_memset(screen, 0, sizeof(char) * 32);
@ -496,6 +492,9 @@ session_start_fork(tbus data, tui8 type, struct SCP_SESSION *s)
return 0; return 0;
} }
/* Create a GUID for the new session before we work */
*guid = guid_new();
pid = g_fork(); /* parent is fork from tcp accept, pid = g_fork(); /* parent is fork from tcp accept,
child forks X and wm, then becomes scp */ child forks X and wm, then becomes scp */
@ -514,7 +513,7 @@ session_start_fork(tbus data, tui8 type, struct SCP_SESSION *s)
/* Clone the session object, as the passed-in copy will be /* Clone the session object, as the passed-in copy will be
* deleted by sesman_close_all() */ * deleted by sesman_close_all() */
if ((s = scp_session_clone(s)) == NULL) if ((s = clone_session_params(s)) == NULL)
{ {
LOG(LOG_LEVEL_ERROR, LOG(LOG_LEVEL_ERROR,
"Failed to clone the session data - out of memory"); "Failed to clone the session data - out of memory");
@ -603,23 +602,23 @@ session_start_fork(tbus data, tui8 type, struct SCP_SESSION *s)
g_set_current_dir(s->directory); g_set_current_dir(s->directory);
} }
} }
if (s->program != 0 && s->program[0] != 0) if (s->shell != 0 && s->shell[0] != 0)
{ {
if (g_strchr(s->program, ' ') != 0 || g_strchr(s->program, '\t') != 0) if (g_strchr(s->shell, ' ') != 0 || g_strchr(s->shell, '\t') != 0)
{ {
LOG(LOG_LEVEL_INFO, LOG(LOG_LEVEL_INFO,
"Starting user requested window manager on " "Starting user requested window manager on "
"display %d with embeded arguments using a shell: %s", "display %d with embeded arguments using a shell: %s",
display, s->program); display, s->shell);
const char *params[] = {"sh", "-c", s->program, NULL}; const char *argv[] = {"sh", "-c", s->shell, NULL};
g_execvp("/bin/sh", (char **)params); g_execvp("/bin/sh", (char **)argv);
} }
else else
{ {
LOG(LOG_LEVEL_INFO, LOG(LOG_LEVEL_INFO,
"Starting user requested window manager on " "Starting user requested window manager on "
"display %d: %s", display, s->program); "display %d: %s", display, s->shell);
g_execlp3(s->program, s->program, 0); g_execlp3(s->shell, s->shell, 0);
} }
} }
else else
@ -684,7 +683,7 @@ session_start_fork(tbus data, tui8 type, struct SCP_SESSION *s)
} }
else if (display_pid == 0) /* child */ else if (display_pid == 0) /* child */
{ {
if (type == SESMAN_SESSION_TYPE_XVNC) if (s->type == SCP_SESSION_TYPE_XVNC)
{ {
env_set_user(s->username, env_set_user(s->username,
&passwd_file, &passwd_file,
@ -733,7 +732,7 @@ session_start_fork(tbus data, tui8 type, struct SCP_SESSION *s)
g_exit(1); g_exit(1);
} }
if (type == SESMAN_SESSION_TYPE_XORG) if (s->type == SCP_SESSION_TYPE_XORG)
{ {
#ifdef HAVE_SYS_PRCTL_H #ifdef HAVE_SYS_PRCTL_H
/* /*
@ -778,10 +777,10 @@ session_start_fork(tbus data, tui8 type, struct SCP_SESSION *s)
g_sprintf(geometry, "%d", s->height); g_sprintf(geometry, "%d", s->height);
g_setenv("XRDP_START_HEIGHT", geometry, 1); g_setenv("XRDP_START_HEIGHT", geometry, 1);
} }
else if (type == SESMAN_SESSION_TYPE_XVNC) else if (s->type == SCP_SESSION_TYPE_XVNC)
{ {
char guid_str[GUID_STR_SIZE]; char guid_str[GUID_STR_SIZE];
guid_to_str(&s->guid, guid_str); guid_to_str(guid, guid_str);
env_check_password_file(passwd_file, guid_str); env_check_password_file(passwd_file, guid_str);
xserver_params = list_create(); xserver_params = list_create();
xserver_params->auto_free = 1; xserver_params->auto_free = 1;
@ -804,7 +803,7 @@ session_start_fork(tbus data, tui8 type, struct SCP_SESSION *s)
g_free(passwd_file); g_free(passwd_file);
/* additional parameters from sesman.ini file */ /* additional parameters from sesman.ini file */
//config_read_xserver_params(SESMAN_SESSION_TYPE_XVNC, //config_read_xserver_params(SCP_SESSION_TYPE_XVNC,
// xserver_params); // xserver_params);
list_append_list_strdup(g_cfg->vnc_params, xserver_params, 1); list_append_list_strdup(g_cfg->vnc_params, xserver_params, 1);
@ -812,7 +811,7 @@ session_start_fork(tbus data, tui8 type, struct SCP_SESSION *s)
list_add_item(xserver_params, 0); list_add_item(xserver_params, 0);
pp1 = (char **)xserver_params->items; pp1 = (char **)xserver_params->items;
} }
else if (type == SESMAN_SESSION_TYPE_XRDP) else if (s->type == SCP_SESSION_TYPE_XRDP)
{ {
xserver_params = list_create(); xserver_params = list_create();
xserver_params->auto_free = 1; xserver_params->auto_free = 1;
@ -831,7 +830,7 @@ session_start_fork(tbus data, tui8 type, struct SCP_SESSION *s)
list_add_item(xserver_params, (tintptr)g_strdup(depth)); list_add_item(xserver_params, (tintptr)g_strdup(depth));
/* additional parameters from sesman.ini file */ /* additional parameters from sesman.ini file */
//config_read_xserver_params(SESMAN_SESSION_TYPE_XRDP, //config_read_xserver_params(SCP_SESSION_TYPE_XRDP,
// xserver_params); // xserver_params);
list_append_list_strdup(g_cfg->rdp_params, xserver_params, 1); list_append_list_strdup(g_cfg->rdp_params, xserver_params, 1);
@ -841,7 +840,8 @@ session_start_fork(tbus data, tui8 type, struct SCP_SESSION *s)
} }
else else
{ {
LOG(LOG_LEVEL_ERROR, "Unknown session type: %d", type); LOG(LOG_LEVEL_ERROR, "Unknown session type: %d",
s->type);
LOG(LOG_LEVEL_ERROR, "A fatal error has occured attempting " LOG(LOG_LEVEL_ERROR, "A fatal error has occured attempting "
"to start the X server on display %d, aborting connection", "to start the X server on display %d, aborting connection",
display); display);
@ -958,19 +958,11 @@ session_start_fork(tbus data, tui8 type, struct SCP_SESSION *s)
temp->item->data = data; temp->item->data = data;
g_strncpy(temp->item->connection_description, s->connection_description, 255); /* store client ip data */ g_strncpy(temp->item->connection_description, s->connection_description, 255); /* store client ip data */
g_strncpy(temp->item->name, s->username, 255); g_strncpy(temp->item->name, s->username, 255);
temp->item->guid = s->guid; temp->item->guid = *guid;
ltime = g_time1(); temp->item->start_time = g_time1();
localtime_r(&ltime, &stime);
temp->item->connect_time.year = (tui16)(stime.tm_year + 1900);
temp->item->connect_time.month = (tui8)(stime.tm_mon + 1);
temp->item->connect_time.day = (tui8)stime.tm_mday;
temp->item->connect_time.hour = (tui8)stime.tm_hour;
temp->item->connect_time.minute = (tui8)stime.tm_min;
zero_time(&(temp->item->disconnect_time));
zero_time(&(temp->item->idle_time));
temp->item->type = type; temp->item->type = s->type;
temp->item->status = SESMAN_SESSION_STATUS_ACTIVE; temp->item->status = SESMAN_SESSION_STATUS_ACTIVE;
temp->next = g_sessions; temp->next = g_sessions;
@ -986,9 +978,8 @@ session_start_fork(tbus data, tui8 type, struct SCP_SESSION *s)
} }
/******************************************************************************/ /******************************************************************************/
/* called with the main thread */ int
static int session_reconnect(int display, const char *username, long data)
session_reconnect_fork(int display, char *username, long data)
{ {
int pid; int pid;
@ -1035,25 +1026,7 @@ session_reconnect_fork(int display, char *username, long data)
} }
/******************************************************************************/ /******************************************************************************/
/* called by a worker thread, ask the main thread to call session_sync_start enum session_kill_status
and wait till done */
int
session_start(long data, tui8 type, struct SCP_SESSION *s)
{
return session_start_fork(data, type, s);
}
/******************************************************************************/
/* called by a worker thread, ask the main thread to call session_sync_start
and wait till done */
int
session_reconnect(int display, char *username, long data)
{
return session_reconnect_fork(display, username, data);
}
/******************************************************************************/
int
session_kill(int pid) session_kill(int pid)
{ {
struct session_chain *tmp; struct session_chain *tmp;
@ -1180,11 +1153,11 @@ session_get_bypid(int pid)
} }
/******************************************************************************/ /******************************************************************************/
struct SCP_DISCONNECTED_SESSION * struct scp_session_info *
session_get_byuser(const char *user, int *cnt, unsigned char flags) session_get_byuser(const char *user, unsigned int *cnt, unsigned char flags)
{ {
struct session_chain *tmp; struct session_chain *tmp;
struct SCP_DISCONNECTED_SESSION *sess; struct scp_session_info *sess;
int count; int count;
int index; int index;
@ -1218,7 +1191,7 @@ session_get_byuser(const char *user, int *cnt, unsigned char flags)
} }
/* malloc() an array of disconnected sessions */ /* malloc() an array of disconnected sessions */
sess = g_new0(struct SCP_DISCONNECTED_SESSION, count); sess = g_new0(struct scp_session_info, count);
if (sess == 0) if (sess == 0)
{ {
@ -1229,43 +1202,31 @@ session_get_byuser(const char *user, int *cnt, unsigned char flags)
tmp = g_sessions; tmp = g_sessions;
index = 0; index = 0;
while (tmp != 0) while (tmp != 0 && index < count)
{ {
/* #warning FIXME: we should get only disconnected sessions! */ /* #warning FIXME: we should get only disconnected sessions! */
if ((NULL == user) || (!g_strncasecmp(user, tmp->item->name, 256))) if ((NULL == user) || (!g_strncasecmp(user, tmp->item->name, 256)))
{ {
if ((tmp->item->status) & flags) if ((tmp->item->status) & flags)
{ {
(sess[index]).SID = tmp->item->pid; (sess[index]).sid = tmp->item->pid;
(sess[index]).display = tmp->item->display;
(sess[index]).type = tmp->item->type; (sess[index]).type = tmp->item->type;
(sess[index]).height = tmp->item->height; (sess[index]).height = tmp->item->height;
(sess[index]).width = tmp->item->width; (sess[index]).width = tmp->item->width;
(sess[index]).bpp = tmp->item->bpp; (sess[index]).bpp = tmp->item->bpp;
/* #warning FIXME: setting idle times and such */ (sess[index]).start_time = tmp->item->start_time;
/*(sess[index]).connect_time.year = tmp->item->connect_time.year; (sess[index]).username = g_strdup(tmp->item->name);
(sess[index]).connect_time.month = tmp->item->connect_time.month; (sess[index]).connection_description =
(sess[index]).connect_time.day = tmp->item->connect_time.day; g_strdup(tmp->item->connection_description);
(sess[index]).connect_time.hour = tmp->item->connect_time.hour;
(sess[index]).connect_time.minute = tmp->item->connect_time.minute;
(sess[index]).disconnect_time.year = tmp->item->disconnect_time.year;
(sess[index]).disconnect_time.month = tmp->item->disconnect_time.month;
(sess[index]).disconnect_time.day = tmp->item->disconnect_time.day;
(sess[index]).disconnect_time.hour = tmp->item->disconnect_time.hour;
(sess[index]).disconnect_time.minute = tmp->item->disconnect_time.minute;
(sess[index]).idle_time.year = tmp->item->idle_time.year;
(sess[index]).idle_time.month = tmp->item->idle_time.month;
(sess[index]).idle_time.day = tmp->item->idle_time.day;
(sess[index]).idle_time.hour = tmp->item->idle_time.hour;
(sess[index]).idle_time.minute = tmp->item->idle_time.minute;*/
(sess[index]).conn_year = tmp->item->connect_time.year;
(sess[index]).conn_month = tmp->item->connect_time.month;
(sess[index]).conn_day = tmp->item->connect_time.day;
(sess[index]).conn_hour = tmp->item->connect_time.hour;
(sess[index]).conn_minute = tmp->item->connect_time.minute;
(sess[index]).idle_days = tmp->item->idle_time.day;
(sess[index]).idle_hours = tmp->item->idle_time.hour;
(sess[index]).idle_minutes = tmp->item->idle_time.minute;
if ((sess[index]).username == NULL ||
(sess[index]).connection_description == NULL)
{
free_session_info_list(sess, *cnt);
(*cnt) = 0;
return 0;
}
index++; index++;
} }
} }
@ -1278,6 +1239,23 @@ session_get_byuser(const char *user, int *cnt, unsigned char flags)
return sess; return sess;
} }
/******************************************************************************/
void
free_session_info_list(struct scp_session_info *sesslist, unsigned int cnt)
{
if (sesslist != NULL && cnt > 0)
{
unsigned int i;
for (i = 0 ; i < cnt ; ++i)
{
g_free(sesslist[i].username);
g_free(sesslist[i].connection_description);
}
}
g_free(sesslist);
}
/******************************************************************************/ /******************************************************************************/
int int
cleanup_sockets(int display) cleanup_sockets(int display)
@ -1372,3 +1350,45 @@ cleanup_sockets(int display)
return error; return error;
} }
/******************************************************************************/
struct session_parameters *
clone_session_params(const struct session_parameters *sp)
{
struct session_parameters *result;
char *strptr;
/* 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->connection_description) + 1;
if ((result = (struct session_parameters *)g_malloc(len, 0)) != NULL)
{
*result = *sp; /* Copy all the scalar parameters */
/* Initialise the string pointers in the result */
strptr = (char *)result + sizeof(*result);
#define COPY_STRING_MEMBER(src,dest)\
{\
unsigned int len = g_strlen(src) + 1;\
g_memcpy(strptr, (src), len);\
(dest) = strptr;\
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->connection_description,
result->connection_description);
#undef COPY_STRING_MEMBER
}
return result;
}

View File

@ -28,12 +28,10 @@
#ifndef SESSION_H #ifndef SESSION_H
#define SESSION_H #define SESSION_H
#include "libscp_types.h" #include <time.h>
#include "guid.h"
#define SESMAN_SESSION_TYPE_XRDP 1 #include "guid.h"
#define SESMAN_SESSION_TYPE_XVNC 2 #include "scp_application_types.h"
#define SESMAN_SESSION_TYPE_XORG 3
#define SESMAN_SESSION_STATUS_ACTIVE 0x01 #define SESMAN_SESSION_STATUS_ACTIVE 0x01
#define SESMAN_SESSION_STATUS_IDLE 0x02 #define SESMAN_SESSION_STATUS_IDLE 0x02
@ -43,20 +41,14 @@
*/ */
#define SESMAN_SESSION_STATUS_ALL 0xFF #define SESMAN_SESSION_STATUS_ALL 0xFF
#define SESMAN_SESSION_KILL_OK 0 enum session_kill_status
#define SESMAN_SESSION_KILL_NULLITEM 1
#define SESMAN_SESSION_KILL_NOTFOUND 2
struct session_date
{ {
tui16 year; SESMAN_SESSION_KILL_OK = 0,
tui8 month; SESMAN_SESSION_KILL_NULLITEM,
tui8 day; SESMAN_SESSION_KILL_NOTFOUND
tui8 hour;
tui8 minute;
}; };
#define zero_time(s) { (s)->year=0; (s)->month=0; (s)->day=0; (s)->hour=0; (s)->minute=0; } struct scp_session_info;
struct session_item struct session_item
{ {
@ -70,12 +62,12 @@ struct session_item
/* status info */ /* status info */
unsigned char status; unsigned char status;
unsigned char type; enum scp_session_type type;
/* time data */ /* time data */
struct session_date connect_time; time_t start_time;
struct session_date disconnect_time; // struct session_date disconnect_time; // Currently unused
struct session_date idle_time; // struct session_date idle_time; // Currently unused
char connection_description[256]; char connection_description[256];
struct guid guid; struct guid guid;
}; };
@ -86,6 +78,22 @@ struct session_chain
struct session_item *item; struct session_item *item;
}; };
/**
* Information used to start or find a session
*/
struct session_parameters
{
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 *connection_description;
};
/** /**
* *
* @brief finds a session matching the supplied parameters * @brief finds a session matching the supplied parameters
@ -93,10 +101,9 @@ struct session_chain
* *
*/ */
struct session_item * struct session_item *
session_get_bydata(const char *name, int width, int height, int bpp, int type, session_get_bydata(const struct session_parameters *params);
const char *connection_description);
#ifndef session_find_item #ifndef session_find_item
#define session_find_item(a, b, c, d, e, f) session_get_bydata(a, b, c, d, e, f); #define session_find_item(a) session_get_bydata(a)
#endif #endif
/** /**
@ -106,10 +113,12 @@ session_get_bydata(const char *name, int width, int height, int bpp, int type,
* *
*/ */
int int
session_start(long data, tui8 type, struct SCP_SESSION *s); session_start(long authdata,
const struct session_parameters *params,
struct guid *guid);
int int
session_reconnect(int display, char *username, long data); session_reconnect(int display, const char *username, long data);
/** /**
* *
@ -118,7 +127,7 @@ session_reconnect(int display, char *username, long data);
* @return * @return
* *
*/ */
int enum session_kill_status
session_kill(int pid); session_kill(int pid);
/** /**
@ -142,13 +151,24 @@ session_get_bypid(int pid);
/** /**
* *
* @brief retrieves a session's descriptor * @brief retrieves session descriptions
* @param pid the session pid * @param user the user for the sessions
* @return a pointer to the session descriptor on success, NULL otherwise * @return A block of session descriptions
*
* Pass the return result to free_session_info_list() after use
* *
*/ */
struct SCP_DISCONNECTED_SESSION * struct scp_session_info *
session_get_byuser(const char *user, int *cnt, unsigned char flags); session_get_byuser(const char *user, unsigned int *cnt, unsigned char flags);
/**
*
* @brief Frees the result of session_get_byuser()
* @param sesslist Resuit of session_get_byuser()
* @param cnt Number of entries in sess
*/
void
free_session_info_list(struct scp_session_info *sesslist, unsigned int cnt);
/** /**
* *
@ -157,4 +177,15 @@ session_get_byuser(const char *user, int *cnt, unsigned char flags);
* @return non-zero value (number of errors) if failed * @return non-zero value (number of errors) if failed
*/ */
int cleanup_sockets(int display); int cleanup_sockets(int display);
/**
* Clone a session_parameters structure
*
* @param sp Parameters to clone
* @return Cloned parameters, or NULL if no memory
*
* The cloned structure can be free'd with a single call to g_free()
*/
struct session_parameters *
clone_session_params(const struct session_parameters *sp);
#endif #endif