From 0413d052a3ec541164049e7d39278c57fb92ed06 Mon Sep 17 00:00:00 2001 From: diva Date: Tue, 14 Apr 2009 19:35:35 +0000 Subject: Adds session authentication upon NewUserConnections. Adds user key authentication (in safemode only) upon CreateChildAgents. All of this for Hypergrid users too. This addresses assorted spoofing vulnerabilities. --- .../CreateCommsManager/CreateCommsManagerPlugin.cs | 10 +- OpenSim/Client/Linden/LLStandaloneLoginModule.cs | 2 +- .../Communications/Clients/RegionClient.cs | 7 +- .../Framework/Communications/IAuthentication.cs | 1 + OpenSim/Framework/Communications/IUserService.cs | 4 + .../Communications/Services/LoginService.cs | 46 +++++ .../Communications/Tests/Cache/AssetCacheTests.cs | 5 + .../Framework/Communications/UserManagerBase.cs | 15 ++ OpenSim/Framework/Util.cs | 16 ++ .../Grid/UserServer.Modules/UserLoginService.cs | 1 + OpenSim/Grid/UserServer.Modules/UserManager.cs | 85 ++------ .../Hypergrid/HGCommunicationsGridMode.cs | 1 + .../Communications/Hypergrid/HGInventoryService.cs | 6 +- .../Communications/Hypergrid/HGUserServices.cs | 221 ++++++++++++++------- .../Communications/REST/RESTInterregionComms.cs | 79 +++++++- .../Hypergrid/HGStandaloneInventoryModule.cs | 2 +- .../Hypergrid/HGStandaloneLoginModule.cs | 3 +- OpenSim/Region/Framework/Scenes/Scene.cs | 93 +++++---- 18 files changed, 403 insertions(+), 194 deletions(-) diff --git a/OpenSim/ApplicationPlugins/CreateCommsManager/CreateCommsManagerPlugin.cs b/OpenSim/ApplicationPlugins/CreateCommsManager/CreateCommsManagerPlugin.cs index 70803c8..3985f42 100644 --- a/OpenSim/ApplicationPlugins/CreateCommsManager/CreateCommsManagerPlugin.cs +++ b/OpenSim/ApplicationPlugins/CreateCommsManager/CreateCommsManagerPlugin.cs @@ -214,20 +214,20 @@ namespace OpenSim.ApplicationPlugins.CreateCommsManager HGInventoryServiceClient inventoryService = new HGInventoryServiceClient(m_openSim.NetServersInfo.InventoryURL, null, false); inventoryService.AddPlugin(m_openSim.ConfigurationSettings.StandaloneInventoryPlugin, m_openSim.ConfigurationSettings.StandaloneInventorySource); - LocalUserServices userService = + LocalUserServices localuserService = new LocalUserServices( m_openSim.NetServersInfo.DefaultHomeLocX, m_openSim.NetServersInfo.DefaultHomeLocY, inventoryService); - userService.AddPlugin(m_openSim.ConfigurationSettings.StandaloneUserPlugin, m_openSim.ConfigurationSettings.StandaloneUserSource); + localuserService.AddPlugin(m_openSim.ConfigurationSettings.StandaloneUserPlugin, m_openSim.ConfigurationSettings.StandaloneUserSource); + HGUserServices userService = new HGUserServices(localuserService); HGGridServicesStandalone gridService = new HGGridServicesStandalone(m_openSim.NetServersInfo, m_httpServer, m_openSim.AssetCache, m_openSim.SceneManager); - // LocalLoginService loginService = CreateLoginService(libraryRootFolder, inventoryService, userService, gridService.LocalBackend); - m_commsManager = new HGCommunicationsStandalone(m_openSim.NetServersInfo, m_httpServer, m_openSim.AssetCache, - userService, userService, inventoryService, gridService, userService, libraryRootFolder, m_openSim.ConfigurationSettings.DumpAssetsToFile); + userService, localuserService, inventoryService, gridService, userService, libraryRootFolder, m_openSim.ConfigurationSettings.DumpAssetsToFile); inventoryService.UserProfileCache = m_commsManager.UserProfileCacheService; HGServices = gridService; + userService.SetCommunicationsManager(m_commsManager); CreateGridInfoService(); } diff --git a/OpenSim/Client/Linden/LLStandaloneLoginModule.cs b/OpenSim/Client/Linden/LLStandaloneLoginModule.cs index 00407fd..8d4ac37 100644 --- a/OpenSim/Client/Linden/LLStandaloneLoginModule.cs +++ b/OpenSim/Client/Linden/LLStandaloneLoginModule.cs @@ -103,7 +103,7 @@ namespace OpenSim.Client.Linden IHttpServer httpServer = m_firstScene.CommsManager.HttpServer; //TODO: fix the casting of the user service, maybe by registering the userManagerBase with scenes, or refactoring so we just need a IUserService reference - m_loginService = new LLStandaloneLoginService((UserManagerBase)m_firstScene.CommsManager.UserService, welcomeMessage, m_firstScene.CommsManager.InterServiceInventoryService, m_firstScene.CommsManager.NetworkServersInfo, authenticate, rootFolder, this); + m_loginService = new LLStandaloneLoginService((UserManagerBase)m_firstScene.CommsManager.UserAdminService, welcomeMessage, m_firstScene.CommsManager.InterServiceInventoryService, m_firstScene.CommsManager.NetworkServersInfo, authenticate, rootFolder, this); httpServer.AddXmlRPCHandler("login_to_simulator", m_loginService.XmlRpcLoginMethod); diff --git a/OpenSim/Framework/Communications/Clients/RegionClient.cs b/OpenSim/Framework/Communications/Clients/RegionClient.cs index 27353b0..da3f620 100644 --- a/OpenSim/Framework/Communications/Clients/RegionClient.cs +++ b/OpenSim/Framework/Communications/Clients/RegionClient.cs @@ -43,7 +43,7 @@ namespace OpenSim.Framework.Communications.Clients { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - public bool DoCreateChildAgentCall(RegionInfo region, AgentCircuitData aCircuit) + public bool DoCreateChildAgentCall(RegionInfo region, AgentCircuitData aCircuit, string authKey) { // Eventually, we want to use a caps url instead of the agentID string uri = "http://" + region.ExternalEndPoint.Address + ":" + region.HttpPort + "/agent/" + aCircuit.AgentID + "/"; @@ -54,6 +54,7 @@ namespace OpenSim.Framework.Communications.Clients AgentCreateRequest.ContentType = "application/json"; AgentCreateRequest.Timeout = 10000; //AgentCreateRequest.KeepAlive = false; + AgentCreateRequest.Headers.Add("Authorization", authKey); // Fill it in OSDMap args = null; @@ -80,7 +81,7 @@ namespace OpenSim.Framework.Communications.Clients } catch (Exception e) { - m_log.WarnFormat("[OSG2]: Exception thrown on serialization of ChildCreate: {0}", e.Message); + m_log.WarnFormat("[REST COMMS]: Exception thrown on serialization of ChildCreate: {0}", e.Message); // ignore. buffer will be empty, caller should check. } @@ -91,7 +92,7 @@ namespace OpenSim.Framework.Communications.Clients os = AgentCreateRequest.GetRequestStream(); os.Write(buffer, 0, strBuffer.Length); //Send it os.Close(); - //m_log.InfoFormat("[REST COMMS]: Posted ChildAgentUpdate request to remote sim {0}", uri); + //m_log.InfoFormat("[REST COMMS]: Posted CreateChildAgent request to remote sim {0}", uri); } //catch (WebException ex) catch diff --git a/OpenSim/Framework/Communications/IAuthentication.cs b/OpenSim/Framework/Communications/IAuthentication.cs index 0f62569..bd568e4 100644 --- a/OpenSim/Framework/Communications/IAuthentication.cs +++ b/OpenSim/Framework/Communications/IAuthentication.cs @@ -34,5 +34,6 @@ namespace OpenSim.Framework.Communications { string GetNewKey(string url, UUID userID, UUID authToken); bool VerifyKey(UUID userID, string key); + bool VerifySession(UUID iserID, UUID sessionID); } } diff --git a/OpenSim/Framework/Communications/IUserService.cs b/OpenSim/Framework/Communications/IUserService.cs index 3c09b40..3a56d35 100644 --- a/OpenSim/Framework/Communications/IUserService.cs +++ b/OpenSim/Framework/Communications/IUserService.cs @@ -119,5 +119,9 @@ namespace OpenSim.Framework.Communications /// /// The agent that we're retreiving the friends Data. List GetUserFriendList(UUID friendlistowner); + + // This probably shouldn't be here, it belongs to IAuthentication + // But since Scenes only have IUserService references, I'm placing it here for now. + bool VerifySession(UUID userID, UUID sessionID); } } diff --git a/OpenSim/Framework/Communications/Services/LoginService.cs b/OpenSim/Framework/Communications/Services/LoginService.cs index d9556e4..d491309 100644 --- a/OpenSim/Framework/Communications/Services/LoginService.cs +++ b/OpenSim/Framework/Communications/Services/LoginService.cs @@ -37,6 +37,7 @@ using log4net; using Nwc.XmlRpc; using OpenMetaverse; using OpenMetaverse.StructuredData; +using OpenSim.Framework; using OpenSim.Framework.Communications.Cache; using OpenSim.Framework.Statistics; @@ -194,6 +195,12 @@ namespace OpenSim.Framework.Communications.Services CreateAgent(userProfile, request); + // We need to commit the agent right here, even though the userProfile info is not complete + // at this point. There is another commit further down. + // This is for the new sessionID to be stored so that the region can check it for session authentication. + // CustomiseResponse->PrepareLoginToRegion + CommitAgent(ref userProfile); + try { UUID agentID = userProfile.ID; @@ -1108,5 +1115,44 @@ namespace OpenSim.Framework.Communications.Services { return false; } + + public XmlRpcResponse XmlRPCCheckAuthSession(XmlRpcRequest request) + { + XmlRpcResponse response = new XmlRpcResponse(); + Hashtable requestData = (Hashtable)request.Params[0]; + + string authed = "FALSE"; + if (requestData.Contains("avatar_uuid") && requestData.Contains("session_id")) + { + UUID guess_aid; + UUID guess_sid; + + UUID.TryParse((string)requestData["avatar_uuid"], out guess_aid); + if (guess_aid == UUID.Zero) + { + return Util.CreateUnknownUserErrorResponse(); + } + UUID.TryParse((string)requestData["session_id"], out guess_sid); + if (guess_sid == UUID.Zero) + { + return Util.CreateUnknownUserErrorResponse(); + } + if (m_userManager.VerifySession(guess_aid, guess_sid)) + { + authed = "TRUE"; + } + m_log.InfoFormat("[UserManager]: CheckAuthSession TRUE for user {0}", guess_aid); + } + else + { + m_log.InfoFormat("[UserManager]: CheckAuthSession FALSE"); + return Util.CreateUnknownUserErrorResponse(); + } + Hashtable responseData = new Hashtable(); + responseData["auth_session"] = authed; + response.Value = responseData; + return response; + } + } } diff --git a/OpenSim/Framework/Communications/Tests/Cache/AssetCacheTests.cs b/OpenSim/Framework/Communications/Tests/Cache/AssetCacheTests.cs index 5d6bc8d..178c356 100644 --- a/OpenSim/Framework/Communications/Tests/Cache/AssetCacheTests.cs +++ b/OpenSim/Framework/Communications/Tests/Cache/AssetCacheTests.cs @@ -178,6 +178,11 @@ namespace OpenSim.Framework.Communications.Tests { throw new NotImplementedException(); } + + public bool VerifySession(UUID userID, UUID sessionID) + { + return true; + } } [Test] diff --git a/OpenSim/Framework/Communications/UserManagerBase.cs b/OpenSim/Framework/Communications/UserManagerBase.cs index 155f5cd..1115041 100644 --- a/OpenSim/Framework/Communications/UserManagerBase.cs +++ b/OpenSim/Framework/Communications/UserManagerBase.cs @@ -839,6 +839,21 @@ namespace OpenSim.Framework.Communications } } + public bool VerifySession(UUID userID, UUID sessionID) + { + UserProfileData userProfile = GetUserProfile(userID); + + if (userProfile != null && userProfile.CurrentAgent != null) + { + m_log.DebugFormat("[USERAUTH]: Verifying session {0} for {1}; current session {2}", sessionID, userID, userProfile.CurrentAgent.SessionID); + if (userProfile.CurrentAgent.SessionID == sessionID) + { + return true; + } + } + return false; + } + #endregion } } diff --git a/OpenSim/Framework/Util.cs b/OpenSim/Framework/Util.cs index 7019096..f1993b2 100644 --- a/OpenSim/Framework/Util.cs +++ b/OpenSim/Framework/Util.cs @@ -26,6 +26,7 @@ */ using System; +using System.Collections; using System.Collections.Generic; using System.Data; using System.Globalization; @@ -820,6 +821,21 @@ namespace OpenSim.Framework } /// + /// Returns an error message that the user could not be found in the database + /// + /// XML string consisting of a error element containing individual error(s) + public static XmlRpcResponse CreateUnknownUserErrorResponse() + { + XmlRpcResponse response = new XmlRpcResponse(); + Hashtable responseData = new Hashtable(); + responseData["error_type"] = "unknown_user"; + responseData["error_desc"] = "The user requested is not in the database"; + + response.Value = responseData; + return response; + } + + /// /// Converts a byte array in big endian order into an ulong. /// /// diff --git a/OpenSim/Grid/UserServer.Modules/UserLoginService.cs b/OpenSim/Grid/UserServer.Modules/UserLoginService.cs index 3598ac6..795efaa 100644 --- a/OpenSim/Grid/UserServer.Modules/UserLoginService.cs +++ b/OpenSim/Grid/UserServer.Modules/UserLoginService.cs @@ -83,6 +83,7 @@ namespace OpenSim.Grid.UserServer.Modules m_httpServer.AddXmlRPCHandler("login_to_simulator", XmlRpcLoginMethod); m_httpServer.AddHTTPHandler("login", ProcessHTMLLogin); m_httpServer.AddXmlRPCHandler("set_login_params", XmlRPCSetLoginParams); + m_httpServer.AddXmlRPCHandler("check_auth_session", XmlRPCCheckAuthSession); if (registerLLSDHandler) { diff --git a/OpenSim/Grid/UserServer.Modules/UserManager.cs b/OpenSim/Grid/UserServer.Modules/UserManager.cs index 515c2bf..33b43e4 100644 --- a/OpenSim/Grid/UserServer.Modules/UserManager.cs +++ b/OpenSim/Grid/UserServer.Modules/UserManager.cs @@ -109,7 +109,6 @@ namespace OpenSim.Grid.UserServer.Modules m_httpServer.AddXmlRPCHandler("update_user_current_region", XmlRPCAtRegion); m_httpServer.AddXmlRPCHandler("logout_of_simulator", XmlRPCLogOffUserMethodUUID); m_httpServer.AddXmlRPCHandler("get_agent_by_uuid", XmlRPCGetAgentMethodUUID); - m_httpServer.AddXmlRPCHandler("check_auth_session", XmlRPCCheckAuthSession); m_httpServer.AddXmlRPCHandler("update_user_profile", XmlRpcResponseXmlRPCUpdateUserProfile); @@ -133,21 +132,6 @@ namespace OpenSim.Grid.UserServer.Modules return "OK"; } - /// - /// Returns an error message that the user could not be found in the database - /// - /// XML string consisting of a error element containing individual error(s) - public XmlRpcResponse CreateUnknownUserErrorResponse() - { - XmlRpcResponse response = new XmlRpcResponse(); - Hashtable responseData = new Hashtable(); - responseData["error_type"] = "unknown_user"; - responseData["error_desc"] = "The user requested is not in the database"; - - response.Value = responseData; - return response; - } - public XmlRpcResponse AvatarPickerListtoXmlRPCResponse(UUID queryID, List returnUsers) { XmlRpcResponse response = new XmlRpcResponse(); @@ -278,7 +262,7 @@ namespace OpenSim.Grid.UserServer.Modules string query = (string)requestData["avatar_name"]; if (null == query) - return CreateUnknownUserErrorResponse(); + return Util.CreateUnknownUserErrorResponse(); // Regex objAlphaNumericPattern = new Regex("[^a-zA-Z0-9]"); @@ -289,17 +273,17 @@ namespace OpenSim.Grid.UserServer.Modules userProfile = m_userDataBaseService.GetUserProfile(querysplit[0], querysplit[1]); if (userProfile == null) { - return CreateUnknownUserErrorResponse(); + return Util.CreateUnknownUserErrorResponse(); } } else { - return CreateUnknownUserErrorResponse(); + return Util.CreateUnknownUserErrorResponse(); } } else { - return CreateUnknownUserErrorResponse(); + return Util.CreateUnknownUserErrorResponse(); } return ProfileToXmlRPCResponse(userProfile); @@ -322,17 +306,17 @@ namespace OpenSim.Grid.UserServer.Modules } catch (FormatException) { - return CreateUnknownUserErrorResponse(); + return Util.CreateUnknownUserErrorResponse(); } if (userProfile == null) { - return CreateUnknownUserErrorResponse(); + return Util.CreateUnknownUserErrorResponse(); } } else { - return CreateUnknownUserErrorResponse(); + return Util.CreateUnknownUserErrorResponse(); } return ProfileToXmlRPCResponse(userProfile); @@ -353,20 +337,20 @@ namespace OpenSim.Grid.UserServer.Modules if (guess == UUID.Zero) { - return CreateUnknownUserErrorResponse(); + return Util.CreateUnknownUserErrorResponse(); } userProfile = m_userDataBaseService.GetUserProfile(guess); if (userProfile == null) { - return CreateUnknownUserErrorResponse(); + return Util.CreateUnknownUserErrorResponse(); } // no agent??? if (userProfile.CurrentAgent == null) { - return CreateUnknownUserErrorResponse(); + return Util.CreateUnknownUserErrorResponse(); } Hashtable responseData = new Hashtable(); @@ -381,53 +365,12 @@ namespace OpenSim.Grid.UserServer.Modules } else { - return CreateUnknownUserErrorResponse(); + return Util.CreateUnknownUserErrorResponse(); } return response; } - public XmlRpcResponse XmlRPCCheckAuthSession(XmlRpcRequest request) - { - XmlRpcResponse response = new XmlRpcResponse(); - Hashtable requestData = (Hashtable)request.Params[0]; - UserProfileData userProfile; - - string authed = "FALSE"; - if (requestData.Contains("avatar_uuid") && requestData.Contains("session_id")) - { - UUID guess_aid; - UUID guess_sid; - - UUID.TryParse((string)requestData["avatar_uuid"], out guess_aid); - if (guess_aid == UUID.Zero) - { - return CreateUnknownUserErrorResponse(); - } - UUID.TryParse((string)requestData["session_id"], out guess_sid); - if (guess_sid == UUID.Zero) - { - return CreateUnknownUserErrorResponse(); - } - userProfile = m_userDataBaseService.GetUserProfile(guess_aid); - if (userProfile != null && userProfile.CurrentAgent != null && - userProfile.CurrentAgent.SessionID == guess_sid) - { - authed = "TRUE"; - } - m_log.InfoFormat("[UserManager]: CheckAuthSession TRUE for user {0}", guess_aid); - } - else - { - m_log.InfoFormat("[UserManager]: CheckAuthSession FALSE"); - return CreateUnknownUserErrorResponse(); - } - Hashtable responseData = new Hashtable(); - responseData["auth_session"] = authed; - response.Value = responseData; - return response; - } - public XmlRpcResponse XmlRpcResponseXmlRPCUpdateUserProfile(XmlRpcRequest request) { m_log.Debug("[UserManager]: Got request to update user profile"); @@ -437,14 +380,14 @@ namespace OpenSim.Grid.UserServer.Modules if (!requestData.Contains("avatar_uuid")) { - return CreateUnknownUserErrorResponse(); + return Util.CreateUnknownUserErrorResponse(); } UUID UserUUID = new UUID((string)requestData["avatar_uuid"]); UserProfileData userProfile = m_userDataBaseService.GetUserProfile(UserUUID); if (null == userProfile) { - return CreateUnknownUserErrorResponse(); + return Util.CreateUnknownUserErrorResponse(); } // don't know how yet. if (requestData.Contains("AllowPublish")) @@ -656,7 +599,7 @@ namespace OpenSim.Grid.UserServer.Modules } else { - return CreateUnknownUserErrorResponse(); + return Util.CreateUnknownUserErrorResponse(); } return response; diff --git a/OpenSim/Region/Communications/Hypergrid/HGCommunicationsGridMode.cs b/OpenSim/Region/Communications/Hypergrid/HGCommunicationsGridMode.cs index d1be94f..2ef0fd3 100644 --- a/OpenSim/Region/Communications/Hypergrid/HGCommunicationsGridMode.cs +++ b/OpenSim/Region/Communications/Hypergrid/HGCommunicationsGridMode.cs @@ -59,6 +59,7 @@ namespace OpenSim.Region.Communications.Hypergrid // The HG InventoryService always uses secure handlers HGInventoryServiceClient invService = new HGInventoryServiceClient(serversInfo.InventoryURL, this.m_userProfileCacheService, true); + invService.UserProfileCache = m_userProfileCacheService; AddSecureInventoryService(invService); m_defaultInventoryHost = invService.Host; if (SecureInventoryService != null) diff --git a/OpenSim/Region/Communications/Hypergrid/HGInventoryService.cs b/OpenSim/Region/Communications/Hypergrid/HGInventoryService.cs index 5e3f229..156137e 100644 --- a/OpenSim/Region/Communications/Hypergrid/HGInventoryService.cs +++ b/OpenSim/Region/Communications/Hypergrid/HGInventoryService.cs @@ -62,7 +62,7 @@ namespace OpenSim.Region.Communications.Hypergrid { _inventoryServerUrl = HGNetworkServersInfo.ServerURI(inventoryServerUrl); //m_Uri = new Uri(_inventoryServerUrl); - m_userProfileCache = userProfileCacheService; + //m_userProfileCache = userProfileCacheService; m_gridmode = gridmode; } @@ -506,6 +506,9 @@ namespace OpenSim.Region.Communications.Hypergrid private bool IsLocalStandaloneUser(UUID userID) { + if (m_userProfileCache == null) + return false; + CachedUserInfo uinfo = m_userProfileCache.GetUserDetails(userID); if (uinfo == null) return true; @@ -522,6 +525,7 @@ namespace OpenSim.Region.Communications.Hypergrid private string GetUserInventoryURI(UUID userID) { string invURI = _inventoryServerUrl; + CachedUserInfo uinfo = m_userProfileCache.GetUserDetails(userID); if ((uinfo == null) || (uinfo.UserProfile == null)) return invURI; diff --git a/OpenSim/Region/Communications/Hypergrid/HGUserServices.cs b/OpenSim/Region/Communications/Hypergrid/HGUserServices.cs index ef08421..05ae5a9 100644 --- a/OpenSim/Region/Communications/Hypergrid/HGUserServices.cs +++ b/OpenSim/Region/Communications/Hypergrid/HGUserServices.cs @@ -31,7 +31,10 @@ using System.Collections.Generic; using OpenMetaverse; using OpenSim.Framework; using OpenSim.Framework.Communications; +using OpenSim.Framework.Communications.Cache; +using OpenSim.Framework.Communications.Clients; using OpenSim.Region.Communications.OGS1; +using OpenSim.Region.Communications.Local; namespace OpenSim.Region.Communications.Hypergrid { @@ -40,32 +43,30 @@ namespace OpenSim.Region.Communications.Hypergrid /// so it always fails for foreign users. /// Later it needs to talk with the foreign users' user servers. /// - public class HGUserServices : IUserService, IAvatarService, IMessagingService + public class HGUserServices : OGS1UserServices { //private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - //private HGCommunicationsGridMode m_parent; - private OGS1UserServices m_remoteUserServices; + //private CommunicationsManager m_parent; + //private OGS1UserServices m_remoteUserServices; + private LocalUserServices m_localUserServices; - public HGUserServices(HGCommunicationsGridMode parent) + // Constructor called when running in grid mode + public HGUserServices(CommunicationsManager parent) + : base(parent) { - //m_parent = parent; - m_remoteUserServices = new OGS1UserServices(parent); } - public UserProfileData ConvertXMLRPCDataToUserProfile(Hashtable data) + // Constructor called when running in standalone + public HGUserServices(LocalUserServices local) { - return m_remoteUserServices.ConvertXMLRPCDataToUserProfile(data); + m_localUserServices = local; } - public UserProfileData GetUserProfile(Uri uri) + // Called for standalone mode only, to set up the communications manager + public void SetCommunicationsManager(CommunicationsManager parent) { - throw new System.NotImplementedException(); - } - - public Uri GetUserUri(UserProfileData userProfile) - { - throw new NotImplementedException(); + m_commsManager = parent; } /// @@ -73,25 +74,15 @@ namespace OpenSim.Region.Communications.Hypergrid /// /// /// null if the request fails - public UserAgentData GetAgentByUUID(UUID userId) + public override UserAgentData GetAgentByUUID(UUID userId) { - return m_remoteUserServices.GetAgentByUUID(userId); - } - - public AvatarAppearance ConvertXMLRPCDataToAvatarAppearance(Hashtable data) - { - return m_remoteUserServices.ConvertXMLRPCDataToAvatarAppearance(data); - } + string url = string.Empty; + if ((m_localUserServices != null) && !IsForeignUser(userId, out url)) + return m_localUserServices.GetAgentByUUID(userId); - public List ConvertXMLRPCDataToAvatarPickerList(UUID queryID, Hashtable data) - { - return m_remoteUserServices.ConvertXMLRPCDataToAvatarPickerList(queryID, data); + return base.GetAgentByUUID(userId); } - public List ConvertXMLRPCDataToFriendListItemList(Hashtable data) - { - return m_remoteUserServices.ConvertXMLRPCDataToFriendListItemList(data); - } /// /// Logs off a user on the user server @@ -101,9 +92,13 @@ namespace OpenSim.Region.Communications.Hypergrid /// regionhandle /// final position /// final lookat - public void LogOffUser(UUID userid, UUID regionid, ulong regionhandle, Vector3 position, Vector3 lookat) + public override void LogOffUser(UUID userid, UUID regionid, ulong regionhandle, Vector3 position, Vector3 lookat) { - m_remoteUserServices.LogOffUser(userid, regionid, regionhandle, position, lookat); + string url = string.Empty; + if ((m_localUserServices != null) && !IsForeignUser(userid, out url)) + m_localUserServices.LogOffUser(userid, regionid, regionhandle, position, lookat); + else + base.LogOffUser(userid, regionid, regionhandle, position, lookat); } /// @@ -115,19 +110,29 @@ namespace OpenSim.Region.Communications.Hypergrid /// final position x /// final position y /// final position z - public void LogOffUser(UUID userid, UUID regionid, ulong regionhandle, float posx, float posy, float posz) + public override void LogOffUser(UUID userid, UUID regionid, ulong regionhandle, float posx, float posy, float posz) { - m_remoteUserServices.LogOffUser(userid, regionid, regionhandle, posx, posy, posz); + string url = string.Empty; + if ((m_localUserServices != null) && !IsForeignUser(userid, out url)) + m_localUserServices.LogOffUser(userid, regionid, regionhandle, posx, posy, posz); + else + base.LogOffUser(userid, regionid, regionhandle, posx, posy, posz); } - public UserProfileData GetUserProfile(string firstName, string lastName) + public override UserProfileData GetUserProfile(string firstName, string lastName) { + if (m_localUserServices != null) + return m_localUserServices.GetUserProfile(firstName, lastName); + return GetUserProfile(firstName + " " + lastName); } - public List GenerateAgentPickerRequestResponse(UUID queryID, string query) + public override List GenerateAgentPickerRequestResponse(UUID queryID, string query) { - return m_remoteUserServices.GenerateAgentPickerRequestResponse(queryID, query); + if (m_localUserServices != null) + return m_localUserServices.GenerateAgentPickerRequestResponse(queryID, query); + + return base.GenerateAgentPickerRequestResponse(queryID, query); } /// @@ -135,9 +140,11 @@ namespace OpenSim.Region.Communications.Hypergrid /// /// /// null if the request fails - public UserProfileData GetUserProfile(string name) + public override UserProfileData GetUserProfile(string name) { - return m_remoteUserServices.GetUserProfile(name); + // This doesn't exist in LocalUserServices + + return base.GetUserProfile(name); } /// @@ -145,14 +152,24 @@ namespace OpenSim.Region.Communications.Hypergrid /// /// /// null if the request fails - public UserProfileData GetUserProfile(UUID avatarID) + public override UserProfileData GetUserProfile(UUID avatarID) { - return m_remoteUserServices.GetUserProfile(avatarID); + string url = string.Empty; + // Unfortunately we can't query for foreigners here, + // because we'll end up in an infinite loop... + //if ((m_localUserServices != null) && (!IsForeignUser(avatarID, out url))) + if (m_localUserServices != null) + return m_localUserServices.GetUserProfile(avatarID); + + return base.GetUserProfile(avatarID); } - public void ClearUserAgent(UUID avatarID) + public override void ClearUserAgent(UUID avatarID) { - m_remoteUserServices.ClearUserAgent(avatarID); + if (m_localUserServices != null) + m_localUserServices.ClearUserAgent(avatarID); + else + base.ClearUserAgent(avatarID); } /// @@ -160,9 +177,12 @@ namespace OpenSim.Region.Communications.Hypergrid /// /// /// - public UserProfileData SetupMasterUser(string firstName, string lastName) + public override UserProfileData SetupMasterUser(string firstName, string lastName) { - return m_remoteUserServices.SetupMasterUser(firstName, lastName); + if (m_localUserServices != null) + return m_localUserServices.SetupMasterUser(firstName, lastName); + + return base.SetupMasterUser(firstName, lastName); } /// @@ -170,9 +190,12 @@ namespace OpenSim.Region.Communications.Hypergrid /// /// /// - public UserProfileData SetupMasterUser(string firstName, string lastName, string password) + public override UserProfileData SetupMasterUser(string firstName, string lastName, string password) { - return m_remoteUserServices.SetupMasterUser(firstName, lastName, password); + if (m_localUserServices != null) + return m_localUserServices.SetupMasterUser(firstName, lastName, password); + + return base.SetupMasterUser(firstName, lastName, password); } /// @@ -180,36 +203,47 @@ namespace OpenSim.Region.Communications.Hypergrid /// /// /// - public UserProfileData SetupMasterUser(UUID uuid) + public override UserProfileData SetupMasterUser(UUID uuid) { - return m_remoteUserServices.SetupMasterUser(uuid); + if (m_localUserServices != null) + return m_localUserServices.SetupMasterUser(uuid); + + return base.SetupMasterUser(uuid); } - public UUID AddUserProfile(string firstName, string lastName, string pass, uint regX, uint regY) + public override bool ResetUserPassword(string firstName, string lastName, string newPassword) { - return m_remoteUserServices.AddUserProfile(firstName, lastName, pass, regX, regY); + if (m_localUserServices != null) + return m_localUserServices.ResetUserPassword(firstName, lastName, newPassword); + else + return base.ResetUserPassword(firstName, lastName, newPassword); } - - public bool ResetUserPassword(string firstName, string lastName, string newPassword) - { - return m_remoteUserServices.ResetUserPassword(firstName, lastName, newPassword); - } - public bool UpdateUserProfile(UserProfileData userProfile) + public override bool UpdateUserProfile(UserProfileData userProfile) { - return m_remoteUserServices.UpdateUserProfile(userProfile); + string url = string.Empty; + if ((m_localUserServices != null) && (!IsForeignUser(userProfile.ID, out url))) + return m_localUserServices.UpdateUserProfile(userProfile); + + return base.UpdateUserProfile(userProfile); } #region IUserServices Friend Methods + + // NOTE: We're still not dealing with foreign user friends + /// /// Adds a new friend to the database for XUser /// /// The agent that who's friends list is being added to /// The agent that being added to the friends list of the friends list owner /// A uint bit vector for set perms that the friend being added has; 0 = none, 1=This friend can see when they sign on, 2 = map, 4 edit objects - public void AddNewUserFriend(UUID friendlistowner, UUID friend, uint perms) + public override void AddNewUserFriend(UUID friendlistowner, UUID friend, uint perms) { - m_remoteUserServices.AddNewUserFriend(friendlistowner, friend, perms); + if (m_localUserServices != null) + m_localUserServices.AddNewUserFriend(friendlistowner, friend, perms); + else + base.AddNewUserFriend(friendlistowner, friend, perms); } /// @@ -217,9 +251,12 @@ namespace OpenSim.Region.Communications.Hypergrid /// /// The agent that who's friends list is being updated /// The Ex-friend agent - public void RemoveUserFriend(UUID friendlistowner, UUID friend) + public override void RemoveUserFriend(UUID friendlistowner, UUID friend) { - m_remoteUserServices.RemoveUserFriend(friend, friend); + if (m_localUserServices != null) + m_localUserServices.RemoveUserFriend(friendlistowner, friend); + else + base.RemoveUserFriend(friend, friend); } /// @@ -228,39 +265,79 @@ namespace OpenSim.Region.Communications.Hypergrid /// The agent that who's friends list is being updated /// The agent that is getting or loosing permissions /// A uint bit vector for set perms that the friend being added has; 0 = none, 1=This friend can see when they sign on, 2 = map, 4 edit objects - public void UpdateUserFriendPerms(UUID friendlistowner, UUID friend, uint perms) + public override void UpdateUserFriendPerms(UUID friendlistowner, UUID friend, uint perms) { - m_remoteUserServices.UpdateUserFriendPerms(friendlistowner, friend, perms); + if (m_localUserServices != null) + m_localUserServices.UpdateUserFriendPerms(friendlistowner, friend, perms); + else + base.UpdateUserFriendPerms(friendlistowner, friend, perms); } /// /// Returns a list of FriendsListItems that describe the friends and permissions in the friend relationship for UUID friendslistowner /// /// The agent that we're retreiving the friends Data. - public List GetUserFriendList(UUID friendlistowner) + public override List GetUserFriendList(UUID friendlistowner) { - return m_remoteUserServices.GetUserFriendList(friendlistowner); + if (m_localUserServices != null) + return m_localUserServices.GetUserFriendList(friendlistowner); + + return base.GetUserFriendList(friendlistowner); } #endregion /// Appearance - public AvatarAppearance GetUserAppearance(UUID user) + public override AvatarAppearance GetUserAppearance(UUID user) { - return m_remoteUserServices.GetUserAppearance(user); + string url = string.Empty; + if ((m_localUserServices != null) && (!IsForeignUser(user, out url))) + return m_localUserServices.GetUserAppearance(user); + else + return base.GetUserAppearance(user); } - public void UpdateUserAppearance(UUID user, AvatarAppearance appearance) + public override void UpdateUserAppearance(UUID user, AvatarAppearance appearance) { - m_remoteUserServices.UpdateUserAppearance(user, appearance); + string url = string.Empty; + if ((m_localUserServices != null) && (!IsForeignUser(user, out url))) + m_localUserServices.UpdateUserAppearance(user, appearance); + else + base.UpdateUserAppearance(user, appearance); } #region IMessagingService - public Dictionary GetFriendRegionInfos(List uuids) + public override Dictionary GetFriendRegionInfos(List uuids) { - return m_remoteUserServices.GetFriendRegionInfos(uuids); + if (m_localUserServices != null) + return m_localUserServices.GetFriendRegionInfos(uuids); + + return base.GetFriendRegionInfos(uuids); } #endregion + protected override string GetUserServerURL(UUID userID) + { + string serverURL = string.Empty; + if (IsForeignUser(userID, out serverURL)) + return serverURL; + + return m_commsManager.NetworkServersInfo.UserURL; + } + + private bool IsForeignUser(UUID userID, out string userServerURL) + { + userServerURL = string.Empty; + CachedUserInfo uinfo = m_commsManager.UserProfileCacheService.GetUserDetails(userID); + if (uinfo != null) + { + if (!HGNetworkServersInfo.Singleton.IsLocalUser(uinfo.UserProfile)) + { + userServerURL = ((ForeignUserProfileData)(uinfo.UserProfile)).UserServerURI; + return true; + } + } + return false; + } } } diff --git a/OpenSim/Region/CoreModules/Communications/REST/RESTInterregionComms.cs b/OpenSim/Region/CoreModules/Communications/REST/RESTInterregionComms.cs index 87272a1..97ffeae 100644 --- a/OpenSim/Region/CoreModules/Communications/REST/RESTInterregionComms.cs +++ b/OpenSim/Region/CoreModules/Communications/REST/RESTInterregionComms.cs @@ -59,6 +59,9 @@ namespace OpenSim.Region.CoreModules.Communications.REST protected RegionToRegionClient m_regionClient; + protected bool m_safemode; + protected IPAddress m_thisIP; + #region IRegionModule public virtual void Initialise(Scene scene, IConfigSource config) @@ -74,6 +77,9 @@ namespace OpenSim.Region.CoreModules.Communications.REST { m_log.Info("[REST COMMS]: Enabling InterregionComms RESTComms module"); m_enabled = true; + if (config.Configs["Hypergrid"] != null) + m_safemode = config.Configs["Hypergrid"].GetBoolean("safemode", false); + InitOnce(scene); } } @@ -117,6 +123,7 @@ namespace OpenSim.Region.CoreModules.Communications.REST m_commsManager = scene.CommsManager; m_aScene = scene; m_regionClient = new RegionToRegionClient(m_aScene); + m_thisIP = Util.GetHostFromDNS(scene.RegionInfo.ExternalHostName); } protected virtual void AddHTTPHandlers() @@ -148,7 +155,7 @@ namespace OpenSim.Region.CoreModules.Communications.REST { m_regionClient.SendUserInformation(regInfo, aCircuit); - return m_regionClient.DoCreateChildAgentCall(regInfo, aCircuit); + return m_regionClient.DoCreateChildAgentCall(regInfo, aCircuit, "None"); } //else // m_log.Warn("[REST COMMS]: Region not found " + regionHandle); @@ -331,6 +338,7 @@ namespace OpenSim.Region.CoreModules.Communications.REST responsedata["content_type"] = "text/html"; responsedata["keepalive"] = false; + UUID agentID; string action; ulong regionHandle; @@ -378,6 +386,28 @@ namespace OpenSim.Region.CoreModules.Communications.REST protected virtual void DoAgentPost(Hashtable request, Hashtable responsedata, UUID id) { + if (m_safemode) + { + // Authentication + string authority = string.Empty; + string authToken = string.Empty; + if (!GetAuthentication(request, out authority, out authToken)) + { + m_log.InfoFormat("[REST COMMS]: Authentication failed for agent message {0}", request["uri"]); + responsedata["int_response_code"] = 403; + responsedata["str_response_string"] = "Forbidden"; + return ; + } + if (!VerifyKey(id, authority, authToken)) + { + m_log.InfoFormat("[REST COMMS]: Authentication failed for agent message {0}", request["uri"]); + responsedata["int_response_code"] = 403; + responsedata["str_response_string"] = "Forbidden"; + return ; + } + m_log.DebugFormat("[REST COMMS]: Authentication succeeded for {0}", id); + } + OSDMap args = RegionClient.GetOSDMap((string)request["body"]); if (args == null) { @@ -793,6 +823,53 @@ namespace OpenSim.Region.CoreModules.Communications.REST } } + public static bool GetAuthentication(Hashtable request, out string authority, out string authKey) + { + authority = string.Empty; + authKey = string.Empty; + + Uri authUri; + Hashtable headers = (Hashtable)request["headers"]; + + // Authorization keys look like this: + // http://orgrid.org:8002/ + if (headers.ContainsKey("authorization") && (string)headers["authorization"] != "None") + { + if (Uri.TryCreate((string)headers["authorization"], UriKind.Absolute, out authUri)) + { + authority = authUri.Authority; + authKey = authUri.PathAndQuery.Trim('/'); + m_log.DebugFormat("[REST COMMS]: Got authority {0} and key {1}", authority, authKey); + return true; + } + else + m_log.Debug("[REST COMMS]: Wrong format for Authorization header: " + (string)headers["authorization"]); + } + else + m_log.Debug("[REST COMMS]: Authorization header not found"); + + return false; + } + + bool VerifyKey(UUID userID, string authority, string key) + { + string[] parts = authority.Split(':'); + IPAddress ipaddr = IPAddress.None; + uint port = 0; + if (parts.Length <= 2) + ipaddr = Util.GetHostFromDNS(parts[0]); + if (parts.Length == 2) + UInt32.TryParse(parts[1], out port); + + // local authority (standalone), local call + if (m_thisIP.Equals(ipaddr) && (m_aScene.RegionInfo.HttpPort == port)) + return ((IAuthentication)m_aScene.CommsManager.UserAdminService).VerifyKey(userID, key); + // remote call + else + return AuthClient.VerifyKey("http://" + authority, userID, key); + } + + #endregion Misc protected class RegionToRegionClient : RegionClient diff --git a/OpenSim/Region/CoreModules/Hypergrid/HGStandaloneInventoryModule.cs b/OpenSim/Region/CoreModules/Hypergrid/HGStandaloneInventoryModule.cs index 3675583..f0d70a7 100644 --- a/OpenSim/Region/CoreModules/Hypergrid/HGStandaloneInventoryModule.cs +++ b/OpenSim/Region/CoreModules/Hypergrid/HGStandaloneInventoryModule.cs @@ -93,7 +93,7 @@ namespace OpenSim.Region.CoreModules.Hypergrid m_inventoryService = new HGInventoryService(m_inventoryBase, ((AssetServerBase)m_scene.CommsManager.AssetCache.AssetServer).AssetProviderPlugin, - (UserManagerBase)m_scene.CommsManager.UserService, m_scene.CommsManager.HttpServer, + (UserManagerBase)m_scene.CommsManager.UserAdminService, m_scene.CommsManager.HttpServer, m_scene.CommsManager.NetworkServersInfo.InventoryURL); AddHttpHandlers(m_scene.CommsManager.HttpServer); diff --git a/OpenSim/Region/CoreModules/Hypergrid/HGStandaloneLoginModule.cs b/OpenSim/Region/CoreModules/Hypergrid/HGStandaloneLoginModule.cs index f0e957b..c458b89 100644 --- a/OpenSim/Region/CoreModules/Hypergrid/HGStandaloneLoginModule.cs +++ b/OpenSim/Region/CoreModules/Hypergrid/HGStandaloneLoginModule.cs @@ -104,11 +104,12 @@ namespace OpenSim.Region.CoreModules.Hypergrid IHttpServer httpServer = m_firstScene.CommsManager.HttpServer; //TODO: fix the casting of the user service, maybe by registering the userManagerBase with scenes, or refactoring so we just need a IUserService reference - m_loginService = new HGLoginAuthService((UserManagerBase)m_firstScene.CommsManager.UserService, welcomeMessage, m_firstScene.CommsManager.InterServiceInventoryService, m_firstScene.CommsManager.NetworkServersInfo, authenticate, rootFolder, this); + m_loginService = new HGLoginAuthService((UserManagerBase)m_firstScene.CommsManager.UserAdminService, welcomeMessage, m_firstScene.CommsManager.InterServiceInventoryService, m_firstScene.CommsManager.NetworkServersInfo, authenticate, rootFolder, this); httpServer.AddXmlRPCHandler("hg_login", m_loginService.XmlRpcLoginMethod); httpServer.AddXmlRPCHandler("hg_new_auth_key", m_loginService.XmlRpcGenerateKeyMethod); httpServer.AddXmlRPCHandler("hg_verify_auth_key", m_loginService.XmlRpcVerifyKeyMethod); + httpServer.AddXmlRPCHandler("check_auth_session", m_loginService.XmlRPCCheckAuthSession); } } diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index c26adc0..5ffa64c 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -40,6 +40,7 @@ using OpenMetaverse.Imaging; using OpenSim.Framework; using OpenSim.Framework.Communications; using OpenSim.Framework.Communications.Cache; +using OpenSim.Framework.Communications.Clients; using OpenSim.Framework.Console; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes.Scripting; @@ -2372,64 +2373,80 @@ namespace OpenSim.Region.Framework.Scenes /// public bool NewUserConnection(AgentCircuitData agent) { - CapsModule.NewUserConnection(agent); + bool goodUserConnection = AuthenticateUser(agent); - ScenePresence sp = m_sceneGraph.GetScenePresence(agent.AgentID); - if (sp != null) + if (goodUserConnection) { - m_log.DebugFormat( - "[SCENE]: Adjusting known seeds for existing agent {0} in {1}", - agent.AgentID, RegionInfo.RegionName); + CapsModule.NewUserConnection(agent); - sp.AdjustKnownSeeds(); + ScenePresence sp = m_sceneGraph.GetScenePresence(agent.AgentID); + if (sp != null) + { + m_log.DebugFormat( + "[SCENE]: Adjusting known seeds for existing agent {0} in {1}", + agent.AgentID, RegionInfo.RegionName); - return true; - } + sp.AdjustKnownSeeds(); - // Don't disable this log message - it's too helpful - m_log.InfoFormat( - "[CONNECTION BEGIN]: Region {0} told of incoming client {1} {2} {3} (circuit code {4})", - RegionInfo.RegionName, agent.firstname, agent.lastname, agent.AgentID, agent.circuitcode); + return true; + } - if (m_regInfo.EstateSettings.IsBanned(agent.AgentID)) - { - m_log.WarnFormat( - "[CONNECTION BEGIN]: Incoming user {0} at {1} is on the region banlist", - agent.AgentID, RegionInfo.RegionName); - //return false; - } + // Don't disable this log message - it's too helpful + m_log.InfoFormat( + "[CONNECTION BEGIN]: Region {0} told of incoming client {1} {2} {3} (circuit code {4})", + RegionInfo.RegionName, agent.firstname, agent.lastname, agent.AgentID, agent.circuitcode); + + if (m_regInfo.EstateSettings.IsBanned(agent.AgentID)) + { + m_log.WarnFormat( + "[CONNECTION BEGIN]: Incoming user {0} at {1} is on the region banlist", + agent.AgentID, RegionInfo.RegionName); + //return false; + } - CapsModule.AddCapsHandler(agent.AgentID); + CapsModule.AddCapsHandler(agent.AgentID); - if (!agent.child) - { - // Honor parcel landing type and position. - ILandObject land = LandChannel.GetLandObject(agent.startpos.X, agent.startpos.Y); - if (land != null) + if (!agent.child) { - if (land.landData.LandingType == (byte)1 && land.landData.UserLocation != Vector3.Zero) + // Honor parcel landing type and position. + ILandObject land = LandChannel.GetLandObject(agent.startpos.X, agent.startpos.Y); + if (land != null) { - agent.startpos = land.landData.UserLocation; + if (land.landData.LandingType == (byte)1 && land.landData.UserLocation != Vector3.Zero) + { + agent.startpos = land.landData.UserLocation; + } } } - } - m_authenticateHandler.AddNewCircuit(agent.circuitcode, agent); + m_authenticateHandler.AddNewCircuit(agent.circuitcode, agent); - // rewrite session_id - CachedUserInfo userinfo = CommsManager.UserProfileCacheService.GetUserDetails(agent.AgentID); + // rewrite session_id + CachedUserInfo userinfo = CommsManager.UserProfileCacheService.GetUserDetails(agent.AgentID); + if (userinfo != null) + { + userinfo.SessionID = agent.SessionID; + } + else + { + m_log.WarnFormat( + "[CONNECTION BEGIN]: We couldn't find a User Info record for {0}. This is usually an indication that the UUID we're looking up is invalid", agent.AgentID); + } - if (userinfo != null) - { - userinfo.SessionID = agent.SessionID; + return true; } else { - m_log.WarnFormat( - "[CONNECTION BEGIN]: We couldn't find a User Info record for {0}. This is usually an indication that the UUID we're looking up is invalid", agent.AgentID); + m_log.WarnFormat("[CONNECTION BEGIN]: failed to authenticate user {0} {1}. Denying connection.", agent.firstname, agent.lastname); + return false; } + } - return true; + public virtual bool AuthenticateUser(AgentCircuitData agent) + { + bool result = CommsManager.UserService.VerifySession(agent.AgentID, agent.SessionID); + m_log.Debug("[CONNECTION BEGIN]: User authentication returned " + result); + return result; } public void UpdateCircuitData(AgentCircuitData data) -- cgit v1.1