diff --git a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs index 8c29ad479f..d139235bcf 100644 --- a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs +++ b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs @@ -636,11 +636,11 @@ namespace OpenSim.Framework.Servers.HttpServer } catch (IOException e) { - m_log.Error(String.Format("[BASE HTTP SERVER]: HandleRequest() threw {0} ", e.Message), e); + m_log.Error(String.Format("[BASE HTTP SERVER]: HandleRequest() threw {0} ", e.StackTrace), e); } catch (Exception e) { - m_log.Error(String.Format("[BASE HTTP SERVER]: HandleRequest() threw {0} ", e.Message), e); + m_log.Error(String.Format("[BASE HTTP SERVER]: HandleRequest() threw {0} ", e.StackTrace), e); SendHTML500(response); } finally diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs index d6ad07e62a..c74584ca4e 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs @@ -859,6 +859,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments InventoryItemBase item = new InventoryItemBase(itemID, sp.UUID); item = m_scene.InventoryService.GetItem(item); + if (item == null) + return; + bool changed = sp.Appearance.SetAttachment((int)AttachmentPt, itemID, item.AssetID); if (changed && m_scene.AvatarFactory != null) { diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs index 0b386d3f67..a6698e6fc3 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs @@ -150,6 +150,34 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer if (m_Enabled) scene.RegisterModuleInterface(this); + + scene.EventManager.OnIncomingSceneObject += OnIncomingSceneObject; + } + + void OnIncomingSceneObject(SceneObjectGroup so) + { + if (!so.IsAttachment) + return; + + if (so.Scene.UserManagementModule.IsLocalGridUser(so.AttachedAvatar)) + return; + + // foreign user + AgentCircuitData aCircuit = so.Scene.AuthenticateHandler.GetAgentCircuitData(so.AttachedAvatar); + if (aCircuit != null && (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0) + { + if (aCircuit.ServiceURLs != null && aCircuit.ServiceURLs.ContainsKey("AssetServerURI")) + { + string url = aCircuit.ServiceURLs["AssetServerURI"].ToString(); + m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Incoming attachement {0} for HG user {1} with asset server {2}", so.Name, so.AttachedAvatar, url); + Dictionary ids = new Dictionary(); + HGUuidGatherer uuidGatherer = new HGUuidGatherer(so.Scene.AssetService, url); + uuidGatherer.GatherAssetUuids(so, ids); + + foreach (KeyValuePair kvp in ids) + uuidGatherer.FetchAsset(kvp.Key); + } + } } protected override void OnNewClient(IClientAPI client) diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs index a0cad40754..80257bd5a2 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs @@ -263,8 +263,13 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess //} // OK, we're done fetching. Pass it up to the default RezObject - return base.RezObject(remoteClient, itemID, RayEnd, RayStart, RayTargetID, BypassRayCast, RayEndIsIntersection, - RezSelected, RemoveItem, fromTaskID, attachment); + SceneObjectGroup sog = base.RezObject(remoteClient, itemID, RayEnd, RayStart, RayTargetID, BypassRayCast, RayEndIsIntersection, + RezSelected, RemoveItem, fromTaskID, attachment); + + if (sog == null) + remoteClient.SendAgentAlertMessage("Unable to rez: problem accessing inventory or locating assets", false); + + return sog; } diff --git a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs index 383604dbd8..28cd09f58c 100644 --- a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs +++ b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs @@ -377,6 +377,8 @@ namespace OpenSim.Region.Framework.Scenes : base(assetService) { m_assetServerURL = assetServerURL; + if (!m_assetServerURL.EndsWith("/") && !m_assetServerURL.EndsWith("=")) + m_assetServerURL = m_assetServerURL + "/"; } protected override AssetBase GetAsset(UUID uuid) @@ -384,22 +386,27 @@ namespace OpenSim.Region.Framework.Scenes if (string.Empty == m_assetServerURL) return base.GetAsset(uuid); else - return FetchAsset(m_assetServerURL, uuid); + return FetchAsset(uuid); } - public AssetBase FetchAsset(string url, UUID assetID) + public AssetBase FetchAsset(UUID assetID) { - if (!url.EndsWith("/") && !url.EndsWith("=")) - url = url + "/"; - AssetBase asset = m_assetService.Get(url + assetID.ToString()); - - if (asset != null) + // Test if it's already here + AssetBase asset = m_assetService.Get(assetID.ToString()); + if (asset == null) { - m_log.DebugFormat("[HGUUIDGatherer]: Copied asset {0} from {1} to local asset server. ", asset.ID, url); - return asset; + // It's not, so fetch it from abroad + asset = m_assetService.Get(m_assetServerURL + assetID.ToString()); + if (asset != null) + m_log.DebugFormat("[HGUUIDGatherer]: Copied asset {0} from {1} to local asset server", assetID, m_assetServerURL); + else + m_log.DebugFormat("[HGUUIDGatherer]: Failed to fetch asset {0} from {1}", assetID, m_assetServerURL); } - return null; + //else + // m_log.DebugFormat("[HGUUIDGatherer]: Asset {0} from {1} was already here", assetID, m_assetServerURL); + + return asset; } } } diff --git a/OpenSim/Services/HypergridService/GatekeeperService.cs b/OpenSim/Services/HypergridService/GatekeeperService.cs index 47d22b95fd..0f7d7c6dc1 100644 --- a/OpenSim/Services/HypergridService/GatekeeperService.cs +++ b/OpenSim/Services/HypergridService/GatekeeperService.cs @@ -58,9 +58,11 @@ namespace OpenSim.Services.HypergridService private static IUserAgentService m_UserAgentService; private static ISimulationService m_SimulationService; - protected string m_AllowedClients = string.Empty; - protected string m_DeniedClients = string.Empty; + private static string m_AllowedClients = string.Empty; + private static string m_DeniedClients = string.Empty; private static bool m_ForeignAgentsAllowed = true; + private static List m_ForeignsAllowedExceptions = new List(); + private static List m_ForeignsDisallowedExceptions = new List(); private static UUID m_ScopeID; private static bool m_AllowTeleportsToAnyRegion; @@ -113,6 +115,9 @@ namespace OpenSim.Services.HypergridService m_DeniedClients = serverConfig.GetString("DeniedClients", string.Empty); m_ForeignAgentsAllowed = serverConfig.GetBoolean("ForeignAgentsAllowed", true); + LoadDomainExceptionsFromConfig(serverConfig, "AllowExcept", m_ForeignsAllowedExceptions); + LoadDomainExceptionsFromConfig(serverConfig, "DisallowExcept", m_ForeignsDisallowedExceptions); + if (m_GridService == null || m_PresenceService == null || m_SimulationService == null) throw new Exception("Unable to load a required plugin, Gatekeeper Service cannot function."); @@ -125,6 +130,15 @@ namespace OpenSim.Services.HypergridService { } + protected void LoadDomainExceptionsFromConfig(IConfig config, string variable, List exceptions) + { + string value = config.GetString(variable, string.Empty); + string[] parts = value.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); + + foreach (string s in parts) + exceptions.Add(s.Trim()); + } + public bool LinkRegion(string regionName, out UUID regionID, out ulong regionHandle, out string externalName, out string imageURL, out string reason) { regionID = UUID.Zero; @@ -260,14 +274,25 @@ namespace OpenSim.Services.HypergridService m_log.DebugFormat("[GATEKEEPER SERVICE]: User is ok"); // - // Foreign agents allowed + // Foreign agents allowed? Exceptions? // - if (account == null && !m_ForeignAgentsAllowed) + if (account == null) { - reason = "Unauthorized"; - m_log.InfoFormat("[GATEKEEPER SERVICE]: Foreign agents are not permitted {0} {1}. Refusing service.", - aCircuit.firstname, aCircuit.lastname); - return false; + bool allowed = m_ForeignAgentsAllowed; + + if (m_ForeignAgentsAllowed && IsException(aCircuit, m_ForeignsAllowedExceptions)) + allowed = false; + + if (!m_ForeignAgentsAllowed && IsException(aCircuit, m_ForeignsDisallowedExceptions)) + allowed = true; + + if (!allowed) + { + reason = "Destination does not allow visitors from your world"; + m_log.InfoFormat("[GATEKEEPER SERVICE]: Foreign agents are not permitted {0} {1} @ {2}. Refusing service.", + aCircuit.firstname, aCircuit.lastname, aCircuit.ServiceURLs["HomeURI"]); + return false; + } } // May want to authorize @@ -393,6 +418,27 @@ namespace OpenSim.Services.HypergridService #region Misc + private bool IsException(AgentCircuitData aCircuit, List exceptions) + { + bool exception = false; + if (exceptions.Count > 0) // we have exceptions + { + // Retrieve the visitor's origin + string userURL = aCircuit.ServiceURLs["HomeURI"].ToString(); + if (!userURL.EndsWith("/")) + userURL += "/"; + + if (exceptions.Find(delegate(string s) + { + if (!s.EndsWith("/")) + s += "/"; + return s == userURL; + }) != null) + exception = true; + } + + return exception; + } #endregion } diff --git a/OpenSim/Services/HypergridService/UserAgentService.cs b/OpenSim/Services/HypergridService/UserAgentService.cs index 49c7f89598..a6fc731e0f 100644 --- a/OpenSim/Services/HypergridService/UserAgentService.cs +++ b/OpenSim/Services/HypergridService/UserAgentService.cs @@ -77,6 +77,10 @@ namespace OpenSim.Services.HypergridService protected static bool m_BypassClientVerification; + private static Dictionary m_ForeignTripsAllowed = new Dictionary(); + private static Dictionary> m_TripsAllowedExceptions = new Dictionary>(); + private static Dictionary> m_TripsDisallowedExceptions = new Dictionary>(); + public UserAgentService(IConfigSource config) : this(config, null) { } @@ -121,6 +125,12 @@ namespace OpenSim.Services.HypergridService m_PresenceService = ServerUtils.LoadPlugin(presenceService, args); m_UserAccountService = ServerUtils.LoadPlugin(userAccountService, args); + m_LevelOutsideContacts = serverConfig.GetInt("LevelOutsideContacts", 0); + + LoadTripPermissionsFromConfig(serverConfig, "ForeignTripsAllowed"); + LoadDomainExceptionsFromConfig(serverConfig, "AllowExcept", m_TripsAllowedExceptions); + LoadDomainExceptionsFromConfig(serverConfig, "DisallowExcept", m_TripsDisallowedExceptions); + m_GridName = serverConfig.GetString("ExternalName", string.Empty); if (m_GridName == string.Empty) { @@ -130,10 +140,43 @@ namespace OpenSim.Services.HypergridService if (!m_GridName.EndsWith("/")) m_GridName = m_GridName + "/"; - m_LevelOutsideContacts = serverConfig.GetInt("LevelOutsideContacts", 0); } } + protected void LoadTripPermissionsFromConfig(IConfig config, string variable) + { + foreach (string keyName in config.GetKeys()) + { + if (keyName.StartsWith(variable + "_Level_")) + { + int level = 0; + if (Int32.TryParse(keyName.Replace(variable + "_Level_", ""), out level)) + m_ForeignTripsAllowed.Add(level, config.GetBoolean(keyName, true)); + } + } + } + + protected void LoadDomainExceptionsFromConfig(IConfig config, string variable, Dictionary> exceptions) + { + foreach (string keyName in config.GetKeys()) + { + if (keyName.StartsWith(variable + "_Level_")) + { + int level = 0; + if (Int32.TryParse(keyName.Replace(variable + "_Level_", ""), out level) && !exceptions.ContainsKey(level)) + { + exceptions.Add(level, new List()); + string value = config.GetString(keyName, string.Empty); + string[] parts = value.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); + + foreach (string s in parts) + exceptions[level].Add(s.Trim()); + } + } + } + } + + public GridRegion GetHomeRegion(UUID userID, out Vector3 position, out Vector3 lookAt) { position = new Vector3(128, 128, 0); lookAt = Vector3.UnitY; @@ -166,13 +209,39 @@ namespace OpenSim.Services.HypergridService m_log.DebugFormat("[USER AGENT SERVICE]: Request to login user {0} {1} (@{2}) to grid {3}", agentCircuit.firstname, agentCircuit.lastname, ((clientIP == null) ? "stored IP" : clientIP.Address.ToString()), gatekeeper.ServerURI); - if (m_UserAccountService.GetUserAccount(UUID.Zero, agentCircuit.AgentID) == null) + string gridName = gatekeeper.ServerURI; + + UserAccount account = m_UserAccountService.GetUserAccount(UUID.Zero, agentCircuit.AgentID); + if (account == null) { m_log.WarnFormat("[USER AGENT SERVICE]: Someone attempted to lauch a foreign user from here {0} {1}", agentCircuit.firstname, agentCircuit.lastname); reason = "Forbidden to launch your agents from here"; return false; } + // Is this user allowed to go there? + if (m_GridName != gridName) + { + if (m_ForeignTripsAllowed.ContainsKey(account.UserLevel)) + { + bool allowed = m_ForeignTripsAllowed[account.UserLevel]; + + if (m_ForeignTripsAllowed[account.UserLevel] && IsException(gridName, account.UserLevel, m_TripsAllowedExceptions)) + allowed = false; + + if (!m_ForeignTripsAllowed[account.UserLevel] && IsException(gridName, account.UserLevel, m_TripsDisallowedExceptions)) + allowed = true; + + if (!allowed) + { + reason = "Your world does not allow you to visit the destination"; + m_log.InfoFormat("[USER AGENT SERVICE]: Agents not permitted to visit {0}. Refusing service.", gridName); + return false; + } + } + } + + // Take the IP address + port of the gatekeeper (reg) plus the info of finalDestination GridRegion region = new GridRegion(gatekeeper); region.ServerURI = gatekeeper.ServerURI; @@ -189,7 +258,6 @@ namespace OpenSim.Services.HypergridService bool success = false; string myExternalIP = string.Empty; - string gridName = gatekeeper.ServerURI; m_log.DebugFormat("[USER AGENT SERVICE]: this grid: {0}, desired grid: {1}", m_GridName, gridName); @@ -588,6 +656,35 @@ namespace OpenSim.Services.HypergridService else return UUID.Zero; } + + #region Misc + + private bool IsException(string dest, int level, Dictionary> exceptions) + { + if (!exceptions.ContainsKey(level)) + return false; + + bool exception = false; + if (exceptions[level].Count > 0) // we have exceptions + { + string destination = dest; + if (!destination.EndsWith("/")) + destination += "/"; + + if (exceptions[level].Find(delegate(string s) + { + if (!s.EndsWith("/")) + s += "/"; + return s == destination; + }) != null) + exception = true; + } + + return exception; + } + + #endregion + } class TravelingAgentInfo diff --git a/bin/Robust.HG.ini.example b/bin/Robust.HG.ini.example index afb3f6feea..18094b7226 100644 --- a/bin/Robust.HG.ini.example +++ b/bin/Robust.HG.ini.example @@ -396,6 +396,18 @@ ServiceConnectors = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector,8003 ;AllowedClients = "" ;DeniedClients = "" + ;; Are foreign visitors allowed? + ;ForeignAgentsAllowed = true + ;; + ;; If ForeignAgentsAllowed is true, make exceptions using AllowExcept. + ;; Leave blank or commented for no exceptions. + ; AllowExcept = "http://griefer.com:8002, http://enemy.com:8002" + ;; + ;; If ForeignAgentsAllowed is false, make exceptions using DisallowExcept + ;; Leave blank or commented for no exceptions. + ; DisallowExcept = "http://myfriendgrid.com:8002, http://myboss.com:8002" + + [UserAgentService] LocalServiceModule = "OpenSim.Services.HypergridService.dll:UserAgentService" ;; for the service @@ -416,6 +428,24 @@ ServiceConnectors = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector,8003 ; User level required to be contacted from other grids ;LevelOutsideContacts = 0 + ;; Restrictions on destinations of local users. + ;; Are local users allowed to visit other grids? + ;; What user level? Use variables of this forrm: + ;; ForeignTripsAllowed_Level_ = true | false + ;; (the default is true) + ;; For example: + ; ForeignTripsAllowed_Level_0 = false + ; ForeignTripsAllowed_Level_200 = true ; true is default, no need to say it + ;; + ;; If ForeignTripsAllowed is false, make exceptions using DisallowExcept + ;; Leave blank or commented for no exceptions. + ; DisallowExcept_Level_0 = "http://myothergrid.com:8002, http://boss.com:8002" + ;; + ;; If ForeignTripsAllowed is true, make exceptions using AllowExcept. + ;; Leave blank or commented for no exceptions. + ; AllowExcept_Level_200 = "http://griefer.com:8002, http://enemy.com:8002" + + ; * The interface that local users get when they are in other grids. ; * This restricts the inventory operations while in other grids. ; * Still not completely safe, especially if users perform inventory operations diff --git a/bin/config-include/StandaloneCommon.ini.example b/bin/config-include/StandaloneCommon.ini.example index 048710a368..84de0ecab2 100644 --- a/bin/config-include/StandaloneCommon.ini.example +++ b/bin/config-include/StandaloneCommon.ini.example @@ -164,8 +164,17 @@ ;AllowedClients = "" ;DeniedClients = "" - ;; Are foreign visitors allowed + ;; Are foreign visitors allowed? ;ForeignAgentsAllowed = true + ;; + ;; If ForeignAgentsAllowed is true, make exceptions using AllowExcept. + ;; Leave blank or commented for no exceptions. + ; AllowExcept = "http://griefer.com:8002, http://enemy.com:8002" + ;; + ;; If ForeignAgentsAllowed is false, make exceptions using DisallowExcept + ;; Leave blank or commented for no exceptions. + ; DisallowExcept = "http://myfriendgrid.com:8002, http://myboss.com:8002" + [FreeswitchService] ;; If FreeSWITCH is not being used then you don't need to set any of these parameters @@ -271,5 +280,22 @@ ; Region_Test_1 = "DisallowForeigners" [UserAgentService] - ; User level required to be contacted from other grids + ;; User level required to be contacted from other grids ;LevelOutsideContacts = 0 + + ;; Restrictions on destinations of local users. + ;; Are local users allowed to visit other grids? + ;; What user level? Use variables of this forrm: + ;; ForeignTripsAllowed_Level_ = true | false + ;; (the default is true) + ;; For example: + ; ForeignTripsAllowed_Level_0 = false + ; ForeignTripsAllowed_Level_200 = true ; true is default, no need to say it + ;; + ;; If ForeignTripsAllowed is false, make exceptions using DisallowExcept + ;; Leave blank or commented for no exceptions. + ; DisallowExcept_Level_0 = "http://myothergrid.com:8002, http://boss.com:8002" + ;; + ;; If ForeignTripsAllowed is true, make exceptions using AllowExcept. + ;; Leave blank or commented for no exceptions. + ; AllowExcept_Level_200 = "http://griefer.com:8002, http://enemy.com:8002"