static bool change_to_user_internal(connection_struct *conn, const struct auth_serversupplied_info *session_info, uint16_t vuid) { int snum; gid_t gid; uid_t uid; char group_c; int num_groups = 0; gid_t *group_list = NULL; bool ok; snum = SNUM(conn); 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, lp_servicename(snum))); return false; } 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. */ if((group_c = *lp_force_group(snum))) { SMB_ASSERT(conn->force_group_gid != (gid_t)-1); 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. */ for (i = 0; i < num_groups; i++) { if (group_list[i] == conn->force_group_gid) { conn->session_info->utok.gid = conn->force_group_gid; gid = conn->force_group_gid; gid_to_sid(&conn->session_info->security_token ->sids[1], gid); break; } } } else { conn->session_info->utok.gid = conn->force_group_gid; gid = conn->force_group_gid; gid_to_sid(&conn->session_info->security_token->sids[1], gid); } } /*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, conn->session_info->security_token); current_user.conn = conn; current_user.vuid = vuid; DEBUG(5, ("Impersonated user: uid=(%d,%d), gid=(%d,%d)\n", (int)getuid(), (int)geteuid(), (int)getgid(), (int)getegid())); return true; }
BOOL change_to_user(connection_struct *conn, uint16 vuid) { user_struct *vuser = get_valid_user_struct(vuid); int snum; gid_t gid; uid_t uid; char group_c; BOOL must_free_token = False; NT_USER_TOKEN *token = NULL; if (!conn) { DEBUG(2,("change_to_user: Connection not open\n")); return(False); } /* * 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.uid == conn->uid)) { DEBUG(4,("change_to_user: Skipping user change - already user\n")); return(True); } else if ((current_user.conn == conn) && (vuser != 0) && (current_user.vuid == vuid) && (current_user.uid == vuser->uid)) { DEBUG(4,("change_to_user: Skipping user change - already user\n")); return True; } snum = SNUM(conn); if((vuser != NULL) && !check_user_ok(conn, vuser, snum)) return False; if (conn->force_user || conn->admin_user || (lp_security() == SEC_SHARE)) { uid = conn->uid; gid = conn->gid; current_user.groups = conn->groups; current_user.ngroups = conn->ngroups; token = conn->nt_user_token; } else { if (!vuser) { DEBUG(2,("change_to_user: Invalid vuid used %d\n",vuid)); return(False); } uid = vuser->uid; gid = vuser->gid; current_user.ngroups = vuser->n_groups; current_user.groups = vuser->groups; token = vuser->nt_user_token; } /* * 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))) { BOOL is_guest = False; if(group_c == '+') { /* * 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 < current_user.ngroups; i++) { if (current_user.groups[i] == conn->gid) { gid = conn->gid; break; } } } else { gid = conn->gid; } /* * We've changed the group list in the token - we must * re-create it. */ if (vuser && vuser->guest) is_guest = True; token = create_nt_token(uid, gid, current_user.ngroups, current_user.groups, is_guest, NULL); must_free_token = True; } set_sec_ctx(uid, gid, current_user.ngroups, current_user.groups, token); /* * Free the new token (as set_sec_ctx copies it). */ if (must_free_token) delete_nt_token(&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())); return(True); }
BOOL change_to_user(connection_struct *conn, uint16 vuid) { user_struct *vuser = get_valid_user_struct(vuid); int snum; gid_t gid; uid_t uid; char group_c; BOOL must_free_token = False; NT_USER_TOKEN *token = NULL; if (!conn) { DEBUG(2,("change_to_user: Connection not open\n")); return(False); } /* * 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->uid)) { DEBUG(4,("change_to_user: Skipping user change - already " "user\n")); return(True); } else if ((current_user.conn == conn) && (vuser != 0) && (current_user.vuid == vuid) && (current_user.ut.uid == vuser->uid)) { DEBUG(4,("change_to_user: Skipping user change - already " "user\n")); return(True); } snum = SNUM(conn); if ((vuser) && !check_user_ok(conn, vuser, snum)) { DEBUG(2,("change_to_user: SMB user %s (unix user %s, vuid %d) " "not permitted access to share %s.\n", vuser->user.smb_name, vuser->user.unix_name, vuid, lp_servicename(snum))); return False; } if (conn->force_user) /* security = share sets this too */ { uid = conn->uid; gid = conn->gid; current_user.ut.groups = conn->groups; current_user.ut.ngroups = conn->ngroups; token = conn->nt_user_token; } else if (vuser) { uid = conn->admin_user ? 0 : vuser->uid; gid = vuser->gid; current_user.ut.ngroups = vuser->n_groups; current_user.ut.groups = vuser->groups; token = vuser->nt_user_token; } else { DEBUG(2,("change_to_user: Invalid vuid used %d in accessing " "share %s.\n",vuid, lp_servicename(snum) )); return False; } /* * 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))) { token = dup_nt_token(NULL, token); if (token == NULL) { DEBUG(0, ("dup_nt_token failed\n")); return False; } must_free_token = True; if(group_c == '+') { /* * 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 < current_user.ut.ngroups; i++) { if (current_user.ut.groups[i] == conn->gid) { gid = conn->gid; gid_to_sid(&token->user_sids[1], gid); break; } } } else { gid = conn->gid; gid_to_sid(&token->user_sids[1], gid); } } set_sec_ctx(uid, gid, current_user.ut.ngroups, current_user.ut.groups, token); /* * Free the new token (as set_sec_ctx copies it). */ if (must_free_token) TALLOC_FREE(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())); return(True); }