c4727ad8f3
As far as possible, use of the X11 display number is kept to X11-specific routines. This is to make it easier to restructure the code to add non-X11 display support.
925 lines
25 KiB
C
925 lines
25 KiB
C
/**
|
|
* xrdp: A Remote Desktop Protocol server.
|
|
*
|
|
* Copyright (C) Jay Sorg 2004-2022, all xrdp contributors
|
|
*
|
|
* 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 libipm/scp.c
|
|
* @brief scp definitions
|
|
* @author Simone Fedele/ Matt Burt
|
|
*/
|
|
|
|
#if defined(HAVE_CONFIG_H)
|
|
#include <config_ac.h>
|
|
#endif
|
|
|
|
#include <ctype.h>
|
|
|
|
#include "scp.h"
|
|
#include "libipm.h"
|
|
#include "guid.h"
|
|
#include "trans.h"
|
|
#include "os_calls.h"
|
|
#include "string_calls.h"
|
|
#include "xrdp_sockets.h"
|
|
|
|
/*****************************************************************************/
|
|
static const char *
|
|
msgno_to_str(unsigned short n)
|
|
{
|
|
return
|
|
(n == E_SCP_SET_PEERNAME_REQUEST) ? "SCP_SET_PEERNAME_REQUEST" :
|
|
|
|
(n == E_SCP_SYS_LOGIN_REQUEST) ? "SCP_SYS_LOGIN_REQUEST" :
|
|
(n == E_SCP_UDS_LOGIN_REQUEST) ? "SCP_UDS_LOGIN_REQUEST" :
|
|
(n == E_SCP_LOGIN_RESPONSE) ? "SCP_LOGIN_RESPONSE" :
|
|
|
|
(n == E_SCP_LOGOUT_REQUEST) ? "SCP_LOGOUT_REQUEST" :
|
|
|
|
(n == E_SCP_CREATE_SESSION_REQUEST) ? "SCP_CREATE_SESSION_REQUEST" :
|
|
(n == E_SCP_CREATE_SESSION_RESPONSE) ? "SCP_CREATE_SESSION_RESPONSE" :
|
|
|
|
(n == E_SCP_CONNECT_SESSION_REQUEST) ? "SCP_CONNECT_SESSION_REQUEST" :
|
|
(n == E_SCP_CONNECT_SESSION_RESPONSE) ? "SCP_CONNECT_SESSION_RESPONSE" :
|
|
|
|
(n == E_SCP_LIST_SESSIONS_REQUEST) ? "SCP_LIST_SESSIONS_REQUEST" :
|
|
(n == E_SCP_LIST_SESSIONS_RESPONSE) ? "SCP_LIST_SESSIONS_RESPONSE" :
|
|
|
|
(n == E_SCP_CLOSE_CONNECTION_REQUEST) ? "SCP_CLOSE_CONNECTION_REQUEST" :
|
|
NULL;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
const char *
|
|
scp_msgno_to_str(enum scp_msg_code n, char *buff, unsigned int buff_size)
|
|
{
|
|
const char *str = msgno_to_str((unsigned short)n);
|
|
|
|
if (str == NULL)
|
|
{
|
|
g_snprintf(buff, buff_size, "[code #%d]", (int)n);
|
|
}
|
|
else
|
|
{
|
|
g_snprintf(buff, buff_size, "%s", str);
|
|
}
|
|
|
|
return buff;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/**
|
|
* Helper function returning 1 if the passed-in string is an integer >= 0
|
|
*/
|
|
static int is_positive_int(const char *s)
|
|
{
|
|
for ( ; *s != '\0' ; ++s)
|
|
{
|
|
if (!isdigit(*s))
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
int
|
|
scp_port_to_unix_domain_path(const char *port, char *buff,
|
|
unsigned int bufflen)
|
|
{
|
|
/* GOTCHA: Changes to this logic should be mirrored in
|
|
* scp_port_to_display_string() */
|
|
|
|
int result;
|
|
|
|
/* Make sure we can safely de-reference 'port' */
|
|
if (port == NULL)
|
|
{
|
|
port = "";
|
|
}
|
|
|
|
if (port[0] == '/')
|
|
{
|
|
result = g_snprintf(buff, bufflen, "%s", port);
|
|
}
|
|
else
|
|
{
|
|
const char *sep;
|
|
if ((sep = g_strrchr(port, '/')) != NULL && sep != port)
|
|
{
|
|
/* We allow the user to specify an absolute path, but not
|
|
* a relative one with embedded '/' characters */
|
|
LOG(LOG_LEVEL_WARNING, "Ignoring path elements of '%s'", port);
|
|
port = sep + 1;
|
|
}
|
|
|
|
if (port[0] == '\0')
|
|
{
|
|
port = SCP_LISTEN_PORT_BASE_STR;
|
|
}
|
|
else if (is_positive_int(port))
|
|
{
|
|
/* Version v0.9.x and earlier of xrdp used a TCP port
|
|
* number. If we come across this, we'll ignore it for
|
|
* compatibility with old config files */
|
|
LOG(LOG_LEVEL_WARNING,
|
|
"Ignoring obsolete SCP port value '%s'", port);
|
|
port = SCP_LISTEN_PORT_BASE_STR;
|
|
}
|
|
|
|
result = g_snprintf(buff, bufflen, XRDP_SOCKET_ROOT_PATH "/%s", port);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
int
|
|
scp_port_to_display_string(const char *port, char *buff, unsigned int bufflen)
|
|
{
|
|
/* Make sure we can safely de-reference 'port' */
|
|
if (port == NULL)
|
|
{
|
|
port = "";
|
|
}
|
|
|
|
/* Ignore any directories for the display */
|
|
const char *sep;
|
|
if ((sep = g_strrchr(port, '/')) != NULL)
|
|
{
|
|
port = sep + 1;
|
|
}
|
|
|
|
/* Check for a default */
|
|
if (port[0] == '\0' || g_strcmp(port, "3350") == 0)
|
|
{
|
|
port = SCP_LISTEN_PORT_BASE_STR;
|
|
}
|
|
|
|
return g_snprintf(buff, bufflen, "%s", port);
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
struct trans *
|
|
scp_connect(const char *port,
|
|
const char *peername,
|
|
int (*term_func)(void))
|
|
{
|
|
char sock_path[256];
|
|
struct trans *t;
|
|
|
|
(void)scp_port_to_unix_domain_path(port, sock_path, sizeof(sock_path));
|
|
if ((t = trans_create(TRANS_MODE_UNIX, 128, 128)) != NULL)
|
|
{
|
|
t->is_term = term_func;
|
|
|
|
if (trans_connect(t, NULL, sock_path, 3000) != 0)
|
|
{
|
|
trans_delete(t);
|
|
t = NULL;
|
|
}
|
|
else if (scp_init_trans(t) != 0)
|
|
{
|
|
trans_delete(t);
|
|
t = NULL;
|
|
}
|
|
else if (scp_send_set_peername_request(t, peername) != 0)
|
|
{
|
|
trans_delete(t);
|
|
t = NULL;
|
|
}
|
|
}
|
|
|
|
return t;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
int
|
|
scp_init_trans(struct trans *trans)
|
|
{
|
|
return libipm_init_trans(trans, LIBIPM_FAC_SCP, msgno_to_str);
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
struct trans *
|
|
scp_init_trans_from_fd(int fd, int trans_type, int (*term_func)(void))
|
|
{
|
|
struct trans *result;
|
|
if ((result = trans_create(TRANS_MODE_UNIX, 128, 128)) == NULL)
|
|
{
|
|
LOG(LOG_LEVEL_ERROR, "Can't create SCP transport [%s]",
|
|
g_get_strerror());
|
|
}
|
|
else
|
|
{
|
|
result->sck = fd;
|
|
result->type1 = trans_type;
|
|
result->status = TRANS_STATUS_UP;
|
|
result->is_term = term_func;
|
|
|
|
// Make sure child processes don't inherit our FD
|
|
(void)g_file_set_cloexec(result->sck, 1);
|
|
|
|
if (scp_init_trans(result) != 0)
|
|
{
|
|
LOG(LOG_LEVEL_ERROR, "scp_init_trans() call failed");
|
|
trans_delete(result);
|
|
result = NULL;
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
/*****************************************************************************/
|
|
int
|
|
scp_msg_in_check_available(struct trans *trans, int *available)
|
|
{
|
|
return libipm_msg_in_check_available(trans, available);
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
int
|
|
scp_msg_in_wait_available(struct trans *trans)
|
|
{
|
|
return libipm_msg_in_wait_available(trans);
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
enum scp_msg_code
|
|
scp_msg_in_get_msgno(const struct trans *trans)
|
|
{
|
|
return (enum scp_msg_code)libipm_msg_in_get_msgno(trans);
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
void
|
|
scp_msg_in_reset(struct trans *trans)
|
|
{
|
|
libipm_msg_in_reset(trans);
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
int
|
|
scp_send_set_peername_request(struct trans *trans,
|
|
const char *peername)
|
|
{
|
|
return libipm_msg_out_simple_send(
|
|
trans,
|
|
(int)E_SCP_SET_PEERNAME_REQUEST,
|
|
"s",
|
|
peername);
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
int
|
|
scp_get_set_peername_request(struct trans *trans,
|
|
const char **peername)
|
|
{
|
|
return libipm_msg_in_parse( trans, "s", peername);
|
|
}
|
|
|
|
|
|
/*****************************************************************************/
|
|
int
|
|
scp_send_uds_login_request(struct trans *trans)
|
|
{
|
|
return libipm_msg_out_simple_send(trans,
|
|
(int)E_SCP_UDS_LOGIN_REQUEST,
|
|
NULL);
|
|
}
|
|
|
|
|
|
/*****************************************************************************/
|
|
int
|
|
scp_send_sys_login_request(struct trans *trans,
|
|
const char *username,
|
|
const char *password,
|
|
const char *ip_addr)
|
|
{
|
|
int rv;
|
|
|
|
rv = libipm_msg_out_simple_send(
|
|
trans,
|
|
(int)E_SCP_SYS_LOGIN_REQUEST,
|
|
"sss",
|
|
username,
|
|
password,
|
|
ip_addr);
|
|
|
|
/* Wipe the output buffer to remove the password */
|
|
libipm_msg_out_erase(trans);
|
|
|
|
return rv;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
int
|
|
scp_get_sys_login_request(struct trans *trans,
|
|
const char **username,
|
|
const char **password,
|
|
const char **ip_addr)
|
|
{
|
|
/* Make sure the buffer is cleared after processing this message */
|
|
libipm_set_flags(trans, LIBIPM_E_MSG_IN_ERASE_AFTER_USE);
|
|
|
|
return libipm_msg_in_parse( trans, "sss",
|
|
username, password, ip_addr);
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
int
|
|
scp_send_login_response(struct trans *trans,
|
|
enum scp_login_status login_result,
|
|
int server_closed,
|
|
int uid)
|
|
{
|
|
return libipm_msg_out_simple_send(
|
|
trans,
|
|
(int)E_SCP_LOGIN_RESPONSE,
|
|
"ibi",
|
|
login_result,
|
|
(server_closed != 0), /* Convert to 0/1 */
|
|
uid);
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
int
|
|
scp_get_login_response(struct trans *trans,
|
|
enum scp_login_status *login_result,
|
|
int *server_closed,
|
|
int *uid)
|
|
{
|
|
int32_t i_login_result = 0;
|
|
int32_t i_uid = 0;
|
|
int dummy;
|
|
|
|
/* User can pass in NULL for server_closed if they're trying an
|
|
* login method like UDS for which all fails are fatal. Likewise
|
|
* they may be uninterested in the uid */
|
|
if (server_closed == NULL)
|
|
{
|
|
server_closed = &dummy;
|
|
}
|
|
if (uid == NULL)
|
|
{
|
|
uid = &dummy;
|
|
}
|
|
|
|
int rv = libipm_msg_in_parse(trans, "ibi",
|
|
&i_login_result, server_closed, &i_uid);
|
|
if (rv == 0)
|
|
{
|
|
*login_result = (enum scp_login_status)i_login_result;
|
|
*uid = i_uid;
|
|
}
|
|
|
|
return rv;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
int
|
|
scp_send_logout_request(struct trans *trans)
|
|
{
|
|
return libipm_msg_out_simple_send( trans, (int)E_SCP_LOGOUT_REQUEST, NULL);
|
|
}
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
int
|
|
scp_send_create_session_request(struct trans *trans,
|
|
enum scp_session_type type,
|
|
unsigned short width,
|
|
unsigned short height,
|
|
unsigned char bpp,
|
|
const char *shell,
|
|
const char *directory,
|
|
const char *instance_name)
|
|
{
|
|
return libipm_msg_out_simple_send(
|
|
trans,
|
|
(int)E_SCP_CREATE_SESSION_REQUEST,
|
|
"yqqysss",
|
|
type,
|
|
width,
|
|
height,
|
|
bpp,
|
|
shell,
|
|
directory,
|
|
instance_name);
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
int
|
|
scp_get_create_session_request(struct trans *trans,
|
|
enum scp_session_type *type,
|
|
unsigned short *width,
|
|
unsigned short *height,
|
|
unsigned char *bpp,
|
|
const char **shell,
|
|
const char **directory,
|
|
const char **instance_name)
|
|
{
|
|
/* Intermediate values */
|
|
uint8_t i_type;
|
|
uint16_t i_width;
|
|
uint16_t i_height;
|
|
uint8_t i_bpp;
|
|
|
|
int rv = libipm_msg_in_parse(
|
|
trans,
|
|
"yqqysss",
|
|
&i_type,
|
|
&i_width,
|
|
&i_height,
|
|
&i_bpp,
|
|
shell,
|
|
directory,
|
|
instance_name);
|
|
|
|
if (rv == 0)
|
|
{
|
|
*type = (enum scp_session_type)i_type;
|
|
*width = i_width;
|
|
*height = i_height;
|
|
/* bpp is fixed for Xorg session types */
|
|
*bpp = (*type == SCP_SESSION_TYPE_XORG) ? 24 : i_bpp;
|
|
}
|
|
|
|
return rv;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
int
|
|
scp_send_create_session_response(struct trans *trans,
|
|
enum scp_screate_status status,
|
|
const char *display,
|
|
const struct guid *guid)
|
|
{
|
|
struct libipm_fsb guid_descriptor = { (void *)guid, sizeof(*guid) };
|
|
|
|
return libipm_msg_out_simple_send(
|
|
trans,
|
|
(int)E_SCP_CREATE_SESSION_RESPONSE,
|
|
"isB",
|
|
status,
|
|
display,
|
|
&guid_descriptor);
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
int
|
|
scp_get_create_session_response(struct trans *trans,
|
|
enum scp_screate_status *status,
|
|
const char **display,
|
|
struct guid *guid)
|
|
{
|
|
/* Intermediate values */
|
|
int32_t i_status;
|
|
|
|
const struct libipm_fsb guid_descriptor = { (void *)guid, sizeof(*guid) };
|
|
|
|
int rv = libipm_msg_in_parse(
|
|
trans,
|
|
"isB",
|
|
&i_status,
|
|
display,
|
|
&guid_descriptor);
|
|
if (rv == 0)
|
|
{
|
|
*status = (enum scp_screate_status)i_status;
|
|
}
|
|
else
|
|
{
|
|
*display = "";
|
|
}
|
|
|
|
return rv;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
int
|
|
scp_send_connect_session_request(struct trans *trans,
|
|
const struct guid *guid,
|
|
const char *client_ip,
|
|
const char *client_name,
|
|
unsigned int flags)
|
|
{
|
|
struct libipm_fsb guid_descriptor = { (void *)guid, sizeof(*guid) };
|
|
|
|
return libipm_msg_out_simple_send(
|
|
trans,
|
|
(int)E_SCP_CONNECT_SESSION_REQUEST,
|
|
"Bssu", &guid_descriptor, client_ip, client_name, flags);
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
int
|
|
scp_get_connect_session_request(struct trans *trans,
|
|
struct guid *guid,
|
|
const char **client_ip,
|
|
const char **client_name,
|
|
unsigned int *flags)
|
|
{
|
|
struct libipm_fsb guid_descriptor = { (void *)guid, sizeof(*guid) };
|
|
/* Intermediate values */
|
|
uint32_t i_flags;
|
|
|
|
int rv = libipm_msg_in_parse(trans, "Bssu",
|
|
&guid_descriptor, client_ip, client_name,
|
|
&i_flags);
|
|
|
|
if (rv == 0)
|
|
{
|
|
*flags = i_flags;
|
|
}
|
|
|
|
return rv;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
int
|
|
scp_send_connect_session_response(struct trans *trans,
|
|
enum scp_sconnect_status status,
|
|
int display_fd,
|
|
int chan_fd)
|
|
{
|
|
int rv = libipm_msg_out_init(
|
|
trans, (int)E_SCP_CONNECT_SESSION_RESPONSE,
|
|
"i", status);
|
|
// Send the display file descriptor, guarded by a boolean
|
|
if (rv == 0)
|
|
{
|
|
if (display_fd >= 0)
|
|
{
|
|
rv = libipm_msg_out_append(
|
|
trans, "bh", 1, display_fd);
|
|
}
|
|
else
|
|
{
|
|
rv = libipm_msg_out_append(trans, "b", 0);
|
|
}
|
|
}
|
|
|
|
// Send the chansrv file descriptor, guarded by a boolean
|
|
if (rv == 0)
|
|
{
|
|
if (chan_fd >= 0)
|
|
{
|
|
rv = libipm_msg_out_append(
|
|
trans, "bh", 1, chan_fd);
|
|
}
|
|
else
|
|
{
|
|
rv = libipm_msg_out_append(trans, "b", 0);
|
|
}
|
|
}
|
|
|
|
if (rv == 0)
|
|
{
|
|
libipm_msg_out_mark_end(trans);
|
|
if (trans_force_write(trans) != 0)
|
|
{
|
|
rv = E_LI_TRANSPORT_ERROR;
|
|
}
|
|
}
|
|
|
|
return rv;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/**
|
|
* Helper function to get the file descriptors for a connect
|
|
*
|
|
* @param trans SCP trans
|
|
* @param[out] display_fd Display server file descriptor
|
|
* @param[out] chan_fd Chansrv file descriptor
|
|
* @return != 0 for error
|
|
*
|
|
* This wrapper is nneded as libipm doesn't currently guarantee to
|
|
* handle received file descriptors well if an error is encountered
|
|
* mid-message.
|
|
*
|
|
* If an error is returned, some file descriptors may be valid.
|
|
*/
|
|
static int
|
|
get_connect_session_response_fds(struct trans *trans,
|
|
int *display_fd,
|
|
int *chan_fd)
|
|
{
|
|
int rv;
|
|
int fd_present;
|
|
|
|
// Read the display server file descriptor and guard
|
|
if ((rv = libipm_msg_in_parse(trans, "b", &fd_present)) != 0)
|
|
{
|
|
return rv;
|
|
}
|
|
if (fd_present)
|
|
{
|
|
if ((rv = libipm_msg_in_parse(trans, "h", display_fd)) != 0)
|
|
{
|
|
return rv;
|
|
}
|
|
}
|
|
|
|
// Read the chansrv file descriptor and guard
|
|
if ((rv = libipm_msg_in_parse(trans, "b", &fd_present)) != 0)
|
|
{
|
|
return rv;
|
|
}
|
|
if (fd_present)
|
|
{
|
|
if ((rv = libipm_msg_in_parse(trans, "h", chan_fd)) != 0)
|
|
{
|
|
return rv;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
int
|
|
scp_get_connect_session_response(struct trans *trans,
|
|
enum scp_sconnect_status *status,
|
|
int *display_fd,
|
|
int *chan_fd)
|
|
{
|
|
int rv;
|
|
/* Intermediate values */
|
|
int32_t i_status;
|
|
|
|
/* Set the returned FDs to nonsensical values to stop valid
|
|
* FDs getting clobbered */
|
|
*display_fd = -1;
|
|
*chan_fd = -1;
|
|
|
|
if ((rv = libipm_msg_in_parse( trans, "i", &i_status)) == 0)
|
|
{
|
|
// Us a helper function to get the file descriptors as this
|
|
// makes flow control easier.
|
|
rv = get_connect_session_response_fds(trans, display_fd, chan_fd);
|
|
if (rv == 0)
|
|
{
|
|
*status = (enum scp_sconnect_status)i_status;
|
|
}
|
|
else
|
|
{
|
|
// Close any fds we did receive to stop leaks
|
|
if (*display_fd >= 0)
|
|
{
|
|
g_file_close(*display_fd);
|
|
*display_fd = -1;
|
|
}
|
|
if (*chan_fd >= 0)
|
|
{
|
|
g_file_close(*chan_fd);
|
|
*chan_fd = -1;
|
|
}
|
|
}
|
|
}
|
|
|
|
return rv;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
int
|
|
scp_send_list_sessions_request(struct trans *trans)
|
|
{
|
|
return libipm_msg_out_simple_send(
|
|
trans,
|
|
(int)E_SCP_LIST_SESSIONS_REQUEST,
|
|
NULL);
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
int
|
|
scp_send_list_sessions_response(
|
|
struct trans *trans,
|
|
enum scp_list_sessions_status status,
|
|
const struct scp_session_info *info)
|
|
{
|
|
int rv;
|
|
|
|
if (status != E_SCP_LS_SESSION_INFO)
|
|
{
|
|
rv = libipm_msg_out_simple_send(
|
|
trans,
|
|
(int)E_SCP_LIST_SESSIONS_RESPONSE,
|
|
"i", status);
|
|
}
|
|
else
|
|
{
|
|
rv = libipm_msg_out_simple_send(
|
|
trans,
|
|
(int)E_SCP_LIST_SESSIONS_RESPONSE,
|
|
"iisyqqyxisssxs",
|
|
status,
|
|
info->sid,
|
|
info->display,
|
|
info->type,
|
|
info->width,
|
|
info->height,
|
|
info->bpp,
|
|
(int64_t)info->start_time,
|
|
info->uid,
|
|
info->start_ip_addr,
|
|
info->client_ip,
|
|
info->client_name,
|
|
(int64_t)info->last_connect_disconnect,
|
|
info->xrdp_instance_name);
|
|
}
|
|
|
|
return rv;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
int
|
|
scp_get_list_sessions_response(
|
|
struct trans *trans,
|
|
enum scp_list_sessions_status *status,
|
|
struct scp_session_info **info)
|
|
{
|
|
int32_t i_status;
|
|
int rv;
|
|
|
|
if (info == NULL)
|
|
{
|
|
LOG_DEVEL(LOG_LEVEL_ERROR, "Bad pointer in %s", __func__);
|
|
rv = 1;
|
|
}
|
|
else if ((rv = libipm_msg_in_parse(trans, "i", &i_status)) == 0)
|
|
{
|
|
*status = (enum scp_list_sessions_status)i_status;
|
|
struct scp_session_info *p = NULL;
|
|
|
|
if (*status == E_SCP_LS_SESSION_INFO)
|
|
{
|
|
int32_t i_sid;
|
|
char *i_display;
|
|
uint8_t i_type;
|
|
uint16_t i_width;
|
|
uint16_t i_height;
|
|
uint8_t i_bpp;
|
|
int64_t i_start_time;
|
|
int32_t i_uid;
|
|
char *i_start_ip_addr;
|
|
char *i_client_ip;
|
|
char *i_client_name;
|
|
int64_t i_last_connect_disconnect;
|
|
char *i_instance_name;
|
|
|
|
rv = libipm_msg_in_parse(
|
|
trans,
|
|
"isyqqyxisssxs",
|
|
&i_sid,
|
|
&i_display,
|
|
&i_type,
|
|
&i_width,
|
|
&i_height,
|
|
&i_bpp,
|
|
&i_start_time,
|
|
&i_uid,
|
|
&i_start_ip_addr,
|
|
&i_client_ip,
|
|
&i_client_name,
|
|
&i_last_connect_disconnect,
|
|
&i_instance_name);
|
|
|
|
if (rv == 0)
|
|
{
|
|
/* Allocate a block of memory large enough for the
|
|
* structure result, and the strings it contains */
|
|
unsigned int len = sizeof(struct scp_session_info) +
|
|
g_strlen(i_display) + 1 +
|
|
g_strlen(i_start_ip_addr) + 1 +
|
|
g_strlen(i_client_ip) + 1 +
|
|
g_strlen(i_client_name) + 1 +
|
|
g_strlen(i_instance_name) + 1;
|
|
if ((p = (struct scp_session_info *)g_malloc(len, 1)) == NULL)
|
|
{
|
|
*status = E_SCP_LS_NO_MEMORY;
|
|
}
|
|
else
|
|
{
|
|
/* Set a pointer to access the strings after the block */
|
|
char *memptr =
|
|
(char *)p + sizeof(struct scp_session_info);
|
|
#define COPY_STRING(ptr,src) \
|
|
{ \
|
|
size_t len = strlen(src) + 1; \
|
|
(ptr) = memptr; \
|
|
memcpy(memptr, src, len); \
|
|
memptr += len; \
|
|
}
|
|
/* Copy the data over */
|
|
p->sid = i_sid;
|
|
COPY_STRING(p->display, i_display);
|
|
p->type = (enum scp_session_type)i_type;
|
|
p->width = i_width;
|
|
p->height = i_height;
|
|
p->bpp = i_bpp;
|
|
p->start_time = i_start_time;
|
|
p->uid = i_uid;
|
|
COPY_STRING(p->start_ip_addr, i_start_ip_addr);
|
|
COPY_STRING(p->client_ip, i_client_ip);
|
|
COPY_STRING(p->client_name, i_client_name);
|
|
p->last_connect_disconnect = i_last_connect_disconnect;
|
|
COPY_STRING(p->xrdp_instance_name, i_instance_name);
|
|
#undef COPY_STRING
|
|
}
|
|
}
|
|
}
|
|
*info = p;
|
|
}
|
|
return rv;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
int
|
|
scp_send_create_sockdir_request(struct trans *trans)
|
|
{
|
|
return libipm_msg_out_simple_send(
|
|
trans,
|
|
(int)E_SCP_CREATE_SOCKDIR_REQUEST,
|
|
NULL);
|
|
}
|
|
|
|
|
|
/*****************************************************************************/
|
|
|
|
int
|
|
scp_send_create_sockdir_response(struct trans *trans,
|
|
enum scp_create_sockdir_status status)
|
|
{
|
|
return libipm_msg_out_simple_send(
|
|
trans,
|
|
(int)E_SCP_CREATE_SOCKDIR_RESPONSE,
|
|
"i", status);
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
int
|
|
scp_get_create_sockdir_response(struct trans *trans,
|
|
enum scp_create_sockdir_status *status)
|
|
{
|
|
int32_t i_status = 0;
|
|
int rv = libipm_msg_in_parse(trans, "i", &i_status);
|
|
if (rv == 0)
|
|
{
|
|
*status = (enum scp_create_sockdir_status)i_status;
|
|
}
|
|
|
|
return rv;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
int
|
|
scp_send_close_connection_request(struct trans *trans)
|
|
{
|
|
return libipm_msg_out_simple_send(
|
|
trans,
|
|
(int)E_SCP_CLOSE_CONNECTION_REQUEST,
|
|
NULL);
|
|
}
|