aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Framework/UserManager/UserManagerBase.cs
diff options
context:
space:
mode:
authorMW2007-06-27 15:28:52 +0000
committerMW2007-06-27 15:28:52 +0000
commit646bbbc84b8010e0dacbeed5342cdb045f46cc49 (patch)
tree770b34d19855363c3c113ab9a0af9a56d821d887 /OpenSim/Framework/UserManager/UserManagerBase.cs
downloadopensim-SC-646bbbc84b8010e0dacbeed5342cdb045f46cc49.zip
opensim-SC-646bbbc84b8010e0dacbeed5342cdb045f46cc49.tar.gz
opensim-SC-646bbbc84b8010e0dacbeed5342cdb045f46cc49.tar.bz2
opensim-SC-646bbbc84b8010e0dacbeed5342cdb045f46cc49.tar.xz
Some work on restructuring the namespaces / project names. Note this doesn't compile yet as not all the code has been changed to use the new namespaces. Am committing it now for feedback on the namespaces.
Diffstat (limited to 'OpenSim/Framework/UserManager/UserManagerBase.cs')
-rw-r--r--OpenSim/Framework/UserManager/UserManagerBase.cs641
1 files changed, 641 insertions, 0 deletions
diff --git a/OpenSim/Framework/UserManager/UserManagerBase.cs b/OpenSim/Framework/UserManager/UserManagerBase.cs
new file mode 100644
index 0000000..eb46c14
--- /dev/null
+++ b/OpenSim/Framework/UserManager/UserManagerBase.cs
@@ -0,0 +1,641 @@
1/*
2* Copyright (c) Contributors, http://www.openmetaverse.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*/
28using System;
29using System.Collections;
30using System.Collections.Generic;
31using System.Text;
32using OpenSim.Framework.Data;
33using libsecondlife;
34using System.Reflection;
35
36using System.Xml;
37using Nwc.XmlRpc;
38using OpenSim.Framework.Sims;
39using OpenSim.Framework.Inventory;
40using OpenSim.Framework.Utilities;
41
42using System.Security.Cryptography;
43
44namespace OpenSim.Framework.UserManagement
45{
46 public class UserManagerBase
47 {
48 public OpenSim.Framework.Interfaces.UserConfig _config;
49 Dictionary<string, IUserData> _plugins = new Dictionary<string, IUserData>();
50
51 /// <summary>
52 /// Adds a new user server plugin - user servers will be requested in the order they were loaded.
53 /// </summary>
54 /// <param name="FileName">The filename to the user server plugin DLL</param>
55 public void AddPlugin(string FileName)
56 {
57 OpenSim.Framework.Console.MainLog.Instance.Verbose( "Userstorage: Attempting to load " + FileName);
58 Assembly pluginAssembly = Assembly.LoadFrom(FileName);
59
60 OpenSim.Framework.Console.MainLog.Instance.Verbose( "Userstorage: Found " + pluginAssembly.GetTypes().Length + " interfaces.");
61 foreach (Type pluginType in pluginAssembly.GetTypes())
62 {
63 if (!pluginType.IsAbstract)
64 {
65 Type typeInterface = pluginType.GetInterface("IUserData", true);
66
67 if (typeInterface != null)
68 {
69 IUserData plug = (IUserData)Activator.CreateInstance(pluginAssembly.GetType(pluginType.ToString()));
70 plug.Initialise();
71 this._plugins.Add(plug.getName(), plug);
72 OpenSim.Framework.Console.MainLog.Instance.Verbose( "Userstorage: Added IUserData Interface");
73 }
74
75 typeInterface = null;
76 }
77 }
78
79 pluginAssembly = null;
80 }
81
82 #region Get UserProfile
83 /// <summary>
84 /// Loads a user profile from a database by UUID
85 /// </summary>
86 /// <param name="uuid">The target UUID</param>
87 /// <returns>A user profile</returns>
88 public UserProfileData getUserProfile(LLUUID uuid)
89 {
90 foreach (KeyValuePair<string, IUserData> plugin in _plugins)
91 {
92 try
93 {
94 UserProfileData profile = plugin.Value.getUserByUUID(uuid);
95 profile.currentAgent = getUserAgent(profile.UUID);
96 return profile;
97 }
98 catch (Exception e)
99 {
100 OpenSim.Framework.Console.MainLog.Instance.Verbose( "Unable to find user via " + plugin.Key + "(" + e.ToString() + ")");
101 }
102 }
103
104 return null;
105 }
106
107
108 /// <summary>
109 /// Loads a user profile by name
110 /// </summary>
111 /// <param name="name">The target name</param>
112 /// <returns>A user profile</returns>
113 public UserProfileData getUserProfile(string name)
114 {
115 foreach (KeyValuePair<string, IUserData> plugin in _plugins)
116 {
117 try
118 {
119 UserProfileData profile = plugin.Value.getUserByName(name);
120 profile.currentAgent = getUserAgent(profile.UUID);
121 return profile;
122 }
123 catch (Exception e)
124 {
125 OpenSim.Framework.Console.MainLog.Instance.Verbose( "Unable to find user via " + plugin.Key + "(" + e.ToString() + ")");
126 }
127 }
128
129 return null;
130 }
131
132 /// <summary>
133 /// Loads a user profile by name
134 /// </summary>
135 /// <param name="fname">First name</param>
136 /// <param name="lname">Last name</param>
137 /// <returns>A user profile</returns>
138 public UserProfileData getUserProfile(string fname, string lname)
139 {
140 foreach (KeyValuePair<string, IUserData> plugin in _plugins)
141 {
142 try
143 {
144 UserProfileData profile = plugin.Value.getUserByName(fname,lname);
145 try
146 {
147 profile.currentAgent = getUserAgent(profile.UUID);
148 }
149 catch (Exception e)
150 {
151 // Ignore
152 }
153 return profile;
154 }
155 catch (Exception e)
156 {
157 OpenSim.Framework.Console.MainLog.Instance.Verbose( "Unable to find user via " + plugin.Key + "(" + e.ToString() + ")");
158 }
159 }
160
161 return null;
162 }
163 #endregion
164
165 #region Get UserAgent
166 /// <summary>
167 /// Loads a user agent by uuid (not called directly)
168 /// </summary>
169 /// <param name="uuid">The agents UUID</param>
170 /// <returns>Agent profiles</returns>
171 public UserAgentData getUserAgent(LLUUID uuid)
172 {
173 foreach (KeyValuePair<string, IUserData> plugin in _plugins)
174 {
175 try
176 {
177 return plugin.Value.getAgentByUUID(uuid);
178 }
179 catch (Exception e)
180 {
181 OpenSim.Framework.Console.MainLog.Instance.Verbose( "Unable to find user via " + plugin.Key + "(" + e.ToString() + ")");
182 }
183 }
184
185 return null;
186 }
187
188 /// <summary>
189 /// Loads a user agent by name (not called directly)
190 /// </summary>
191 /// <param name="name">The agents name</param>
192 /// <returns>A user agent</returns>
193 public UserAgentData getUserAgent(string name)
194 {
195 foreach (KeyValuePair<string, IUserData> plugin in _plugins)
196 {
197 try
198 {
199 return plugin.Value.getAgentByName(name);
200 }
201 catch (Exception e)
202 {
203 OpenSim.Framework.Console.MainLog.Instance.Verbose( "Unable to find user via " + plugin.Key + "(" + e.ToString() + ")");
204 }
205 }
206
207 return null;
208 }
209
210 /// <summary>
211 /// Loads a user agent by name (not called directly)
212 /// </summary>
213 /// <param name="fname">The agents firstname</param>
214 /// <param name="lname">The agents lastname</param>
215 /// <returns>A user agent</returns>
216 public UserAgentData getUserAgent(string fname, string lname)
217 {
218 foreach (KeyValuePair<string, IUserData> plugin in _plugins)
219 {
220 try
221 {
222 return plugin.Value.getAgentByName(fname,lname);
223 }
224 catch (Exception e)
225 {
226 OpenSim.Framework.Console.MainLog.Instance.Verbose( "Unable to find user via " + plugin.Key + "(" + e.ToString() + ")");
227 }
228 }
229
230 return null;
231 }
232
233 #endregion
234
235 #region CreateAgent
236 /// <summary>
237 /// Creates and initialises a new user agent - make sure to use CommitAgent when done to submit to the DB
238 /// </summary>
239 /// <param name="profile">The users profile</param>
240 /// <param name="request">The users loginrequest</param>
241 public void CreateAgent(ref UserProfileData profile, XmlRpcRequest request)
242 {
243 Hashtable requestData = (Hashtable)request.Params[0];
244
245 UserAgentData agent = new UserAgentData();
246
247 // User connection
248 agent.agentIP = "";
249 agent.agentOnline = true;
250 agent.agentPort = 0;
251
252 // Generate sessions
253 RNGCryptoServiceProvider rand = new RNGCryptoServiceProvider();
254 byte[] randDataS = new byte[16];
255 byte[] randDataSS = new byte[16];
256 rand.GetBytes(randDataS);
257 rand.GetBytes(randDataSS);
258
259 agent.secureSessionID = new LLUUID(randDataSS, 0);
260 agent.sessionID = new LLUUID(randDataS, 0);
261
262 // Profile UUID
263 agent.UUID = profile.UUID;
264
265 // Current position (from Home)
266 agent.currentHandle = profile.homeRegion;
267 agent.currentPos = profile.homeLocation;
268
269 // If user specified additional start, use that
270 if (requestData.ContainsKey("start"))
271 {
272 string startLoc = ((string)requestData["start"]).Trim();
273 if (!(startLoc == "last" || startLoc == "home"))
274 {
275 // Format: uri:Ahern&162&213&34
276 try
277 {
278 string[] parts = startLoc.Remove(0, 4).Split('&');
279 string region = parts[0];
280
281 ////////////////////////////////////////////////////
282 //SimProfile SimInfo = new SimProfile();
283 //SimInfo = SimInfo.LoadFromGrid(theUser.currentAgent.currentHandle, _config.GridServerURL, _config.GridSendKey, _config.GridRecvKey);
284 }
285 catch (Exception e)
286 {
287
288 }
289 }
290 }
291
292 // What time did the user login?
293 agent.loginTime = Util.UnixTimeSinceEpoch();
294 agent.logoutTime = 0;
295
296 // Current location
297 agent.regionID = new LLUUID(); // Fill in later
298 agent.currentRegion = new LLUUID(); // Fill in later
299
300 profile.currentAgent = agent;
301 }
302
303 /// <summary>
304 /// Saves a target agent to the database
305 /// </summary>
306 /// <param name="profile">The users profile</param>
307 /// <returns>Successful?</returns>
308 public bool CommitAgent(ref UserProfileData profile)
309 {
310 // Saves the agent to database
311 return true;
312 }
313
314 #endregion
315
316 /// <summary>
317 /// Checks a user against it's password hash
318 /// </summary>
319 /// <param name="profile">The users profile</param>
320 /// <param name="password">The supplied password</param>
321 /// <returns>Authenticated?</returns>
322 public virtual bool AuthenticateUser(ref UserProfileData profile, string password)
323 {
324 OpenSim.Framework.Console.MainLog.Instance.Verbose(
325 "Authenticating " + profile.username + " " + profile.surname);
326
327 password = password.Remove(0, 3); //remove $1$
328
329 string s = Util.Md5Hash(password + ":" + profile.passwordSalt);
330
331 return profile.passwordHash.Equals(s.ToString(), StringComparison.InvariantCultureIgnoreCase);
332 }
333
334 #region Xml Response
335
336 /// <summary>
337 ///
338 /// </summary>
339 /// <param name="firstname"></param>
340 /// <param name="lastname"></param>
341 /// <returns></returns>
342 public virtual UserProfileData GetTheUser(string firstname, string lastname)
343 {
344 return getUserProfile(firstname, lastname);
345 }
346
347 /// <summary>
348 ///
349 /// </summary>
350 /// <returns></returns>
351 public virtual string GetMessage()
352 {
353 return _config.DefaultStartupMsg;
354 }
355
356 /// <summary>
357 /// Customises the login response and fills in missing values.
358 /// </summary>
359 /// <param name="response">The existing response</param>
360 /// <param name="theUser">The user profile</param>
361 public virtual void CustomiseResponse(ref LoginResponse response, ref UserProfileData theUser)
362 {
363
364 }
365
366 /// <summary>
367 /// Main user login function
368 /// </summary>
369 /// <param name="request">The XMLRPC request</param>
370 /// <returns>The response to send</returns>
371 public XmlRpcResponse XmlRpcLoginMethod(XmlRpcRequest request)
372 {
373 XmlRpcResponse response = new XmlRpcResponse();
374 Hashtable requestData = (Hashtable)request.Params[0];
375
376 bool GoodXML = (requestData.Contains("first") && requestData.Contains("last") && requestData.Contains("passwd"));
377 bool GoodLogin = false;
378 string firstname = "";
379 string lastname = "";
380 string passwd = "";
381
382 UserProfileData TheUser;
383 LoginResponse logResponse = new LoginResponse();
384
385 if (GoodXML)
386 {
387 firstname = (string)requestData["first"];
388 lastname = (string)requestData["last"];
389 passwd = (string)requestData["passwd"];
390
391 TheUser = GetTheUser(firstname, lastname);
392 if (TheUser == null)
393 return logResponse.CreateLoginFailedResponse();
394
395 GoodLogin = AuthenticateUser(ref TheUser, passwd);
396 }
397 else
398 {
399 return logResponse.CreateGridErrorResponse();
400 }
401
402 if (!GoodLogin)
403 {
404 return logResponse.CreateLoginFailedResponse();
405 }
406 else
407 {
408 // If we already have a session...
409 if (TheUser.currentAgent != null && TheUser.currentAgent.agentOnline)
410 {
411 // Reject the login
412 return logResponse.CreateAlreadyLoggedInResponse();
413 }
414 // Otherwise...
415 // Create a new agent session
416 CreateAgent(ref TheUser, request);
417
418 try
419 {
420
421 LLUUID AgentID = TheUser.UUID;
422
423 // Inventory Library Section
424 ArrayList AgentInventoryArray = new ArrayList();
425 Hashtable TempHash;
426
427 AgentInventory Library = new AgentInventory();
428 Library.CreateRootFolder(AgentID, true);
429
430 foreach (InventoryFolder InvFolder in Library.InventoryFolders.Values)
431 {
432 TempHash = new Hashtable();
433 TempHash["name"] = InvFolder.FolderName;
434 TempHash["parent_id"] = InvFolder.ParentID.ToStringHyphenated();
435 TempHash["version"] = (Int32)InvFolder.Version;
436 TempHash["type_default"] = (Int32)InvFolder.DefaultType;
437 TempHash["folder_id"] = InvFolder.FolderID.ToStringHyphenated();
438 AgentInventoryArray.Add(TempHash);
439 }
440
441 Hashtable InventoryRootHash = new Hashtable();
442 InventoryRootHash["folder_id"] = Library.InventoryRoot.FolderID.ToStringHyphenated();
443 ArrayList InventoryRoot = new ArrayList();
444 InventoryRoot.Add(InventoryRootHash);
445
446 // Circuit Code
447 uint circode = (uint)(Util.RandomClass.Next());
448
449 logResponse.Lastname = TheUser.surname;
450 logResponse.Firstname = TheUser.username;
451 logResponse.AgentID = AgentID.ToStringHyphenated();
452 logResponse.SessionID = TheUser.currentAgent.sessionID.ToStringHyphenated();
453 logResponse.SecureSessionID = TheUser.currentAgent.secureSessionID.ToStringHyphenated();
454 logResponse.InventoryRoot = InventoryRoot;
455 logResponse.InventorySkeleton = AgentInventoryArray;
456 logResponse.CircuitCode = (Int32)circode;
457 logResponse.RegionX = 0; //overwritten
458 logResponse.RegionY = 0; //overwritten
459 logResponse.Home = "!!null temporary value {home}!!"; // Overwritten
460 //logResponse.LookAt = "\n[r" + TheUser.homeLookAt.X.ToString() + ",r" + TheUser.homeLookAt.Y.ToString() + ",r" + TheUser.homeLookAt.Z.ToString() + "]\n";
461 logResponse.SimAddress = "127.0.0.1"; //overwritten
462 logResponse.SimPort = 0; //overwritten
463 logResponse.Message = this.GetMessage();
464
465 try
466 {
467 this.CustomiseResponse(ref logResponse, ref TheUser);
468 }
469 catch (Exception e)
470 {
471 System.Console.WriteLine(e.ToString());
472 return logResponse.CreateDeadRegionResponse();
473 }
474 CommitAgent(ref TheUser);
475
476 return logResponse.ToXmlRpcResponse();
477
478 }
479 catch (Exception E)
480 {
481 System.Console.WriteLine(E.ToString());
482 }
483 //}
484 }
485 return response;
486
487 }
488
489 #endregion
490
491 /// <summary>
492 /// Deletes an active agent session
493 /// </summary>
494 /// <param name="request">The request</param>
495 /// <param name="path">The path (eg /bork/narf/test)</param>
496 /// <param name="param">Parameters sent</param>
497 /// <returns>Success "OK" else error</returns>
498 public string RestDeleteUserSessionMethod(string request, string path, string param)
499 {
500 // TODO! Important!
501
502 return "OK";
503 }
504
505 /// <summary>
506 ///
507 /// </summary>
508 /// <param name="user"></param>
509 public void AddUserProfile(string firstName, string lastName, string pass, uint regX, uint regY)
510 {
511 UserProfileData user = new UserProfileData();
512 user.homeLocation = new LLVector3(128, 128, 100);
513 user.UUID = LLUUID.Random();
514 user.username = firstName;
515 user.surname = lastName;
516 user.passwordHash = pass;
517 user.passwordSalt = "";
518 user.created = Util.UnixTimeSinceEpoch();
519 user.homeLookAt = new LLVector3(100, 100, 100);
520 user.homeRegion = Util.UIntsToLong((regX * 256), (regY * 256));
521
522 foreach (KeyValuePair<string, IUserData> plugin in _plugins)
523 {
524 try
525 {
526 plugin.Value.addNewUserProfile(user);
527
528 }
529 catch (Exception e)
530 {
531 OpenSim.Framework.Console.MainLog.Instance.Verbose("Unable to add user via " + plugin.Key + "(" + e.ToString() + ")");
532 }
533 }
534 }
535
536 /// <summary>
537 /// Returns an error message that the user could not be found in the database
538 /// </summary>
539 /// <returns>XML string consisting of a error element containing individual error(s)</returns>
540 public string CreateUnknownUserErrorResponse()
541 {
542 System.IO.StringWriter sw = new System.IO.StringWriter();
543 XmlTextWriter xw = new XmlTextWriter(sw);
544
545 // Header
546 xw.Formatting = Formatting.Indented;
547 xw.WriteStartDocument();
548 xw.WriteDocType("error", null, null, null);
549 xw.WriteComment("An error occured");
550 xw.WriteStartElement("error");
551
552 // User
553 xw.WriteElementString("unknownuser", "Unable to find a user with that name");
554
555 // Footer
556 xw.WriteEndElement();
557 xw.Flush();
558 xw.Close();
559
560 return sw.ToString();
561 }
562
563 /// <summary>
564 /// Converts a user profile to an XML element which can be returned
565 /// </summary>
566 /// <param name="profile">The user profile</param>
567 /// <returns>A string containing an XML Document of the user profile</returns>
568 public string ProfileToXml(UserProfileData profile)
569 {
570 System.IO.StringWriter sw = new System.IO.StringWriter();
571 XmlTextWriter xw = new XmlTextWriter(sw);
572
573 // Header
574 xw.Formatting = Formatting.Indented;
575 xw.WriteStartDocument();
576 xw.WriteDocType("userprofile", null, null, null);
577 xw.WriteComment("Found user profiles matching the request");
578 xw.WriteStartElement("users");
579
580 // User
581 xw.WriteStartElement("user");
582 // Account information
583 xw.WriteAttributeString("firstname", profile.username);
584 xw.WriteAttributeString("lastname", profile.surname);
585 xw.WriteAttributeString("uuid", profile.UUID.ToStringHyphenated());
586 // Server Information
587 xw.WriteAttributeString("server_inventory", profile.userInventoryURI);
588 xw.WriteAttributeString("server_asset", profile.userAssetURI);
589 // Profile Information
590 xw.WriteAttributeString("profile_about", profile.profileAboutText);
591 xw.WriteAttributeString("profile_firstlife_about", profile.profileFirstText);
592 xw.WriteAttributeString("profile_firstlife_image", profile.profileFirstImage.ToStringHyphenated());
593 xw.WriteAttributeString("profile_can_do", profile.profileCanDoMask.ToString());
594 xw.WriteAttributeString("profile_want_do", profile.profileWantDoMask.ToString());
595 xw.WriteAttributeString("profile_image", profile.profileImage.ToStringHyphenated());
596 xw.WriteAttributeString("profile_created",profile.created.ToString());
597 xw.WriteAttributeString("profile_lastlogin",profile.lastLogin.ToString());
598 // Home region information
599 xw.WriteAttributeString("home_coordinates", profile.homeLocation.ToString());
600 xw.WriteAttributeString("home_region", profile.homeRegion.ToString());
601 xw.WriteAttributeString("home_look", profile.homeLookAt.ToString());
602
603 xw.WriteEndElement();
604
605 // Footer
606 xw.WriteEndElement();
607 xw.Flush();
608 xw.Close();
609
610 return sw.ToString();
611 }
612
613 #region REST Methods
614 //should most likely move out of here and into the grid's userserver sub class
615 public string RestGetUserMethodName(string request, string path, string param)
616 {
617 UserProfileData userProfile = getUserProfile(param.Trim());
618
619 if (userProfile == null)
620 {
621 return CreateUnknownUserErrorResponse();
622 }
623
624 return ProfileToXml(userProfile);
625 }
626
627 public string RestGetUserMethodUUID(string request, string path, string param)
628 {
629 UserProfileData userProfile = getUserProfile(new LLUUID(param));
630
631 if (userProfile == null)
632 {
633 return CreateUnknownUserErrorResponse();
634 }
635
636 return ProfileToXml(userProfile);
637 }
638 #endregion
639
640 }
641}