From 2485ca8225d380ae6237df131998d4c710889949 Mon Sep 17 00:00:00 2001 From: Ylian Saint-Hilaire Date: Fri, 26 Mar 2021 02:03:22 -0700 Subject: [PATCH] Version 1.6 --- LocalPipe.cs | 86 ++++++++++++++++++++++++++++++++++++++ MainForm.cs | 61 +++++++++++++++++++++++++++ MeshCentralRouter.csproj | 1 + Program.cs | 11 +++++ Properties/AssemblyInfo.cs | 2 +- 5 files changed, 160 insertions(+), 1 deletion(-) create mode 100644 LocalPipe.cs diff --git a/LocalPipe.cs b/LocalPipe.cs new file mode 100644 index 0000000..bc06bdb --- /dev/null +++ b/LocalPipe.cs @@ -0,0 +1,86 @@ +using System; +using System.Collections.Generic; +using System.IO.Pipes; +using System.Linq; +using System.Security.Principal; +using System.Text; +using System.Threading.Tasks; + +namespace MeshCentralRouter +{ + public class LocalPipeServer + { + private String name; + private byte[] buffer = new byte[4096]; + private NamedPipeServerStream pipeServer; + + public delegate void onArgsHandler(string args); + public event onArgsHandler onArgs; + + public LocalPipeServer(string name) + { + this.name = name; + pipeServer = new NamedPipeServerStream(name, PipeDirection.InOut, 1, PipeTransmissionMode.Message, PipeOptions.Asynchronous); + pipeServer.BeginWaitForConnection(new AsyncCallback(processConnection), null); + } + + public void Dispose() + { + try { pipeServer.Close(); } catch (Exception) { } + pipeServer = null; + } + + private void processConnection(IAsyncResult ar) + { + try { pipeServer.EndWaitForConnection(ar); } catch (Exception) { } + try { pipeServer.BeginRead(buffer, 0, buffer.Length, new AsyncCallback(processRead), null); } catch (Exception) { } + } + + + private void processRead(IAsyncResult ar) + { + int len = 0; + try { len = pipeServer.EndRead(ar); } catch (Exception) { } + if (len > 0) + { + string args = UTF8Encoding.UTF8.GetString(buffer, 0, len); + pipeServer.Close(); + onArgs(args); + pipeServer = new NamedPipeServerStream(name, PipeDirection.InOut, 1, PipeTransmissionMode.Message, PipeOptions.Asynchronous); + pipeServer.BeginWaitForConnection(new AsyncCallback(processConnection), null); + } + } + + } + + + public class LocalPipeClient + { + private byte[] buffer = new byte[4096]; + private NamedPipeClientStream pipeClient; + + public LocalPipeClient(string name) + { + pipeClient = new NamedPipeClientStream(".", name, PipeDirection.InOut, PipeOptions.Asynchronous, TokenImpersonationLevel.None); + } + + public bool TrySendingArguments(string args) + { + try + { + byte[] buf = UTF8Encoding.UTF8.GetBytes(args); + pipeClient.Connect(10); + pipeClient.BeginWrite(buf, 0, buf.Length, new AsyncCallback(processWrite), null); + } + catch (Exception) { return false; } + return true; + } + + private void processWrite(IAsyncResult ar) + { + try { pipeClient.EndWrite(ar); } catch (Exception) { } + pipeClient.Close(); + } + } + +} diff --git a/MainForm.cs b/MainForm.cs index a33ff10..99f8f46 100644 --- a/MainForm.cs +++ b/MainForm.cs @@ -28,6 +28,7 @@ using System.Web.Script.Serialization; using System.Security.Cryptography.X509Certificates; using Microsoft.Win32; using System.Drawing; +using System.Text; namespace MeshCentralRouter { @@ -55,6 +56,7 @@ namespace MeshCentralRouter public Process autoExitProc = null; public int deviceDoubleClickAction = 0; public FileInfo nativeSshPath = null; + public LocalPipeServer localPipeServer = null; public bool isRouterHooked() { @@ -835,6 +837,9 @@ namespace MeshCentralRouter } } + // Clean up single instance pipe server + if (localPipeServer != null) { localPipeServer.Dispose(); localPipeServer = null; } + // Clean up the server cookieRefreshTimer.Enabled = false; meshcentral.onStateChanged -= Meshcentral_onStateChanged; @@ -868,6 +873,62 @@ namespace MeshCentralRouter // If we need to remember the 2nd factor, ask for a cookie now. if (tokenRememberCheckBox.Checked) { meshcentral.sendCommand("{\"action\":\"twoFactorCookie\"}"); } + + // Setup single instance pipe server + if (authLoginUrl != null) { + string urlstring = "wss://" + authLoginUrl.Host + ":" + ((authLoginUrl.Port > 0) ? authLoginUrl.Port : 443) + authLoginUrl.LocalPath; + localPipeServer = new LocalPipeServer(Convert.ToBase64String(UTF8Encoding.UTF8.GetBytes(urlstring))); // + "" + meshcentral.certHash + localPipeServer.onArgs += LocalPipeServer_onArgs; + } + } + } + + private delegate void LocalPipeServerOnArgsHandler(string args); + + private void LocalPipeServer_onArgs(string args) + { + if (args.StartsWith("mcrouter://") == false) return; + if (this.InvokeRequired) { this.Invoke(new LocalPipeServerOnArgsHandler(LocalPipeServer_onArgs), args); return; } + + Uri authLoginUrl2 = new Uri(args); + + // Set automatic port map values + if (authLoginUrl2 != null) + { + string autoNodeId = null; + string autoRemoteIp = null; + int autoRemotePort = 0; + int autoProtocol = 0; + int autoAppId = 0; + bool autoExit = false; + try + { + // Automatic mappings + autoNodeId = getValueFromQueryString(authLoginUrl2.Query, "nodeid"); + autoRemoteIp = getValueFromQueryString(authLoginUrl2.Query, "remoteip"); + autoRemotePort = int.Parse(getValueFromQueryString(authLoginUrl2.Query, "remoteport")); + autoProtocol = int.Parse(getValueFromQueryString(authLoginUrl2.Query, "protocol")); + autoAppId = int.Parse(getValueFromQueryString(authLoginUrl2.Query, "appid")); + autoExit = (getValueFromQueryString(authLoginUrl2.Query, "autoexit") == "1"); + } + catch (Exception) { } + if ((autoRemotePort != 0) && (autoProtocol != 0) && (autoNodeId != null)) + { + Dictionary map = new Dictionary(); + map.Add("nodeId", autoNodeId); + if (autoRemoteIp != null) { map.Add("remoteIP", autoRemoteIp); } + map.Add("remotePort", autoRemotePort); + map.Add("localPort", 0); + map.Add("protocol", autoProtocol); + map.Add("appId", autoAppId); + map.Add("autoExit", autoExit); + map.Add("launch", 1); + mappingsToSetup = new ArrayList(); + mappingsToSetup.Add(map); + devicesTabControl.SelectedIndex = 1; + setupMappings(); + cancelAutoClose(); + } } } diff --git a/MeshCentralRouter.csproj b/MeshCentralRouter.csproj index 72f34ad..e24969f 100644 --- a/MeshCentralRouter.csproj +++ b/MeshCentralRouter.csproj @@ -94,6 +94,7 @@ AddRelayMapForm.cs + Form diff --git a/Program.cs b/Program.cs index b5d11f2..877399a 100644 --- a/Program.cs +++ b/Program.cs @@ -16,6 +16,7 @@ limitations under the License. using System; using System.IO; +using System.Text; using System.Windows.Forms; namespace MeshCentralRouter @@ -28,6 +29,7 @@ namespace MeshCentralRouter [STAThread] static void Main(string[] args) { + Uri authLoginUrl = null; // Setup settings & visual style Application.EnableVisualStyles(); @@ -43,6 +45,15 @@ namespace MeshCentralRouter if (arg.Length > 3 && string.Compare(arg.Substring(0, 3), "-l:", true) == 0) { try { System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo(arg.Substring(3)); } catch (ArgumentException) { } } + if (arg.Length > 11 && arg.Substring(0, 11).ToLower() == "mcrouter://") { authLoginUrl = new Uri(arg); } + } + + // Setup single instance pipe client + if (authLoginUrl != null) + { + string urlstring = "wss://" + authLoginUrl.Host + ":" + ((authLoginUrl.Port > 0) ? authLoginUrl.Port : 443) + authLoginUrl.LocalPath; + LocalPipeClient localPipeClient = new LocalPipeClient(Convert.ToBase64String(UTF8Encoding.UTF8.GetBytes(urlstring))); // + "" + meshcentral.certHash + if (localPipeClient.TrySendingArguments(authLoginUrl.ToString()) == true) { Application.Exit(); return; } } MainForm main; diff --git a/Properties/AssemblyInfo.cs b/Properties/AssemblyInfo.cs index fee1fd9..fad8751 100644 --- a/Properties/AssemblyInfo.cs +++ b/Properties/AssemblyInfo.cs @@ -31,6 +31,6 @@ using System.Runtime.InteropServices; // // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: -[assembly: AssemblyVersion("1.5.*")] +[assembly: AssemblyVersion("1.6.*")] //[assembly: AssemblyVersion("1.0.0.0")] //[assembly: AssemblyFileVersion("1.0.0.0")]