Merge pull request #3567 from matt335672/close_on_reconnect
Close on reconnect
This commit is contained in:
+13
-21
@@ -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
|
||||
|
||||
@@ -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
@@ -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)
|
||||
|
||||
@@ -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
@@ -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
@@ -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 */
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
@@ -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
@@ -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 */
|
||||
|
||||
@@ -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
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
/**
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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);
|
||||
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 \
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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(
|
||||
|
||||
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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
@@ -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");
|
||||
}
|
||||
|
||||
@@ -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
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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 \
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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
@@ -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))
|
||||
|
||||
@@ -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
@@ -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);
|
||||
|
||||
@@ -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 */
|
||||
|
||||
Reference in New Issue
Block a user