aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Framework/Communications/Services/LoginService.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Framework/Communications/Services/LoginService.cs')
-rw-r--r--OpenSim/Framework/Communications/Services/LoginService.cs1243
1 files changed, 0 insertions, 1243 deletions
diff --git a/OpenSim/Framework/Communications/Services/LoginService.cs b/OpenSim/Framework/Communications/Services/LoginService.cs
deleted file mode 100644
index 57ca704..0000000
--- a/OpenSim/Framework/Communications/Services/LoginService.cs
+++ /dev/null
@@ -1,1243 +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;
30using System.Collections.Generic;
31using System.IO;
32using System.Net;
33using System.Reflection;
34using System.Text.RegularExpressions;
35using System.Threading;
36using System.Web;
37using log4net;
38using Nwc.XmlRpc;
39using OpenMetaverse;
40using OpenMetaverse.StructuredData;
41using OpenSim.Framework;
42using OpenSim.Framework.Communications.Cache;
43using OpenSim.Framework.Statistics;
44using OpenSim.Services.Interfaces;
45
46namespace OpenSim.Framework.Communications.Services
47{
48 public abstract class LoginService
49 {
50 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
51
52 protected string m_welcomeMessage = "Welcome to OpenSim";
53 protected int m_minLoginLevel = 0;
54 protected UserManagerBase m_userManager = null;
55 protected Mutex m_loginMutex = new Mutex(false);
56
57 /// <summary>
58 /// Used during login to send the skeleton of the OpenSim Library to the client.
59 /// </summary>
60 protected LibraryRootFolder m_libraryRootFolder;
61
62 protected uint m_defaultHomeX;
63 protected uint m_defaultHomeY;
64
65 protected bool m_warn_already_logged = true;
66
67 /// <summary>
68 /// Used by the login service to make requests to the inventory service.
69 /// </summary>
70 protected IInterServiceInventoryServices m_interInventoryService;
71 // Hack
72 protected IInventoryService m_InventoryService;
73
74 /// <summary>
75 /// Constructor
76 /// </summary>
77 /// <param name="userManager"></param>
78 /// <param name="libraryRootFolder"></param>
79 /// <param name="welcomeMess"></param>
80 public LoginService(UserManagerBase userManager, LibraryRootFolder libraryRootFolder,
81 string welcomeMess)
82 {
83 m_userManager = userManager;
84 m_libraryRootFolder = libraryRootFolder;
85
86 if (welcomeMess != String.Empty)
87 {
88 m_welcomeMessage = welcomeMess;
89 }
90 }
91
92 /// <summary>
93 /// If the user is already logged in, try to notify the region that the user they've got is dead.
94 /// </summary>
95 /// <param name="theUser"></param>
96 public virtual void LogOffUser(UserProfileData theUser, string message)
97 {
98 }
99
100 /// <summary>
101 /// Called when we receive the client's initial XMLRPC login_to_simulator request message
102 /// </summary>
103 /// <param name="request">The XMLRPC request</param>
104 /// <returns>The response to send</returns>
105 public virtual XmlRpcResponse XmlRpcLoginMethod(XmlRpcRequest request, IPEndPoint remoteClient)
106 {
107 // Temporary fix
108 m_loginMutex.WaitOne();
109
110 try
111 {
112 //CFK: CustomizeResponse contains sufficient strings to alleviate the need for this.
113 //CKF: m_log.Info("[LOGIN]: Attempting login now...");
114 XmlRpcResponse response = new XmlRpcResponse();
115 Hashtable requestData = (Hashtable)request.Params[0];
116
117 SniffLoginKey((Uri)request.Params[2], requestData);
118
119 bool GoodXML = (requestData.Contains("first") && requestData.Contains("last") &&
120 (requestData.Contains("passwd") || requestData.Contains("web_login_key")));
121
122 string startLocationRequest = "last";
123
124 UserProfileData userProfile;
125 LoginResponse logResponse = new LoginResponse();
126
127 string firstname;
128 string lastname;
129
130 if (GoodXML)
131 {
132 if (requestData.Contains("start"))
133 {
134 startLocationRequest = (string)requestData["start"];
135 }
136
137 firstname = (string)requestData["first"];
138 lastname = (string)requestData["last"];
139
140 m_log.InfoFormat(
141 "[LOGIN BEGIN]: XMLRPC Received login request message from user '{0}' '{1}'",
142 firstname, lastname);
143
144 string clientVersion = "Unknown";
145
146 if (requestData.Contains("version"))
147 {
148 clientVersion = (string)requestData["version"];
149 }
150
151 m_log.DebugFormat(
152 "[LOGIN]: XMLRPC Client is {0}, start location is {1}", clientVersion, startLocationRequest);
153
154 if (!TryAuthenticateXmlRpcLogin(request, firstname, lastname, out userProfile))
155 {
156 return logResponse.CreateLoginFailedResponse();
157 }
158 }
159 else
160 {
161 m_log.Info(
162 "[LOGIN END]: XMLRPC login_to_simulator login message did not contain all the required data");
163
164 return logResponse.CreateGridErrorResponse();
165 }
166
167 if (userProfile.GodLevel < m_minLoginLevel)
168 {
169 return logResponse.CreateLoginBlockedResponse();
170 }
171 else
172 {
173 // If we already have a session...
174 if (userProfile.CurrentAgent != null && userProfile.CurrentAgent.AgentOnline)
175 {
176 //TODO: The following statements can cause trouble:
177 // If agentOnline could not turn from true back to false normally
178 // because of some problem, for instance, the crashment of server or client,
179 // the user cannot log in any longer.
180 userProfile.CurrentAgent.AgentOnline = false;
181
182 m_userManager.CommitAgent(ref userProfile);
183
184 // try to tell the region that their user is dead.
185 LogOffUser(userProfile, " XMLRPC You were logged off because you logged in from another location");
186
187 if (m_warn_already_logged)
188 {
189 // This is behavior for for grid, reject login
190 m_log.InfoFormat(
191 "[LOGIN END]: XMLRPC Notifying user {0} {1} that they are already logged in",
192 firstname, lastname);
193
194 return logResponse.CreateAlreadyLoggedInResponse();
195 }
196 else
197 {
198 // This is behavior for standalone (silent logout of last hung session)
199 m_log.InfoFormat(
200 "[LOGIN]: XMLRPC User {0} {1} is already logged in, not notifying user, kicking old presence and starting new login.",
201 firstname, lastname);
202 }
203 }
204
205 // Otherwise...
206 // Create a new agent session
207
208 // XXYY we don't need this
209 //m_userManager.ResetAttachments(userProfile.ID);
210
211 CreateAgent(userProfile, request);
212
213 // We need to commit the agent right here, even though the userProfile info is not complete
214 // at this point. There is another commit further down.
215 // This is for the new sessionID to be stored so that the region can check it for session authentication.
216 // CustomiseResponse->PrepareLoginToRegion
217 CommitAgent(ref userProfile);
218
219 try
220 {
221 UUID agentID = userProfile.ID;
222 InventoryData inventData = null;
223
224 try
225 {
226 inventData = GetInventorySkeleton(agentID);
227 }
228 catch (Exception e)
229 {
230 m_log.ErrorFormat(
231 "[LOGIN END]: Error retrieving inventory skeleton of agent {0} - {1}",
232 agentID, e);
233
234 // Let's not panic
235 if (!AllowLoginWithoutInventory())
236 return logResponse.CreateLoginInventoryFailedResponse();
237 }
238
239 if (inventData != null)
240 {
241 ArrayList AgentInventoryArray = inventData.InventoryArray;
242
243 Hashtable InventoryRootHash = new Hashtable();
244 InventoryRootHash["folder_id"] = inventData.RootFolderID.ToString();
245 ArrayList InventoryRoot = new ArrayList();
246 InventoryRoot.Add(InventoryRootHash);
247
248 logResponse.InventoryRoot = InventoryRoot;
249 logResponse.InventorySkeleton = AgentInventoryArray;
250 }
251
252 // Inventory Library Section
253 Hashtable InventoryLibRootHash = new Hashtable();
254 InventoryLibRootHash["folder_id"] = "00000112-000f-0000-0000-000100bba000";
255 ArrayList InventoryLibRoot = new ArrayList();
256 InventoryLibRoot.Add(InventoryLibRootHash);
257
258 logResponse.InventoryLibRoot = InventoryLibRoot;
259 logResponse.InventoryLibraryOwner = GetLibraryOwner();
260 logResponse.InventoryLibrary = GetInventoryLibrary();
261
262 logResponse.CircuitCode = Util.RandomClass.Next();
263 logResponse.Lastname = userProfile.SurName;
264 logResponse.Firstname = userProfile.FirstName;
265 logResponse.AgentID = agentID;
266 logResponse.SessionID = userProfile.CurrentAgent.SessionID;
267 logResponse.SecureSessionID = userProfile.CurrentAgent.SecureSessionID;
268 logResponse.Message = GetMessage();
269 logResponse.BuddList = ConvertFriendListItem(m_userManager.GetUserFriendList(agentID));
270 logResponse.StartLocation = startLocationRequest;
271
272 if (CustomiseResponse(logResponse, userProfile, startLocationRequest, remoteClient))
273 {
274 userProfile.LastLogin = userProfile.CurrentAgent.LoginTime;
275 CommitAgent(ref userProfile);
276
277 // If we reach this point, then the login has successfully logged onto the grid
278 if (StatsManager.UserStats != null)
279 StatsManager.UserStats.AddSuccessfulLogin();
280
281 m_log.DebugFormat(
282 "[LOGIN END]: XMLRPC Authentication of user {0} {1} successful. Sending response to client.",
283 firstname, lastname);
284
285 return logResponse.ToXmlRpcResponse();
286 }
287 else
288 {
289 m_log.ErrorFormat("[LOGIN END]: XMLRPC informing user {0} {1} that login failed due to an unavailable region", firstname, lastname);
290 return logResponse.CreateDeadRegionResponse();
291 }
292 }
293 catch (Exception e)
294 {
295 m_log.Error("[LOGIN END]: XMLRPC Login failed, " + e);
296 m_log.Error(e.StackTrace);
297 }
298 }
299
300 m_log.Info("[LOGIN END]: XMLRPC Login failed. Sending back blank XMLRPC response");
301 return response;
302 }
303 finally
304 {
305 m_loginMutex.ReleaseMutex();
306 }
307 }
308
309 protected virtual bool TryAuthenticateXmlRpcLogin(
310 XmlRpcRequest request, string firstname, string lastname, out UserProfileData userProfile)
311 {
312 Hashtable requestData = (Hashtable)request.Params[0];
313
314 userProfile = GetTheUser(firstname, lastname);
315 if (userProfile == null)
316 {
317 m_log.Debug("[LOGIN END]: XMLRPC Could not find a profile for " + firstname + " " + lastname);
318 return false;
319 }
320 else
321 {
322 if (requestData.Contains("passwd"))
323 {
324 string passwd = (string)requestData["passwd"];
325 bool authenticated = AuthenticateUser(userProfile, passwd);
326
327 if (!authenticated)
328 m_log.DebugFormat("[LOGIN END]: XMLRPC User {0} {1} failed password authentication",
329 firstname, lastname);
330
331 return authenticated;
332 }
333
334 if (requestData.Contains("web_login_key"))
335 {
336 try
337 {
338 UUID webloginkey = new UUID((string)requestData["web_login_key"]);
339 bool authenticated = AuthenticateUser(userProfile, webloginkey);
340
341 if (!authenticated)
342 m_log.DebugFormat("[LOGIN END]: XMLRPC User {0} {1} failed web login key authentication",
343 firstname, lastname);
344
345 return authenticated;
346 }
347 catch (Exception e)
348 {
349 m_log.DebugFormat(
350 "[LOGIN END]: XMLRPC Bad web_login_key: {0} for user {1} {2}, exception {3}",
351 requestData["web_login_key"], firstname, lastname, e);
352
353 return false;
354 }
355 }
356
357 m_log.DebugFormat(
358 "[LOGIN END]: XMLRPC login request for {0} {1} contained neither a password nor a web login key",
359 firstname, lastname);
360 }
361
362 return false;
363 }
364
365 protected virtual bool TryAuthenticateLLSDLogin(string firstname, string lastname, string passwd, out UserProfileData userProfile)
366 {
367 bool GoodLogin = false;
368 userProfile = GetTheUser(firstname, lastname);
369 if (userProfile == null)
370 {
371 m_log.Info("[LOGIN]: LLSD Could not find a profile for " + firstname + " " + lastname);
372
373 return false;
374 }
375
376 GoodLogin = AuthenticateUser(userProfile, passwd);
377 return GoodLogin;
378 }
379
380 /// <summary>
381 /// Called when we receive the client's initial LLSD login_to_simulator request message
382 /// </summary>
383 /// <param name="request">The LLSD request</param>
384 /// <returns>The response to send</returns>
385 public OSD LLSDLoginMethod(OSD request, IPEndPoint remoteClient)
386 {
387 // Temporary fix
388 m_loginMutex.WaitOne();
389
390 try
391 {
392 // bool GoodLogin = false;
393
394 string startLocationRequest = "last";
395
396 UserProfileData userProfile = null;
397 LoginResponse logResponse = new LoginResponse();
398
399 if (request.Type == OSDType.Map)
400 {
401 OSDMap map = (OSDMap)request;
402
403 if (map.ContainsKey("first") && map.ContainsKey("last") && map.ContainsKey("passwd"))
404 {
405 string firstname = map["first"].AsString();
406 string lastname = map["last"].AsString();
407 string passwd = map["passwd"].AsString();
408
409 if (map.ContainsKey("start"))
410 {
411 m_log.Info("[LOGIN]: LLSD StartLocation Requested: " + map["start"].AsString());
412 startLocationRequest = map["start"].AsString();
413 }
414 m_log.Info("[LOGIN]: LLSD Login Requested for: '" + firstname + "' '" + lastname + "' / " + passwd);
415
416 if (!TryAuthenticateLLSDLogin(firstname, lastname, passwd, out userProfile))
417 {
418 return logResponse.CreateLoginFailedResponseLLSD();
419 }
420 }
421 else
422 return logResponse.CreateLoginFailedResponseLLSD();
423 }
424 else
425 return logResponse.CreateLoginFailedResponseLLSD();
426
427
428 if (userProfile.GodLevel < m_minLoginLevel)
429 {
430 return logResponse.CreateLoginBlockedResponseLLSD();
431 }
432 else
433 {
434 // If we already have a session...
435 if (userProfile.CurrentAgent != null && userProfile.CurrentAgent.AgentOnline)
436 {
437 userProfile.CurrentAgent.AgentOnline = false;
438
439 m_userManager.CommitAgent(ref userProfile);
440 // try to tell the region that their user is dead.
441 LogOffUser(userProfile, " LLSD You were logged off because you logged in from another location");
442
443 if (m_warn_already_logged)
444 {
445 // This is behavior for for grid, reject login
446 m_log.InfoFormat(
447 "[LOGIN END]: LLSD Notifying user {0} {1} that they are already logged in",
448 userProfile.FirstName, userProfile.SurName);
449
450 userProfile.CurrentAgent = null;
451 return logResponse.CreateAlreadyLoggedInResponseLLSD();
452 }
453 else
454 {
455 // This is behavior for standalone (silent logout of last hung session)
456 m_log.InfoFormat(
457 "[LOGIN]: LLSD User {0} {1} is already logged in, not notifying user, kicking old presence and starting new login.",
458 userProfile.FirstName, userProfile.SurName);
459 }
460 }
461
462 // Otherwise...
463 // Create a new agent session
464
465 // XXYY We don't need this
466 //m_userManager.ResetAttachments(userProfile.ID);
467
468 CreateAgent(userProfile, request);
469
470 // We need to commit the agent right here, even though the userProfile info is not complete
471 // at this point. There is another commit further down.
472 // This is for the new sessionID to be stored so that the region can check it for session authentication.
473 // CustomiseResponse->PrepareLoginToRegion
474 CommitAgent(ref userProfile);
475
476 try
477 {
478 UUID agentID = userProfile.ID;
479
480 //InventoryData inventData = GetInventorySkeleton(agentID);
481 InventoryData inventData = null;
482
483 try
484 {
485 inventData = GetInventorySkeleton(agentID);
486 }
487 catch (Exception e)
488 {
489 m_log.ErrorFormat(
490 "[LOGIN END]: LLSD Error retrieving inventory skeleton of agent {0}, {1} - {2}",
491 agentID, e.GetType(), e.Message);
492
493 return logResponse.CreateLoginFailedResponseLLSD();// .CreateLoginInventoryFailedResponseLLSD ();
494 }
495
496
497 ArrayList AgentInventoryArray = inventData.InventoryArray;
498
499 Hashtable InventoryRootHash = new Hashtable();
500 InventoryRootHash["folder_id"] = inventData.RootFolderID.ToString();
501 ArrayList InventoryRoot = new ArrayList();
502 InventoryRoot.Add(InventoryRootHash);
503
504
505 // Inventory Library Section
506 Hashtable InventoryLibRootHash = new Hashtable();
507 InventoryLibRootHash["folder_id"] = "00000112-000f-0000-0000-000100bba000";
508 ArrayList InventoryLibRoot = new ArrayList();
509 InventoryLibRoot.Add(InventoryLibRootHash);
510
511 logResponse.InventoryLibRoot = InventoryLibRoot;
512 logResponse.InventoryLibraryOwner = GetLibraryOwner();
513 logResponse.InventoryRoot = InventoryRoot;
514 logResponse.InventorySkeleton = AgentInventoryArray;
515 logResponse.InventoryLibrary = GetInventoryLibrary();
516
517 logResponse.CircuitCode = (Int32)Util.RandomClass.Next();
518 logResponse.Lastname = userProfile.SurName;
519 logResponse.Firstname = userProfile.FirstName;
520 logResponse.AgentID = agentID;
521 logResponse.SessionID = userProfile.CurrentAgent.SessionID;
522 logResponse.SecureSessionID = userProfile.CurrentAgent.SecureSessionID;
523 logResponse.Message = GetMessage();
524 logResponse.BuddList = ConvertFriendListItem(m_userManager.GetUserFriendList(agentID));
525 logResponse.StartLocation = startLocationRequest;
526
527 try
528 {
529 CustomiseResponse(logResponse, userProfile, startLocationRequest, remoteClient);
530 }
531 catch (Exception ex)
532 {
533 m_log.Info("[LOGIN]: LLSD " + ex.ToString());
534 return logResponse.CreateDeadRegionResponseLLSD();
535 }
536
537 userProfile.LastLogin = userProfile.CurrentAgent.LoginTime;
538 CommitAgent(ref userProfile);
539
540 // If we reach this point, then the login has successfully logged onto the grid
541 if (StatsManager.UserStats != null)
542 StatsManager.UserStats.AddSuccessfulLogin();
543
544 m_log.DebugFormat(
545 "[LOGIN END]: LLSD Authentication of user {0} {1} successful. Sending response to client.",
546 userProfile.FirstName, userProfile.SurName);
547
548 return logResponse.ToLLSDResponse();
549 }
550 catch (Exception ex)
551 {
552 m_log.Info("[LOGIN]: LLSD " + ex.ToString());
553 return logResponse.CreateFailedResponseLLSD();
554 }
555 }
556 }
557 finally
558 {
559 m_loginMutex.ReleaseMutex();
560 }
561 }
562
563 public Hashtable ProcessHTMLLogin(Hashtable keysvals)
564 {
565 // Matches all unspecified characters
566 // Currently specified,; lowercase letters, upper case letters, numbers, underline
567 // period, space, parens, and dash.
568
569 Regex wfcut = new Regex("[^a-zA-Z0-9_\\.\\$ \\(\\)\\-]");
570
571 Hashtable returnactions = new Hashtable();
572 int statuscode = 200;
573
574 string firstname = String.Empty;
575 string lastname = String.Empty;
576 string location = String.Empty;
577 string region = String.Empty;
578 string grid = String.Empty;
579 string channel = String.Empty;
580 string version = String.Empty;
581 string lang = String.Empty;
582 string password = String.Empty;
583 string errormessages = String.Empty;
584
585 // the client requires the HTML form field be named 'username'
586 // however, the data it sends when it loads the first time is 'firstname'
587 // another one of those little nuances.
588
589 if (keysvals.Contains("firstname"))
590 firstname = wfcut.Replace((string)keysvals["firstname"], String.Empty, 99999);
591
592 if (keysvals.Contains("username"))
593 firstname = wfcut.Replace((string)keysvals["username"], String.Empty, 99999);
594
595 if (keysvals.Contains("lastname"))
596 lastname = wfcut.Replace((string)keysvals["lastname"], String.Empty, 99999);
597
598 if (keysvals.Contains("location"))
599 location = wfcut.Replace((string)keysvals["location"], String.Empty, 99999);
600
601 if (keysvals.Contains("region"))
602 region = wfcut.Replace((string)keysvals["region"], String.Empty, 99999);
603
604 if (keysvals.Contains("grid"))
605 grid = wfcut.Replace((string)keysvals["grid"], String.Empty, 99999);
606
607 if (keysvals.Contains("channel"))
608 channel = wfcut.Replace((string)keysvals["channel"], String.Empty, 99999);
609
610 if (keysvals.Contains("version"))
611 version = wfcut.Replace((string)keysvals["version"], String.Empty, 99999);
612
613 if (keysvals.Contains("lang"))
614 lang = wfcut.Replace((string)keysvals["lang"], String.Empty, 99999);
615
616 if (keysvals.Contains("password"))
617 password = wfcut.Replace((string)keysvals["password"], String.Empty, 99999);
618
619 // load our login form.
620 string loginform = GetLoginForm(firstname, lastname, location, region, grid, channel, version, lang, password, errormessages);
621
622 if (keysvals.ContainsKey("show_login_form"))
623 {
624 UserProfileData user = GetTheUser(firstname, lastname);
625 bool goodweblogin = false;
626
627 if (user != null)
628 goodweblogin = AuthenticateUser(user, password);
629
630 if (goodweblogin)
631 {
632 UUID webloginkey = UUID.Random();
633 m_userManager.StoreWebLoginKey(user.ID, webloginkey);
634 //statuscode = 301;
635
636 // string redirectURL = "about:blank?redirect-http-hack=" +
637 // HttpUtility.UrlEncode("secondlife:///app/login?first_name=" + firstname + "&last_name=" +
638 // lastname +
639 // "&location=" + location + "&grid=Other&web_login_key=" + webloginkey.ToString());
640 //m_log.Info("[WEB]: R:" + redirectURL);
641 returnactions["int_response_code"] = statuscode;
642 //returnactions["str_redirect_location"] = redirectURL;
643 //returnactions["str_response_string"] = "<HTML><BODY>GoodLogin</BODY></HTML>";
644 returnactions["str_response_string"] = webloginkey.ToString();
645 }
646 else
647 {
648 errormessages = "The Username and password supplied did not match our records. Check your caps lock and try again";
649
650 loginform = GetLoginForm(firstname, lastname, location, region, grid, channel, version, lang, password, errormessages);
651 returnactions["int_response_code"] = statuscode;
652 returnactions["str_response_string"] = loginform;
653 }
654 }
655 else
656 {
657 returnactions["int_response_code"] = statuscode;
658 returnactions["str_response_string"] = loginform;
659 }
660 return returnactions;
661 }
662
663 public string GetLoginForm(string firstname, string lastname, string location, string region,
664 string grid, string channel, string version, string lang,
665 string password, string errormessages)
666 {
667 // inject our values in the form at the markers
668
669 string loginform = String.Empty;
670 string file = Path.Combine(Util.configDir(), "http_loginform.html");
671 if (!File.Exists(file))
672 {
673 loginform = GetDefaultLoginForm();
674 }
675 else
676 {
677 StreamReader sr = File.OpenText(file);
678 loginform = sr.ReadToEnd();
679 sr.Close();
680 }
681
682 loginform = loginform.Replace("[$firstname]", firstname);
683 loginform = loginform.Replace("[$lastname]", lastname);
684 loginform = loginform.Replace("[$location]", location);
685 loginform = loginform.Replace("[$region]", region);
686 loginform = loginform.Replace("[$grid]", grid);
687 loginform = loginform.Replace("[$channel]", channel);
688 loginform = loginform.Replace("[$version]", version);
689 loginform = loginform.Replace("[$lang]", lang);
690 loginform = loginform.Replace("[$password]", password);
691 loginform = loginform.Replace("[$errors]", errormessages);
692
693 return loginform;
694 }
695
696 public string GetDefaultLoginForm()
697 {
698 string responseString =
699 "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">";
700 responseString += "<html xmlns=\"http://www.w3.org/1999/xhtml\">";
701 responseString += "<head>";
702 responseString += "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />";
703 responseString += "<meta http-equiv=\"cache-control\" content=\"no-cache\">";
704 responseString += "<meta http-equiv=\"Pragma\" content=\"no-cache\">";
705 responseString += "<title>OpenSim Login</title>";
706 responseString += "<body><br />";
707 responseString += "<div id=\"login_box\">";
708
709 responseString += "<form action=\"/go.cgi\" method=\"GET\" id=\"login-form\">";
710
711 responseString += "<div id=\"message\">[$errors]</div>";
712 responseString += "<fieldset id=\"firstname\">";
713 responseString += "<legend>First Name:</legend>";
714 responseString += "<input type=\"text\" id=\"firstname_input\" size=\"15\" maxlength=\"100\" name=\"username\" value=\"[$firstname]\" />";
715 responseString += "</fieldset>";
716 responseString += "<fieldset id=\"lastname\">";
717 responseString += "<legend>Last Name:</legend>";
718 responseString += "<input type=\"text\" size=\"15\" maxlength=\"100\" name=\"lastname\" value=\"[$lastname]\" />";
719 responseString += "</fieldset>";
720 responseString += "<fieldset id=\"password\">";
721 responseString += "<legend>Password:</legend>";
722 responseString += "<table cellspacing=\"0\" cellpadding=\"0\" border=\"0\">";
723 responseString += "<tr>";
724 responseString += "<td colspan=\"2\"><input type=\"password\" size=\"15\" maxlength=\"100\" name=\"password\" value=\"[$password]\" /></td>";
725 responseString += "</tr>";
726 responseString += "<tr>";
727 responseString += "<td valign=\"middle\"><input type=\"checkbox\" name=\"remember_password\" id=\"remember_password\" [$remember_password] style=\"margin-left:0px;\"/></td>";
728 responseString += "<td><label for=\"remember_password\">Remember password</label></td>";
729 responseString += "</tr>";
730 responseString += "</table>";
731 responseString += "</fieldset>";
732 responseString += "<input type=\"hidden\" name=\"show_login_form\" value=\"FALSE\" />";
733 responseString += "<input type=\"hidden\" name=\"method\" value=\"login\" />";
734 responseString += "<input type=\"hidden\" id=\"grid\" name=\"grid\" value=\"[$grid]\" />";
735 responseString += "<input type=\"hidden\" id=\"region\" name=\"region\" value=\"[$region]\" />";
736 responseString += "<input type=\"hidden\" id=\"location\" name=\"location\" value=\"[$location]\" />";
737 responseString += "<input type=\"hidden\" id=\"channel\" name=\"channel\" value=\"[$channel]\" />";
738 responseString += "<input type=\"hidden\" id=\"version\" name=\"version\" value=\"[$version]\" />";
739 responseString += "<input type=\"hidden\" id=\"lang\" name=\"lang\" value=\"[$lang]\" />";
740 responseString += "<div id=\"submitbtn\">";
741 responseString += "<input class=\"input_over\" type=\"submit\" value=\"Connect\" />";
742 responseString += "</div>";
743 responseString += "<div id=\"connecting\" style=\"visibility:hidden\"> Connecting...</div>";
744
745 responseString += "<div id=\"helplinks\"><!---";
746 responseString += "<a href=\"#join now link\" target=\"_blank\"></a> | ";
747 responseString += "<a href=\"#forgot password link\" target=\"_blank\"></a>";
748 responseString += "---></div>";
749
750 responseString += "<div id=\"channelinfo\"> [$channel] | [$version]=[$lang]</div>";
751 responseString += "</form>";
752 responseString += "<script language=\"JavaScript\">";
753 responseString += "document.getElementById('firstname_input').focus();";
754 responseString += "</script>";
755 responseString += "</div>";
756 responseString += "</div>";
757 responseString += "</body>";
758 responseString += "</html>";
759
760 return responseString;
761 }
762
763 /// <summary>
764 /// Saves a target agent to the database
765 /// </summary>
766 /// <param name="profile">The users profile</param>
767 /// <returns>Successful?</returns>
768 public bool CommitAgent(ref UserProfileData profile)
769 {
770 return m_userManager.CommitAgent(ref profile);
771 }
772
773 /// <summary>
774 /// Checks a user against it's password hash
775 /// </summary>
776 /// <param name="profile">The users profile</param>
777 /// <param name="password">The supplied password</param>
778 /// <returns>Authenticated?</returns>
779 public virtual bool AuthenticateUser(UserProfileData profile, string password)
780 {
781 bool passwordSuccess = false;
782 //m_log.InfoFormat("[LOGIN]: Authenticating {0} {1} ({2})", profile.FirstName, profile.SurName, profile.ID);
783
784 // Web Login method seems to also occasionally send the hashed password itself
785
786 // we do this to get our hash in a form that the server password code can consume
787 // when the web-login-form submits the password in the clear (supposed to be over SSL!)
788 if (!password.StartsWith("$1$"))
789 password = "$1$" + Util.Md5Hash(password);
790
791 password = password.Remove(0, 3); //remove $1$
792
793 string s = Util.Md5Hash(password + ":" + profile.PasswordSalt);
794 // Testing...
795 //m_log.Info("[LOGIN]: SubHash:" + s + " userprofile:" + profile.passwordHash);
796 //m_log.Info("[LOGIN]: userprofile:" + profile.passwordHash + " SubCT:" + password);
797
798 passwordSuccess = (profile.PasswordHash.Equals(s.ToString(), StringComparison.InvariantCultureIgnoreCase)
799 || profile.PasswordHash.Equals(password, StringComparison.InvariantCulture));
800
801 return passwordSuccess;
802 }
803
804 public virtual bool AuthenticateUser(UserProfileData profile, UUID webloginkey)
805 {
806 bool passwordSuccess = false;
807 m_log.InfoFormat("[LOGIN]: Authenticating {0} {1} ({2})", profile.FirstName, profile.SurName, profile.ID);
808
809 // Match web login key unless it's the default weblogin key UUID.Zero
810 passwordSuccess = ((profile.WebLoginKey == webloginkey) && profile.WebLoginKey != UUID.Zero);
811
812 return passwordSuccess;
813 }
814
815 /// <summary>
816 ///
817 /// </summary>
818 /// <param name="profile"></param>
819 /// <param name="request"></param>
820 public void CreateAgent(UserProfileData profile, XmlRpcRequest request)
821 {
822 m_userManager.CreateAgent(profile, request);
823 }
824
825 public void CreateAgent(UserProfileData profile, OSD request)
826 {
827 m_userManager.CreateAgent(profile, request);
828 }
829
830 /// <summary>
831 ///
832 /// </summary>
833 /// <param name="firstname"></param>
834 /// <param name="lastname"></param>
835 /// <returns></returns>
836 public virtual UserProfileData GetTheUser(string firstname, string lastname)
837 {
838 return m_userManager.GetUserProfile(firstname, lastname);
839 }
840
841 /// <summary>
842 ///
843 /// </summary>
844 /// <returns></returns>
845 public virtual string GetMessage()
846 {
847 return m_welcomeMessage;
848 }
849
850 private static LoginResponse.BuddyList ConvertFriendListItem(List<FriendListItem> LFL)
851 {
852 LoginResponse.BuddyList buddylistreturn = new LoginResponse.BuddyList();
853 foreach (FriendListItem fl in LFL)
854 {
855 LoginResponse.BuddyList.BuddyInfo buddyitem = new LoginResponse.BuddyList.BuddyInfo(fl.Friend);
856 buddyitem.BuddyID = fl.Friend;
857 buddyitem.BuddyRightsHave = (int)fl.FriendListOwnerPerms;
858 buddyitem.BuddyRightsGiven = (int)fl.FriendPerms;
859 buddylistreturn.AddNewBuddy(buddyitem);
860 }
861 return buddylistreturn;
862 }
863
864 /// <summary>
865 /// Converts the inventory library skeleton into the form required by the rpc request.
866 /// </summary>
867 /// <returns></returns>
868 protected virtual ArrayList GetInventoryLibrary()
869 {
870 Dictionary<UUID, InventoryFolderImpl> rootFolders
871 = m_libraryRootFolder.RequestSelfAndDescendentFolders();
872 ArrayList folderHashes = new ArrayList();
873
874 foreach (InventoryFolderBase folder in rootFolders.Values)
875 {
876 Hashtable TempHash = new Hashtable();
877 TempHash["name"] = folder.Name;
878 TempHash["parent_id"] = folder.ParentID.ToString();
879 TempHash["version"] = (Int32)folder.Version;
880 TempHash["type_default"] = (Int32)folder.Type;
881 TempHash["folder_id"] = folder.ID.ToString();
882 folderHashes.Add(TempHash);
883 }
884
885 return folderHashes;
886 }
887
888 /// <summary>
889 ///
890 /// </summary>
891 /// <returns></returns>
892 protected virtual ArrayList GetLibraryOwner()
893 {
894 //for now create random inventory library owner
895 Hashtable TempHash = new Hashtable();
896 TempHash["agent_id"] = "11111111-1111-0000-0000-000100bba000";
897 ArrayList inventoryLibOwner = new ArrayList();
898 inventoryLibOwner.Add(TempHash);
899 return inventoryLibOwner;
900 }
901
902 public class InventoryData
903 {
904 public ArrayList InventoryArray = null;
905 public UUID RootFolderID = UUID.Zero;
906
907 public InventoryData(ArrayList invList, UUID rootID)
908 {
909 InventoryArray = invList;
910 RootFolderID = rootID;
911 }
912 }
913
914 protected void SniffLoginKey(Uri uri, Hashtable requestData)
915 {
916 string uri_str = uri.ToString();
917 string[] parts = uri_str.Split(new char[] { '=' });
918 if (parts.Length > 1)
919 {
920 string web_login_key = parts[1];
921 requestData.Add("web_login_key", web_login_key);
922 m_log.InfoFormat("[LOGIN]: Login with web_login_key {0}", web_login_key);
923 }
924 }
925
926 /// <summary>
927 /// Customises the login response and fills in missing values. This method also tells the login region to
928 /// expect a client connection.
929 /// </summary>
930 /// <param name="response">The existing response</param>
931 /// <param name="theUser">The user profile</param>
932 /// <param name="startLocationRequest">The requested start location</param>
933 /// <returns>true on success, false if the region was not successfully told to expect a user connection</returns>
934 public bool CustomiseResponse(LoginResponse response, UserProfileData theUser, string startLocationRequest, IPEndPoint client)
935 {
936 // add active gestures to login-response
937 AddActiveGestures(response, theUser);
938
939 // HomeLocation
940 RegionInfo homeInfo = null;
941
942 // use the homeRegionID if it is stored already. If not, use the regionHandle as before
943 UUID homeRegionId = theUser.HomeRegionID;
944 ulong homeRegionHandle = theUser.HomeRegion;
945 if (homeRegionId != UUID.Zero)
946 {
947 homeInfo = GetRegionInfo(homeRegionId);
948 }
949 else
950 {
951 homeInfo = GetRegionInfo(homeRegionHandle);
952 }
953
954 if (homeInfo != null)
955 {
956 response.Home =
957 string.Format(
958 "{{'region_handle':[r{0},r{1}], 'position':[r{2},r{3},r{4}], 'look_at':[r{5},r{6},r{7}]}}",
959 (homeInfo.RegionLocX * Constants.RegionSize),
960 (homeInfo.RegionLocY * Constants.RegionSize),
961 theUser.HomeLocation.X, theUser.HomeLocation.Y, theUser.HomeLocation.Z,
962 theUser.HomeLookAt.X, theUser.HomeLookAt.Y, theUser.HomeLookAt.Z);
963 }
964 else
965 {
966 m_log.InfoFormat("not found the region at {0} {1}", theUser.HomeRegionX, theUser.HomeRegionY);
967 // Emergency mode: Home-region isn't available, so we can't request the region info.
968 // Use the stored home regionHandle instead.
969 // NOTE: If the home-region moves, this will be wrong until the users update their user-profile again
970 ulong regionX = homeRegionHandle >> 32;
971 ulong regionY = homeRegionHandle & 0xffffffff;
972 response.Home =
973 string.Format(
974 "{{'region_handle':[r{0},r{1}], 'position':[r{2},r{3},r{4}], 'look_at':[r{5},r{6},r{7}]}}",
975 regionX, regionY,
976 theUser.HomeLocation.X, theUser.HomeLocation.Y, theUser.HomeLocation.Z,
977 theUser.HomeLookAt.X, theUser.HomeLookAt.Y, theUser.HomeLookAt.Z);
978
979 m_log.InfoFormat("[LOGIN] Home region of user {0} {1} is not available; using computed region position {2} {3}",
980 theUser.FirstName, theUser.SurName,
981 regionX, regionY);
982 }
983
984 // StartLocation
985 RegionInfo regionInfo = null;
986 if (startLocationRequest == "home")
987 {
988 regionInfo = homeInfo;
989 theUser.CurrentAgent.Position = theUser.HomeLocation;
990 response.LookAt = String.Format("[r{0},r{1},r{2}]", theUser.HomeLookAt.X.ToString(),
991 theUser.HomeLookAt.Y.ToString(), theUser.HomeLookAt.Z.ToString());
992 }
993 else if (startLocationRequest == "last")
994 {
995 UUID lastRegion = theUser.CurrentAgent.Region;
996 regionInfo = GetRegionInfo(lastRegion);
997 response.LookAt = String.Format("[r{0},r{1},r{2}]", theUser.CurrentAgent.LookAt.X.ToString(),
998 theUser.CurrentAgent.LookAt.Y.ToString(), theUser.CurrentAgent.LookAt.Z.ToString());
999 }
1000 else
1001 {
1002 Regex reURI = new Regex(@"^uri:(?<region>[^&]+)&(?<x>\d+)&(?<y>\d+)&(?<z>\d+)$");
1003 Match uriMatch = reURI.Match(startLocationRequest);
1004 if (uriMatch == null)
1005 {
1006 m_log.InfoFormat("[LOGIN]: Got Custom Login URL {0}, but can't process it", startLocationRequest);
1007 }
1008 else
1009 {
1010 string region = uriMatch.Groups["region"].ToString();
1011 regionInfo = RequestClosestRegion(region);
1012 if (regionInfo == null)
1013 {
1014 m_log.InfoFormat("[LOGIN]: Got Custom Login URL {0}, can't locate region {1}", startLocationRequest, region);
1015 }
1016 else
1017 {
1018 theUser.CurrentAgent.Position = new Vector3(float.Parse(uriMatch.Groups["x"].Value),
1019 float.Parse(uriMatch.Groups["y"].Value), float.Parse(uriMatch.Groups["z"].Value));
1020 }
1021 }
1022 response.LookAt = "[r0,r1,r0]";
1023 // can be: last, home, safe, url
1024 response.StartLocation = "url";
1025 }
1026
1027 if ((regionInfo != null) && (PrepareLoginToRegion(regionInfo, theUser, response, client)))
1028 {
1029 return true;
1030 }
1031
1032 // Get the default region handle
1033 ulong defaultHandle = Utils.UIntsToLong(m_defaultHomeX * Constants.RegionSize, m_defaultHomeY * Constants.RegionSize);
1034
1035 // If we haven't already tried the default region, reset regionInfo
1036 if (regionInfo != null && defaultHandle != regionInfo.RegionHandle)
1037 regionInfo = null;
1038
1039 if (regionInfo == null)
1040 {
1041 m_log.Error("[LOGIN]: Sending user to default region " + defaultHandle + " instead");
1042 regionInfo = GetRegionInfo(defaultHandle);
1043 }
1044
1045 if (regionInfo == null)
1046 {
1047 m_log.ErrorFormat("[LOGIN]: Sending user to any region");
1048 regionInfo = RequestClosestRegion(String.Empty);
1049 }
1050
1051 theUser.CurrentAgent.Position = new Vector3(128f, 128f, 0f);
1052 response.StartLocation = "safe";
1053
1054 return PrepareLoginToRegion(regionInfo, theUser, response, client);
1055 }
1056
1057 protected abstract RegionInfo RequestClosestRegion(string region);
1058 protected abstract RegionInfo GetRegionInfo(ulong homeRegionHandle);
1059 protected abstract RegionInfo GetRegionInfo(UUID homeRegionId);
1060
1061 /// <summary>
1062 /// Prepare a login to the given region. This involves both telling the region to expect a connection
1063 /// and appropriately customising the response to the user.
1064 /// </summary>
1065 /// <param name="sim"></param>
1066 /// <param name="user"></param>
1067 /// <param name="response"></param>
1068 /// <param name="remoteClient"></param>
1069 /// <returns>true if the region was successfully contacted, false otherwise</returns>
1070 protected abstract bool PrepareLoginToRegion(
1071 RegionInfo regionInfo, UserProfileData user, LoginResponse response, IPEndPoint client);
1072
1073 /// <summary>
1074 /// Add active gestures of the user to the login response.
1075 /// </summary>
1076 /// <param name="response">
1077 /// A <see cref="LoginResponse"/>
1078 /// </param>
1079 /// <param name="theUser">
1080 /// A <see cref="UserProfileData"/>
1081 /// </param>
1082 protected void AddActiveGestures(LoginResponse response, UserProfileData theUser)
1083 {
1084 List<InventoryItemBase> gestures = null;
1085 try
1086 {
1087 if (m_InventoryService != null)
1088 gestures = m_InventoryService.GetActiveGestures(theUser.ID);
1089 else
1090 gestures = m_interInventoryService.GetActiveGestures(theUser.ID);
1091 }
1092 catch (Exception e)
1093 {
1094 m_log.Debug("[LOGIN]: Unable to retrieve active gestures from inventory server. Reason: " + e.Message);
1095 }
1096 //m_log.DebugFormat("[LOGIN]: AddActiveGestures, found {0}", gestures == null ? 0 : gestures.Count);
1097 ArrayList list = new ArrayList();
1098 if (gestures != null)
1099 {
1100 foreach (InventoryItemBase gesture in gestures)
1101 {
1102 Hashtable item = new Hashtable();
1103 item["item_id"] = gesture.ID.ToString();
1104 item["asset_id"] = gesture.AssetID.ToString();
1105 list.Add(item);
1106 }
1107 }
1108 response.ActiveGestures = list;
1109 }
1110
1111 /// <summary>
1112 /// Get the initial login inventory skeleton (in other words, the folder structure) for the given user.
1113 /// </summary>
1114 /// <param name="userID"></param>
1115 /// <returns></returns>
1116 /// <exception cref='System.Exception'>This will be thrown if there is a problem with the inventory service</exception>
1117 protected InventoryData GetInventorySkeleton(UUID userID)
1118 {
1119 List<InventoryFolderBase> folders = null;
1120 if (m_InventoryService != null)
1121 {
1122 folders = m_InventoryService.GetInventorySkeleton(userID);
1123 }
1124 else
1125 {
1126 folders = m_interInventoryService.GetInventorySkeleton(userID);
1127 }
1128
1129 // If we have user auth but no inventory folders for some reason, create a new set of folders.
1130 if (folders == null || folders.Count == 0)
1131 {
1132 m_log.InfoFormat(
1133 "[LOGIN]: A root inventory folder for user {0} was not found. Requesting creation.", userID);
1134
1135 // Although the create user function creates a new agent inventory along with a new user profile, some
1136 // tools are creating the user profile directly in the database without creating the inventory. At
1137 // this time we'll accomodate them by lazily creating the user inventory now if it doesn't already
1138 // exist.
1139 if (m_interInventoryService != null)
1140 {
1141 if (!m_interInventoryService.CreateNewUserInventory(userID))
1142 {
1143 throw new Exception(
1144 String.Format(
1145 "The inventory creation request for user {0} did not succeed."
1146 + " Please contact your inventory service provider for more information.",
1147 userID));
1148 }
1149 }
1150 else if ((m_InventoryService != null) && !m_InventoryService.CreateUserInventory(userID))
1151 {
1152 throw new Exception(
1153 String.Format(
1154 "The inventory creation request for user {0} did not succeed."
1155 + " Please contact your inventory service provider for more information.",
1156 userID));
1157 }
1158
1159
1160 m_log.InfoFormat("[LOGIN]: A new inventory skeleton was successfully created for user {0}", userID);
1161
1162 if (m_InventoryService != null)
1163 folders = m_InventoryService.GetInventorySkeleton(userID);
1164 else
1165 folders = m_interInventoryService.GetInventorySkeleton(userID);
1166
1167 if (folders == null || folders.Count == 0)
1168 {
1169 throw new Exception(
1170 String.Format(
1171 "A root inventory folder for user {0} could not be retrieved from the inventory service",
1172 userID));
1173 }
1174 }
1175
1176 UUID rootID = UUID.Zero;
1177 ArrayList AgentInventoryArray = new ArrayList();
1178 Hashtable TempHash;
1179 foreach (InventoryFolderBase InvFolder in folders)
1180 {
1181 if (InvFolder.ParentID == UUID.Zero)
1182 {
1183 rootID = InvFolder.ID;
1184 }
1185 TempHash = new Hashtable();
1186 TempHash["name"] = InvFolder.Name;
1187 TempHash["parent_id"] = InvFolder.ParentID.ToString();
1188 TempHash["version"] = (Int32)InvFolder.Version;
1189 TempHash["type_default"] = (Int32)InvFolder.Type;
1190 TempHash["folder_id"] = InvFolder.ID.ToString();
1191 AgentInventoryArray.Add(TempHash);
1192 }
1193
1194 return new InventoryData(AgentInventoryArray, rootID);
1195 }
1196
1197 protected virtual bool AllowLoginWithoutInventory()
1198 {
1199 return false;
1200 }
1201
1202 public XmlRpcResponse XmlRPCCheckAuthSession(XmlRpcRequest request, IPEndPoint remoteClient)
1203 {
1204 XmlRpcResponse response = new XmlRpcResponse();
1205 Hashtable requestData = (Hashtable)request.Params[0];
1206
1207 string authed = "FALSE";
1208 if (requestData.Contains("avatar_uuid") && requestData.Contains("session_id"))
1209 {
1210 UUID guess_aid;
1211 UUID guess_sid;
1212
1213 UUID.TryParse((string)requestData["avatar_uuid"], out guess_aid);
1214 if (guess_aid == UUID.Zero)
1215 {
1216 return Util.CreateUnknownUserErrorResponse();
1217 }
1218
1219 UUID.TryParse((string)requestData["session_id"], out guess_sid);
1220 if (guess_sid == UUID.Zero)
1221 {
1222 return Util.CreateUnknownUserErrorResponse();
1223 }
1224
1225 if (m_userManager.VerifySession(guess_aid, guess_sid))
1226 {
1227 authed = "TRUE";
1228 m_log.InfoFormat("[UserManager]: CheckAuthSession TRUE for user {0}", guess_aid);
1229 }
1230 else
1231 {
1232 m_log.InfoFormat("[UserManager]: CheckAuthSession FALSE");
1233 return Util.CreateUnknownUserErrorResponse();
1234 }
1235 }
1236
1237 Hashtable responseData = new Hashtable();
1238 responseData["auth_session"] = authed;
1239 response.Value = responseData;
1240 return response;
1241 }
1242 }
1243} \ No newline at end of file