From 515e62dc2f4614b140da222c082d3cd69c5960d4 Mon Sep 17 00:00:00 2001 From: Dr Scofield Date: Mon, 27 Apr 2009 11:51:25 +0000 Subject: From: Alan M Webb Added support for access control lists. Scene: Added test to AddNewClient for an entry in the access list when connecting to a region with limited access. EstateSettings: Added an HasAccess(UUID) property to test for an entry in the estate's access list. RemoteAdmin: Add RPC calls for admin_acl_list, clear, add, and remove. --- .../RemoteController/RemoteAdminPlugin.cs | 288 ++++++++++++++++++++- OpenSim/Framework/EstateSettings.cs | 5 + OpenSim/Region/Framework/Scenes/Scene.cs | 82 +++--- 3 files changed, 341 insertions(+), 34 deletions(-) (limited to 'OpenSim') diff --git a/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs b/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs index a7290b9..f6bfb33 100644 --- a/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs +++ b/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs @@ -102,19 +102,26 @@ namespace OpenSim.ApplicationPlugins.RemoteController Dictionary availableMethods = new Dictionary(); availableMethods["admin_create_region"] = XmlRpcCreateRegionMethod; availableMethods["admin_delete_region"] = XmlRpcDeleteRegionMethod; + availableMethods["admin_region_query"] = XmlRpcRegionQueryMethod; availableMethods["admin_shutdown"] = XmlRpcShutdownMethod; availableMethods["admin_broadcast"] = XmlRpcAlertMethod; availableMethods["admin_restart"] = XmlRpcRestartMethod; availableMethods["admin_load_heightmap"] = XmlRpcLoadHeightmapMethod; + // User management availableMethods["admin_create_user"] = XmlRpcCreateUserMethod; availableMethods["admin_create_user_email"] = XmlRpcCreateUserMethod; availableMethods["admin_exists_user"] = XmlRpcUserExistsMethod; availableMethods["admin_update_user"] = XmlRpcUpdateUserAccountMethod; + // Region state management availableMethods["admin_load_xml"] = XmlRpcLoadXMLMethod; availableMethods["admin_save_xml"] = XmlRpcSaveXMLMethod; availableMethods["admin_load_oar"] = XmlRpcLoadOARMethod; availableMethods["admin_save_oar"] = XmlRpcSaveOARMethod; - availableMethods["admin_region_query"] = XmlRpcRegionQueryMethod; + // Estate access list management + availableMethods["admin_acl_clear"] = XmlRpcAccessListClear; + availableMethods["admin_acl_add"] = XmlRpcAccessListAdd; + availableMethods["admin_acl_remove"] = XmlRpcAccessListRemove; + availableMethods["admin_acl_list"] = XmlRpcAccessListList; // Either enable full remote functionality or just selected features string enabledMethods = m_config.GetString("enabled_methods", "all"); @@ -1496,8 +1503,287 @@ namespace OpenSim.ApplicationPlugins.RemoteController return response; } + public XmlRpcResponse XmlRpcAccessListClear(XmlRpcRequest request) + { + + m_log.Info("[RADMIN]: Received Access List Clear Request"); + XmlRpcResponse response = new XmlRpcResponse(); + Hashtable responseData = new Hashtable(); + + try + { + responseData["success"] = "true"; + + Hashtable requestData = (Hashtable) request.Params[0]; + + if (!requestData.Contains("password")) + throw new Exception(String.Format("missing required parameter")); + if (!String.IsNullOrEmpty(requiredPassword) && + (string) requestData["password"] != requiredPassword) throw new Exception("wrong password"); + + if (requestData.Contains("region_uuid")) + { + UUID region_uuid = (UUID) (string) requestData["region_uuid"]; + if (!m_app.SceneManager.TrySetCurrentScene(region_uuid)) + throw new Exception(String.Format("failed to switch to region {0}", region_uuid.ToString())); + m_log.InfoFormat("[RADMIN] Switched to region {0}", region_uuid.ToString()); + } + else if (requestData.Contains("region_name")) + { + string region_name = (string) requestData["region_name"]; + if (!m_app.SceneManager.TrySetCurrentScene(region_name)) + throw new Exception(String.Format("failed to switch to region {0}", region_name)); + m_log.InfoFormat("[RADMIN] Switched to region {0}", region_name); + } + else throw new Exception("neither region_name nor region_uuid given"); + + Scene s = m_app.SceneManager.CurrentScene; + s.RegionInfo.EstateSettings.EstateAccess = new UUID[]{}; + + } + catch (Exception e) + { + m_log.InfoFormat("[RADMIN] Access List Clear Request: {0}", e.Message); + + responseData["success"] = "false"; + responseData["error"] = e.Message; + + } + finally + { + response.Value = responseData; + } + + m_log.Info("[RADMIN]: Access List Clear Request complete"); + return response; + } + + public XmlRpcResponse XmlRpcAccessListAdd(XmlRpcRequest request) + { + + m_log.Info("[RADMIN]: Received Access List Add Request"); + XmlRpcResponse response = new XmlRpcResponse(); + Hashtable responseData = new Hashtable(); + + try + { + responseData["success"] = "true"; + + Hashtable requestData = (Hashtable) request.Params[0]; + + if (!requestData.Contains("password")) + throw new Exception(String.Format("missing required parameter")); + if (!String.IsNullOrEmpty(requiredPassword) && + (string) requestData["password"] != requiredPassword) throw new Exception("wrong password"); + + if (requestData.Contains("region_uuid")) + { + UUID region_uuid = (UUID) (string) requestData["region_uuid"]; + if (!m_app.SceneManager.TrySetCurrentScene(region_uuid)) + throw new Exception(String.Format("failed to switch to region {0}", region_uuid.ToString())); + m_log.InfoFormat("[RADMIN] Switched to region {0}", region_uuid.ToString()); + } + else if (requestData.Contains("region_name")) + { + string region_name = (string) requestData["region_name"]; + if (!m_app.SceneManager.TrySetCurrentScene(region_name)) + throw new Exception(String.Format("failed to switch to region {0}", region_name)); + m_log.InfoFormat("[RADMIN] Switched to region {0}", region_name); + } + else throw new Exception("neither region_name nor region_uuid given"); + + int addk = 0; + + if(requestData.Contains("users")) + { + UserProfileCacheService ups = m_app.CommunicationsManager.UserProfileCacheService; + Scene s = m_app.SceneManager.CurrentScene; + Hashtable users = (Hashtable) requestData["users"]; + List uuids = new List(); + foreach(string name in users.Values) + { + string[] parts = name.Split(); + uuids.Add(ups.GetUserDetails(parts[0],parts[1]).UserProfile.ID); + } + List acl = new List(s.RegionInfo.EstateSettings.EstateAccess); + foreach(UUID uuid in uuids) + { + if(!acl.Contains(uuid)) + { + acl.Add(uuid); + addk++; + } + } + s.RegionInfo.EstateSettings.EstateAccess = acl.ToArray(); + } + + responseData["added"] = addk; + + } + catch (Exception e) + { + m_log.InfoFormat("[RADMIN] Access List Add Request: {0}", e.Message); + + responseData["success"] = "false"; + responseData["error"] = e.Message; + + } + finally + { + response.Value = responseData; + } + + m_log.Info("[RADMIN]: Access List Add Request complete"); + return response; + } + + public XmlRpcResponse XmlRpcAccessListRemove(XmlRpcRequest request) + { + + m_log.Info("[RADMIN]: Received Access List Remove Request"); + XmlRpcResponse response = new XmlRpcResponse(); + Hashtable responseData = new Hashtable(); + + try + { + responseData["success"] = "true"; + + Hashtable requestData = (Hashtable) request.Params[0]; + + if (!requestData.Contains("password")) + throw new Exception(String.Format("missing required parameter")); + if (!String.IsNullOrEmpty(requiredPassword) && + (string) requestData["password"] != requiredPassword) throw new Exception("wrong password"); + + if (requestData.Contains("region_uuid")) + { + UUID region_uuid = (UUID) (string) requestData["region_uuid"]; + if (!m_app.SceneManager.TrySetCurrentScene(region_uuid)) + throw new Exception(String.Format("failed to switch to region {0}", region_uuid.ToString())); + m_log.InfoFormat("[RADMIN] Switched to region {0}", region_uuid.ToString()); + } + else if (requestData.Contains("region_name")) + { + string region_name = (string) requestData["region_name"]; + if (!m_app.SceneManager.TrySetCurrentScene(region_name)) + throw new Exception(String.Format("failed to switch to region {0}", region_name)); + m_log.InfoFormat("[RADMIN] Switched to region {0}", region_name); + } + else throw new Exception("neither region_name nor region_uuid given"); + + int remk = 0; + + if(requestData.Contains("users")) + { + UserProfileCacheService ups = m_app.CommunicationsManager.UserProfileCacheService; + Scene s = m_app.SceneManager.CurrentScene; + Hashtable users = (Hashtable) requestData["users"]; + List uuids = new List(); + foreach(string name in users.Values) + { + string[] parts = name.Split(); + uuids.Add(ups.GetUserDetails(parts[0],parts[1]).UserProfile.ID); + } + List acl = new List(s.RegionInfo.EstateSettings.EstateAccess); + foreach(UUID uuid in uuids) + { + if(acl.Contains(uuid)) + { + acl.Remove(uuid); + remk++; + } + } + s.RegionInfo.EstateSettings.EstateAccess = acl.ToArray(); + } + + responseData["added"] = remk; + + + } + catch (Exception e) + { + m_log.InfoFormat("[RADMIN] Access List Remove Request: {0}", e.Message); + + responseData["success"] = "false"; + responseData["error"] = e.Message; + + } + finally + { + response.Value = responseData; + } + + m_log.Info("[RADMIN]: Access List Remove Request complete"); + return response; + } + + public XmlRpcResponse XmlRpcAccessListList(XmlRpcRequest request) + { + + m_log.Info("[RADMIN]: Received Access List List Request"); + XmlRpcResponse response = new XmlRpcResponse(); + Hashtable responseData = new Hashtable(); + + try + { + responseData["success"] = "true"; + + Hashtable requestData = (Hashtable) request.Params[0]; + + if (!requestData.Contains("password")) + throw new Exception(String.Format("missing required parameter")); + if (!String.IsNullOrEmpty(requiredPassword) && + (string) requestData["password"] != requiredPassword) throw new Exception("wrong password"); + + if (requestData.Contains("region_uuid")) + { + UUID region_uuid = (UUID) (string) requestData["region_uuid"]; + if (!m_app.SceneManager.TrySetCurrentScene(region_uuid)) + throw new Exception(String.Format("failed to switch to region {0}", region_uuid.ToString())); + m_log.InfoFormat("[RADMIN] Switched to region {0}", region_uuid.ToString()); + } + else if (requestData.Contains("region_name")) + { + string region_name = (string) requestData["region_name"]; + if (!m_app.SceneManager.TrySetCurrentScene(region_name)) + throw new Exception(String.Format("failed to switch to region {0}", region_name)); + m_log.InfoFormat("[RADMIN] Switched to region {0}", region_name); + } + else throw new Exception("neither region_name nor region_uuid given"); + + Scene s = m_app.SceneManager.CurrentScene; + UUID[] acl = s.RegionInfo.EstateSettings.EstateAccess; + Hashtable users = new Hashtable(); + + foreach(UUID user in acl) + { + users[user.ToString()] = + m_app.CommunicationsManager.UserProfileCacheService.GetUserDetails(user).UserProfile.Name; + } + + responseData["users"] = users; + + } + catch (Exception e) + { + m_log.InfoFormat("[RADMIN] Acces List List: {0}", e.Message); + + responseData["success"] = "false"; + responseData["error"] = e.Message; + + } + finally + { + response.Value = responseData; + } + + m_log.Info("[RADMIN]: Access List List Request complete"); + return response; + } + public void Dispose() { } } + } diff --git a/OpenSim/Framework/EstateSettings.cs b/OpenSim/Framework/EstateSettings.cs index ff0445f..14bb9ef 100644 --- a/OpenSim/Framework/EstateSettings.cs +++ b/OpenSim/Framework/EstateSettings.cs @@ -358,6 +358,11 @@ namespace OpenSim.Framework l_EstateBans.Remove(ban); } + public bool HasAccess(UUID user) + { + return l_EstateAccess.Contains(user); + } + public void loadConfigurationOptions() { configMember.addConfigurationOption("billable_factor", diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 70713c4..c7d32cc 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -1846,11 +1846,25 @@ namespace OpenSim.Region.Framework.Scenes public override void AddNewClient(IClientAPI client) { - if (m_regInfo.EstateSettings.IsBanned(client.AgentId)) + bool welcome = true; + + if(m_regInfo.EstateSettings.IsBanned(client.AgentId)) { m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user is on the banlist", client.AgentId, client.FirstName, client.LastName, RegionInfo.RegionName); client.SendAlertMessage("Denied access to region " + RegionInfo.RegionName + ". You have been banned from that region."); + welcome = false; + } + else if (!m_regInfo.EstateSettings.PublicAccess && !m_regInfo.EstateSettings.HasAccess(client.AgentId)) + { + m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user does not have access", + client.AgentId, client.FirstName, client.LastName, RegionInfo.RegionName); + client.SendAlertMessage("Denied access to private region " + RegionInfo.RegionName + ". You do not have access to this region."); + welcome = false; + } + + if(!welcome) + { try { IEventQueue eq = RequestModuleInterface(); @@ -1867,50 +1881,52 @@ namespace OpenSim.Region.Framework.Scenes } catch (Exception e) { - m_log.DebugFormat("[SCENE]: Exception while closing banned client {0} {1}: {2}", client.FirstName, client.LastName, e.Message); + m_log.DebugFormat("[SCENE]: Exception while closing unwelcome client {0} {1}: {2}", client.FirstName, client.LastName, e.Message); } } + else + { + SubscribeToClientEvents(client); + ScenePresence presence; - SubscribeToClientEvents(client); - ScenePresence presence; + if (m_restorePresences.ContainsKey(client.AgentId)) + { + m_log.DebugFormat("[SCENE]: Restoring agent {0} {1} in {2}", client.Name, client.AgentId, RegionInfo.RegionName); - if (m_restorePresences.ContainsKey(client.AgentId)) - { - m_log.DebugFormat("[SCENE]: Restoring agent {0} {1} in {2}", client.Name, client.AgentId, RegionInfo.RegionName); + presence = m_restorePresences[client.AgentId]; + m_restorePresences.Remove(client.AgentId); - presence = m_restorePresences[client.AgentId]; - m_restorePresences.Remove(client.AgentId); + // This is one of two paths to create avatars that are + // used. This tends to get called more in standalone + // than grid, not really sure why, but as such needs + // an explicity appearance lookup here. + AvatarAppearance appearance = null; + GetAvatarAppearance(client, out appearance); + presence.Appearance = appearance; - // This is one of two paths to create avatars that are - // used. This tends to get called more in standalone - // than grid, not really sure why, but as such needs - // an explicity appearance lookup here. - AvatarAppearance appearance = null; - GetAvatarAppearance(client, out appearance); - presence.Appearance = appearance; + presence.initializeScenePresence(client, RegionInfo, this); - presence.initializeScenePresence(client, RegionInfo, this); + m_sceneGraph.AddScenePresence(presence); - m_sceneGraph.AddScenePresence(presence); + lock (m_restorePresences) + { + Monitor.PulseAll(m_restorePresences); + } + } + else + { + m_log.DebugFormat( + "[SCENE]: Adding new child agent for {0} in {1}", + client.Name, RegionInfo.RegionName); - lock (m_restorePresences) - { - Monitor.PulseAll(m_restorePresences); - } - } - else - { - m_log.DebugFormat( - "[SCENE]: Adding new child agent for {0} in {1}", - client.Name, RegionInfo.RegionName); + CommsManager.UserProfileCacheService.AddNewUser(client.AgentId); - CommsManager.UserProfileCacheService.AddNewUser(client.AgentId); + CreateAndAddScenePresence(client); + } - CreateAndAddScenePresence(client); + m_LastLogin = Environment.TickCount; + EventManager.TriggerOnNewClient(client); } - - m_LastLogin = Environment.TickCount; - EventManager.TriggerOnNewClient(client); } protected virtual void SubscribeToClientEvents(IClientAPI client) -- cgit v1.1