aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/embeddable-dll-service
diff options
context:
space:
mode:
Diffstat (limited to 'embeddable-dll-service')
-rw-r--r--embeddable-dll-service/.gitignore4
-rw-r--r--embeddable-dll-service/README.md47
-rw-r--r--embeddable-dll-service/build.bat16
-rw-r--r--embeddable-dll-service/csharp/.gitignore3
-rw-r--r--embeddable-dll-service/csharp/DemoUI/MainWindow.Designer.cs87
-rw-r--r--embeddable-dll-service/csharp/DemoUI/MainWindow.cs215
-rw-r--r--embeddable-dll-service/csharp/DemoUI/MainWindow.resx60
-rw-r--r--embeddable-dll-service/csharp/DemoUI/Program.cs44
-rw-r--r--embeddable-dll-service/csharp/DemoUI/app.manifest48
-rw-r--r--embeddable-dll-service/csharp/Program.cs92
-rw-r--r--embeddable-dll-service/csharp/README.md7
-rw-r--r--embeddable-dll-service/csharp/TunnelDll/Driver.cs234
-rw-r--r--embeddable-dll-service/csharp/TunnelDll/Keypair.cs (renamed from embeddable-dll-service/csharp/Keypair.cs)4
-rw-r--r--embeddable-dll-service/csharp/TunnelDll/Ringlogger.cs (renamed from embeddable-dll-service/csharp/Ringlogger.cs)2
-rw-r--r--embeddable-dll-service/csharp/TunnelDll/Service.cs (renamed from embeddable-dll-service/csharp/Service.cs)36
-rw-r--r--embeddable-dll-service/csharp/TunnelDll/Win32.cs (renamed from embeddable-dll-service/csharp/Win32.cs)54
-rw-r--r--embeddable-dll-service/csharp/demo-client.csproj14
-rw-r--r--embeddable-dll-service/csharp/demo-client.csproj.user8
-rw-r--r--embeddable-dll-service/csharp/demo-client.sln25
-rw-r--r--embeddable-dll-service/main.go15
20 files changed, 861 insertions, 154 deletions
diff --git a/embeddable-dll-service/.gitignore b/embeddable-dll-service/.gitignore
new file mode 100644
index 00000000..9e3c52ab
--- /dev/null
+++ b/embeddable-dll-service/.gitignore
@@ -0,0 +1,4 @@
+# Build Output
+/x86
+/amd64
+/arm64
diff --git a/embeddable-dll-service/README.md b/embeddable-dll-service/README.md
index 3ac0dbae..a326dc70 100644
--- a/embeddable-dll-service/README.md
+++ b/embeddable-dll-service/README.md
@@ -1,19 +1,21 @@
## Embeddable WireGuard Tunnel Library
-This allows embedding WireGuard as a service inside of another application. Build `tunnel.dll` by running `./build.bat` in this folder. The first time you run it, it will invoke `..\build.bat` simply for downloading dependencies. After, you should have `amd64/tunnel.dll` and `x86/tunnel.dll`.
+This allows embedding WireGuard as a service inside of another application. Build `tunnel.dll` by running `./build.bat` in this folder. The first time you run it, it will invoke `..\build.bat` simply for downloading dependencies. After, you should have `amd64/tunnel.dll`, `x86/tunnel.dll`, and `arm64/tunnel.dll`. In addition, `tunnel.dll` requires `wireguard.dll`, which can be downloaded from [the wireguard-nt download server](https://download.wireguard.com/wireguard-nt/).
The basic setup to use `tunnel.dll` is:
##### 1. Install a service with these parameters:
- Service Name: "SomeServiceName"
- Display Name: "Some Service Name"
- Service Type: SERVICE_WIN32_OWN_PROCESS
- Start Type: StartAutomatic
- Error Control: ErrorNormal,
- Dependencies: [ "Nsi" ]
- Sid Type: SERVICE_SID_TYPE_UNRESTRICTED
- Executable: "C:\path\to\example\vpnclient.exe /service configfile.conf"
+```text
+Service Name: "WireGuardTunnel$SomeTunnelName"
+Display Name: "Some Service Name"
+Service Type: SERVICE_WIN32_OWN_PROCESS
+Start Type: StartAutomatic
+Error Control: ErrorNormal,
+Dependencies: [ "Nsi", "TcpIp" ]
+Sid Type: SERVICE_SID_TYPE_UNRESTRICTED
+Executable: "C:\path\to\example\vpnclient.exe /service configfile.conf"
+```
Some of these may have to be changed with `ChangeServiceConfig2` after the
initial call to `CreateService` The `SERVICE_SID_TYPE_UNRESTRICTED` parameter
@@ -21,22 +23,19 @@ is absolutely essential; do not forget it.
##### 2. Have your program's main function handle the `/service` switch:
- if (!strcmp(argv[1], "/service") && argc == 3) {
- HMODULE tunnel_lib = LoadLibrary("tunnel.dll");
- if (!tunnel_lib)
- abort();
- tunnel_proc_t tunnel_proc = (tunnel_proc_t)GetProcAddress(tunnel_lib, "WireGuardTunnelService");
- if (!tunnel_proc)
- abort();
- struct go_string conf_file = {
- .str = argv[2],
- .n = strlen(argv[2])
- };
- return tunnel_proc(conf_file);
- }
+```c
+if (wargc == 3 && !wcscmp(wargv[1], L"/service")) {
+ HMODULE tunnel_lib = LoadLibrary("tunnel.dll");
+ if (!tunnel_lib)
+ abort();
+ BOOL (_cdecl *tunnel_proc)(_In_ LPCWSTR conf_file);
+ *(FARPROC*)&tunnel_proc = GetProcAddress(tunnel_lib, "WireGuardTunnelService");
+ if (!tunnel_proc)
+ abort();
+ return tunnel_proc(wargv[2]);
+}
+```
##### 3. Scoop up logs by implementing a ringlogger format reader.
-##### 4. Talk to the service over its named pipe.
-
There is a sample implementation of bits and pieces of this inside of the `csharp\` directory.
diff --git a/embeddable-dll-service/build.bat b/embeddable-dll-service/build.bat
index cae35f70..f1001192 100644
--- a/embeddable-dll-service/build.bat
+++ b/embeddable-dll-service/build.bat
@@ -1,10 +1,10 @@
@echo off
rem SPDX-License-Identifier: MIT
-rem Copyright (C) 2019 WireGuard LLC. All Rights Reserved.
+rem Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
setlocal
set BUILDDIR=%~dp0
-set PATH=%BUILDDIR%..\.deps\go\bin;%BUILDDIR%..\.deps;%PATH%
+set PATH=%BUILDDIR%..\.deps\llvm-mingw\bin;%BUILDDIR%..\.deps\go\bin;%PATH%
set PATHEXT=.exe
cd /d %BUILDDIR% || exit /b 1
@@ -14,21 +14,27 @@ if exist ..\.deps\prepared goto :build
:build
set GOOS=windows
+ set GOARM=7
set GOPATH=%BUILDDIR%..\.deps\gopath
set GOROOT=%BUILDDIR%..\.deps\go
set CGO_ENABLED=1
set CGO_CFLAGS=-O3 -Wall -Wno-unused-function -Wno-switch -std=gnu11 -DWINVER=0x0601
- set CGO_LDFLAGS=-Wl,--dynamicbase -Wl,--nxcompat -Wl,--export-all-symbols
call :build_plat x86 i686 386 || goto :error
- set CGO_LDFLAGS=%CGO_LDFLAGS% -Wl,--high-entropy-va
call :build_plat amd64 x86_64 amd64 || goto :error
+ call :build_plat arm64 aarch64 arm64 || goto :error
+
+:sign
+ if exist ..\sign.bat call ..\sign.bat
+ if "%SigningProvider%"=="" goto :success
+ if "%TimestampServer%"=="" goto :success
+ echo [+] Signing
+ signtool sign %SigningProvider% /fd sha256 /tr "%TimestampServer%" /td sha256 /d "WireGuard Tunnel" x86\tunnel.dll amd64\tunnel.dll arm64\tunnel.dll || goto :error
:success
echo [+] Success
exit /b 0
:build_plat
- set PATH=%BUILDDIR%..\.deps\%~2-w64-mingw32-native\bin;%PATH%
set CC=%~2-w64-mingw32-gcc
set GOARCH=%~3
mkdir %1 >NUL 2>&1
diff --git a/embeddable-dll-service/csharp/.gitignore b/embeddable-dll-service/csharp/.gitignore
new file mode 100644
index 00000000..28bcb4ab
--- /dev/null
+++ b/embeddable-dll-service/csharp/.gitignore
@@ -0,0 +1,3 @@
+/.vs
+/bin
+/obj
diff --git a/embeddable-dll-service/csharp/DemoUI/MainWindow.Designer.cs b/embeddable-dll-service/csharp/DemoUI/MainWindow.Designer.cs
new file mode 100644
index 00000000..5aad1b97
--- /dev/null
+++ b/embeddable-dll-service/csharp/DemoUI/MainWindow.Designer.cs
@@ -0,0 +1,87 @@
+/* SPDX-License-Identifier: MIT
+ *
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
+ */
+
+namespace DemoUI
+{
+ partial class MainWindow
+ {
+ /// <summary>
+ /// Required designer variable.
+ /// </summary>
+ private System.ComponentModel.IContainer components = null;
+
+ /// <summary>
+ /// Clean up any resources being used.
+ /// </summary>
+ /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing && (components != null))
+ {
+ components.Dispose();
+ }
+ base.Dispose(disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ /// <summary>
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ /// </summary>
+ private void InitializeComponent()
+ {
+ this.connectButton = new System.Windows.Forms.Button();
+ this.logBox = new System.Windows.Forms.TextBox();
+ this.SuspendLayout();
+ //
+ // connectButton
+ //
+ this.connectButton.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.connectButton.Location = new System.Drawing.Point(12, 12);
+ this.connectButton.Name = "connectButton";
+ this.connectButton.Size = new System.Drawing.Size(1137, 46);
+ this.connectButton.TabIndex = 5;
+ this.connectButton.Text = "&Connect";
+ this.connectButton.UseVisualStyleBackColor = true;
+ this.connectButton.Click += new System.EventHandler(this.connectButton_Click);
+ //
+ // logBox
+ //
+ this.logBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
+ | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.logBox.Location = new System.Drawing.Point(12, 64);
+ this.logBox.Multiline = true;
+ this.logBox.Name = "logBox";
+ this.logBox.ReadOnly = true;
+ this.logBox.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
+ this.logBox.Size = new System.Drawing.Size(1137, 561);
+ this.logBox.TabIndex = 4;
+ this.logBox.TabStop = false;
+ //
+ // MainWindow
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(13F, 32F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ClientSize = new System.Drawing.Size(1161, 637);
+ this.Controls.Add(this.logBox);
+ this.Controls.Add(this.connectButton);
+ this.Name = "MainWindow";
+ this.Text = "WireGuard Demo Client";
+ this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.MainWindow_FormClosing);
+ this.Load += new System.EventHandler(this.MainWindow_Load);
+ this.ResumeLayout(false);
+ this.PerformLayout();
+
+ }
+
+ #endregion
+ private System.Windows.Forms.Button connectButton;
+ private System.Windows.Forms.TextBox logBox;
+ }
+}
+
diff --git a/embeddable-dll-service/csharp/DemoUI/MainWindow.cs b/embeddable-dll-service/csharp/DemoUI/MainWindow.cs
new file mode 100644
index 00000000..1df17181
--- /dev/null
+++ b/embeddable-dll-service/csharp/DemoUI/MainWindow.cs
@@ -0,0 +1,215 @@
+/* SPDX-License-Identifier: MIT
+ *
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
+ */
+
+using System;
+using System.Text;
+using System.Threading.Tasks;
+using System.IO;
+using System.Windows.Forms;
+using System.Threading;
+using System.IO.Pipes;
+using System.Diagnostics;
+using System.Net.Sockets;
+using System.Security.AccessControl;
+
+namespace DemoUI
+{
+ public partial class MainWindow : Form
+ {
+ private static readonly string userDirectory = Path.Combine(Path.GetDirectoryName(Process.GetCurrentProcess().MainModule.FileName), "Config"); //TODO: put in Program Files in real code.
+ private static readonly string configFile = Path.Combine(userDirectory, "demobox.conf");
+ private static readonly string logFile = Path.Combine(userDirectory, "log.bin");
+
+ private Tunnel.Ringlogger log;
+ private Thread logPrintingThread, transferUpdateThread;
+ private volatile bool threadsRunning;
+ private bool connected;
+
+ public MainWindow()
+ {
+ makeConfigDirectory();
+ InitializeComponent();
+ Application.ApplicationExit += Application_ApplicationExit;
+ try { File.Delete(logFile); } catch { }
+ log = new Tunnel.Ringlogger(logFile, "GUI");
+ logPrintingThread = new Thread(new ThreadStart(tailLog));
+ transferUpdateThread = new Thread(new ThreadStart(tailTransfer));
+ }
+
+ private void makeConfigDirectory()
+ {
+ var ds = new DirectorySecurity();
+ ds.SetSecurityDescriptorSddlForm("O:BAG:BAD:PAI(A;OICI;FA;;;BA)(A;OICI;FA;;;SY)");
+ FileSystemAclExtensions.CreateDirectory(ds, userDirectory);
+ }
+
+ private void tailLog()
+ {
+ var cursor = Tunnel.Ringlogger.CursorAll;
+ while (threadsRunning)
+ {
+ var lines = log.FollowFromCursor(ref cursor);
+ foreach (var line in lines)
+ logBox.Invoke(new Action<string>(logBox.AppendText), new object[] { line + "\r\n" });
+ try
+ {
+ Thread.Sleep(300);
+ }
+ catch
+ {
+ break;
+ }
+ }
+ }
+
+ private void tailTransfer()
+ {
+ Tunnel.Driver.Adapter adapter = null;
+ while (threadsRunning)
+ {
+ if (adapter == null)
+ {
+ while (threadsRunning)
+ {
+ try
+ {
+ adapter = Tunnel.Service.GetAdapter(configFile);
+ break;
+ }
+ catch
+ {
+ try
+ {
+ Thread.Sleep(1000);
+ }
+ catch { }
+ }
+ }
+ }
+ if (adapter == null)
+ continue;
+ try
+ {
+ ulong rx = 0, tx = 0;
+ var config = adapter.GetConfiguration();
+ foreach (var peer in config.Peers)
+ {
+ rx += peer.RxBytes;
+ tx += peer.TxBytes;
+ }
+ Invoke(new Action<ulong, ulong>(updateTransferTitle), new object[] { rx, tx });
+ Thread.Sleep(1000);
+ }
+ catch { adapter = null; }
+ }
+ }
+
+ private void Application_ApplicationExit(object sender, EventArgs e)
+ {
+ Tunnel.Service.Remove(configFile, true);
+ try { File.Delete(logFile); } catch { }
+ try { File.Delete(configFile); } catch { }
+ }
+
+ private void MainWindow_Load(object sender, EventArgs e)
+ {
+ threadsRunning = true;
+ logPrintingThread.Start();
+ transferUpdateThread.Start();
+ }
+
+ private void MainWindow_FormClosing(object sender, FormClosingEventArgs e)
+ {
+ threadsRunning = false;
+ logPrintingThread.Interrupt();
+ transferUpdateThread.Interrupt();
+ try { logPrintingThread.Join(); } catch { }
+ try { transferUpdateThread.Join(); } catch { }
+ }
+
+ private static string formatBytes(ulong bytes)
+ {
+ decimal d = bytes;
+ string selectedUnit = null;
+ foreach (string unit in new string[] { "B", "KiB", "MiB", "GiB", "TiB" })
+ {
+ selectedUnit = unit;
+ if (d < 1024)
+ break;
+ d /= 1024;
+ }
+ return string.Format("{0:0.##} {1}", d, selectedUnit);
+ }
+
+ private void updateTransferTitle(ulong rx, ulong tx)
+ {
+ var titleBase = Text;
+ var idx = titleBase.IndexOf(" - ");
+ if (idx != -1)
+ titleBase = titleBase.Substring(0, idx);
+ if (rx == 0 && tx == 0)
+ Text = titleBase;
+ else
+ Text = string.Format("{0} - rx: {1}, tx: {2}", titleBase, formatBytes(rx), formatBytes(tx));
+ }
+
+ private async Task<string> generateNewConfig()
+ {
+ log.Write("Generating keys");
+ var keys = Tunnel.Keypair.Generate();
+ log.Write("Exchanging keys with demo server");
+ var client = new TcpClient();
+ await client.ConnectAsync("demo.wireguard.com", 42912);
+ var stream = client.GetStream();
+ var reader = new StreamReader(stream, Encoding.UTF8);
+ var pubKeyBytes = Encoding.UTF8.GetBytes(keys.Public + "\n");
+ await stream.WriteAsync(pubKeyBytes, 0, pubKeyBytes.Length);
+ await stream.FlushAsync();
+ var ret = (await reader.ReadLineAsync()).Split(':');
+ client.Close();
+ var status = ret.Length >= 1 ? ret[0] : "";
+ var serverPubkey = ret.Length >= 2 ? ret[1] : "";
+ var serverPort = ret.Length >= 3 ? ret[2] : "";
+ var internalIP = ret.Length >= 4 ? ret[3] : "";
+ if (status != "OK")
+ throw new InvalidOperationException(string.Format("Server status is {0}", status));
+ return string.Format("[Interface]\nPrivateKey = {0}\nAddress = {1}/24\nDNS = 8.8.8.8, 8.8.4.4\n\n[Peer]\nPublicKey = {2}\nEndpoint = demo.wireguard.com:{3}\nAllowedIPs = 0.0.0.0/0\n", keys.Private, internalIP, serverPubkey, serverPort);
+ }
+
+ private async void connectButton_Click(object sender, EventArgs e)
+ {
+ if (connected)
+ {
+ connectButton.Enabled = false;
+ await Task.Run(() =>
+ {
+ Tunnel.Service.Remove(configFile, true);
+ try { File.Delete(configFile); } catch { }
+ });
+ updateTransferTitle(0, 0);
+ connectButton.Text = "&Connect";
+ connectButton.Enabled = true;
+ connected = false;
+ return;
+ }
+
+ connectButton.Enabled = false;
+ try
+ {
+ var config = await generateNewConfig();
+ await File.WriteAllBytesAsync(configFile, Encoding.UTF8.GetBytes(config));
+ await Task.Run(() => Tunnel.Service.Add(configFile, true));
+ connected = true;
+ connectButton.Text = "&Disconnect";
+ }
+ catch (Exception ex)
+ {
+ log.Write(ex.Message);
+ try { File.Delete(configFile); } catch { }
+ }
+ connectButton.Enabled = true;
+ }
+ }
+}
diff --git a/embeddable-dll-service/csharp/DemoUI/MainWindow.resx b/embeddable-dll-service/csharp/DemoUI/MainWindow.resx
new file mode 100644
index 00000000..f298a7be
--- /dev/null
+++ b/embeddable-dll-service/csharp/DemoUI/MainWindow.resx
@@ -0,0 +1,60 @@
+<root>
+ <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
+ <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
+ <xsd:element name="root" msdata:IsDataSet="true">
+ <xsd:complexType>
+ <xsd:choice maxOccurs="unbounded">
+ <xsd:element name="metadata">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" />
+ </xsd:sequence>
+ <xsd:attribute name="name" use="required" type="xsd:string" />
+ <xsd:attribute name="type" type="xsd:string" />
+ <xsd:attribute name="mimetype" type="xsd:string" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="assembly">
+ <xsd:complexType>
+ <xsd:attribute name="alias" type="xsd:string" />
+ <xsd:attribute name="name" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="data">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
+ <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
+ <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
+ <xsd:attribute ref="xml:space" />
+ </xsd:complexType>
+ </xsd:element>
+ <xsd:element name="resheader">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
+ </xsd:sequence>
+ <xsd:attribute name="name" type="xsd:string" use="required" />
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:choice>
+ </xsd:complexType>
+ </xsd:element>
+ </xsd:schema>
+ <resheader name="resmimetype">
+ <value>text/microsoft-resx</value>
+ </resheader>
+ <resheader name="version">
+ <value>2.0</value>
+ </resheader>
+ <resheader name="reader">
+ <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+ <resheader name="writer">
+ <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
+ </resheader>
+</root> \ No newline at end of file
diff --git a/embeddable-dll-service/csharp/DemoUI/Program.cs b/embeddable-dll-service/csharp/DemoUI/Program.cs
new file mode 100644
index 00000000..3649ab93
--- /dev/null
+++ b/embeddable-dll-service/csharp/DemoUI/Program.cs
@@ -0,0 +1,44 @@
+/* SPDX-License-Identifier: MIT
+ *
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
+ */
+
+using System;
+using System.Threading;
+using System.Diagnostics;
+using System.Windows.Forms;
+
+namespace DemoUI
+{
+ static class Program
+ {
+ [STAThread]
+ static void Main(string[] args)
+ {
+ if (args.Length == 3 && args[0] == "/service")
+ {
+ var t = new Thread(() =>
+ {
+ try
+ {
+ var currentProcess = Process.GetCurrentProcess();
+ var uiProcess = Process.GetProcessById(int.Parse(args[2]));
+ if (uiProcess.MainModule.FileName != currentProcess.MainModule.FileName)
+ return;
+ uiProcess.WaitForExit();
+ Tunnel.Service.Remove(args[1], false);
+ }
+ catch { }
+ });
+ t.Start();
+ Tunnel.Service.Run(args[1]);
+ t.Interrupt();
+ return;
+ }
+ Application.SetHighDpiMode(HighDpiMode.SystemAware);
+ Application.EnableVisualStyles();
+ Application.SetCompatibleTextRenderingDefault(false);
+ Application.Run(new MainWindow());
+ }
+ }
+}
diff --git a/embeddable-dll-service/csharp/DemoUI/app.manifest b/embeddable-dll-service/csharp/DemoUI/app.manifest
new file mode 100644
index 00000000..616ab5b9
--- /dev/null
+++ b/embeddable-dll-service/csharp/DemoUI/app.manifest
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="utf-8"?>
+<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
+ <assemblyIdentity version="1.0.0.0" name="demo-client"/>
+ <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
+ <security>
+ <requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
+ <requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
+ </requestedPrivileges>
+ </security>
+ </trustInfo>
+
+ <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
+ <application>
+ <!-- Windows 7 -->
+ <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}" />
+
+ <!-- Windows 8 -->
+ <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}" />
+
+ <!-- Windows 8.1 -->
+ <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}" />
+
+ <!-- Windows 10 -->
+ <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
+
+ </application>
+ </compatibility>
+
+ <application xmlns="urn:schemas-microsoft-com:asm.v3">
+ <windowsSettings>
+ <dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware>
+ </windowsSettings>
+ </application>
+
+ <dependency>
+ <dependentAssembly>
+ <assemblyIdentity
+ type="win32"
+ name="Microsoft.Windows.Common-Controls"
+ version="6.0.0.0"
+ processorArchitecture="*"
+ publicKeyToken="6595b64144ccf1df"
+ language="*"
+ />
+ </dependentAssembly>
+ </dependency>
+
+</assembly>
diff --git a/embeddable-dll-service/csharp/Program.cs b/embeddable-dll-service/csharp/Program.cs
deleted file mode 100644
index d99e66fd..00000000
--- a/embeddable-dll-service/csharp/Program.cs
+++ /dev/null
@@ -1,92 +0,0 @@
-/* SPDX-License-Identifier: MIT
- *
- * Copyright (C) 2019 WireGuard LLC. All Rights Reserved.
- */
-
-using System;
-using System.Net.Sockets;
-using System.IO;
-using System.Text;
-using System.Diagnostics;
-using System.Threading;
-using System.Runtime.InteropServices;
-
-namespace Tunnel
-{
- class Program
- {
-
- [DllImport("kernel32.dll")]
- private static extern bool SetConsoleCtrlHandler(SetConsoleCtrlEventHandler handler, bool add);
- private delegate bool SetConsoleCtrlEventHandler(UInt32 signal);
-
- public static void Main(string[] args)
- {
- if (args.Length == 2 && args[0] == "/service")
- {
- Service.Run(args[1]);
- return;
- }
-
- var baseDirectory = Path.GetDirectoryName(Process.GetCurrentProcess().MainModule.FileName);
- var configFile = Path.Combine(baseDirectory, "demobox.conf");
- var logFile = Path.Combine(baseDirectory, "log.bin");
-
- try { File.Delete(logFile); } catch { }
- Ringlogger log = new Ringlogger(logFile, "GUI");
-
- var logPrintingThread = new Thread(() =>
- {
- var cursor = Ringlogger.CursorAll;
- while (Thread.CurrentThread.IsAlive)
- {
- var lines = log.FollowFromCursor(ref cursor);
- foreach (var line in lines)
- Console.WriteLine(line);
- Thread.Sleep(300);
- }
- });
- logPrintingThread.Start();
-
- log.Write("Generating keys");
- var keys = Keypair.Generate();
- log.Write("Exchanging keys with demo server");
- var client = new TcpClient("demo.wireguard.com", 42912);
- var stream = client.GetStream();
- var reader = new StreamReader(stream, Encoding.UTF8);
- var pubKeyBytes = Encoding.UTF8.GetBytes(keys.Public + "\n");
- stream.Write(pubKeyBytes, 0, pubKeyBytes.Length);
- stream.Flush();
- var ret = reader.ReadLine().Split(':');
- client.Close();
- var status = ret.Length >= 1 ? ret[0] : "";
- var serverPubkey = ret.Length >= 2 ? ret[1] : "";
- var serverPort = ret.Length >= 3 ? ret[2] : "";
- var internalIP = ret.Length >= 4 ? ret[3] : "";
-
- if (status != "OK")
- throw new InvalidOperationException(String.Format("Server status is {0}", status));
-
- SetConsoleCtrlHandler(delegate
- {
- Service.Remove(configFile);
- Environment.Exit(0);
- return true;
- }, true);
-
- log.Write("Writing config file to disk");
- var configFileContents = String.Format("[Interface]\nPrivateKey = {0}\nAddress = {1}/24\nDNS = 8.8.8.8, 8.8.4.4\n\n[Peer]\nPublicKey = {2}\nEndpoint = demo.wireguard.com:{3}\nAllowedIPs = 0.0.0.0/0\n", keys.Private, internalIP, serverPubkey, serverPort);
- File.WriteAllText(configFile, configFileContents);
-
- try
- {
- Service.Add(configFile);
- logPrintingThread.Join();
- }
- finally
- {
- Service.Remove(configFile);
- }
- }
- }
-}
diff --git a/embeddable-dll-service/csharp/README.md b/embeddable-dll-service/csharp/README.md
new file mode 100644
index 00000000..24b36563
--- /dev/null
+++ b/embeddable-dll-service/csharp/README.md
@@ -0,0 +1,7 @@
+# Example WireGuard Demo Client for Windows
+
+This is a simple client for demo.wireguard.com, which brings up WireGuard tunnels using the [embeddable-dll-service](https://git.zx2c4.com/wireguard-windows/about/embeddable-dll-service/README.md).
+
+## Building
+
+The code in this repository can be built in Visual Studio 2019 by opening the .sln and pressing build. However, it requires [`tunnel.dll` and `wireguard.dll`](../README.md).
diff --git a/embeddable-dll-service/csharp/TunnelDll/Driver.cs b/embeddable-dll-service/csharp/TunnelDll/Driver.cs
new file mode 100644
index 00000000..69911ec8
--- /dev/null
+++ b/embeddable-dll-service/csharp/TunnelDll/Driver.cs
@@ -0,0 +1,234 @@
+/* SPDX-License-Identifier: MIT
+ *
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
+ */
+
+using System;
+using System.ComponentModel;
+using System.Net;
+using System.Runtime.InteropServices;
+
+namespace Tunnel
+{
+ public class Driver
+ {
+ [DllImport("wireguard.dll", EntryPoint = "WireGuardOpenAdapter", CallingConvention = CallingConvention.StdCall, SetLastError = true)]
+ private static extern IntPtr openAdapter([MarshalAs(UnmanagedType.LPWStr)] string name);
+ [DllImport("wireguard.dll", EntryPoint = "WireGuardCloseAdapter", CallingConvention = CallingConvention.StdCall)]
+ private static extern void freeAdapter(IntPtr adapter);
+ [DllImport("wireguard.dll", EntryPoint = "WireGuardGetConfiguration", CallingConvention = CallingConvention.StdCall, SetLastError = true)]
+ private static extern bool getConfiguration(IntPtr adapter, byte[] iface, ref UInt32 bytes);
+
+ public class Adapter
+ {
+ private IntPtr _handle;
+ private UInt32 _lastGetGuess;
+ public Adapter(string name)
+ {
+ _lastGetGuess = 1024;
+ _handle = openAdapter(name);
+ if (_handle == IntPtr.Zero)
+ throw new Win32Exception();
+ }
+ ~Adapter()
+ {
+ freeAdapter(_handle);
+ }
+ public unsafe Interface GetConfiguration()
+ {
+ var iface = new Interface();
+ byte[] bytes;
+ for (; ; )
+ {
+ bytes = new byte[_lastGetGuess];
+ if (getConfiguration(_handle, bytes, ref _lastGetGuess))
+ break;
+ if (Marshal.GetLastWin32Error() != 234 /* ERROR_MORE_DATA */)
+ throw new Win32Exception();
+ }
+ fixed (void* start = bytes)
+ {
+ var ioctlIface = (IoctlInterface*)start;
+ if ((ioctlIface->Flags & IoctlInterfaceFlags.HasPublicKey) != 0)
+ iface.PublicKey = new Key(ioctlIface->PublicKey);
+ if ((ioctlIface->Flags & IoctlInterfaceFlags.HasPrivateKey) != 0)
+ iface.PrivateKey = new Key(ioctlIface->PrivateKey);
+ if ((ioctlIface->Flags & IoctlInterfaceFlags.HasListenPort) != 0)
+ iface.ListenPort = ioctlIface->ListenPort;
+ var peers = new Peer[ioctlIface->PeersCount];
+ var ioctlPeer = (IoctlPeer*)((byte*)ioctlIface + sizeof(IoctlInterface));
+ for (UInt32 i = 0; i < peers.Length; ++i)
+ {
+ var peer = new Peer();
+ if ((ioctlPeer->Flags & IoctlPeerFlags.HasPublicKey) != 0)
+ peer.PublicKey = new Key(ioctlPeer->PublicKey);
+ if ((ioctlPeer->Flags & IoctlPeerFlags.HasPresharedKey) != 0)
+ peer.PresharedKey = new Key(ioctlPeer->PresharedKey);
+ if ((ioctlPeer->Flags & IoctlPeerFlags.HasPersistentKeepalive) != 0)
+ peer.PersistentKeepalive = ioctlPeer->PersistentKeepalive;
+ if ((ioctlPeer->Flags & IoctlPeerFlags.HasEndpoint) != 0)
+ {
+ if (ioctlPeer->Endpoint.si_family == Win32.ADDRESS_FAMILY.AF_INET)
+ {
+ var ip = new byte[4];
+ Marshal.Copy((IntPtr)ioctlPeer->Endpoint.Ipv4.sin_addr.bytes, ip, 0, 4);
+ peer.Endpoint = new IPEndPoint(new IPAddress(ip), (ushort)IPAddress.NetworkToHostOrder((short)ioctlPeer->Endpoint.Ipv4.sin_port));
+ }
+ else if (ioctlPeer->Endpoint.si_family == Win32.ADDRESS_FAMILY.AF_INET6)
+ {
+ var ip = new byte[16];
+ Marshal.Copy((IntPtr)ioctlPeer->Endpoint.Ipv6.sin6_addr.bytes, ip, 0, 16);
+ peer.Endpoint = new IPEndPoint(new IPAddress(ip), (ushort)IPAddress.NetworkToHostOrder((short)ioctlPeer->Endpoint.Ipv6.sin6_port));
+ }
+ }
+ peer.TxBytes = ioctlPeer->TxBytes;
+ peer.RxBytes = ioctlPeer->RxBytes;
+ if (ioctlPeer->LastHandshake != 0)
+ peer.LastHandshake = DateTime.FromFileTimeUtc((long)ioctlPeer->LastHandshake);
+ var allowedIPs = new AllowedIP[ioctlPeer->AllowedIPsCount];
+ var ioctlAllowedIP = (IoctlAllowedIP*)((byte*)ioctlPeer + sizeof(IoctlPeer));
+ for (UInt32 j = 0; j < allowedIPs.Length; ++j)
+ {
+ var allowedIP = new AllowedIP();
+ if (ioctlAllowedIP->AddressFamily == Win32.ADDRESS_FAMILY.AF_INET)
+ {
+ var ip = new byte[4];
+ Marshal.Copy((IntPtr)ioctlAllowedIP->V4.bytes, ip, 0, 4);
+ allowedIP.Address = new IPAddress(ip);
+ }
+ else if (ioctlAllowedIP->AddressFamily == Win32.ADDRESS_FAMILY.AF_INET6)
+ {
+ var ip = new byte[16];
+ Marshal.Copy((IntPtr)ioctlAllowedIP->V6.bytes, ip, 0, 16);
+ allowedIP.Address = new IPAddress(ip);
+ }
+ allowedIP.Cidr = ioctlAllowedIP->Cidr;
+ allowedIPs[j] = allowedIP;
+ ioctlAllowedIP = (IoctlAllowedIP*)((byte*)ioctlAllowedIP + sizeof(IoctlAllowedIP));
+ }
+ peer.AllowedIPs = allowedIPs;
+ peers[i] = peer;
+ ioctlPeer = (IoctlPeer*)ioctlAllowedIP;
+ }
+ iface.Peers = peers;
+ }
+ return iface;
+ }
+
+ public class Key
+ {
+ private byte[] _bytes;
+ public byte[] Bytes
+ {
+ get
+ {
+ return _bytes;
+ }
+ set
+ {
+ if (value == null || value.Length != 32)
+ throw new ArgumentException("Keys must be 32 bytes");
+ _bytes = value;
+ }
+ }
+ public Key(byte[] bytes)
+ {
+ Bytes = bytes;
+ }
+ public unsafe Key(byte* bytes)
+ {
+ _bytes = new byte[32];
+ Marshal.Copy((IntPtr)bytes, _bytes, 0, 32);
+ }
+ public override String ToString()
+ {
+ return Convert.ToBase64String(_bytes);
+ }
+ }
+
+ public class Interface
+ {
+ public UInt16 ListenPort { get; set; }
+ public Key PrivateKey { get; set; }
+ public Key PublicKey { get; set; }
+ public Peer[] Peers { get; set; }
+ }
+
+ public class Peer
+ {
+ public Key PublicKey { get; set; }
+ public Key PresharedKey { get; set; }
+ public UInt16 PersistentKeepalive { get; set; }
+ public IPEndPoint Endpoint { get; set; }
+ public UInt64 TxBytes { get; set; }
+ public UInt64 RxBytes { get; set; }
+ public DateTime LastHandshake { get; set; }
+ public AllowedIP[] AllowedIPs { get; set; }
+ }
+
+ public class AllowedIP
+ {
+ public IPAddress Address { get; set; }
+ public byte Cidr { get; set; }
+ }
+
+ private enum IoctlInterfaceFlags : UInt32
+ {
+ HasPublicKey = 1 << 0,
+ HasPrivateKey = 1 << 1,
+ HasListenPort = 1 << 2,
+ ReplacePeers = 1 << 3
+ };
+
+ [StructLayout(LayoutKind.Sequential, Pack = 8, Size = 80)]
+ private unsafe struct IoctlInterface
+ {
+ public IoctlInterfaceFlags Flags;
+ public UInt16 ListenPort;
+ public fixed byte PrivateKey[32];
+ public fixed byte PublicKey[32];
+ public UInt32 PeersCount;
+ };
+
+ private enum IoctlPeerFlags : UInt32
+ {
+ HasPublicKey = 1 << 0,
+ HasPresharedKey = 1 << 1,
+ HasPersistentKeepalive = 1 << 2,
+ HasEndpoint = 1 << 3,
+ ReplaceAllowedIPs = 1 << 5,
+ Remove = 1 << 6,
+ UpdateOnly = 1 << 7
+ };
+
+ [StructLayout(LayoutKind.Sequential, Pack = 8, Size = 136)]
+ private unsafe struct IoctlPeer
+ {
+ public IoctlPeerFlags Flags;
+ public UInt32 Reserved;
+ public fixed byte PublicKey[32];
+ public fixed byte PresharedKey[32];
+ public UInt16 PersistentKeepalive;
+ public Win32.SOCKADDR_INET Endpoint;
+ public UInt64 TxBytes, RxBytes;
+ public UInt64 LastHandshake;
+ public UInt32 AllowedIPsCount;
+ };
+
+ [StructLayout(LayoutKind.Explicit, Pack = 8, Size = 24)]
+ private unsafe struct IoctlAllowedIP
+ {
+ [FieldOffset(0)]
+ [MarshalAs(UnmanagedType.Struct)]
+ public Win32.IN_ADDR V4;
+ [FieldOffset(0)]
+ [MarshalAs(UnmanagedType.Struct)]
+ public Win32.IN6_ADDR V6;
+ [FieldOffset(16)]
+ public Win32.ADDRESS_FAMILY AddressFamily;
+ [FieldOffset(20)]
+ public byte Cidr;
+ }
+ }
+ }
+}
diff --git a/embeddable-dll-service/csharp/Keypair.cs b/embeddable-dll-service/csharp/TunnelDll/Keypair.cs
index e5764fbd..59847b98 100644
--- a/embeddable-dll-service/csharp/Keypair.cs
+++ b/embeddable-dll-service/csharp/TunnelDll/Keypair.cs
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
using System;
@@ -13,7 +13,7 @@ namespace Tunnel
public readonly string Public;
public readonly string Private;
- private Keypair(string pub, string priv)
+ public Keypair(string pub, string priv)
{
Public = pub;
Private = priv;
diff --git a/embeddable-dll-service/csharp/Ringlogger.cs b/embeddable-dll-service/csharp/TunnelDll/Ringlogger.cs
index d0957926..9db01fc8 100644
--- a/embeddable-dll-service/csharp/Ringlogger.cs
+++ b/embeddable-dll-service/csharp/TunnelDll/Ringlogger.cs
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
using System;
diff --git a/embeddable-dll-service/csharp/Service.cs b/embeddable-dll-service/csharp/TunnelDll/Service.cs
index db600819..74e1a888 100644
--- a/embeddable-dll-service/csharp/Service.cs
+++ b/embeddable-dll-service/csharp/TunnelDll/Service.cs
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
using System;
@@ -9,36 +9,30 @@ using System.IO.Pipes;
using System.Runtime.InteropServices;
using System.ComponentModel;
using System.Diagnostics;
-using System.Security.Principal;
using System.Threading;
namespace Tunnel
{
public class Service
{
- private const string LongName = "Example WireGuard Tunnel Client";
- private const string Description = "A WireGuard tunnel created by example code.";
+ private const string LongName = "WireGuard Demo Box";
+ private const string Description = "Demonstration tunnel for testing WireGuard";
[DllImport("tunnel.dll", EntryPoint = "WireGuardTunnelService", CallingConvention = CallingConvention.Cdecl)]
public static extern bool Run([MarshalAs(UnmanagedType.LPWStr)] string configFile);
- public static NamedPipeClientStream GetPipe(string configFile)
+ public static Driver.Adapter GetAdapter(string configFile)
{
- var pipepath = "ProtectedPrefix\\Administrators\\WireGuard\\" + Path.GetFileNameWithoutExtension(configFile);
- return new NamedPipeClientStream(pipepath);
+ return new Driver.Adapter(Path.GetFileNameWithoutExtension(configFile));
}
- public static void Add(string configFile)
+ public static void Add(string configFile, bool ephemeral)
{
var tunnelName = Path.GetFileNameWithoutExtension(configFile);
var shortName = String.Format("WireGuardTunnel${0}", tunnelName);
var longName = String.Format("{0}: {1}", LongName, tunnelName);
var exeName = Process.GetCurrentProcess().MainModule.FileName;
- var pathAndArgs = String.Format("\"{0}\" /service \"{1}\"", exeName, configFile); //TODO: This is not the proper way to escape file args.
-
- var accessControl = File.GetAccessControl(configFile); //TODO: TOCTOU!
- accessControl.SetOwner(new NTAccount(Environment.UserDomainName, Environment.UserName));
- File.SetAccessControl(configFile, accessControl);
+ var pathAndArgs = String.Format("\"{0}\" /service \"{1}\" {2}", exeName, configFile, Process.GetCurrentProcess().Id); //TODO: This is not the proper way to escape file args.
var scm = Win32.OpenSCManager(null, null, Win32.ScmAccessRights.AllAccess);
if (scm == IntPtr.Zero)
@@ -49,9 +43,9 @@ namespace Tunnel
if (service != IntPtr.Zero)
{
Win32.CloseServiceHandle(service);
- Remove(configFile);
+ Remove(configFile, true);
}
- service = Win32.CreateService(scm, shortName, longName, Win32.ServiceAccessRights.AllAccess, Win32.ServiceType.Win32OwnProcess, Win32.ServiceStartType.Demand, Win32.ServiceError.Normal, pathAndArgs, null, IntPtr.Zero, "Nsi", null, null);
+ service = Win32.CreateService(scm, shortName, longName, Win32.ServiceAccessRights.AllAccess, Win32.ServiceType.Win32OwnProcess, Win32.ServiceStartType.Demand, Win32.ServiceError.Normal, pathAndArgs, null, IntPtr.Zero, "Nsi\0TcpIp\0", null, null);
if (service == IntPtr.Zero)
throw new Win32Exception(Marshal.GetLastWin32Error());
try
@@ -66,6 +60,9 @@ namespace Tunnel
if (!Win32.StartService(service, 0, null))
throw new Win32Exception(Marshal.GetLastWin32Error());
+
+ if (ephemeral && !Win32.DeleteService(service))
+ throw new Win32Exception(Marshal.GetLastWin32Error());
}
finally
{
@@ -78,7 +75,7 @@ namespace Tunnel
}
}
- public static void Remove(string configFile)
+ public static void Remove(string configFile, bool waitForStop)
{
var tunnelName = Path.GetFileNameWithoutExtension(configFile);
var shortName = String.Format("WireGuardTunnel${0}", tunnelName);
@@ -90,19 +87,16 @@ namespace Tunnel
{
var service = Win32.OpenService(scm, shortName, Win32.ServiceAccessRights.AllAccess);
if (service == IntPtr.Zero)
- {
- Win32.CloseServiceHandle(service);
return;
- }
try
{
var serviceStatus = new Win32.ServiceStatus();
Win32.ControlService(service, Win32.ServiceControl.Stop, serviceStatus);
- for (int i = 0; i < 180 && Win32.QueryServiceStatus(service, serviceStatus) && serviceStatus.dwCurrentState != Win32.ServiceState.Stopped; ++i)
+ for (int i = 0; waitForStop && i < 180 && Win32.QueryServiceStatus(service, serviceStatus) && serviceStatus.dwCurrentState != Win32.ServiceState.Stopped; ++i)
Thread.Sleep(1000);
- if (!Win32.DeleteService(service))
+ if (!Win32.DeleteService(service) && Marshal.GetLastWin32Error() != 0x00000430)
throw new Win32Exception(Marshal.GetLastWin32Error());
}
finally
diff --git a/embeddable-dll-service/csharp/Win32.cs b/embeddable-dll-service/csharp/TunnelDll/Win32.cs
index 76395f7e..8e7f986d 100644
--- a/embeddable-dll-service/csharp/Win32.cs
+++ b/embeddable-dll-service/csharp/TunnelDll/Win32.cs
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
using System;
@@ -135,6 +135,58 @@ namespace Tunnel
SidInfo = 5
}
+ [StructLayout(LayoutKind.Sequential)]
+ public unsafe struct IN_ADDR
+ {
+ public fixed byte bytes[4];
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ public unsafe struct IN6_ADDR
+ {
+ public fixed byte bytes[16];
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct SOCKADDR_IN
+ {
+ public ushort sin_family;
+ public ushort sin_port;
+ public IN_ADDR sin_addr;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct SOCKADDR_IN6
+ {
+ public ushort sin6_family;
+ public ushort sin6_port;
+ public uint sin6_flowinfo;
+ public IN6_ADDR sin6_addr;
+ public uint sin6_scope_id;
+ }
+
+ [StructLayout(LayoutKind.Explicit)]
+ public struct SOCKADDR_INET
+ {
+ [FieldOffset(0)]
+ [MarshalAs(UnmanagedType.Struct)]
+ public SOCKADDR_IN Ipv4;
+
+ [FieldOffset(0)]
+ [MarshalAs(UnmanagedType.Struct)]
+ public SOCKADDR_IN6 Ipv6;
+
+ [FieldOffset(0)]
+ public ADDRESS_FAMILY si_family;
+ }
+
+ public enum ADDRESS_FAMILY : UInt16
+ {
+ AF_UNSPEC = 0,
+ AF_INET = 2,
+ AF_INET6 = 23
+ }
+
[DllImport("advapi32.dll", EntryPoint = "OpenSCManagerW", ExactSpelling = true, CharSet = CharSet.Unicode, SetLastError = true)]
public static extern IntPtr OpenSCManager(string machineName, string databaseName, ScmAccessRights dwDesiredAccess);
diff --git a/embeddable-dll-service/csharp/demo-client.csproj b/embeddable-dll-service/csharp/demo-client.csproj
new file mode 100644
index 00000000..00339ee2
--- /dev/null
+++ b/embeddable-dll-service/csharp/demo-client.csproj
@@ -0,0 +1,14 @@
+<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">
+
+ <PropertyGroup>
+ <OutputType>WinExe</OutputType>
+ <TargetFramework>net5.0-windows</TargetFramework>
+ <RootNamespace>DemoUI</RootNamespace>
+ <UseWindowsForms>true</UseWindowsForms>
+ <AssemblyName>demo-client</AssemblyName>
+ <Platforms>x64</Platforms>
+ <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+ <ApplicationManifest>DemoUI\app.manifest</ApplicationManifest>
+ </PropertyGroup>
+
+</Project>
diff --git a/embeddable-dll-service/csharp/demo-client.csproj.user b/embeddable-dll-service/csharp/demo-client.csproj.user
new file mode 100644
index 00000000..27d1a581
--- /dev/null
+++ b/embeddable-dll-service/csharp/demo-client.csproj.user
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Compile Update="DemoUI\MainWindow.cs">
+ <SubType>Form</SubType>
+ </Compile>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/embeddable-dll-service/csharp/demo-client.sln b/embeddable-dll-service/csharp/demo-client.sln
new file mode 100644
index 00000000..a7d8b0ee
--- /dev/null
+++ b/embeddable-dll-service/csharp/demo-client.sln
@@ -0,0 +1,25 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.30804.86
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "demo-client", "demo-client.csproj", "{AADC81E1-0294-483B-ABAE-63DBE82436E9}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|x64 = Debug|x64
+ Release|x64 = Release|x64
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {AADC81E1-0294-483B-ABAE-63DBE82436E9}.Debug|x64.ActiveCfg = Debug|x64
+ {AADC81E1-0294-483B-ABAE-63DBE82436E9}.Debug|x64.Build.0 = Debug|x64
+ {AADC81E1-0294-483B-ABAE-63DBE82436E9}.Release|x64.ActiveCfg = Release|x64
+ {AADC81E1-0294-483B-ABAE-63DBE82436E9}.Release|x64.Build.0 = Release|x64
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {E410FD53-4E4A-4299-B6BD-CE91685DF7BE}
+ EndGlobalSection
+EndGlobal
diff --git a/embeddable-dll-service/main.go b/embeddable-dll-service/main.go
index 27fca4ee..f313ae7f 100644
--- a/embeddable-dll-service/main.go
+++ b/embeddable-dll-service/main.go
@@ -1,28 +1,27 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package main
import (
"C"
+ "crypto/rand"
+ "log"
+ "path/filepath"
+ "unsafe"
"golang.org/x/crypto/curve25519"
"golang.org/x/sys/windows"
"golang.zx2c4.com/wireguard/windows/conf"
"golang.zx2c4.com/wireguard/windows/tunnel"
-
- "crypto/rand"
- "log"
- "path/filepath"
- "unsafe"
)
//export WireGuardTunnelService
func WireGuardTunnelService(confFile16 *uint16) bool {
- confFile := windows.UTF16ToString((*[(1 << 30) - 1]uint16)(unsafe.Pointer(confFile16))[:])
+ confFile := windows.UTF16PtrToString(confFile16)
conf.PresetRootDirectory(filepath.Dir(confFile))
tunnel.UseFixedGUIDInsteadOfDeterministic = true
err := tunnel.Run(confFile)
@@ -33,7 +32,7 @@ func WireGuardTunnelService(confFile16 *uint16) bool {
}
//export WireGuardGenerateKeypair
-func WireGuardGenerateKeypair(publicKey *byte, privateKey *byte) {
+func WireGuardGenerateKeypair(publicKey, privateKey *byte) {
publicKeyArray := (*[32]byte)(unsafe.Pointer(publicKey))
privateKeyArray := (*[32]byte)(unsafe.Pointer(privateKey))
n, err := rand.Read(privateKeyArray[:])