Merge pull request #3567 from matt335672/close_on_reconnect

Close on reconnect
This commit is contained in:
matt335672
2025-07-21 14:37:16 +01:00
committed by GitHub
43 changed files with 1521 additions and 148 deletions
+13 -21
View File
@@ -82,6 +82,7 @@
#define RNS_UD_32BPP_SUPPORT 0x0008
/* Client Core Data: earlyCapabilityFlags (2.2.1.3.2) */
#define RNS_UD_CS_SUPPORT_ERRINFO_PDU 0x0001
#define RNS_UD_CS_WANT_32BPP_SESSION 0x0002
#define RNS_UD_CS_SUPPORT_MONITOR_LAYOUT_PDU 0x0040
#define RNS_UD_CS_SUPPORT_DYNVC_GFX_PROTOCOL 0x0100
@@ -272,27 +273,18 @@
/* RDP5 disconnect PDU */
/* Set Error Info PDU Data: errorInfo (2.2.5.1.1) */
/* TODO: to be renamed */
#define exDiscReasonNoInfo 0x0000
#define exDiscReasonAPIInitiatedDisconnect 0x0001
#define exDiscReasonAPIInitiatedLogoff 0x0002
#define exDiscReasonServerIdleTimeout 0x0003
#define exDiscReasonServerLogonTimeout 0x0004
#define exDiscReasonReplacedByOtherConnection 0x0005
#define exDiscReasonOutOfMemory 0x0006
#define exDiscReasonServerDeniedConnection 0x0007
#define exDiscReasonServerDeniedConnectionFips 0x0008
#define exDiscReasonLicenseInternal 0x0100
#define exDiscReasonLicenseNoLicenseServer 0x0101
#define exDiscReasonLicenseNoLicense 0x0102
#define exDiscReasonLicenseErrClientMsg 0x0103
#define exDiscReasonLicenseHwidDoesntMatchLicense 0x0104
#define exDiscReasonLicenseErrClientLicense 0x0105
#define exDiscReasonLicenseCantFinishProtocol 0x0106
#define exDiscReasonLicenseClientEndedProtocol 0x0107
#define exDiscReasonLicenseErrClientEncryption 0x0108
#define exDiscReasonLicenseCantUpgradeLicense 0x0109
#define exDiscReasonLicenseNoRemoteConnections 0x010a
#define ERRINFO_NONE 0x0000
#define ERRINFO_RPC_INITIATED_DISCONNECT 0x0001
#define ERRINFO_RPC_INITIATED_LOGOFF 0x0002
#define ERRINFO_IDLE_TIMEOUT 0x0003
#define ERRINFO_LOGON_TIMEOUT 0x0004
#define ERRINFO_DISCONNECTED_BY_OTHERCONNECTION 0x0005
#define ERRINFO_OUT_OF_MEMORY 0x0006
#define ERRINFO_SERVER_DENIED_CONNECTION 0x0007
#define ERRINFO_SERVER_INSUFFICIENT_PRIVILEGES 0x0009
#define ERRINFO_LOGOFF_BY_USER 0x000c
#define ERRINFO_SERVER_DWM_CRASH 0x0010
#define ERRINFO_SERVER_CSRSS_CRASH 0x0018
/* Virtual channel PDU (2.2.6.1) */
#define CHANNEL_CHUNK_LENGTH 1600
+1 -1
View File
@@ -146,7 +146,7 @@ struct xrdp_client_info
int op2; /* use smaller bitmap header in bitmap cache */
int desktop_cache;
int use_compact_packets; /* rdp5 smaller packets */
char hostname[32];
char client_name[INFO_CLIENT_NAME_BYTES_UTF8];
int build;
int keylayout;
char username[INFO_CLIENT_MAX_CB_LEN];
+13 -1
View File
@@ -51,8 +51,20 @@
*/
#define MAX_PEER_DESCSTRLEN (46 + 2 + 1 + 5)
#define INFO_CLIENT_NAME_BYTES 32
/*
* Number of bytes used to send a client name in the client core data
* ([MS-RDPBCGR] 2.2.1.3.2). This is 15 characters plus a terminator in
* UTF-16
*/
#define INFO_CLIENT_NAME_BYTES_UTF16 ((15 + 1) * 2)
/*
* Number of bytes needed to store the client name as UTF-8. It is assumed
* that the 15 Unicode characters in the name all occupy BMP codepoints
* between U+0800 and U+FFFF. These codepoints all need three octets
* in UTF-8
*/
#define INFO_CLIENT_NAME_BYTES_UTF8 ((3 * 15) + 1)
/**
* Maximum length of a string including the mandatory null terminator
* [MS-RDPBCGR] TS_INFO_PACKET(2.2.1.11.1.1)
+4
View File
@@ -13,6 +13,10 @@ libipm_la_SOURCES = \
libipm_recv.c \
libipm_facilities.h \
libipm_private.h \
ccp.h \
ccp.c \
ccp_application_types.h \
ccp_application_types.c \
eicp.h \
eicp.c \
ercp.h \
+122
View File
@@ -0,0 +1,122 @@
/**
* xrdp: A Remote Desktop Protocol server.
*
* Copyright (C) Jay Sorg 2004-2022, all xrdp contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
*
* @file libipm/ccp.c
* @brief CCP definitions
* @author Matt Burt
*/
#if defined(HAVE_CONFIG_H)
#include <config_ac.h>
#endif
#include <stddef.h>
#include <stdio.h>
#include "ccp.h"
#include "libipm.h"
#include "trans.h"
/*****************************************************************************/
static const char *
msgno_to_str(unsigned short n)
{
return
(n == E_CCP_CLOSE_CONNECTION_REQUEST) ? "E_CCP_CLOSE_CONNECTION_REQUEST" :
NULL;
}
/*****************************************************************************/
const char *
ccp_msgno_to_str(enum ccp_msg_code n, char *buff, unsigned int buff_size)
{
const char *str = msgno_to_str((unsigned short)n);
if (str == NULL)
{
(void)snprintf(buff, buff_size, "[code #%d]", (int)n);
}
else
{
(void)snprintf(buff, buff_size, "%s", str);
}
return buff;
}
/*****************************************************************************/
void
ccp_trans_from_scp_trans(struct trans *trans,
ttrans_data_in callback_func,
void *callback_data)
{
libipm_change_facility(trans, LIBIPM_FAC_SCP, LIBIPM_FAC_CCP);
trans->trans_data_in = callback_func;
trans->callback_data = callback_data;
}
/*****************************************************************************/
int
ccp_msg_in_check_available(struct trans *trans, int *available)
{
return libipm_msg_in_check_available(trans, available);
}
/*****************************************************************************/
enum ccp_msg_code
ccp_msg_in_get_msgno(const struct trans *trans)
{
return (enum ccp_msg_code)libipm_msg_in_get_msgno(trans);
}
/*****************************************************************************/
void
ccp_msg_in_reset(struct trans *trans)
{
libipm_msg_in_reset(trans);
}
/*****************************************************************************/
int
ccp_send_close_connection_request(struct trans *trans,
enum ccp_close_reason_type reason)
{
return libipm_msg_out_simple_send(
trans,
(int)E_CCP_CLOSE_CONNECTION_REQUEST,
"i", reason);
}
/*****************************************************************************/
int
ccp_get_close_connection_request(struct trans *trans,
enum ccp_close_reason_type *reason)
{
/* Intermediate values */
int32_t i_reason;
int rv = libipm_msg_in_parse( trans, "i", &i_reason);
if (rv == 0)
{
*reason = (enum ccp_close_reason_type)i_reason;
}
return rv;
}
+136
View File
@@ -0,0 +1,136 @@
/**
* xrdp: A Remote Desktop Protocol server.
*
* Copyright (C) Jay Sorg 2004-2025, all xrdp contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
*
* @file libipm/ccp.h
* @brief CCP declarations
* @author Matt Burt
*
* Functions in this file use the following naming conventions:-
*
* E_CCP_{msg}_REQUEST is sent by ccp_send_{msg}_request()
* E_CCP_{msg}_REQUEST is parsed by ccp_get_{msg}_request()
* E_CCP_{msg}_RESPONSE is sent by ccp_send_{msg}_response()
* E_CCP_{msg}_RESPONSE is parsed by ccp_get_{msg}_response()
* E_CCP_{msg}_EVENT is sent by ccp_send_{msg}_event()
* E_CCP_{msg}_EVENT is parsed by ccp_get_{msg}_event()
*/
#ifndef CCP_H
#define CCP_H
#include "arch.h"
#include "trans.h"
#include "ccp_application_types.h"
/* Message codes */
enum ccp_msg_code
{
E_CCP_CLOSE_CONNECTION_REQUEST // sesexec -> xrdp
// No E_CCP_CLOSE_CONNECTION_RESPONSE
};
/* Common facilities */
/**
* Convert a message code to a string for output
* @param n Message code
* @param buff to contain string
* @param buff_size length of buff
* @return buff is returned for convenience.
*/
const char *
ccp_msgno_to_str(enum ccp_msg_code n, char *buff, unsigned int buff_size);
/* Connection management facilities */
/**
* Converts an SCP transport to an CCP transport.
*
* This is done following successful transmission or receipt of an
* E_SCP_CONNECT_SESSION_RESPONSE
*
* @param trans connected endpoint
* @param callback_func New callback function for CCP messages.
* @param callback_data New argument for callback function
*/
void
ccp_trans_from_scp_trans(struct trans *trans,
ttrans_data_in callback_func,
void *callback_data);
/**
* Checks an CCP transport to see if a complete message is
* available for parsing
*
* @param trans CCP transport
* @param[out] available != 0 if a complete message is available
* @return != 0 for error
*/
int
ccp_msg_in_check_available(struct trans *trans, int *available);
/**
* Gets the CCP message number of an incoming message
*
* @param trans CCP transport
* @return message in the buffer
*
* The results of calling this routine before ccp_msg_in_check_available()
* states a message is available are undefined.
*/
enum ccp_msg_code
ccp_msg_in_get_msgno(const struct trans *trans);
/**
* Resets an CCP message buffer ready to receive the next message
*
* @param trans libipm transport
*/
void
ccp_msg_in_reset(struct trans *trans);
/* -------------------- Session messages-------------------- */
/**
* Send an E_CCP_CLOSE_CONNECTION_REQUEST
*
* Direction : sesexec -> xrdp
*
* @param trans CCP transport
* @param reason reason_code
* @return != 0 for error
*/
int
ccp_send_close_connection_request(struct trans *trans,
enum ccp_close_reason_type reason);
/**
* Parse an incoming E_CCP_CLOSE_CONNECTION_REQUEST
*
* Direction : sesexec -> xrdp
*
* @param trans CCP transport
* @param[out] reason reason_code
* @return != 0 for error
*/
int
ccp_get_close_connection_request(struct trans *trans,
enum ccp_close_reason_type *reason);
#endif /* CCP_H */
+60
View File
@@ -0,0 +1,60 @@
/**
* xrdp: A Remote Desktop Protocol server.
*
* Copyright (C) Jay Sorg 2004-2022, all xrdp contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
*
* @file libipm/ccp_application_types.c
* @brief Support routines for types in ccp_application_types.h
* @author Matt Burt
*/
#if defined(HAVE_CONFIG_H)
#include <config_ac.h>
#endif
#include <stdio.h>
#include "ccp_application_types.h"
/*****************************************************************************/
const char *
ccp_close_reason_to_str(enum ccp_close_reason_type n,
char *buff, unsigned int buff_size)
{
const char *str =
(n == CCP_CLOSE_RPC_INITIATED_DISCONNECT)
? "Connection closed by administrator request" :
(n == CCP_CLOSE_DISCONNECTED_BY_OTHERCONNECTION)
? "Another connection was made to the session" :
(n == CCP_CLOSE_LOGOFF_BY_USER)
? "The user logged out of the session" :
(n == CCP_CLOSE_SOFTWARE_FAILURE)
? "A software failure has occurred" :
/* Default */ NULL;
if (str == NULL)
{
(void)snprintf(buff, buff_size, "[ccp reason code #%d]", (int)n);
}
else
{
(void)snprintf(buff, buff_size, "%s", str);
}
return buff;
}
+53
View File
@@ -0,0 +1,53 @@
/**
* xrdp: A Remote Desktop Protocol server.
*
* Copyright (C) Jay Sorg 2004-2022, all xrdp contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
*
* @file libipm/ccp_application_types.h
* @brief ccp type declarations intended for use in the application
* @author Simone Fedele/ Matt Burt
*/
#ifndef CCP_APPLICATION_TYPES_H
#define CCP_APPLICATION_TYPES_H
#include <sys/types.h>
/**
* Select the reason for a close connection request
*/
enum ccp_close_reason_type
{
CCP_CLOSE_RPC_INITIATED_DISCONNECT = 1,
CCP_CLOSE_DISCONNECTED_BY_OTHERCONNECTION,
CCP_CLOSE_LOGOFF_BY_USER,
CCP_CLOSE_SOFTWARE_FAILURE
};
/**
* Convert an ccp_close_reason_type to a readable string for output
* @param n Message code
* @param buff to contain string
* @param buff_size length of buff
* @return buff is returned for convenience.
*/
const char *
ccp_close_reason_to_str(enum ccp_close_reason_type n,
char *buff, unsigned int buff_size);
#endif /* CCP_APPLICATION_TYPES_H */
+74 -4
View File
@@ -43,6 +43,9 @@ msgno_to_str(unsigned short n)
(n == E_ERCP_CONNECT_SESSION_REQUEST) ? "ERCP_CONNECT_SESSION_REQUEST" :
(n == E_ERCP_CLIENT_CONNECT_EVENT) ? "ERCP_CLIENT_CONNECT_EVENT" :
(n == E_ERCP_CLIENT_DISCONNECT_EVENT) ? "ERCP_CLIENT_DISCONNECT_EVENT" :
NULL;
}
@@ -168,7 +171,7 @@ ercp_send_session_announce_event(struct trans *trans,
bpp,
&guid_descriptor,
start_ip_addr,
start_time);
(int64_t)start_time);
}
/*****************************************************************************/
@@ -237,24 +240,28 @@ ercp_send_session_finished_event(struct trans *trans)
int
ercp_send_connect_session_request(struct trans *trans,
int scp_fd,
const char *client_ip,
const char *client_name,
unsigned int scp_flags)
{
return libipm_msg_out_simple_send(
trans, (int)E_ERCP_CONNECT_SESSION_REQUEST,
"hu", scp_fd, scp_flags);
"hssu", scp_fd, client_ip, client_name, scp_flags);
}
/*****************************************************************************/
int
ercp_get_connect_session_request(struct trans *trans,
int *scp_fd,
const char **client_ip,
const char **client_name,
unsigned int *scp_flags)
{
/* Intermediate values */
uint32_t i_flags;
int rv = libipm_msg_in_parse(trans, "hu", scp_fd, &i_flags);
int rv = libipm_msg_in_parse(trans, "hssu",
scp_fd, client_ip, client_name, &i_flags);
if (rv == 0)
{
*scp_flags = i_flags;
@@ -262,3 +269,66 @@ ercp_get_connect_session_request(struct trans *trans,
return rv;
}
/*****************************************************************************/
int
ercp_send_client_connect_event(struct trans *trans,
const char *client_ip,
const char *client_name,
time_t connect_time)
{
return libipm_msg_out_simple_send(
trans, (int)E_ERCP_CLIENT_CONNECT_EVENT,
"ssx", client_ip, client_name, (int64_t)connect_time);
}
/*****************************************************************************/
int
ercp_get_client_connect_event(struct trans *trans,
const char **client_ip,
const char **client_name,
time_t *connect_time)
{
/* Intermediate values */
int64_t i_connect_time;
int rv = libipm_msg_in_parse(trans, "ssx",
client_ip, client_name, &i_connect_time);
if (rv == 0)
{
*connect_time = i_connect_time;
}
return rv;
}
/*****************************************************************************/
int
ercp_send_client_disconnect_event(struct trans *trans,
time_t disconnect_time)
{
return libipm_msg_out_simple_send(
trans, (int)E_ERCP_CLIENT_DISCONNECT_EVENT,
"x", (int64_t)disconnect_time);
}
/*****************************************************************************/
int
ercp_get_client_disconnect_event(struct trans *trans,
time_t *disconnect_time)
{
/* Intermediate values */
int64_t i_disconnect_time;
int rv = libipm_msg_in_parse(trans, "x", &i_disconnect_time);
if (rv == 0)
{
*disconnect_time = i_disconnect_time;
}
return rv;
}
+83 -3
View File
@@ -47,8 +47,13 @@ enum ercp_msg_code
E_ERCP_SESSION_ANNOUNCE_EVENT, // sesexec -> sesman
E_ERCP_SESSION_FINISHED_EVENT, // sesexec -> sesman
E_ERCP_CONNECT_SESSION_REQUEST // sesman -> sesexec
// No E_EICP_CONNECT_SESSION_RESPONSE - response sent over SCP
// A connect session request has no matching response, but if
// successful, a client connect event will be generated.
E_ERCP_CONNECT_SESSION_REQUEST, // sesman -> sesexec
// No E_ERCP_CONNECT_SESSION_RESPONSE
E_ERCP_CLIENT_CONNECT_EVENT, // sesexec -> sesman
E_ERCP_CLIENT_DISCONNECT_EVENT // sesexec -> sesman
};
/* Common facilities */
@@ -236,14 +241,18 @@ ercp_send_session_finished_event(struct trans *trans);
* A response is sent directly to the SCP client, rather than back
* to sesman
*
* @param trans EiCP transport
* @param trans ERCP transport
* @param scp_fd SCP file descriptor for a response
* @param client_ip IP address of connecting client
* @param client_name Name of connecting client (from RDP client core info)
* @param scp_flags Flags from scp_send_connect_session_request()
* @return != 0 for error
*/
int
ercp_send_connect_session_request(struct trans *trans,
int scp_fd,
const char *client_ip,
const char *client_name,
unsigned int scp_flags);
/**
@@ -258,13 +267,84 @@ ercp_send_connect_session_request(struct trans *trans,
*
* @param trans ERCP transport
* @param[out] scp_fd SCP file descriptor for a response
* @param[out] client_ip IP address of connecting client
* @param[out] client_name Name of connecting client
* @param[out] scp_flags Flags from scp_send_connect_session_request()
* @return != 0 for error
*/
int
ercp_get_connect_session_request(struct trans *trans,
int *scp_fd,
const char **client_ip,
const char **client_name,
unsigned int *scp_flags);
/**
* Send an E_ERCP_CLIENT_CONNECT_EVENT
*
* Direction : sesexec -> sesman
*
* This request tells sesman to update its connected client information
*
* @param trans ERCP transport
* @param client_ip IP address of connecting client
* @param client_name Name of connecting client (from RDP client core info)
* @param connect_time Time at which the connect event occurred
* @return != 0 for error
*/
int
ercp_send_client_connect_event(struct trans *trans,
const char *client_ip,
const char *client_name,
time_t connect_time);
/**
* Get an E_ERCP_CLIENT_CONNECT_EVENT
*
* Direction : sesexec -> sesman
*
* This request tells sesman to update its connected client information
*
* @param trans ERCP transport
* @param[out] client_ip IP address of connecting client
* @param[out] client_name Name of connecting client (from RDP client core info)
* @param[out] connect_time Time at which the connect event occurred
* @return != 0 for error
*/
int
ercp_get_client_connect_event(struct trans *trans,
const char **client_ip,
const char **client_name,
time_t *connect_time);
/**
* Send an E_ERCP_CLIENT_DISCONNECT_EVENT
*
* Direction : sesexec -> sesman
*
* This request tells sesman to update its connected client information
*
* @param trans ERCP transport
* @param disconnect_time Time at which the disconnect event occurred
* @return != 0 for error
*/
int
ercp_send_client_disconnect_event(struct trans *trans,
time_t disconnect_time);
/**
* Get an E_ERCP_CLIENT_DISCONNECT_EVENT
*
* Direction : sesexec -> sesman
*
* This request tells sesman to update its connected client information
*
* @param trans ERCP transport
* @param[out] disconnect_time Time at which the disconnect event occurred
* @return != 0 for error
*/
int
ercp_get_client_disconnect_event(struct trans *trans,
time_t *disconnect_time);
#endif /* ERCP_H */
+1
View File
@@ -30,6 +30,7 @@ enum libipm_facility
LIBIPM_FAC_SCP = 1, /**< SCP - Sesman Control Protocol */
LIBIPM_FAC_EICP, /**< EICP - Executive Initialization Control Protocol */
LIBIPM_FAC_ERCP, /**< ERCP - Executive Run-time Control Protocol */
LIBIPM_FAC_CCP, /**< CCP - Connection Control Protocol */
LIBIPM_FAC_TEST = 65535 /**< Used for unit testing */
};
+39 -13
View File
@@ -525,6 +525,8 @@ scp_get_create_session_response(struct trans *trans,
int
scp_send_connect_session_request(struct trans *trans,
const struct guid *guid,
const char *client_ip,
const char *client_name,
unsigned int flags)
{
struct libipm_fsb guid_descriptor = { (void *)guid, sizeof(*guid) };
@@ -532,7 +534,7 @@ scp_send_connect_session_request(struct trans *trans,
return libipm_msg_out_simple_send(
trans,
(int)E_SCP_CONNECT_SESSION_REQUEST,
"Bu", &guid_descriptor, flags);
"Bssu", &guid_descriptor, client_ip, client_name, flags);
}
/*****************************************************************************/
@@ -540,13 +542,17 @@ scp_send_connect_session_request(struct trans *trans,
int
scp_get_connect_session_request(struct trans *trans,
struct guid *guid,
const char **client_ip,
const char **client_name,
unsigned int *flags)
{
struct libipm_fsb guid_descriptor = { (void *)guid, sizeof(*guid) };
/* Intermediate values */
uint32_t i_flags;
int rv = libipm_msg_in_parse( trans, "Bu", &guid_descriptor, &i_flags);
int rv = libipm_msg_in_parse(trans, "Bssu",
&guid_descriptor, client_ip, client_name,
&i_flags);
if (rv == 0)
{
@@ -737,7 +743,7 @@ scp_send_list_sessions_response(
rv = libipm_msg_out_simple_send(
trans,
(int)E_SCP_LIST_SESSIONS_RESPONSE,
"iiuyqqyxis",
"iiuyqqyxisssx",
status,
info->sid,
info->display,
@@ -745,9 +751,12 @@ scp_send_list_sessions_response(
info->width,
info->height,
info->bpp,
info->start_time,
(int64_t)info->start_time,
info->uid,
info->start_ip_addr);
info->start_ip_addr,
info->client_ip,
info->client_name,
(int64_t)info->last_connect_disconnect);
}
return rv;
@@ -785,10 +794,13 @@ scp_get_list_sessions_response(
int64_t i_start_time;
int32_t i_uid;
char *i_start_ip_addr;
char *i_client_ip;
char *i_client_name;
int64_t i_last_connect_disconnect;
rv = libipm_msg_in_parse(
trans,
"iuyqqyxis",
"iuyqqyxisssx",
&i_sid,
&i_display,
&i_type,
@@ -797,25 +809,35 @@ scp_get_list_sessions_response(
&i_bpp,
&i_start_time,
&i_uid,
&i_start_ip_addr);
&i_start_ip_addr,
&i_client_ip,
&i_client_name,
&i_last_connect_disconnect);
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_start_ip_addr) + 1;
g_strlen(i_start_ip_addr) + 1 +
g_strlen(i_client_ip) + 1 +
g_strlen(i_client_name) + 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->start_ip_addr =
/* Set a pointer to access the strings after the block */
char *memptr =
(char *)p + sizeof(struct scp_session_info);
#define COPY_STRING(ptr,src) \
{ \
size_t len = strlen(src) + 1; \
(ptr) = memptr; \
memcpy(memptr, src, len); \
memptr += len; \
}
/* Copy the data over */
p->sid = i_sid;
p->display = i_display;
@@ -825,7 +847,11 @@ scp_get_list_sessions_response(
p->bpp = i_bpp;
p->start_time = i_start_time;
p->uid = i_uid;
g_strcpy(p->start_ip_addr, i_start_ip_addr);
COPY_STRING(p->start_ip_addr, i_start_ip_addr);
COPY_STRING(p->client_ip, i_client_ip);
COPY_STRING(p->client_name, i_client_name);
p->last_connect_disconnect = i_last_connect_disconnect;
#undef COPY_STRING
}
}
}
+8
View File
@@ -421,6 +421,8 @@ scp_get_create_session_response(struct trans *trans,
*
* @param trans SCP transport
* @param guid Session guid
* @param client_ip IP address of connecting client
* @param client_name Name of connecting client (from RDP client core info)
* @param flags Flags which affect the returned FDs
* @return != 0 for error
*
@@ -429,6 +431,8 @@ scp_get_create_session_response(struct trans *trans,
int
scp_send_connect_session_request(struct trans *trans,
const struct guid *guid,
const char *client_ip,
const char *client_name,
unsigned int flags);
@@ -437,12 +441,16 @@ scp_send_connect_session_request(struct trans *trans,
*
* @param trans SCP transport
* @param[out] guid Session guid
* @param[out] client_ip IP address of connecting client
* @param[out] client_name Name of connecting client
* @param[out] flags Flags which affect the returned FDs
* @return != 0 for error
*/
int
scp_get_connect_session_request(struct trans *trans,
struct guid *guid,
const char **client_ip,
const char **client_name,
unsigned int *flags);
/**
+3
View File
@@ -59,6 +59,9 @@ struct scp_session_info
time_t start_time; ///< When session was created
uid_t uid; ///< Username for session
char *start_ip_addr; ///< IP address of starting client
char *client_ip; ///< Current client IP
char *client_name; ///< Current client name
time_t last_connect_disconnect; ///< Time of last client connect/disconnect
};
/**
+39 -2
View File
@@ -73,9 +73,46 @@ libxrdp_exit(struct xrdp_session *session)
/******************************************************************************/
int EXPORT_CC
libxrdp_disconnect(struct xrdp_session *session)
libxrdp_disconnect(struct xrdp_session *session, int errinfo)
{
return xrdp_rdp_disconnect((struct xrdp_rdp *)session->rdp);
int rv = 0;
struct trans *trans = NULL;
struct xrdp_rdp *rdp = NULL;
int early_capability_flags = 0;
if (session != NULL)
{
trans = session->trans;
rdp = (struct xrdp_rdp *)session->rdp;
if (session->client_info != NULL)
{
early_capability_flags =
session->client_info->mcs_early_capability_flags;
}
}
if (trans != NULL && trans->status == TRANS_STATUS_UP &&
trans->sck >= 0 && rdp != NULL)
{
/* Only send the error info PDU if the client has
* indicated it can receive it */
if ((early_capability_flags & RNS_UD_CS_SUPPORT_ERRINFO_PDU) != 0)
{
rv = xrdp_rdp_send_set_error(rdp, errinfo);
}
if (rv == 0)
{
rv = xrdp_rdp_send_deactivate(rdp);
}
if (rv == 0)
{
rv = xrdp_rdp_disconnect(rdp);
}
}
return rv;
}
/******************************************************************************/
+12
View File
@@ -456,6 +456,18 @@ xrdp_rdp_send_deactivate(struct xrdp_rdp *self);
int
xrdp_rdp_send_session_info(struct xrdp_rdp *self, const char *data,
int data_bytes);
/**
* Send a [MS-RDPBCGR] TS_SET_ERROR_INFO_PDU message
* @param self xrdp_rdp struct
* @param reason errinfo code ([MS-RDPBCGR] 2.2.5.1.1)
* @return != 0 for error
* The caller is responsible for checking the client supports
* reception of this message (see 2.2.5.1)
*/
int
xrdp_rdp_send_set_error(struct xrdp_rdp *self, int reason);
/**
* Request output suppress or resume
*
+11 -1
View File
@@ -104,8 +104,18 @@ struct xrdp_session *
libxrdp_init(tbus id, struct trans *trans, const char *xrdp_ini);
int
libxrdp_exit(struct xrdp_session *session);
/**
* Sends a disconnect sequence from the server ([MS-RDPBCGR] 1.3.1.4.x)
* @param session xrdp session
* @param errinfo Reason ([MS-RDPBCGR] 2.2.5.1.1)
* @return != 0 for an error
*
* After this call, the rdp channel is closed and cannot be re-used. This
* routine can be called more than once, but only the first call is
* effective.
*/
int
libxrdp_disconnect(struct xrdp_session *session);
libxrdp_disconnect(struct xrdp_session *session, int errinfo);
int
libxrdp_process_incoming(struct xrdp_session *session);
int EXPORT_CC
+3 -6
View File
@@ -1364,11 +1364,9 @@ xrdp_rdp_send_disconnect_query_response(struct xrdp_rdp *self)
return 0;
}
#if 0 /* not used */
/*****************************************************************************/
/* Send a [MS-RDPBCGR] TS_SET_ERROR_INFO_PDU message */
static int
xrdp_rdp_send_disconnect_reason(struct xrdp_rdp *self, int reason)
int
xrdp_rdp_send_set_error(struct xrdp_rdp *self, int reason)
{
struct stream *s;
@@ -1378,7 +1376,7 @@ xrdp_rdp_send_disconnect_reason(struct xrdp_rdp *self, int reason)
if (xrdp_rdp_init_data(self, s) != 0)
{
LOG(LOG_LEVEL_ERROR,
"xrdp_rdp_send_disconnect_reason: xrdp_rdp_init_data failed");
"xrdp_rdp_send_set_error_pdu: xrdp_rdp_init_data failed");
free_stream(s);
return 1;
}
@@ -1399,7 +1397,6 @@ xrdp_rdp_send_disconnect_reason(struct xrdp_rdp *self, int reason)
free_stream(s);
return 0;
}
#endif
/*****************************************************************************/
/* Process a [MS-RDPRFX] TS_FRAME_ACKNOWLEDGE_PDU message */
+6 -6
View File
@@ -1477,7 +1477,7 @@ xrdp_sec_process_mcs_data_CS_CORE(struct xrdp_sec *self, struct stream *s)
2 + 2 + /* desktopWidth + desktopHeight */ \
2 + 2 + /* colorDepth + SASSequence */ \
4 + /* keyboardLayout */ \
4 + INFO_CLIENT_NAME_BYTES + /* clientBuild + clientName */ \
4 + INFO_CLIENT_NAME_BYTES_UTF16 + /* clientBuild + clientName */ \
4 + 4 + 4 + /* keyboardType + keyboardSubType + keyboardFunctionKey */ \
64 + /* imeFileName */ \
0)
@@ -1523,12 +1523,12 @@ xrdp_sec_process_mcs_data_CS_CORE(struct xrdp_sec *self, struct stream *s)
* This should be null-terminated. Allow for the possibility it
* isn't by ignoring the last two bytes and treating them as a
* terminator anyway */
in_utf16_le_fixed_as_utf8(s, (INFO_CLIENT_NAME_BYTES - 2) / 2,
client_info->hostname,
sizeof(client_info->hostname));
in_utf16_le_fixed_as_utf8(s, (INFO_CLIENT_NAME_BYTES_UTF16 - 2) / 2,
client_info->client_name,
sizeof(client_info->client_name));
in_uint8s(s, 2); /* See above */
LOG(LOG_LEVEL_INFO, "Connected client computer name: %s",
client_info->hostname);
client_info->client_name);
in_uint32_le(s, client_info->keyboard_type); /* [MS-RDPBCGR] TS_UD_CS_CORE keyboardType */
in_uint32_le(s, client_info->keyboard_subtype); /* [MS-RDPBCGR] TS_UD_CS_CORE keyboardSubType */
in_uint8s(s, 4); /* keyboardFunctionKey */
@@ -1548,7 +1548,7 @@ xrdp_sec_process_mcs_data_CS_CORE(struct xrdp_sec *self, struct stream *s)
"unknown"),
client_info->keylayout,
client_info->build,
client_info->hostname,
client_info->client_name,
client_info->keyboard_type,
client_info->keyboard_subtype);
+1 -1
View File
@@ -611,7 +611,7 @@ lxrdp_set_param(struct mod *mod, const char *name, const char *value)
settings = mod->inst->settings;
if (g_strcmp(name, "hostname") == 0)
if (g_strcmp(name, "client_name") == 0)
{
}
else if (g_strcmp(name, "ip") == 0)
+54 -1
View File
@@ -91,6 +91,51 @@ process_session_finished_event(struct session_item *si)
si->sesexec_trans->status = TRANS_STATUS_DOWN;
}
/******************************************************************************/
static int
process_client_connect_event(struct session_item *si)
{
int rv;
const char *client_ip;
const char *client_name;
time_t connect_time;
rv = ercp_get_client_connect_event(si->sesexec_trans,
&client_ip, &client_name, &connect_time);
if (rv == 0)
{
strlcpy(si->client_ip, client_ip, sizeof(si->client_ip));
strlcpy(si->client_name, client_name, sizeof(si->client_name));
si->last_connect_disconnect = connect_time;
LOG(LOG_LEVEL_INFO,
"sesman: Session on display :%d is connected from client '%s'",
si->display, si->client_name);
}
return rv;
}
/******************************************************************************/
static int
process_client_disconnect_event(struct session_item *si)
{
int rv;
time_t disconnect_time;
rv = ercp_get_client_disconnect_event(si->sesexec_trans, &disconnect_time);
if (rv == 0)
{
si->client_ip[0] = '\0';
si->client_name[0] = '\0';
si->last_connect_disconnect = disconnect_time;
LOG(LOG_LEVEL_INFO,
"sesman: Session on display :%d has no client connection",
si->display);
}
return rv;
}
/******************************************************************************/
int
ercp_process(struct session_item *si)
@@ -108,11 +153,19 @@ ercp_process(struct session_item *si)
process_session_finished_event(si);
break;
case E_ERCP_CLIENT_CONNECT_EVENT:
rv = process_client_connect_event(si);
break;
case E_ERCP_CLIENT_DISCONNECT_EVENT:
rv = process_client_disconnect_event(si);
break;
default:
{
char buff[64];
ercp_msgno_to_str(msgno, buff, sizeof(buff));
LOG(LOG_LEVEL_ERROR, "Ignored EICP message %s", buff);
LOG(LOG_LEVEL_ERROR, "Ignored ERCP message %s", buff);
}
}
return rv;
+6 -1
View File
@@ -576,10 +576,13 @@ process_connect_session_request(struct scp_list_item *sli)
int rv;
/* Client parameters describing new session */
struct guid guid;
const char *client_ip;
const char *client_name;
unsigned int flags;
enum scp_sconnect_status status = E_SCP_SCONNECT_OK;
rv = scp_get_connect_session_request(sli->client_trans, &guid, &flags);
rv = scp_get_connect_session_request(sli->client_trans, &guid,
&client_ip, &client_name, &flags);
if (rv == 0)
{
@@ -615,6 +618,8 @@ process_connect_session_request(struct scp_list_item *sli)
ercp_stat = ercp_send_connect_session_request(
s_item->sesexec_trans,
sli->client_trans->sck,
client_ip,
client_name,
flags);
if (ercp_stat != 0)
+2
View File
@@ -21,6 +21,8 @@ xrdp_sesexec_SOURCES = \
sesexec.h \
session.c \
session.h \
ccp_server.c \
ccp_server.h \
eicp_server.c \
eicp_server.h \
ercp_server.c \
+53
View File
@@ -0,0 +1,53 @@
/**
* xrdp: A Remote Desktop Protocol server.
*
* Copyright (C) Jay Sorg 2004-2023
*
* 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 eicp_server.c
* @brief eicp (executive initialisation control protocol) server function
* @author Matt Burt
*
*/
#if defined(HAVE_CONFIG_H)
#include <config_ac.h>
#endif
#include "trans.h"
#include "ccp.h"
#include "ccp_server.h"
/******************************************************************************/
int
ccp_server(struct trans *self)
{
int rv = 0;
enum ccp_msg_code msgno;
switch ((msgno = ccp_msg_in_get_msgno(self)))
{
default:
{
char buff[64];
ccp_msgno_to_str(msgno, buff, sizeof(buff));
LOG(LOG_LEVEL_ERROR, "Ignored CCP message %s", buff);
}
}
return rv;
}
+39
View File
@@ -0,0 +1,39 @@
/**
* xrdp: A Remote Desktop Protocol server.
*
* Copyright (C) Jay Sorg 2004-2023
*
* 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 ccp_server.h
* @brief ccp (connection control protocol) server function
* @author Matt Burt
*
*/
#ifndef CCP_SERVER_H
#define CCP_SERVER_H
/**
*
* @brief Processes an CCP message
* @param self The CCP transport the message is coming in on
*
*/
int
ccp_server(struct trans *self);
#endif // CCP_SERVER_H
+1 -3
View File
@@ -172,9 +172,7 @@ handle_create_session_request(struct trans *self)
if (status == 0 && scp_status == E_SCP_SCREATE_OK)
{
// Further comms to sesman is sent over the ERCP protocol
ercp_trans_from_eicp_trans(self,
sesexec_ercp_data_in,
(void *)self);
ercp_trans_from_eicp_trans(self, sesexec_ercp_data_in, NULL);
// Announce the session to sesman
if ((status = ercp_send_session_announce_event(
+55 -8
View File
@@ -72,8 +72,10 @@ handle_connect_session_request(struct trans *self)
{
int scp_fd = -1;
unsigned int scp_flags;
int rv = ercp_get_connect_session_request(self, &scp_fd, &scp_flags);
const char *client_ip;
const char *client_name;
int rv = ercp_get_connect_session_request(self, &scp_fd, &client_ip,
&client_name, &scp_flags);
if (rv == 0)
{
struct trans *scp_trans;
@@ -87,20 +89,55 @@ handle_connect_session_request(struct trans *self)
}
else
{
scp_fd = -1; // Don't close this twice!
// Ownership of the file descriptor is passed to scp_trans;
// don't delete it separately.
scp_fd = -1;
// Now we've got a transport we can send data back to
// the SCP client
enum scp_sconnect_status scp_status;
int display_fd = -1;
int chan_fd = -1;
// Terminate any existing xrdp process to sesexec
if (g_ccp_trans != NULL)
{
sesexec_terminate_connected_xrdp_process(
CCP_CLOSE_DISCONNECTED_BY_OTHERCONNECTION);
g_sleep(500);
}
scp_status = get_session_fds(g_session_data, scp_flags,
&display_fd, &chan_fd);
if (scp_status == E_SCP_SCONNECT_OK)
{
// Tell sesman about the new client connection
strlcpy(g_client_ip, client_ip, sizeof(g_client_ip));
strlcpy(g_client_name, client_name, sizeof(g_client_name));
g_last_connect_disconnect = time(NULL);
if (g_ecp_trans != NULL)
{
(void)ercp_send_client_connect_event(
g_ecp_trans, g_client_ip, g_client_name,
g_last_connect_disconnect);
}
}
// Pass the session file descriptors to the client
rv = scp_send_connect_session_response(scp_trans, scp_status,
display_fd, chan_fd);
if (rv == 0 && scp_status == E_SCP_SCONNECT_OK)
{
// Variables to pass to the reconnect script
const char *vars[] =
{
"XRDP_CLIENT_IP", g_client_ip,
"XRDP_CLIENT_NAME", g_client_name,
NULL // Terminator
};
// Don't run the reconnect script on the first connect,
// unless we're configured to do so.
if (session_increment_connect_count(g_session_data) == 0)
@@ -110,7 +147,7 @@ handle_connect_session_request(struct trans *self)
if (g_cfg->always_run_reconnect)
{
session_run_reconnect_script(g_login_info,
g_session_data);
g_session_data, vars);
}
}
else
@@ -118,12 +155,19 @@ handle_connect_session_request(struct trans *self)
LOG(LOG_LEVEL_INFO, "User %s has reconnected to a session",
g_login_info->username);
session_run_reconnect_script(g_login_info,
g_session_data);
g_session_data, vars);
}
// Convert the SCP transport to a CCP transport, and
// record it
if (sesexec_set_ccp_trans(scp_trans) == 0)
{
scp_trans = NULL; // Prevent transport being deleted.
}
}
// Regardless of the result of the send, we must close all
// our copies of file descriptors.
// Close all our copies of file descriptors, including the
// SCP transport if we failed to convert it to a CCP transport
if (display_fd >= 0)
{
g_file_close(display_fd);
@@ -132,7 +176,10 @@ handle_connect_session_request(struct trans *self)
{
g_file_close(chan_fd);
}
trans_delete(scp_trans);
if (scp_trans != NULL)
{
trans_delete(scp_trans);
}
}
}
+207 -5
View File
@@ -32,6 +32,8 @@
#include <stdarg.h>
#include "arch.h"
#include "ccp.h"
#include "ccp_server.h"
#include "eicp.h"
#include "eicp_server.h"
#include "ercp.h"
@@ -52,6 +54,12 @@ struct startup_params
const char *sesman_ini;
};
enum
{
MAX_ROBJS = 32, ///< Maximum number of file objects in use at any one time
XRDP_EXIT_TIMEOUT = 2500 ///< Time to wait for xrdp process to exit
};
/*
* Program-scope globals
*/
@@ -64,10 +72,15 @@ tintptr g_term_event = 0;
tintptr g_sigchld_event = 0;
pid_t g_pid;
struct trans *g_ecp_trans;
struct trans *g_ccp_trans;
char g_client_ip[MAX_PEER_ADDRSTRLEN];
char g_client_name[INFO_CLIENT_NAME_BYTES_UTF8];
time_t g_last_connect_disconnect;
/*
* Module-scope globals
*/
static struct trans *g_ecp_trans;
static pid_t g_ecp_pid;
static int g_terminate_loop = 0;
static int g_terminate_status = 0;
@@ -163,6 +176,27 @@ sesexec_ercp_data_in(struct trans *self)
return rv;
}
/******************************************************************************/
static int
sesexec_ccp_data_in(struct trans *self)
{
int rv;
int available;
rv = ccp_msg_in_check_available(self, &available);
if (rv == 0 && available)
{
if ((rv = ccp_server(self)) != 0)
{
LOG(LOG_LEVEL_ERROR, "%s: ccp_server failed", __func__);
}
ccp_msg_in_reset(self);
}
return rv;
}
/******************************************************************************/
/**
* Informs the main loop a termination signal has been received
@@ -235,6 +269,12 @@ sesexec_set_ecp_transport(struct trans *t)
g_ecp_pid = 0;
rv = 0;
}
else if (t == g_ecp_trans)
{
// This would break the memory subsystem!
LOG(LOG_LEVEL_ERROR, "%s: programming error", __func__);
rv = 1;
}
else if ((rv = g_sck_get_peer_cred(t->sck, &pid, &uid, &gid)) != 0)
{
LOG(LOG_LEVEL_ERROR, "Can't get credentials of sesman socket [%s]",
@@ -286,6 +326,19 @@ sesexec_main_loop_cleanup(void)
session_data_free(g_session_data);
}
/******************************************************************************/
/**
* Close the CCP trans unconditionally
*
* Use this call if you are certain the other end has gone away
*/
static void
close_ccp_trans(void)
{
trans_delete(g_ccp_trans);
g_ccp_trans = NULL;
}
/******************************************************************************/
/**
*
@@ -297,7 +350,6 @@ sesexec_main_loop(void)
{
int error = 0;
int robjs_count;
#define MAX_ROBJS 32
intptr_t robjs[MAX_ROBJS];
g_terminate_loop = 0;
@@ -323,6 +375,19 @@ sesexec_main_loop(void)
}
}
// CCP transport is set if we have an xrdp connection
if (g_ccp_trans != NULL)
{
error = trans_get_wait_objs(g_ccp_trans, robjs, &robjs_count);
if (error != 0)
{
LOG(LOG_LEVEL_ERROR, "sesexec_main_loop: "
"trans_get_wait_objs(CCP) failed");
sesexec_terminate_main_loop(error);
continue;
}
}
// Add any objects from the discover module
error = sesexec_discover_get_wait_objs(robjs, &robjs_count, MAX_ROBJS);
if (error != 0)
@@ -370,13 +435,16 @@ sesexec_main_loop(void)
session_process_sigchld_event(g_session_data);
if (session_was_active && !session_active(g_session_data))
{
// We've finished the session. Tell sesman and
// We've finished the session. Tell sesman, xrdp and
// finish up.
if (g_ecp_trans != NULL)
{
(void)ercp_send_session_finished_event(g_ecp_trans);
}
sesexec_terminate_connected_xrdp_process(
CCP_CLOSE_LOGOFF_BY_USER);
session_data_free(g_session_data);
g_session_data = NULL;
sesexec_terminate_main_loop(0);
@@ -411,6 +479,44 @@ sesexec_main_loop(void)
}
}
if (g_ccp_trans != NULL)
{
error = trans_check_wait_objs(g_ccp_trans);
if (error != 0)
{
if (g_ccp_trans->status != TRANS_STATUS_UP)
{
// xrdp has gone away.
LOG(LOG_LEVEL_INFO, "sesexec_main_loop: "
"xrdp connection has exited (client '%s')",
g_client_name);
g_client_ip[0] = '\0';
g_client_name[0] = '\0';
g_last_connect_disconnect = time(NULL);
if (g_ecp_trans != NULL)
{
(void)ercp_send_client_disconnect_event(
g_ecp_trans, g_last_connect_disconnect);
}
close_ccp_trans();
}
else
{
// A callback has failed. This shouldn't really happen.
// Try to signal a software failure to the xrdp process
LOG(LOG_LEVEL_ERROR, "sesexec_main_loop: "
"trans_check_wait_objs failed for CCP transport");
sesexec_terminate_connected_xrdp_process(
CCP_CLOSE_SOFTWARE_FAILURE);
}
continue;
}
}
error = sesexec_discover_check_wait_objs();
if (error != 0)
{
@@ -419,14 +525,16 @@ sesexec_main_loop(void)
sesexec_terminate_main_loop(error);
continue;
}
}
/* close sesman communications immediately */
sesexec_set_ecp_transport(NULL);
/* We should already have notified xrdp of the reason why we are
* closing, in which case this call has no effect */
sesexec_terminate_connected_xrdp_process(CCP_CLOSE_SOFTWARE_FAILURE);
return g_terminate_status;
#undef MAX_ROBJS
}
/******************************************************************************/
@@ -598,3 +706,97 @@ main(int argc, char **argv)
g_deinit();
return error;
}
/******************************************************************************/
void
sesexec_terminate_connected_xrdp_process(enum ccp_close_reason_type reason)
{
if (g_ccp_trans != NULL && g_ccp_trans->status == TRANS_STATUS_UP)
{
// Ask xrdp to exit, specifying the reason to return to
// the RDP client (if possible)
(void)ccp_send_close_connection_request(g_ccp_trans, reason);
unsigned int start_ms = g_get_elapsed_ms();
while (1)
{
int robjs_count = 0;
intptr_t robjs[MAX_ROBJS];
// How long have we been waiting for xrdp to exit?
unsigned int elapsed = g_get_elapsed_ms() - start_ms;
if (elapsed > XRDP_EXIT_TIMEOUT)
{
// A timeout has occurred
LOG(LOG_LEVEL_WARNING,
"xrdp process failed to exit after %u ms", elapsed);
break;
}
robjs[robjs_count++] = g_term_event;
if (trans_get_wait_objs(g_ccp_trans, robjs, &robjs_count) != 0)
{
// Transport has gone away
LOG(LOG_LEVEL_WARNING,
"xrdp process exited after %u ms", elapsed);
break;
}
if (g_obj_wait(robjs, robjs_count, NULL, 0,
XRDP_EXIT_TIMEOUT - elapsed) != 0)
{
/* should not get here */
g_sleep(100);
}
else if (g_is_wait_obj_set(g_term_event))
{
// Get out as quickly as possible
break;
}
else
{
// This will cause trans_get_wait_objs() to return a failure
// when the end of the data on the socket is reached.
(void)trans_check_wait_objs(g_ccp_trans);
}
}
}
close_ccp_trans();
}
/******************************************************************************/
int
sesexec_set_ccp_trans(struct trans *scp_trans)
{
int rv = 1;
pid_t pid;
if (scp_trans == NULL)
{
close_ccp_trans();
rv = 0;
}
else if (scp_trans == g_ccp_trans)
{
// This would break the memory subsystem!
LOG(LOG_LEVEL_ERROR, "%s: programming error", __func__);
rv = 1;
}
else if ((rv = g_sck_get_peer_cred(scp_trans->sck, &pid, NULL, NULL)) != 0)
{
LOG(LOG_LEVEL_ERROR, "Can't get credentials of xrdp socket [%s]",
g_get_strerror());
}
else
{
// Convert the transport to a CCP transport
ccp_trans_from_scp_trans(scp_trans,
sesexec_ccp_data_in,
NULL);
trans_delete(g_ccp_trans);
g_ccp_trans = scp_trans;
rv = 0;
}
return rv;
}
+103 -3
View File
@@ -29,6 +29,9 @@
#include <sys/types.h>
#include "ccp_application_types.h"
#include "xrdp_constants.h"
struct config_sesman;
struct trans;
struct login_info;
@@ -39,15 +42,85 @@ struct session_data;
#endif
/* Globals */
/**
* Pointer to config data for sesman/sesexec
*/
extern struct config_sesman *g_cfg;
/**
* DES key used to obfuscate VNC password files.
*
* This key is not documented in RFC6143, but can readily be found by
* searching VNC sources.
*
* You can also find the 'reversed' form "e84ad660c4721ae0"
* on the net, particulary for openssl one-liners to decrypt VNC
* password files.
*/
extern unsigned char g_fixedkey[8];
/**
* Information about the logged-in user
*
* This is set when the user successfully passes authentication
*/
extern struct login_info *g_login_info;
/**
* Information about the user session (opaque type)
*
* Set when the user is succesfully logged in
*/
extern struct session_data *g_session_data;
/**
* Program has received a termination event
*/
extern tintptr g_term_event;
/**
* Program has received one or more SIGCHLD events
*/
extern tintptr g_sigchld_event;
/**
* PID of sesexec process
*
* Used to detect when we are running in a form of the original process
*/
extern pid_t g_pid;
/**
* EICP/ERCP transport
*
* Used to communicate with the sesman process
*
* Use sesexec_is_ecp_active() if you need to check sesman is
* truly there.
*/
extern struct trans *g_ecp_trans;
/**
* CCP transport
*
* Used to communicate with the currently connected xrdp process
*/
extern struct trans *g_ccp_trans;
/**
* Last connected client IP address
*/
extern char g_client_ip[MAX_PEER_ADDRSTRLEN];
/**
* Last connected client name
*/
extern char g_client_name[INFO_CLIENT_NAME_BYTES_UTF8];
/**
* Last connect / disconnect time
*/
extern time_t g_last_connect_disconnect;
/**
* Callback to process incoming ERCP data
@@ -55,14 +128,18 @@ extern pid_t g_pid;
int
sesexec_ercp_data_in(struct trans *self);
/*
/**
* Check for termination
*
* @return boolean. Set if program has been asked to terminate
*/
int
sesexec_is_term(void);
/*
/**
* Terminate the sesexec main loop
*
* @param status Status to return to the OS
*/
void
sesexec_terminate_main_loop(int status);
@@ -79,12 +156,35 @@ sesexec_terminate_main_loop(int status);
int
sesexec_set_ecp_transport(struct trans *t);
/*
/**
* Is the ECP transport still active?
*
* @result boolean
*
* This is intended to be used as a guard to prevent an active ECP
* transport being overwritten. Do not use it to check if sesman is
* active before sending messages, as this introduces a race condition.
*/
int
sesexec_is_ecp_active(void);
/**
* Terminate an active xrdp process
*
* @param Reason to pass back to the xrdp process (if connected)
*
* After this call, g_ccp_trans will be NULL
*/
void
sesexec_terminate_connected_xrdp_process(enum ccp_close_reason_type reason);
/**
* Set the CCP transport from an SCP transport
*
* This call is intended to be used at the end of a connection
* event, to record our end of the connection to the xrdp process
*/
int
sesexec_set_ccp_trans(struct trans *scp_trans);
#endif // SESEXEC_H
+15 -1
View File
@@ -83,7 +83,7 @@ discover_trans_conn_in(struct trans *trans, struct trans *new_trans)
// session
ercp_init_trans(new_trans);
new_trans->trans_data_in = sesexec_ercp_data_in;
new_trans->callback_data = (void *)new_trans;
new_trans->callback_data = NULL;
// Note, this call makes further privilege checks that may still
// fail. If they do however, we wish to carry on running. These
@@ -101,6 +101,20 @@ discover_trans_conn_in(struct trans *trans, struct trans *new_trans)
&sp->guid,
g_login_info->ip_addr,
session_get_start_time(g_session_data));
// Tell semsan about the last client connect or disconnect
if (g_ccp_trans != NULL)
{
(void)ercp_send_client_connect_event(new_trans,
g_client_ip,
g_client_name,
g_last_connect_disconnect);
}
else
{
(void)ercp_send_client_disconnect_event(new_trans,
g_last_connect_disconnect);
}
}
}
return rv;
+31 -12
View File
@@ -189,7 +189,8 @@ dumpItemsToString(struct list *self, char *outstr, int len)
/******************************************************************************/
static void
start_chansrv(const struct login_info *login_info,
const struct session_parameters *s)
const struct session_parameters *s,
void *closure /* unused */)
{
struct list *chansrv_params = list_create();
const char *exe_path = XRDP_SBIN_PATH "/xrdp-chansrv";
@@ -227,7 +228,8 @@ start_chansrv(const struct login_info *login_info,
/******************************************************************************/
static void
start_window_manager(const struct login_info *login_info,
const struct session_parameters *s)
const struct session_parameters *s,
void *closure /* unused */)
{
char text[256];
@@ -476,7 +478,8 @@ prepare_xvnc_xserver_params(const struct session_parameters *s,
/* Either execs the X server, or returns */
static void
start_x_server(const struct login_info *login_info,
const struct session_parameters *s)
const struct session_parameters *s,
void *closure /* unused */)
{
char authfile[256]; /* The filename for storing xauth information */
char execvpparams[2048];
@@ -579,10 +582,13 @@ start_x_server(const struct login_info *login_info,
* Simple helper process to fork a child and log errors */
static int
fork_child(
void (*runproc)(const struct login_info *, const struct session_parameters *),
void (*runproc)(const struct login_info *,
const struct session_parameters *,
void *closure),
const struct login_info *login_info,
const struct session_parameters *s,
pid_t group_pid)
pid_t group_pid,
void *closure)
{
int pid = g_fork();
if (pid == 0)
@@ -592,7 +598,7 @@ fork_child(
{
(void)g_setpgid(0, group_pid);
}
runproc(login_info, s);
runproc(login_info, s, closure);
g_exit(0);
}
@@ -720,7 +726,7 @@ session_start_wrapped(struct login_info *login_info,
* without affecting sesexec (and vice-versa). This is particularly
* important when debugging sesexec as we don't want a SIGINT in
* the debugger to be passed to the children */
display_pid = fork_child(start_x_server, login_info, s, 0);
display_pid = fork_child(start_x_server, login_info, s, 0, NULL);
if (display_pid > 0)
{
enum xwait_status xws;
@@ -756,7 +762,7 @@ session_start_wrapped(struct login_info *login_info,
s->display);
window_manager_pid = fork_child(start_window_manager,
login_info, s, display_pid);
login_info, s, display_pid, NULL);
if (window_manager_pid < 0)
{
g_sigterm(display_pid);
@@ -770,7 +776,7 @@ session_start_wrapped(struct login_info *login_info,
s->display);
chansrv_pid = fork_child(start_chansrv, login_info,
s, display_pid);
s, display_pid, NULL);
sd->win_mgr = window_manager_pid;
sd->x_server = display_pid;
@@ -1129,7 +1135,8 @@ session_send_term(struct session_data *sd, int wait_for_all)
/******************************************************************************/
static void
start_reconnect_script(const struct login_info *login_info,
const struct session_parameters *s)
const struct session_parameters *s,
void *closure)
{
env_set_user(login_info->uid, 0, s->display,
g_cfg->env_names,
@@ -1139,6 +1146,17 @@ start_reconnect_script(const struct login_info *login_info,
if (g_file_exist(g_cfg->reconnect_sh))
{
/* The 'closure' parameter points to a list of strings
* which need to be set in the environment for the reconnect script */
if (closure != NULL)
{
const char **p = (const char **)closure;
while (*p != NULL && *(p + 1) != NULL)
{
(void)g_setenv(*p, *(p + 1), 1);
p += 2;
}
}
LOG_DEVEL_LEAKING_FDS("reconnect script", 3, -1);
LOG(LOG_LEVEL_INFO,
@@ -1162,10 +1180,11 @@ start_reconnect_script(const struct login_info *login_info,
/******************************************************************************/
void
session_run_reconnect_script(const struct login_info *login_info,
const struct session_data *sd)
const struct session_data *sd,
const char *vars[])
{
if (fork_child(start_reconnect_script,
login_info, &sd->params, sd->x_server) < 0)
login_info, &sd->params, sd->x_server, (void *)vars) < 0)
{
LOG(LOG_LEVEL_ERROR, "Failed to fork for session reconnection script");
}
+9 -2
View File
@@ -32,7 +32,6 @@
#include "guid.h"
#include "scp_application_types.h"
#include "xrdp_constants.h"
struct login_info;
struct proc_exit_status;
@@ -159,10 +158,18 @@ session_data_free(struct session_data *session_data);
/**
* Runs the reconnect script for the session
* @param login_info Login info for the session
* @param sd Session data for the session
* @param vars environment variables for the reconnect script
*
* The vars parameter points to an array of strings in pairs. The
* first string in the pair is the name of an environment variable to
* set, and the second string is the value
*/
void
session_run_reconnect_script(const struct login_info *login_info,
const struct session_data *sd);
const struct session_data *sd,
const char *vars[]);
/**
* Connects a file descriptor to the display server
+17 -10
View File
@@ -336,18 +336,23 @@ session_list_get_byuid(const uid_t *uid, unsigned int *cnt, unsigned int flags)
if (SESSION_IN_USE(si) && (uid == NULL || *uid == si->uid))
{
(sess[index]).sid = si->sesexec_pid;
(sess[index]).display = si->display;
(sess[index]).type = si->type;
(sess[index]).height = si->start_height;
(sess[index]).width = si->start_width;
(sess[index]).bpp = si->bpp;
(sess[index]).start_time = si->start_time;
(sess[index]).uid = si->uid;
(sess[index]).start_ip_addr = g_strdup(si->start_ip_addr);
sess[index].sid = si->sesexec_pid;
sess[index].display = si->display;
sess[index].type = si->type;
sess[index].height = si->start_height;
sess[index].width = si->start_width;
sess[index].bpp = si->bpp;
sess[index].start_time = si->start_time;
sess[index].uid = si->uid;
sess[index].start_ip_addr = g_strdup(si->start_ip_addr);
sess[index].client_ip = g_strdup(si->client_ip);
sess[index].client_name = g_strdup(si->client_name);
sess[index].last_connect_disconnect = si->last_connect_disconnect;
/* Check for string allocation failures */
if ((sess[index]).start_ip_addr == NULL)
if (sess[index].start_ip_addr == NULL ||
sess[index].client_ip == NULL ||
sess[index].client_name == NULL)
{
free_session_info_list(sess, *cnt);
(*cnt) = 0;
@@ -390,6 +395,8 @@ free_session_info_list(struct scp_session_info *sesslist, unsigned int cnt)
for (i = 0 ; i < cnt ; ++i)
{
g_free(sesslist[i].start_ip_addr);
g_free(sesslist[i].client_ip);
g_free(sesslist[i].client_name);
}
}
+3
View File
@@ -68,6 +68,9 @@ struct session_item
struct guid guid;
char start_ip_addr[MAX_PEER_ADDRSTRLEN];
time_t start_time;
char client_ip[MAX_PEER_ADDRSTRLEN];
char client_name[INFO_CLIENT_NAME_BYTES_UTF8];
time_t last_connect_disconnect;
};
/**
+15
View File
@@ -151,6 +151,21 @@ print_session(const struct scp_session_info *s)
{
printf("\tStart IP address: %s\n", s->start_ip_addr);
}
if (s->client_ip[0] != '\0' && s->client_name[0] != '\0')
{
printf("\tConnection state: connected\n");
printf("\tConnected client IP: %s\n", s->client_ip);
printf("\tConnected client name: %s\n", s->client_name);
printf("\tConnection start time: %s\n",
ctime(&s->last_connect_disconnect));
}
else
{
printf("\tConnection state: disconnected\n");
printf("\tConnection end time: %s\n",
(s->last_connect_disconnect == 0) ? "-" :
ctime(&s->last_connect_disconnect));
}
g_free(username);
}
+1
View File
@@ -61,6 +61,7 @@ test_xrdp_LDADD = \
$(top_builddir)/libxrdp/libxrdp.la \
$(top_builddir)/xrdp/lang.o \
$(top_builddir)/xrdp/xrdp_mm.o \
$(top_builddir)/xrdp/xrdp_mm_ccp.o \
$(top_builddir)/xrdp/xrdp_wm.o \
$(top_builddir)/xrdp/xrdp_font.o \
$(top_builddir)/xrdp/xrdp_egfx.o \
+1
View File
@@ -71,6 +71,7 @@ xrdp_SOURCES = \
xrdp_listen.c \
xrdp_login_wnd.c \
xrdp_mm.c \
xrdp_mm_ccp.c \
xrdp_mm.h \
xrdp_painter.c \
xrdp_process.c \
+32
View File
@@ -503,6 +503,31 @@ xrdp_mm_suppress_output(struct xrdp_mm *self, int suppress,
int left, int top, int right, int bottom);
int
xrdp_mm_up_and_running(struct xrdp_mm *self);
/**
* Ask the xrdp process (or thread) to terminate
* @param self xrdp_mm struct
* @param errinfo Error code to return to the client
*
* Execution continues after this call until the main process loop
* is reached. This routine could be called multiple times. In this
* instance the first code set is passed back to the client.
*/
void
xrdp_mm_set_fatal(struct xrdp_mm *self, int errinfo);
/**
* Tell the user via the log window a fatal error has occurred
* @param self xrdp_mm struct
* @param errinfo Error code to return to the client
*
* The log window must already contain the fatal error.
* When the user presses OK in the log window, the xrdp process
* (or thread) is terminated.
*/
void
xrdp_mm_logwnd_fatal(struct xrdp_mm *self, int errinfo);
int
xrdp_mm_send_unicode_to_chansrv(struct xrdp_mm *self,
int key_down,
@@ -535,4 +560,11 @@ xrdp_mm_egfx_send_planar_bitmap(struct xrdp_mm *self,
struct xrdp_bitmap *bitmap,
struct xrdp_rect *rect,
int surface_id, int x, int y);
/* xrdp_mm_cpp.c */
/* Callback registered for sesman communication replies over CCP */
int
xrdp_mm_ccp_data_in(struct trans *trans);
#endif
+2
View File
@@ -216,6 +216,8 @@ xrdp_wm_cancel_clicked(struct xrdp_bitmap *wnd)
{
if (wnd->wm->pro_layer != 0)
{
wnd->wm->pro_layer->errinfo =
ERRINFO_SERVER_INSUFFICIENT_PRIVILEGES;
g_set_wait_obj(wnd->wm->pro_layer->self_term_event);
}
}
+81 -41
View File
@@ -28,6 +28,7 @@
#include "guid.h"
#include "ms-rdpedisp.h"
#include "ms-rdpbcgr.h"
#include "ccp.h"
#include "scp.h"
#include <ctype.h>
#include "xrdp_encoder.h"
@@ -362,7 +363,10 @@ xrdp_mm_get_session_fds(struct xrdp_mm *self)
}
rv = scp_send_connect_session_request(self->sesman_trans,
&self->guid, flags);
&self->guid,
self->wm->client_info->client_ip,
self->wm->client_info->client_name,
flags);
return rv;
}
@@ -1991,6 +1995,26 @@ xrdp_mm_up_and_running(struct xrdp_mm *self)
return 0;
}
/******************************************************************************/
void
xrdp_mm_set_fatal(struct xrdp_mm *self, int errinfo)
{
if (self->wm->pro_layer->errinfo == ERRINFO_NONE)
{
self->wm->pro_layer->errinfo = errinfo;
}
g_set_wait_obj(self->wm->pro_layer->self_term_event);
}
/******************************************************************************/
void
xrdp_mm_logwnd_fatal(struct xrdp_mm *self, int errinfo)
{
xrdp_wm_log_msg(self->wm, LOG_LEVEL_INFO, "Close the log window to exit.");
self->wm->pro_layer->errinfo = errinfo;
self->wm->fatal_error_in_log_window = 1;
}
/*****************************************************************************/
/* open response from client going to channel server */
static int
@@ -2621,9 +2645,9 @@ xrdp_mm_process_login_response(struct xrdp_mm *self)
if (self->wm->client_info->require_credentials)
{
/* Credentials had to be specified, but were invalid */
g_set_wait_obj(self->wm->pro_layer->self_term_event);
LOG(LOG_LEVEL_ERROR, "require_credentials is set, "
"but the user could not be logged in");
xrdp_mm_set_fatal(self, ERRINFO_SERVER_INSUFFICIENT_PRIVILEGES);
}
if (server_closed)
@@ -2633,9 +2657,8 @@ xrdp_mm_process_login_response(struct xrdp_mm *self)
xrdp_wm_log_msg(self->wm, LOG_LEVEL_INFO, "%s",
"Login retry limit reached");
}
xrdp_wm_log_msg(self->wm, LOG_LEVEL_INFO, "%s",
"Close the log window to exit.");
self->wm->fatal_error_in_log_window = 1;
xrdp_mm_logwnd_fatal(self,
ERRINFO_SERVER_INSUFFICIENT_PRIVILEGES);
/* Transport can be deleted now */
self->delete_sesman_trans = 1;
}
@@ -2717,16 +2740,24 @@ xrdp_mm_process_connect_session_response(struct xrdp_mm *self)
rv = scp_get_connect_session_response(self->sesman_trans, &status,
&self->sesman_display_fd,
&self->sesman_chansrv_fd);
/* Following this response, the sesman trans is closed */
self->delete_sesman_trans = 1;
if (rv == 0)
if (rv != 0)
{
self->delete_sesman_trans = 1;
}
else
{
if (status == E_SCP_SCONNECT_OK)
{
xrdp_wm_log_msg(self->wm, LOG_LEVEL_INFO,
"Got connection details for session");
/* Convert the sesman transport fron an SCP transport
* to a CCP transport */
ccp_trans_from_scp_trans(self->sesman_trans,
xrdp_mm_ccp_data_in,
self);
self->sesman_trans_is_ccp = 1;
/* Carry on with the connect state machine */
xrdp_mm_connect_sm(self);
}
@@ -2745,10 +2776,11 @@ xrdp_mm_process_connect_session_response(struct xrdp_mm *self)
xrdp_wm_log_msg(self->wm, LOG_LEVEL_INFO,
"Can't create session for user %s - %s",
username, buff);
xrdp_wm_log_msg(self->wm, LOG_LEVEL_INFO, "%s",
"Close the log window to exit.");
self->wm->fatal_error_in_log_window = 1;
xrdp_mm_logwnd_fatal(self,
ERRINFO_SERVER_DWM_CRASH);
xrdp_wm_mod_connect_done(self->wm, 1);
// The sesman tranport is now useless to us.
self->delete_sesman_trans = 1;
}
}
@@ -2756,7 +2788,7 @@ xrdp_mm_process_connect_session_response(struct xrdp_mm *self)
}
/*****************************************************************************/
/* This is the callback registered for sesman communication replies. */
/* This is the callback registered for sesman communication replies over SCP */
static int
xrdp_mm_scp_data_in(struct trans *trans)
{
@@ -3389,19 +3421,15 @@ xrdp_mm_connect_sm(struct xrdp_mm *self)
if (!self->mmcs_expecting_msg)
{
/* We don't need the sesman transport anymore */
if (self->sesman_trans != NULL)
{
self->delete_sesman_trans = 1;
}
/* Close any uncomsumed file descriptors from sesman */
close_sesman_file_descriptors(self);
xrdp_wm_mod_connect_done(self->wm, status);
/* Make sure the module is cleaned up if we weren't successful */
if (status != 0)
{
self->delete_sesman_trans = 1;
xrdp_mm_module_cleanup(self);
}
}
@@ -3776,35 +3804,44 @@ xrdp_mm_draw_dirty(struct xrdp_mm *self)
int
xrdp_mm_check_wait_objs(struct xrdp_mm *self)
{
int rv;
int rv = 0;
if (self == 0)
{
return 0;
}
rv = 0;
if (self->sesman_trans != NULL &&
!self->delete_sesman_trans &&
self->sesman_trans->status == TRANS_STATUS_UP)
{
if (trans_check_wait_objs(self->sesman_trans) != 0)
{
if (self->mmcs_expecting_msg)
if (self->sesman_trans_is_ccp)
{
/* The sesman transport has failed with an
* outstanding message */
xrdp_wm_log_msg(self->wm, LOG_LEVEL_ERROR,
"Unexpected sesman failure - check sesman log");
xrdp_wm_mod_connect_done(self->wm, 1);
/* Comms with the sesexec has failed - we have to assume
* the session has failed */
xrdp_mm_set_fatal(self, ERRINFO_LOGOFF_BY_USER);
}
else
{
/* We're still using the SCP transport for
* pre-connection activities */
if (self->mmcs_expecting_msg)
{
/* The sesman transport has failed with an
* outstanding message while connecting */
xrdp_wm_log_msg(self->wm, LOG_LEVEL_ERROR, "Unexpected"
" sesman failure - check sesman log");
xrdp_wm_mod_connect_done(self->wm, 1);
}
if (self->wm->hide_log_window)
{
/* if hide_log_window, this is fatal */
rv = 1;
}
}
self->delete_sesman_trans = 1;
if (self->wm->hide_log_window)
{
/* if hide_log_window, this is fatal */
rv = 1;
}
}
}
if (self->delete_sesman_trans)
@@ -3827,9 +3864,12 @@ xrdp_mm_check_wait_objs(struct xrdp_mm *self)
if (self->mod != NULL)
{
if (self->mod->mod_check_wait_objs != NULL)
if (self->mod->mod_check_wait_objs != NULL &&
self->mod->mod_check_wait_objs(self->mod) != 0)
{
rv = self->mod->mod_check_wait_objs(self->mod);
/* Comms with the module has failed - we have to assume
* the display server, and hence the session has failed */
xrdp_mm_set_fatal(self, ERRINFO_LOGOFF_BY_USER);
}
}
@@ -3859,7 +3899,7 @@ xrdp_mm_check_wait_objs(struct xrdp_mm *self)
{
if (self->egfx_up)
{
rv = xrdp_mm_draw_dirty(self);
rv |= xrdp_mm_draw_dirty(self);
xrdp_region_delete(self->wm->screen_dirty_region);
self->wm->screen_dirty_region = NULL;
self->wm->last_screen_draw_time = now;
@@ -5259,7 +5299,7 @@ xrdp_mm_setup_mod2(struct xrdp_mm *self)
self->wm->screen->height,
self->wm->screen->bpp) != 0)
{
g_set_wait_obj(self->wm->pro_layer->self_term_event); /* kill session */
xrdp_mm_set_fatal(self, ERRINFO_SERVER_DWM_CRASH);
}
}
@@ -5269,7 +5309,7 @@ xrdp_mm_setup_mod2(struct xrdp_mm *self)
{
LOG(LOG_LEVEL_ERROR,
"Unexpected display value %d setting up module", self->display);
g_set_wait_obj(self->wm->pro_layer->self_term_event); /* kill session */
xrdp_mm_set_fatal(self, ERRINFO_SERVER_DWM_CRASH);
}
else if (self->code == XVNC_SESSION_CODE)
{
@@ -5285,7 +5325,7 @@ xrdp_mm_setup_mod2(struct xrdp_mm *self)
{
LOG(LOG_LEVEL_ERROR,
"Unexpected session code %d setting up module", self->code);
g_set_wait_obj(self->wm->pro_layer->self_term_event); /* kill session */
xrdp_mm_set_fatal(self, ERRINFO_SERVER_DWM_CRASH);
}
}
@@ -5305,8 +5345,8 @@ xrdp_mm_setup_mod2(struct xrdp_mm *self)
self->mod->mod_set_param(self->mod, "client_info",
(const char *) (self->wm->session->client_info));
name = self->wm->session->client_info->hostname;
self->mod->mod_set_param(self->mod, "hostname", name);
name = self->wm->session->client_info->client_name;
self->mod->mod_set_param(self->mod, "client_name", name);
g_snprintf(text, 255, "%d", self->wm->session->client_info->keylayout);
self->mod->mod_set_param(self->mod, "keylayout", text);
if (guid_is_set(&self->guid))
+107
View File
@@ -0,0 +1,107 @@
/**
* xrdp: A Remote Desktop Protocol server.
*
* Copyright (C) Jay Sorg 2004-2014
*
* 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.
*
* module manager
*/
#if defined(HAVE_CONFIG_H)
#include <config_ac.h>
#endif
#include "ccp.h"
#include "xrdp.h"
#include "log.h"
/*****************************************************************************/
/**
* We've been asked by sesman/sesexec to close the connection
*/
static int
xrdp_mm_process_close_ccp_connection_request(struct xrdp_mm *self)
{
enum ccp_close_reason_type reason;
int rv = ccp_get_close_connection_request(self->sesman_trans, &reason);
if (rv == 0)
{
int errinfo;
char buff[64];
switch (reason)
{
case CCP_CLOSE_RPC_INITIATED_DISCONNECT:
errinfo = ERRINFO_RPC_INITIATED_DISCONNECT;
break;
case CCP_CLOSE_DISCONNECTED_BY_OTHERCONNECTION:
errinfo = ERRINFO_DISCONNECTED_BY_OTHERCONNECTION;
break;
case CCP_CLOSE_LOGOFF_BY_USER:
errinfo = ERRINFO_LOGOFF_BY_USER;
break;
case CCP_CLOSE_SOFTWARE_FAILURE:
errinfo = ERRINFO_SERVER_CSRSS_CRASH;
break;
default:
LOG(LOG_LEVEL_WARNING, "Unexpected close connection reason %d",
(int)reason);
errinfo = ERRINFO_LOGOFF_BY_USER;
}
LOG(LOG_LEVEL_INFO, "Request to close connection : '%s'",
ccp_close_reason_to_str(reason, buff, sizeof(buff)));
xrdp_mm_set_fatal(self, errinfo);
}
return rv;
}
/*****************************************************************************/
int
xrdp_mm_ccp_data_in(struct trans *trans)
{
int rv = 0;
int available;
rv = ccp_msg_in_check_available(trans, &available);
if (rv == 0 && available)
{
struct xrdp_mm *self = (struct xrdp_mm *)(trans->callback_data);
enum ccp_msg_code msgno;
switch ((msgno = ccp_msg_in_get_msgno(trans)))
{
case E_CCP_CLOSE_CONNECTION_REQUEST:
rv = xrdp_mm_process_close_ccp_connection_request(self);
break;
default:
{
char buff[64];
ccp_msgno_to_str(msgno, buff, sizeof(buff));
LOG(LOG_LEVEL_ERROR, "Ignored CCP message %s from sesman",
buff);
}
}
ccp_msg_in_reset(trans);
}
return rv;
}
+2 -2
View File
@@ -295,14 +295,14 @@ xrdp_process_main_loop(struct xrdp_process *self)
}
}
/* send disconnect message if possible */
libxrdp_disconnect(self->session);
libxrdp_disconnect(self->session, self->errinfo);
}
else
{
LOG(LOG_LEVEL_ERROR, "xrdp_process_main_loop: libxrdp_process_incoming failed");
/* this will try to send a disconnect,
maybe should check that connection got far enough */
libxrdp_disconnect(self->session);
libxrdp_disconnect(self->session, self->errinfo);
}
/* Run end in module */
xrdp_process_mod_end(self);
+3
View File
@@ -464,6 +464,8 @@ struct xrdp_mm
int last_sync_saved;
int last_sync_key_flags;
int last_sync_device_flags;
/* Whether the sesman_trans is a CCP trans or not */
int sesman_trans_is_ccp;
};
struct xrdp_key_info
@@ -610,6 +612,7 @@ struct xrdp_process
int status;
struct trans *server_trans; /* in tcp server mode */
tbus self_term_event;
int errinfo; /* Reason for self_term_event being set */
struct xrdp_listen *lis_layer; /* owner */
struct xrdp_session *session;
/* create these when up and running */