From d09ebb2d10fbd9869cbfccf186e874c24818a9c6 Mon Sep 17 00:00:00 2001 From: matt335672 <30179339+matt335672@users.noreply.github.com> Date: Mon, 30 Jun 2025 14:59:52 +0100 Subject: [PATCH] Add initial CCP to libipm --- libipm/Makefile.am | 4 + libipm/ccp.c | 122 +++++++++++++++++++++++++++++ libipm/ccp.h | 136 +++++++++++++++++++++++++++++++++ libipm/ccp_application_types.c | 58 ++++++++++++++ libipm/ccp_application_types.h | 52 +++++++++++++ libipm/libipm_facilities.h | 1 + 6 files changed, 373 insertions(+) create mode 100644 libipm/ccp.c create mode 100644 libipm/ccp.h create mode 100644 libipm/ccp_application_types.c create mode 100644 libipm/ccp_application_types.h diff --git a/libipm/Makefile.am b/libipm/Makefile.am index 8da084bc..6ec0c810 100644 --- a/libipm/Makefile.am +++ b/libipm/Makefile.am @@ -13,6 +13,10 @@ libipm_la_SOURCES = \ libipm_recv.c \ libipm_facilities.h \ libipm_private.h \ + ccp.h \ + ccp.c \ + ccp_application_types.h \ + ccp_application_types.c \ eicp.h \ eicp.c \ ercp.h \ diff --git a/libipm/ccp.c b/libipm/ccp.c new file mode 100644 index 00000000..3df33721 --- /dev/null +++ b/libipm/ccp.c @@ -0,0 +1,122 @@ +/** + * 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/ccp.c + * @brief CCP definitions + * @author Matt Burt + */ + +#if defined(HAVE_CONFIG_H) +#include +#endif + +#include +#include + +#include "ccp.h" +#include "libipm.h" +#include "trans.h" + +/*****************************************************************************/ +static const char * +msgno_to_str(unsigned short n) +{ + return + (n == E_CCP_CLOSE_CONNECTION_REQUEST) ? "E_CCP_CLOSE_CONNECTION_REQUEST" : + NULL; +} + +/*****************************************************************************/ +const char * +ccp_msgno_to_str(enum ccp_msg_code n, char *buff, unsigned int buff_size) +{ + const char *str = msgno_to_str((unsigned short)n); + + if (str == NULL) + { + (void)snprintf(buff, buff_size, "[code #%d]", (int)n); + } + else + { + (void)snprintf(buff, buff_size, "%s", str); + } + + return buff; +} + +/*****************************************************************************/ +void +ccp_trans_from_scp_trans(struct trans *trans, + ttrans_data_in callback_func, + void *callback_data) +{ + libipm_change_facility(trans, LIBIPM_FAC_SCP, LIBIPM_FAC_CCP); + trans->trans_data_in = callback_func; + trans->callback_data = callback_data; +} + +/*****************************************************************************/ +int +ccp_msg_in_check_available(struct trans *trans, int *available) +{ + return libipm_msg_in_check_available(trans, available); +} + +/*****************************************************************************/ +enum ccp_msg_code +ccp_msg_in_get_msgno(const struct trans *trans) +{ + return (enum ccp_msg_code)libipm_msg_in_get_msgno(trans); +} + +/*****************************************************************************/ +void +ccp_msg_in_reset(struct trans *trans) +{ + libipm_msg_in_reset(trans); +} + +/*****************************************************************************/ +int +ccp_send_close_connection_request(struct trans *trans, + enum ccp_close_reason_type reason) +{ + return libipm_msg_out_simple_send( + trans, + (int)E_CCP_CLOSE_CONNECTION_REQUEST, + "i", reason); +} + +/*****************************************************************************/ +int +ccp_get_close_connection_request(struct trans *trans, + enum ccp_close_reason_type *reason) +{ + /* Intermediate values */ + int32_t i_reason; + + int rv = libipm_msg_in_parse( trans, "i", &i_reason); + if (rv == 0) + { + *reason = (enum ccp_close_reason_type)i_reason; + } + + return rv; +} diff --git a/libipm/ccp.h b/libipm/ccp.h new file mode 100644 index 00000000..419f0b40 --- /dev/null +++ b/libipm/ccp.h @@ -0,0 +1,136 @@ +/** + * xrdp: A Remote Desktop Protocol server. + * + * Copyright (C) Jay Sorg 2004-2025, 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/ccp.h + * @brief CCP declarations + * @author Matt Burt + * + * Functions in this file use the following naming conventions:- + * + * E_CCP_{msg}_REQUEST is sent by ccp_send_{msg}_request() + * E_CCP_{msg}_REQUEST is parsed by ccp_get_{msg}_request() + * E_CCP_{msg}_RESPONSE is sent by ccp_send_{msg}_response() + * E_CCP_{msg}_RESPONSE is parsed by ccp_get_{msg}_response() + * E_CCP_{msg}_EVENT is sent by ccp_send_{msg}_event() + * E_CCP_{msg}_EVENT is parsed by ccp_get_{msg}_event() + */ + +#ifndef CCP_H +#define CCP_H + +#include "arch.h" +#include "trans.h" +#include "ccp_application_types.h" + +/* Message codes */ +enum ccp_msg_code +{ + E_CCP_CLOSE_CONNECTION_REQUEST // sesexec -> xrdp + // No E_CCP_CLOSE_CONNECTION_RESPONSE +}; + +/* 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 * +ccp_msgno_to_str(enum ccp_msg_code n, char *buff, unsigned int buff_size); + +/* Connection management facilities */ + +/** + * Converts an SCP transport to an CCP transport. + * + * This is done following successful transmission or receipt of an + * E_SCP_CONNECT_SESSION_RESPONSE + * + * @param trans connected endpoint + * @param callback_func New callback function for CCP messages. + * @param callback_data New argument for callback function + */ +void +ccp_trans_from_scp_trans(struct trans *trans, + ttrans_data_in callback_func, + void *callback_data); + +/** + * Checks an CCP transport to see if a complete message is + * available for parsing + * + * @param trans CCP transport + * @param[out] available != 0 if a complete message is available + * @return != 0 for error + */ +int +ccp_msg_in_check_available(struct trans *trans, int *available); + +/** + * Gets the CCP message number of an incoming message + * + * @param trans CCP transport + * @return message in the buffer + * + * The results of calling this routine before ccp_msg_in_check_available() + * states a message is available are undefined. + */ +enum ccp_msg_code +ccp_msg_in_get_msgno(const struct trans *trans); + +/** + * Resets an CCP message buffer ready to receive the next message + * + * @param trans libipm transport + */ +void +ccp_msg_in_reset(struct trans *trans); + +/* -------------------- Session messages-------------------- */ +/** + * Send an E_CCP_CLOSE_CONNECTION_REQUEST + * + * Direction : sesexec -> xrdp + * + * @param trans CCP transport + * @param reason reason_code + * @return != 0 for error + */ +int +ccp_send_close_connection_request(struct trans *trans, + enum ccp_close_reason_type reason); + +/** + * Parse an incoming E_CCP_CLOSE_CONNECTION_REQUEST + * + * Direction : sesexec -> xrdp + * + * @param trans CCP transport + * @param[out] reason reason_code + * @return != 0 for error + */ +int +ccp_get_close_connection_request(struct trans *trans, + enum ccp_close_reason_type *reason); + +#endif /* CCP_H */ diff --git a/libipm/ccp_application_types.c b/libipm/ccp_application_types.c new file mode 100644 index 00000000..b2518e44 --- /dev/null +++ b/libipm/ccp_application_types.c @@ -0,0 +1,58 @@ +/** + * 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/ccp_application_types.c + * @brief Support routines for types in ccp_application_types.h + * @author Matt Burt + */ + +#if defined(HAVE_CONFIG_H) +#include +#endif + +#include + +#include "ccp_application_types.h" + +/*****************************************************************************/ +const char * +ccp_close_reason_to_str(enum ccp_close_reason_type n, + char *buff, unsigned int buff_size) +{ + const char *str = + (n == CCP_CLOSE_RPC_INITIATED_DISCONNECT) + ? "Connection closed by administrator request" : + (n == CCP_CLOSE_DISCONNECTED_BY_OTHERCONNECTION) + ? "Another connection was made to the session" : + (n == CCP_CLOSE_LOGOFF_BY_USER) + ? "The user logged out of the session" : + /* Default */ NULL; + + if (str == NULL) + { + (void)snprintf(buff, buff_size, "[ccp reason code #%d]", (int)n); + } + else + { + (void)snprintf(buff, buff_size, "%s", str); + } + + return buff; +} diff --git a/libipm/ccp_application_types.h b/libipm/ccp_application_types.h new file mode 100644 index 00000000..55fe6c78 --- /dev/null +++ b/libipm/ccp_application_types.h @@ -0,0 +1,52 @@ +/** + * 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/ccp_application_types.h + * @brief ccp type declarations intended for use in the application + * @author Simone Fedele/ Matt Burt + */ + +#ifndef CCP_APPLICATION_TYPES_H +#define CCP_APPLICATION_TYPES_H + +#include + +/** + * Select the reason for a close connection request + */ +enum ccp_close_reason_type +{ + CCP_CLOSE_RPC_INITIATED_DISCONNECT = 1, + CCP_CLOSE_DISCONNECTED_BY_OTHERCONNECTION, + CCP_CLOSE_LOGOFF_BY_USER +}; + +/** + * Convert an ccp_close_reason_type to a readable 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 * +ccp_close_reason_to_str(enum ccp_close_reason_type n, + char *buff, unsigned int buff_size); + +#endif /* CCP_APPLICATION_TYPES_H */ diff --git a/libipm/libipm_facilities.h b/libipm/libipm_facilities.h index 16b1cd2c..4dbd2561 100644 --- a/libipm/libipm_facilities.h +++ b/libipm/libipm_facilities.h @@ -30,6 +30,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_CCP, /**< CCP - Connection Control Protocol */ LIBIPM_FAC_TEST = 65535 /**< Used for unit testing */ };