LocalLoginService.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  1. /*
  2. * Copyright (c) Contributors, http://opensimulator.org/
  3. * See CONTRIBUTORS.TXT for a full list of copyright holders.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions are met:
  7. * * Redistributions of source code must retain the above copyright
  8. * notice, this list of conditions and the following disclaimer.
  9. * * Redistributions in binary form must reproduce the above copyright
  10. * notice, this list of conditions and the following disclaimer in the
  11. * documentation and/or other materials provided with the distribution.
  12. * * Neither the name of the OpenSim Project nor the
  13. * names of its contributors may be used to endorse or promote products
  14. * derived from this software without specific prior written permission.
  15. *
  16. * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
  17. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  18. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  19. * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
  20. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  21. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  22. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  23. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  24. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  25. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  26. */
  27. using System;
  28. using System.Collections;
  29. using System.Collections.Generic;
  30. using System.Reflection;
  31. using System.Text.RegularExpressions;
  32. using libsecondlife;
  33. using log4net;
  34. using OpenSim.Framework;
  35. using OpenSim.Framework.Communications;
  36. namespace OpenSim.Region.Communications.Local
  37. {
  38. public delegate void LoginToRegionEvent(ulong regionHandle, Login login);
  39. public class LocalLoginService : LoginService
  40. {
  41. private static readonly ILog m_log
  42. = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
  43. private CommunicationsLocal m_Parent;
  44. private NetworkServersInfo serversInfo;
  45. private uint defaultHomeX;
  46. private uint defaultHomeY;
  47. private bool authUsers = false;
  48. public event LoginToRegionEvent OnLoginToRegion;
  49. private LoginToRegionEvent handlerLoginToRegion = null; // OnLoginToRegion;
  50. public LocalLoginService(UserManagerBase userManager, string welcomeMess,
  51. CommunicationsLocal parent, NetworkServersInfo serversInfo,
  52. bool authenticate)
  53. : base(userManager, parent.UserProfileCacheService.libraryRoot, welcomeMess)
  54. {
  55. m_Parent = parent;
  56. this.serversInfo = serversInfo;
  57. defaultHomeX = this.serversInfo.DefaultHomeLocX;
  58. defaultHomeY = this.serversInfo.DefaultHomeLocY;
  59. authUsers = authenticate;
  60. }
  61. public override UserProfileData GetTheUser(string firstname, string lastname)
  62. {
  63. UserProfileData profile = m_userManager.GetUserProfile(firstname, lastname);
  64. if (profile != null)
  65. {
  66. return profile;
  67. }
  68. if (!authUsers)
  69. {
  70. //no current user account so make one
  71. m_log.Info("[LOGIN]: No user account found so creating a new one.");
  72. m_userManager.AddUserProfile(firstname, lastname, "test", defaultHomeX, defaultHomeY);
  73. profile = m_userManager.GetUserProfile(firstname, lastname);
  74. if (profile != null)
  75. {
  76. m_Parent.InventoryService.CreateNewUserInventory(profile.ID);
  77. }
  78. return profile;
  79. }
  80. return null;
  81. }
  82. public override bool AuthenticateUser(UserProfileData profile, string password)
  83. {
  84. if (!authUsers)
  85. {
  86. //for now we will accept any password in sandbox mode
  87. m_log.Info("[LOGIN]: Authorising user (no actual password check)");
  88. return true;
  89. }
  90. else
  91. {
  92. m_log.Info(
  93. "[LOGIN]: Authenticating " + profile.FirstName + " " + profile.SurName);
  94. if (!password.StartsWith("$1$"))
  95. password = "$1$" + Util.Md5Hash(password);
  96. password = password.Remove(0, 3); //remove $1$
  97. string s = Util.Md5Hash(password + ":" + profile.PasswordSalt);
  98. bool loginresult = (profile.PasswordHash.Equals(s.ToString(), StringComparison.InvariantCultureIgnoreCase)
  99. || profile.PasswordHash.Equals(password, StringComparison.InvariantCultureIgnoreCase));
  100. return loginresult;
  101. }
  102. }
  103. private Regex reURI = new Regex(@"^uri:(?<region>[^&]+)&(?<x>\d+)&(?<y>\d+)&(?<z>\d+)$");
  104. public override void CustomiseResponse(LoginResponse response, UserProfileData theUser, string startLocationRequest)
  105. {
  106. ulong currentRegion = 0;
  107. uint locX = 0;
  108. uint locY = 0;
  109. uint locZ = 0;
  110. bool specificStartLocation = false;
  111. // get start location
  112. if (startLocationRequest == "last")
  113. {
  114. currentRegion = theUser.CurrentAgent.Handle;
  115. }
  116. else if (startLocationRequest == "home")
  117. {
  118. currentRegion = theUser.HomeRegion;
  119. }
  120. else
  121. {
  122. // use last location as default
  123. currentRegion = theUser.CurrentAgent.Handle;
  124. Match uriMatch = reURI.Match(startLocationRequest);
  125. if (null == uriMatch)
  126. {
  127. m_log.InfoFormat("[LOGIN]: Got Custom Login URL {0}, but can't process it", startLocationRequest);
  128. }
  129. else
  130. {
  131. string region = uriMatch.Groups["region"].ToString();
  132. RegionInfo r = m_Parent.GridService.RequestClosestRegion(region);
  133. if (null == r)
  134. {
  135. m_log.InfoFormat("[LOGIN]: Got Custom Login URL {0}, can't locate region {1}",
  136. startLocationRequest, region);
  137. }
  138. else
  139. {
  140. currentRegion = r.RegionHandle;
  141. locX = UInt32.Parse(uriMatch.Groups["x"].ToString());
  142. locY = UInt32.Parse(uriMatch.Groups["y"].ToString());
  143. locZ = UInt32.Parse(uriMatch.Groups["z"].ToString());
  144. specificStartLocation = true;
  145. }
  146. }
  147. }
  148. RegionInfo homeReg = m_Parent.GridService.RequestNeighbourInfo(theUser.HomeRegion);
  149. RegionInfo reg = m_Parent.GridService.RequestNeighbourInfo(currentRegion);
  150. if ((homeReg != null) && (reg != null))
  151. {
  152. response.Home = "{'region_handle':[r" +
  153. (homeReg.RegionLocX * Constants.RegionSize).ToString() + ",r" +
  154. (homeReg.RegionLocY * Constants.RegionSize).ToString() + "], " +
  155. "'position':[r" +
  156. theUser.HomeLocation.X.ToString() + ",r" +
  157. theUser.HomeLocation.Y.ToString() + ",r" +
  158. theUser.HomeLocation.Z.ToString() + "], " +
  159. "'look_at':[r" +
  160. theUser.HomeLocation.X.ToString() + ",r" +
  161. theUser.HomeLocation.Y.ToString() + ",r" +
  162. theUser.HomeLocation.Z.ToString() + "]}";
  163. string capsPath = Util.GetRandomCapsPath();
  164. response.SimAddress = reg.ExternalEndPoint.Address.ToString();
  165. response.SimPort = (uint) reg.ExternalEndPoint.Port;
  166. response.RegionX = reg.RegionLocX;
  167. response.RegionY = reg.RegionLocY;
  168. m_log.DebugFormat(
  169. "[CAPS][LOGIN]: RegionX {0} RegionY {0}", response.RegionX, response.RegionY);
  170. // can be: last, home, safe, url
  171. if (specificStartLocation) response.StartLocation = "url";
  172. response.SeedCapability = "http://" + reg.ExternalHostName + ":" +
  173. serversInfo.HttpListenerPort.ToString() + "/CAPS/" + capsPath + "0000/";
  174. m_log.DebugFormat(
  175. "[CAPS]: Sending new CAPS seed url {0} to client {1}",
  176. response.SeedCapability, response.AgentID);
  177. theUser.CurrentAgent.Region = reg.RegionID;
  178. theUser.CurrentAgent.Handle = reg.RegionHandle;
  179. LoginResponse.BuddyList buddyList = new LoginResponse.BuddyList();
  180. response.BuddList = ConvertFriendListItem(m_userManager.GetUserFriendList(theUser.ID));
  181. Login _login = new Login();
  182. //copy data to login object
  183. _login.First = response.Firstname;
  184. _login.Last = response.Lastname;
  185. _login.Agent = response.AgentID;
  186. _login.Session = response.SessionID;
  187. _login.SecureSession = response.SecureSessionID;
  188. _login.CircuitCode = (uint) response.CircuitCode;
  189. if (specificStartLocation)
  190. _login.StartPos = new LLVector3(locX, locY, locZ);
  191. else
  192. _login.StartPos = new LLVector3(128, 128, 128);
  193. _login.CapsPath = capsPath;
  194. m_log.InfoFormat(
  195. "[LOGIN]: Telling region {0} @ {1},{2} ({3}:{4}) to expect user connection",
  196. reg.RegionName, response.RegionX, response.RegionY, response.SimAddress, response.SimPort);
  197. handlerLoginToRegion = OnLoginToRegion;
  198. if (handlerLoginToRegion != null)
  199. {
  200. handlerLoginToRegion(currentRegion, _login);
  201. }
  202. }
  203. else
  204. {
  205. m_log.Warn("[LOGIN]: Not found region " + currentRegion);
  206. }
  207. }
  208. private LoginResponse.BuddyList ConvertFriendListItem(List<FriendListItem> LFL)
  209. {
  210. LoginResponse.BuddyList buddylistreturn = new LoginResponse.BuddyList();
  211. foreach (FriendListItem fl in LFL)
  212. {
  213. LoginResponse.BuddyList.BuddyInfo buddyitem = new LoginResponse.BuddyList.BuddyInfo(fl.Friend);
  214. buddyitem.BuddyID = fl.Friend;
  215. buddyitem.BuddyRightsHave = (int)fl.FriendListOwnerPerms;
  216. buddyitem.BuddyRightsGiven = (int)fl.FriendPerms;
  217. buddylistreturn.AddNewBuddy(buddyitem);
  218. }
  219. return buddylistreturn;
  220. }
  221. // See LoginService
  222. protected override InventoryData GetInventorySkeleton(LLUUID userID)
  223. {
  224. List<InventoryFolderBase> folders = m_Parent.InventoryService.GetInventorySkeleton(userID);
  225. // If we have user auth but no inventory folders for some reason, create a new set of folders.
  226. if (null == folders || 0 == folders.Count)
  227. {
  228. m_Parent.InventoryService.CreateNewUserInventory(userID);
  229. folders = m_Parent.InventoryService.GetInventorySkeleton(userID);
  230. }
  231. LLUUID rootID = LLUUID.Zero;
  232. ArrayList AgentInventoryArray = new ArrayList();
  233. Hashtable TempHash;
  234. foreach (InventoryFolderBase InvFolder in folders)
  235. {
  236. if (InvFolder.ParentID == LLUUID.Zero)
  237. {
  238. rootID = InvFolder.ID;
  239. }
  240. TempHash = new Hashtable();
  241. TempHash["name"] = InvFolder.Name;
  242. TempHash["parent_id"] = InvFolder.ParentID.ToString();
  243. TempHash["version"] = (Int32) InvFolder.Version;
  244. TempHash["type_default"] = (Int32) InvFolder.Type;
  245. TempHash["folder_id"] = InvFolder.ID.ToString();
  246. AgentInventoryArray.Add(TempHash);
  247. }
  248. return new InventoryData(AgentInventoryArray, rootID);
  249. }
  250. }
  251. }