From dec05f91fad217df7d23cbe9b0addc60c446f877 Mon Sep 17 00:00:00 2001 From: matt335672 <30179339+matt335672@users.noreply.github.com> Date: Wed, 22 Mar 2023 14:48:58 +0000 Subject: [PATCH] libipm: Add ERCP --- libipm/Makefile.am | 2 + libipm/ercp.c | 216 +++++++++++++++++++++++++++++++++ libipm/ercp.h | 236 +++++++++++++++++++++++++++++++++++++ libipm/libipm_facilities.h | 1 + 4 files changed, 455 insertions(+) create mode 100644 libipm/ercp.c create mode 100644 libipm/ercp.h diff --git a/libipm/Makefile.am b/libipm/Makefile.am index f0bd2a1a..84ea0948 100644 --- a/libipm/Makefile.am +++ b/libipm/Makefile.am @@ -15,6 +15,8 @@ libipm_la_SOURCES = \ libipm_private.h \ eicp.h \ eicp.c \ + ercp.h \ + ercp.c \ scp.h \ scp.c \ scp_application_types.h \ diff --git a/libipm/ercp.c b/libipm/ercp.c new file mode 100644 index 00000000..a5ba61c9 --- /dev/null +++ b/libipm/ercp.c @@ -0,0 +1,216 @@ +/** + * 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/ercp.c + * @brief ERCP definitions + * @author Matt Burt + */ + +#if defined(HAVE_CONFIG_H) +#include +#endif + +#include "ercp.h" +#include "libipm.h" +#include "guid.h" +#include "os_calls.h" +#include "trans.h" + +/*****************************************************************************/ +static const char * +msgno_to_str(unsigned short n) +{ + return + (n == E_ERCP_SESSION_ANNOUNCE_EVENT) ? "ERCP_SESSION_ANNOUNCE_EVENT" : + (n == E_ERCP_SESSION_FINISHED_EVENT) ? "ERCP_SESSION_FINISHED_EVENT" : + NULL; +} + +/*****************************************************************************/ +const char * +ercp_msgno_to_str(enum ercp_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; +} + +/*****************************************************************************/ +int +ercp_init_trans(struct trans *trans) +{ + return libipm_init_trans(trans, LIBIPM_FAC_ERCP, msgno_to_str); +} + +/*****************************************************************************/ +void +ercp_trans_from_eicp_trans(struct trans *trans, + ttrans_data_in callback_func, + void *callback_data) +{ + libipm_change_facility(trans, LIBIPM_FAC_EICP, LIBIPM_FAC_ERCP); + trans->trans_data_in = callback_func; + trans->callback_data = callback_data; +} + +/*****************************************************************************/ + +int +ercp_msg_in_check_available(struct trans *trans, int *available) +{ + return libipm_msg_in_check_available(trans, available); +} + +/*****************************************************************************/ + +int +ercp_msg_in_wait_available(struct trans *trans) +{ + return libipm_msg_in_wait_available(trans); +} + +/*****************************************************************************/ + +enum ercp_msg_code +ercp_msg_in_get_msgno(const struct trans *trans) +{ + return (enum ercp_msg_code)libipm_msg_in_get_msgno(trans); +} + +/*****************************************************************************/ + +void +ercp_msg_in_reset(struct trans *trans) +{ + libipm_msg_in_reset(trans); +} + +/*****************************************************************************/ + +int +ercp_send_session_announce_event(struct trans *trans, + unsigned int display, + uid_t uid, + enum scp_session_type type, + unsigned short start_width, + unsigned short start_height, + unsigned char bpp, + const struct guid *guid, + const char *start_ip_addr, + time_t start_time) +{ + struct libipm_fsb guid_descriptor = { (void *)guid, sizeof(*guid) }; + + return libipm_msg_out_simple_send( + trans, + (int)E_ERCP_SESSION_ANNOUNCE_EVENT, + "uiyqqyBsx", + display, + uid, + type, + start_width, + start_height, + bpp, + &guid_descriptor, + start_ip_addr, + start_time); +} + +/*****************************************************************************/ + +int +ercp_get_session_announce_event(struct trans *trans, + unsigned int *display, + uid_t *uid, + enum scp_session_type *type, + unsigned short *start_width, + unsigned short *start_height, + unsigned char *bpp, + struct guid *guid, + const char **start_ip_addr, + time_t *start_time) +{ + /* Intermediate values */ + uint32_t i_display; + int32_t i_uid; + uint8_t i_type; + uint16_t i_width; + uint16_t i_height; + uint8_t i_bpp; + int64_t i_start_time; + + const struct libipm_fsb guid_descriptor = { (void *)guid, sizeof(*guid) }; + + int rv = libipm_msg_in_parse( + trans, + "uiyqqyBsx", + &i_display, + &i_uid, + &i_type, + &i_width, + &i_height, + &i_bpp, + &guid_descriptor, + start_ip_addr, + &i_start_time); + + if (rv == 0) + { + if (display != NULL) + { + *display = i_display; + } + *uid = (uid_t)i_uid; + *type = (enum scp_session_type)i_type; + *start_width = i_width; + *start_height = i_height; + *bpp = i_bpp; + *start_time = (time_t)i_start_time; + } + + return rv; +} + +/*****************************************************************************/ + +int +ercp_send_session_finished_event(struct trans *trans) +{ + return libipm_msg_out_simple_send( + trans, (int)E_ERCP_SESSION_FINISHED_EVENT, NULL); +} + +/*****************************************************************************/ + +int +ercp_send_session_reconnect_event(struct trans *trans) +{ + return libipm_msg_out_simple_send( + trans, (int)E_ERCP_SESSION_RECONNECT_EVENT, NULL); +} diff --git a/libipm/ercp.h b/libipm/ercp.h new file mode 100644 index 00000000..aac0a8d6 --- /dev/null +++ b/libipm/ercp.h @@ -0,0 +1,236 @@ +/** + * 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/ercp.h + * @brief ERCP declarations + * @author Matt Burt + * + * Functions in this file use the following naming conventions:- + * + * E_ERCP_{msg}_REQUEST is sent by ercp_send_{msg}_request() + * E_ERCP_{msg}_REQUEST is parsed by ercp_get_{msg}_request() + * E_ERCP_{msg}_RESPONSE is sent by ercp_send_{msg}_response() + * E_ERCP_{msg}_RESPONSE is parsed by ercp_get_{msg}_response() + * E_ERCP_{msg}_EVENT is sent by ercp_send_{msg}_event() + * E_ERCP_{msg}_EVENT is parsed by ercp_get_{msg}_event() + */ + +#ifndef ERCP_H +#define ERCP_H + +#include "arch.h" +#include "scp_application_types.h" +#include "trans.h" + +struct guid; + +/* Message codes */ +enum ercp_msg_code +{ + E_ERCP_SESSION_ANNOUNCE_EVENT, + E_ERCP_SESSION_FINISHED_EVENT, + + E_ERCP_SESSION_RECONNECT_EVENT +}; + +/* Common facilities */ + +/** + * Convert a message code to a string for output + * @param n Message code + * @param buff to contain string + * @param buff_size length of buff + * @return buff is returned for convenience. + */ +const char * +ercp_msgno_to_str(enum ercp_msg_code n, char *buff, unsigned int buff_size); + +/* Connection management facilities */ + +/** + * Converts a standard trans connected to an ERCP endpoint to an ERCP transport + * + * @param trans connected endpoint + * @return != 0 for error + */ +int +ercp_init_trans(struct trans *trans); + +/** + * Converts an EICP transport to an ERCP transport. + * + * This is done following successful transmission or receipt of an + * E_EICP_CREATE_SESSION_REQUEST. + * + * @param trans connected endpoint + * @param callback_func New callback function for ERCP messages. + * @param callback_data New argument for callback function + */ +void +ercp_trans_from_eicp_trans(struct trans *trans, + ttrans_data_in callback_func, + void *callback_data); + + +/** + * Checks an ERCP transport to see if a complete message is + * available for parsing + * + * @param trans ERCP transport + * @param[out] available != 0 if a complete message is available + * @return != 0 for error + */ +int +ercp_msg_in_check_available(struct trans *trans, int *available); + +/** + * Waits on a single transport for an ERCP message to be available for + * parsing + * + * @param trans libipm transport + * @return != 0 for error + * + * While the call is active, data-in callbacks for the transport are + * disabled. + * + * Only use this call if you have nothing to do until a message + * arrives on the transport. If you have other transports to service, use + * ercp_msg_in_check_available() + */ +int +ercp_msg_in_wait_available(struct trans *trans); + + +/** + * Gets the ERCP message number of an incoming message + * + * @param trans ERCP transport + * @return message in the buffer + * + * The results of calling this routine before ercp_msg_in_check_available() + * states a message is available are undefined. + */ +enum ercp_msg_code +ercp_msg_in_get_msgno(const struct trans *trans); + +/** + * Resets an ERCP message buffer ready to receive the next message + * + * @param trans libipm transport + */ +void +ercp_msg_in_reset(struct trans *trans); + +/* -------------------- Session event messages-------------------- */ +/** + * Send an E_ERCP_SESSION_ANNOUNCE_EVENT + * + * Direction : sesexec -> sesman + * + * This event contains all the information known about a session + * + * @param trans EICP transport + * @param display Display used by session + * @param uid UID of user logged in to session + * @param type Session type + * @param start_width Starting width of seenio + * @param start_height Starting height of session + * @param bpp Bits-per-pixel for session + * @param guid Session GUID + * @param start_ip_addr Starting IP address of client + * @param start_time Session start time + * @return != 0 for error + */ +int +ercp_send_session_announce_event(struct trans *trans, + unsigned int display, + uid_t uid, + enum scp_session_type type, + unsigned short start_width, + unsigned short start_height, + unsigned char bpp, + const struct guid *guid, + const char *start_ip_addr, + time_t start_time); + + +/** + * Parse an incoming E_ERCP_SESSION_ANNOUNCE_EVENT + * + * This event contains all the information known about a session + * + * @param trans EICP transport + * @param[out] display Display used by session. + * Pointer can be NULL if this is already known. + * @param[out] uid UID of user logged in to session + * @param[out] type Session type + * @param[out] start_width Starting width of seenio + * @param[out] start_height Starting height of session + * @param[out] bpp Bits-per-pixel for session + * @param[out] guid Session GUID + * @param[out] start_ip_addr Starting IP address of client + * @param[out] start_time Session start time + * @return != 0 for error + */ +int +ercp_get_session_announce_event(struct trans *trans, + unsigned int *display, + uid_t *uid, + enum scp_session_type *type, + unsigned short *start_width, + unsigned short *start_height, + unsigned char *bpp, + struct guid *guid, + const char **start_ip_addr, + time_t *start_time); + + +/** + * Send an E_ERCP_SESSION_FINISHED_EVENT + * + * Direction : sesexec -> sesman + * + * This event simply states the attached session has finished and can be + * removed from any data structures held by sesman + * + * @param trans EICP transport + * @return != 0 for error + */ +int +ercp_send_session_finished_event(struct trans *trans); + + + +/** + * Send an E_ERCP_SESSION_RECONNECT_EVENT + * + * Direction : sesman -> sesexec + * + * This event tells sesexec that a reconnection is about to occur, and + * sesexec should run the reconnect script. + * + * @param trans EICP transport + * @return != 0 for error + */ +int +ercp_send_session_reconnect_event(struct trans *trans); + + +#endif /* ERCP_H */ diff --git a/libipm/libipm_facilities.h b/libipm/libipm_facilities.h index aa5482ac..16b1cd2c 100644 --- a/libipm/libipm_facilities.h +++ b/libipm/libipm_facilities.h @@ -29,6 +29,7 @@ enum libipm_facility { LIBIPM_FAC_SCP = 1, /**< SCP - Sesman Control Protocol */ LIBIPM_FAC_EICP, /**< EICP - Executive Initialization Control Protocol */ + LIBIPM_FAC_ERCP, /**< ERCP - Executive Run-time Control Protocol */ LIBIPM_FAC_TEST = 65535 /**< Used for unit testing */ };