aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--OpenSim/Framework/Communications/LoginService.cs148
-rw-r--r--OpenSim/Framework/Servers/BaseHttpServer.cs7
-rw-r--r--OpenSim/Grid/UserServer/Main.cs2
-rw-r--r--OpenSim/Region/Application/OpenSimMain.cs6
-rw-r--r--OpenSim/Region/Communications/Local/LocalLoginService.cs7
-rw-r--r--bin/http_loginform.html.example60
6 files changed, 210 insertions, 20 deletions
diff --git a/OpenSim/Framework/Communications/LoginService.cs b/OpenSim/Framework/Communications/LoginService.cs
index f0a0a0b..04b8501 100644
--- a/OpenSim/Framework/Communications/LoginService.cs
+++ b/OpenSim/Framework/Communications/LoginService.cs
@@ -30,6 +30,7 @@ using System;
30using System.Collections; 30using System.Collections;
31using System.Collections.Generic; 31using System.Collections.Generic;
32using System.IO; 32using System.IO;
33using System.Text.RegularExpressions;
33using System.Threading; 34using System.Threading;
34using libsecondlife; 35using libsecondlife;
35using libsecondlife.StructuredData; 36using libsecondlife.StructuredData;
@@ -359,21 +360,103 @@ namespace OpenSim.Framework.UserManagement
359 360
360 public Hashtable ProcessHTMLLogin(Hashtable keysvals) 361 public Hashtable ProcessHTMLLogin(Hashtable keysvals)
361 { 362 {
363
364 // Matches all unspecified characters
365 // Currently specified,; lowercase letters, upper case letters, numbers, underline
366 // period, space, parens, and dash.
367
368 Regex wfcut = new Regex("[^a-zA-Z0-9_\\.\\$ \\(\\)\\-]");
369
362 Hashtable returnactions = new Hashtable(); 370 Hashtable returnactions = new Hashtable();
363 int statuscode = 200; 371 int statuscode = 200;
364 372
365 returnactions["int_response_code"] = statuscode; 373 string firstname = "";
366 returnactions["str_response_string"] = GetDefaultLoginForm(); 374 string lastname = "";
375 string location = "";
376 string region ="";
377 string grid = "";
378 string channel = "";
379 string version = "";
380 string lang = "";
381 string password = "";
382 string errormessages = "";
383
384 // the client requires the HTML form field be named 'username'
385 // however, the data it sends when it loads the first time is 'firstname'
386 // another one of those little nuances.
387
388
389 if (keysvals.Contains("firstname"))
390 firstname = wfcut.Replace((string)keysvals["firstname"],"",99999);
391 if (keysvals.Contains("username"))
392 firstname = wfcut.Replace((string)keysvals["username"],"",99999);
393
394 if (keysvals.Contains("lastname"))
395 lastname = wfcut.Replace((string)keysvals["lastname"],"",99999);
396
397 if (keysvals.Contains("location"))
398 location = wfcut.Replace((string)keysvals["location"],"",99999);
399
400 if (keysvals.Contains("region"))
401 region = wfcut.Replace((string)keysvals["region"],"",99999);
402
403 if (keysvals.Contains("grid"))
404 grid = wfcut.Replace((string)keysvals["grid"],"",99999);
405
406 if (keysvals.Contains("channel"))
407 channel = wfcut.Replace((string)keysvals["channel"],"",99999);
408
409 if (keysvals.Contains("version"))
410 version = wfcut.Replace((string)keysvals["version"],"",99999);
411
412 if (keysvals.Contains("lang"))
413 lang = wfcut.Replace((string)keysvals["lang"],"",99999);
414
415 if (keysvals.Contains("password"))
416 password = wfcut.Replace((string)keysvals["password"], "", 99999);
417
418
419 // load our login form.
420 string loginform = GetLoginForm(firstname,lastname,location,region,grid,channel,version,lang,password,errormessages);
367 421
368 if (keysvals.ContainsKey("show_login_form")) 422 if (keysvals.ContainsKey("show_login_form"))
369 { 423 {
370 if ((string)keysvals["show_login_form"] == "TRUE") 424 if ((string)keysvals["show_login_form"] == "TRUE")
371 { 425 {
372 426 returnactions["int_response_code"] = statuscode;
427 returnactions["str_response_string"] = loginform;
373 } 428 }
374 else 429 else
375 { 430 {
431 UserProfileData user = GetTheUser(firstname, lastname);
432 bool goodweblogin = false;
376 433
434 if (user != null)
435 goodweblogin = AuthenticateUser(user, password);
436
437 if (goodweblogin)
438 {
439 LLUUID webloginkey = LLUUID.Random();
440 m_userManager.StoreWebLoginKey(user.UUID, webloginkey);
441 statuscode = 301;
442
443 string redirectURL = "secondlife:///app/login?first_name=" + firstname + "&last_name=" +
444 lastname +
445 "&location=" + location + "&grid=Other&web_login_key=" + webloginkey.ToString();
446
447 returnactions["int_response_code"] = statuscode;
448 returnactions["str_redirect_location"] = redirectURL;
449 returnactions["str_response_string"] = "<HTML><BODY>GoodLogin</BODY></HTML>";
450 }
451 else
452 {
453 errormessages = "The Username and password supplied did not match our records. Check your caps lock and try again";
454
455 loginform = GetLoginForm(firstname, lastname, location, region, grid, channel, version, lang, password, errormessages);
456 returnactions["int_response_code"] = statuscode;
457 returnactions["str_response_string"] = loginform;
458
459 }
377 460
378 } 461 }
379 462
@@ -382,16 +465,36 @@ namespace OpenSim.Framework.UserManagement
382 465
383 } 466 }
384 467
385 public string GetLoginForm() 468 public string GetLoginForm(string firstname, string lastname, string location, string region,
469 string grid, string channel, string version, string lang,
470 string password, string errormessages)
386 { 471 {
472 // inject our values in the form at the markers
473
474 string loginform="";
387 string file = Path.Combine(Util.configDir(), "http_loginform.html"); 475 string file = Path.Combine(Util.configDir(), "http_loginform.html");
388 if (!File.Exists(file)) 476 if (!File.Exists(file))
389 return GetDefaultLoginForm(); 477 {
390 478 loginform = GetDefaultLoginForm();
391 StreamReader sr = File.OpenText(file); 479 }
392 string result = sr.ReadToEnd(); 480 else
393 sr.Close(); 481 {
394 return result; 482 StreamReader sr = File.OpenText(file);
483 loginform = sr.ReadToEnd();
484 sr.Close();
485 }
486
487 loginform = loginform.Replace("[$firstname]", firstname);
488 loginform = loginform.Replace("[$lastname]", lastname);
489 loginform = loginform.Replace("[$location]", location);
490 loginform = loginform.Replace("[$region]", region);
491 loginform = loginform.Replace("[$grid]", grid);
492 loginform = loginform.Replace("[$channel]", channel);
493 loginform = loginform.Replace("[$version]", version);
494 loginform = loginform.Replace("[$lang]", lang);
495 loginform = loginform.Replace("[$password]", password);
496 loginform = loginform.Replace("[$errors]", errormessages);
497 return loginform;
395 } 498 }
396 499
397 public string GetDefaultLoginForm() 500 public string GetDefaultLoginForm()
@@ -405,7 +508,7 @@ namespace OpenSim.Framework.UserManagement
405 responseString = responseString + "<meta http-equiv=\"cache-control\" content=\"no-cache\">"; 508 responseString = responseString + "<meta http-equiv=\"cache-control\" content=\"no-cache\">";
406 responseString = responseString + "<meta http-equiv=\"Pragma\" content=\"no-cache\">"; 509 responseString = responseString + "<meta http-equiv=\"Pragma\" content=\"no-cache\">";
407 responseString = responseString + "<title>Second Life Login</title>"; 510 responseString = responseString + "<title>Second Life Login</title>";
408 responseString = responseString + "<body>"; 511 responseString = responseString + "<body><br />";
409 responseString = responseString + "<div id=\"login_box\">"; 512 responseString = responseString + "<div id=\"login_box\">";
410 513
411 responseString = responseString + "<form action=\"/\" method=\"GET\" id=\"login-form\">"; 514 responseString = responseString + "<form action=\"/\" method=\"GET\" id=\"login-form\">";
@@ -434,6 +537,11 @@ namespace OpenSim.Framework.UserManagement
434 responseString = responseString + "<input type=\"hidden\" name=\"show_login_form\" value=\"FALSE\" />"; 537 responseString = responseString + "<input type=\"hidden\" name=\"show_login_form\" value=\"FALSE\" />";
435 responseString = responseString + "<input type=\"hidden\" name=\"method\" value=\"login\" />"; 538 responseString = responseString + "<input type=\"hidden\" name=\"method\" value=\"login\" />";
436 responseString = responseString + "<input type=\"hidden\" id=\"grid\" name=\"grid\" value=\"[$grid]\" />"; 539 responseString = responseString + "<input type=\"hidden\" id=\"grid\" name=\"grid\" value=\"[$grid]\" />";
540 responseString = responseString + "<input type=\"hidden\" id=\"region\" name=\"region\" value=\"[$region]\" />";
541 responseString = responseString + "<input type=\"hidden\" id=\"location\" name=\"location\" value=\"[$location]\" />";
542 responseString = responseString + "<input type=\"hidden\" id=\"channel\" name=\"channel\" value=\"[$channel]\" />";
543 responseString = responseString + "<input type=\"hidden\" id=\"version\" name=\"version\" value=\"[$version]\" />";
544 responseString = responseString + "<input type=\"hidden\" id=\"lang\" name=\"lang\" value=\"[$lang]\" />";
437 responseString = responseString + "<div id=\"submitbtn\">"; 545 responseString = responseString + "<div id=\"submitbtn\">";
438 responseString = responseString + "<input class=\"input_over\" type=\"submit\" value=\"Connect\" />"; 546 responseString = responseString + "<input class=\"input_over\" type=\"submit\" value=\"Connect\" />";
439 responseString = responseString + "</div>"; 547 responseString = responseString + "</div>";
@@ -444,7 +552,7 @@ namespace OpenSim.Framework.UserManagement
444 responseString = responseString + "<a href=\"http://www.secondlife.com/account/request.php\" target=\"_blank\">Forgot password?</a>"; 552 responseString = responseString + "<a href=\"http://www.secondlife.com/account/request.php\" target=\"_blank\">Forgot password?</a>";
445 responseString = responseString + "</div>"; 553 responseString = responseString + "</div>";
446 554
447 responseString = responseString + "<div id=\"channelinfo\"> [$clientchannelinfo] | [$clientversion]=[$clientlanguage]</div>"; 555 responseString = responseString + "<div id=\"channelinfo\"> [$channel] | [$version]=[$lang]</div>";
448 responseString = responseString + "</form>"; 556 responseString = responseString + "</form>";
449 responseString = responseString + "<script language=\"JavaScript\">"; 557 responseString = responseString + "<script language=\"JavaScript\">";
450 responseString = responseString + "document.getElementById('firstname_input').focus();"; 558 responseString = responseString + "document.getElementById('firstname_input').focus();";
@@ -480,14 +588,26 @@ namespace OpenSim.Framework.UserManagement
480 "LOGIN", "Authenticating {0} {1} ({2})", profile.username, profile.surname, profile.UUID); 588 "LOGIN", "Authenticating {0} {1} ({2})", profile.username, profile.surname, profile.UUID);
481 589
482 // Web Login method seems to also occasionally send the hashed password itself 590 // Web Login method seems to also occasionally send the hashed password itself
483
484 591
592
593 // we do this to get our hash in a form that the server password code can consume
594 // when the web-login-form submits the password in the clear (supposed to be over SSL!)
595 if (!password.StartsWith("$1$"))
596 password = "$1$" + Util.Md5Hash(password);
597
598
599
485 password = password.Remove(0, 3); //remove $1$ 600 password = password.Remove(0, 3); //remove $1$
601
602
486 603
487 string s = Util.Md5Hash(password + ":" + profile.passwordSalt); 604 string s = Util.Md5Hash(password + ":" + profile.passwordSalt);
605 // Testing...
606 //MainLog.Instance.Verbose("LOGIN", "SubHash:" + s + " userprofile:" + profile.passwordHash);
607 //MainLog.Instance.Verbose("LOGIN", "userprofile:" + profile.passwordHash + " SubCT:" + password);
488 608
489 passwordSuccess = (profile.passwordHash.Equals(s.ToString(), StringComparison.InvariantCultureIgnoreCase) 609 passwordSuccess = (profile.passwordHash.Equals(s.ToString(), StringComparison.InvariantCultureIgnoreCase)
490 || profile.passwordHash.Equals(password.ToString(),StringComparison.InvariantCultureIgnoreCase)); 610 || profile.passwordHash.Equals(password,StringComparison.InvariantCultureIgnoreCase));
491 611
492 return passwordSuccess; 612 return passwordSuccess;
493 } 613 }
diff --git a/OpenSim/Framework/Servers/BaseHttpServer.cs b/OpenSim/Framework/Servers/BaseHttpServer.cs
index 32d65af..3ca4187 100644
--- a/OpenSim/Framework/Servers/BaseHttpServer.cs
+++ b/OpenSim/Framework/Servers/BaseHttpServer.cs
@@ -389,12 +389,9 @@ namespace OpenSim.Framework.Servers
389 foreach (string queryname in querystringkeys) 389 foreach (string queryname in querystringkeys)
390 { 390 {
391 keysvals.Add(queryname, request.QueryString[queryname]); 391 keysvals.Add(queryname, request.QueryString[queryname]);
392 MainLog.Instance.Warn("HTTP", queryname + "=" + request.QueryString[queryname]); 392
393 } 393 }
394 //foreach (string headername in rHeaders) 394
395 //{
396 //MainLog.Instance.Warn("HEADER", headername + "=" + request.Headers[headername]);
397 //}
398 if (keysvals.Contains("method")) 395 if (keysvals.Contains("method"))
399 { 396 {
400 MainLog.Instance.Warn("HTTP", "Contains Method"); 397 MainLog.Instance.Warn("HTTP", "Contains Method");
diff --git a/OpenSim/Grid/UserServer/Main.cs b/OpenSim/Grid/UserServer/Main.cs
index 02ca385..f40c6f6 100644
--- a/OpenSim/Grid/UserServer/Main.cs
+++ b/OpenSim/Grid/UserServer/Main.cs
@@ -103,6 +103,8 @@ namespace OpenSim.Grid.UserServer
103 BaseHttpServer httpServer = new BaseHttpServer(Cfg.HttpPort); 103 BaseHttpServer httpServer = new BaseHttpServer(Cfg.HttpPort);
104 104
105 httpServer.AddXmlRPCHandler("login_to_simulator", m_loginService.XmlRpcLoginMethod); 105 httpServer.AddXmlRPCHandler("login_to_simulator", m_loginService.XmlRpcLoginMethod);
106
107 httpServer.AddHTTPHandler("login", m_loginService.ProcessHTMLLogin);
106 108
107 httpServer.SetLLSDHandler(m_loginService.LLSDLoginMethod); 109 httpServer.SetLLSDHandler(m_loginService.LLSDLoginMethod);
108 110
diff --git a/OpenSim/Region/Application/OpenSimMain.cs b/OpenSim/Region/Application/OpenSimMain.cs
index 3818a50..297c9b2 100644
--- a/OpenSim/Region/Application/OpenSimMain.cs
+++ b/OpenSim/Region/Application/OpenSimMain.cs
@@ -323,7 +323,13 @@ namespace OpenSim
323 m_standaloneAuthenticate); 323 m_standaloneAuthenticate);
324 m_loginService.OnLoginToRegion += backendService.AddNewSession; 324 m_loginService.OnLoginToRegion += backendService.AddNewSession;
325 325
326 // XMLRPC action
326 m_httpServer.AddXmlRPCHandler("login_to_simulator", m_loginService.XmlRpcLoginMethod); 327 m_httpServer.AddXmlRPCHandler("login_to_simulator", m_loginService.XmlRpcLoginMethod);
328
329 // provides the web form login
330 m_httpServer.AddHTTPHandler("login", m_loginService.ProcessHTMLLogin);
331
332 // Provides the LLSD login
327 m_httpServer.SetLLSDHandler(m_loginService.LLSDLoginMethod); 333 m_httpServer.SetLLSDHandler(m_loginService.LLSDLoginMethod);
328 334
329 if (m_standaloneAuthenticate) 335 if (m_standaloneAuthenticate)
diff --git a/OpenSim/Region/Communications/Local/LocalLoginService.cs b/OpenSim/Region/Communications/Local/LocalLoginService.cs
index 2c92491..38f1970 100644
--- a/OpenSim/Region/Communications/Local/LocalLoginService.cs
+++ b/OpenSim/Region/Communications/Local/LocalLoginService.cs
@@ -103,12 +103,17 @@ namespace OpenSim.Region.Communications.Local
103 { 103 {
104 MainLog.Instance.Notice( 104 MainLog.Instance.Notice(
105 "LOGIN", "Authenticating " + profile.username + " " + profile.surname); 105 "LOGIN", "Authenticating " + profile.username + " " + profile.surname);
106
107 if (!password.StartsWith("$1$"))
108 password = "$1$" + Util.Md5Hash(password);
106 109
107 password = password.Remove(0, 3); //remove $1$ 110 password = password.Remove(0, 3); //remove $1$
108 111
109 string s = Util.Md5Hash(password + ":" + profile.passwordSalt); 112 string s = Util.Md5Hash(password + ":" + profile.passwordSalt);
110 113
111 return profile.passwordHash.Equals(s.ToString(), StringComparison.InvariantCultureIgnoreCase); 114 bool loginresult = (profile.passwordHash.Equals(s.ToString(), StringComparison.InvariantCultureIgnoreCase)
115 || profile.passwordHash.Equals(password, StringComparison.InvariantCultureIgnoreCase));
116 return loginresult;
112 } 117 }
113 } 118 }
114 119
diff --git a/bin/http_loginform.html.example b/bin/http_loginform.html.example
new file mode 100644
index 0000000..16655de
--- /dev/null
+++ b/bin/http_loginform.html.example
@@ -0,0 +1,60 @@
1<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2<html xmlns="http://www.w3.org/1999/xhtml">
3<head>
4<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
5<meta http-equiv="cache-control" content="no-cache">
6<meta http-equiv="Pragma" content="no-cache">
7<title>Second Life Login</title>
8<body><br />
9<div id="login_box">
10
11<form action="/" method="GET" id="login-form">
12
13<div id="message">[$errors]</div>
14<fieldset id="firstname">
15<legend>First Name:</legend>
16<input type="text" id="firstname_input" size="15" maxlength="100" name="username" value="[$firstname]" />
17</fieldset>
18<fieldset id="lastname">
19<legend>Last Name:</legend>
20<input type="text" size="15" maxlength="100" name="lastname" value="[$lastname]" />
21</fieldset>
22<fieldset id="password">
23<legend>Password:</legend>
24<table cellspacing="0" cellpadding="0" border="0">
25<tr>
26<td colspan="2"><input type="password" size="15" maxlength="100" name="password" value="[$password]" /></td>
27</tr>
28<tr>
29<td valign="middle"><input type="checkbox" name="remember_password" id="remember_password" [$remember_password] style="margin-left:0px;"/></td>
30<td><label for="remember_password">Remember password</label></td>";
31</tr>
32</table>
33</fieldset>
34<input type="hidden" name="show_login_form" value="FALSE" />
35<input type="hidden" name="method" value="login" />
36<input type="hidden" id="grid" name="grid" value="[$grid]" />
37<input type="hidden" id="region" name="region" value="[$region]" />
38<input type="hidden" id="location" name="location" value="[$location]" />
39<input type="hidden" id="channel" name="channel" value="[$channel]" />
40<input type="hidden" id="version" name="version" value="[$version]" />
41<input type="hidden" id="lang" name="lang" value="[$lang]" />
42<div id="submitbtn">
43<input class="input_over" type="submit" value="Connect" />
44</div>
45<div id="connecting" style="visibility:hidden"> Connecting...</div>
46
47<div id="helplinks">
48<a href="http://www.secondlife.com/join/index.php" target="_blank">Create new account</a> |
49<a href="http://www.secondlife.com/account/request.php" target="_blank">Forgot password?</a>
50</div>
51
52<div id="channelinfo"> [$channel] | [$version]=[$lang]</div>
53</form>
54<script language="JavaScript">
55document.getElementById('firstname_input').focus();
56</script>
57</div>
58</div>
59</body>
60</html> \ No newline at end of file