OpenSimMirror/OpenSim/Region/Communications/Local/LocalLoginService.cs

249 lines
11 KiB
C#

/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSim Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using System;
using System.Collections;
using System.Collections.Generic;
using libsecondlife;
using OpenSim.Framework;
using OpenSim.Framework.Communications.Cache;
using OpenSim.Framework.Console;
using OpenSim.Framework.Statistics;
using OpenSim.Framework.UserManagement;
using InventoryFolder=OpenSim.Framework.InventoryFolder;
namespace OpenSim.Region.Communications.Local
{
public delegate void LoginToRegionEvent(ulong regionHandle, Login login);
public class LocalLoginService : LoginService
{
private static readonly log4net.ILog m_log
= log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
private CommunicationsLocal m_Parent;
private NetworkServersInfo serversInfo;
private uint defaultHomeX;
private uint defaultHomeY;
private bool authUsers = false;
public event LoginToRegionEvent OnLoginToRegion;
private LoginToRegionEvent handlerLoginToRegion = null; // OnLoginToRegion;
public LocalLoginService(UserManagerBase userManager, string welcomeMess,
CommunicationsLocal parent, NetworkServersInfo serversInfo,
bool authenticate)
: base(userManager, parent.UserProfileCacheService.libraryRoot, welcomeMess)
{
m_Parent = parent;
this.serversInfo = serversInfo;
defaultHomeX = this.serversInfo.DefaultHomeLocX;
defaultHomeY = this.serversInfo.DefaultHomeLocY;
authUsers = authenticate;
}
public override UserProfileData GetTheUser(string firstname, string lastname)
{
UserProfileData profile = m_userManager.GetUserProfile(firstname, lastname);
if (profile != null)
{
return profile;
}
if (!authUsers)
{
//no current user account so make one
m_log.Info("[LOGIN]: No user account found so creating a new one.");
m_userManager.AddUserProfile(firstname, lastname, "test", defaultHomeX, defaultHomeY);
profile = m_userManager.GetUserProfile(firstname, lastname);
if (profile != null)
{
m_Parent.InventoryService.CreateNewUserInventory(profile.ID);
}
return profile;
}
return null;
}
public override bool AuthenticateUser(UserProfileData profile, string password)
{
if (!authUsers)
{
//for now we will accept any password in sandbox mode
m_log.Info("[LOGIN]: Authorising user (no actual password check)");
return true;
}
else
{
m_log.Info(
"[LOGIN]: Authenticating " + profile.FirstName + " " + profile.SurName);
if (!password.StartsWith("$1$"))
password = "$1$" + Util.Md5Hash(password);
password = password.Remove(0, 3); //remove $1$
string s = Util.Md5Hash(password + ":" + profile.PasswordSalt);
bool loginresult = (profile.PasswordHash.Equals(s.ToString(), StringComparison.InvariantCultureIgnoreCase)
|| profile.PasswordHash.Equals(password, StringComparison.InvariantCultureIgnoreCase));
return loginresult;
}
}
public override void CustomiseResponse(LoginResponse response, UserProfileData theUser, string startLocationRequest)
{
ulong currentRegion = 0;
if (startLocationRequest == "last")
{
currentRegion = theUser.CurrentAgent.Handle;
}
else if (startLocationRequest == "home")
{
currentRegion = theUser.HomeRegion;
}
else
{
m_log.Info("[LOGIN]: Got Custom Login URL, but can't process it");
// LocalBackEndServices can't possibly look up a region by name :(
// TODO: Parse string in the following format: 'uri:RegionName&X&Y&Z'
currentRegion = theUser.CurrentAgent.Handle;
}
RegionInfo reg = m_Parent.GridService.RequestNeighbourInfo(currentRegion);
if (reg != null)
{
response.Home = "{'region_handle':[r" + (reg.RegionLocX * Constants.RegionSize).ToString() + ",r" +
(reg.RegionLocY * Constants.RegionSize).ToString() + "], " +
"'position':[r" + theUser.HomeLocation.X.ToString() + ",r" +
theUser.HomeLocation.Y.ToString() + ",r" + theUser.HomeLocation.Z.ToString() + "], " +
"'look_at':[r" + theUser.HomeLocation.X.ToString() + ",r" +
theUser.HomeLocation.Y.ToString() + ",r" + theUser.HomeLocation.Z.ToString() + "]}";
string capsPath = Util.GetRandomCapsPath();
response.SimAddress = reg.ExternalEndPoint.Address.ToString();
response.SimPort = (uint) reg.ExternalEndPoint.Port;
response.RegionX = reg.RegionLocX;
response.RegionY = reg.RegionLocY ;
response.SeedCapability = "http://" + reg.ExternalHostName + ":" +
serversInfo.HttpListenerPort.ToString() + "/CAPS/" + capsPath + "0000/";
m_log.DebugFormat(
"[CAPS]: Sending new CAPS seed url {0} to client {1}",
response.SeedCapability, response.AgentID);
theUser.CurrentAgent.Region = reg.RegionID;
theUser.CurrentAgent.Handle = reg.RegionHandle;
LoginResponse.BuddyList buddyList = new LoginResponse.BuddyList();
response.BuddList = ConvertFriendListItem(m_userManager.GetUserFriendList(theUser.ID));
Login _login = new Login();
//copy data to login object
_login.First = response.Firstname;
_login.Last = response.Lastname;
_login.Agent = response.AgentID;
_login.Session = response.SessionID;
_login.SecureSession = response.SecureSessionID;
_login.CircuitCode = (uint) response.CircuitCode;
_login.StartPos = new LLVector3(128, 128, 70);
_login.CapsPath = capsPath;
m_log.InfoFormat(
"[LOGIN]: Telling region {0} @ {1},{2} ({3}:{4}) to expect user connection",
reg.RegionName, response.RegionX, response.RegionY, response.SimAddress, response.SimPort);
handlerLoginToRegion = OnLoginToRegion;
if (handlerLoginToRegion != null)
{
handlerLoginToRegion(currentRegion, _login);
}
}
else
{
m_log.Warn("[LOGIN]: Not found region " + currentRegion);
}
}
private LoginResponse.BuddyList ConvertFriendListItem(List<FriendListItem> LFL)
{
LoginResponse.BuddyList buddylistreturn = new LoginResponse.BuddyList();
foreach (FriendListItem fl in LFL)
{
LoginResponse.BuddyList.BuddyInfo buddyitem = new LoginResponse.BuddyList.BuddyInfo(fl.Friend);
buddyitem.BuddyID = fl.Friend;
buddyitem.BuddyRightsHave = (int)fl.FriendListOwnerPerms;
buddyitem.BuddyRightsGiven = (int)fl.FriendPerms;
buddylistreturn.AddNewBuddy(buddyitem);
}
return buddylistreturn;
}
// See LoginService
protected override InventoryData GetInventorySkeleton(LLUUID userID)
{
List<InventoryFolderBase> folders = m_Parent.InventoryService.GetInventorySkeleton(userID);
// If we have user auth but no inventory folders for some reason, create a new set of folders.
if (null == folders || 0 == folders.Count)
{
m_Parent.InventoryService.CreateNewUserInventory(userID);
folders = m_Parent.InventoryService.GetInventorySkeleton(userID);
}
LLUUID rootID = LLUUID.Zero;
ArrayList AgentInventoryArray = new ArrayList();
Hashtable TempHash;
foreach (InventoryFolderBase InvFolder in folders)
{
if (InvFolder.ParentID == LLUUID.Zero)
{
rootID = InvFolder.ID;
}
TempHash = new Hashtable();
TempHash["name"] = InvFolder.Name;
TempHash["parent_id"] = InvFolder.ParentID.ToString();
TempHash["version"] = (Int32) InvFolder.Version;
TempHash["type_default"] = (Int32) InvFolder.Type;
TempHash["folder_id"] = InvFolder.ID.ToString();
AgentInventoryArray.Add(TempHash);
}
return new InventoryData(AgentInventoryArray, rootID);
}
}
}