From f24b120f5b0e1ec7c656c54e3afe82703e7020f0 Mon Sep 17 00:00:00 2001 From: Simon Smith Date: Tue, 27 Aug 2024 19:40:16 +0100 Subject: [PATCH] fixes for upload #99 delete unused file, increase upload speed size, fix random crashing --- MeshCentralServer-new.cs | 1156 -------------------------------------- src/FileViewer.cs | 2 +- src/KVMControl.cs | 4 +- 3 files changed, 4 insertions(+), 1158 deletions(-) delete mode 100644 MeshCentralServer-new.cs diff --git a/MeshCentralServer-new.cs b/MeshCentralServer-new.cs deleted file mode 100644 index 6b980fd..0000000 --- a/MeshCentralServer-new.cs +++ /dev/null @@ -1,1156 +0,0 @@ -/* -Copyright 2009-2022 Intel Corporation - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -using System; -using System.IO; -using System.Web; -using System.Collections; -using System.Collections.Generic; -using System.Security.Cryptography; -using System.Deployment.Application; -using System.Collections.Specialized; -using System.Web.Script.Serialization; -using System.Security.Cryptography.X509Certificates; -using Microsoft.Win32; -using System.Text; - -namespace MeshCentralRouter -{ - - public class MeshCentralServer - { - public Uri wsurl = null; - private string user = null; - private string pass = null; - private string token = null; - private webSocketClient wc = null; - //private System.Timers.Timer procTimer = new System.Timers.Timer(5000); - private int constate = 0; - public Dictionary nodes = null; - public Dictionary meshes = null; - public string disconnectCause = null; - public string disconnectMsg = null; - public bool disconnectEmail2FA = false; - public bool disconnectEmail2FASent = false; - public bool disconnectSms2FA = false; - public bool disconnectSms2FASent = false; - public X509Certificate2 disconnectCert; - public string authCookie = null; - public string rauthCookie = null; - public string loginCookie = null; - public string wshash = null; - public string certHash = null; - public string okCertHash = null; - public string okCertHash2 = null; - public bool debug = false; - public bool tlsdump = false; - public bool ignoreCert = false; - public string userid = null; - public string username = null; - public int twoFactorCookieDays = 0; - public Dictionary userRights = null; - public Dictionary userGroups = null; - private JavaScriptSerializer JSON = new JavaScriptSerializer(); - public int features = 0; // Bit flags of server features - public int features2 = 0; // Bit flags of server features - - public int connectionState { get { return constate; } } - - // Mesh Rights - /* - const MESHRIGHT_EDITMESH = 1; - const MESHRIGHT_MANAGEUSERS = 2; - const MESHRIGHT_MANAGECOMPUTERS = 4; - const MESHRIGHT_REMOTECONTROL = 8; - const MESHRIGHT_AGENTCONSOLE = 16; - const MESHRIGHT_SERVERFILES = 32; - const MESHRIGHT_WAKEDEVICE = 64; - const MESHRIGHT_SETNOTES = 128; - const MESHRIGHT_REMOTEVIEWONLY = 256; - const MESHRIGHT_NOTERMINAL = 512; - const MESHRIGHT_NOFILES = 1024; - const MESHRIGHT_NOAMT = 2048; - const MESHRIGHT_DESKLIMITEDINPUT = 4096; - const MESHRIGHT_LIMITEVENTS = 8192; - const MESHRIGHT_CHATNOTIFY = 16384; - const MESHRIGHT_UNINSTALL = 32768; - */ - - public static void saveToRegistry(string name, string value) - { - try { Registry.SetValue(@"HKEY_CURRENT_USER\SOFTWARE\OpenSource\MeshRouter", name, value); } catch (Exception) { } - } - public static string loadFromRegistry(string name) - { - try { return Registry.GetValue(@"HKEY_CURRENT_USER\SOFTWARE\OpenSource\MeshRouter", name, "").ToString(); } catch (Exception) { return ""; } - } - - - // Parse the URL query parameters and returns a collection - public static NameValueCollection GetQueryStringParameters() - { - NameValueCollection nameValueTable = new NameValueCollection(); - if (ApplicationDeployment.IsNetworkDeployed) - { - string queryString = ApplicationDeployment.CurrentDeployment.ActivationUri.Query; - nameValueTable = HttpUtility.ParseQueryString(queryString); - } - return (nameValueTable); - } - - // Starts the routing server, called when the start button is pressed - public void connect(Uri wsurl, string user, string pass, string token) - { - JSON.MaxJsonLength = 217483647; - this.user = user; - this.pass = pass; - this.token = token; - this.wsurl = wsurl; - - // Setup extra headers if needed - Dictionary extraHeaders = new Dictionary(); - if (user != null && pass != null && token != null) { - extraHeaders.Add("x-meshauth", Base64Encode(user) + "," + Base64Encode(pass) + "," + Base64Encode(token)); - } else if (user != null && pass != null) { - extraHeaders.Add("x-meshauth", Base64Encode(user) + "," + Base64Encode(pass)); - } - - wc = new webSocketClient(); - wc.extraHeaders = extraHeaders; - wc.onStateChanged += new webSocketClient.onStateChangedHandler(changeStateEx); - wc.onStringData += new webSocketClient.onStringDataHandler(processServerData); - //Debug("#" + counter + ": Connecting web socket to: " + wsurl.ToString()); - wc.TLSCertCheck = webSocketClient.TLSCertificateCheck.Verify; - wc.Start(wsurl, okCertHash, okCertHash2); - if (debug || tlsdump) { try { File.AppendAllText("debug.log", "Connect-" + wsurl + "\r\n"); } catch (Exception) { } } - wc.debug = debug; - wc.tlsdump = tlsdump; - wc.TLSCertCheck = (ignoreCert) ? webSocketClient.TLSCertificateCheck.Ignore : webSocketClient.TLSCertificateCheck.Verify; - } - - public void disconnect() - { - if (wc != null) - { - wc.Dispose(); - wc = null; - if (debug || tlsdump) { try { File.AppendAllText("debug.log", "Disconnect\r\n"); } catch (Exception) { } } - } - } - - public void sendCommand(string cmd) - { - if (wc != null) - { - if (debug) { try { File.AppendAllText("debug.log", "sendCommand: " + cmd + "\r\n"); } catch (Exception) { } } - wc.SendString(cmd); - } - } - - public void refreshCookies() - { - if (wc != null) { - if (debug) { try { File.AppendAllText("debug.log", "RefreshCookies\r\n"); } catch (Exception) { } } - wc.SendString("{\"action\":\"authcookie\"}"); - wc.SendString("{\"action\":\"logincookie\"}"); - } - } - - public void setRdpPort(NodeClass node, int port) - { - if (wc != null) - { - if (debug) { try { File.AppendAllText("debug.log", "SetRdpPort\r\n"); } catch (Exception) { } } - wc.SendString("{\"action\":\"changedevice\",\"nodeid\":\"" + node.nodeid + "\",\"rdpport\":" + port + "}"); - } - } - - public void processServerData(webSocketClient sender, string data, int orglen) - { - if (debug) { try { File.AppendAllText("debug.log", "ServerData-" + data + "\r\n"); } catch (Exception) { } } - - // Parse the received JSON - Dictionary jsonAction = new Dictionary(); - try - { - jsonAction = JSON.Deserialize>(data); - } catch (Exception ex) { - if (debug) { - try { - File.AppendAllText("debug.log", "processServerData JSON Deserialize error: \r\n" + ex.ToString()); - File.AppendAllText("debug.log", "Invalid data (" + data.Length + "): \r\n" + data); - } catch (Exception) { } - } - return; - } - if (jsonAction == null || jsonAction["action"].GetType() != typeof(string)) return; - - try - { - string action = jsonAction["action"].ToString(); - switch (action) - { - case "pong": - { - // NOP - break; - } - case "ping": - { - // Send pong back - if (wc != null) { wc.SendString("{\"action\":\"pong\"}"); } - break; - } - case "close": - { - disconnectCause = jsonAction["cause"].ToString(); - disconnectMsg = jsonAction["msg"].ToString(); - if (jsonAction.ContainsKey("email2fa")) { disconnectEmail2FA = (bool)jsonAction["email2fa"]; } else { disconnectEmail2FA = false; } - if (jsonAction.ContainsKey("email2fasent")) { disconnectEmail2FASent = (bool)jsonAction["email2fasent"]; } else { disconnectEmail2FASent = false; } - if (jsonAction.ContainsKey("sms2fa")) { disconnectSms2FA = (bool)jsonAction["sms2fa"]; } else { disconnectSms2FA = false; } - if (jsonAction.ContainsKey("sms2fasent")) { disconnectSms2FASent = (bool)jsonAction["sms2fasent"]; } else { disconnectSms2FASent = false; } - if (jsonAction.ContainsKey("twoFactorCookieDays") && (jsonAction["twoFactorCookieDays"].GetType() == typeof(int))) { twoFactorCookieDays = (int)jsonAction["twoFactorCookieDays"]; } - break; - } - case "serverinfo": - { - // Get the bit flags of server features - Dictionary serverinfo = (Dictionary)jsonAction["serverinfo"]; - if (serverinfo.ContainsKey("features") && (serverinfo["features"].GetType() == typeof(int))) { features = (int)serverinfo["features"]; } - if (serverinfo.ContainsKey("features2") && (serverinfo["features2"].GetType() == typeof(int))) { features2 = (int)serverinfo["features2"]; } - - // Ask for a lot of things from the server - wc.SendString("{\"action\":\"usergroups\"}"); - wc.SendString("{\"action\":\"meshes\"}"); - wc.SendString("{\"action\":\"nodes\"}"); - wc.SendString("{\"action\":\"authcookie\"}"); - wc.SendString("{\"action\":\"logincookie\"}"); - wc.SendString("{\"action\":\"meshToolInfo\",\"name\":\"MeshCentralRouter\"}"); - break; - } - case "authcookie": - { - authCookie = jsonAction["cookie"].ToString(); - rauthCookie = jsonAction["rcookie"].ToString(); - changeState(2); - - if (sender.RemoteCertificate != null) - { - certHash = webSocketClient.GetMeshCertHash(new X509Certificate2(sender.RemoteCertificate)); - } - - break; - } - case "logincookie": - { - loginCookie = jsonAction["cookie"].ToString(); - if (onLoginTokenChanged != null) { onLoginTokenChanged(); } - break; - } - case "userinfo": - { - Dictionary userinfo = (Dictionary)jsonAction["userinfo"]; - userid = (string)userinfo["_id"]; - if (userinfo.ContainsKey("name")) { username = (string)userinfo["name"]; } - userRights = new Dictionary(); - if (userinfo.ContainsKey("links")) - { - Dictionary userLinks = (Dictionary)userinfo["links"]; - foreach (string i in userLinks.Keys) - { - Dictionary userLinksEx = (Dictionary)userLinks[i]; - if (userLinksEx.ContainsKey("rights")) - { - userRights[i] = ulong.Parse(userLinksEx["rights"].ToString()); - } - } - } - break; - } - case "usergroups": - { - userGroups = new Dictionary(); - if (jsonAction.ContainsKey("ugroups")) - { - Dictionary usergroups = (Dictionary)jsonAction["ugroups"]; - if (usergroups != null) - { - foreach (string i in usergroups.Keys) - { - Dictionary usergroupsEx = (Dictionary)usergroups[i]; - if (usergroupsEx.ContainsKey("name")) - { - userGroups.Add(i, usergroupsEx["name"].ToString()); - } - } - if ((onNodesChanged != null) && (nodes != null)) onNodesChanged(false); - } - } - break; - } - case "event": - { - Dictionary ev = (Dictionary)jsonAction["event"]; - string action2 = ev["action"].ToString(); - switch (action2) - { - case "meshchange": - { - // Get the new values - string meshid = ev["meshid"].ToString(); - string meshname = (string)ev["name"]; - string meshdesc = (string)ev["desc"]; - int meshtype = (int)ev["mtype"]; - ulong meshrights = 0; - Dictionary links = ((Dictionary)ev["links"]); - if (links.ContainsKey(userid)) - { - Dictionary urights = ((Dictionary)links[userid]); - if (urights != null) - { - if (urights["rights"].GetType() == typeof(int)) { meshrights = (ulong)((int)urights["rights"]); } - if (urights["rights"].GetType() == typeof(Int64)) { meshrights = (ulong)((Int64)urights["rights"]); } - } - } - - Dictionary newlinks = new Dictionary(); - foreach (string j in links.Keys) - { - Dictionary urights = ((Dictionary)links[j]); - if (urights != null) - { - if (urights["rights"].GetType() == typeof(int)) { newlinks[j] = (ulong)((int)urights["rights"]); } - if (urights["rights"].GetType() == typeof(Int64)) { newlinks[j] = (ulong)((Int64)urights["rights"]); } - } - } - - // Update the mesh - if (meshes.ContainsKey(meshid)) - { - MeshClass mesh = (MeshClass)meshes[meshid]; - mesh.name = meshname; - mesh.desc = meshdesc; - mesh.rights = meshrights; - mesh.links = newlinks; - } - else - { - MeshClass mesh = new MeshClass(); - mesh.name = meshname; - mesh.desc = meshdesc; - mesh.rights = meshrights; - mesh.type = meshtype; - mesh.links = newlinks; - meshes[meshid] = mesh; - } - wc.SendString("{\"action\":\"nodes\"}"); - if ((onNodesChanged != null) && (nodes != null)) onNodesChanged(false); - break; - } - case "changenode": - { - if (nodes == null) return; - Dictionary node = (Dictionary)ev["node"]; - string nodeid = (string)node["_id"]; - if (nodes.ContainsKey(nodeid)) - { - // Change existing node - lock (nodes) - { - NodeClass n = (NodeClass)nodes[nodeid]; - n.name = (string)node["name"]; - if (node.ContainsKey("agent")) - { - n.agentid = (int)((Dictionary)node["agent"])["id"]; - if (((Dictionary)node["agent"]).ContainsKey("caps")) { n.agentcaps = (int)((Dictionary)node["agent"])["caps"]; } else { n.agentcaps = 0; } - } - if (node.ContainsKey("conn")) { n.conn = (int)node["conn"]; } - n.icon = 1; - if (node.ContainsKey("icon")) { n.icon = (int)node["icon"]; } - if (node.ContainsKey("users")) { n.users = (string[])((ArrayList)node["users"]).ToArray(typeof(string)); } else { n.users = null; } - if (node.ContainsKey("rdpport")) { n.rdpport = (int)node["rdpport"]; } - ulong nodeRights = 0; - if (node.ContainsKey("links")) - { - Dictionary links = ((Dictionary)node["links"]); - if (links.ContainsKey(userid)) - { - Dictionary linksEx = ((Dictionary)links[userid]); - if (linksEx.ContainsKey("rights")) { nodeRights = (ulong)(int)linksEx["rights"]; } - } - - n.links = new Dictionary(); - foreach (string j in links.Keys) - { - Dictionary linksEx = ((Dictionary)links[j]); - if (linksEx.ContainsKey("rights")) - { - n.links.Add(j, ulong.Parse(linksEx["rights"].ToString())); - } - } - } - n.rights = nodeRights; - - // Compute rights on this device - ulong rights = n.rights; // Direct device rights - if (meshes.ContainsKey(n.meshid)) { rights |= meshes[n.meshid].rights; } // Device group rights - foreach (string i in n.links.Keys) { if (userGroups.ContainsKey(i)) { rights |= n.links[i]; } } // Take a look at group rights - - if (rights == 0) - { - // We have no rights to this device, remove it - nodes.Remove(n.nodeid); - } - else - { - // Update the node - nodes[n.nodeid] = n; - } - } - if ((onNodesChanged != null) && (nodes != null)) onNodesChanged(false); - } - else - { - wc.SendString("{\"action\":\"nodes\"}"); - } - break; - } - case "nodeconnect": - { - if (nodes == null) return; - string nodeid = (string)ev["nodeid"]; - if (nodes.ContainsKey(nodeid)) - { - lock (nodes) - { - NodeClass n = (NodeClass)nodes[nodeid]; - if (ev.ContainsKey("conn")) { n.conn = (int)ev["conn"]; } - nodes[n.nodeid] = n; - } - if ((onNodesChanged != null) && (nodes != null)) onNodesChanged(false); - } - break; - } - case "usergroupchange": - { - wc.SendString("{\"action\":\"usergroups\"}"); - wc.SendString("{\"action\":\"nodes\"}"); - break; - } - } - break; - } - case "meshes": - { - meshes = new Dictionary(); - - ArrayList meshList = (ArrayList)jsonAction["meshes"]; - for (int i = 0; i < meshList.Count; i++) - { - Dictionary mesh = (Dictionary)meshList[i]; - MeshClass m = new MeshClass(); - m.meshid = (string)mesh["_id"]; - m.name = (string)mesh["name"]; - if (mesh.ContainsKey("desc")) { m.desc = (string)mesh["desc"]; } - m.rights = 0; - m.links = new Dictionary(); - - Dictionary links = ((Dictionary)mesh["links"]); - if (links.ContainsKey(userid)) - { - Dictionary urights = ((Dictionary)links[userid]); - if (urights != null) - { - if (urights["rights"].GetType() == typeof(int)) { m.rights = (ulong)((int)urights["rights"]); } - if (urights["rights"].GetType() == typeof(Int64)) { m.rights = (ulong)((Int64)urights["rights"]); } - } - } - - foreach (string j in links.Keys) - { - Dictionary urights = ((Dictionary)links[j]); - if (urights != null) - { - if (urights["rights"].GetType() == typeof(int)) { m.links[j] = (ulong)((int)urights["rights"]); } - if (urights["rights"].GetType() == typeof(Int64)) { m.links[j] = (ulong)((Int64)urights["rights"]); } - } - } - - if (mesh["mtype"].GetType() == typeof(string)) { m.type = int.Parse((string)mesh["mtype"]); } - if (mesh["mtype"].GetType() == typeof(int)) { m.type = (int)mesh["mtype"]; } - meshes[m.meshid] = m; - } - - break; - } - case "nodes": - { - if (nodes == null) { nodes = new Dictionary(); } - Dictionary nodes2 = new Dictionary(); - lock (nodes) - { - Dictionary groups = (Dictionary)jsonAction["nodes"]; - foreach (string meshid in groups.Keys) - { - ArrayList nodesinMesh = (ArrayList)groups[meshid]; - for (int i = 0; i < nodesinMesh.Count; i++) - { - Dictionary node = (Dictionary)nodesinMesh[i]; - string nodeid = (string)node["_id"]; - if (nodes.ContainsKey(nodeid)) - { - NodeClass n = (NodeClass)nodes[nodeid]; - n.nodeid = nodeid; - if (node.ContainsKey("agent")) - { - n.agentid = (int)((Dictionary)node["agent"])["id"]; - if (((Dictionary)node["agent"]).ContainsKey("caps")) { n.agentcaps = (int)((Dictionary)node["agent"])["caps"]; } else { n.agentcaps = 0; } - } - else - { - n.agentid = -1; - n.agentcaps = 0; - } - n.name = (string)node["name"]; - n.meshid = meshid; - if (node.ContainsKey("mtype")) - { - if (node["mtype"].GetType() == typeof(string)) { n.mtype = int.Parse((string)node["mtype"]); } - if (node["mtype"].GetType() == typeof(int)) { n.mtype = (int)node["mtype"]; } - } - if (node.ContainsKey("users")) { n.users = (string[])((ArrayList)node["users"]).ToArray(typeof(string)); } else { n.users = null; } - if (node.ContainsKey("rdpport")) { n.rdpport = (int)node["rdpport"]; } else { n.rdpport = 3389; } - if (node.ContainsKey("conn")) { n.conn = (int)node["conn"]; } else { n.conn = 0; } - if (node.ContainsKey("icon")) { n.icon = (int)node["icon"]; } - if (n.icon == 0) { n.icon = 1; } - n.rights = 0; - n.links = new Dictionary(); - if (node.ContainsKey("links")) - { - Dictionary links = ((Dictionary)node["links"]); - if (links.ContainsKey(userid)) - { - Dictionary linksEx = ((Dictionary)links[userid]); - if (linksEx.ContainsKey("rights")) { n.rights = (ulong)(int)linksEx["rights"]; } - } - foreach (string j in links.Keys) - { - Dictionary linksEx = ((Dictionary)links[j]); - if (linksEx.ContainsKey("rights")) - { - n.links.Add(j, ulong.Parse(linksEx["rights"].ToString())); - } - } - } - nodes2[n.nodeid] = n; - } - else - { - NodeClass n = new NodeClass(); - n.nodeid = nodeid; - if (node.ContainsKey("agent")) - { - n.agentid = (int)((Dictionary)node["agent"])["id"]; - if (((Dictionary)node["agent"]).ContainsKey("caps")) { n.agentcaps = (int)((Dictionary)node["agent"])["caps"]; } else { n.agentcaps = 0; } - } - else - { - n.agentid = -1; - n.agentcaps = 0; - } - n.name = (string)node["name"]; - n.meshid = meshid; - - if (node.ContainsKey("mtype")) - { - if (node["mtype"].GetType() == typeof(string)) { n.mtype = int.Parse((string)node["mtype"]); } - if (node["mtype"].GetType() == typeof(int)) { n.mtype = (int)node["mtype"]; } - } - if (node.ContainsKey("users")) - { - if (node["users"].GetType() == typeof(ArrayList)) - { - n.users = (string[])((ArrayList)node["users"]).ToArray(typeof(string)); - } - else if (node["users"].GetType() == typeof(Dictionary)) - { - Dictionary users = (Dictionary)node["users"]; - ArrayList users2 = new ArrayList(); - foreach (string u in users.Keys) { if (users[u].GetType() == typeof(string)) { users2.Add((string)users[u]); } } - n.users = (string[])users2.ToArray(typeof(string)); - } - else - { - n.users = null; - } - } - else - { - n.users = null; - } - if (node.ContainsKey("rdpport")) { n.rdpport = (int)node["rdpport"]; } else { n.rdpport = 3389; } - if (node.ContainsKey("conn")) { n.conn = (int)node["conn"]; } else { n.conn = 0; } - if (node.ContainsKey("icon")) { n.icon = (int)node["icon"]; } - if (n.icon == 0) { n.icon = 1; } - n.rights = 0; - n.links = new Dictionary(); - if (node.ContainsKey("links")) - { - Dictionary links = ((Dictionary)node["links"]); - if (links.ContainsKey(userid)) - { - Dictionary linksEx = ((Dictionary)links[userid]); - if (linksEx.ContainsKey("rights")) { n.rights = (ulong)(int)linksEx["rights"]; } - } - foreach (string j in links.Keys) - { - Dictionary linksEx = ((Dictionary)links[j]); - if (linksEx.ContainsKey("rights")) - { - n.links.Add(j, ulong.Parse(linksEx["rights"].ToString())); - } - } - } - nodes2[n.nodeid] = n; - } - } - } - } - nodes = nodes2; - if ((onNodesChanged != null) && (nodes != null)) onNodesChanged(true); - break; - } - case "msg": - { - if (jsonAction.ContainsKey("type")) - { - string type = (string)jsonAction["type"]; - if ((type == "getclip") && (jsonAction.ContainsKey("data")) && (jsonAction.ContainsKey("nodeid"))) - { - // We requested the remote clipboard - string nodeid = (string)jsonAction["nodeid"]; - string clipData = (string)jsonAction["data"]; - if (onClipboardData != null) { onClipboardData(nodeid, clipData); } - } - } - break; - } - case "twoFactorCookie": - { - if (jsonAction.ContainsKey("cookie")) - { - string cookie = (string)jsonAction["cookie"]; - if (onTwoFactorCookie != null) { onTwoFactorCookie(cookie); } - } - break; - } - case "meshToolInfo": - { - if (onToolUpdate == null) return; - if (jsonAction.ContainsKey("hash") && jsonAction.ContainsKey("url")) - { - // MeshCentral Router hash on the server - string hash = (string)jsonAction["hash"]; - - // Hash our own executable - byte[] selfHash; - using (var sha384 = SHA384Managed.Create()) { using (var stream = File.OpenRead(System.Reflection.Assembly.GetEntryAssembly().Location)) { selfHash = sha384.ComputeHash(stream); } } - string selfExecutableHashHex = BitConverter.ToString(selfHash).Replace("-", string.Empty).ToLower(); - - // Get login key - string url = jsonAction["url"] + "&auth=" + authCookie; - if (url.StartsWith("*/")) { url = "https://" + wsurl.Authority + url.Substring(1); } - string loginkey = getValueFromQueryString(wsurl.Query, "key"); - if (loginkey != null) { url += ("&key=" + loginkey); } - - // Server TLS certificate hash - string serverhash = null; - if (jsonAction.ContainsKey("serverhash")) { serverhash = jsonAction["serverhash"].ToString(); } - - // If the hashes don't match, event the tool update with URL - if (selfExecutableHashHex != hash) { onToolUpdate((string)url, (string)jsonAction["hash"], (int)jsonAction["size"], serverhash); } - } - break; - } - default: - { - break; - } - } - } catch (Exception ex) - { - if (debug) { try { File.AppendAllText("debug.log", ex.ToString() + "\r\n"); } catch (Exception) { } } - } - } - - private static string getValueFromQueryString(string query, string name) - { - if ((query == null) || (name == null)) return null; - int i = query.IndexOf("?" + name + "="); - if (i == -1) { i = query.IndexOf("&" + name + "="); } - if (i == -1) return null; - string r = query.Substring(i + name.Length + 2); - i = r.IndexOf("&"); - if (i >= 0) { r = r.Substring(0, i); } - return r; - } - - public delegate void onStateChangedHandler(int state); - public event onStateChangedHandler onStateChanged; - public void changeState(int newState) { if (constate != newState) { constate = newState; if (onStateChanged != null) { onStateChanged(constate); } } } - - private void changeStateEx(webSocketClient sender, webSocketClient.ConnectionStates newState) - { - if (newState == webSocketClient.ConnectionStates.Disconnected) { - if (sender.failedTlsCert != null) { certHash = null; disconnectMsg = "cert"; disconnectCert = sender.failedTlsCert; } - changeState(0); - } - if (newState == webSocketClient.ConnectionStates.Connecting) { changeState(1); } - if (newState == webSocketClient.ConnectionStates.Connected) { } - } - - public delegate void onNodeListChangedHandler(bool fullRefresh); - public event onNodeListChangedHandler onNodesChanged; - public delegate void onLoginTokenChangedHandler(); - public event onLoginTokenChangedHandler onLoginTokenChanged; - public delegate void onClipboardDataHandler(string nodeid, string data); - public event onClipboardDataHandler onClipboardData; - public delegate void twoFactorCookieHandler(string cookie); - public event twoFactorCookieHandler onTwoFactorCookie; - public delegate void toolUpdateHandler(string url, string hash, int size, string serverhash); - public event toolUpdateHandler onToolUpdate; - - private MeshCentralServer parent = null; - private TcpClient wsclient = null; - private SslStream wsstream = null; - private NetworkStream wsrawstream = null; - private int state = 0; - private Uri url = null; - private byte[] readBuffer = new Byte[500]; - private int readBufferLen = 0; - private int accopcodes = 0; - private bool accmask = false; - private int acclen = 0; - private bool proxyInUse = false; - private Uri proxyUri = null; - private string user = null; - private string pass = null; - private string token = null; - public bool xdebug = false; - public bool xtlsdump = false; - public bool xignoreCert = false; - - public void Dispose() { - try { wsstream.Close(); } catch (Exception) { } - try { wsstream.Dispose(); } catch (Exception) { } - wsstream = null; - wsclient = null; - state = -1; - parent.changeState(0); - parent.wshash = null; - } - - public void Debug(string msg) { if (xdebug) { try { File.AppendAllText("debug.log", "Debug-" + msg + "\r\n"); } catch (Exception) { } } } - public void TlsDump(string direction, byte[] data, int offset, int len) { if (xtlsdump) { try { File.AppendAllText("debug.log", direction + ": " + BitConverter.ToString(data, offset, len).Replace("-", string.Empty) + "\r\n"); } catch (Exception) { } } } - - public bool Start(MeshCentralServer parent, Uri url, string user, string pass, string token, string fingerprint) - { - if (state != 0) return false; - parent.changeState(1); - state = 1; - this.parent = parent; - this.url = url; - this.user = user; - this.pass = pass; - this.token = token; - this.proxyUri = null; - - this.proxyUri = Win32Api.GetProxy(url); - - if (proxyUri != null) - { - // Proxy in use - proxyInUse = true; - wsclient = new TcpClient(); - // This may log proxy password to debug log - Debug("Connecting with proxy in use: " + proxyUri.ToString()); - wsclient.BeginConnect(proxyUri.Host, proxyUri.Port, new AsyncCallback(OnConnectSink), this); - } - else - { - // No proxy in use - proxyInUse = false; - wsclient = new TcpClient(); - Debug("Connecting without proxy"); - wsclient.BeginConnect(url.Host, url.Port, new AsyncCallback(OnConnectSink), this); - } - return true; - } - - private void OnConnectSink(IAsyncResult ar) - { - if (wsclient == null) return; - - // Accept the connection - try - { - wsclient.EndConnect(ar); - } catch (Exception ex) { - Debug("Websocket TCP failed to connect: " + ex.ToString()); - Dispose(); - return; - } - - if (proxyInUse == true) - { - // Send proxy connection request - wsrawstream = wsclient.GetStream(); - string userCreds = proxyUri.UserInfo; - string basicAuth = ""; - if (userCreds.Length > 0) - { - // Base64 encode for basic authentication - userCreds = System.Convert.ToBase64String(Encoding.GetEncoding("ISO-8859-1").GetBytes(userCreds)); - basicAuth = "\r\nProxy-Authorization: Basic " + userCreds; - } - - byte[] proxyRequestBuf = UTF8Encoding.UTF8.GetBytes("CONNECT " + url.Host + ":" + url.Port + " HTTP/1.1\r\nHost: " + url.Host + ":" + url.Port + basicAuth + "\r\n\r\n"); - TlsDump("OutRaw", proxyRequestBuf, 0, proxyRequestBuf.Length); - try { wsrawstream.Write(proxyRequestBuf, 0, proxyRequestBuf.Length); } catch (Exception ex) { Debug(ex.ToString()); } - wsrawstream.BeginRead(readBuffer, readBufferLen, readBuffer.Length - readBufferLen, new AsyncCallback(OnProxyResponseSink), this); - } - else - { - // Start TLS connection - Debug("Websocket TCP connected, doing TLS..."); - wsstream = new SslStream(wsclient.GetStream(), false, VerifyServerCertificate, null); - wsstream.BeginAuthenticateAsClient(url.Host, null, System.Security.Authentication.SslProtocols.Tls12, false, new AsyncCallback(OnTlsSetupSink), this); - } - } - - private void OnProxyResponseSink(IAsyncResult ar) - { - if (wsrawstream == null) return; - - int len = 0; - try { len = wsrawstream.EndRead(ar); } catch (Exception) { } - if (len == 0) - { - // Disconnect - Debug("Websocket proxy disconnected, length = 0."); - Dispose(); - return; - } - - TlsDump("InRaw", readBuffer, 0, readBufferLen); - - readBufferLen += len; - string proxyResponse = UTF8Encoding.UTF8.GetString(readBuffer, 0, readBufferLen); - if (proxyResponse.IndexOf("\r\n\r\n") >= 0) - { - // We get a full proxy response, we should get something like "HTTP/1.1 200 Connection established\r\n\r\n" - if (proxyResponse.StartsWith("HTTP/1.1 200 ")) - { - // All good, start TLS setup. - readBufferLen = 0; - Debug("Websocket TCP connected, doing TLS..."); - wsstream = new SslStream(wsrawstream, false, VerifyServerCertificate, null); - wsstream.BeginAuthenticateAsClient(url.Host, null, System.Security.Authentication.SslProtocols.Tls12, false, new AsyncCallback(OnTlsSetupSink), this); - } - else - { - // Invalid response - Debug("Proxy connection failed: " + proxyResponse); - Dispose(); - } - } else { - if (readBufferLen == readBuffer.Length) - { - // Buffer overflow - Debug("Proxy connection failed"); - Dispose(); - } - else - { - // Read more proxy data - wsrawstream.BeginRead(readBuffer, readBufferLen, readBuffer.Length - readBufferLen, new AsyncCallback(OnProxyResponseSink), this); - } - } - } - - public string Base64Encode(string plainText) - { - var plainTextBytes = System.Text.Encoding.UTF8.GetBytes(plainText); - return System.Convert.ToBase64String(plainTextBytes); - } - - public string Base64Decode(string base64EncodedData) - { - var base64EncodedBytes = System.Convert.FromBase64String(base64EncodedData); - return System.Text.Encoding.UTF8.GetString(base64EncodedBytes); - } - - private void OnTlsSetupSink(IAsyncResult ar) - { - if (wsstream == null) return; - - // Accept the connection - try - { - wsstream.EndAuthenticateAsClient(ar); - } - catch (Exception ex) - { - // Disconnect - if (ex.InnerException != null) { - MessageBox.Show(ex.Message + ", Inner: " + ex.InnerException.ToString(), "MeshCentral Router"); - } else { - MessageBox.Show(ex.Message, "MeshCentral Router"); - } - Debug("Websocket TLS failed: " + ex.ToString()); - Dispose(); - return; - } - - // Fetch remote certificate - parent.wshash = wsstream.RemoteCertificate.GetCertHashString(); - - // Setup extra headers if needed - string extraHeaders = ""; - if (user != null && pass != null && token != null) { extraHeaders = "x-meshauth: " + Base64Encode(user) + "," + Base64Encode(pass) + "," + Base64Encode(token) + "\r\n"; } - else if (user != null && pass != null) { extraHeaders = "x-meshauth: " + Base64Encode(user) + "," + Base64Encode(pass) + "\r\n"; } - - // Send the HTTP headers - Debug("Websocket TLS setup, sending HTTP header..."); - string header = "GET " + url.PathAndQuery + " HTTP/1.1\r\nHost: " + url.Host + "\r\nUpgrade: websocket\r\nConnection: Upgrade\r\nSec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==\r\nSec-WebSocket-Version: 13\r\n" + extraHeaders + "\r\n"; - try { wsstream.Write(UTF8Encoding.UTF8.GetBytes(header)); } catch (Exception ex) { Debug(ex.ToString()); } - - // Start receiving data - wsstream.BeginRead(readBuffer, readBufferLen, readBuffer.Length - readBufferLen, new AsyncCallback(OnTlsDataSink), this); - } - - private void OnTlsDataSink(IAsyncResult ar) - { - if (wsstream == null) return; - - int len = 0; - try { len = wsstream.EndRead(ar); } catch (Exception) { } - if (len == 0) - { - // Disconnect - Debug("Websocket disconnected, length = 0."); - Dispose(); - return; - } - //parent.Debug("#" + counter + ": Websocket got new data: " + len); - readBufferLen += len; - TlsDump("In", readBuffer, 0, len); - - // Consume all of the data - int consumed = 0; - int ptr = 0; - do - { - consumed = ProcessBuffer(readBuffer, ptr, readBufferLen - ptr); - if (consumed < 0) { Dispose(); return; } // Error, close the connection - ptr += consumed; - } while ((consumed > 0) && ((readBufferLen - consumed) > 0)); - - // Move the data forward - if ((ptr > 0) && (readBufferLen - ptr) > 0) { - //Console.Write("MOVE FORWARD\r\n"); - Array.Copy(readBuffer, ptr, readBuffer, 0, (readBufferLen - ptr)); - } - readBufferLen = (readBufferLen - ptr); - - // If the buffer is too small, double the size here. - if (readBuffer.Length - readBufferLen == 0) - { - Debug("Increasing the read buffer size from " + readBuffer.Length + " to " + (readBuffer.Length * 2) + "."); - byte[] readBuffer2 = new byte[readBuffer.Length * 2]; - Array.Copy(readBuffer, 0, readBuffer2, 0, readBuffer.Length); - readBuffer = readBuffer2; - } - - // Receive more data - try { wsstream.BeginRead(readBuffer, readBufferLen, readBuffer.Length - readBufferLen, new AsyncCallback(OnTlsDataSink), this); } catch (Exception) { } - } - - private int ProcessBuffer(byte[] buffer, int offset, int len) - { - string ss = UTF8Encoding.UTF8.GetString(buffer, offset, len); - - if (state == 1) - { - // Look for the end of the http header - string header = UTF8Encoding.UTF8.GetString(buffer, offset, len); - int i = header.IndexOf("\r\n\r\n"); - if (i == -1) return 0; - Dictionary parsedHeader = ParseHttpHeader(header.Substring(0, i)); - if ((parsedHeader == null) || (parsedHeader["_Path"] != "101")) { Debug("Websocket bad header."); return -1; } // Bad header, close the connection - Debug("Websocket got setup upgrade header."); - state = 2; - return len; // TODO: Technically we need to return the header length before UTF8 convert. - } else if (state == 2) { - // Parse a websocket fragment header - if (len < 2) return 0; - int headsize = 2; - accopcodes = buffer[offset]; - accmask = ((buffer[offset + 1] & 0x80) != 0); - acclen = (buffer[offset + 1] & 0x7F); - - if ((accopcodes & 0x0F) == 8) - { - // Close the websocket - Debug("Websocket got closed fragment."); - return -1; - } - - if (acclen == 126) - { - if (len < 4) return 0; - headsize = 4; - acclen = (buffer[offset + 2] << 8) + (buffer[offset + 3]); - } - else if (acclen == 127) - { - if (len < 10) return 0; - headsize = 10; - acclen = (buffer[offset + 6] << 24) + (buffer[offset + 7] << 16) + (buffer[offset + 8] << 8) + (buffer[offset + 9]); - Debug("Websocket receive large fragment: " + acclen); - } - if (accmask == true) - { - // TODO: Do unmasking here. - headsize += 4; - } - //parent.Debug("#" + counter + ": Websocket frag header - FIN: " + ((accopcodes & 0x80) != 0) + ", OP: " + (accopcodes & 0x0F) + ", LEN: " + acclen + ", MASK: " + accmask); - state = 3; - return headsize; - } - else if (state == 3) - { - // Parse a websocket fragment data - if (len < acclen) return 0; - //Console.Write("WSREAD: " + acclen + "\r\n"); - ProcessWsBuffer(buffer, offset, acclen, accopcodes); - state = 2; - return acclen; - } - return 0; - } - - private void ProcessWsBuffer(byte[] data, int offset, int len, int op) - { - Debug("Websocket got data."); - //try { parent.processServerData(UTF8Encoding.UTF8.GetString(data, offset, len)); } catch (Exception ex) { } - parent.processServerData(UTF8Encoding.UTF8.GetString(data, offset, len)); - } - - private Dictionary ParseHttpHeader(string header) - { - string[] lines = header.Replace("\r\n", "\r").Split('\r'); - if (lines.Length < 2) { return null; } - string[] directive = lines[0].Split(' '); - Dictionary values = new Dictionary(); - values["_Action"] = directive[0]; - values["_Path"] = directive[1]; - values["_Protocol"] = directive[2]; - for (int i = 1; i < lines.Length; i++) - { - var j = lines[i].IndexOf(":"); - values[lines[i].Substring(0, j).ToLower()] = lines[i].Substring(j + 1).Trim(); - } - return values; - } - - // Return a modified base64 SHA384 hash string of the certificate public key - public static string GetMeshKeyHash(X509Certificate cert) - { - return ByteArrayToHexString(new SHA384Managed().ComputeHash(cert.GetPublicKey())); - } - - // Return a modified base64 SHA384 hash string of the certificate - public static string GetMeshCertHash(X509Certificate cert) - { - return ByteArrayToHexString(new SHA384Managed().ComputeHash(cert.GetRawCertData())); - } - - public static string ByteArrayToHexString(byte[] Bytes) - { - StringBuilder Result = new StringBuilder(Bytes.Length * 2); - string HexAlphabet = "0123456789ABCDEF"; - foreach (byte B in Bytes) { Result.Append(HexAlphabet[(int)(B >> 4)]); Result.Append(HexAlphabet[(int)(B & 0xF)]); } - return Result.ToString(); - } - - private bool VerifyServerCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors) - { - parent.certHash = GetMeshKeyHash(certificate); - Debug("Verify cert: " + parent.certHash); - if (xignoreCert) return true; - if (chain.Build(new X509Certificate2(certificate)) == true) return true; - - // Check that the remote certificate is the expected one - if ((parent.okCertHash != null) && (parent.okCertHash == certificate.GetCertHashString())) return true; - - // Check that the remote certificate is the expected one - if ((parent.okCertHash2 != null) && ((parent.okCertHash2 == GetMeshKeyHash(certificate)) || (parent.okCertHash2 == GetMeshCertHash(certificate)))) { return true; } - - parent.certHash = null; - parent.disconnectMsg = "cert"; - parent.disconnectCert = new X509Certificate2(certificate); - return false; - } - - public void WriteStringWebSocket(string data) - { - // Convert the string into a buffer with 4 byte of header space. - int len = UTF8Encoding.UTF8.GetByteCount(data); - byte[] buf = new byte[4 + len]; - UTF8Encoding.UTF8.GetBytes(data, 0, data.Length, buf, 4); - len = buf.Length - 4; - - // Check that everything is ok - if ((state < 2) || (len < 1) || (len > 65535)) { Dispose(); return; } - - //Console.Write("Length: " + len + "\r\n"); - //System.Threading.Thread.Sleep(0); - - if (len < 126) - { - // Small fragment - buf[2] = 130; // Fragment op code (129 = text, 130 = binary) - buf[3] = (byte)(len & 0x7F); - //try { wsstream.BeginWrite(buf, 2, len + 2, new AsyncCallback(WriteWebSocketAsyncDone), args); } catch (Exception) { Dispose(); return; } - TlsDump("Out", buf, 2, len + 2); - try { wsstream.Write(buf, 2, len + 2); } catch (Exception ex) { Debug(ex.ToString()); } - } - else - { - // Large fragment - buf[0] = 130; // Fragment op code (129 = text, 130 = binary) - buf[1] = 126; - buf[2] = (byte)((len >> 8) & 0xFF); - buf[3] = (byte)(len & 0xFF); - //try { wsstream.BeginWrite(buf, 0, len + 4, new AsyncCallback(WriteWebSocketAsyncDone), args); } catch (Exception) { Dispose(); return; } - TlsDump("Out", buf, 0, len + 4); - try { wsstream.Write(buf, 0, len + 4); } catch (Exception ex) { Debug(ex.ToString()); } - } - } - - } -} \ No newline at end of file diff --git a/src/FileViewer.cs b/src/FileViewer.cs index 559f07a..553849e 100644 --- a/src/FileViewer.cs +++ b/src/FileViewer.cs @@ -1539,7 +1539,7 @@ namespace MeshCentralRouter private void uploadNextPart(bool dataPriming) { if(uploadActive == false) return; - byte[] buffer = new byte[16385]; + byte[] buffer = new byte[65565]; int len = uploadFileStream.Read(buffer, 1, buffer.Length - 1); if(dataPriming && (len == 0)) return; uploadFilePtr += len; diff --git a/src/KVMControl.cs b/src/KVMControl.cs index e456d8c..ef0f074 100644 --- a/src/KVMControl.cs +++ b/src/KVMControl.cs @@ -965,7 +965,9 @@ namespace MeshCentralRouter private IntPtr captureKey(int nCode, IntPtr wp, IntPtr lp) { bool bIsForegroundWindow = false; - try { bIsForegroundWindow = GetForegroundWindow() == this.ParentForm.Handle; } catch { } + if(this.ParentForm != null) { + try { bIsForegroundWindow = GetForegroundWindow() == this.ParentForm.Handle; } catch { } + } if(nCode >= 0 && bIsForegroundWindow) { KBDLLHOOKSTRUCT objKeyInfo = (KBDLLHOOKSTRUCT)Marshal.PtrToStructure(lp, typeof(KBDLLHOOKSTRUCT));