UserManagerBase.cs 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906
  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 OpenSimulator 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.Generic;
  29. using System.Net;
  30. using System.Reflection;
  31. using System.Security.Cryptography;
  32. using log4net;
  33. using Nwc.XmlRpc;
  34. using OpenMetaverse;
  35. using OpenMetaverse.StructuredData;
  36. using OpenSim.Data;
  37. using OpenSim.Framework.Communications;
  38. using OpenSim.Framework.Statistics;
  39. using OpenSim.Services.Interfaces;
  40. namespace OpenSim.Framework.Communications
  41. {
  42. /// <summary>
  43. /// Base class for user management (create, read, etc)
  44. /// </summary>
  45. public abstract class UserManagerBase : IUserService, IUserAdminService, IAvatarService, IMessagingService, IAuthentication
  46. {
  47. private static readonly ILog m_log
  48. = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
  49. /// <value>
  50. /// List of plugins to search for user data
  51. /// </value>
  52. private List<IUserDataPlugin> m_plugins = new List<IUserDataPlugin>();
  53. protected CommunicationsManager m_commsManager;
  54. protected IInventoryService m_InventoryService;
  55. /// <summary>
  56. /// Constructor
  57. /// </summary>
  58. /// <param name="commsManager"></param>
  59. public UserManagerBase(CommunicationsManager commsManager)
  60. {
  61. m_commsManager = commsManager;
  62. }
  63. public virtual void SetInventoryService(IInventoryService invService)
  64. {
  65. m_InventoryService = invService;
  66. }
  67. /// <summary>
  68. /// Add a new user data plugin - plugins will be requested in the order they were added.
  69. /// </summary>
  70. /// <param name="plugin">The plugin that will provide user data</param>
  71. public void AddPlugin(IUserDataPlugin plugin)
  72. {
  73. m_plugins.Add(plugin);
  74. }
  75. /// <summary>
  76. /// Adds a list of user data plugins, as described by `provider' and
  77. /// `connect', to `_plugins'.
  78. /// </summary>
  79. /// <param name="provider">
  80. /// The filename of the inventory server plugin DLL.
  81. /// </param>
  82. /// <param name="connect">
  83. /// The connection string for the storage backend.
  84. /// </param>
  85. public void AddPlugin(string provider, string connect)
  86. {
  87. m_plugins.AddRange(DataPluginFactory.LoadDataPlugins<IUserDataPlugin>(provider, connect));
  88. }
  89. #region UserProfile
  90. public virtual void AddTemporaryUserProfile(UserProfileData userProfile)
  91. {
  92. foreach (IUserDataPlugin plugin in m_plugins)
  93. {
  94. plugin.AddTemporaryUserProfile(userProfile);
  95. }
  96. }
  97. public virtual UserProfileData GetUserProfile(string fname, string lname)
  98. {
  99. foreach (IUserDataPlugin plugin in m_plugins)
  100. {
  101. UserProfileData profile = plugin.GetUserByName(fname, lname);
  102. if (profile != null)
  103. {
  104. profile.CurrentAgent = GetUserAgent(profile.ID);
  105. return profile;
  106. }
  107. }
  108. return null;
  109. }
  110. public void LogoutUsers(UUID regionID)
  111. {
  112. foreach (IUserDataPlugin plugin in m_plugins)
  113. {
  114. plugin.LogoutUsers(regionID);
  115. }
  116. }
  117. public void ResetAttachments(UUID userID)
  118. {
  119. foreach (IUserDataPlugin plugin in m_plugins)
  120. {
  121. plugin.ResetAttachments(userID);
  122. }
  123. }
  124. public UserProfileData GetUserProfile(Uri uri)
  125. {
  126. foreach (IUserDataPlugin plugin in m_plugins)
  127. {
  128. UserProfileData profile = plugin.GetUserByUri(uri);
  129. if (null != profile)
  130. return profile;
  131. }
  132. return null;
  133. }
  134. public virtual UserAgentData GetAgentByUUID(UUID userId)
  135. {
  136. foreach (IUserDataPlugin plugin in m_plugins)
  137. {
  138. UserAgentData agent = plugin.GetAgentByUUID(userId);
  139. if (agent != null)
  140. {
  141. return agent;
  142. }
  143. }
  144. return null;
  145. }
  146. public Uri GetUserUri(UserProfileData userProfile)
  147. {
  148. throw new NotImplementedException();
  149. }
  150. // see IUserService
  151. public virtual UserProfileData GetUserProfile(UUID uuid)
  152. {
  153. foreach (IUserDataPlugin plugin in m_plugins)
  154. {
  155. UserProfileData profile = plugin.GetUserByUUID(uuid);
  156. if (null != profile)
  157. {
  158. profile.CurrentAgent = GetUserAgent(profile.ID);
  159. return profile;
  160. }
  161. }
  162. return null;
  163. }
  164. public virtual List<AvatarPickerAvatar> GenerateAgentPickerRequestResponse(UUID queryID, string query)
  165. {
  166. List<AvatarPickerAvatar> allPickerList = new List<AvatarPickerAvatar>();
  167. foreach (IUserDataPlugin plugin in m_plugins)
  168. {
  169. try
  170. {
  171. List<AvatarPickerAvatar> pickerList = plugin.GeneratePickerResults(queryID, query);
  172. if (pickerList != null)
  173. allPickerList.AddRange(pickerList);
  174. }
  175. catch (Exception)
  176. {
  177. m_log.Error(
  178. "[USERSTORAGE]: Unable to generate AgentPickerData via " + plugin.Name + "(" + query + ")");
  179. }
  180. }
  181. return allPickerList;
  182. }
  183. public virtual bool UpdateUserProfile(UserProfileData data)
  184. {
  185. bool result = false;
  186. foreach (IUserDataPlugin plugin in m_plugins)
  187. {
  188. try
  189. {
  190. plugin.UpdateUserProfile(data);
  191. result = true;
  192. }
  193. catch (Exception e)
  194. {
  195. m_log.ErrorFormat(
  196. "[USERSTORAGE]: Unable to set user {0} {1} via {2}: {3}",
  197. data.FirstName, data.SurName, plugin.Name, e.ToString());
  198. }
  199. }
  200. return result;
  201. }
  202. #endregion
  203. #region Get UserAgent
  204. /// <summary>
  205. /// Loads a user agent by uuid (not called directly)
  206. /// </summary>
  207. /// <param name="uuid">The agent's UUID</param>
  208. /// <returns>Agent profiles</returns>
  209. public UserAgentData GetUserAgent(UUID uuid)
  210. {
  211. foreach (IUserDataPlugin plugin in m_plugins)
  212. {
  213. try
  214. {
  215. UserAgentData result = plugin.GetAgentByUUID(uuid);
  216. if (result != null)
  217. return result;
  218. }
  219. catch (Exception e)
  220. {
  221. m_log.Error("[USERSTORAGE]: Unable to find user via " + plugin.Name + "(" + e.ToString() + ")");
  222. }
  223. }
  224. return null;
  225. }
  226. /// <summary>
  227. /// Loads a user agent by name (not called directly)
  228. /// </summary>
  229. /// <param name="name">The agent's name</param>
  230. /// <returns>A user agent</returns>
  231. public UserAgentData GetUserAgent(string name)
  232. {
  233. foreach (IUserDataPlugin plugin in m_plugins)
  234. {
  235. try
  236. {
  237. UserAgentData result = plugin.GetAgentByName(name);
  238. if (result != null)
  239. return result;
  240. }
  241. catch (Exception e)
  242. {
  243. m_log.Error("[USERSTORAGE]: Unable to find user via " + plugin.Name + "(" + e.ToString() + ")");
  244. }
  245. }
  246. return null;
  247. }
  248. /// <summary>
  249. /// Loads a user agent by name (not called directly)
  250. /// </summary>
  251. /// <param name="fname">The agent's firstname</param>
  252. /// <param name="lname">The agent's lastname</param>
  253. /// <returns>A user agent</returns>
  254. public UserAgentData GetUserAgent(string fname, string lname)
  255. {
  256. foreach (IUserDataPlugin plugin in m_plugins)
  257. {
  258. try
  259. {
  260. UserAgentData result = plugin.GetAgentByName(fname, lname);
  261. if (result != null)
  262. return result;
  263. }
  264. catch (Exception e)
  265. {
  266. m_log.Error("[USERSTORAGE]: Unable to find user via " + plugin.Name + "(" + e.ToString() + ")");
  267. }
  268. }
  269. return null;
  270. }
  271. public virtual List<FriendListItem> GetUserFriendList(UUID ownerID)
  272. {
  273. List<FriendListItem> allFriends = new List<FriendListItem>();
  274. foreach (IUserDataPlugin plugin in m_plugins)
  275. {
  276. try
  277. {
  278. List<FriendListItem> friends = plugin.GetUserFriendList(ownerID);
  279. if (friends != null)
  280. allFriends.AddRange(friends);
  281. }
  282. catch (Exception e)
  283. {
  284. m_log.Error("[USERSTORAGE]: Unable to GetUserFriendList via " + plugin.Name + "(" + e.ToString() + ")");
  285. }
  286. }
  287. return allFriends;
  288. }
  289. public virtual Dictionary<UUID, FriendRegionInfo> GetFriendRegionInfos (List<UUID> uuids)
  290. {
  291. //Dictionary<UUID, FriendRegionInfo> allFriendRegions = new Dictionary<UUID, FriendRegionInfo>();
  292. foreach (IUserDataPlugin plugin in m_plugins)
  293. {
  294. try
  295. {
  296. Dictionary<UUID, FriendRegionInfo> friendRegions = plugin.GetFriendRegionInfos(uuids);
  297. if (friendRegions != null)
  298. return friendRegions;
  299. }
  300. catch (Exception e)
  301. {
  302. m_log.Error("[USERSTORAGE]: Unable to GetFriendRegionInfos via " + plugin.Name + "(" + e.ToString() + ")");
  303. }
  304. }
  305. return new Dictionary<UUID, FriendRegionInfo>();
  306. }
  307. public void StoreWebLoginKey(UUID agentID, UUID webLoginKey)
  308. {
  309. foreach (IUserDataPlugin plugin in m_plugins)
  310. {
  311. try
  312. {
  313. plugin.StoreWebLoginKey(agentID, webLoginKey);
  314. }
  315. catch (Exception e)
  316. {
  317. m_log.Error("[USERSTORAGE]: Unable to Store WebLoginKey via " + plugin.Name + "(" + e.ToString() + ")");
  318. }
  319. }
  320. }
  321. public virtual void AddNewUserFriend(UUID friendlistowner, UUID friend, uint perms)
  322. {
  323. foreach (IUserDataPlugin plugin in m_plugins)
  324. {
  325. try
  326. {
  327. plugin.AddNewUserFriend(friendlistowner, friend, perms);
  328. }
  329. catch (Exception e)
  330. {
  331. m_log.Error("[USERSTORAGE]: Unable to AddNewUserFriend via " + plugin.Name + "(" + e.ToString() + ")");
  332. }
  333. }
  334. }
  335. public virtual void RemoveUserFriend(UUID friendlistowner, UUID friend)
  336. {
  337. foreach (IUserDataPlugin plugin in m_plugins)
  338. {
  339. try
  340. {
  341. plugin.RemoveUserFriend(friendlistowner, friend);
  342. }
  343. catch (Exception e)
  344. {
  345. m_log.Error("[USERSTORAGE]: Unable to RemoveUserFriend via " + plugin.Name + "(" + e.ToString() + ")");
  346. }
  347. }
  348. }
  349. public virtual void UpdateUserFriendPerms(UUID friendlistowner, UUID friend, uint perms)
  350. {
  351. foreach (IUserDataPlugin plugin in m_plugins)
  352. {
  353. try
  354. {
  355. plugin.UpdateUserFriendPerms(friendlistowner, friend, perms);
  356. }
  357. catch (Exception e)
  358. {
  359. m_log.Error("[USERSTORAGE]: Unable to UpdateUserFriendPerms via " + plugin.Name + "(" + e.ToString() + ")");
  360. }
  361. }
  362. }
  363. /// <summary>
  364. /// Resets the currentAgent in the user profile
  365. /// </summary>
  366. /// <param name="agentID">The agent's ID</param>
  367. public virtual void ClearUserAgent(UUID agentID)
  368. {
  369. UserProfileData profile = GetUserProfile(agentID);
  370. if (profile == null)
  371. {
  372. return;
  373. }
  374. profile.CurrentAgent = null;
  375. UpdateUserProfile(profile);
  376. }
  377. #endregion
  378. #region CreateAgent
  379. /// <summary>
  380. /// Creates and initialises a new user agent - make sure to use CommitAgent when done to submit to the DB
  381. /// </summary>
  382. /// <param name="profile">The users profile</param>
  383. /// <param name="request">The users loginrequest</param>
  384. public void CreateAgent(UserProfileData profile, XmlRpcRequest request)
  385. {
  386. //m_log.DebugFormat("[USER MANAGER]: Creating agent {0} {1}", profile.Name, profile.ID);
  387. UserAgentData agent = new UserAgentData();
  388. // User connection
  389. agent.AgentOnline = true;
  390. if (request.Params.Count > 1)
  391. {
  392. if (request.Params[1] != null)
  393. {
  394. IPEndPoint RemoteIPEndPoint = (IPEndPoint)request.Params[1];
  395. agent.AgentIP = RemoteIPEndPoint.Address.ToString();
  396. agent.AgentPort = (uint)RemoteIPEndPoint.Port;
  397. }
  398. }
  399. // Generate sessions
  400. RNGCryptoServiceProvider rand = new RNGCryptoServiceProvider();
  401. byte[] randDataS = new byte[16];
  402. byte[] randDataSS = new byte[16];
  403. rand.GetBytes(randDataS);
  404. rand.GetBytes(randDataSS);
  405. agent.SecureSessionID = new UUID(randDataSS, 0);
  406. agent.SessionID = new UUID(randDataS, 0);
  407. // Profile UUID
  408. agent.ProfileID = profile.ID;
  409. // Current location/position/alignment
  410. if (profile.CurrentAgent != null)
  411. {
  412. agent.Region = profile.CurrentAgent.Region;
  413. agent.Handle = profile.CurrentAgent.Handle;
  414. agent.Position = profile.CurrentAgent.Position;
  415. agent.LookAt = profile.CurrentAgent.LookAt;
  416. }
  417. else
  418. {
  419. agent.Region = profile.HomeRegionID;
  420. agent.Handle = profile.HomeRegion;
  421. agent.Position = profile.HomeLocation;
  422. agent.LookAt = profile.HomeLookAt;
  423. }
  424. // What time did the user login?
  425. agent.LoginTime = Util.UnixTimeSinceEpoch();
  426. agent.LogoutTime = 0;
  427. profile.CurrentAgent = agent;
  428. }
  429. public void CreateAgent(UserProfileData profile, OSD request)
  430. {
  431. //m_log.DebugFormat("[USER MANAGER]: Creating agent {0} {1}", profile.Name, profile.ID);
  432. UserAgentData agent = new UserAgentData();
  433. // User connection
  434. agent.AgentOnline = true;
  435. //if (request.Params.Count > 1)
  436. //{
  437. // IPEndPoint RemoteIPEndPoint = (IPEndPoint)request.Params[1];
  438. // agent.AgentIP = RemoteIPEndPoint.Address.ToString();
  439. // agent.AgentPort = (uint)RemoteIPEndPoint.Port;
  440. //}
  441. // Generate sessions
  442. RNGCryptoServiceProvider rand = new RNGCryptoServiceProvider();
  443. byte[] randDataS = new byte[16];
  444. byte[] randDataSS = new byte[16];
  445. rand.GetBytes(randDataS);
  446. rand.GetBytes(randDataSS);
  447. agent.SecureSessionID = new UUID(randDataSS, 0);
  448. agent.SessionID = new UUID(randDataS, 0);
  449. // Profile UUID
  450. agent.ProfileID = profile.ID;
  451. // Current location/position/alignment
  452. if (profile.CurrentAgent != null)
  453. {
  454. agent.Region = profile.CurrentAgent.Region;
  455. agent.Handle = profile.CurrentAgent.Handle;
  456. agent.Position = profile.CurrentAgent.Position;
  457. agent.LookAt = profile.CurrentAgent.LookAt;
  458. }
  459. else
  460. {
  461. agent.Region = profile.HomeRegionID;
  462. agent.Handle = profile.HomeRegion;
  463. agent.Position = profile.HomeLocation;
  464. agent.LookAt = profile.HomeLookAt;
  465. }
  466. // What time did the user login?
  467. agent.LoginTime = Util.UnixTimeSinceEpoch();
  468. agent.LogoutTime = 0;
  469. profile.CurrentAgent = agent;
  470. }
  471. /// <summary>
  472. /// Saves a target agent to the database
  473. /// </summary>
  474. /// <param name="profile">The users profile</param>
  475. /// <returns>Successful?</returns>
  476. public bool CommitAgent(ref UserProfileData profile)
  477. {
  478. //m_log.DebugFormat("[USER MANAGER]: Committing agent {0} {1}", profile.Name, profile.ID);
  479. // TODO: how is this function different from setUserProfile? -> Add AddUserAgent() here and commit both tables "users" and "agents"
  480. // TODO: what is the logic should be?
  481. bool ret = false;
  482. ret = AddUserAgent(profile.CurrentAgent);
  483. ret = ret & UpdateUserProfile(profile);
  484. return ret;
  485. }
  486. /// <summary>
  487. /// Process a user logoff from OpenSim.
  488. /// </summary>
  489. /// <param name="userid"></param>
  490. /// <param name="regionid"></param>
  491. /// <param name="regionhandle"></param>
  492. /// <param name="position"></param>
  493. /// <param name="lookat"></param>
  494. public virtual void LogOffUser(UUID userid, UUID regionid, ulong regionhandle, Vector3 position, Vector3 lookat)
  495. {
  496. if (StatsManager.UserStats != null)
  497. StatsManager.UserStats.AddLogout();
  498. UserProfileData userProfile = GetUserProfile(userid);
  499. if (userProfile != null)
  500. {
  501. UserAgentData userAgent = userProfile.CurrentAgent;
  502. if (userAgent != null)
  503. {
  504. userAgent.AgentOnline = false;
  505. userAgent.LogoutTime = Util.UnixTimeSinceEpoch();
  506. //userAgent.sessionID = UUID.Zero;
  507. if (regionid != UUID.Zero)
  508. {
  509. userAgent.Region = regionid;
  510. }
  511. userAgent.Handle = regionhandle;
  512. userAgent.Position = position;
  513. userAgent.LookAt = lookat;
  514. //userProfile.CurrentAgent = userAgent;
  515. userProfile.LastLogin = userAgent.LogoutTime;
  516. CommitAgent(ref userProfile);
  517. }
  518. else
  519. {
  520. // If currentagent is null, we can't reference it here or the UserServer crashes!
  521. m_log.Info("[LOGOUT]: didn't save logout position: " + userid.ToString());
  522. }
  523. }
  524. else
  525. {
  526. m_log.Warn("[LOGOUT]: Unknown User logged out");
  527. }
  528. }
  529. public void LogOffUser(UUID userid, UUID regionid, ulong regionhandle, float posx, float posy, float posz)
  530. {
  531. LogOffUser(userid, regionid, regionhandle, new Vector3(posx, posy, posz), new Vector3());
  532. }
  533. #endregion
  534. /// <summary>
  535. /// Add a new user
  536. /// </summary>
  537. /// <param name="firstName">first name</param>
  538. /// <param name="lastName">last name</param>
  539. /// <param name="password">password</param>
  540. /// <param name="email">email</param>
  541. /// <param name="regX">location X</param>
  542. /// <param name="regY">location Y</param>
  543. /// <returns>The UUID of the created user profile. On failure, returns UUID.Zero</returns>
  544. public virtual UUID AddUser(string firstName, string lastName, string password, string email, uint regX, uint regY)
  545. {
  546. return AddUser(firstName, lastName, password, email, regX, regY, UUID.Random());
  547. }
  548. /// <summary>
  549. /// Add a new user
  550. /// </summary>
  551. /// <param name="firstName">first name</param>
  552. /// <param name="lastName">last name</param>
  553. /// <param name="password">password</param>
  554. /// <param name="email">email</param>
  555. /// <param name="regX">location X</param>
  556. /// <param name="regY">location Y</param>
  557. /// <param name="SetUUID">UUID of avatar.</param>
  558. /// <returns>The UUID of the created user profile. On failure, returns UUID.Zero</returns>
  559. public virtual UUID AddUser(
  560. string firstName, string lastName, string password, string email, uint regX, uint regY, UUID SetUUID)
  561. {
  562. string md5PasswdHash = Util.Md5Hash(Util.Md5Hash(password) + ":" + String.Empty);
  563. UserProfileData user = new UserProfileData();
  564. user.HomeLocation = new Vector3(128, 128, 100);
  565. user.ID = SetUUID;
  566. user.FirstName = firstName;
  567. user.SurName = lastName;
  568. user.PasswordHash = md5PasswdHash;
  569. user.PasswordSalt = String.Empty;
  570. user.Created = Util.UnixTimeSinceEpoch();
  571. user.HomeLookAt = new Vector3(100, 100, 100);
  572. user.HomeRegionX = regX;
  573. user.HomeRegionY = regY;
  574. user.Email = email;
  575. foreach (IUserDataPlugin plugin in m_plugins)
  576. {
  577. try
  578. {
  579. plugin.AddNewUserProfile(user);
  580. }
  581. catch (Exception e)
  582. {
  583. m_log.Error("[USERSTORAGE]: Unable to add user via " + plugin.Name + "(" + e.ToString() + ")");
  584. }
  585. }
  586. UserProfileData userProf = GetUserProfile(firstName, lastName);
  587. if (userProf == null)
  588. {
  589. return UUID.Zero;
  590. }
  591. else
  592. {
  593. //
  594. // WARNING: This is a horrible hack
  595. // The purpose here is to avoid touching the user server at this point.
  596. // There are dragons there that I can't deal with right now.
  597. // diva 06/09/09
  598. //
  599. if (m_InventoryService != null)
  600. {
  601. // local service (standalone)
  602. m_log.Debug("[USERSTORAGE]: using IInventoryService to create user's inventory");
  603. m_InventoryService.CreateUserInventory(userProf.ID);
  604. InventoryFolderBase rootfolder = m_InventoryService.GetRootFolder(userProf.ID);
  605. if (rootfolder != null)
  606. userProf.RootInventoryFolderID = rootfolder.ID;
  607. }
  608. else if (m_commsManager.InterServiceInventoryService != null)
  609. {
  610. // used by the user server
  611. m_log.Debug("[USERSTORAGE]: using m_commsManager.InterServiceInventoryService to create user's inventory");
  612. m_commsManager.InterServiceInventoryService.CreateNewUserInventory(userProf.ID);
  613. }
  614. return userProf.ID;
  615. }
  616. }
  617. /// <summary>
  618. /// Reset a user password.
  619. /// </summary>
  620. /// <param name="firstName"></param>
  621. /// <param name="lastName"></param>
  622. /// <param name="newPassword"></param>
  623. /// <returns>true if the update was successful, false otherwise</returns>
  624. public virtual bool ResetUserPassword(string firstName, string lastName, string newPassword)
  625. {
  626. string md5PasswdHash = Util.Md5Hash(Util.Md5Hash(newPassword) + ":" + String.Empty);
  627. UserProfileData profile = GetUserProfile(firstName, lastName);
  628. if (null == profile)
  629. {
  630. m_log.ErrorFormat("[USERSTORAGE]: Could not find user {0} {1}", firstName, lastName);
  631. return false;
  632. }
  633. profile.PasswordHash = md5PasswdHash;
  634. profile.PasswordSalt = String.Empty;
  635. UpdateUserProfile(profile);
  636. return true;
  637. }
  638. public abstract UserProfileData SetupMasterUser(string firstName, string lastName);
  639. public abstract UserProfileData SetupMasterUser(string firstName, string lastName, string password);
  640. public abstract UserProfileData SetupMasterUser(UUID uuid);
  641. /// <summary>
  642. /// Add an agent using data plugins.
  643. /// </summary>
  644. /// <param name="agentdata">The agent data to be added</param>
  645. /// <returns>
  646. /// true if at least one plugin added the user agent. false if no plugin successfully added the agent
  647. /// </returns>
  648. public virtual bool AddUserAgent(UserAgentData agentdata)
  649. {
  650. bool result = false;
  651. foreach (IUserDataPlugin plugin in m_plugins)
  652. {
  653. try
  654. {
  655. plugin.AddNewUserAgent(agentdata);
  656. result = true;
  657. }
  658. catch (Exception e)
  659. {
  660. m_log.Error("[USERSTORAGE]: Unable to add agent via " + plugin.Name + "(" + e.ToString() + ")");
  661. }
  662. }
  663. return result;
  664. }
  665. /// <summary>
  666. /// Get avatar appearance information
  667. /// </summary>
  668. /// <param name="user"></param>
  669. /// <returns></returns>
  670. public virtual AvatarAppearance GetUserAppearance(UUID user)
  671. {
  672. foreach (IUserDataPlugin plugin in m_plugins)
  673. {
  674. try
  675. {
  676. AvatarAppearance appearance = plugin.GetUserAppearance(user);
  677. if (appearance != null)
  678. return appearance;
  679. }
  680. catch (Exception e)
  681. {
  682. m_log.ErrorFormat("[USERSTORAGE]: Unable to find user appearance {0} via {1} ({2})", user.ToString(), plugin.Name, e.ToString());
  683. }
  684. }
  685. return null;
  686. }
  687. public virtual void UpdateUserAppearance(UUID user, AvatarAppearance appearance)
  688. {
  689. foreach (IUserDataPlugin plugin in m_plugins)
  690. {
  691. try
  692. {
  693. plugin.UpdateUserAppearance(user, appearance);
  694. }
  695. catch (Exception e)
  696. {
  697. m_log.ErrorFormat("[USERSTORAGE]: Unable to update user appearance {0} via {1} ({2})", user.ToString(), plugin.Name, e.ToString());
  698. }
  699. }
  700. }
  701. #region IAuthentication
  702. protected Dictionary<UUID, List<string>> m_userKeys = new Dictionary<UUID, List<string>>();
  703. /// <summary>
  704. /// This generates authorization keys in the form
  705. /// http://userserver/uuid
  706. /// after verifying that the caller is, indeed, authorized to request a key
  707. /// </summary>
  708. /// <param name="url">URL of the user server</param>
  709. /// <param name="userID">The user ID requesting the new key</param>
  710. /// <param name="authToken">The original authorization token for that user, obtained during login</param>
  711. /// <returns></returns>
  712. public string GetNewKey(string url, UUID userID, UUID authToken)
  713. {
  714. UserProfileData profile = GetUserProfile(userID);
  715. string newKey = string.Empty;
  716. if (!url.EndsWith("/"))
  717. url = url + "/";
  718. if (profile != null)
  719. {
  720. // I'm overloading webloginkey for this, so that no changes are needed in the DB
  721. // The uses of webloginkey are fairly mutually exclusive
  722. if (profile.WebLoginKey.Equals(authToken))
  723. {
  724. newKey = UUID.Random().ToString();
  725. List<string> keys;
  726. lock (m_userKeys)
  727. {
  728. if (m_userKeys.ContainsKey(userID))
  729. {
  730. keys = m_userKeys[userID];
  731. }
  732. else
  733. {
  734. keys = new List<string>();
  735. m_userKeys.Add(userID, keys);
  736. }
  737. keys.Add(newKey);
  738. }
  739. m_log.InfoFormat("[USERAUTH]: Successfully generated new auth key for user {0}", userID);
  740. }
  741. else
  742. m_log.Warn("[USERAUTH]: Unauthorized key generation request. Denying new key.");
  743. }
  744. else
  745. m_log.Warn("[USERAUTH]: User not found.");
  746. return url + newKey;
  747. }
  748. /// <summary>
  749. /// This verifies the uuid portion of the key given out by GenerateKey
  750. /// </summary>
  751. /// <param name="userID"></param>
  752. /// <param name="key"></param>
  753. /// <returns></returns>
  754. public bool VerifyKey(UUID userID, string key)
  755. {
  756. lock (m_userKeys)
  757. {
  758. if (m_userKeys.ContainsKey(userID))
  759. {
  760. List<string> keys = m_userKeys[userID];
  761. if (keys.Contains(key))
  762. {
  763. // Keys are one-time only, so remove it
  764. keys.Remove(key);
  765. return true;
  766. }
  767. return false;
  768. }
  769. else
  770. return false;
  771. }
  772. }
  773. public virtual bool VerifySession(UUID userID, UUID sessionID)
  774. {
  775. UserProfileData userProfile = GetUserProfile(userID);
  776. if (userProfile != null && userProfile.CurrentAgent != null)
  777. {
  778. m_log.DebugFormat("[USER AUTH]: Verifying session {0} for {1}; current session {2}", sessionID, userID, userProfile.CurrentAgent.SessionID);
  779. if (userProfile.CurrentAgent.SessionID == sessionID)
  780. {
  781. return true;
  782. }
  783. }
  784. return false;
  785. }
  786. #endregion
  787. }
  788. }