diff --git a/OpenSim/Framework/AgentCircuitManager.cs b/OpenSim/Framework/AgentCircuitManager.cs index e5dbb5a81a..49d7822416 100644 --- a/OpenSim/Framework/AgentCircuitManager.cs +++ b/OpenSim/Framework/AgentCircuitManager.cs @@ -36,6 +36,7 @@ namespace OpenSim.Framework public class AgentCircuitManager { public Dictionary AgentCircuits = new Dictionary(); + public Dictionary AgentCircuitsByUUID = new Dictionary(); public virtual AuthenticateResponse AuthenticateSession(UUID sessionID, UUID agentID, uint circuitcode) { @@ -86,10 +87,12 @@ namespace OpenSim.Framework if (AgentCircuits.ContainsKey(circuitCode)) { AgentCircuits[circuitCode] = agentData; + AgentCircuitsByUUID[agentData.AgentID] = agentData; } else { AgentCircuits.Add(circuitCode, agentData); + AgentCircuitsByUUID.Add(agentData.AgentID, agentData); } } } @@ -99,10 +102,26 @@ namespace OpenSim.Framework lock (AgentCircuits) { if (AgentCircuits.ContainsKey(circuitCode)) + { + UUID agentID = AgentCircuits[circuitCode].AgentID; AgentCircuits.Remove(circuitCode); + AgentCircuitsByUUID.Remove(agentID); + } } } + public virtual void RemoveCircuit(UUID agentID) + { + lock (AgentCircuits) + { + if (AgentCircuitsByUUID.ContainsKey(agentID)) + { + uint circuitCode = AgentCircuitsByUUID[agentID].circuitcode; + AgentCircuits.Remove(circuitCode); + AgentCircuitsByUUID.Remove(agentID); + } + } + } public AgentCircuitData GetAgentCircuitData(uint circuitCode) { AgentCircuitData agentCircuit = null; @@ -110,6 +129,13 @@ namespace OpenSim.Framework return agentCircuit; } + public AgentCircuitData GetAgentCircuitData(UUID agentID) + { + AgentCircuitData agentCircuit = null; + AgentCircuitsByUUID.TryGetValue(agentID, out agentCircuit); + return agentCircuit; + } + public void UpdateAgentData(AgentCircuitData agentData) { if (AgentCircuits.ContainsKey((uint) agentData.circuitcode)) diff --git a/OpenSim/Framework/Capabilities/Caps.cs b/OpenSim/Framework/Capabilities/Caps.cs index b27d0112af..62a1e17f50 100644 --- a/OpenSim/Framework/Capabilities/Caps.cs +++ b/OpenSim/Framework/Capabilities/Caps.cs @@ -99,6 +99,7 @@ namespace OpenSim.Framework.Capabilities // private static readonly string m_remoteParcelRequestPath = "0009/";// This is in the LandManagementModule. //private string eventQueue = "0100/"; + private IScene m_Scene; private IHttpServer m_httpListener; private UUID m_agentID; private IAssetService m_assetCache; @@ -130,9 +131,10 @@ namespace OpenSim.Framework.Capabilities public FetchInventoryDescendentsCAPS CAPSFetchInventoryDescendents = null; public GetClientDelegate GetClient = null; - public Caps(IAssetService assetCache, IHttpServer httpServer, string httpListen, uint httpPort, string capsPath, + public Caps(IScene scene, IAssetService assetCache, IHttpServer httpServer, string httpListen, uint httpPort, string capsPath, UUID agent, bool dumpAssetsToFile, string regionName) { + m_Scene = scene; m_assetCache = assetCache; m_capsObjectPath = capsPath; m_httpListener = httpServer; @@ -278,7 +280,13 @@ namespace OpenSim.Framework.Capabilities public string CapsRequest(string request, string path, string param, OSHttpRequest httpRequest, OSHttpResponse httpResponse) { - //m_log.Debug("[CAPS]: Seed Caps Request in region: " + m_regionName); + m_log.Debug("[CAPS]: Seed Caps Request in region: " + m_regionName); + + if (!m_Scene.CheckClient(m_agentID, httpRequest.RemoteIPEndPoint)) + { + m_log.DebugFormat("[CAPS]: Unauthorized CAPS client"); + return string.Empty; + } string result = LLSDHelpers.SerialiseLLSDReply(m_capsHandlers.CapsDetails); diff --git a/OpenSim/Framework/IScene.cs b/OpenSim/Framework/IScene.cs index 19ab409098..6798b7be8a 100644 --- a/OpenSim/Framework/IScene.cs +++ b/OpenSim/Framework/IScene.cs @@ -102,5 +102,7 @@ namespace OpenSim.Framework void AddCommand(object module, string command, string shorthelp, string longhelp, CommandDelegate callback); ISceneObject DeserializeObject(string representation); + + bool CheckClient(UUID agentID, System.Net.IPEndPoint ep); } } diff --git a/OpenSim/Region/CoreModules/Agent/Capabilities/CapabilitiesModule.cs b/OpenSim/Region/CoreModules/Agent/Capabilities/CapabilitiesModule.cs index 2a1355b9ef..a6f5d97ad2 100644 --- a/OpenSim/Region/CoreModules/Agent/Capabilities/CapabilitiesModule.cs +++ b/OpenSim/Region/CoreModules/Agent/Capabilities/CapabilitiesModule.cs @@ -107,7 +107,7 @@ namespace OpenSim.Region.CoreModules.Agent.Capabilities } Caps caps - = new Caps( + = new Caps(m_scene, m_scene.AssetService, MainServer.Instance, m_scene.RegionInfo.ExternalHostName, MainServer.Instance.Port, capsObjectPath, agentId, m_scene.DumpAssetsToFile, m_scene.RegionInfo.RegionName); diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index edbef4c884..401551de36 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -2629,34 +2629,23 @@ namespace OpenSim.Region.Framework.Scenes AgentCircuitData aCircuit = m_authenticateHandler.GetAgentCircuitData(client.CircuitCode); // Do the verification here - System.Net.EndPoint ep = client.GetClientEP(); + System.Net.IPEndPoint ep = (System.Net.IPEndPoint)client.GetClientEP(); if (aCircuit != null) { - if ((aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0) + if (!VerifyClient(aCircuit, ep, out vialogin)) { - m_log.DebugFormat("[Scene]: Incoming client {0} {1} in region {2} via Login", aCircuit.firstname, aCircuit.lastname, RegionInfo.RegionName); - vialogin = true; - IUserAgentVerificationModule userVerification = RequestModuleInterface(); - if (userVerification != null && ep != null) + // uh-oh, this is fishy + m_log.WarnFormat("[Scene]: Agent {0} with session {1} connecting with unidentified end point {2}. Refusing service.", + client.AgentId, client.SessionId, ep.ToString()); + try { - if (!userVerification.VerifyClient(aCircuit, ep.ToString())) - { - // uh-oh, this is fishy - m_log.WarnFormat("[Scene]: Agent {0} with session {1} connecting with unidentified end point {2}. Refusing service.", - client.AgentId, client.SessionId, ep.ToString()); - try - { - client.Close(); - } - catch (Exception e) - { - m_log.DebugFormat("[Scene]: Exception while closing aborted client: {0}", e.StackTrace); - } - return; - } - else - m_log.DebugFormat("[Scene]: User Client Verification for {0} {1} returned true", aCircuit.firstname, aCircuit.lastname); + client.Close(); } + catch (Exception e) + { + m_log.DebugFormat("[Scene]: Exception while closing aborted client: {0}", e.StackTrace); + } + return; } } @@ -2682,7 +2671,65 @@ namespace OpenSim.Region.Framework.Scenes EventManager.TriggerOnClientLogin(client); } - + private bool VerifyClient(AgentCircuitData aCircuit, System.Net.IPEndPoint ep, out bool vialogin) + { + vialogin = false; + + // Do the verification here + if ((aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0) + { + m_log.DebugFormat("[Scene]: Incoming client {0} {1} in region {2} via Login", aCircuit.firstname, aCircuit.lastname, RegionInfo.RegionName); + vialogin = true; + IUserAgentVerificationModule userVerification = RequestModuleInterface(); + if (userVerification != null && ep != null) + { + if (!userVerification.VerifyClient(aCircuit, ep.Address.ToString())) + { + // uh-oh, this is fishy + m_log.DebugFormat("[Scene]: User Client Verification for {0} {1} in {2} returned false", aCircuit.firstname, aCircuit.lastname, RegionInfo.RegionName); + return false; + } + else + m_log.DebugFormat("[Scene]: User Client Verification for {0} {1} in {2} returned true", aCircuit.firstname, aCircuit.lastname, RegionInfo.RegionName); + } + } + + return true; + } + + // Called by Caps, on the first HTTP contact from the client + public override bool CheckClient(UUID agentID, System.Net.IPEndPoint ep) + { + AgentCircuitData aCircuit = m_authenticateHandler.GetAgentCircuitData(agentID); + if (aCircuit != null) + { + bool vialogin = false; + if (!VerifyClient(aCircuit, ep, out vialogin)) + { + // if it doesn't pass, we remove the agentcircuitdata altogether + // and the scene presence and the client, if they exist + try + { + ScenePresence sp = GetScenePresence(agentID); + if (sp != null) + sp.ControllingClient.Close(); + + // BANG! SLASH! + m_authenticateHandler.RemoveCircuit(agentID); + + return false; + } + catch (Exception e) + { + m_log.DebugFormat("[Scene]: Exception while closing aborted client: {0}", e.StackTrace); + } + } + else + return true; + } + + return false; + } /// /// Register for events from the client diff --git a/OpenSim/Region/Framework/Scenes/SceneBase.cs b/OpenSim/Region/Framework/Scenes/SceneBase.cs index 3218dadc24..bfc19b754c 100644 --- a/OpenSim/Region/Framework/Scenes/SceneBase.cs +++ b/OpenSim/Region/Framework/Scenes/SceneBase.cs @@ -536,5 +536,6 @@ namespace OpenSim.Region.Framework.Scenes get { return false; } } + public abstract bool CheckClient(UUID agentID, System.Net.IPEndPoint ep); } } diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneBaseTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneBaseTests.cs index dd9f8f6654..42587c1116 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/SceneBaseTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/SceneBaseTests.cs @@ -70,6 +70,11 @@ namespace OpenSim.Region.Framework.Scenes.Tests { throw new NotImplementedException(); } + + public override bool CheckClient(UUID agentID, System.Net.IPEndPoint ep) + { + throw new NotImplementedException(); + } } [Test] diff --git a/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs b/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs index 3e91e3a113..42eca05ec5 100644 --- a/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs +++ b/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs @@ -204,6 +204,11 @@ namespace OpenSim.Services.Connectors.Hypergrid return args; } + public void SetClientToken(UUID sessionID, string token) + { + // no-op + } + public GridRegion GetHomeRegion(UUID userID, out Vector3 position, out Vector3 lookAt) { position = Vector3.UnitY; lookAt = Vector3.UnitY; diff --git a/OpenSim/Services/HypergridService/UserAgentService.cs b/OpenSim/Services/HypergridService/UserAgentService.cs index 64f7e8aaca..01729607fa 100644 --- a/OpenSim/Services/HypergridService/UserAgentService.cs +++ b/OpenSim/Services/HypergridService/UserAgentService.cs @@ -148,6 +148,15 @@ namespace OpenSim.Services.HypergridService return true; } + public void SetClientToken(UUID sessionID, string token) + { + if (m_TravelingAgents.ContainsKey(sessionID)) + { + m_log.DebugFormat("[USER AGENT SERVICE]: Setting token {0} for session {1}", token, sessionID); + m_TravelingAgents[sessionID].ClientToken = token; + } + } + TravelingAgentInfo UpdateTravelInfo(AgentCircuitData agentCircuit, GridRegion region) { TravelingAgentInfo travel = new TravelingAgentInfo(); @@ -203,22 +212,16 @@ namespace OpenSim.Services.HypergridService public bool VerifyClient(UUID sessionID, string token) { - return true; + m_log.DebugFormat("[USER AGENT SERVICE]: Verifying Client session {0} with token {1}", sessionID, token); + //return true; // Commenting this for now until I understand better what part of a sender's // info stays unchanged throughout a session // - //if (m_TravelingAgents.ContainsKey(sessionID)) - //{ - // // Aquiles heel. Must trust the first grid upon login - // if (m_TravelingAgents[sessionID].ClientToken == string.Empty) - // { - // m_TravelingAgents[sessionID].ClientToken = token; - // return true; - // } - // return m_TravelingAgents[sessionID].ClientToken == token; - //} - //return false; + if (m_TravelingAgents.ContainsKey(sessionID)) + return m_TravelingAgents[sessionID].ClientToken == token; + + return false; } public bool VerifyAgent(UUID sessionID, string token) diff --git a/OpenSim/Services/Interfaces/IGatekeeperService.cs b/OpenSim/Services/Interfaces/IGatekeeperService.cs index ca7b9b3324..2d397bc03d 100644 --- a/OpenSim/Services/Interfaces/IGatekeeperService.cs +++ b/OpenSim/Services/Interfaces/IGatekeeperService.cs @@ -49,6 +49,7 @@ namespace OpenSim.Services.Interfaces public interface IUserAgentService { bool LoginAgentToGrid(AgentCircuitData agent, GridRegion gatekeeper, GridRegion finalDestination, out string reason); + void SetClientToken(UUID sessionID, string token); void LogoutAgent(UUID userID, UUID sessionID); GridRegion GetHomeRegion(UUID userID, out Vector3 position, out Vector3 lookAt); diff --git a/OpenSim/Services/LLLoginService/LLLoginService.cs b/OpenSim/Services/LLLoginService/LLLoginService.cs index 9e24a396c1..7471c7721d 100644 --- a/OpenSim/Services/LLLoginService/LLLoginService.cs +++ b/OpenSim/Services/LLLoginService/LLLoginService.cs @@ -329,7 +329,7 @@ namespace OpenSim.Services.LLLoginService // Instantiate/get the simulation interface and launch an agent at the destination // string reason = string.Empty; - AgentCircuitData aCircuit = LaunchAgentAtGrid(gatekeeper, destination, account, avatar, session, secureSession, position, where, clientVersion, out where, out reason); + AgentCircuitData aCircuit = LaunchAgentAtGrid(gatekeeper, destination, account, avatar, session, secureSession, position, where, clientVersion, clientIP, out where, out reason); if (aCircuit == null) { @@ -589,7 +589,7 @@ namespace OpenSim.Services.LLLoginService } protected AgentCircuitData LaunchAgentAtGrid(GridRegion gatekeeper, GridRegion destination, UserAccount account, AvatarData avatar, - UUID session, UUID secureSession, Vector3 position, string currentWhere, string viewer, out string where, out string reason) + UUID session, UUID secureSession, Vector3 position, string currentWhere, string viewer, IPEndPoint clientIP, out string where, out string reason) { where = currentWhere; ISimulationService simConnector = null; @@ -655,7 +655,7 @@ namespace OpenSim.Services.LLLoginService { circuitCode = (uint)Util.RandomClass.Next(); ; aCircuit = MakeAgent(destination, account, avatar, session, secureSession, circuitCode, position, viewer); - success = LaunchAgentIndirectly(gatekeeper, destination, aCircuit, out reason); + success = LaunchAgentIndirectly(gatekeeper, destination, aCircuit, clientIP, out reason); if (!success && m_GridService != null) { // Try the fallback regions @@ -664,7 +664,7 @@ namespace OpenSim.Services.LLLoginService { foreach (GridRegion r in fallbacks) { - success = LaunchAgentIndirectly(gatekeeper, r, aCircuit, out reason); + success = LaunchAgentIndirectly(gatekeeper, r, aCircuit, clientIP, out reason); if (success) { where = "safe"; @@ -741,10 +741,15 @@ namespace OpenSim.Services.LLLoginService return simConnector.CreateAgent(region, aCircuit, (int)Constants.TeleportFlags.ViaLogin, out reason); } - private bool LaunchAgentIndirectly(GridRegion gatekeeper, GridRegion destination, AgentCircuitData aCircuit, out string reason) + private bool LaunchAgentIndirectly(GridRegion gatekeeper, GridRegion destination, AgentCircuitData aCircuit, IPEndPoint clientIP, out string reason) { m_log.Debug("[LLOGIN SERVICE] Launching agent at " + destination.RegionName); - return m_UserAgentService.LoginAgentToGrid(aCircuit, gatekeeper, destination, out reason); + if (m_UserAgentService.LoginAgentToGrid(aCircuit, gatekeeper, destination, out reason)) + { + m_UserAgentService.SetClientToken(aCircuit.SessionID, clientIP.Address.ToString()); + return true; + } + return false; } #region Console Commands