Give privilege to users in TerminalServerAdmins
Revives the currently unused TerminalServerAdmins group. Users in this group will eventually have special privileges for session management. Currently, members of this group will be allowed to list all sessions with the xrdp-sesadmin command.
This commit is contained in:
@@ -36,6 +36,8 @@
|
||||
#include "pre_session_list.h"
|
||||
#include "scp.h"
|
||||
#include "sesman.h"
|
||||
#include "sesman_access.h"
|
||||
#include "sesman_config.h"
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
@@ -79,6 +81,10 @@ process_sys_login_response(struct pre_session_item *psi)
|
||||
psi->client_trans->callback_data = (void *)psi;
|
||||
psi->login_state = E_PS_LOGIN_SYS;
|
||||
psi->uid = uid;
|
||||
// For system logins, don't allow admin access
|
||||
//psi->is_admin = access_login_mng_allowed(&g_cfg->sec,
|
||||
// psi->username);
|
||||
psi->is_admin = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+104
-118
@@ -39,131 +39,90 @@
|
||||
|
||||
/******************************************************************************/
|
||||
/**
|
||||
* Root user login check
|
||||
* user is root
|
||||
*
|
||||
* @param cfg_sec Sesman security config
|
||||
* @param user user name
|
||||
* @return 0 if user is root and root accesses are not allowed
|
||||
* @param username
|
||||
* @return 1 if user is UID 0
|
||||
*/
|
||||
static int
|
||||
root_login_check(const struct config_security *cfg_sec,
|
||||
const char *user)
|
||||
user_is_root(const char *user)
|
||||
{
|
||||
int rv = 0;
|
||||
if (cfg_sec->allow_root)
|
||||
{
|
||||
rv = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Check the UID of the user isn't 0
|
||||
int uid;
|
||||
if (g_getuser_info_by_name(user, &uid, NULL, NULL, NULL, NULL) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "Can't get UID for user %s", user);
|
||||
}
|
||||
else if (0 == uid)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"ROOT login attempted, but root login is disabled");
|
||||
}
|
||||
else
|
||||
{
|
||||
rv = 1;
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/**
|
||||
* Common access control for group checks
|
||||
* @param group Group name
|
||||
* @param param Where group comes from (e.g. "TerminalServerUsers")
|
||||
* @param always_check_group 0 if a missing group allows a login
|
||||
* @param user Username
|
||||
* @return != 0 if the access is allowed */
|
||||
|
||||
static int
|
||||
access_login_allowed_common(const char *group, const char *param,
|
||||
int always_check_group,
|
||||
const char *user)
|
||||
{
|
||||
int rv = 0;
|
||||
int gid;
|
||||
int ok;
|
||||
|
||||
if (group == NULL || group[0] == '\0')
|
||||
{
|
||||
/* Group is not defined. Default access depends on whether
|
||||
* we must have the group or not */
|
||||
if (always_check_group)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"%s group is not defined. Access denied for %s",
|
||||
param, user);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(LOG_LEVEL_INFO,
|
||||
"%s group is not defined. Access granted for %s",
|
||||
param, user);
|
||||
rv = 1;
|
||||
}
|
||||
}
|
||||
else if (g_getgroup_info(group, &gid) != 0)
|
||||
{
|
||||
/* Group is defined but doesn't exist. Default access depends
|
||||
* on whether we must have the group or not */
|
||||
if (always_check_group)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"%s group %s doesn't exist. Access denied for %s",
|
||||
param, group, user);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(LOG_LEVEL_INFO,
|
||||
"%s group %s doesn't exist. Access granted for %s",
|
||||
param, group, user);
|
||||
rv = 1;
|
||||
}
|
||||
}
|
||||
else if (0 != g_check_user_in_group(user, gid, &ok))
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "Error checking %s group %s. "
|
||||
"Access denied for %s", param, group, user);
|
||||
}
|
||||
else if (!ok)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "User %s is not in %s group %s. Access denied",
|
||||
user, param, group);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(LOG_LEVEL_INFO, "User %s is in %s group %s. Access granted",
|
||||
user, param, group);
|
||||
rv = 1;
|
||||
}
|
||||
|
||||
return rv;
|
||||
int uid = -1;
|
||||
(void)g_getuser_info_by_name(user, &uid, NULL, NULL, NULL, NULL);
|
||||
return (uid == 0);
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
int
|
||||
access_login_allowed(const struct config_security *cfg_sec, const char *user)
|
||||
{
|
||||
int rv = 0;
|
||||
int ok = 0;
|
||||
|
||||
if (root_login_check(cfg_sec, user))
|
||||
if (!cfg_sec->allow_root && user_is_root(user))
|
||||
{
|
||||
rv = access_login_allowed_common(cfg_sec->ts_users,
|
||||
"TerminalServerUsers",
|
||||
cfg_sec->ts_always_group_check,
|
||||
user);
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"ROOT login attempted, but root login is disabled");
|
||||
}
|
||||
else
|
||||
{
|
||||
const char *group = cfg_sec->ts_users;
|
||||
const char *param = "TerminalServerUsers";
|
||||
int gid = -1;
|
||||
|
||||
if (group == NULL || group[0] == '\0')
|
||||
{
|
||||
/* Group is not defined. Default access depends on whether
|
||||
* we must have the group or not */
|
||||
if (cfg_sec->ts_always_group_check)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"%s group is not defined. Access denied for %s",
|
||||
param, user);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(LOG_LEVEL_INFO,
|
||||
"%s group is not defined. Access granted for %s",
|
||||
param, user);
|
||||
ok = 1;
|
||||
}
|
||||
}
|
||||
else if (g_getgroup_info(group, &gid) != 0)
|
||||
{
|
||||
/* Group is defined but doesn't exist. Default access depends
|
||||
* on whether we must have the group or not */
|
||||
if (cfg_sec->ts_always_group_check)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"%s group %s doesn't exist. Access denied for %s",
|
||||
param, group, user);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(LOG_LEVEL_INFO,
|
||||
"%s group %s doesn't exist. Access granted for %s",
|
||||
param, group, user);
|
||||
ok = 1;
|
||||
}
|
||||
}
|
||||
else if (0 != g_check_user_in_group(user, gid, &ok))
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "Error checking %s group %s. "
|
||||
"Access denied for %s", param, group, user);
|
||||
}
|
||||
else if (!ok)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "User %s is not in %s group %s. Access denied",
|
||||
user, param, group);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(LOG_LEVEL_INFO, "User %s is in %s group %s. Access granted",
|
||||
user, param, group);
|
||||
}
|
||||
}
|
||||
|
||||
return rv;
|
||||
return ok;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
@@ -171,15 +130,42 @@ int
|
||||
access_login_is_admin(const struct config_security *cfg_sec,
|
||||
const char *user)
|
||||
{
|
||||
int rv = 0;
|
||||
int ok = 0;
|
||||
|
||||
if (root_login_check(cfg_sec, user))
|
||||
const char *group = cfg_sec->ts_admins;
|
||||
const char *param = "TerminalServerAdmins";
|
||||
int gid = -1;
|
||||
|
||||
if (group == NULL || group[0] == '\0')
|
||||
{
|
||||
rv = access_login_allowed_common(cfg_sec->ts_admins,
|
||||
"TerminalServerAdmins",
|
||||
1,
|
||||
user);
|
||||
if (cfg_sec->ts_always_group_check)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "%s group is not defined", param);
|
||||
}
|
||||
}
|
||||
else if (g_getgroup_info(group, &gid) != 0)
|
||||
{
|
||||
/* Group is defined but doesn't exist */
|
||||
if (cfg_sec->ts_always_group_check)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "%s group %s doesn't exist.", param, group);
|
||||
}
|
||||
}
|
||||
else if (0 != g_check_user_in_group(user, gid, &ok))
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "Error checking %s group %s.", param, group);
|
||||
}
|
||||
|
||||
return rv;
|
||||
// Root always has access. Do other checks and logging first
|
||||
if (!ok && user_is_root(user))
|
||||
{
|
||||
ok = 1;
|
||||
}
|
||||
|
||||
if (ok)
|
||||
{
|
||||
LOG(LOG_LEVEL_INFO, "User %s is in %s group %s", user, param, group);
|
||||
}
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
@@ -77,6 +77,7 @@ struct pre_session_item
|
||||
uid_t uid; ///< User
|
||||
char *username; ///< Username from UID (at time of logon)
|
||||
char start_ip_addr[MAX_PEER_ADDRSTRLEN];
|
||||
int is_admin;
|
||||
};
|
||||
|
||||
|
||||
|
||||
+20
-3
@@ -204,11 +204,21 @@ authenticate_and_authorize_uds_connection(struct pre_session_item *psi,
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(LOG_LEVEL_INFO, "Access permitted for user: %s",
|
||||
username);
|
||||
psi->login_state = E_PS_LOGIN_UDS;
|
||||
psi->uid = uid;
|
||||
psi->start_ip_addr[0] = '\0';
|
||||
psi->is_admin = access_login_is_admin(&g_cfg->sec,
|
||||
psi->username);
|
||||
if (psi->is_admin)
|
||||
{
|
||||
LOG(LOG_LEVEL_INFO, "Admin access permitted for user: %s",
|
||||
username);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(LOG_LEVEL_INFO, "Normal access permitted for user: %s",
|
||||
username);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -555,7 +565,14 @@ process_list_sessions_request(struct pre_session_item *psi)
|
||||
"Received request from %s to list sessions for user %s",
|
||||
psi->peername, psi->username);
|
||||
|
||||
info = session_list_get_byuid(psi->uid, &cnt, 0);
|
||||
if (psi->is_admin)
|
||||
{
|
||||
info = session_list_get_byuid(NULL, &cnt, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
info = session_list_get_byuid(&psi->uid, &cnt, 0);
|
||||
}
|
||||
|
||||
for (i = 0; rv == 0 && i < cnt; ++i)
|
||||
{
|
||||
|
||||
@@ -18,7 +18,8 @@ XAuthorityInSystemDir=no
|
||||
TerminalServerUsers=tsusers
|
||||
TerminalServerAdmins=tsadmins
|
||||
; When AlwaysGroupCheck=false access will be permitted
|
||||
; if the group TerminalServerUsers is not defined.
|
||||
; if the group TerminalServerUsers is not defined, and the
|
||||
; non-existence of TerminalServerAdmins will not be reported
|
||||
AlwaysGroupCheck=false
|
||||
; When RestrictOutboundClipboard=all clipboard from the
|
||||
; server is not pushed to the client.
|
||||
|
||||
+11
-4
@@ -438,7 +438,7 @@ session_list_get_bydata(uid_t uid,
|
||||
|
||||
/******************************************************************************/
|
||||
struct scp_session_info *
|
||||
session_list_get_byuid(uid_t uid, unsigned int *cnt, unsigned int flags)
|
||||
session_list_get_byuid(const uid_t *uid, unsigned int *cnt, unsigned int flags)
|
||||
{
|
||||
int i;
|
||||
struct scp_session_info *sess;
|
||||
@@ -447,13 +447,20 @@ session_list_get_byuid(uid_t uid, unsigned int *cnt, unsigned int flags)
|
||||
|
||||
count = 0;
|
||||
|
||||
LOG(LOG_LEVEL_DEBUG, "searching for session by UID: %d", uid);
|
||||
if (uid != NULL)
|
||||
{
|
||||
LOG(LOG_LEVEL_DEBUG, "searching for session by UID: %d", (int)*uid);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(LOG_LEVEL_DEBUG, "searching for all sessions");
|
||||
}
|
||||
|
||||
for (i = 0 ; i < g_session_list->count ; ++i)
|
||||
{
|
||||
const struct session_item *si;
|
||||
si = (const struct session_item *)list_get_item(g_session_list, i);
|
||||
if (SESSION_IN_USE(si) && uid == si->uid)
|
||||
if (SESSION_IN_USE(si) && (uid == NULL || *uid == si->uid))
|
||||
{
|
||||
count++;
|
||||
}
|
||||
@@ -480,7 +487,7 @@ session_list_get_byuid(uid_t uid, unsigned int *cnt, unsigned int flags)
|
||||
const struct session_item *si;
|
||||
si = (const struct session_item *)list_get_item(g_session_list, i);
|
||||
|
||||
if (SESSION_IN_USE(si) && uid == si->uid)
|
||||
if (SESSION_IN_USE(si) && (uid == NULL || *uid == si->uid))
|
||||
{
|
||||
(sess[index]).sid = si->sesexec_pid;
|
||||
(sess[index]).display = si->display;
|
||||
|
||||
@@ -140,7 +140,8 @@ session_list_get_bydata(uid_t uid,
|
||||
|
||||
/**
|
||||
* @brief retrieves session descriptions
|
||||
* @param uid the UID for the descriptions
|
||||
* @param uid the UID for the descriptions by reference, or NULL for
|
||||
* all UIDs
|
||||
* @param[out] cnt The number of sessions returned
|
||||
* @param flags Future expansion
|
||||
* @return A block of session descriptions
|
||||
@@ -149,7 +150,7 @@ session_list_get_bydata(uid_t uid,
|
||||
*
|
||||
*/
|
||||
struct scp_session_info *
|
||||
session_list_get_byuid(uid_t uid, unsigned int *cnt, unsigned int flags);
|
||||
session_list_get_byuid(const uid_t *uid, unsigned int *cnt, unsigned int flags);
|
||||
|
||||
/**
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user