From f3c03aaa62724b6e215984849263cc0839a718cc Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Sun, 13 Dec 2015 11:31:06 +0000 Subject: [PATCH] several changes to region and land access control - this may be a bit broken now --- OpenSim/Region/Framework/Scenes/Scene.cs | 390 +++++++++++------------ 1 file changed, 192 insertions(+), 198 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 9061244c64..97b11c7871 100755 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -4060,7 +4060,6 @@ namespace OpenSim.Region.Framework.Scenes return false; } - ILandObject land; ScenePresence sp; lock (m_removeClientLock) @@ -4166,28 +4165,19 @@ namespace OpenSim.Region.Framework.Scenes // If the checks fail, we remove the circuit. acd.teleportFlags = teleportFlags; - // Remove any preexisting circuit - we don't want duplicates - // This is a stab at preventing avatar "ghosting" - if (vialogin) - m_authenticateHandler.RemoveCircuit(acd.AgentID); - - m_authenticateHandler.AddNewCircuit(acd.circuitcode, acd); - - land = LandChannel.GetLandObject(acd.startpos.X, acd.startpos.Y); - - // On login test land permisions if (vialogin) { IUserAccountCacheModule cache = RequestModuleInterface(); if (cache != null) cache.Remove(acd.firstname + " " + acd.lastname); - if (land != null && !TestLandRestrictions(acd.AgentID, out reason, ref acd.startpos.X, ref acd.startpos.Y)) - { - m_authenticateHandler.RemoveCircuit(acd.circuitcode); - return false; - } + + // Remove any preexisting circuit - we don't want duplicates + // This is a stab at preventing avatar "ghosting" + m_authenticateHandler.RemoveCircuit(acd.AgentID); } + m_authenticateHandler.AddNewCircuit(acd.circuitcode, acd); + if (sp == null) // We don't have an [child] agent here already { if (requirePresenceLookup) @@ -4271,92 +4261,41 @@ namespace OpenSim.Region.Framework.Scenes CapsModule.ActivateCaps(acd.circuitcode); } - if (vialogin) - { +// if (vialogin) +// { // CleanDroppedAttachments(); +// } - // Make sure avatar position is in the region (why it wouldn't be is a mystery but do sanity checking) - if (acd.startpos.X < 0) acd.startpos.X = 1f; - if (acd.startpos.X >= RegionInfo.RegionSizeX) acd.startpos.X = RegionInfo.RegionSizeX - 1f; - if (acd.startpos.Y < 0) acd.startpos.Y = 1f; - if (acd.startpos.Y >= RegionInfo.RegionSizeY) acd.startpos.Y = RegionInfo.RegionSizeY - 1f; + // Make sure avatar position is in the region (why it wouldn't be is a mystery but do sanity checking) + if (acd.startpos.X < 0) + acd.startpos.X = 1f; + else if (acd.startpos.X >= RegionInfo.RegionSizeX) + acd.startpos.X = RegionInfo.RegionSizeX - 1f; + if (acd.startpos.Y < 0) + acd.startpos.Y = 1f; + else if (acd.startpos.Y >= RegionInfo.RegionSizeY) + acd.startpos.Y = RegionInfo.RegionSizeY - 1f; -// m_log.DebugFormat( -// "[SCENE]: Found telehub object {0} for new user connection {1} to {2}", -// RegionInfo.RegionSettings.TelehubObject, acd.Name, Name); + // only check access, actual relocations will happen later on ScenePresence MakeRoot + // allow child agents creation + if(!godlike || teleportFlags != (uint) TPFlags.Default) + { + bool checkTeleHub; - // Honor Estate teleport routing via Telehubs excluding ViaHome and GodLike TeleportFlags - if (RegionInfo.RegionSettings.TelehubObject != UUID.Zero && - RegionInfo.EstateSettings.AllowDirectTeleport == false && - !viahome && !godlike) + // don't check hubs if via home or via lure + if((teleportFlags & (uint) TPFlags.ViaHome) != 0 + || (teleportFlags & (uint) TPFlags.ViaLure) != 0) + checkTeleHub = false; + else + checkTeleHub = vialogin + || (TelehubAllowLandmarks == true ? false : ((teleportFlags & (uint)TPFlags.ViaLandmark) != 0 )) + || (teleportFlags & (uint) TPFlags.ViaLocation) != 0; + + if(!CheckLandPositionAccess(acd.AgentID, true, checkTeleHub, acd.startpos, out reason)) { - SceneObjectGroup telehub = GetSceneObjectGroup(RegionInfo.RegionSettings.TelehubObject); - - if (telehub != null) - { - // Can have multiple SpawnPoints - List spawnpoints = RegionInfo.RegionSettings.SpawnPoints(); - if (spawnpoints.Count > 1) - { - // We have multiple SpawnPoints, Route the agent to a random or sequential one - if (SpawnPointRouting == "random") - acd.startpos = spawnpoints[Util.RandomClass.Next(spawnpoints.Count) - 1].GetLocation( - telehub.AbsolutePosition, - telehub.GroupRotation - ); - else - acd.startpos = spawnpoints[SpawnPoint()].GetLocation( - telehub.AbsolutePosition, - telehub.GroupRotation - ); - } - else if (spawnpoints.Count == 1) - { - // We have a single SpawnPoint and will route the agent to it - acd.startpos = spawnpoints[0].GetLocation(telehub.AbsolutePosition, telehub.GroupRotation); - } - else - { - m_log.DebugFormat( - "[SCENE]: No spawnpoints defined for telehub {0} for {1} in {2}. Continuing.", - RegionInfo.RegionSettings.TelehubObject, acd.Name, Name); - } - } - else - { - m_log.DebugFormat( - "[SCENE]: No telehub {0} found to direct {1} in {2}. Continuing.", - RegionInfo.RegionSettings.TelehubObject, acd.Name, Name); - } - - // Final permissions check; this time we don't allow changing the position - if (!IsPositionAllowed(acd.AgentID, acd.startpos, ref reason)) - { - m_authenticateHandler.RemoveCircuit(acd.circuitcode); - return false; - } - - return true; + m_authenticateHandler.RemoveCircuit(acd.circuitcode); + return false; } - - // Honor parcel landing type and position. - /* - ILandObject land = LandChannel.GetLandObject(agent.startpos.X, agent.startpos.Y); - if (land != null) - { - if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero) - { - acd.startpos = land.LandData.UserLocation; - - // Final permissions check; this time we don't allow changing the position - if (!IsPositionAllowed(acd.AgentID, acd.startpos, ref reason)) - { - m_authenticateHandler.RemoveCircuit(acd.circuitcode); - return false; - } - } - } - */// This is now handled properly in ScenePresence.MakeRootAgent } return true; @@ -4406,7 +4345,7 @@ namespace OpenSim.Region.Framework.Scenes if (nearestParcel != null) { //Move agent to nearest allowed - Vector3 newPosition = GetParcelCenterAtGround(nearestParcel); + Vector2 newPosition = GetParcelSafeCorner(nearestParcel); posX = newPosition.X; posY = newPosition.Y; } @@ -4468,8 +4407,10 @@ namespace OpenSim.Region.Framework.Scenes { reason = String.Empty; - if (!m_strictAccessControl) return true; - if (Permissions.IsGod(agent.AgentID)) return true; + if (!m_strictAccessControl) + return true; + if (Permissions.IsGod(agent.AgentID)) + return true; if (AuthorizationService != null) { @@ -4489,99 +4430,85 @@ namespace OpenSim.Region.Framework.Scenes // the root is done elsewhere (QueryAccess) if (!bypassAccessControl) { - if (RegionInfo.EstateSettings != null) - { - int flags = GetUserFlags(agent.AgentID); - if (RegionInfo.EstateSettings.IsBanned(agent.AgentID, flags)) - { - m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user is on the banlist", - agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName); - reason = String.Format("Denied access to region {0}: You have been banned from that region.", - RegionInfo.RegionName); - return false; - } - } - else + if(RegionInfo.EstateSettings == null) { + // something is broken? let it get in m_log.ErrorFormat("[CONNECTION BEGIN]: Estate Settings is null!"); + return true; + } + + // check estate ban + int flags = GetUserFlags(agent.AgentID); + if (RegionInfo.EstateSettings.IsBanned(agent.AgentID, flags)) + { + m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user is on the banlist", + agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName); + reason = String.Format("Denied access to region {0}: You have been banned from that region.", + RegionInfo.RegionName); + return false; + } + + // public access + if (RegionInfo.EstateSettings.PublicAccess) + return true; + + // in access list / owner / manager + if (RegionInfo.EstateSettings.HasAccess(agent.AgentID)) + return true; + + // finally test groups + + if (m_groupsModule == null) // if no groups allow + return true; + + UUID[] estateGroups = RegionInfo.EstateSettings.EstateGroups; + + if (estateGroups == null) + { + m_log.ErrorFormat("[CONNECTION BEGIN]: Estate GroupMembership is null!"); + return false; + } + + if(estateGroups.Length == 0) + { + return false; } List agentGroups = new List(); + GroupMembershipData[] GroupMembership = m_groupsModule.GetMembershipData(agent.AgentID); - if (m_groupsModule != null) + if (GroupMembership == null) { - GroupMembershipData[] GroupMembership = m_groupsModule.GetMembershipData(agent.AgentID); - - if (GroupMembership != null) - { - for (int i = 0; i < GroupMembership.Length; i++) - agentGroups.Add(GroupMembership[i].GroupID); - } - else - { - m_log.ErrorFormat("[CONNECTION BEGIN]: GroupMembership is null!"); - } + m_log.ErrorFormat("[CONNECTION BEGIN]: GroupMembership is null!"); + return false; } - + + if(GroupMembership.Length == 0) + return false; + + for (int i = 0; i < GroupMembership.Length; i++) + agentGroups.Add(GroupMembership[i].GroupID); + bool groupAccess = false; - UUID[] estateGroups = RegionInfo.EstateSettings.EstateGroups; - - if (estateGroups != null) + foreach (UUID group in estateGroups) { - foreach (UUID group in estateGroups) + if (agentGroups.Contains(group)) { - if (agentGroups.Contains(group)) - { - groupAccess = true; - break; - } + groupAccess = true; + break; } } - else - { - m_log.ErrorFormat("[CONNECTION BEGIN]: EstateGroups is null!"); - } - if (!RegionInfo.EstateSettings.PublicAccess && - !RegionInfo.EstateSettings.HasAccess(agent.AgentID) && - !groupAccess) + if (!groupAccess) { m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user does not have access to the estate", agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName); reason = String.Format("Denied access to private region {0}: You are not on the access list for that region.", - RegionInfo.RegionName); + RegionInfo.RegionName); return false; } } - // TODO: estate/region settings are not properly hooked up - // to ILandObject.isRestrictedFromLand() - // if (null != LandChannel) - // { - // // region seems to have local Id of 1 - // ILandObject land = LandChannel.GetLandObject(1); - // if (null != land) - // { - // if (land.isBannedFromLand(agent.AgentID)) - // { - // m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user has been banned from land", - // agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName); - // reason = String.Format("Denied access to private region {0}: You are banned from that region.", - // RegionInfo.RegionName); - // return false; - // } - - // if (land.isRestrictedFromLand(agent.AgentID)) - // { - // m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user does not have access to the region", - // agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName); - // reason = String.Format("Denied access to private region {0}: You are not on the access list for that region.", - // RegionInfo.RegionName); - // return false; - // } - // } - // } - return true; } @@ -5951,6 +5878,14 @@ Environment.Exit(1); return LandChannel.AllParcels(); } + private Vector2 GetParcelSafeCorner(ILandObject parcel) + { + Vector3 start = parcel.StartPoint; + float x = start.X + 2.0f; + float y = start.Y + 2.0f; + return new Vector2(x, y); + } + private float GetParcelDistancefromPoint(ILandObject parcel, float x, float y) { return Vector2.Distance(new Vector2(x, y), GetParcelCenter(parcel)); @@ -5962,9 +5897,16 @@ Environment.Exit(1); int count = 0; int avgx = 0; int avgy = 0; - for (int x = 0; x < RegionInfo.RegionSizeX; x++) + Vector3 start = parcel.StartPoint; + Vector3 end = parcel.EndPoint; + int startX = (int) start.X; + int startY = (int) start.Y; + int endX = (int) end.X; + int endY = (int) end.Y; + + for (int x = startX; x < endX; x += 4) { - for (int y = 0; y < RegionInfo.RegionSizeY; y++) + for (int y = startY; y < endY; y += 4) { //Just keep a running average as we check if all the points are inside or not if (parcel.ContainsPoint(x, y)) @@ -5983,6 +5925,7 @@ Environment.Exit(1); } } } + return new Vector2(avgx, avgy); } @@ -6230,13 +6173,16 @@ Environment.Exit(1); reason = string.Empty; if (Permissions.IsGod(agentID)) - { - reason = String.Empty; return true; - } if (!AllowAvatarCrossing && !viaTeleport) + { + reason = "Region Crossing not allowed"; return false; + } + + bool isAdmin = Permissions.IsAdministrator(agentID); + bool isManager = Permissions.IsEstateManager(agentID); // FIXME: Root agent count is currently known to be inaccurate. This forces a recount before we check. // However, the long term fix is to make sure root agent count is always accurate. @@ -6246,7 +6192,7 @@ Environment.Exit(1); if (num >= RegionInfo.RegionSettings.AgentLimit) { - if (!Permissions.IsAdministrator(agentID)) + if (!(isAdmin || isManager)) { reason = "The region is full"; @@ -6284,6 +6230,7 @@ Environment.Exit(1); if (!AuthorizeUser(aCircuit, false, out reason)) { //m_log.DebugFormat("[SCENE]: Denying access for {0}", agentID); +// reason = "Region authorization fail"; return false; } } @@ -6293,53 +6240,101 @@ Environment.Exit(1); reason = "Error authorizing agent: " + e.Message; return false; } + + // last check aditional land access restrictions and relocations + // if crossing (viaTeleport false) check only the specified parcel + return CheckLandPositionAccess(agentID, viaTeleport, true, position, out reason); + } - if (viaTeleport) + // check access to land. + public bool CheckLandPositionAccess(UUID agentID, bool agentRootCrossing, bool checkTeleHub, Vector3 position, out string reason) + { + reason = string.Empty; + + if (Permissions.IsGod(agentID)) + return true; + + bool isAdmin = Permissions.IsAdministrator(agentID); + if(isAdmin) + return true; + + // also honor estate managers access rights + bool isManager = Permissions.IsEstateManager(agentID); + if(isManager) + return true; + + if (!agentRootCrossing) { if (!RegionInfo.EstateSettings.AllowDirectTeleport) { SceneObjectGroup telehub; - if (RegionInfo.RegionSettings.TelehubObject != UUID.Zero && (telehub = GetSceneObjectGroup(RegionInfo.RegionSettings.TelehubObject)) != null) - { - List spawnPoints = RegionInfo.RegionSettings.SpawnPoints(); + if (RegionInfo.RegionSettings.TelehubObject != UUID.Zero && (telehub = GetSceneObjectGroup (RegionInfo.RegionSettings.TelehubObject)) != null && checkTeleHub) + { bool banned = true; - foreach (SpawnPoint sp in spawnPoints) + bool validTelehub = false; + List spawnPoints = RegionInfo.RegionSettings.SpawnPoints(); + Vector3 spawnPoint; + ILandObject land = null; + Vector3 telehubPosition = telehub.AbsolutePosition; + + if(spawnPoints.Count == 0) { - Vector3 spawnPoint = sp.GetLocation(telehub.AbsolutePosition, telehub.GroupRotation); - ILandObject land = LandChannel.GetLandObject(spawnPoint.X, spawnPoint.Y); - if (land == null) - continue; - if (land.IsEitherBannedOrRestricted(agentID)) - continue; - banned = false; - break; + // will this ever happen? + // if so use the telehub object position + spawnPoint = telehubPosition; + land = LandChannel.GetLandObject(spawnPoint.X, spawnPoint.Y); + if(land != null && !land.IsEitherBannedOrRestricted(agentID)) + { + banned = false; + validTelehub = true; + } + } + else + { + Quaternion telehubRotation = telehub.GroupRotation; + foreach (SpawnPoint spawn in spawnPoints) + { + spawnPoint = spawn.GetLocation(telehubPosition, telehubRotation); + land = LandChannel.GetLandObject(spawnPoint.X, spawnPoint.Y); + if (land == null) + continue; + validTelehub = true; + if (!land.IsEitherBannedOrRestricted(agentID)) + { + banned = false; + break; + } + } } - if (banned) + if(validTelehub) { - if (Permissions.IsAdministrator(agentID) == false || Permissions.IsGridGod(agentID) == false) + if (banned) { reason = "No suitable landing point found"; return false; } - reason = "Administrative access only"; - return true; + else + return true; } + // possible broken telehub, fall into normal check } } - float posX = 128.0f; - float posY = 128.0f; + float posX = position.X; + float posY = position.Y; + // allow position relocation if (!TestLandRestrictions(agentID, out reason, ref posX, ref posY)) { // m_log.DebugFormat("[SCENE]: Denying {0} because they are banned on all parcels", agentID); - reason = "You are banned from the region on all parcels"; + reason = "You dont have access to the region parcels"; return false; } } - else // Walking + else // check for query region crossing only { + // no relocation allowed on crossings ILandObject land = LandChannel.GetLandObject(position.X, position.Y); if (land == null) { @@ -6360,7 +6355,6 @@ Environment.Exit(1); } } - reason = String.Empty; return true; }