mirror of https://github.com/neutrinolabs/xrdp
Add libipm facility
This commit is contained in:
parent
8f4860cb55
commit
e059336dff
|
@ -45,6 +45,7 @@ SUBDIRS = \
|
|||
xup \
|
||||
mc \
|
||||
$(NEUTRINORDPDIR) \
|
||||
libipm \
|
||||
libxrdp \
|
||||
$(PAINTERDIR) \
|
||||
$(RFXCODECDIR) \
|
||||
|
|
|
@ -484,6 +484,7 @@ AC_CONFIG_FILES([
|
|||
instfiles/pulse/Makefile
|
||||
instfiles/rc.d/Makefile
|
||||
keygen/Makefile
|
||||
libipm/Makefile
|
||||
libxrdp/Makefile
|
||||
Makefile
|
||||
mc/Makefile
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -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
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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 */
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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 */
|
|
@ -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