Move sesman to new SCP interface
This commit is contained in:
parent
6cf053c9df
commit
c0cb03801c
@ -9,7 +9,7 @@ AM_CPPFLAGS = \
|
||||
-DXRDP_PID_PATH=\"${localstatedir}/run\" \
|
||||
-DXRDP_SOCKET_PATH=\"${socketdir}\" \
|
||||
-I$(top_srcdir)/common \
|
||||
-I$(top_srcdir)/sesman/libscp
|
||||
-I$(top_srcdir)/libipm
|
||||
|
||||
if SESMAN_BSD
|
||||
AUTH_C = verify_user_bsd.c
|
||||
@ -45,14 +45,8 @@ xrdp_sesman_SOURCES = \
|
||||
config.h \
|
||||
env.c \
|
||||
env.h \
|
||||
scp.c \
|
||||
scp.h \
|
||||
scp_v0.c \
|
||||
scp_v0.h \
|
||||
scp_v1.c \
|
||||
scp_v1.h \
|
||||
scp_v1_mng.c \
|
||||
scp_v1_mng.h \
|
||||
scp_process.c \
|
||||
scp_process.h \
|
||||
sesman.c \
|
||||
sesman.h \
|
||||
session.c \
|
||||
@ -64,8 +58,8 @@ xrdp_sesman_SOURCES = \
|
||||
$(AUTH_C)
|
||||
|
||||
xrdp_sesman_LDADD = \
|
||||
$(top_builddir)/libipm/libipm.la \
|
||||
$(top_builddir)/common/libcommon.la \
|
||||
$(top_builddir)/sesman/libscp/libscp.la \
|
||||
$(AUTH_LIB) \
|
||||
-lpthread
|
||||
|
||||
@ -90,6 +84,5 @@ dist_sesmansysconf_SCRIPTS = \
|
||||
reconnectwm.sh
|
||||
|
||||
SUBDIRS = \
|
||||
libscp \
|
||||
tools \
|
||||
chansrv
|
||||
|
@ -7,60 +7,5 @@
|
||||
** internal, and may change for even minor releases. **
|
||||
************************************************************
|
||||
|
||||
|
||||
message header
|
||||
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
|
||||
|
||||
The SCP protocol is layered on top of libipm, which is in
|
||||
../libipm. See ../libipm/scp.h for the interface messages to xrdp-sesman
|
||||
|
88
sesman/scp.c
88
sesman/scp.c
@ -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;
|
||||
}
|
||||
|
45
sesman/scp.h
45
sesman/scp.h
@ -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
277
sesman/scp_process.c
Normal 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;
|
||||
}
|
||||
|
@ -18,18 +18,24 @@
|
||||
|
||||
/**
|
||||
*
|
||||
* @file scp_v0.h
|
||||
* @brief scp version 0 declarations
|
||||
* @file scp_process.h
|
||||
* @brief scp (sesman control protocol) handler function
|
||||
* @author Simone Fedele
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SCP_V0_H
|
||||
#define SCP_V0_H
|
||||
#ifndef SCP_PROCESS_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
|
174
sesman/scp_v0.c
174
sesman/scp_v0.c
@ -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;
|
||||
}
|
307
sesman/scp_v1.c
307
sesman/scp_v1.c
@ -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;
|
||||
}
|
||||
}
|
@ -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
|
@ -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;
|
||||
}
|
||||
}
|
@ -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
|
@ -33,6 +33,9 @@
|
||||
#include "sesman.h"
|
||||
#include "xrdp_configure_options.h"
|
||||
#include "string_calls.h"
|
||||
#include "trans.h"
|
||||
|
||||
#include "scp_process.h"
|
||||
|
||||
/**
|
||||
* Maximum number of short-lived connections to sesman
|
||||
@ -64,7 +67,6 @@ tintptr g_reload_event = 0;
|
||||
struct sesman_con
|
||||
{
|
||||
struct trans *t;
|
||||
struct SCP_SESSION *s;
|
||||
};
|
||||
|
||||
static struct trans *g_list_trans;
|
||||
@ -108,22 +110,10 @@ static struct sesman_con *
|
||||
alloc_connection(struct trans *t)
|
||||
{
|
||||
struct sesman_con *result;
|
||||
struct SCP_SESSION *s;
|
||||
|
||||
if ((result = g_new(struct sesman_con, 1)) != NULL)
|
||||
{
|
||||
if ((s = scp_session_create()) != NULL)
|
||||
{
|
||||
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;
|
||||
}
|
||||
result->t = t;
|
||||
}
|
||||
|
||||
return result;
|
||||
@ -141,7 +131,6 @@ static void
|
||||
delete_connection(struct sesman_con *sc)
|
||||
{
|
||||
trans_delete(sc->t);
|
||||
scp_session_destroy(sc->s);
|
||||
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.",
|
||||
cfg->listen_address, cfg->listen_port);
|
||||
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)
|
||||
{
|
||||
/* try to listen */
|
||||
@ -277,39 +266,21 @@ sesman_close_all(void)
|
||||
static int
|
||||
sesman_data_in(struct trans *self)
|
||||
{
|
||||
#define HEADER_SIZE 8
|
||||
int version;
|
||||
int size;
|
||||
int rv;
|
||||
int available;
|
||||
|
||||
if (self->extra_flags == 0)
|
||||
rv = scp_msg_in_check_available(self, &available);
|
||||
|
||||
if (rv == 0 && available)
|
||||
{
|
||||
in_uint32_be(self->in_s, version);
|
||||
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)
|
||||
if ((rv = scp_process(self)) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "sesman_data_in: scp_process_msg failed");
|
||||
return 1;
|
||||
}
|
||||
/* reset for next message */
|
||||
self->header_size = HEADER_SIZE;
|
||||
self->extra_flags = 0;
|
||||
init_stream(self->in_s, 0); /* Reset input stream pointers */
|
||||
scp_msg_in_reset(self);
|
||||
}
|
||||
return 0;
|
||||
#undef HEADER_SIZE
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
@ -323,7 +294,8 @@ sesman_listen_conn_in(struct trans *self, struct trans *new_self)
|
||||
"connections, rejecting");
|
||||
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 "
|
||||
"new connection");
|
||||
@ -331,10 +303,8 @@ sesman_listen_conn_in(struct trans *self, struct trans *new_self)
|
||||
}
|
||||
else
|
||||
{
|
||||
new_self->header_size = 8;
|
||||
new_self->callback_data = (void *)sc;
|
||||
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);
|
||||
}
|
||||
|
||||
@ -775,10 +745,6 @@ main(int argc, char **argv)
|
||||
}
|
||||
}
|
||||
|
||||
/* libscp initialization */
|
||||
scp_init();
|
||||
|
||||
|
||||
if (daemon)
|
||||
{
|
||||
/* start of daemonizing code */
|
||||
|
@ -39,8 +39,6 @@
|
||||
#include "access.h"
|
||||
#include "scp.h"
|
||||
|
||||
#include "libscp.h"
|
||||
|
||||
/* Globals */
|
||||
extern struct config_sesman *g_cfg;
|
||||
extern unsigned char g_fixedkey[8];
|
||||
|
274
sesman/session.c
274
sesman/session.c
@ -38,7 +38,6 @@
|
||||
#endif
|
||||
|
||||
#include "sesman.h"
|
||||
#include "libscp_types.h"
|
||||
#include "xauth.h"
|
||||
#include "xrdp_sockets.h"
|
||||
#include "string_calls.h"
|
||||
@ -87,58 +86,38 @@ dumpItemsToString(struct list *self, char *outstr, int len)
|
||||
|
||||
/******************************************************************************/
|
||||
struct session_item *
|
||||
session_get_bydata(const char *name, int width, int height, int bpp, int type,
|
||||
const char *connection_description)
|
||||
session_get_bydata(const struct session_parameters *sp)
|
||||
{
|
||||
struct session_chain *tmp;
|
||||
enum SESMAN_CFG_SESS_POLICY policy = g_cfg->sess.policy;
|
||||
char 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;
|
||||
}
|
||||
char tmp_ip[64];
|
||||
|
||||
if ((policy & SESMAN_CFG_SESS_POLICY_I) != 0)
|
||||
{
|
||||
/* 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
|
||||
{
|
||||
ip[0] = '\0';
|
||||
tmp_ip[0] = '\0';
|
||||
}
|
||||
|
||||
LOG(LOG_LEVEL_DEBUG,
|
||||
"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)
|
||||
{
|
||||
g_get_ip_from_description(tmp->item->connection_description,
|
||||
tmp_ip, sizeof (tmp_ip));
|
||||
}
|
||||
else
|
||||
{
|
||||
tmp_ip[0] = '\0';
|
||||
}
|
||||
|
||||
LOG(LOG_LEVEL_DEBUG,
|
||||
"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->connection_description);
|
||||
|
||||
if (g_strncmp(name, tmp->item->name, 255) == 0 &&
|
||||
(!(policy & SESMAN_CFG_SESS_POLICY_D) ||
|
||||
(tmp->item->width == width && tmp->item->height == height)) &&
|
||||
(!(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)
|
||||
if (g_strncmp(sp->username, tmp->item->name, 255) != 0 ||
|
||||
tmp->item->bpp != sp->bpp ||
|
||||
tmp->item->type != sp->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;
|
||||
@ -390,7 +388,7 @@ wait_for_xserver(int display)
|
||||
|
||||
/******************************************************************************/
|
||||
static int
|
||||
session_start_chansrv(char *username, int display)
|
||||
session_start_chansrv(const char *username, int display)
|
||||
{
|
||||
struct list *chansrv_params;
|
||||
char exe_path[262];
|
||||
@ -427,9 +425,11 @@ session_start_chansrv(char *username, int display)
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/* called with the main thread */
|
||||
static int
|
||||
session_start_fork(tbus data, tui8 type, struct SCP_SESSION *s)
|
||||
|
||||
int
|
||||
session_start(long data,
|
||||
const struct session_parameters *s,
|
||||
struct guid *guid)
|
||||
{
|
||||
int display = 0;
|
||||
int pid = 0;
|
||||
@ -443,16 +443,12 @@ session_start_fork(tbus data, tui8 type, struct SCP_SESSION *s)
|
||||
char **pp1 = (char **)NULL;
|
||||
struct session_chain *temp = (struct session_chain *)NULL;
|
||||
struct list *xserver_params = (struct list *)NULL;
|
||||
struct tm stime;
|
||||
time_t ltime;
|
||||
char authfile[256]; /* The filename for storing xauth informations */
|
||||
int chansrv_pid;
|
||||
int display_pid;
|
||||
int window_manager_pid;
|
||||
|
||||
/* initialize (zero out) local variables: */
|
||||
g_memset(<ime, 0, sizeof(time_t));
|
||||
g_memset(&stime, 0, sizeof(struct tm));
|
||||
g_memset(geometry, 0, sizeof(char) * 32);
|
||||
g_memset(depth, 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;
|
||||
}
|
||||
|
||||
/* Create a GUID for the new session before we work */
|
||||
*guid = guid_new();
|
||||
|
||||
pid = g_fork(); /* parent is fork from tcp accept,
|
||||
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
|
||||
* deleted by sesman_close_all() */
|
||||
if ((s = scp_session_clone(s)) == NULL)
|
||||
if ((s = clone_session_params(s)) == NULL)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"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);
|
||||
}
|
||||
}
|
||||
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,
|
||||
"Starting user requested window manager on "
|
||||
"display %d with embeded arguments using a shell: %s",
|
||||
display, s->program);
|
||||
const char *params[] = {"sh", "-c", s->program, NULL};
|
||||
g_execvp("/bin/sh", (char **)params);
|
||||
display, s->shell);
|
||||
const char *argv[] = {"sh", "-c", s->shell, NULL};
|
||||
g_execvp("/bin/sh", (char **)argv);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(LOG_LEVEL_INFO,
|
||||
"Starting user requested window manager on "
|
||||
"display %d: %s", display, s->program);
|
||||
g_execlp3(s->program, s->program, 0);
|
||||
"display %d: %s", display, s->shell);
|
||||
g_execlp3(s->shell, s->shell, 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -684,7 +683,7 @@ session_start_fork(tbus data, tui8 type, struct SCP_SESSION *s)
|
||||
}
|
||||
else if (display_pid == 0) /* child */
|
||||
{
|
||||
if (type == SESMAN_SESSION_TYPE_XVNC)
|
||||
if (s->type == SCP_SESSION_TYPE_XVNC)
|
||||
{
|
||||
env_set_user(s->username,
|
||||
&passwd_file,
|
||||
@ -733,7 +732,7 @@ session_start_fork(tbus data, tui8 type, struct SCP_SESSION *s)
|
||||
g_exit(1);
|
||||
}
|
||||
|
||||
if (type == SESMAN_SESSION_TYPE_XORG)
|
||||
if (s->type == SCP_SESSION_TYPE_XORG)
|
||||
{
|
||||
#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_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];
|
||||
guid_to_str(&s->guid, guid_str);
|
||||
guid_to_str(guid, guid_str);
|
||||
env_check_password_file(passwd_file, guid_str);
|
||||
xserver_params = list_create();
|
||||
xserver_params->auto_free = 1;
|
||||
@ -804,7 +803,7 @@ session_start_fork(tbus data, tui8 type, struct SCP_SESSION *s)
|
||||
g_free(passwd_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);
|
||||
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);
|
||||
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->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));
|
||||
|
||||
/* additional parameters from sesman.ini file */
|
||||
//config_read_xserver_params(SESMAN_SESSION_TYPE_XRDP,
|
||||
//config_read_xserver_params(SCP_SESSION_TYPE_XRDP,
|
||||
// xserver_params);
|
||||
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
|
||||
{
|
||||
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 "
|
||||
"to start the X server on display %d, aborting connection",
|
||||
display);
|
||||
@ -958,19 +958,11 @@ session_start_fork(tbus data, tui8 type, struct SCP_SESSION *s)
|
||||
temp->item->data = data;
|
||||
g_strncpy(temp->item->connection_description, s->connection_description, 255); /* store client ip data */
|
||||
g_strncpy(temp->item->name, s->username, 255);
|
||||
temp->item->guid = s->guid;
|
||||
temp->item->guid = *guid;
|
||||
|
||||
ltime = g_time1();
|
||||
localtime_r(<ime, &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->start_time = g_time1();
|
||||
|
||||
temp->item->type = type;
|
||||
temp->item->type = s->type;
|
||||
temp->item->status = SESMAN_SESSION_STATUS_ACTIVE;
|
||||
|
||||
temp->next = g_sessions;
|
||||
@ -986,9 +978,8 @@ session_start_fork(tbus data, tui8 type, struct SCP_SESSION *s)
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/* called with the main thread */
|
||||
static int
|
||||
session_reconnect_fork(int display, char *username, long data)
|
||||
int
|
||||
session_reconnect(int display, const char *username, long data)
|
||||
{
|
||||
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
|
||||
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
|
||||
enum session_kill_status
|
||||
session_kill(int pid)
|
||||
{
|
||||
struct session_chain *tmp;
|
||||
@ -1180,11 +1153,11 @@ session_get_bypid(int pid)
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
struct SCP_DISCONNECTED_SESSION *
|
||||
session_get_byuser(const char *user, int *cnt, unsigned char flags)
|
||||
struct scp_session_info *
|
||||
session_get_byuser(const char *user, unsigned int *cnt, unsigned char flags)
|
||||
{
|
||||
struct session_chain *tmp;
|
||||
struct SCP_DISCONNECTED_SESSION *sess;
|
||||
struct scp_session_info *sess;
|
||||
int count;
|
||||
int index;
|
||||
|
||||
@ -1218,7 +1191,7 @@ session_get_byuser(const char *user, int *cnt, unsigned char flags)
|
||||
}
|
||||
|
||||
/* 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)
|
||||
{
|
||||
@ -1229,43 +1202,31 @@ session_get_byuser(const char *user, int *cnt, unsigned char flags)
|
||||
tmp = g_sessions;
|
||||
index = 0;
|
||||
|
||||
while (tmp != 0)
|
||||
while (tmp != 0 && index < count)
|
||||
{
|
||||
/* #warning FIXME: we should get only disconnected sessions! */
|
||||
if ((NULL == user) || (!g_strncasecmp(user, tmp->item->name, 256)))
|
||||
{
|
||||
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]).height = tmp->item->height;
|
||||
(sess[index]).width = tmp->item->width;
|
||||
(sess[index]).bpp = tmp->item->bpp;
|
||||
/* #warning FIXME: setting idle times and such */
|
||||
/*(sess[index]).connect_time.year = tmp->item->connect_time.year;
|
||||
(sess[index]).connect_time.month = tmp->item->connect_time.month;
|
||||
(sess[index]).connect_time.day = tmp->item->connect_time.day;
|
||||
(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;
|
||||
(sess[index]).start_time = tmp->item->start_time;
|
||||
(sess[index]).username = g_strdup(tmp->item->name);
|
||||
(sess[index]).connection_description =
|
||||
g_strdup(tmp->item->connection_description);
|
||||
|
||||
if ((sess[index]).username == NULL ||
|
||||
(sess[index]).connection_description == NULL)
|
||||
{
|
||||
free_session_info_list(sess, *cnt);
|
||||
(*cnt) = 0;
|
||||
return 0;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
}
|
||||
@ -1278,6 +1239,23 @@ session_get_byuser(const char *user, int *cnt, unsigned char flags)
|
||||
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
|
||||
cleanup_sockets(int display)
|
||||
@ -1372,3 +1350,45 @@ cleanup_sockets(int display)
|
||||
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;
|
||||
}
|
||||
|
@ -28,12 +28,10 @@
|
||||
#ifndef SESSION_H
|
||||
#define SESSION_H
|
||||
|
||||
#include "libscp_types.h"
|
||||
#include "guid.h"
|
||||
#include <time.h>
|
||||
|
||||
#define SESMAN_SESSION_TYPE_XRDP 1
|
||||
#define SESMAN_SESSION_TYPE_XVNC 2
|
||||
#define SESMAN_SESSION_TYPE_XORG 3
|
||||
#include "guid.h"
|
||||
#include "scp_application_types.h"
|
||||
|
||||
#define SESMAN_SESSION_STATUS_ACTIVE 0x01
|
||||
#define SESMAN_SESSION_STATUS_IDLE 0x02
|
||||
@ -43,20 +41,14 @@
|
||||
*/
|
||||
#define SESMAN_SESSION_STATUS_ALL 0xFF
|
||||
|
||||
#define SESMAN_SESSION_KILL_OK 0
|
||||
#define SESMAN_SESSION_KILL_NULLITEM 1
|
||||
#define SESMAN_SESSION_KILL_NOTFOUND 2
|
||||
|
||||
struct session_date
|
||||
enum session_kill_status
|
||||
{
|
||||
tui16 year;
|
||||
tui8 month;
|
||||
tui8 day;
|
||||
tui8 hour;
|
||||
tui8 minute;
|
||||
SESMAN_SESSION_KILL_OK = 0,
|
||||
SESMAN_SESSION_KILL_NULLITEM,
|
||||
SESMAN_SESSION_KILL_NOTFOUND
|
||||
};
|
||||
|
||||
#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
|
||||
{
|
||||
@ -70,12 +62,12 @@ struct session_item
|
||||
|
||||
/* status info */
|
||||
unsigned char status;
|
||||
unsigned char type;
|
||||
enum scp_session_type type;
|
||||
|
||||
/* time data */
|
||||
struct session_date connect_time;
|
||||
struct session_date disconnect_time;
|
||||
struct session_date idle_time;
|
||||
time_t start_time;
|
||||
// struct session_date disconnect_time; // Currently unused
|
||||
// struct session_date idle_time; // Currently unused
|
||||
char connection_description[256];
|
||||
struct guid guid;
|
||||
};
|
||||
@ -86,6 +78,22 @@ struct session_chain
|
||||
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
|
||||
@ -93,10 +101,9 @@ struct session_chain
|
||||
*
|
||||
*/
|
||||
struct session_item *
|
||||
session_get_bydata(const char *name, int width, int height, int bpp, int type,
|
||||
const char *connection_description);
|
||||
session_get_bydata(const struct session_parameters *params);
|
||||
#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
|
||||
|
||||
/**
|
||||
@ -106,10 +113,12 @@ session_get_bydata(const char *name, int width, int height, int bpp, int type,
|
||||
*
|
||||
*/
|
||||
int
|
||||
session_start(long data, tui8 type, struct SCP_SESSION *s);
|
||||
session_start(long authdata,
|
||||
const struct session_parameters *params,
|
||||
struct guid *guid);
|
||||
|
||||
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
|
||||
*
|
||||
*/
|
||||
int
|
||||
enum session_kill_status
|
||||
session_kill(int pid);
|
||||
|
||||
/**
|
||||
@ -142,13 +151,24 @@ session_get_bypid(int pid);
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief retrieves a session's descriptor
|
||||
* @param pid the session pid
|
||||
* @return a pointer to the session descriptor on success, NULL otherwise
|
||||
* @brief retrieves session descriptions
|
||||
* @param user the user for the sessions
|
||||
* @return A block of session descriptions
|
||||
*
|
||||
* Pass the return result to free_session_info_list() after use
|
||||
*
|
||||
*/
|
||||
struct SCP_DISCONNECTED_SESSION *
|
||||
session_get_byuser(const char *user, int *cnt, unsigned char flags);
|
||||
struct scp_session_info *
|
||||
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
|
||||
*/
|
||||
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
|
||||
|
Loading…
Reference in New Issue
Block a user