From 70efa042176d2dd1c49f9f00a6e5b9452bbc9de6 Mon Sep 17 00:00:00 2001 From: onefang Date: Tue, 13 Aug 2019 07:35:50 +1000 Subject: Beef up the web server a bit. Sanatize the path. Add support for Last-Modified, If-Modified-Since, and Cache-Control: no-cache. Teach the base server about more binary content types. --- OpenSim/Server/Handlers/Web/WebServerConnector.cs | 37 +++++++++++++++++++++++ 1 file changed, 37 insertions(+) (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 2607386..06fd892 100644 --- a/OpenSim/Server/Handlers/Web/WebServerConnector.cs +++ b/OpenSim/Server/Handlers/Web/WebServerConnector.cs @@ -91,6 +91,7 @@ namespace OpenSim.Server.Handlers.Web long HGin = m_database.Count("Presence", "UserID NOT IN (SELECT PrincipalID FROM UserAccounts)"); // HGers in world. long locOut = m_database.Count("hg_traveling_data", "GridExternalName != '" + ssi["uri"] + "'"); // Locals that are HGing. Hashtable reply = new Hashtable(); + Hashtable replyHeaders = new Hashtable(); ssi["members"] = m_database.Count("UserAccounts").ToString(); ssi["sims"] = m_database.Count("regions").ToString(); ssi["inworld"] = (locIn - HGin).ToString(); @@ -107,6 +108,16 @@ namespace OpenSim.Server.Handlers.Web string file = reqpath.Remove(0, 5); string path = Path.Combine(Util.webDir(), file); + if (! Path.GetFullPath(path).StartsWith(Path.GetFullPath(Util.webDir()))) + { + m_log.ErrorFormat("[WEB SERVICE]: INVALID PATH {0} != {1}", Path.GetFullPath(path), Path.GetFullPath(Util.webDir())); + reply["int_response_code"] = 404; + reply["content_type"] = "text/html"; + reply["str_response_string"] = "404 Unknown page" + + "404 error, can't find the " + reqpath + " page.

 

"; + return reply; + } + m_log.InfoFormat("[WEB SERVICE]: {0} method path {1} 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); @@ -118,12 +129,36 @@ namespace OpenSim.Server.Handlers.Web { if (File.Exists(path)) { + DateTime dt = File.GetLastWriteTimeUtc(path); string m = (string) mime[Path.GetExtension(path).ToLower()]; reply["content_type"] = m; if ((null == m) || ("text/" != m.Substring(0, 5))) + { + string ifdtr = (string) headers["if-modified-since"]; + if (null != ifdtr) + { + try + { + DateTime ifdt = DateTime.Parse(ifdtr, System.Globalization.CultureInfo.InvariantCulture); + if (0 >= DateTime.Compare(ifdt, dt)) + { + reply["int_response_code"] = 304; + m_log.InfoFormat("[WEB SERVICE]: If-Modified-Since is earliar or equal to Last-Modified, from {0}", path); + reply["headers"] = replyHeaders; + return reply; + } + } + catch (Exception) + { + m_log.ErrorFormat("[WEB SERVICE]: Invalid If-Modified-Since header, ignoring it, from {0}", path); + } + } + replyHeaders["Last-Modified"] = dt.ToString("R"); reply["bin_response_data"] = File.ReadAllBytes(path); + } else { + replyHeaders["Cache-Control"] = "no-cache"; StreamReader csr = File.OpenText(path); string content = csr.ReadToEnd(); // Slow and wasteful, but I'm expecting only tiny web files, not accessed very often. @@ -169,6 +204,7 @@ namespace OpenSim.Server.Handlers.Web if ("account.html" == file) { + replyHeaders["Cache-Control"] = "no-cache"; if ("logout" == fields["doit"].ToString()) reply["str_response_string"] = loginPage(null, "Logged out."); else if ("create" == fields["doit"].ToString()) @@ -213,6 +249,7 @@ namespace OpenSim.Server.Handlers.Web } m_log.Info("[WEB SERVICE]: "); + reply["headers"] = replyHeaders; return reply; } -- cgit v1.1