UserManagerBase.cs 31 KB

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