/// <summary> /// Called when we receive the client's initial XMLRPC login_to_simulator request message /// </summary> /// <param name="request">The XMLRPC request</param> /// <returns>The response to send</returns> public virtual XmlRpcResponse XmlRpcLoginMethod(XmlRpcRequest request, IPEndPoint remoteClient) { // Temporary fix m_loginMutex.WaitOne(); try { //CFK: CustomizeResponse contains sufficient strings to alleviate the need for this. //CKF: m_log.Info("[LOGIN]: Attempting login now..."); XmlRpcResponse response = new XmlRpcResponse(); Hashtable requestData = (Hashtable)request.Params[0]; SniffLoginKey((Uri)request.Params[2], requestData); bool GoodXML = (requestData.Contains("first") && requestData.Contains("last") && (requestData.Contains("passwd") || requestData.Contains("web_login_key"))); string startLocationRequest = "last"; UserProfileData userProfile; LoginResponse logResponse = new LoginResponse(); string firstname; string lastname; if (GoodXML) { if (requestData.Contains("start")) { startLocationRequest = (string)requestData["start"]; } firstname = (string)requestData["first"]; lastname = (string)requestData["last"]; m_log.InfoFormat( "[LOGIN BEGIN]: XMLRPC Received login request message from user '{0}' '{1}'", firstname, lastname); string clientVersion = "Unknown"; if (requestData.Contains("version")) { clientVersion = (string)requestData["version"]; } m_log.DebugFormat( "[LOGIN]: XMLRPC Client is {0}, start location is {1}", clientVersion, startLocationRequest); if (!TryAuthenticateXmlRpcLogin(request, firstname, lastname, out userProfile)) { return logResponse.CreateLoginFailedResponse(); } } else { m_log.Info( "[LOGIN END]: XMLRPC login_to_simulator login message did not contain all the required data"); return logResponse.CreateGridErrorResponse(); } if (userProfile.GodLevel < m_minLoginLevel) { return logResponse.CreateLoginBlockedResponse(); } else { // If we already have a session... if (userProfile.CurrentAgent != null && userProfile.CurrentAgent.AgentOnline) { //TODO: The following statements can cause trouble: // If agentOnline could not turn from true back to false normally // because of some problem, for instance, the crashment of server or client, // the user cannot log in any longer. userProfile.CurrentAgent.AgentOnline = false; m_userManager.CommitAgent(ref userProfile); // try to tell the region that their user is dead. LogOffUser(userProfile, " XMLRPC You were logged off because you logged in from another location"); if (m_warn_already_logged) { // This is behavior for for grid, reject login m_log.InfoFormat( "[LOGIN END]: XMLRPC Notifying user {0} {1} that they are already logged in", firstname, lastname); return logResponse.CreateAlreadyLoggedInResponse(); } else { // This is behavior for standalone (silent logout of last hung session) m_log.InfoFormat( "[LOGIN]: XMLRPC User {0} {1} is already logged in, not notifying user, kicking old presence and starting new login.", firstname, lastname); } } // Otherwise... // Create a new agent session // XXYY we don't need this //m_userManager.ResetAttachments(userProfile.ID); 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; InventoryData inventData = null; try { inventData = GetInventorySkeleton(agentID); } catch (Exception e) { m_log.ErrorFormat( "[LOGIN END]: Error retrieving inventory skeleton of agent {0} - {1}", agentID, e); // Let's not panic if (!AllowLoginWithoutInventory()) return logResponse.CreateLoginInventoryFailedResponse(); } if (inventData != null) { ArrayList AgentInventoryArray = inventData.InventoryArray; Hashtable InventoryRootHash = new Hashtable(); InventoryRootHash["folder_id"] = inventData.RootFolderID.ToString(); ArrayList InventoryRoot = new ArrayList(); InventoryRoot.Add(InventoryRootHash); logResponse.InventoryRoot = InventoryRoot; logResponse.InventorySkeleton = AgentInventoryArray; } // Inventory Library Section Hashtable InventoryLibRootHash = new Hashtable(); InventoryLibRootHash["folder_id"] = "00000112-000f-0000-0000-000100bba000"; ArrayList InventoryLibRoot = new ArrayList(); InventoryLibRoot.Add(InventoryLibRootHash); logResponse.InventoryLibRoot = InventoryLibRoot; logResponse.InventoryLibraryOwner = GetLibraryOwner(); logResponse.InventoryLibrary = GetInventoryLibrary(); logResponse.CircuitCode = Util.RandomClass.Next(); logResponse.Lastname = userProfile.SurName; logResponse.Firstname = userProfile.FirstName; logResponse.AgentID = agentID; logResponse.SessionID = userProfile.CurrentAgent.SessionID; logResponse.SecureSessionID = userProfile.CurrentAgent.SecureSessionID; logResponse.Message = GetMessage(); logResponse.BuddList = ConvertFriendListItem(m_userManager.GetUserFriendList(agentID)); logResponse.StartLocation = startLocationRequest; if (CustomiseResponse(logResponse, userProfile, startLocationRequest, remoteClient)) { userProfile.LastLogin = userProfile.CurrentAgent.LoginTime; CommitAgent(ref userProfile); // If we reach this point, then the login has successfully logged onto the grid if (StatsManager.UserStats != null) StatsManager.UserStats.AddSuccessfulLogin(); m_log.DebugFormat( "[LOGIN END]: XMLRPC Authentication of user {0} {1} successful. Sending response to client.", firstname, lastname); return logResponse.ToXmlRpcResponse(); } else { m_log.ErrorFormat("[LOGIN END]: XMLRPC informing user {0} {1} that login failed due to an unavailable region", firstname, lastname); return logResponse.CreateDeadRegionResponse(); } } catch (Exception e) { m_log.Error("[LOGIN END]: XMLRPC Login failed, " + e); m_log.Error(e.StackTrace); } } m_log.Info("[LOGIN END]: XMLRPC Login failed. Sending back blank XMLRPC response"); return response; } finally { m_loginMutex.ReleaseMutex(); } }
/// <summary> /// Called when we receive the client's initial XMLRPC login_to_simulator request message /// </summary> /// <param name="request">The XMLRPC request</param> /// <returns>The response to send</returns> public virtual XmlRpcResponse XmlRpcLoginMethod(XmlRpcRequest request, IPEndPoint remoteClient) { string loginUsername = null; try { XmlRpcResponse response = new XmlRpcResponse(); Hashtable requestData = (Hashtable)request.Params[0]; SniffLoginKey((Uri)request.Params[2], requestData); bool GoodXML = (requestData.Contains("first") && requestData.Contains("last") && (requestData.Contains("passwd") || requestData.Contains("web_login_key"))); string firstname = null; string lastname = null; LoginResponse logResponse = new LoginResponse(); if (GoodXML) { //make sure the user isn't already trying to log in firstname = (string)requestData["first"]; lastname = (string)requestData["last"]; loginUsername = firstname + " " + lastname; lock (_loginsProcessing) { if (_loginsProcessing.Contains(loginUsername)) { return logResponse.CreateAlreadyLoggedInResponse(); } else { _loginsProcessing.Add(loginUsername); } } } string startLocationRequest = "last"; UserProfileData userProfile; string clientVersion = "Unknown"; if (GoodXML) { if (requestData.Contains("start")) { startLocationRequest = (string)requestData["start"]; } m_log.InfoFormat( "[LOGIN BEGIN]: XMLRPC Received login request message from user '{0}' '{1}'", firstname, lastname); if (requestData.Contains("version")) { clientVersion = (string)requestData["version"]; } if (this.IsViewerBlacklisted(clientVersion)) { m_log.DebugFormat("[LOGIN]: Denying login, Client {0} is blacklisted", clientVersion); return logResponse.CreateViewerNotAllowedResponse(); } m_log.DebugFormat( "[LOGIN]: XMLRPC Client is {0}, start location is {1}", clientVersion, startLocationRequest); if (!TryAuthenticateXmlRpcLogin(request, firstname, lastname, out userProfile)) { return logResponse.CreateLoginFailedResponse(); } } else { m_log.Info("[LOGIN END]: XMLRPC login_to_simulator login message did not contain all the required data"); return logResponse.CreateGridErrorResponse(); } if (userProfile.GodLevel < m_minLoginLevel) { return logResponse.CreateLoginBlockedResponse(); } else { // If we already have a session... if (userProfile.CurrentAgent != null && userProfile.CurrentAgent.AgentOnline) { // Force a refresh for this due to Commit below UUID userID = userProfile.ID; m_userManager.PurgeUserFromCaches(userID); userProfile = m_userManager.GetUserProfile(userID); // on an error, return the former error we returned before recovery was supported. if (userProfile == null) return logResponse.CreateAlreadyLoggedInResponse(); //TODO: The following statements can cause trouble: // If agentOnline could not turn from true back to false normally // because of some problem, for instance, the crashment of server or client, // the user cannot log in any longer. userProfile.CurrentAgent.AgentOnline = false; userProfile.CurrentAgent.LogoutTime = Util.UnixTimeSinceEpoch(); m_userManager.CommitAgent(ref userProfile); // try to tell the region that their user is dead. LogOffUser(userProfile, " XMLRPC You were logged off because you logged in from another location"); // Don't reject the login. We've already cleaned it up, above. m_log.InfoFormat( "[LOGIN END]: XMLRPC Reset user {0} {1} that we believe is already logged in", firstname, lastname); // return logResponse.CreateAlreadyLoggedInResponse(); } // Otherwise... // Create a new agent session m_userManager.ResetAttachments(userProfile.ID); 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; InventoryData inventData = null; try { inventData = GetInventorySkeleton(agentID); } catch (Exception e) { m_log.ErrorFormat( "[LOGIN END]: Error retrieving inventory skeleton of agent {0} - {1}", agentID, e); return logResponse.CreateLoginInventoryFailedResponse(); } if (inventData != null) { ArrayList AgentInventoryArray = inventData.InventoryArray; Hashtable InventoryRootHash = new Hashtable(); InventoryRootHash["folder_id"] = inventData.RootFolderID.ToString(); ArrayList InventoryRoot = new ArrayList(); InventoryRoot.Add(InventoryRootHash); userProfile.RootInventoryFolderID = inventData.RootFolderID; logResponse.InventoryRoot = InventoryRoot; logResponse.InventorySkeleton = AgentInventoryArray; } // Inventory Library Section Hashtable InventoryLibRootHash = new Hashtable(); InventoryLibRootHash["folder_id"] = "00000112-000f-0000-0000-000100bba000"; ArrayList InventoryLibRoot = new ArrayList(); InventoryLibRoot.Add(InventoryLibRootHash); logResponse.InventoryLibRoot = InventoryLibRoot; logResponse.InventoryLibraryOwner = GetLibraryOwner(); logResponse.InventoryLibrary = GetInventoryLibrary(); logResponse.CircuitCode = Util.RandomClass.Next(); logResponse.Lastname = userProfile.SurName; logResponse.Firstname = userProfile.FirstName; logResponse.AgentID = agentID; logResponse.SessionID = userProfile.CurrentAgent.SessionID; logResponse.SecureSessionID = userProfile.CurrentAgent.SecureSessionID; logResponse.Message = GetMessage(); logResponse.MapServerURI = m_MapServerURI; logResponse.BuddList = ConvertFriendListItem(m_userManager.GetUserFriendList(agentID)); logResponse.StartLocation = startLocationRequest; // m_log.WarnFormat("[LOGIN END]: >>> Login response for {0} SSID={1}", logResponse.AgentID, logResponse.SecureSessionID); if (CustomiseResponse(logResponse, userProfile, startLocationRequest, clientVersion)) { userProfile.LastLogin = userProfile.CurrentAgent.LoginTime; CommitAgent(ref userProfile); // If we reach this point, then the login has successfully logged onto the grid if (StatsManager.UserStats != null) StatsManager.UserStats.AddSuccessfulLogin(); m_log.DebugFormat( "[LOGIN END]: XMLRPC Authentication of user {0} {1} successful. Sending response to client.", firstname, lastname); return logResponse.ToXmlRpcResponse(); } else { m_log.ErrorFormat("[LOGIN END]: XMLRPC informing user {0} {1} that login failed due to an unavailable region", firstname, lastname); return logResponse.CreateDeadRegionResponse(); } } catch (Exception e) { m_log.Error("[LOGIN END]: XMLRPC Login failed, " + e); m_log.Error(e.StackTrace); } } m_log.Info("[LOGIN END]: XMLRPC Login failed. Sending back blank XMLRPC response"); return response; } finally { if (loginUsername != null) { lock (_loginsProcessing) { _loginsProcessing.Remove(loginUsername); } } } }
public override XmlRpcResponse XmlRpcLoginMethod(XmlRpcRequest request, IPEndPoint client) { m_loginMutex.WaitOne(); try { #region Authenticate & check if login is wellformed m_log.Info("[LOGIN]: Attempting login in realXtend mode..."); XmlRpcResponse response = new XmlRpcResponse(); Hashtable requestData = (Hashtable)request.Params[0]; bool GoodLogin; string startLocationRequest = "last"; LoginResponse logResponse = new LoginResponse(); string account; string sessionHash; string clientVersion = "Unknown"; if (requestData.Contains("version")) { clientVersion = (string)requestData["version"]; } account = (string)requestData["account"]; sessionHash = (string)requestData["sessionhash"]; m_log.InfoFormat( "[REX LOGIN BEGIN]: XMLRPC Received login request message from user '{0}' '{1}'", account, sessionHash); if (requestData.Contains("start")) { startLocationRequest = (string)requestData["start"]; } m_log.DebugFormat( "[REXLOGIN]: XMLRPC Client is {0}, start location is {1}", clientVersion, startLocationRequest); GoodLogin = AuthenticateUser(account, sessionHash); if (!GoodLogin) { m_log.InfoFormat("[LOGIN END]: XMLRPC User {0} ({1}) failed authentication", account, sessionHash); return logResponse.CreateLoginFailedResponse(); } try { string actName = account.Split('@')[0]; string actSrv = account.Split('@')[1]; RexUserProfileData userProfile = AuthenticationService.GetUserByAccount(actName, actSrv); userProfile.PasswordHash = "$1$"; userProfile.PasswordSalt = ""; UUID agentID = userProfile.ID; // Used to transmit the login URL to the // RexAvatar class when it connects. m_userData[agentID] = userProfile; logResponse.CircuitCode = Util.RandomClass.Next(); logResponse.Lastname = "<" + account + ">"; logResponse.Firstname = userProfile.FirstName + " " + userProfile.SurName; logResponse.AgentID = agentID; logResponse.Message = m_UserConfig.DefaultStartupMsg; #endregion Authenticate & check if login is wellformed if (userProfile.GodLevel < m_minLoginLevel) { return logResponse.CreateLoginBlockedResponse(); } else { #region If we already have a session... // agent is probably newer null because it's realXtend login, so there's probably no need for checking this, // but online check is still valid if (userProfile.CurrentAgent != null && userProfile.CurrentAgent.AgentOnline) { userProfile.CurrentAgent.AgentOnline = false; // Commiting online status to userserver: AuthenticationService.UpdateUserAgent(agentID.ToString(), userProfile.CurrentAgent.Handle.ToString(), userProfile.CurrentAgent.Position.ToString(), userProfile.GridUrl.ToString(), userProfile.AuthUrl); //try to tell the region that their user is dead. m_UserLoginService.LogOffUser(userProfile, " XMLRPC You were logged off because you logged in from another location"); if (m_warn_already_logged) { m_log.InfoFormat( "[LOGIN END]: XMLRPC Notifying user {0} that they are already logged in", userProfile.Name); return logResponse.CreateAlreadyLoggedInResponse(); } // This is behavior for standalone (silent logout of last hung session) m_log.InfoFormat( "[LOGIN]: XMLRPC User {0} is already logged in, not notifying user, kicking old presence and starting new login.", userProfile.Name); } #endregion //If we already have a session... } try { LoginService.InventoryData inventData = null; try { inventData = CableBeachState.LoginService.GetInventorySkeleton(agentID); //inventData = GetInventorySkeleton(agentID); } catch (Exception e) { m_log.ErrorFormat( "[LOGIN END]: Error retrieving inventory skeleton of agent {0} - {1}", agentID, e); // Let's not panic if (!AllowLoginWithoutInventory()) return logResponse.CreateLoginInventoryFailedResponse(); } if (inventData != null) { ArrayList AgentInventoryArray = inventData.InventoryArray; Hashtable InventoryRootHash = new Hashtable(); InventoryRootHash["folder_id"] = inventData.RootFolderID.ToString(); ArrayList InventoryRoot = new ArrayList(); InventoryRoot.Add(InventoryRootHash); logResponse.InventoryRoot = InventoryRoot; logResponse.InventorySkeleton = AgentInventoryArray; } // Inventory Library Section Hashtable InventoryLibRootHash = new Hashtable(); InventoryLibRootHash["folder_id"] = "00000112-000f-0000-0000-000100bba000"; //UUID.Zero.ToString(); ArrayList InventoryLibRoot = new ArrayList(); InventoryLibRoot.Add(InventoryLibRootHash); logResponse.InventoryLibRoot = InventoryLibRoot; //logResponse.InventoryLibraryOwner = GetLibraryOwner(); logResponse.InventoryLibraryOwner = CableBeachState.LoginService.GetLibraryOwner(); //logResponse.InventoryLibrary = GetInventoryLibrary(); logResponse.InventoryLibrary = CableBeachState.LoginService.GetInventoryLibrary(); logResponse.CircuitCode = Util.RandomClass.Next(); logResponse.Lastname = userProfile.SurName; logResponse.Firstname = userProfile.FirstName; logResponse.AgentID = agentID; logResponse.SessionID = userProfile.CurrentAgent.SessionID = UUID.Random(); logResponse.SecureSessionID = userProfile.CurrentAgent.SecureSessionID = UUID.Random(); // get inventory // TODO: Fetch avatar storage global inventory // possibly debricated: //logResponse.BuddList = ConvertFriendListItem(m_userManager.GetUserFriendList(agentID)); //List<RexFriendListItem> friendList = AuthenticationService.GetUserFriendList(agentID.ToString(), userProfile.AuthUrl); //TODO: convert List<RexFriendListItem> to Buddlist logResponse.StartLocation = startLocationRequest; //TODO: if already trying to log in.. bool added = m_LoginSwitch.AddLoggingInClient(userProfile.ID, userProfile.CurrentAgent.SessionID); // setup avatar // then get region OpenSim.Grid.UserServer.Modules.RexLogin.Avatar avatar = SetUpAvatar(account, userProfile.AuthUrl, userProfile.CurrentAgent.SessionID, userProfile); userProfile.Account = account; // Identity: <authentication server uri>/users/<account> if (!Uri.TryCreate("http://" + userProfile.AuthUrl + "/users/" + account.Split('@')[0] //+ "." + userProfile.AuthUrl , UriKind.Absolute, out avatar.Identity)) { m_log.Error("[RealXtendLogin]: Failed to parse avatar identity "); OpenSim.Grid.UserServer.Modules.RexLogin.LindenLoginHelper.CreateFailureResponse( "Failed to parse avatar identity", "Failed to parse avatar identity for " + account, false); } OpenSim.Grid.UserServer.Modules.RexLogin.LindenLoginData loginData = SetUpLindenLoginData(avatar, account, logResponse.Message, userProfile.CurrentAgent.SessionID); CableBeachMessages.RegionInfo startReg; Vector3 startPosition; if (TryGetStartingRegion(avatar, startLocationRequest, ref loginData, out startReg, out startPosition)) { string simIp = startReg.IP.ToString(); logResponse.SimPort = (uint)startReg.Port; logResponse.SimAddress = simIp; if (TryPrepareLogin(avatar, startReg, startPosition, clientVersion, client.Address, ref loginData, HttpCertificate, logResponse.CircuitCode)) { m_log.Info("[RealXtendLogin] Login to " + startReg.Name + " prepared for " + avatar.Identity + ", returning response"); userProfile.CurrentAgent.AgentOnline = true; AuthenticationService.UpdateUserAgent(agentID.ToString(), startReg.Handle.ToString(), userProfile.CurrentAgent.Position.ToString(), startReg.ToString(), userProfile.AuthUrl); return logResponse.ToXmlRpcResponse(); } else { m_log.Info("[RealXtendLogin] Preparing Login to " + startReg.Name + " failed " + avatar.Identity + ", returning failure response"); OpenSim.Grid.UserServer.Modules.RexLogin.LindenLoginHelper.CreateFailureResponse( "Preparing login fail", "Preparing Login to " + startReg.Name + " failed", false); } } else { m_log.ErrorFormat("[LOGIN END]: XMLRPC informing user {0} that login failed due to an unavailable region", userProfile.Name); return OpenSim.Grid.UserServer.Modules.RexLogin.LindenLoginHelper.CreateLoginNoRegionResponse(); } return OpenSim.Grid.UserServer.Modules.RexLogin.LindenLoginHelper.CreateLoginInternalErrorResponse(); } catch (Exception e) { m_log.Error("[LOGIN END]: XMLRPC Login failed: " + e.StackTrace + "\nSending back blank XMLRPC response."); m_log.Error(e.StackTrace); return response; } } catch (Exception e) { m_log.Error("[LOGIN END]: XMLRPC Login failed: " + e.StackTrace + "\nSending back blank XMLRPC response."); return response; } } finally { m_loginMutex.ReleaseMutex(); } }