Add libipm facility
This commit is contained in:
parent
8f4860cb55
commit
e059336dff
@ -45,6 +45,7 @@ SUBDIRS = \
|
|||||||
xup \
|
xup \
|
||||||
mc \
|
mc \
|
||||||
$(NEUTRINORDPDIR) \
|
$(NEUTRINORDPDIR) \
|
||||||
|
libipm \
|
||||||
libxrdp \
|
libxrdp \
|
||||||
$(PAINTERDIR) \
|
$(PAINTERDIR) \
|
||||||
$(RFXCODECDIR) \
|
$(RFXCODECDIR) \
|
||||||
|
@ -484,6 +484,7 @@ AC_CONFIG_FILES([
|
|||||||
instfiles/pulse/Makefile
|
instfiles/pulse/Makefile
|
||||||
instfiles/rc.d/Makefile
|
instfiles/rc.d/Makefile
|
||||||
keygen/Makefile
|
keygen/Makefile
|
||||||
|
libipm/Makefile
|
||||||
libxrdp/Makefile
|
libxrdp/Makefile
|
||||||
Makefile
|
Makefile
|
||||||
mc/Makefile
|
mc/Makefile
|
||||||
|
2523
libipm/Doxyfile
Normal file
2523
libipm/Doxyfile
Normal file
File diff suppressed because it is too large
Load Diff
20
libipm/Makefile.am
Normal file
20
libipm/Makefile.am
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
|
||||||
|
AM_CPPFLAGS = \
|
||||||
|
-I$(top_srcdir)/common
|
||||||
|
|
||||||
|
module_LTLIBRARIES = \
|
||||||
|
libipm.la
|
||||||
|
|
||||||
|
libipm_la_SOURCES = \
|
||||||
|
libipm.h \
|
||||||
|
libipm.c \
|
||||||
|
libipm_send.c \
|
||||||
|
libipm_recv.c \
|
||||||
|
libipm_facilities.h \
|
||||||
|
libipm_private.h \
|
||||||
|
scp.h \
|
||||||
|
scp.c \
|
||||||
|
scp_application_types.h
|
||||||
|
|
||||||
|
libipm_la_LIBADD = \
|
||||||
|
$(top_builddir)/common/libcommon.la
|
121
libipm/libipm.c
Normal file
121
libipm/libipm.c
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (C) 2022 Matt Burt, 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/libipm.c
|
||||||
|
* @brief Inter-Process Messaging building and parsing definitions
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if defined(HAVE_CONFIG_H)
|
||||||
|
#include <config_ac.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "libipm.h"
|
||||||
|
#include "libipm_private.h"
|
||||||
|
#include "libipm_facilities.h"
|
||||||
|
#include "trans.h"
|
||||||
|
#include "log.h"
|
||||||
|
#include "os_calls.h"
|
||||||
|
|
||||||
|
const char *libipm_valid_type_chars = "ybnqiuxtsdhogB";
|
||||||
|
|
||||||
|
/**************************************************************************//**
|
||||||
|
* Destructor for a struct trans initialised with libipm_init_trans()
|
||||||
|
*
|
||||||
|
* @param trans Transport to destroy
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
libipm_trans_destructor(struct trans *trans)
|
||||||
|
{
|
||||||
|
struct libipm_priv *priv = (struct libipm_priv *)trans->extra_data;
|
||||||
|
|
||||||
|
if (priv != NULL)
|
||||||
|
{
|
||||||
|
if ((priv->flags & LIBIPM_E_MSG_IN_ERASE_AFTER_USE) != 0 &&
|
||||||
|
trans->in_s->data != NULL)
|
||||||
|
{
|
||||||
|
g_memset(trans->in_s->data, '\0',
|
||||||
|
trans->in_s->end - trans->in_s->data);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_free(priv);
|
||||||
|
trans->extra_data = NULL;
|
||||||
|
trans->extra_destructor = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
enum libipm_status
|
||||||
|
libipm_init_trans(struct trans *trans,
|
||||||
|
enum libipm_facility facility,
|
||||||
|
const char *(*msgno_to_str)(unsigned short msgno))
|
||||||
|
{
|
||||||
|
struct libipm_priv *priv;
|
||||||
|
enum libipm_status rv;
|
||||||
|
|
||||||
|
if (trans->extra_data != NULL || trans->extra_destructor != NULL)
|
||||||
|
{
|
||||||
|
LOG(LOG_LEVEL_ERROR, "%s() called with sub-classed transport",
|
||||||
|
__func__);
|
||||||
|
rv = E_LI_PROGRAM_ERROR;
|
||||||
|
}
|
||||||
|
else if ((priv = g_new0(struct libipm_priv, 1)) == 0)
|
||||||
|
{
|
||||||
|
LOG(LOG_LEVEL_ERROR, "%s() out of memory", __func__);
|
||||||
|
rv = E_LI_NO_MEMORY;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
priv->facility = facility;
|
||||||
|
priv->msgno_to_str = msgno_to_str;
|
||||||
|
|
||||||
|
trans->extra_data = priv;
|
||||||
|
trans->extra_destructor = libipm_trans_destructor;
|
||||||
|
|
||||||
|
libipm_msg_in_reset(trans);
|
||||||
|
|
||||||
|
rv = E_LI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
void
|
||||||
|
libipm_set_flags(struct trans *trans, unsigned int flags)
|
||||||
|
{
|
||||||
|
struct libipm_priv *priv = (struct libipm_priv *)trans->extra_data;
|
||||||
|
|
||||||
|
if (priv != NULL)
|
||||||
|
{
|
||||||
|
priv->flags |= flags;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
void
|
||||||
|
libipm_clear_flags(struct trans *trans, unsigned int flags)
|
||||||
|
{
|
||||||
|
struct libipm_priv *priv = (struct libipm_priv *)trans->extra_data;
|
||||||
|
|
||||||
|
if (priv != NULL)
|
||||||
|
{
|
||||||
|
priv->flags &= ~flags;
|
||||||
|
}
|
||||||
|
}
|
329
libipm/libipm.h
Normal file
329
libipm/libipm.h
Normal file
@ -0,0 +1,329 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (C) 2022 Matt Burt, 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/libipm.h
|
||||||
|
* @brief Inter-Process Messaging building and parsing - public declarations
|
||||||
|
*
|
||||||
|
* The functions in this file are inspired by the D-Bus type system
|
||||||
|
* (see https://dbus.freedesktop.org/doc/dbus-specification.html),
|
||||||
|
* and the sd-bus library API.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if !defined(LIBIPM_H)
|
||||||
|
#define LIBIPM_H
|
||||||
|
|
||||||
|
#if defined(HAVE_CONFIG_H)
|
||||||
|
#include <config_ac.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "arch.h"
|
||||||
|
#include "libipm_facilities.h"
|
||||||
|
|
||||||
|
struct trans;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fixed-size block descriptor for sending blocks of data using libipm
|
||||||
|
*
|
||||||
|
* Use with the type code 'B'
|
||||||
|
*
|
||||||
|
* See the descriptions of libipm_msg_out_append() and libipm_msg_in_parse()
|
||||||
|
* for instructions on how to use this type.
|
||||||
|
*/
|
||||||
|
struct libipm_fsb
|
||||||
|
{
|
||||||
|
void *data;
|
||||||
|
unsigned int datalen;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Status code for library calls
|
||||||
|
*
|
||||||
|
* These are mainly intended so that the test suite can check the expected
|
||||||
|
* codepath has been followed.
|
||||||
|
*
|
||||||
|
* Wrappers around libipm may assume success is 0, and anything else
|
||||||
|
* is an error.
|
||||||
|
*/
|
||||||
|
enum libipm_status
|
||||||
|
{
|
||||||
|
E_LI_SUCCESS = 0,
|
||||||
|
E_LI_PROGRAM_ERROR, /***< Programming error */
|
||||||
|
E_LI_NO_MEMORY, /***< Memory allocaton failure */
|
||||||
|
E_LI_UNSUPPORTED_TYPE, /***< Specified type code is unsupported */
|
||||||
|
E_LI_UNIMPLEMENTED_TYPE, /***< Specified type code is unimplemented */
|
||||||
|
E_LI_UNEXPECTED_TYPE, /***< Encountered unexpected type on input */
|
||||||
|
E_LI_BUFFER_OVERFLOW, /***< End of buffer reached unexpectedly */
|
||||||
|
E_LI_BAD_VALUE, /***< Specified (or incoming) value is out of range */
|
||||||
|
E_LI_BAD_HEADER, /***< Bad incoming message header */
|
||||||
|
E_LI_TRANSPORT_ERROR /***< Error detected at the transport level */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Flags values for libipm_[set/clear]_flags() */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Input buffer contains sensitive information and must be
|
||||||
|
* erased by libipm_msg_in_reset(). The flag is one-shot, and
|
||||||
|
* is cleared after use.
|
||||||
|
*
|
||||||
|
* There is no corresponding flag for the output buffer -
|
||||||
|
* use libipm_msg_out_erase() explicitly
|
||||||
|
*/
|
||||||
|
#define LIBIPM_E_MSG_IN_ERASE_AFTER_USE (1u<<0)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prepare a standard 'struct trans' for use with libipm
|
||||||
|
*
|
||||||
|
* @param trans libipm transport
|
||||||
|
* @param facility Facility number from libipm_facilities.h
|
||||||
|
* @param msgno_to_str Function to turn a message number into a string
|
||||||
|
* @return != 0 for error.
|
||||||
|
*
|
||||||
|
* The msgno_to_str() function is used for error logging. If the routine
|
||||||
|
* is not specified, or the routine returns NULL, a numeric code is
|
||||||
|
* logged instead.
|
||||||
|
*/
|
||||||
|
enum libipm_status
|
||||||
|
libipm_init_trans(struct trans *trans,
|
||||||
|
enum libipm_facility facility,
|
||||||
|
const char *(*msgno_to_str)(unsigned short msgno));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the flag(s) specified for the transport
|
||||||
|
* @param trans libipm transport
|
||||||
|
* @param flags flags to set. Multiple flags should be or'd together.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
libipm_set_flags(struct trans *trans, unsigned int flags);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear the flag(s) specified for the transport
|
||||||
|
* @param trans libipm transport
|
||||||
|
* @param flags flags to clear. Multiple flags should be or'd together.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
libipm_clear_flags(struct trans *trans, unsigned int flags);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialise an output message
|
||||||
|
*
|
||||||
|
* @param trans libipm transport
|
||||||
|
* @param msgno message number
|
||||||
|
* @param format a description of any arguments to add to the buffer, or
|
||||||
|
* NULL if no arguments are to be added at this time.
|
||||||
|
*
|
||||||
|
* See libipm_msg_out_append() for details of the format string. The format
|
||||||
|
* string is followed immediately by the arguments it describes */
|
||||||
|
enum libipm_status
|
||||||
|
libipm_msg_out_init(struct trans *trans, unsigned short msgno,
|
||||||
|
const char *format, ...);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Append more arguments to an output message
|
||||||
|
*
|
||||||
|
* @param trans libipm transport
|
||||||
|
* @param format a description of any arguments to add to the buffer.
|
||||||
|
* @param != 0 if an error occurs
|
||||||
|
*
|
||||||
|
* The format string is followed immediately by the arguments it
|
||||||
|
* describes. The format string may contain these characters (from the
|
||||||
|
* D-Bus type system):-
|
||||||
|
*
|
||||||
|
* Char | C Type | Description
|
||||||
|
* ---- |------ | -----------
|
||||||
|
* y |uint8_t | Unsigned 8-bit integer
|
||||||
|
* b |int | Boolean value (see below)
|
||||||
|
* n |int16_t | Signed (two's complement) 16-bit integer
|
||||||
|
* q |uint16_t | Unsigned 16-bit integer
|
||||||
|
* i |int32_t | Signed (two's complement) 32-bit integer
|
||||||
|
* u |uint32_t | Unsigned 32-bit integer
|
||||||
|
* x |int64_t | Signed (two's complement) 64-bit integer
|
||||||
|
* t |uint64_t | Unsigned 64-bit integer
|
||||||
|
* s |char * | NULL-terminated string
|
||||||
|
* d | - | (reserved)
|
||||||
|
* h | - | (reserved)
|
||||||
|
* o | - | (reserved)
|
||||||
|
* g | - | (reserved)
|
||||||
|
*
|
||||||
|
* For the 'b' type, only values 0 and 1 are allowed. Other values
|
||||||
|
* generate an error.
|
||||||
|
*
|
||||||
|
* The following additions to the D-Bus type system are also supported:-
|
||||||
|
*
|
||||||
|
* Char |C Type | Description
|
||||||
|
* -----|------ | -----------
|
||||||
|
* B |const struct libipm_fsb * | Fixed-size block pointer
|
||||||
|
*
|
||||||
|
* For the 'B' type, pass in the address of a descriptor containing the
|
||||||
|
* address and size of the object. The object is copied to the output
|
||||||
|
* stream, along with its length.
|
||||||
|
*/
|
||||||
|
enum libipm_status
|
||||||
|
libipm_msg_out_append(struct trans *trans, const char *format, ...);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Marks a message as complete and ready for transmission
|
||||||
|
*
|
||||||
|
* @param trans libipm transport
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
libipm_msg_out_mark_end(struct trans *trans);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convenience sending function
|
||||||
|
*
|
||||||
|
* Constructs a simple message and sends it immediately using
|
||||||
|
* libipm_msg_out_init() / libipm_msg_out_mark_end() and
|
||||||
|
* trans_force_write()
|
||||||
|
*
|
||||||
|
* @param trans libipm transport
|
||||||
|
* @param msgno message number
|
||||||
|
* @param format a description of any arguments to add to the buffer, or
|
||||||
|
* NULL if no arguments are to be added at this time.
|
||||||
|
*
|
||||||
|
* See libipm_msg_out_append() for details of the format string. The format
|
||||||
|
* string is followed immediately by the arguments it describes
|
||||||
|
*/
|
||||||
|
enum libipm_status
|
||||||
|
libipm_msg_out_simple_send(struct trans *trans, unsigned short msgno,
|
||||||
|
const char *format, ...);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Erase (rather than just ignore) the contents of an output buffer
|
||||||
|
*
|
||||||
|
* Use after sending a message containing data which should not be
|
||||||
|
* kept in memory (e.g. passwords)`
|
||||||
|
* @param trans libipm transport
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
libipm_msg_out_erase(struct trans *trans);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks a transport to see if a complete libipm message is
|
||||||
|
* available for parsing
|
||||||
|
*
|
||||||
|
* @param trans libipm transport
|
||||||
|
* @param[out] available != 0 if a complete message is available
|
||||||
|
* @return != 0 for error
|
||||||
|
*/
|
||||||
|
enum libipm_status
|
||||||
|
libipm_msg_in_check_available(struct trans *trans, int *available);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Waits on a single transport for a libipm 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
|
||||||
|
* libipm_msg_in_check_available()
|
||||||
|
*/
|
||||||
|
enum libipm_status
|
||||||
|
libipm_msg_in_wait_available(struct trans *trans);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start parsing a message
|
||||||
|
*
|
||||||
|
* @param trans libipm transport
|
||||||
|
* @return message number in the buffer
|
||||||
|
*
|
||||||
|
* The results of calling this routine after a call to
|
||||||
|
* libipm_msg_in_reset() and before a successful call to
|
||||||
|
* libipm_msg_in_check_available() (or libipm_msg_wait_available())
|
||||||
|
* are undefined.
|
||||||
|
*
|
||||||
|
* Calling this function resets the message parsing pointer to the start
|
||||||
|
* of the message
|
||||||
|
*/
|
||||||
|
unsigned short
|
||||||
|
libipm_msg_in_start(struct trans *trans);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a letter corresponding to the next available type in the
|
||||||
|
* input stream.
|
||||||
|
*
|
||||||
|
* @param trans libipm transport
|
||||||
|
* @return letter of the type, '\0' for end of message, or '?' for
|
||||||
|
* an unrecognised type
|
||||||
|
*/
|
||||||
|
char
|
||||||
|
libipm_msg_in_peek_type(struct trans *trans);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads arguments from an input message
|
||||||
|
*
|
||||||
|
* @param trans libipm transport
|
||||||
|
* @param format a description of the arguments to read from the buffer.
|
||||||
|
* @param != 0 if an error occurs
|
||||||
|
*
|
||||||
|
* The format string is followed immediately by the arguments it
|
||||||
|
* describes. The format string may contain these characters (from the
|
||||||
|
* D-Bus type system):-
|
||||||
|
*
|
||||||
|
* Char | C Type | Description
|
||||||
|
* ---- | ------ | -----------
|
||||||
|
* y | uint8_t * | Unsigned 8-bit integer
|
||||||
|
* b | int * | Boolean value (0 or 1 only)
|
||||||
|
* n | int16_t * | Signed (two's complement) 16-bit integer
|
||||||
|
* q | uint16_t * | Unsigned 16-bit integer
|
||||||
|
* i | int32_t * | Signed (two's complement) 32-bit integer
|
||||||
|
* u | uint32_t * | Unsigned 32-bit integer
|
||||||
|
* x | int64_t * | Signed (two's complement) 64-bit integer
|
||||||
|
* t | uint64_t * | Unsigned 64-bit integer
|
||||||
|
* s | char ** | NULL-terminated string
|
||||||
|
* d | - | (reserved)
|
||||||
|
* h | - | (reserved)
|
||||||
|
* o | - | (reserved)
|
||||||
|
* g | - | (reserved)
|
||||||
|
*
|
||||||
|
* The following additions to the D-Bus type system are also supported:-
|
||||||
|
*
|
||||||
|
* Char | C Type | Description
|
||||||
|
* -----| ------ | -----------
|
||||||
|
* B | const struct libipm_fsb * | Fixed-size block pointer
|
||||||
|
*
|
||||||
|
* For the 's' type, a pointer into the string in the input buffer is
|
||||||
|
* returned. This pointer will only be valid until the next call to
|
||||||
|
* libipm_msg_in_reset()
|
||||||
|
*
|
||||||
|
* For the 'B' type, pass in the address of an initialised descriptor
|
||||||
|
* containing the address and size of the object to copy the data
|
||||||
|
* to. The size in the descriptor must match the size of the object
|
||||||
|
* on-the-wire. Unlike 's', the data is copied out of the input buffer.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
enum libipm_status
|
||||||
|
libipm_msg_in_parse(struct trans *trans, const char *format, ...);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resets a message buffer ready to receive the next message
|
||||||
|
*
|
||||||
|
* If the LIBIPM_E_MSG_IN_ERASE_AFTER_USE flag is set for the transport,
|
||||||
|
* the entire buffer is erased, and the flag is cleared
|
||||||
|
*
|
||||||
|
* @param trans libipm transport
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
libipm_msg_in_reset(struct trans *trans);
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* LIBIPM_H */
|
34
libipm/libipm_facilities.h
Normal file
34
libipm/libipm_facilities.h
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (C) 2022 Matt Burt, 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/libipm_facilities.h
|
||||||
|
* @brief Facilities numbers for facilities built on top of libipm
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if !defined(LIBIPM__FACILITIES_H)
|
||||||
|
#define LIBIPM__FACILITIES_H
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Facilities layered on top of libipm (16 bits)
|
||||||
|
*/
|
||||||
|
enum libipm_facility
|
||||||
|
{
|
||||||
|
LIBIPM_FAC_SCP = 1, /**< SCP - Sesman Control Protocol */
|
||||||
|
LIBIPM_FAC_TEST = 65535 /**< Used for unit testing */
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* LIBIPM_FACILITIES_H */
|
67
libipm/libipm_private.h
Normal file
67
libipm/libipm_private.h
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (C) 2022 Matt Burt, 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/libipm_private.h
|
||||||
|
* @brief Inter-Process Messaging building and parsing - private declarations
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if !defined(LIBIPM_PRIVATE_H)
|
||||||
|
#define LIBIPM_PRIVATE_H
|
||||||
|
|
||||||
|
#include "libipm_facilities.h"
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Max size of a libipm message
|
||||||
|
*/
|
||||||
|
LIBIPM_MAX_MSG_SIZE = 8192,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Version of libipm wire protocol
|
||||||
|
*/
|
||||||
|
LIBIPM_VERSION = 2,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Size of libipm header
|
||||||
|
*/
|
||||||
|
HEADER_SIZE = 12
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Private class data stored in the trans 'extra_data' field
|
||||||
|
*/
|
||||||
|
struct libipm_priv
|
||||||
|
{
|
||||||
|
enum libipm_facility facility;
|
||||||
|
unsigned int flags;
|
||||||
|
const char *(*msgno_to_str)(unsigned short msgno);
|
||||||
|
unsigned short out_msgno;
|
||||||
|
unsigned short out_param_count;
|
||||||
|
unsigned short in_msgno;
|
||||||
|
unsigned short in_param_count;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Valid type-system characters
|
||||||
|
*
|
||||||
|
* Contains a list of all the types accepted by libipm_msg_out_append() and
|
||||||
|
* libipm_msg_in_parse()
|
||||||
|
*/
|
||||||
|
extern const char *libipm_valid_type_chars;
|
||||||
|
|
||||||
|
#endif /* LIBIPM__PRIVATE_H */
|
660
libipm/libipm_recv.c
Normal file
660
libipm/libipm_recv.c
Normal file
@ -0,0 +1,660 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (C) 2022 Matt Burt, 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/libipm.c
|
||||||
|
* @brief Inter-Process Messaging building and parsing definitions
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if defined(HAVE_CONFIG_H)
|
||||||
|
#include <config_ac.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
#include "libipm.h"
|
||||||
|
#include "libipm_private.h"
|
||||||
|
#include "libipm_facilities.h"
|
||||||
|
#include "trans.h"
|
||||||
|
#include "log.h"
|
||||||
|
#include "os_calls.h"
|
||||||
|
#include "string_calls.h"
|
||||||
|
|
||||||
|
/**************************************************************************//**
|
||||||
|
* Checks the message header in the input stream, and gets the size
|
||||||
|
*/
|
||||||
|
static enum libipm_status
|
||||||
|
validate_msg_header(struct trans *trans, int *size)
|
||||||
|
{
|
||||||
|
struct libipm_priv *priv = (struct libipm_priv *)trans->extra_data;
|
||||||
|
enum libipm_status rv = E_LI_BAD_HEADER;
|
||||||
|
|
||||||
|
int version;
|
||||||
|
int facility;
|
||||||
|
int reserved;
|
||||||
|
|
||||||
|
in_uint16_le(trans->in_s, version);
|
||||||
|
in_uint16_le(trans->in_s, *size);
|
||||||
|
in_uint16_le(trans->in_s, facility);
|
||||||
|
in_uint16_le(trans->in_s, priv->in_msgno);
|
||||||
|
in_uint32_le(trans->in_s, reserved);
|
||||||
|
|
||||||
|
if (version != LIBIPM_VERSION)
|
||||||
|
{
|
||||||
|
LOG(LOG_LEVEL_ERROR,
|
||||||
|
"Unexpected version number %d from IPM", version);
|
||||||
|
}
|
||||||
|
else if (*size < HEADER_SIZE || *size > LIBIPM_MAX_MSG_SIZE)
|
||||||
|
{
|
||||||
|
LOG(LOG_LEVEL_ERROR,
|
||||||
|
"Invalid message length %d from IPM", *size);
|
||||||
|
}
|
||||||
|
else if (facility != priv->facility)
|
||||||
|
{
|
||||||
|
LOG(LOG_LEVEL_ERROR,
|
||||||
|
"Invalid facility %d from IPM - expected %d",
|
||||||
|
facility, priv->facility);
|
||||||
|
}
|
||||||
|
else if (reserved != 0)
|
||||||
|
{
|
||||||
|
LOG(LOG_LEVEL_ERROR,
|
||||||
|
"Invalid reserved field %d from IPM", reserved);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rv = E_LI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
enum libipm_status
|
||||||
|
libipm_msg_in_check_available(struct trans *trans, int *available)
|
||||||
|
{
|
||||||
|
enum libipm_status rv = E_LI_SUCCESS;
|
||||||
|
|
||||||
|
*available = 0;
|
||||||
|
|
||||||
|
if (trans == NULL || trans->extra_data == NULL)
|
||||||
|
{
|
||||||
|
LOG_DEVEL(LOG_LEVEL_ERROR, "Failed devel check");
|
||||||
|
rv = E_LI_PROGRAM_ERROR;
|
||||||
|
}
|
||||||
|
else if (trans->status != TRANS_STATUS_UP)
|
||||||
|
{
|
||||||
|
rv = E_LI_PROGRAM_ERROR; /* Caller should have checked this */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int len = trans->in_s->end - trans->in_s->data; /* Data read so far */
|
||||||
|
|
||||||
|
if (len == trans->header_size)
|
||||||
|
{
|
||||||
|
if (trans->extra_flags == 0)
|
||||||
|
{
|
||||||
|
/* We've read the header so far - validate it */
|
||||||
|
int size;
|
||||||
|
rv = validate_msg_header(trans, &size);
|
||||||
|
if (rv == 0)
|
||||||
|
{
|
||||||
|
/* Header is OK */
|
||||||
|
trans->extra_flags = 1;
|
||||||
|
trans->header_size = size;
|
||||||
|
|
||||||
|
*available = (size == HEADER_SIZE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
*available = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
enum libipm_status
|
||||||
|
libipm_msg_in_wait_available(struct trans *trans)
|
||||||
|
{
|
||||||
|
tbus wobj[1];
|
||||||
|
int ocnt = 0;
|
||||||
|
enum libipm_status rv = E_LI_SUCCESS;
|
||||||
|
|
||||||
|
if (trans == NULL || trans->extra_data == NULL ||
|
||||||
|
trans->status != TRANS_STATUS_UP)
|
||||||
|
{
|
||||||
|
LOG_DEVEL(LOG_LEVEL_ERROR, "Failed devel check");
|
||||||
|
rv = E_LI_PROGRAM_ERROR;
|
||||||
|
}
|
||||||
|
else if (trans_get_wait_objs(trans, wobj, &ocnt) != 0)
|
||||||
|
{
|
||||||
|
LOG(LOG_LEVEL_ERROR, "Can't get wait object for libipm transport");
|
||||||
|
rv = E_LI_TRANSPORT_ERROR;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int gotmsg = 0;
|
||||||
|
/* Prevent trans_check_wait_objs() actioning any callcacks
|
||||||
|
* when the message is complete */
|
||||||
|
ttrans_data_in saved_trans_data_in = trans->trans_data_in;
|
||||||
|
trans->trans_data_in = NULL;
|
||||||
|
|
||||||
|
while (rv == E_LI_SUCCESS && !gotmsg)
|
||||||
|
{
|
||||||
|
if (g_obj_wait(wobj, ocnt, NULL, 0, -1) != 0)
|
||||||
|
{
|
||||||
|
LOG(LOG_LEVEL_ERROR, "Error waiting on libipm transport");
|
||||||
|
rv = E_LI_TRANSPORT_ERROR;
|
||||||
|
}
|
||||||
|
else if (trans_check_wait_objs(trans) != 0)
|
||||||
|
{
|
||||||
|
LOG(LOG_LEVEL_ERROR, "Error reading libipm transport");
|
||||||
|
rv = E_LI_TRANSPORT_ERROR;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* This call logs errors already */
|
||||||
|
rv = libipm_msg_in_check_available(trans, &gotmsg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Restore transport callback operation */
|
||||||
|
trans->trans_data_in = saved_trans_data_in;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
unsigned short
|
||||||
|
libipm_msg_in_start(struct trans *trans)
|
||||||
|
{
|
||||||
|
struct libipm_priv *priv = (struct libipm_priv *)trans->extra_data;
|
||||||
|
|
||||||
|
trans->in_s->p = trans->in_s->data + HEADER_SIZE;
|
||||||
|
return (priv == NULL) ? 0 : priv->in_msgno;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
char
|
||||||
|
libipm_msg_in_peek_type(struct trans *trans)
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
|
||||||
|
if (s_check_rem(trans->in_s, 1))
|
||||||
|
{
|
||||||
|
char c;
|
||||||
|
in_uint8_peek(trans->in_s, c);
|
||||||
|
if (g_strchr(libipm_valid_type_chars, c) != NULL)
|
||||||
|
{
|
||||||
|
result = c; /* Only return valid characters */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = '?';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************//**
|
||||||
|
* Log an input parsing error
|
||||||
|
*
|
||||||
|
* @param trans libipm transport
|
||||||
|
* @param format printf-like format descriptor
|
||||||
|
*/
|
||||||
|
printflike(2, 3) static void
|
||||||
|
log_parse_error(struct trans *trans, const char *format, ...)
|
||||||
|
{
|
||||||
|
struct libipm_priv *priv = (struct libipm_priv *)trans->extra_data;
|
||||||
|
const char *msgno_str = NULL;
|
||||||
|
char msgno_str_buff[32];
|
||||||
|
|
||||||
|
char buff[256];
|
||||||
|
unsigned int len;
|
||||||
|
|
||||||
|
/* Find a string for the message number */
|
||||||
|
if (priv->msgno_to_str != NULL)
|
||||||
|
{
|
||||||
|
msgno_str = priv->msgno_to_str(priv->in_msgno);
|
||||||
|
}
|
||||||
|
if (msgno_str == NULL)
|
||||||
|
{
|
||||||
|
g_snprintf(msgno_str_buff, sizeof(msgno_str_buff),
|
||||||
|
"[code #%d]", priv->in_msgno);
|
||||||
|
msgno_str = msgno_str_buff;
|
||||||
|
}
|
||||||
|
|
||||||
|
len = g_snprintf(buff, sizeof(buff),
|
||||||
|
"Error parsing ipm message for %s, parameter %d :",
|
||||||
|
msgno_str, priv->in_param_count);
|
||||||
|
if (len < sizeof(buff))
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
|
||||||
|
va_start(ap, format);
|
||||||
|
vsnprintf(&buff[len], sizeof(buff) - len, format, ap);
|
||||||
|
va_end(ap);
|
||||||
|
}
|
||||||
|
LOG(LOG_LEVEL_ERROR, "%s", buff);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Common format string for overflow reporting */
|
||||||
|
static const char *
|
||||||
|
not_enough_input_msg = "Input buffer overflow for '%c'";
|
||||||
|
|
||||||
|
/**************************************************************************//**
|
||||||
|
* Extract a bool from the input stream
|
||||||
|
*
|
||||||
|
* @param c Type letter which triggered the call
|
||||||
|
* @param trans libipm transport
|
||||||
|
* @param argptr Pointer to pointer to receive the value
|
||||||
|
* @return != 0 for error
|
||||||
|
*
|
||||||
|
* The value must be a 0 or 1 on-the-wire, or an error is returned.
|
||||||
|
*/
|
||||||
|
static enum libipm_status
|
||||||
|
extract_bool_type(char c, struct trans *trans, va_list argptr)
|
||||||
|
{
|
||||||
|
enum libipm_status rv = E_LI_SUCCESS;
|
||||||
|
struct stream *s = trans->in_s;
|
||||||
|
int b;
|
||||||
|
|
||||||
|
if (!s_check_rem(s, 1))
|
||||||
|
{
|
||||||
|
log_parse_error(trans, not_enough_input_msg, c);
|
||||||
|
rv = E_LI_BUFFER_OVERFLOW;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
in_uint8(s, b);
|
||||||
|
if (b < 0 || b > 1)
|
||||||
|
{
|
||||||
|
log_parse_error(trans, "Boolean has value other than 0/1");
|
||||||
|
rv = E_LI_BAD_VALUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int *tmp = va_arg(argptr, int *);
|
||||||
|
*tmp = b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************//**
|
||||||
|
* Extract an octet from the input stream
|
||||||
|
*
|
||||||
|
* @param c Type letter which triggered the call
|
||||||
|
* @param trans libipm transport
|
||||||
|
* @param argptr argptr to pointer to receive the value
|
||||||
|
* @return != 0 for error
|
||||||
|
*/
|
||||||
|
static enum libipm_status
|
||||||
|
extract_int8_type(char c, struct trans *trans, va_list argptr)
|
||||||
|
{
|
||||||
|
enum libipm_status rv = E_LI_SUCCESS;
|
||||||
|
struct stream *s = trans->in_s;
|
||||||
|
|
||||||
|
if (!s_check_rem(s, 1))
|
||||||
|
{
|
||||||
|
log_parse_error(trans, not_enough_input_msg, c);
|
||||||
|
rv = E_LI_BUFFER_OVERFLOW;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
unsigned char *tmp = va_arg(argptr, unsigned char *);
|
||||||
|
in_uint8(s, *tmp);
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************************************************************************//**
|
||||||
|
* Extract a 16-bit integer from the input stream
|
||||||
|
*
|
||||||
|
* @param c Type letter which triggered the call
|
||||||
|
* @param trans libipm transport
|
||||||
|
* @param argptr argptr to pointer to receive the value
|
||||||
|
* @return != 0 for error
|
||||||
|
*/
|
||||||
|
static enum libipm_status
|
||||||
|
extract_int16_type(char c, struct trans *trans, va_list argptr)
|
||||||
|
{
|
||||||
|
enum libipm_status rv = E_LI_SUCCESS;
|
||||||
|
struct stream *s = trans->in_s;
|
||||||
|
|
||||||
|
if (!s_check_rem(s, 2))
|
||||||
|
{
|
||||||
|
log_parse_error(trans, not_enough_input_msg, c);
|
||||||
|
rv = E_LI_BUFFER_OVERFLOW;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uint16_t *tmp = va_arg(argptr, uint16_t *);
|
||||||
|
/*
|
||||||
|
* C99 7.18.1.1 requires int16_t (if present) to be a two's
|
||||||
|
* complement representation, so this line is valid for both
|
||||||
|
* int16_t and uint16_t */
|
||||||
|
in_uint16_le(s, *tmp);
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************//**
|
||||||
|
* Extract a 32-bit integer from the input stream
|
||||||
|
*
|
||||||
|
* @param c Type letter which triggered the call
|
||||||
|
* @param trans libipm transport
|
||||||
|
* @param argptr argptr to pointer to receive the value
|
||||||
|
* @return != 0 for error
|
||||||
|
*/
|
||||||
|
static enum libipm_status
|
||||||
|
extract_int32_type(char c, struct trans *trans, va_list argptr)
|
||||||
|
{
|
||||||
|
enum libipm_status rv = E_LI_SUCCESS;
|
||||||
|
struct stream *s = trans->in_s;
|
||||||
|
|
||||||
|
if (!s_check_rem(s, 4))
|
||||||
|
{
|
||||||
|
log_parse_error(trans, not_enough_input_msg, c);
|
||||||
|
rv = E_LI_BUFFER_OVERFLOW;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uint32_t *tmp = va_arg(argptr, uint32_t *);
|
||||||
|
/*
|
||||||
|
* C99 7.18.1.1 requires int32_t (if present) to be a two's
|
||||||
|
* complement representation, so this line is valid for both
|
||||||
|
* int32_t and uint32_t */
|
||||||
|
in_uint32_le(s, *tmp);
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************//**
|
||||||
|
* Extract a 64-bit integer from the input stream
|
||||||
|
*
|
||||||
|
* @param c Type letter which triggered the call
|
||||||
|
* @param trans libipm transport
|
||||||
|
* @param argptr argptr to pointer to receive the value
|
||||||
|
* @return != 0 for error
|
||||||
|
*/
|
||||||
|
static enum libipm_status
|
||||||
|
extract_int64_type(char c, struct trans *trans, va_list argptr)
|
||||||
|
{
|
||||||
|
enum libipm_status rv = E_LI_SUCCESS;
|
||||||
|
struct stream *s = trans->in_s;
|
||||||
|
|
||||||
|
if (!s_check_rem(s, 8))
|
||||||
|
{
|
||||||
|
log_parse_error(trans, not_enough_input_msg, c);
|
||||||
|
rv = E_LI_BUFFER_OVERFLOW;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uint64_t *tmp = va_arg(argptr, uint64_t *);
|
||||||
|
/*
|
||||||
|
* C99 7.18.1.1 requires int64_t (if present) to be a two's
|
||||||
|
* complement representation, so this line is valid for both
|
||||||
|
* int64_t and uint64_t */
|
||||||
|
in_uint64_le(s, *tmp);
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************//**
|
||||||
|
* Extract a char * pointer from the input stream
|
||||||
|
*
|
||||||
|
* @param c Type letter which triggered the call
|
||||||
|
* @param trans libipm transport
|
||||||
|
* @param argptr argptr to pointer to receive the value
|
||||||
|
* @return != 0 for error
|
||||||
|
*/
|
||||||
|
static enum libipm_status
|
||||||
|
extract_char_ptr_type(char c, struct trans *trans, va_list argptr)
|
||||||
|
{
|
||||||
|
enum libipm_status rv = E_LI_SUCCESS;
|
||||||
|
struct stream *s = trans->in_s;
|
||||||
|
|
||||||
|
/* Look for a string terminator in the rest of the input stream */
|
||||||
|
char *termptr = g_strnchr(s->p, '\0', s->end - s->p);
|
||||||
|
|
||||||
|
if (termptr == NULL)
|
||||||
|
{
|
||||||
|
log_parse_error(trans, "Unterminated string value");
|
||||||
|
rv = E_LI_BAD_VALUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
char **tmp = va_arg(argptr, char **);
|
||||||
|
|
||||||
|
*tmp = s->p;
|
||||||
|
s->p = termptr + 1;
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************//**
|
||||||
|
* Extract a fixed size block from the input stream
|
||||||
|
*
|
||||||
|
* @param c Type letter which triggered the call
|
||||||
|
* @param trans libipm transport
|
||||||
|
* @param argptr argptr to pointer to block descriptor
|
||||||
|
* @return != 0 for error
|
||||||
|
*/
|
||||||
|
static enum libipm_status
|
||||||
|
extract_fsb_type(char c, struct trans *trans, va_list argptr)
|
||||||
|
{
|
||||||
|
enum libipm_status rv = E_LI_SUCCESS;
|
||||||
|
struct stream *s = trans->in_s;
|
||||||
|
const struct libipm_fsb *fsb = va_arg(argptr, const struct libipm_fsb *);
|
||||||
|
|
||||||
|
if (fsb == NULL || fsb->data == NULL)
|
||||||
|
{
|
||||||
|
log_parse_error(trans, "Malformed descriptor for '%c'", c);
|
||||||
|
rv = E_LI_PROGRAM_ERROR;
|
||||||
|
}
|
||||||
|
else if (!s_check_rem(s, 2))
|
||||||
|
{
|
||||||
|
log_parse_error(trans, not_enough_input_msg, c);
|
||||||
|
rv = E_LI_BUFFER_OVERFLOW;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
unsigned int len;
|
||||||
|
in_uint16_le(s, len);
|
||||||
|
|
||||||
|
if (len != fsb->datalen)
|
||||||
|
{
|
||||||
|
log_parse_error(trans, "Type '%c'. Expected %u bytes, but got %u",
|
||||||
|
c, fsb->datalen, len);
|
||||||
|
rv = E_LI_BAD_VALUE;
|
||||||
|
}
|
||||||
|
else if (!s_check_rem(s, len))
|
||||||
|
{
|
||||||
|
log_parse_error(trans, not_enough_input_msg, c);
|
||||||
|
rv = E_LI_BUFFER_OVERFLOW;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
in_uint8a(s, fsb->data, len);
|
||||||
|
rv = E_LI_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************//**
|
||||||
|
* Local function to pull data from the input stream
|
||||||
|
*
|
||||||
|
* @param trans libipm transport
|
||||||
|
* @param format type-system compatible string
|
||||||
|
* @param argptr Pointers to variables to receive extracted data
|
||||||
|
* @pre - trans->priv has been checked to be non-NULL
|
||||||
|
* @return != 0 for error
|
||||||
|
*/
|
||||||
|
static enum libipm_status
|
||||||
|
libipm_msg_in_parsev(struct trans *trans, const char *format, va_list argptr)
|
||||||
|
{
|
||||||
|
enum libipm_status rv = E_LI_SUCCESS;
|
||||||
|
struct stream *s = trans->in_s;
|
||||||
|
struct libipm_priv *priv = (struct libipm_priv *)trans->extra_data;
|
||||||
|
const char *cp;
|
||||||
|
|
||||||
|
if (format != NULL)
|
||||||
|
{
|
||||||
|
for (cp = format; rv == 0 && *cp != '\0' ; ++cp)
|
||||||
|
{
|
||||||
|
char c = *cp;
|
||||||
|
char actual_c;
|
||||||
|
++priv->in_param_count; /* Count the parameter */
|
||||||
|
|
||||||
|
/* Check the type of the input is supported */
|
||||||
|
if (g_strchr(libipm_valid_type_chars, c) == NULL)
|
||||||
|
{
|
||||||
|
log_parse_error(trans,
|
||||||
|
"Type code '%c' is not supported", c);
|
||||||
|
rv = E_LI_UNSUPPORTED_TYPE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check the type of the input matches the stream */
|
||||||
|
if (!s_check_rem(s, 1))
|
||||||
|
{
|
||||||
|
log_parse_error(trans, not_enough_input_msg, c);
|
||||||
|
rv = E_LI_BUFFER_OVERFLOW;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
in_uint8(s, actual_c);
|
||||||
|
if (c != actual_c)
|
||||||
|
{
|
||||||
|
log_parse_error(trans, "Expected '%c', got '%c'", c, actual_c);
|
||||||
|
rv = E_LI_UNEXPECTED_TYPE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (c)
|
||||||
|
{
|
||||||
|
case 'y':
|
||||||
|
rv = extract_int8_type(c, trans, argptr);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'b':
|
||||||
|
rv = extract_bool_type(c, trans, argptr);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'n':
|
||||||
|
case 'q':
|
||||||
|
rv = extract_int16_type(c, trans, argptr);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'i':
|
||||||
|
case 'u':
|
||||||
|
rv = extract_int32_type(c, trans, argptr);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'x':
|
||||||
|
case 't':
|
||||||
|
rv = extract_int64_type(c, trans, argptr);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 's':
|
||||||
|
rv = extract_char_ptr_type(c, trans, argptr);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'B':
|
||||||
|
rv = extract_fsb_type(c, trans, argptr);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
log_parse_error(trans,
|
||||||
|
"Reserved type code '%c' "
|
||||||
|
"is unimplemented", c);
|
||||||
|
rv = E_LI_UNIMPLEMENTED_TYPE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
enum libipm_status
|
||||||
|
libipm_msg_in_parse(struct trans *trans, const char *format, ...)
|
||||||
|
{
|
||||||
|
enum libipm_status rv;
|
||||||
|
struct libipm_priv *priv = (struct libipm_priv *)trans->extra_data;
|
||||||
|
if (priv == NULL)
|
||||||
|
{
|
||||||
|
LOG_DEVEL(LOG_LEVEL_ERROR, "uninitialised transport");
|
||||||
|
rv = E_LI_PROGRAM_ERROR;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
va_list argptr;
|
||||||
|
|
||||||
|
va_start(argptr, format);
|
||||||
|
rv = libipm_msg_in_parsev(trans, format, argptr);
|
||||||
|
va_end(argptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
void
|
||||||
|
libipm_msg_in_reset(struct trans *trans)
|
||||||
|
{
|
||||||
|
struct libipm_priv *priv = (struct libipm_priv *)trans->extra_data;
|
||||||
|
|
||||||
|
if (priv == NULL)
|
||||||
|
{
|
||||||
|
LOG_DEVEL(LOG_LEVEL_ERROR, "uninitialised transport");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ((priv->flags & LIBIPM_E_MSG_IN_ERASE_AFTER_USE) != 0)
|
||||||
|
{
|
||||||
|
struct stream *s = trans->in_s;
|
||||||
|
g_memset(s->data, '\0', s->end - s->data);
|
||||||
|
priv->flags &= ~LIBIPM_E_MSG_IN_ERASE_AFTER_USE;
|
||||||
|
}
|
||||||
|
priv->in_msgno = 0;
|
||||||
|
priv->in_param_count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
trans->extra_flags = 0;
|
||||||
|
trans->header_size = HEADER_SIZE;
|
||||||
|
trans->no_stream_init_on_data_in = 1;
|
||||||
|
init_stream(trans->in_s, LIBIPM_MAX_MSG_SIZE);
|
||||||
|
}
|
570
libipm/libipm_send.c
Normal file
570
libipm/libipm_send.c
Normal file
@ -0,0 +1,570 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (C) 2022 Matt Burt, 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/libipm.c
|
||||||
|
* @brief Inter-Process Messaging building and parsing definitions
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if defined(HAVE_CONFIG_H)
|
||||||
|
#include <config_ac.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
#include "libipm.h"
|
||||||
|
#include "libipm_private.h"
|
||||||
|
#include "libipm_facilities.h"
|
||||||
|
#include "trans.h"
|
||||||
|
#include "log.h"
|
||||||
|
#include "os_calls.h"
|
||||||
|
#include "string_calls.h"
|
||||||
|
|
||||||
|
/**************************************************************************//**
|
||||||
|
* Log an output appending error
|
||||||
|
*
|
||||||
|
* @param trans libipm transport
|
||||||
|
* @param format printf-like format descriptor
|
||||||
|
*/
|
||||||
|
printflike(2, 3) static void
|
||||||
|
log_append_error(struct trans *trans, const char *format, ...)
|
||||||
|
{
|
||||||
|
struct libipm_priv *priv = (struct libipm_priv *)trans->extra_data;
|
||||||
|
const char *msgno_str = NULL;
|
||||||
|
char msgno_str_buff[32];
|
||||||
|
|
||||||
|
char buff[256];
|
||||||
|
unsigned int len;
|
||||||
|
|
||||||
|
/* Find a string for the message number */
|
||||||
|
if (priv->msgno_to_str != NULL)
|
||||||
|
{
|
||||||
|
msgno_str = priv->msgno_to_str(priv->out_msgno);
|
||||||
|
}
|
||||||
|
if (msgno_str == NULL)
|
||||||
|
{
|
||||||
|
g_snprintf(msgno_str_buff, sizeof(msgno_str_buff),
|
||||||
|
"[code #%d]", priv->out_msgno);
|
||||||
|
msgno_str = msgno_str_buff;
|
||||||
|
}
|
||||||
|
|
||||||
|
len = g_snprintf(buff, sizeof(buff),
|
||||||
|
"Error creating ipm message for %s, parameter %d :",
|
||||||
|
msgno_str, priv->out_param_count);
|
||||||
|
if (len < sizeof(buff))
|
||||||
|
{
|
||||||
|
va_list ap;
|
||||||
|
|
||||||
|
va_start(ap, format);
|
||||||
|
vsnprintf(&buff[len], sizeof(buff) - len, format, ap);
|
||||||
|
va_end(ap);
|
||||||
|
}
|
||||||
|
LOG(LOG_LEVEL_ERROR, "%s", buff);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Common format string for overflow reporting */
|
||||||
|
static const char *
|
||||||
|
not_enough_output_msg = "Not enough space in output buffer for '%c'";
|
||||||
|
/* Common format string for bad value reporting */
|
||||||
|
static const char *
|
||||||
|
bad_value_msg = "Type '%c' has unsupported value '%d'";
|
||||||
|
|
||||||
|
/**************************************************************************//**
|
||||||
|
* Add a bool to the output stream
|
||||||
|
*
|
||||||
|
* @param c Type letter which triggered the call
|
||||||
|
* @param trans libipm transport
|
||||||
|
* @param argptr Pointer to value in argument stack (promoted to int)
|
||||||
|
* @return != 0 for error
|
||||||
|
*
|
||||||
|
* The boolean value must be a 0 or a 1.
|
||||||
|
*/
|
||||||
|
static enum libipm_status
|
||||||
|
append_bool_type(char c, va_list argptr, struct trans *trans)
|
||||||
|
{
|
||||||
|
enum libipm_status rv = E_LI_SUCCESS;
|
||||||
|
struct stream *s = trans->out_s;
|
||||||
|
if (!s_check_rem_out(s, 1 + 1))
|
||||||
|
{
|
||||||
|
log_append_error(trans, not_enough_output_msg, c);
|
||||||
|
rv = E_LI_BUFFER_OVERFLOW;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int tmp = va_arg(argptr, int);
|
||||||
|
if (tmp < 0 || tmp > 1)
|
||||||
|
{
|
||||||
|
log_append_error(trans, bad_value_msg, c, tmp);
|
||||||
|
rv = E_LI_BAD_VALUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
out_uint8(s, c);
|
||||||
|
out_uint8(s, tmp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************//**
|
||||||
|
* Add an octet to the output stream
|
||||||
|
*
|
||||||
|
* @param c Type letter which triggered the call
|
||||||
|
* @param trans libipm transport
|
||||||
|
* @param argptr Pointer to value in argument stack (promoted to int)
|
||||||
|
* @return != 0 for error
|
||||||
|
*/
|
||||||
|
static enum libipm_status
|
||||||
|
append_int8_type(char c, va_list argptr, struct trans *trans)
|
||||||
|
{
|
||||||
|
enum libipm_status rv = E_LI_SUCCESS;
|
||||||
|
struct stream *s = trans->out_s;
|
||||||
|
if (!s_check_rem_out(s, 1 + 1))
|
||||||
|
{
|
||||||
|
log_append_error(trans, not_enough_output_msg, c);
|
||||||
|
rv = E_LI_BUFFER_OVERFLOW;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int tmp = va_arg(argptr, int);
|
||||||
|
if (tmp < 0 || tmp > 255)
|
||||||
|
{
|
||||||
|
log_append_error(trans, bad_value_msg, c, tmp);
|
||||||
|
rv = E_LI_BAD_VALUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
out_uint8(s, c);
|
||||||
|
out_uint8(s, tmp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************//**
|
||||||
|
* Add an 16-bit integer to the output stream
|
||||||
|
*
|
||||||
|
* @param c Type letter which triggered the call
|
||||||
|
* @param trans libipm transport
|
||||||
|
* @param argptr Pointer to value in argument stack (promoted to int)
|
||||||
|
* @return != 0 for error
|
||||||
|
*/
|
||||||
|
static enum libipm_status
|
||||||
|
append_int16_type(char c, va_list argptr, struct trans *trans)
|
||||||
|
{
|
||||||
|
enum libipm_status rv = E_LI_SUCCESS;
|
||||||
|
struct stream *s = trans->out_s;
|
||||||
|
if (!s_check_rem_out(s, 1 + 2))
|
||||||
|
{
|
||||||
|
log_append_error(trans, not_enough_output_msg, c);
|
||||||
|
rv = E_LI_BUFFER_OVERFLOW;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int tmp = va_arg(argptr, int);
|
||||||
|
if ((c == 'n' && (tmp < -0x8000 || tmp > 0x7fff)) ||
|
||||||
|
(c == 'q' && (tmp < 0 || tmp > 0xffff)))
|
||||||
|
{
|
||||||
|
log_append_error(trans, bad_value_msg, c, tmp);
|
||||||
|
rv = E_LI_BAD_VALUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
out_uint8(s, c);
|
||||||
|
out_uint16_le(s, tmp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************//**
|
||||||
|
* Add a 32-bit integer to the output stream
|
||||||
|
*
|
||||||
|
* @param c Type letter which triggered the call
|
||||||
|
* @param trans libipm transport
|
||||||
|
* @param argptr Pointer to value in argument stack
|
||||||
|
* @return != 0 for error
|
||||||
|
*/
|
||||||
|
static enum libipm_status
|
||||||
|
append_int32_type(char c, va_list argptr, struct trans *trans)
|
||||||
|
{
|
||||||
|
enum libipm_status rv = E_LI_SUCCESS;
|
||||||
|
struct stream *s = trans->out_s;
|
||||||
|
if (!s_check_rem_out(s, 1 + 4))
|
||||||
|
{
|
||||||
|
log_append_error(trans, not_enough_output_msg, c);
|
||||||
|
rv = E_LI_BUFFER_OVERFLOW;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* If int is bigger than 4 bytes, the argument will be
|
||||||
|
* promoted to 'int' rather than 'int32_t'/'uint32_t',
|
||||||
|
* and we will need to check the specified value is in range.
|
||||||
|
*/
|
||||||
|
#if SIZEOF_INT > 4
|
||||||
|
int tmp = va_arg(argptr, int);
|
||||||
|
if ((c == 'i' && (tmp < -0x80000000 || tmp > 0x7fffffff)) ||
|
||||||
|
(c == 'u' && (tmp < 0 || tmp > 0xffffffff)))
|
||||||
|
{
|
||||||
|
log_append_error(trans, bad_value_msg, c, tmp);
|
||||||
|
rv = E_LI_BAD_VALUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
out_uint8(s, c);
|
||||||
|
out_uint32_le(s, tmp);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
uint32_t tmp = va_arg(argptr, uint32_t);
|
||||||
|
out_uint8(s, c);
|
||||||
|
out_uint32_le(s, tmp);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************//**
|
||||||
|
* Add a 64-bit integer to the output stream
|
||||||
|
*
|
||||||
|
* @param c Type letter which triggered the call
|
||||||
|
* @param trans libipm transport
|
||||||
|
* @param argptr Pointer to value in argument stack
|
||||||
|
* @return != 0 for error
|
||||||
|
*/
|
||||||
|
static enum libipm_status
|
||||||
|
append_int64_type(char c, va_list argptr, struct trans *trans)
|
||||||
|
{
|
||||||
|
enum libipm_status rv = E_LI_SUCCESS;
|
||||||
|
struct stream *s = trans->out_s;
|
||||||
|
if (!s_check_rem_out(s, 1 + 8))
|
||||||
|
{
|
||||||
|
log_append_error(trans, not_enough_output_msg, c);
|
||||||
|
rv = E_LI_BUFFER_OVERFLOW;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uint64_t tmp = va_arg(argptr, uint64_t);
|
||||||
|
out_uint8(s, c);
|
||||||
|
out_uint64_le(s, tmp);
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************//**
|
||||||
|
* Add a terminated string to the output stream
|
||||||
|
*
|
||||||
|
* @param c Type letter which triggered the call
|
||||||
|
* @param trans libipm transport
|
||||||
|
* @param argptr Pointer to value in argument stack (promoted to int)
|
||||||
|
* @return != 0 for error
|
||||||
|
*
|
||||||
|
* NULL pointers are not allowed for the string.
|
||||||
|
*/
|
||||||
|
static enum libipm_status
|
||||||
|
append_char_ptr_type(char c, va_list argptr, struct trans *trans)
|
||||||
|
{
|
||||||
|
enum libipm_status rv = E_LI_SUCCESS;
|
||||||
|
struct stream *s = trans->out_s;
|
||||||
|
const char *str = va_arg(argptr, const char *);
|
||||||
|
if (str == NULL)
|
||||||
|
{
|
||||||
|
log_append_error(trans, "String cannot be NULL");
|
||||||
|
rv = E_LI_PROGRAM_ERROR;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
unsigned int len = g_strlen(str);
|
||||||
|
|
||||||
|
if ((len > (LIBIPM_MAX_MSG_SIZE - HEADER_SIZE - 1)) ||
|
||||||
|
(!s_check_rem_out(s, 1 + 1 + len)))
|
||||||
|
{
|
||||||
|
log_append_error(trans,
|
||||||
|
"Not enough space in output buffer for "
|
||||||
|
"'%c'[len=%u]", c, len);
|
||||||
|
rv = E_LI_BUFFER_OVERFLOW;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
out_uint8(s, c);
|
||||||
|
out_uint8p(s, str, len + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************//**
|
||||||
|
* Append a fixed size block to the output stream
|
||||||
|
*
|
||||||
|
* @param c Type letter which triggered the call
|
||||||
|
* @param trans libipm transport
|
||||||
|
* @param argptr argptr to pointer to block descriptor
|
||||||
|
* @return != 0 for error
|
||||||
|
*/
|
||||||
|
static enum libipm_status
|
||||||
|
append_fsb_type(char c, va_list argptr, struct trans *trans)
|
||||||
|
{
|
||||||
|
enum libipm_status rv = E_LI_SUCCESS;
|
||||||
|
struct stream *s = trans->out_s;
|
||||||
|
const struct libipm_fsb *fsb = va_arg(argptr, const struct libipm_fsb *);
|
||||||
|
if (fsb == NULL || fsb->data == NULL)
|
||||||
|
{
|
||||||
|
log_append_error(trans, "Malformed descriptor for '%c'", c);
|
||||||
|
rv = E_LI_PROGRAM_ERROR;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
unsigned int len = fsb->datalen;
|
||||||
|
|
||||||
|
if ((len > (LIBIPM_MAX_MSG_SIZE - HEADER_SIZE - 2)) ||
|
||||||
|
(!s_check_rem_out(s, 1 + 2 + len)))
|
||||||
|
{
|
||||||
|
log_append_error(trans, "Not enough space in output buffer"
|
||||||
|
" for '%c'[len=%u]", c, len);
|
||||||
|
rv = E_LI_BUFFER_OVERFLOW;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
out_uint8(s, c);
|
||||||
|
out_uint16_le(s, len);
|
||||||
|
out_uint8a(s, fsb->data, len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************//**
|
||||||
|
* Local function to append data to the output stream
|
||||||
|
*
|
||||||
|
* @param trans libipm transport
|
||||||
|
* @param format type-system compatible string
|
||||||
|
* @param argptr Variables containing data to append
|
||||||
|
* @pre - trans->priv has been checked to be non-NULL
|
||||||
|
* @return != 0 for error
|
||||||
|
*/
|
||||||
|
static enum libipm_status
|
||||||
|
libipm_msg_out_appendv(struct trans *trans, const char *format, va_list argptr)
|
||||||
|
{
|
||||||
|
enum libipm_status rv = E_LI_SUCCESS;
|
||||||
|
struct libipm_priv *priv = (struct libipm_priv *)trans->extra_data;
|
||||||
|
const char *cp;
|
||||||
|
|
||||||
|
if (format != NULL)
|
||||||
|
{
|
||||||
|
for (cp = format; rv == 0 && *cp != '\0' ; ++cp)
|
||||||
|
{
|
||||||
|
char c = *cp;
|
||||||
|
++priv->out_param_count; /* Count the parameter */
|
||||||
|
if (g_strchr(libipm_valid_type_chars, c) == NULL)
|
||||||
|
{
|
||||||
|
log_append_error(trans,
|
||||||
|
"Type code '%c' is not supported", c);
|
||||||
|
rv = E_LI_UNSUPPORTED_TYPE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (c)
|
||||||
|
{
|
||||||
|
case 'y':
|
||||||
|
rv = append_int8_type(c, argptr, trans);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'b':
|
||||||
|
rv = append_bool_type(c, argptr, trans);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'n':
|
||||||
|
case 'q':
|
||||||
|
rv = append_int16_type(c, argptr, trans);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'i':
|
||||||
|
case 'u':
|
||||||
|
rv = append_int32_type(c, argptr, trans);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'x':
|
||||||
|
case 't':
|
||||||
|
rv = append_int64_type(c, argptr, trans);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 's':
|
||||||
|
rv = append_char_ptr_type(c, argptr, trans);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'B':
|
||||||
|
rv = append_fsb_type(c, argptr, trans);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
log_append_error(trans,
|
||||||
|
"Reserved type code '%c' "
|
||||||
|
"is unimplemented", c);
|
||||||
|
rv = E_LI_UNIMPLEMENTED_TYPE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************//**
|
||||||
|
* Prepare the tranport to build an output message
|
||||||
|
* @param trans libipm trans
|
||||||
|
* @param msgno Number of message
|
||||||
|
* @return != 0 for error
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
init_output_buffer(struct trans *trans, unsigned short msgno)
|
||||||
|
{
|
||||||
|
struct stream *s = trans->out_s;
|
||||||
|
struct libipm_priv *priv = (struct libipm_priv *)trans->extra_data;
|
||||||
|
|
||||||
|
init_stream(s, LIBIPM_MAX_MSG_SIZE);
|
||||||
|
|
||||||
|
/* Leave space for header */
|
||||||
|
s_push_layer(s, iso_hdr, HEADER_SIZE);
|
||||||
|
|
||||||
|
priv->out_msgno = msgno;
|
||||||
|
priv->out_param_count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
enum libipm_status
|
||||||
|
libipm_msg_out_init(struct trans *trans, unsigned short msgno,
|
||||||
|
const char *format, ...)
|
||||||
|
{
|
||||||
|
enum libipm_status rv;
|
||||||
|
struct libipm_priv *priv = (struct libipm_priv *)trans->extra_data;
|
||||||
|
if (priv == NULL)
|
||||||
|
{
|
||||||
|
LOG_DEVEL(LOG_LEVEL_ERROR, "uninitialised transport");
|
||||||
|
rv = E_LI_PROGRAM_ERROR;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
va_list argptr;
|
||||||
|
|
||||||
|
init_output_buffer(trans, msgno);
|
||||||
|
|
||||||
|
va_start(argptr, format);
|
||||||
|
rv = libipm_msg_out_appendv(trans, format, argptr);
|
||||||
|
va_end(argptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
enum libipm_status
|
||||||
|
libipm_msg_out_append(struct trans *trans, const char *format, ...)
|
||||||
|
{
|
||||||
|
enum libipm_status rv;
|
||||||
|
struct libipm_priv *priv = (struct libipm_priv *)trans->extra_data;
|
||||||
|
if (priv == NULL)
|
||||||
|
{
|
||||||
|
LOG_DEVEL(LOG_LEVEL_ERROR, "uninitialised transport");
|
||||||
|
rv = E_LI_PROGRAM_ERROR;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
va_list argptr;
|
||||||
|
|
||||||
|
va_start(argptr, format);
|
||||||
|
rv = libipm_msg_out_appendv(trans, format, argptr);
|
||||||
|
va_end(argptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
void
|
||||||
|
libipm_msg_out_mark_end(struct trans *trans)
|
||||||
|
{
|
||||||
|
struct libipm_priv *priv = (struct libipm_priv *)trans->extra_data;
|
||||||
|
if (priv == NULL)
|
||||||
|
{
|
||||||
|
LOG_DEVEL(LOG_LEVEL_ERROR, "uninitialised transport");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
struct stream *s = trans->out_s;
|
||||||
|
s_mark_end(s);
|
||||||
|
s_pop_layer(s, iso_hdr);
|
||||||
|
|
||||||
|
/* Write the message header */
|
||||||
|
out_uint16_le(s, LIBIPM_VERSION);
|
||||||
|
out_uint16_le(s, s->end - s->data);
|
||||||
|
out_uint16_le(s, priv->facility);
|
||||||
|
out_uint16_le(s, priv->out_msgno);
|
||||||
|
out_uint32_le(s, 0); /* Reserved */
|
||||||
|
|
||||||
|
/* Move the output pointer back to the end so another
|
||||||
|
* append works, and so libipm_msg_out_erase() knows
|
||||||
|
* exactly what to do */
|
||||||
|
s->p = s->end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
enum libipm_status
|
||||||
|
libipm_msg_out_simple_send(struct trans *trans, unsigned short msgno,
|
||||||
|
const char *format, ...)
|
||||||
|
{
|
||||||
|
enum libipm_status rv;
|
||||||
|
struct libipm_priv *priv = (struct libipm_priv *)trans->extra_data;
|
||||||
|
if (priv == NULL)
|
||||||
|
{
|
||||||
|
LOG_DEVEL(LOG_LEVEL_ERROR, "uninitialised transport");
|
||||||
|
rv = E_LI_PROGRAM_ERROR;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
va_list argptr;
|
||||||
|
|
||||||
|
va_start(argptr, format);
|
||||||
|
init_output_buffer(trans, msgno);
|
||||||
|
|
||||||
|
rv = libipm_msg_out_appendv(trans, format, argptr);
|
||||||
|
if (rv == E_LI_SUCCESS)
|
||||||
|
{
|
||||||
|
libipm_msg_out_mark_end(trans);
|
||||||
|
if (trans_force_write(trans) != 0)
|
||||||
|
{
|
||||||
|
rv = E_LI_TRANSPORT_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
va_end(argptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
void
|
||||||
|
libipm_msg_out_erase(struct trans *trans)
|
||||||
|
{
|
||||||
|
struct stream *s = trans->out_s;
|
||||||
|
if (s->size > 0 && s->data != 0)
|
||||||
|
{
|
||||||
|
g_memset(s->data, '\0', s->p - s->data);
|
||||||
|
}
|
||||||
|
}
|
505
libipm/scp.c
Normal file
505
libipm/scp.c
Normal file
@ -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;
|
||||||
|
}
|
384
libipm/scp.h
Normal file
384
libipm/scp.h
Normal file
@ -0,0 +1,384 @@
|
|||||||
|
/**
|
||||||
|
* 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.h
|
||||||
|
* @brief scp declarations
|
||||||
|
* @author Simone Fedele/ Matt Burt
|
||||||
|
*
|
||||||
|
* Functions in this file use the following naming conventions:-
|
||||||
|
*
|
||||||
|
* E_SCP_<msg>_REQUEST is sent by scp_send_<msg>_request()
|
||||||
|
* E_SCP_<msg>_REQUEST is parsed by scp_get_<msg>_request()
|
||||||
|
* E_SCP_<msg>_RESPONSE is sent by scp_send_<msg>_response()
|
||||||
|
* E_SCP_<msg>_RESPONSE is parsed by scp_get_<msg>_response()
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SCP_H
|
||||||
|
#define SCP_H
|
||||||
|
|
||||||
|
#include "arch.h"
|
||||||
|
|
||||||
|
struct guid;
|
||||||
|
struct trans;
|
||||||
|
|
||||||
|
#include "scp_application_types.h"
|
||||||
|
|
||||||
|
/* Message codes */
|
||||||
|
enum scp_msg_code
|
||||||
|
{
|
||||||
|
E_SCP_GATEWAY_REQUEST = 1,
|
||||||
|
E_SCP_GATEWAY_RESPONSE,
|
||||||
|
E_SCP_CREATE_SESSION_REQUEST,
|
||||||
|
E_SCP_CREATE_SESSION_RESPONSE,
|
||||||
|
E_SCP_LIST_SESSIONS_REQUEST,
|
||||||
|
E_SCP_LIST_SESSIONS_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 *
|
||||||
|
scp_msgno_to_str(enum scp_msg_code n, char *buff, unsigned int buff_size);
|
||||||
|
|
||||||
|
/* Connection management facilities */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Connect to an SCP server
|
||||||
|
*
|
||||||
|
* @param host Host providing SCP service
|
||||||
|
* @param port TCP port for SCP service
|
||||||
|
* @param term_func Function to poll during connection for program
|
||||||
|
* termination, or NULL for none.
|
||||||
|
* @return Initialised SCP transport
|
||||||
|
*
|
||||||
|
* The returned tranport has the is_term member set to term_func.
|
||||||
|
*/
|
||||||
|
struct trans *
|
||||||
|
scp_connect(const char *host, const char *port,
|
||||||
|
int (*term_func)(void));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a standard trans connected to an SCP endpoint to an SCP transport
|
||||||
|
*
|
||||||
|
* @param trans connected endpoint
|
||||||
|
* @return != 0 for error
|
||||||
|
*
|
||||||
|
* The returned tranport has the is_term member set to term_func.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
scp_init_trans(struct trans *trans);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks an SCP transport to see if a complete message is
|
||||||
|
* available for parsing
|
||||||
|
*
|
||||||
|
* @param trans SCP transport
|
||||||
|
* @param[out] available != 0 if a complete message is available
|
||||||
|
* @return != 0 for error
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
scp_msg_in_check_available(struct trans *trans, int *available);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Waits on a single transport for an SCP 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
|
||||||
|
* scp_msg_in_check_available()
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
scp_msg_in_wait_available(struct trans *trans);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Start parsing an SCP message
|
||||||
|
*
|
||||||
|
* @param trans SCP transport
|
||||||
|
* @return message in the buffer
|
||||||
|
*
|
||||||
|
* The results of calling this routine before scp_msg_in_check_available()
|
||||||
|
* states a message is available are undefined.
|
||||||
|
*
|
||||||
|
* Calling this function rests the message parsing pointer to the start
|
||||||
|
* of the message
|
||||||
|
*/
|
||||||
|
enum scp_msg_code
|
||||||
|
scp_msg_in_start(struct trans *trans);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resets an SCP message buffer ready to receive the next message
|
||||||
|
*
|
||||||
|
* @param trans libipm transport
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
scp_msg_in_reset(struct trans *trans);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send an E_SCP_GATEWAY_REQUEST (SCP client)
|
||||||
|
*
|
||||||
|
* @param trans SCP transport
|
||||||
|
* @param username Username
|
||||||
|
* @param password Password
|
||||||
|
* @return != 0 for error
|
||||||
|
*
|
||||||
|
* Server replies with E_SCP_GATEWAY_RESPONSE
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
scp_send_gateway_request(struct trans *trans,
|
||||||
|
const char *username,
|
||||||
|
const char *password);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse an incoming E_SCP_GATEWAY_REQUEST message (SCP server)
|
||||||
|
*
|
||||||
|
* @param trans SCP transport
|
||||||
|
* @param[out] username Username
|
||||||
|
* @param[out] password Password
|
||||||
|
* @return != 0 for error
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
scp_get_gateway_request(struct trans *trans,
|
||||||
|
const char **username,
|
||||||
|
const char **password);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send an E_SCP_GATEWAY_RESPONSE (SCP server)
|
||||||
|
*
|
||||||
|
* @param trans SCP transport
|
||||||
|
* @param auth_result 0 for success, PAM error code otherwise
|
||||||
|
* @return != 0 for error
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
scp_send_gateway_response(struct trans *trans,
|
||||||
|
int auth_result);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses an incoming E_SCP_GATEWAY_RESPONSE (SCP client)
|
||||||
|
*
|
||||||
|
* @param trans SCP transport
|
||||||
|
* @param[out] auth_result 0 for success, PAM error code otherwise
|
||||||
|
* @return != 0 for error
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
scp_get_gateway_response(struct trans *trans,
|
||||||
|
int *auth_result);
|
||||||
|
|
||||||
|
/* Session messages */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send an E_SCP_CREATE_SESSION_REQUEST (SCP client)
|
||||||
|
*
|
||||||
|
* @param trans SCP transport
|
||||||
|
* @param username Username of session to create or re-connect to
|
||||||
|
* @param password Password for user
|
||||||
|
* @param type Session type
|
||||||
|
* @param width Initial session width
|
||||||
|
* @param height Initial session height
|
||||||
|
* @param bpp Session bits-per-pixel (ignored for Xorg sessions)
|
||||||
|
* @param shell User program to run. May be ""
|
||||||
|
* @param directory Directory to run the program in. May be ""
|
||||||
|
* @param connection_description Description of the connection
|
||||||
|
* @return != 0 for error
|
||||||
|
*
|
||||||
|
* Server replies with E_SCP_CREATE_SESSION_RESPONSE
|
||||||
|
*/
|
||||||
|
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);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse an incoming E_SCP_CREATE_SESSION_REQUEST (SCP server)
|
||||||
|
*
|
||||||
|
* @param trans SCP transport
|
||||||
|
* @param[out] username Username of session to create or re-connect to
|
||||||
|
* @param[out] password Password for user
|
||||||
|
* @param[out] type Session type
|
||||||
|
* @param[out] width Initial session width
|
||||||
|
* @param[out] height Initial session height
|
||||||
|
* @param[out] bpp Session bits-per-pixel (ignored for Xorg sessions)
|
||||||
|
* @param[out] shell User program to run. May be ""
|
||||||
|
* @param[out] directory Directory to run the program in. May be ""
|
||||||
|
* @param[out] connection_description Description of the connection
|
||||||
|
* @return != 0 for error
|
||||||
|
*
|
||||||
|
* Returned string pointers are valid until scp_msg_in_reset() is
|
||||||
|
* called for the transport
|
||||||
|
*/
|
||||||
|
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);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send an E_SCP_CREATE_SESSION_RESPONSE (SCP server)
|
||||||
|
*
|
||||||
|
* @param trans SCP transport
|
||||||
|
* @param auth_result 0 for success, PAM error code otherwise
|
||||||
|
* @param display Should be zero if authentication failed.
|
||||||
|
* @param guid Guid for session. Should be all zeros if authentication failed
|
||||||
|
*
|
||||||
|
* @return != 0 for error
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
scp_send_create_session_response(struct trans *trans,
|
||||||
|
int auth_result,
|
||||||
|
int display,
|
||||||
|
const struct guid *guid);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse an incoming E_SCP_CREATE_SESSION_RESPONSE (SCP client)
|
||||||
|
*
|
||||||
|
* @param trans SCP transport
|
||||||
|
* @param[out] auth_result 0 for success, PAM error code otherwise
|
||||||
|
* @param[out] display Should be zero if authentication failed.
|
||||||
|
* @param[out] guid Guid for session. Should be all zeros if authentication
|
||||||
|
* failed
|
||||||
|
*
|
||||||
|
* @return != 0 for error
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
scp_get_create_session_response(struct trans *trans,
|
||||||
|
int *auth_result,
|
||||||
|
int *display,
|
||||||
|
struct guid *guid);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Status of an E_SCP_LIST_SESSIONS_RESPONSE message
|
||||||
|
*/
|
||||||
|
enum scp_list_sessions_status
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* This message contains a valid session, and other messages
|
||||||
|
* will be sent
|
||||||
|
*/
|
||||||
|
E_SCP_LS_SESSION_INFO = 0,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This message indicates the end of a list of sessions. No session
|
||||||
|
* is contained in the message */
|
||||||
|
E_SCP_LS_END_OF_LIST,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Authentication failed for the user
|
||||||
|
*/
|
||||||
|
E_SCP_LS_AUTHENTICATION_FAIL = 100,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A client-side error occurred allocating memory for the session
|
||||||
|
*/
|
||||||
|
E_SCP_LS_NO_MEMORY
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send an E_LIST_SESSIONS_REQUEST (SCP client)
|
||||||
|
*
|
||||||
|
* @param trans SCP transport
|
||||||
|
* @param username Username
|
||||||
|
* @param password Password
|
||||||
|
* @return != 0 for error
|
||||||
|
*
|
||||||
|
* Server replies with one or more E_SCP_LIST_SESSIONS_RESPONSE
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
scp_send_list_sessions_request(struct trans *trans,
|
||||||
|
const char *username,
|
||||||
|
const char *password);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse an incoming E_LIST_SESSIONS_REQUEST (SCP server)
|
||||||
|
*
|
||||||
|
* @param trans SCP transport
|
||||||
|
* @param[out] username Username
|
||||||
|
* @param[out] password Password
|
||||||
|
* @return != 0 for error
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
scp_get_list_sessions_request(struct trans *trans,
|
||||||
|
const char **username,
|
||||||
|
const char **password);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send an E_LIST_SESSIONS_RESPONSE (SCP server)
|
||||||
|
*
|
||||||
|
* @param trans SCP transport
|
||||||
|
* @param status Status of request
|
||||||
|
* @param info Session to send if status == E_SCL_LS_SESSION_INFO
|
||||||
|
* @return != 0 for error
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
scp_send_list_sessions_response(
|
||||||
|
struct trans *trans,
|
||||||
|
enum scp_list_sessions_status status,
|
||||||
|
const struct scp_session_info *info);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse an incoming E_LIST_SESSIONS_RESPONSE (SCP client)
|
||||||
|
*
|
||||||
|
* @param trans SCP transport
|
||||||
|
* @param[out] status Status of request
|
||||||
|
* @param[out] info Session if status == E_SCL_LS_SESSION_INFO
|
||||||
|
* @return != 0 for error
|
||||||
|
*
|
||||||
|
* The session info is returned as a dynamically allocated structure.
|
||||||
|
* After use the structure (and its members) can be de-allocated with
|
||||||
|
* a single call to g_free()
|
||||||
|
*
|
||||||
|
* The info structures can be added to a 'struct list' with auto_free set.
|
||||||
|
* When the list is de-allocated, all the structures will be de-allocated too.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
scp_get_list_sessions_response(
|
||||||
|
struct trans *trans,
|
||||||
|
enum scp_list_sessions_status *status,
|
||||||
|
struct scp_session_info **info);
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* SCP_H */
|
65
libipm/scp_application_types.h
Normal file
65
libipm/scp_application_types.h
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
/**
|
||||||
|
* 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_application_types.h
|
||||||
|
* @brief scp type declarations intended for use in the application
|
||||||
|
* @author Simone Fedele/ Matt Burt
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SCP_APPLICATION_TYPES_H
|
||||||
|
#define SCP_APPLICATION_TYPES_H
|
||||||
|
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Select the desktop application session type
|
||||||
|
*/
|
||||||
|
enum scp_session_type
|
||||||
|
{
|
||||||
|
SCP_SESSION_TYPE_XVNC = 0, ///< Session used Xvnc
|
||||||
|
SCP_SESSION_TYPE_XRDP, ///< Session uses X11rdp
|
||||||
|
SCP_SESSION_TYPE_XORG ///< Session used Xorg + xorgxrdp
|
||||||
|
};
|
||||||
|
|
||||||
|
#define SCP_SESSION_TYPE_TO_STR(t) \
|
||||||
|
((t) == SCP_SESSION_TYPE_XVNC ? "Xvnc" : \
|
||||||
|
(t) == SCP_SESSION_TYPE_XRDP ? "Xrdp" : \
|
||||||
|
(t) == SCP_SESSION_TYPE_XORG ? "Xorg" : \
|
||||||
|
"unknown" \
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Information to display about a particular sesman session
|
||||||
|
*/
|
||||||
|
struct scp_session_info
|
||||||
|
{
|
||||||
|
int sid; ///< Session ID
|
||||||
|
unsigned int display; ///< Display number
|
||||||
|
enum scp_session_type type; ///< Session type
|
||||||
|
unsigned short width; ///< Initial session width
|
||||||
|
unsigned short height; ///< Initial session height
|
||||||
|
unsigned char bpp; ///< Session bits-per-pixel
|
||||||
|
time_t start_time; ///< When sesion was created
|
||||||
|
char *username; ///< Username for session
|
||||||
|
char *connection_description; ///< Initial connection to session
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* SCP_APPLICATION_TYPES_H */
|
Loading…
Reference in New Issue
Block a user