Skip to content

Commit

Permalink
Parameterise the sockdir with the UID of the user
Browse files Browse the repository at this point in the history
xrdp sockets are now all created by user processes. These changes
move the sockets into a directory below XRDP_SOCKET_PATH which
is only writeable by the user, and readable by the user and the
xrdp process.
  • Loading branch information
matt335672 committed Jun 14, 2023
1 parent d921afb commit cba94ba
Show file tree
Hide file tree
Showing 20 changed files with 211 additions and 123 deletions.
22 changes: 15 additions & 7 deletions common/xrdp_sockets.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,21 +21,29 @@
#if !defined(XRDP_SOCKETS_H)
#define XRDP_SOCKETS_H

/* Buffer size for code for fullpath declarations
*
* This needs to fit in the sun_path field of a sockaddr_un. POSIX
* does not define this size, so the value below is the lower of
* the FreeBSD/OpenBSD/NetBSD(104) and Linux(108) values */
#define XRDP_SOCKETS_MAXPATH 104

/* basename of socket files */
#define XRDP_CHANSRV_BASE_STR "xrdp_chansrv_socket_%d"
#define CHANSRV_PORT_OUT_BASE_STR "xrdp_chansrv_audio_out_socket_%d"
#define CHANSRV_PORT_IN_BASE_STR "xrdp_chansrv_audio_in_socket_%d"
#define CHANSRV_API_BASE_STR "xrdpapi_%d"
#define XRDP_X11RDP_BASE_STR "xrdp_display_%d"
#define XRDP_DISCONNECT_BASE_STR "xrdp_disconnect_display_%d"

#define SCP_LISTEN_PORT_BASE_STR "sesman.socket"

/* fullpath of sockets */
#define XRDP_CHANSRV_STR XRDP_SOCKET_PATH "/" XRDP_CHANSRV_BASE_STR
#define CHANSRV_PORT_OUT_STR XRDP_SOCKET_PATH "/" CHANSRV_PORT_OUT_BASE_STR
#define CHANSRV_PORT_IN_STR XRDP_SOCKET_PATH "/" CHANSRV_PORT_IN_BASE_STR
#define CHANSRV_API_STR XRDP_SOCKET_PATH "/" CHANSRV_API_BASE_STR
#define XRDP_X11RDP_STR XRDP_SOCKET_PATH "/" XRDP_X11RDP_BASE_STR
#define XRDP_DISCONNECT_STR XRDP_SOCKET_PATH "/" XRDP_DISCONNECT_BASE_STR
/* fullpath of sockdir sockets */
#define XRDP_CHANSRV_STR XRDP_SOCKET_PATH "/%d/" XRDP_CHANSRV_BASE_STR
#define CHANSRV_PORT_OUT_STR XRDP_SOCKET_PATH "/%d/" CHANSRV_PORT_OUT_BASE_STR
#define CHANSRV_PORT_IN_STR XRDP_SOCKET_PATH "/%d/" CHANSRV_PORT_IN_BASE_STR
#define CHANSRV_API_STR XRDP_SOCKET_PATH "/%d/" CHANSRV_API_BASE_STR
#define XRDP_X11RDP_STR XRDP_SOCKET_PATH "/%d/" XRDP_X11RDP_BASE_STR
#define XRDP_DISCONNECT_STR XRDP_SOCKET_PATH "/%d/" XRDP_DISCONNECT_BASE_STR

#endif
5 changes: 5 additions & 0 deletions docs/man/sesman.ini.5.in
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,11 @@ to a setuid Xorg executable. However, if a kernel security module (such as
AppArmor) is used to confine xrdp, \fIno_new_privs\fR may interfere with
transitions between confinement domains.

.TP
\fBSessionSockdirGroup\fR=\fIgroup\fR
Sets the group owner of the directories containing session sockets. This
is normally the GID of the xrdp process so xrdp can connect to user sessions.

.SH "X11 SERVER"
Following parameters can be used in the \fB[Xvnc]\fR and
\fB[Xorg]\fR sections.
Expand Down
25 changes: 19 additions & 6 deletions libipm/scp.c
Original file line number Diff line number Diff line change
Expand Up @@ -332,37 +332,50 @@ scp_get_sys_login_request(struct trans *trans,
int
scp_send_login_response(struct trans *trans,
enum scp_login_status login_result,
int server_closed)
int server_closed,
int uid)
{
return libipm_msg_out_simple_send(
trans,
(int)E_SCP_LOGIN_RESPONSE,
"ib",
"ibi",
login_result,
(server_closed != 0)); /* Convert to 0/1 */
(server_closed != 0), /* Convert to 0/1 */
uid);
}

/*****************************************************************************/

int
scp_get_login_response(struct trans *trans,
enum scp_login_status *login_result,
int *server_closed)
int *server_closed,
int *uid)
{
int32_t i_login_result = 0;
int32_t i_uid = 0;
int dummy;

/* User can pass in NULL for server_closed if they're trying an
* login method like UDS for which all fails are fatal */
* login method like UDS for which all fails are fatal. Likewise
* they may be uninterested in the uid */
if (server_closed == NULL)
{
server_closed = &dummy;
}
if (uid == NULL)
{
uid = &dummy;
}

int rv = libipm_msg_in_parse(trans, "ib", &i_login_result, server_closed);
int rv = libipm_msg_in_parse(trans, "ibi",
&i_login_result, server_closed, &i_uid);
if (rv == 0)
{
*login_result = (enum scp_login_status)i_login_result;
*uid = i_uid;
}

return rv;
}

Expand Down
11 changes: 9 additions & 2 deletions libipm/scp.h
Original file line number Diff line number Diff line change
Expand Up @@ -284,12 +284,14 @@ scp_get_sys_login_request(struct trans *trans,
* @param login_result What happened to the login
* @param server_closed If login fails, whether server has closed connection.
* If not, a retry can be made.
* @param uid UID for a successful login
* @return != 0 for error
*/
int
scp_send_login_response(struct trans *trans,
enum scp_login_status login_result,
int server_closed);
int server_closed,
int uid);

/**
* Parses an incoming E_SCP_LOGIN_RESPONSE (SCP client)
Expand All @@ -298,12 +300,17 @@ scp_send_login_response(struct trans *trans,
* @param[out] login_result 0 for success, PAM error code otherwise
* @param[out] server_closed If login fails, whether server has closed
* connection. If not a retry can be made.
* @param[out] uid UID for a successful login
*
* server_closed and uid can be passed NULL if the caller isn't interested.
*
* @return != 0 for error
*/
int
scp_get_login_response(struct trans *trans,
enum scp_login_status *login_result,
int *server_closed);
int *server_closed,
int *uid);

/**
* Send an E_SCP_LOGOUT_REQUEST (SCP client)
Expand Down
8 changes: 4 additions & 4 deletions sesman/chansrv/chansrv.c
Original file line number Diff line number Diff line change
Expand Up @@ -1238,7 +1238,7 @@ my_api_trans_conn_in(struct trans *trans, struct trans *new_trans)
static int
setup_listen(void)
{
char port[256];
char port[XRDP_SOCKETS_MAXPATH];
int error = 0;

if (g_lis_trans != 0)
Expand All @@ -1248,7 +1248,7 @@ setup_listen(void)

g_lis_trans = trans_create(TRANS_MODE_UNIX, 8192, 8192);
g_lis_trans->is_term = g_is_term;
g_snprintf(port, 255, XRDP_CHANSRV_STR, g_display_num);
g_snprintf(port, sizeof(port), XRDP_CHANSRV_STR, g_getuid(), g_display_num);

g_lis_trans->trans_conn_in = my_trans_conn_in;
error = trans_listen(g_lis_trans, port);
Expand All @@ -1267,12 +1267,12 @@ setup_listen(void)
static int
setup_api_listen(void)
{
char port[256];
char port[XRDP_SOCKETS_MAXPATH];
int error = 0;

g_api_lis_trans = trans_create(TRANS_MODE_UNIX, 8192 * 4, 8192 * 4);
g_api_lis_trans->is_term = g_is_term;
g_snprintf(port, 255, CHANSRV_API_STR, g_display_num);
g_snprintf(port, sizeof(port), CHANSRV_API_STR, g_getuid(), g_display_num);
g_api_lis_trans->trans_conn_in = my_api_trans_conn_in;
error = trans_listen(g_api_lis_trans, port);

Expand Down
8 changes: 4 additions & 4 deletions sesman/chansrv/sound.c
Original file line number Diff line number Diff line change
Expand Up @@ -1894,11 +1894,11 @@ sound_sndsrvr_source_data_in(struct trans *trans)
static int
sound_start_source_listener(void)
{
char port[1024];
char port[XRDP_SOCKETS_MAXPATH];

g_audio_l_trans_in = trans_create(TRANS_MODE_UNIX, 128 * 1024, 8192);
g_audio_l_trans_in->is_term = g_is_term;
g_snprintf(port, 255, CHANSRV_PORT_IN_STR, g_display_num);
g_snprintf(port, sizeof(port), CHANSRV_PORT_IN_STR, g_getuid(), g_display_num);
g_audio_l_trans_in->trans_conn_in = sound_sndsrvr_source_conn_in;
if (trans_listen(g_audio_l_trans_in, port) != 0)
{
Expand All @@ -1913,11 +1913,11 @@ sound_start_source_listener(void)
static int
sound_start_sink_listener(void)
{
char port[1024];
char port[XRDP_SOCKETS_MAXPATH];

g_audio_l_trans_out = trans_create(TRANS_MODE_UNIX, 128 * 1024, 8192);
g_audio_l_trans_out->is_term = g_is_term;
g_snprintf(port, 255, CHANSRV_PORT_OUT_STR, g_display_num);
g_snprintf(port, sizeof(port), CHANSRV_PORT_OUT_STR, g_getuid(), g_display_num);
g_audio_l_trans_out->trans_conn_in = sound_sndsrvr_sink_conn_in;
if (trans_listen(g_audio_l_trans_out, port) != 0)
{
Expand Down
58 changes: 33 additions & 25 deletions sesman/libsesman/sesman_config.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@
#define SESMAN_CFG_SEC_RESTRICT_INBOUND_CLIPBOARD "RestrictInboundClipboard"
#define SESMAN_CFG_SEC_ALLOW_ALTERNATE_SHELL "AllowAlternateShell"
#define SESMAN_CFG_SEC_XORG_NO_NEW_PRIVILEGES "XorgNoNewPrivileges"
#define SESMAN_CFG_SEC_SESSION_SOCKDIR_GROUP "SessionSockdirGroup"

#define SESMAN_CFG_SESSIONS "Sessions"
#define SESMAN_CFG_SESS_MAX "MaxSessions"
Expand Down Expand Up @@ -298,7 +299,6 @@ config_read_security(int file, struct config_security *sc,
{
int i;
int gid;
char *buf;

list_clear(param_v);
list_clear(param_n);
Expand All @@ -312,46 +312,44 @@ config_read_security(int file, struct config_security *sc,
sc->restrict_inbound_clipboard = 0;
sc->allow_alternate_shell = 1;
sc->xorg_no_new_privileges = 1;
sc->session_sockdir_group = 0;

file_read_section(file, SESMAN_CFG_SECURITY, param_n, param_v);

for (i = 0; i < param_n->count; i++)
{
buf = (char *)list_get_item(param_n, i);
const char *param = (const char *)list_get_item(param_n, i);
const char *val = (const char *)list_get_item(param_v, i);

if (0 == g_strcasecmp(buf, SESMAN_CFG_SEC_ALLOW_ROOT))
if (0 == g_strcasecmp(param, SESMAN_CFG_SEC_ALLOW_ROOT))
{
sc->allow_root = g_text2bool((char *)list_get_item(param_v, i));
sc->allow_root = g_text2bool(val);
}

if (0 == g_strcasecmp(buf, SESMAN_CFG_SEC_LOGIN_RETRY))
else if (0 == g_strcasecmp(param, SESMAN_CFG_SEC_LOGIN_RETRY))
{
sc->login_retry = g_atoi((char *)list_get_item(param_v, i));
sc->login_retry = g_atoi(val);
}

if (0 == g_strcasecmp(buf, SESMAN_CFG_SEC_USR_GROUP))
else if (0 == g_strcasecmp(param, SESMAN_CFG_SEC_USR_GROUP))
{
if (g_getgroup_info((char *)list_get_item(param_v, i), &gid) == 0)
if (g_getgroup_info(val, &gid) == 0)
{
sc->ts_users_enable = 1;
sc->ts_users = gid;
}
}

if (0 == g_strcasecmp(buf, SESMAN_CFG_SEC_ADM_GROUP))
else if (0 == g_strcasecmp(param, SESMAN_CFG_SEC_ADM_GROUP))
{
if (g_getgroup_info((char *)list_get_item(param_v, i), &gid) == 0)
if (g_getgroup_info(val, &gid) == 0)
{
sc->ts_admins_enable = 1;
sc->ts_admins = gid;
}
}
if (0 == g_strcasecmp(buf, SESMAN_CFG_SEC_ALWAYSGROUPCHECK))
else if (0 == g_strcasecmp(param, SESMAN_CFG_SEC_ALWAYSGROUPCHECK))
{
sc->ts_always_group_check = g_text2bool((char *)list_get_item(param_v, i));
sc->ts_always_group_check = g_text2bool(val);
}

if (0 == g_strcasecmp(buf, SESMAN_CFG_SEC_RESTRICT_OUTBOUND_CLIPBOARD))
else if (0 == g_strcasecmp(param, SESMAN_CFG_SEC_RESTRICT_OUTBOUND_CLIPBOARD))
{
char unrecognised[256];
sc->restrict_outbound_clipboard =
Expand All @@ -365,7 +363,7 @@ config_read_security(int file, struct config_security *sc,
unrecognised);
}
}
if (0 == g_strcasecmp(buf, SESMAN_CFG_SEC_RESTRICT_INBOUND_CLIPBOARD))
else if (0 == g_strcasecmp(param, SESMAN_CFG_SEC_RESTRICT_INBOUND_CLIPBOARD))
{
char unrecognised[256];
sc->restrict_inbound_clipboard =
Expand All @@ -379,16 +377,26 @@ config_read_security(int file, struct config_security *sc,
unrecognised);
}
}
if (0 == g_strcasecmp(buf, SESMAN_CFG_SEC_ALLOW_ALTERNATE_SHELL))
else if (0 == g_strcasecmp(param, SESMAN_CFG_SEC_ALLOW_ALTERNATE_SHELL))
{
sc->allow_alternate_shell =
g_text2bool((char *)list_get_item(param_v, i));
sc->allow_alternate_shell = g_text2bool(val);
}

if (0 == g_strcasecmp(buf, SESMAN_CFG_SEC_XORG_NO_NEW_PRIVILEGES))
else if (0 == g_strcasecmp(param, SESMAN_CFG_SEC_XORG_NO_NEW_PRIVILEGES))
{
sc->xorg_no_new_privileges =
g_text2bool((char *)list_get_item(param_v, i));
sc->xorg_no_new_privileges = g_text2bool(val);
}
else if (0 == g_strcasecmp(param, SESMAN_CFG_SEC_SESSION_SOCKDIR_GROUP))
{
if (g_getgroup_info(val, &gid) == 0)
{
sc->session_sockdir_group = gid;
}
else
{
LOG(LOG_LEVEL_WARNING,
"Group '%s' is not recognised - using group %d",
val, sc->session_sockdir_group);
}
}
}

Expand Down
6 changes: 6 additions & 0 deletions sesman/libsesman/sesman_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,12 @@ struct config_security
* @brief if the Xorg X11 server should be started with no_new_privs (Linux only)
*/
int xorg_no_new_privileges;

/*
* @var session_sockdir_group
* @brief Group to have read access to the session sockdirs
*/
int session_sockdir_group;
};

/**
Expand Down
Loading

0 comments on commit cba94ba

Please sign in to comment.