summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/smbd/proto.h2
-rw-r--r--source3/smbd/uid.c170
2 files changed, 98 insertions, 74 deletions
diff --git a/source3/smbd/proto.h b/source3/smbd/proto.h
index f4b2e5ef59..75fc5f8341 100644
--- a/source3/smbd/proto.h
+++ b/source3/smbd/proto.h
@@ -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);
diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c
index 7938cc447a..96c4574827 100644
--- a/source3/smbd/uid.c
+++ b/source3/smbd/uid.c
@@ -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);
}
/****************************************************************************