Add libipm facility
This commit is contained in:
+505
@@ -0,0 +1,505 @@
|
||||
/**
|
||||
* 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 "scp.h"
|
||||
#include "libipm.h"
|
||||
#include "guid.h"
|
||||
#include "trans.h"
|
||||
#include "os_calls.h"
|
||||
#include "string_calls.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
static const char *
|
||||
msgno_to_str(unsigned short n)
|
||||
{
|
||||
return
|
||||
(n == E_SCP_GATEWAY_REQUEST) ? "SCP_GATEWAY_REQUEST" :
|
||||
(n == E_SCP_GATEWAY_RESPONSE) ? "SCP_GATEWAY_RESPONSE" :
|
||||
(n == E_SCP_CREATE_SESSION_REQUEST) ? "SCP_CREATE_SESSION_REQUEST" :
|
||||
(n == E_SCP_CREATE_SESSION_RESPONSE) ? "SCP_CREATE_SESSION_RESPONSE" :
|
||||
(n == E_SCP_LIST_SESSIONS_REQUEST) ? "SCP_LIST_SESSIONS_REQUEST" :
|
||||
(n == E_SCP_LIST_SESSIONS_RESPONSE) ? "SCP_LIST_SESSIONS_RESPONSE" :
|
||||
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;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
struct trans *
|
||||
scp_connect(const char *host, const char *port,
|
||||
int (*term_func)(void))
|
||||
{
|
||||
struct trans *t;
|
||||
if ((t = trans_create(TRANS_MODE_TCP, 128, 128)) != NULL)
|
||||
{
|
||||
int index;
|
||||
|
||||
if (host == NULL)
|
||||
{
|
||||
host = "localhost";
|
||||
}
|
||||
|
||||
if (port == NULL)
|
||||
{
|
||||
port = "3350";
|
||||
}
|
||||
|
||||
t->is_term = term_func;
|
||||
|
||||
/* try to connect up to 4 times
|
||||
*
|
||||
* term_func can be NULL, so check before calling it */
|
||||
index = 4;
|
||||
while (trans_connect(t, host, port, 3000) != 0 &&
|
||||
!(term_func && term_func()) &&
|
||||
--index > 0)
|
||||
{
|
||||
g_sleep(1000);
|
||||
LOG_DEVEL(LOG_LEVEL_DEBUG, "Connect failed. Trying again...");
|
||||
}
|
||||
|
||||
if (t->status != TRANS_STATUS_UP)
|
||||
{
|
||||
trans_delete(t);
|
||||
t = NULL;
|
||||
}
|
||||
else if (libipm_init_trans(t, LIBIPM_FAC_SCP, msgno_to_str) !=
|
||||
E_LI_SUCCESS)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
void
|
||||
scp_msg_in_reset(struct trans *trans)
|
||||
{
|
||||
libipm_msg_in_reset(trans);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
enum scp_msg_code
|
||||
scp_msg_in_start(struct trans *trans)
|
||||
{
|
||||
return (enum scp_msg_code)libipm_msg_in_start(trans);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int
|
||||
scp_send_gateway_request(struct trans *trans,
|
||||
const char *username,
|
||||
const char *password)
|
||||
{
|
||||
int rv;
|
||||
|
||||
rv = libipm_msg_out_simple_send(
|
||||
trans,
|
||||
(int)E_SCP_GATEWAY_REQUEST,
|
||||
"ss",
|
||||
username,
|
||||
password);
|
||||
|
||||
/* Wipe the output buffer to remove the password */
|
||||
libipm_msg_out_erase(trans);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
int
|
||||
scp_get_gateway_request(struct trans *trans,
|
||||
const char **username,
|
||||
const char **password)
|
||||
{
|
||||
/* 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, "ss", username, password);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
int
|
||||
scp_send_gateway_response(struct trans *trans,
|
||||
int auth_result)
|
||||
{
|
||||
return libipm_msg_out_simple_send(
|
||||
trans,
|
||||
(int)E_SCP_GATEWAY_RESPONSE,
|
||||
"i",
|
||||
auth_result);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
int
|
||||
scp_get_gateway_response(struct trans *trans,
|
||||
int *auth_result)
|
||||
{
|
||||
int32_t i_auth_result = 0;
|
||||
int rv = libipm_msg_in_parse(trans, "i", &i_auth_result);
|
||||
if (rv == 0)
|
||||
{
|
||||
*auth_result = i_auth_result;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
int
|
||||
scp_send_create_session_request(struct trans *trans,
|
||||
const char *username,
|
||||
const char *password,
|
||||
enum scp_session_type type,
|
||||
unsigned short width,
|
||||
unsigned short height,
|
||||
unsigned char bpp,
|
||||
const char *shell,
|
||||
const char *directory,
|
||||
const char *connection_description)
|
||||
{
|
||||
int rv = libipm_msg_out_simple_send(
|
||||
trans,
|
||||
(int)E_SCP_CREATE_SESSION_REQUEST,
|
||||
"ssyqqysss",
|
||||
username,
|
||||
password,
|
||||
type,
|
||||
width,
|
||||
height,
|
||||
bpp,
|
||||
shell,
|
||||
directory,
|
||||
connection_description);
|
||||
|
||||
/* Wipe the output buffer to remove the password */
|
||||
libipm_msg_out_erase(trans);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
int
|
||||
scp_get_create_session_request(struct trans *trans,
|
||||
const char **username,
|
||||
const char **password,
|
||||
enum scp_session_type *type,
|
||||
unsigned short *width,
|
||||
unsigned short *height,
|
||||
unsigned char *bpp,
|
||||
const char **shell,
|
||||
const char **directory,
|
||||
const char **connection_description)
|
||||
{
|
||||
/* Intermediate values */
|
||||
uint8_t i_type;
|
||||
uint16_t i_width;
|
||||
uint16_t i_height;
|
||||
uint8_t i_bpp;
|
||||
|
||||
/* Make sure the buffer is cleared after processing this message */
|
||||
libipm_set_flags(trans, LIBIPM_E_MSG_IN_ERASE_AFTER_USE);
|
||||
|
||||
int rv = libipm_msg_in_parse(
|
||||
trans,
|
||||
"ssyqqysss",
|
||||
username,
|
||||
password,
|
||||
&i_type,
|
||||
&i_width,
|
||||
&i_height,
|
||||
&i_bpp,
|
||||
shell,
|
||||
directory,
|
||||
connection_description);
|
||||
|
||||
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,
|
||||
int auth_result,
|
||||
int 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,
|
||||
"iiB",
|
||||
auth_result,
|
||||
display,
|
||||
&guid_descriptor);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
int
|
||||
scp_get_create_session_response(struct trans *trans,
|
||||
int *auth_result,
|
||||
int *display,
|
||||
struct guid *guid)
|
||||
{
|
||||
/* Intermediate values */
|
||||
int32_t i_auth_result;
|
||||
int32_t i_display;
|
||||
|
||||
const struct libipm_fsb guid_descriptor = { (void *)guid, sizeof(*guid) };
|
||||
|
||||
int rv = libipm_msg_in_parse(
|
||||
trans,
|
||||
"iiB",
|
||||
&i_auth_result,
|
||||
&i_display,
|
||||
&guid_descriptor);
|
||||
if (rv == 0)
|
||||
{
|
||||
*auth_result = i_auth_result;
|
||||
*display = i_display;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
int
|
||||
scp_send_list_sessions_request(struct trans *trans,
|
||||
const char *username,
|
||||
const char *password)
|
||||
{
|
||||
int rv;
|
||||
|
||||
rv = libipm_msg_out_simple_send(
|
||||
trans,
|
||||
(int)E_SCP_LIST_SESSIONS_REQUEST,
|
||||
"ss",
|
||||
username,
|
||||
password);
|
||||
|
||||
/* Wipe the output buffer to remove the password */
|
||||
libipm_msg_out_erase(trans);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
int
|
||||
scp_get_list_sessions_request(struct trans *trans,
|
||||
const char **username,
|
||||
const char **password)
|
||||
{
|
||||
/* 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, "ss", username, password);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
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,
|
||||
"iiuyqqyxss",
|
||||
status,
|
||||
info->sid,
|
||||
info->display,
|
||||
info->type,
|
||||
info->width,
|
||||
info->height,
|
||||
info->bpp,
|
||||
info->start_time,
|
||||
info->username,
|
||||
info->connection_description);
|
||||
}
|
||||
|
||||
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;
|
||||
uint32_t i_display;
|
||||
uint8_t i_type;
|
||||
uint16_t i_width;
|
||||
uint16_t i_height;
|
||||
uint8_t i_bpp;
|
||||
int64_t i_start_time;
|
||||
char *i_username;
|
||||
char *i_connection_description;
|
||||
|
||||
rv = libipm_msg_in_parse(
|
||||
trans,
|
||||
"iuyqqyxss",
|
||||
&i_sid,
|
||||
&i_display,
|
||||
&i_type,
|
||||
&i_width,
|
||||
&i_height,
|
||||
&i_bpp,
|
||||
&i_start_time,
|
||||
&i_username,
|
||||
&i_connection_description);
|
||||
|
||||
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_username) + 1 +
|
||||
g_strlen(i_connection_description) + 1;
|
||||
if ((p = (struct scp_session_info *)g_malloc(len, 1)) == NULL)
|
||||
{
|
||||
*status = E_SCP_LS_NO_MEMORY;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Set up the string pointers in the block to point
|
||||
* into the memory allocated after the block */
|
||||
p->username = (char *)p + sizeof(struct scp_session_info);
|
||||
p->connection_description =
|
||||
p->username + g_strlen(i_username) + 1;
|
||||
|
||||
/* Copy the data over */
|
||||
p->sid = i_sid;
|
||||
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;
|
||||
g_strcpy(p->username, i_username);
|
||||
g_strcpy(p->connection_description,
|
||||
i_connection_description);
|
||||
}
|
||||
}
|
||||
}
|
||||
*info = p;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
Reference in New Issue
Block a user