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
The top level socket directory is now called XRDP_SOCKET_ROOT_PATH.
Below that are user-specific directories referred to with the
XRDP_SOCKET_PATH macro - this name is hard-coded into xorgxrdp and
the audio modules as an environment variable.

XRDP_SOCKET_PATH now looks like $XRDP_SOCKET_ROOT_PATH/<uid>

XRDP_SOCKET_PATH is only writeable by the user, and readable by the user
and the xrdp process.
  • Loading branch information
matt335672 committed Oct 23, 2023
1 parent 63235ea commit c295092
Show file tree
Hide file tree
Showing 28 changed files with 221 additions and 116 deletions.
31 changes: 28 additions & 3 deletions common/xrdp_sockets.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,41 @@
#if !defined(XRDP_SOCKETS_H)
#define XRDP_SOCKETS_H

/* basename of socket files */
/* XRDP_SOCKET_ROOT_PATH must be defined to include this file */
#if !defined(XRDP_SOCKET_ROOT_PATH)
# ifdef __cppcheck__
/* avoid syntax errors */
# define XRDP_SOCKET_ROOT_PATH "/dummy"
# else
# error "XRDP_SOCKET_ROOT_PATH must be defined"
# endif
#endif

/* 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

/* The socketdir is rooted at XRDP_SOCKET_ROOT_PATH. User-specific
* sockets live in a user-specific sub-directory of this called
* XRDP_SOCKET_PATH. The sub-directory is the UID of the user */
#define XRDP_SOCKET_PATH XRDP_SOCKET_ROOT_PATH "/%d"

/* Sockets in XRDP_SOCKET_ROOT_PATH */
#define SCP_LISTEN_PORT_BASE_STR "sesman.socket"

/* names of socket files within XRDP_SOCKET_PATH, qualified by
* display number */
#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 */
/* fullpath declarations */
#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
Expand Down
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
1 change: 1 addition & 0 deletions libipm/Makefile.am
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@

AM_CPPFLAGS = \
-DSESMAN_RUNTIME_PATH=\"${sesmanruntimedir}\" \
-DXRDP_SOCKET_ROOT_PATH=\"${socketdir}\" \
-I$(top_srcdir)/common

module_LTLIBRARIES = \
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
2 changes: 1 addition & 1 deletion sesman/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ AM_CPPFLAGS = \
-DXRDP_SBIN_PATH=\"${sbindir}\" \
-DXRDP_LIBEXEC_PATH=\"${libexecdir}/xrdp\" \
-DXRDP_PID_PATH=\"${localstatedir}/run\" \
-DXRDP_SOCKET_PATH=\"${socketdir}\" \
-DXRDP_SOCKET_ROOT_PATH=\"${socketdir}\" \
-DSESMAN_RUNTIME_PATH=\"${sesmanruntimedir}\" \
-I$(top_srcdir)/sesman/libsesman \
-I$(top_srcdir)/common \
Expand Down
2 changes: 1 addition & 1 deletion sesman/chansrv/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ AM_CPPFLAGS = \
-DXRDP_SBIN_PATH=\"${sbindir}\" \
-DXRDP_SHARE_PATH=\"${datadir}/xrdp\" \
-DXRDP_PID_PATH=\"${localstatedir}/run\" \
-DXRDP_SOCKET_PATH=\"${socketdir}\" \
-DXRDP_SOCKET_ROOT_PATH=\"${socketdir}\" \
-I$(top_srcdir)/sesman/libsesman \
-I$(top_srcdir)/common

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
30 changes: 17 additions & 13 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 @@ -312,6 +313,7 @@ config_read_security(int file, struct config_security *sc,
sc->xorg_no_new_privileges = 1;
sc->ts_users = g_strdup("");
sc->ts_admins = g_strdup("");
sc->session_sockdir_group = g_strdup("");

file_read_section(file, SESMAN_CFG_SECURITY, param_n, param_v);

Expand All @@ -324,29 +326,25 @@ config_read_security(int file, struct config_security *sc,
{
sc->allow_root = g_text2bool(value);
}

if (0 == g_strcasecmp(buf, SESMAN_CFG_SEC_LOGIN_RETRY))
else if (0 == g_strcasecmp(buf, SESMAN_CFG_SEC_LOGIN_RETRY))
{
sc->login_retry = g_atoi(value);
}

if (0 == g_strcasecmp(buf, SESMAN_CFG_SEC_USR_GROUP))
else if (0 == g_strcasecmp(buf, SESMAN_CFG_SEC_USR_GROUP))
{
g_free(sc->ts_users);
sc->ts_users = g_strdup(value);
}

if (0 == g_strcasecmp(buf, SESMAN_CFG_SEC_ADM_GROUP))
else if (0 == g_strcasecmp(buf, SESMAN_CFG_SEC_ADM_GROUP))
{
g_free(sc->ts_admins);
sc->ts_admins = g_strdup(value);
}
if (0 == g_strcasecmp(buf, SESMAN_CFG_SEC_ALWAYSGROUPCHECK))
else if (0 == g_strcasecmp(buf, SESMAN_CFG_SEC_ALWAYSGROUPCHECK))
{
sc->ts_always_group_check = g_text2bool(value);
}

if (0 == g_strcasecmp(buf, SESMAN_CFG_SEC_RESTRICT_OUTBOUND_CLIPBOARD))
else if (0 == g_strcasecmp(buf, SESMAN_CFG_SEC_RESTRICT_OUTBOUND_CLIPBOARD))
{
char unrecognised[256];
sc->restrict_outbound_clipboard =
Expand All @@ -360,7 +358,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(buf, SESMAN_CFG_SEC_RESTRICT_INBOUND_CLIPBOARD))
{
char unrecognised[256];
sc->restrict_inbound_clipboard =
Expand All @@ -374,17 +372,21 @@ 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(buf, SESMAN_CFG_SEC_ALLOW_ALTERNATE_SHELL))
{
sc->allow_alternate_shell =
g_text2bool(value);
}

if (0 == g_strcasecmp(buf, SESMAN_CFG_SEC_XORG_NO_NEW_PRIVILEGES))
else if (0 == g_strcasecmp(buf, SESMAN_CFG_SEC_XORG_NO_NEW_PRIVILEGES))
{
sc->xorg_no_new_privileges =
g_text2bool(value);
}
else if (0 == g_strcasecmp(buf, SESMAN_CFG_SEC_SESSION_SOCKDIR_GROUP))
{
g_free(sc->session_sockdir_group);
sc->session_sockdir_group = g_strdup(value);
}
}

return 0;
Expand Down Expand Up @@ -684,6 +686,7 @@ config_dump(struct config_sesman *config)
g_writeln(" RestrictInboundClipboard: %s", restrict_s);
g_writeln(" TSUsersGroup: %s", sc->ts_users);
g_writeln(" TSAdminsGroup: %s", sc->ts_admins);
g_writeln(" SessionSockdirGroup: %s", sc->session_sockdir_group);


/* Xorg */
Expand Down Expand Up @@ -741,6 +744,7 @@ config_free(struct config_sesman *cs)
list_delete(cs->env_values);
g_free(cs->sec.ts_users);
g_free(cs->sec.ts_admins);
g_free(cs->sec.session_sockdir_group);
g_free(cs);
}
}
6 changes: 6 additions & 0 deletions sesman/libsesman/sesman_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,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
*/
char *session_sockdir_group;
};

/**
Expand Down
Loading

0 comments on commit c295092

Please sign in to comment.