From ee33dd4b56f7782bbf7798fa3ff8821ff81acd36 Mon Sep 17 00:00:00 2001 From: onefang Date: Sat, 17 Aug 2019 07:09:16 +1000 Subject: VArious additions to account manager. First and last names merged into one name. Is name two words check, a suprisingly effective spam blocker. Poor mans Bobby Tables protection. Various other input checking. Added account creation confirmation page. Some text and length tweaks. --- OpenSim/Server/Handlers/Web/WebServerConnector.cs | 102 ++++++++++++++++++---- 1 file changed, 83 insertions(+), 19 deletions(-) (limited to 'OpenSim/Server/Handlers/Web/WebServerConnector.cs') diff --git a/OpenSim/Server/Handlers/Web/WebServerConnector.cs b/OpenSim/Server/Handlers/Web/WebServerConnector.cs index 3a8e906..7879e4e 100644 --- a/OpenSim/Server/Handlers/Web/WebServerConnector.cs +++ b/OpenSim/Server/Handlers/Web/WebServerConnector.cs @@ -6,6 +6,7 @@ using System.Net; using System.Reflection; using System.Security; using System.Text; +using System.Text.RegularExpressions; using log4net; using Nini.Config; using OpenMetaverse; @@ -131,13 +132,14 @@ namespace OpenSim.Server.Handlers.Web return reply; } - m_log.InfoFormat("[WEB SERVICE]: {0} method path {1} type {2} body {3}.", method, reqpath, type, body); + m_log.InfoFormat("[WEB SERVICE]: {0} method path {1} contont type {2} body {3}.", method, reqpath, type, body); foreach (DictionaryEntry h in headers) m_log.InfoFormat("[WEB SERVICE]: {0} method path {1} header {2} = {3}", method, reqpath, (string) h.Key, (string) h.Value); foreach (String q in query) m_log.InfoFormat("[WEB SERVICE]: {0} method path {1} query {2} value {3}", method, reqpath, q, (string) request[q]); reply["int_response_code"] = 200; +// TODO - need to support HEAD method, seems to be what triggers the endles GETs. if ("GET" == method) { if (File.Exists(path)) @@ -211,25 +213,71 @@ namespace OpenSim.Server.Handlers.Web String v = ""; if (b.Length > 1) v = System.Web.HttpUtility.UrlDecode(b[1]); + if ((0 != String.Compare("password", n)) && (0 != String.Compare("psswrd", n))) + { + // Poor mans Bobby Tables protection. + v = v.Replace("'", "_"); + v = v.Replace("\"", "_"); + v = v.Replace(";", "_"); + v = v.Replace("(", "_"); + v = v.Replace(")", "_"); + } fields[n] = v; body = body + "

" + n + " = " + v + "

\n"; } if ("account.html" == file) { + string doit = fields["doit"].ToString(); replyHeaders["Cache-Control"] = "no-cache"; - if ("logout" == fields["doit"].ToString()) + if ("logout" == doit) reply["str_response_string"] = loginPage(null, "Logged out."); - else if ("create" == fields["doit"].ToString()) + else if (("create" == doit) || ("confirm" == doit)) { + Regex rgxName = new Regex("^[a-zA-Z0-9]+$"); + Regex rgxEmail = new Regex("^.+@.+\\..+$"); + string[] names = fields["name"].ToString().Split(' '); if ("" == fields["email"].ToString()) reply["str_response_string"] = loginPage(fields, "Please supply an email address when creating an account."); + else if (!rgxEmail.IsMatch(fields["email"].ToString())) + reply["str_response_string"] = loginPage(fields, "Please supply a valid email address when creating an account."); + else if (!Uri.IsWellFormedUriString("mailto:" + fields["email"].ToString(), System.UriKind.Absolute)) + reply["str_response_string"] = loginPage(fields, "Please supply a valid email address when creating an account."); +// TODO - the other test to do here is actually lookup the domain name, looking for any sort of record. + else if (2 != names.Length) + reply["str_response_string"] = loginPage(fields, "Please supply a two word name when creating an account."); + // SL docs say 31 characters each for first and last name. UserAccounts table is varchar(64) each. userinfo has varchar(50) for the combined name. + // The userinfo table seems to be obsolete. + // Singularity at least limits the total name to 64. + // I can't find any limitations on characters allowed, but I only ever see letters and digits used. Case is stored, but not significant. + // OpenSims "create user" console command doesn't sanitize it at all, even crashing on some names. + else if (31 < names[0].Length) + reply["str_response_string"] = loginPage(fields, "First and last names are limited to 31 letters each."); + else if (31 < names[1].Length) + reply["str_response_string"] = loginPage(fields, "First and last names are limited to 31 letters each."); + else if (!rgxName.IsMatch(names[0])) + reply["str_response_string"] = loginPage(fields, "First and last names are limited to letters and digits."); + else if (!rgxName.IsMatch(names[1])) + reply["str_response_string"] = loginPage(fields, "First and last names are limited to letters and digits."); +// TODO - check and disallow god names, those are done in the console. else { - reply["str_response_string"] = loggedOnPage(body, fields); + if (("create" == doit)) + reply["str_response_string"] = accountCreationPage(body, fields); + else + { + if (0 != String.Compare(fields["psswrd"].ToString(), fields["password"].ToString())) + reply["str_response_string"] = loginPage(fields, "Passwords are not the same."); + else + reply["str_response_string"] = loggedOnPage(body, fields); + } } } - else if ("list" == fields["doit"].ToString()) + else if ("cancel" == doit) + { + reply["str_response_string"] = loginPage(null, "Cancelled."); + } + else if ("list" == doit) { List< Hashtable > rows = m_database.Select("UserAccounts", "CONCAT(FirstName,' ',LastName) as Name,UserTitle as Title,UserLevel as Level,UserFlags as Flags,PrincipalID as UUID", @@ -268,21 +316,19 @@ namespace OpenSim.Server.Handlers.Web private string loginPage(Hashtable fields, string message) { - string f = ""; - string l = ""; + string n = ""; string e = ""; if (null != fields) { - f = fields["firstName"].ToString(); - l = fields["lastName"].ToString(); + n = fields["name"].ToString(); e = fields["email"].ToString(); } return header(ssi["grid"] + " account") + form("account.html", "", - text("text", "first name", "firstName", f, 16, true) - + text("text", "last name", "lastName", l, 16, true) - + text("email", "email", "email", e, 0, false) - + text("password", "password", "password", "", 14,true) + text("text", "name", "name", n, 63, true) + + text("email", "email", "email", e, 254, false) + + text("password", "password", "password", "", 0, true) + + "Warning, the limit on password length is set by your viewer, some can't handle longer than 16 characters." + button("create") + button("login") ) @@ -290,17 +336,35 @@ namespace OpenSim.Server.Handlers.Web + footer(); } + private string accountCreationPage(string body, Hashtable fields) + { + return header(ssi["grid"] + " account") + + "

Creating " + ssi["grid"] + " account for " + fields["name"].ToString() + "

" + + form("account.html", fields["token"].ToString(), + hidden("name", fields["name"].ToString()) + + hidden("psswrd", fields["password"].ToString()) + + text("email", "An email will be sent to", "email", fields["email"].ToString(), 254, true) + + " to validate it, please double check this." + + text("password", "Re-enter your password", "password", "", 0, true) + + "Warning, the limit on password length is set by your viewer, some can't handle longer than 16 characters." + + button("confirm") + + button("cancel") + ) + + body + + footer(); + } + private string loggedOnPage(string body, Hashtable fields) { return header(ssi["grid"] + " account") - + "

" + ssi["grid"] + " account for " + fields["firstName"].ToString() + " " + fields["lastName"].ToString() + "

" + + "

" + ssi["grid"] + " account for " + fields["name"].ToString() + "

" + form("account.html", fields["token"].ToString(), - hidden("firstName", fields["firstName"].ToString()) - + hidden("lastName", fields["lastName"].ToString()) + hidden("name", fields["name"].ToString()) // + hidden("UUID", fields["UUID"].ToString()) - + text("email", "email", "email", fields["email"].ToString(), 0, false) - + text("password", "password", "password", "", 14, false) -// + text("title", "text", "title", fields["title"].ToString(), 0, false) + + text("email", "email", "email", fields["email"].ToString(), 254, true) + + text("password", "password", "password", "", 0, false) + + "Warning, the limit on password length is set by your viewer, some can't handle longer than 16 characters." +// + text("title", "text", "title", fields["title"].ToString(), 64, false) + select("type", "type", option("", false) + option("approved", true) -- cgit v1.1