From 51b208e96c881bd322b3769b843f0ebae3c09a84 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Tue, 13 Jul 2010 23:19:45 +0100 Subject: [PATCH] implement prim media control permissions serverside in order to stop bad clients --- .../World/Media/Moap/MoapModule.cs | 87 ++++++++++++++----- .../World/Permissions/PermissionsModule.cs | 43 ++++++++- .../Framework/Scenes/Scene.Permissions.cs | 21 ++++- 3 files changed, 127 insertions(+), 24 deletions(-) diff --git a/OpenSim/Region/CoreModules/World/Media/Moap/MoapModule.cs b/OpenSim/Region/CoreModules/World/Media/Moap/MoapModule.cs index 378ff4a915..d7aede91dd 100644 --- a/OpenSim/Region/CoreModules/World/Media/Moap/MoapModule.cs +++ b/OpenSim/Region/CoreModules/World/Media/Moap/MoapModule.cs @@ -58,8 +58,21 @@ namespace OpenSim.Region.CoreModules.Media.Moap public string Name { get { return "MoapModule"; } } public Type ReplaceableInterface { get { return null; } } + /// + /// The scene to which this module is attached + /// protected Scene m_scene; + /// + /// Track the ObjectMedia capabilities given to users + /// + protected Dictionary m_omCapUsers = new Dictionary(); + + /// + /// Track the ObjectMediaUpdate capabilities given to users + /// + protected Dictionary m_omuCapUsers = new Dictionary(); + public void Initialise(IConfigSource config) { // TODO: Add config switches to enable/disable this module @@ -87,16 +100,27 @@ namespace OpenSim.Region.CoreModules.Media.Moap m_log.DebugFormat( "[MOAP]: Registering ObjectMedia and ObjectMediaNavigate capabilities for agent {0}", agentID); - // We do receive a post to ObjectMedia when a new avatar enters the region - though admittedly this is the - // avatar that set the texture in the first place. - // Even though we're registering for POST we're going to get GETS and UPDATES too - caps.RegisterHandler( - "ObjectMedia", new RestStreamHandler("POST", "/CAPS/" + UUID.Random(), HandleObjectMediaMessage)); + string omCapUrl = "/CAPS/" + UUID.Random(); - // We do get these posts when the url has been changed. - // Even though we're registering for POST we're going to get GETS and UPDATES too - caps.RegisterHandler( - "ObjectMediaNavigate", new RestStreamHandler("POST", "/CAPS/" + UUID.Random(), HandleObjectMediaNavigateMessage)); + lock (m_omCapUsers) + { + m_omCapUsers[omCapUrl] = agentID; + + // Even though we're registering for POST we're going to get GETS and UPDATES too + caps.RegisterHandler( + "ObjectMedia", new RestStreamHandler("POST", omCapUrl, HandleObjectMediaMessage)); + } + + string omuCapUrl = "/CAPS/" + UUID.Random(); + + lock (m_omuCapUsers) + { + m_omuCapUsers[omuCapUrl] = agentID; + + // Even though we're registering for POST we're going to get GETS and UPDATES too + caps.RegisterHandler( + "ObjectMediaNavigate", new RestStreamHandler("POST", omuCapUrl, HandleObjectMediaNavigateMessage)); + } } public MediaEntry GetMediaEntry(SceneObjectPart part, int face) @@ -147,7 +171,7 @@ namespace OpenSim.Region.CoreModules.Media.Moap protected string HandleObjectMediaMessage( string request, string path, string param, OSHttpRequest httpRequest, OSHttpResponse httpResponse) { - m_log.DebugFormat("[MOAP]: Got ObjectMedia raw request [{0}]", request); + m_log.DebugFormat("[MOAP]: Got ObjectMedia path [{0}], raw request [{1}]", path, request); OSDMap osd = (OSDMap)OSDParser.DeserializeLLSDXml(request); ObjectMediaMessage omm = new ObjectMediaMessage(); @@ -156,7 +180,7 @@ namespace OpenSim.Region.CoreModules.Media.Moap if (omm.Request is ObjectMediaRequest) return HandleObjectMediaRequest(omm.Request as ObjectMediaRequest); else if (omm.Request is ObjectMediaUpdate) - return HandleObjectMediaUpdate(omm.Request as ObjectMediaUpdate); + return HandleObjectMediaUpdate(path, omm.Request as ObjectMediaUpdate); throw new Exception( string.Format( @@ -165,7 +189,7 @@ namespace OpenSim.Region.CoreModules.Media.Moap } /// - /// Handle a request for media textures + /// Handle a fetch request for media textures /// /// /// @@ -202,9 +226,10 @@ namespace OpenSim.Region.CoreModules.Media.Moap /// /// Handle an update of media textures. /// + /// Path on which this request was made /// /param> /// - protected string HandleObjectMediaUpdate(ObjectMediaUpdate omu) + protected string HandleObjectMediaUpdate(string path, ObjectMediaUpdate omu) { UUID primId = omu.PrimID; @@ -216,16 +241,16 @@ namespace OpenSim.Region.CoreModules.Media.Moap "[MOAP]: Received an UPDATE ObjectMediaRequest for prim {0} but this doesn't exist in region {1}", primId, m_scene.RegionInfo.RegionName); return string.Empty; - } + } m_log.DebugFormat("[MOAP]: Received {0} media entries for prim {1}", omu.FaceMedia.Length, primId); -// for (int i = 0; i < omu.FaceMedia.Length; i++) -// { -// MediaEntry me = omu.FaceMedia[i]; -// string v = (null == me ? "null": OSDParser.SerializeLLSDXmlString(me.GetOSD())); -// m_log.DebugFormat("[MOAP]: Face {0} [{1}]", i, v); -// } + for (int i = 0; i < omu.FaceMedia.Length; i++) + { + MediaEntry me = omu.FaceMedia[i]; + string v = (null == me ? "null": OSDParser.SerializeLLSDXmlString(me.GetOSD())); + m_log.DebugFormat("[MOAP]: Face {0} [{1}]", i, v); + } if (omu.FaceMedia.Length > part.GetNumberOfSides()) { @@ -235,7 +260,27 @@ namespace OpenSim.Region.CoreModules.Media.Moap return string.Empty; } - part.Shape.Media = new List(omu.FaceMedia); + List media = part.Shape.Media; + + if (null == media) + { + part.Shape.Media = new List(omu.FaceMedia); + } + else + { + // We need to go through the media textures one at a time to make sure that we have permission + // to change them + UUID agentId = default(UUID); + + lock (m_omCapUsers) + agentId = m_omCapUsers[path]; + + for (int i = 0; i < media.Count; i++) + { + if (m_scene.Permissions.CanControlPrimMedia(agentId, part.UUID, i)) + media[i] = omu.FaceMedia[i]; + } + } UpdateMediaUrl(part); diff --git a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs index 69b247c350..358ea59216 100644 --- a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs +++ b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs @@ -164,6 +164,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions private Dictionary GrantYP = new Dictionary(); private IFriendsModule m_friendsModule; private IGroupsModule m_groupsModule; + private IMoapModule m_moapModule; #endregion @@ -248,6 +249,8 @@ namespace OpenSim.Region.CoreModules.World.Permissions m_scene.Permissions.OnDeleteUserInventory += CanDeleteUserInventory; //NOT YET IMPLEMENTED m_scene.Permissions.OnTeleport += CanTeleport; //NOT YET IMPLEMENTED + + m_scene.Permissions.OnControlPrimMedia += CanControlPrimMedia; m_scene.AddCommand(this, "bypass permissions", "bypass permissions ", @@ -393,6 +396,8 @@ namespace OpenSim.Region.CoreModules.World.Permissions if (m_groupsModule == null) m_log.Warn("[PERMISSIONS]: Groups module not found, group permissions will not work"); + + m_moapModule = m_scene.RequestModuleInterface(); } public void Close() @@ -1893,5 +1898,41 @@ namespace OpenSim.Region.CoreModules.World.Permissions } return(false); } + + private bool CanControlPrimMedia(UUID agentID, UUID primID, int face) + { + if (null == m_moapModule) + return false; + + SceneObjectPart part = m_scene.GetSceneObjectPart(primID); + if (null == part) + return false; + + MediaEntry me = m_moapModule.GetMediaEntry(part, face); + + // If there is no existing media entry then it can be controlled (in this context, created). + if (null == me) + return true; + + if (IsAdministrator(agentID)) + return true; + + if ((me.ControlPermissions & MediaPermission.Anyone) == MediaPermission.Anyone) + return true; + + if ((me.ControlPermissions & MediaPermission.Owner) == MediaPermission.Owner) + { + if (agentID == part.OwnerID) + return true; + } + + if ((me.ControlPermissions & MediaPermission.Group) == MediaPermission.Group) + { + if (IsGroupMember(part.GroupID, agentID, 0)) + return true; + } + + return false; + } } -} +} \ No newline at end of file diff --git a/OpenSim/Region/Framework/Scenes/Scene.Permissions.cs b/OpenSim/Region/Framework/Scenes/Scene.Permissions.cs index 7dab04fbd2..70af978719 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Permissions.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Permissions.cs @@ -1,4 +1,4 @@ -/* +/* * Copyright (c) Contributors, http://opensimulator.org/ * See CONTRIBUTORS.TXT for a full list of copyright holders. * @@ -81,6 +81,7 @@ namespace OpenSim.Region.Framework.Scenes public delegate bool CopyUserInventoryHandler(UUID itemID, UUID userID); public delegate bool DeleteUserInventoryHandler(UUID itemID, UUID userID); public delegate bool TeleportHandler(UUID userID, Scene scene); + public delegate bool ControlPrimMediaHandler(UUID userID, UUID primID, int face); #endregion public class ScenePermissions @@ -139,6 +140,7 @@ namespace OpenSim.Region.Framework.Scenes public event CopyUserInventoryHandler OnCopyUserInventory; public event DeleteUserInventoryHandler OnDeleteUserInventory; public event TeleportHandler OnTeleport; + public event ControlPrimMediaHandler OnControlPrimMedia; #endregion #region Object Permission Checks @@ -947,5 +949,20 @@ namespace OpenSim.Region.Framework.Scenes } return true; } + + public bool CanControlPrimMedia(UUID userID, UUID primID, int face) + { + ControlPrimMediaHandler handler = OnControlPrimMedia; + if (handler != null) + { + Delegate[] list = handler.GetInvocationList(); + foreach (ControlPrimMediaHandler h in list) + { + if (h(userID, primID, face) == false) + return false; + } + } + return true; + } } -} +} \ No newline at end of file