1
0
mirror of https://github.com/samba-team/samba.git synced 2025-03-03 12:58:35 +03:00

s3-smbd: Added a change_to_user_by_session() function.

Signed-off-by: Jeremy Allison <jra@samba.org>
This commit is contained in:
Andreas Schneider 2011-04-05 13:54:31 +02:00 committed by Jeremy Allison
parent d1ded271b6
commit 27cb378283
2 changed files with 98 additions and 74 deletions

View File

@ -1050,6 +1050,8 @@ void reply_transs2(struct smb_request *req);
bool change_to_guest(void);
void conn_clear_vuid_cache(connection_struct *conn, uint16_t vuid);
bool change_to_user(connection_struct *conn, uint16 vuid);
bool change_to_user_by_session(connection_struct *conn,
const struct auth_serversupplied_info *session_info);
bool change_to_root_user(void);
bool become_authenticated_pipe_user(struct pipes_struct *p);
bool unbecome_authenticated_pipe_user(void);

View File

@ -231,104 +231,54 @@ void conn_clear_vuid_cache(connection_struct *conn, uint16_t vuid)
stack, but modify the current_user entries.
****************************************************************************/
bool change_to_user(connection_struct *conn, uint16 vuid)
static bool change_to_user_internal(connection_struct *conn,
const struct auth_serversupplied_info *session_info,
uint16_t vuid)
{
const struct auth_serversupplied_info *session_info = NULL;
user_struct *vuser;
int snum;
gid_t gid;
uid_t uid;
char group_c;
int num_groups = 0;
gid_t *group_list = NULL;
if (!conn) {
DEBUG(2,("change_to_user: Connection not open\n"));
return(False);
}
vuser = get_valid_user_struct(conn->sconn, vuid);
/*
* We need a separate check in security=share mode due to vuid
* always being UID_FIELD_INVALID. If we don't do this then
* in share mode security we are *always* changing uid's between
* SMB's - this hurts performance - Badly.
*/
if((lp_security() == SEC_SHARE) && (current_user.conn == conn) &&
(current_user.ut.uid == conn->session_info->utok.uid)) {
DEBUG(4,("change_to_user: Skipping user change - already "
"user\n"));
return(True);
} else if ((current_user.conn == conn) &&
(vuser != NULL) && (current_user.vuid == vuid) &&
(current_user.ut.uid == vuser->session_info->utok.uid)) {
DEBUG(4,("change_to_user: Skipping user change - already "
"user\n"));
return(True);
}
bool ok;
snum = SNUM(conn);
session_info = vuser ? vuser->session_info : conn->session_info;
if (!session_info) {
/* Invalid vuid sent - even with security = share. */
DEBUG(2,("change_to_user: Invalid vuid %d used on "
"share %s.\n",vuid, lp_servicename(snum) ));
return false;
}
if (!check_user_ok(conn, vuid, session_info, snum)) {
DEBUG(2,("change_to_user: SMB user %s (unix user %s, vuid %d) "
ok = check_user_ok(conn, vuid, session_info, snum);
if (!ok) {
DEBUG(2,("SMB user %s (unix user %s) "
"not permitted access to share %s.\n",
session_info->sanitized_username,
session_info->unix_name, vuid,
session_info->unix_name,
lp_servicename(snum)));
return false;
}
/* security = share sets force_user. */
if (!conn->force_user && !vuser) {
DEBUG(2,("change_to_user: Invalid vuid used %d in accessing "
"share %s.\n",vuid, lp_servicename(snum) ));
return False;
}
/*
* conn->session_info is now correctly set up with a copy we can mess
* with for force_group etc.
*/
uid = conn->session_info->utok.uid;
gid = conn->session_info->utok.gid;
num_groups = conn->session_info->utok.ngroups;
group_list = conn->session_info->utok.groups;
/*
* See if we should force group for this service.
* If so this overrides any group set in the force
* user code.
* See if we should force group for this service. If so this overrides
* any group set in the force user code.
*/
if((group_c = *lp_force_group(snum))) {
SMB_ASSERT(conn->force_group_gid != (gid_t)-1);
if(group_c == '+') {
if (group_c == '+') {
int i;
/*
* Only force group if the user is a member of
* the service group. Check the group memberships for
* this user (we already have this) to
* see if we should force the group.
* Only force group if the user is a member of the
* service group. Check the group memberships for this
* user (we already have this) to see if we should force
* the group.
*/
int i;
for (i = 0; i < num_groups; i++) {
if (group_list[i]
== conn->force_group_gid) {
if (group_list[i] == conn->force_group_gid) {
conn->session_info->utok.gid =
conn->force_group_gid;
gid = conn->force_group_gid;
@ -345,22 +295,94 @@ bool change_to_user(connection_struct *conn, uint16 vuid)
}
}
/* Now set current_user since we will immediately also call
set_sec_ctx() */
/*Set current_user since we will immediately also call set_sec_ctx() */
current_user.ut.ngroups = num_groups;
current_user.ut.groups = group_list;
set_sec_ctx(uid, gid, current_user.ut.ngroups, current_user.ut.groups,
set_sec_ctx(uid,
gid,
current_user.ut.ngroups,
current_user.ut.groups,
conn->session_info->security_token);
current_user.conn = conn;
current_user.vuid = vuid;
DEBUG(5,("change_to_user uid=(%d,%d) gid=(%d,%d)\n",
(int)getuid(),(int)geteuid(),(int)getgid(),(int)getegid()));
DEBUG(5, ("Impersonated user: uid=(%d,%d), gid=(%d,%d)\n",
(int)getuid(),
(int)geteuid(),
(int)getgid(),
(int)getegid()));
return(True);
return true;
}
bool change_to_user(connection_struct *conn, uint16_t vuid)
{
const struct auth_serversupplied_info *session_info = NULL;
user_struct *vuser;
int snum = SNUM(conn);
if (!conn) {
DEBUG(2,("Connection not open\n"));
return(False);
}
vuser = get_valid_user_struct(conn->sconn, vuid);
/*
* We need a separate check in security=share mode due to vuid
* always being UID_FIELD_INVALID. If we don't do this then
* in share mode security we are *always* changing uid's between
* SMB's - this hurts performance - Badly.
*/
if((lp_security() == SEC_SHARE) && (current_user.conn == conn) &&
(current_user.ut.uid == conn->session_info->utok.uid)) {
DEBUG(4,("Skipping user change - already "
"user\n"));
return(True);
} else if ((current_user.conn == conn) &&
(vuser != NULL) && (current_user.vuid == vuid) &&
(current_user.ut.uid == vuser->session_info->utok.uid)) {
DEBUG(4,("Skipping user change - already "
"user\n"));
return(True);
}
session_info = vuser ? vuser->session_info : conn->session_info;
if (session_info == NULL) {
/* Invalid vuid sent - even with security = share. */
DEBUG(2,("Invalid vuid %d used on "
"share %s.\n", vuid, lp_servicename(snum) ));
return false;
}
/* security = share sets force_user. */
if (!conn->force_user && vuser == NULL) {
DEBUG(2,("Invalid vuid used %d in accessing "
"share %s.\n", vuid, lp_servicename(snum) ));
return False;
}
return change_to_user_internal(conn, session_info, vuid);
}
bool change_to_user_by_session(connection_struct *conn,
const struct auth_serversupplied_info *session_info)
{
SMB_ASSERT(conn != NULL);
SMB_ASSERT(session_info != NULL);
if ((current_user.conn == conn) &&
(current_user.ut.uid == session_info->utok.uid)) {
DEBUG(7, ("Skipping user change - already user\n"));
return true;
}
return change_to_user_internal(conn, session_info, UID_FIELD_INVALID);
}
/****************************************************************************