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