diff options
Diffstat (limited to 'OpenSim/Framework/Communications/LoginService.cs')
-rw-r--r-- | OpenSim/Framework/Communications/LoginService.cs | 148 |
1 files changed, 134 insertions, 14 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; | |||
30 | using System.Collections; | 30 | using System.Collections; |
31 | using System.Collections.Generic; | 31 | using System.Collections.Generic; |
32 | using System.IO; | 32 | using System.IO; |
33 | using System.Text.RegularExpressions; | ||
33 | using System.Threading; | 34 | using System.Threading; |
34 | using libsecondlife; | 35 | using libsecondlife; |
35 | using libsecondlife.StructuredData; | 36 | using 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 | } |