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