Import code from RomikB/amneziawg-client-windows (#2)

AmneziaWG for Windows client
This commit is contained in:
Roman Zakharchuk
2024-04-29 20:37:53 +02:00
committed by GitHub
parent dcc0eb72a0
commit 918fd3ed3f
137 changed files with 695 additions and 14139 deletions

View File

@@ -10,12 +10,12 @@ RCFLAGS := -DWIREGUARD_VERSION_ARRAY=$(subst $(space),$(comma),$(wordlist 1,4,$(
rwildcard=$(foreach d,$(filter-out .deps,$(wildcard $1*)),$(call rwildcard,$d/,$2) $(filter $(subst *,%,$2),$d))
SOURCE_FILES := $(call rwildcard,,*.go) .deps/go/prepared go.mod go.sum
RESOURCE_FILES := resources.rc version/version.go manifest.xml $(patsubst %.svg,%.ico,$(wildcard ui/icon/*.svg)) .deps/wireguard-nt/prepared
RESOURCE_FILES := resources.rc version/version.go manifest.xml $(patsubst %.svg,%.ico,$(wildcard ui/icon/*.svg)) .deps/wintun/prepared
DEPLOYMENT_HOST ?= winvm
DEPLOYMENT_PATH ?= Desktop
all: amd64/wireguard.exe x86/wireguard.exe arm64/wireguard.exe
all: amd64/wireguard.exe x86/wireguard.exe
define download =
.distfiles/$(1):
@@ -25,8 +25,8 @@ define download =
if ! mv $$@.unverified $$@; then rm -f $$@.unverified; exit 1; fi
endef
$(eval $(call download,go.tar.gz,https://go.dev/dl/go1.18.linux-amd64.tar.gz,e85278e98f57cdb150fe8409e6e5df5343ecb13cebf03a5d5ff12bd55a80264f))
$(eval $(call download,wireguard-nt.zip,https://download.wireguard.com/wireguard-nt/wireguard-nt-0.10.1.zip,772c0b1463d8d2212716f43f06f4594d880dea4f735165bd68e388fc41b81605))
$(eval $(call download,go.tar.gz,https://go.dev/dl/go1.22.0.linux-amd64.tar.gz,f6c8a87aa03b92c4b0bf3d558e28ea03006eb29db78917daec5cfb6ec1046265))
$(eval $(call download,wintun.zip,https://www.wintun.net/builds/wintun-0.14.1.zip,07c256185d6ee3652e09fa55c0b673e2624b565e02c4b9091c79ca7d2f24ef51))
.deps/go/prepared: .distfiles/go.tar.gz
mkdir -p .deps
@@ -35,36 +35,42 @@ $(eval $(call download,wireguard-nt.zip,https://download.wireguard.com/wireguard
chmod -R +w .deps/go
touch $@
.deps/wireguard-nt/prepared: .distfiles/wireguard-nt.zip
.deps/wintun/prepared: .distfiles/wintun.zip
mkdir -p .deps
rm -rf .deps/wireguard-nt
bsdtar -C .deps -xf .distfiles/wireguard-nt.zip
rm -rf .deps/wintun
bsdtar -C .deps -xf .distfiles/wintun.zip
touch $@
%.ico: %.svg
convert -background none $< -define icon:auto-resize="256,192,128,96,64,48,40,32,24,20,16" -compress zip $@
resources_amd64.syso: $(RESOURCE_FILES)
x86_64-w64-mingw32-windres $(RCFLAGS) -I .deps/wireguard-nt/bin/amd64 -i $< -o $@
x86_64-w64-mingw32-windres $(RCFLAGS) -i $< -o $@
resources_386.syso: $(RESOURCE_FILES)
i686-w64-mingw32-windres $(RCFLAGS) -I .deps/wireguard-nt/bin/x86 -i $< -o $@
i686-w64-mingw32-windres $(RCFLAGS) -i $< -o $@
resources_arm64.syso: $(RESOURCE_FILES)
aarch64-w64-mingw32-windres $(RCFLAGS) -I .deps/wireguard-nt/bin/arm64 -i $< -o $@
aarch64-w64-mingw32-windres $(RCFLAGS) -i $< -o $@
amd64/wireguard.exe: export GOARCH := amd64
amd64/wireguard.exe: resources_amd64.syso $(SOURCE_FILES)
amd64/wireguard.exe: amd64/wintun.dll resources_amd64.syso $(SOURCE_FILES)
go build $(GOFLAGS) -o $@
x86/wireguard.exe: export GOARCH := 386
x86/wireguard.exe: resources_386.syso $(SOURCE_FILES)
x86/wireguard.exe: x86/wintun.dll resources_386.syso $(SOURCE_FILES)
go build $(GOFLAGS) -o $@
arm64/wireguard.exe: export GOARCH := arm64
arm64/wireguard.exe: resources_arm64.syso $(SOURCE_FILES)
go build $(GOFLAGS) -o $@
amd64/wintun.dll:
cp .deps/wintun/bin/amd64/wintun.dll $@
x86/wintun.dll:
cp .deps/wintun/bin/x86/wintun.dll $@
remaster: export GOARCH := amd64
remaster: export GOPROXY := direct
remaster: .deps/go/prepared

View File

@@ -4,7 +4,7 @@ rem Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
setlocal enabledelayedexpansion
set BUILDDIR=%~dp0
set PATH=%BUILDDIR%.deps\llvm-mingw\bin;%BUILDDIR%.deps\go\bin;%BUILDDIR%.deps;%PATH%
set PATH=%BUILDDIR%.deps\llvm-mingw-20231128-ucrt-x86_64\bin;%BUILDDIR%.deps\go\bin;%BUILDDIR%.deps;%PATH%
set PATHEXT=.exe
cd /d %BUILDDIR% || exit /b 1
@@ -13,15 +13,14 @@ if exist .deps\prepared goto :render
rmdir /s /q .deps 2> NUL
mkdir .deps || goto :error
cd .deps || goto :error
call :download go.zip https://go.dev/dl/go1.18.windows-amd64.zip 65c5c0c709a7ca1b357091b10b795b439d8b50e579d3893edab4c7e9b384f435 || goto :error
rem Mirror of https://github.com/mstorsjo/llvm-mingw/releases/download/20201020/llvm-mingw-20201020-msvcrt-x86_64.zip
call :download llvm-mingw-msvcrt.zip https://download.wireguard.com/windows-toolchain/distfiles/llvm-mingw-20201020-msvcrt-x86_64.zip 2e46593245090df96d15e360e092f0b62b97e93866e0162dca7f93b16722b844 || goto :error
call :download go.zip https://go.dev/dl/go1.22.0.windows-amd64.zip 78b3158fe3aa358e0b6c9f26ecd338f9a11441e88bc434ae2e9f0ca2b0cc4dd3 || goto :error
call :download llvm-mingw-20231128-ucrt-x86_64.zip https://github.com/mstorsjo/llvm-mingw/releases/download/20231128/llvm-mingw-20231128-ucrt-x86_64.zip 7a344dafa6942de2c1f4643b3eb5c5ce5317fbab671a887e4d39f326b331798f || goto :error
rem Mirror of https://imagemagick.org/download/binaries/ImageMagick-7.0.8-42-portable-Q16-x64.zip
call :download imagemagick.zip https://download.wireguard.com/windows-toolchain/distfiles/ImageMagick-7.0.8-42-portable-Q16-x64.zip 584e069f56456ce7dde40220948ff9568ac810688c892c5dfb7f6db902aa05aa "convert.exe colors.xml delegates.xml" || goto :error
rem Mirror of https://sourceforge.net/projects/ezwinports/files/make-4.2.1-without-guile-w32-bin.zip
call :download make.zip https://download.wireguard.com/windows-toolchain/distfiles/make-4.2.1-without-guile-w32-bin.zip 30641be9602712be76212b99df7209f4f8f518ba764cf564262bc9d6e4047cc7 "--strip-components 1 bin" || goto :error
call :download wireguard-tools.zip https://git.zx2c4.com/wireguard-tools/snapshot/wireguard-tools-1ee37b8e4833a25efe6f1fc0d5bdcb476148f4ba.zip ed0739bc3e5a7021a59d4cc4fc63e5fb60a0cb8628d30515a747bfbdcf1fdb0a "--exclude wg-quick --strip-components 1" || goto :error
call :download wireguard-nt.zip https://download.wireguard.com/wireguard-nt/wireguard-nt-0.10.1.zip 772c0b1463d8d2212716f43f06f4594d880dea4f735165bd68e388fc41b81605 || goto :error
call :download wintun.zip https://www.wintun.net/builds/wintun-0.14.1.zip 07c256185d6ee3652e09fa55c0b673e2624b565e02c4b9091c79ca7d2f24ef51 || goto :error
copy /y NUL prepared > NUL || goto :error
cd .. || goto :error
@@ -71,7 +70,7 @@ if exist .deps\prepared goto :render
set GOARCH=%~3
mkdir %1 >NUL 2>&1
echo [+] Assembling resources %1
%~2-w64-mingw32-windres -I ".deps\wireguard-nt\bin\%~1" -DWIREGUARD_VERSION_ARRAY=%WIREGUARD_VERSION_ARRAY% -DWIREGUARD_VERSION_STR=%WIREGUARD_VERSION% -i resources.rc -o "resources_%~3.syso" -O coff -c 65001 || exit /b %errorlevel%
%~2-w64-mingw32-windres -DWIREGUARD_VERSION_ARRAY=%WIREGUARD_VERSION_ARRAY% -DWIREGUARD_VERSION_STR=%WIREGUARD_VERSION% -i resources.rc -o "resources_%~3.syso" -O coff -c 65001 || exit /b %errorlevel%
echo [+] Building program %1
go build -tags load_wgnt_from_rsrc -ldflags="-H windowsgui -s -w" -trimpath -buildvcs=false -v -o "%~1\wireguard.exe" || exit /b 1
if not exist "%~1\wg.exe" (
@@ -81,6 +80,9 @@ if exist .deps\prepared goto :render
make --no-print-directory -C .deps\src PLATFORM=windows CC=%~2-w64-mingw32-gcc WINDRES=%~2-w64-mingw32-windres V=1 RUNSTATEDIR= SYSTEMDUNITDIR= -j%NUMBER_OF_PROCESSORS% || exit /b 1
move /Y .deps\src\wg.exe "%~1\wg.exe" > NUL || exit /b 1
)
if not exist "%~1\wintun.dll" (
copy /Y ".deps\wintun\bin\%~1\wintun.dll" "%~1\wintun.dll" > NUL || exit /b 1
)
goto :eof
:error

View File

@@ -1,36 +0,0 @@
/* SPDX-License-Identifier: MIT
*
* Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package conf
import "golang.org/x/sys/windows/registry"
const adminRegKey = `Software\WireGuard`
var adminKey registry.Key
func openAdminKey() (registry.Key, error) {
if adminKey != 0 {
return adminKey, nil
}
var err error
adminKey, err = registry.OpenKey(registry.LOCAL_MACHINE, adminRegKey, registry.QUERY_VALUE|registry.WOW64_64KEY)
if err != nil {
return 0, err
}
return adminKey, nil
}
func AdminBool(name string) bool {
key, err := openAdminKey()
if err != nil {
return false
}
val, _, err := key.GetIntegerValue(name)
if err != nil {
return false
}
return val != 0
}

View File

@@ -1,248 +0,0 @@
/* SPDX-License-Identifier: MIT
*
* Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package conf
import (
"crypto/rand"
"crypto/subtle"
"encoding/base64"
"fmt"
"net/netip"
"strings"
"time"
"golang.org/x/crypto/curve25519"
"golang.zx2c4.com/wireguard/windows/l18n"
)
const KeyLength = 32
type Endpoint struct {
Host string
Port uint16
}
type (
Key [KeyLength]byte
HandshakeTime time.Duration
Bytes uint64
)
type Config struct {
Name string
Interface Interface
Peers []Peer
}
type Interface struct {
PrivateKey Key
Addresses []netip.Prefix
ListenPort uint16
MTU uint16
DNS []netip.Addr
DNSSearch []string
PreUp string
PostUp string
PreDown string
PostDown string
TableOff bool
}
type Peer struct {
PublicKey Key
PresharedKey Key
AllowedIPs []netip.Prefix
Endpoint Endpoint
PersistentKeepalive uint16
RxBytes Bytes
TxBytes Bytes
LastHandshakeTime HandshakeTime
}
func (conf *Config) IntersectsWith(other *Config) bool {
allRoutes := make(map[netip.Prefix]bool, len(conf.Interface.Addresses)*2+len(conf.Peers)*3)
for _, a := range conf.Interface.Addresses {
allRoutes[netip.PrefixFrom(a.Addr(), a.Addr().BitLen())] = true
allRoutes[a.Masked()] = true
}
for i := range conf.Peers {
for _, a := range conf.Peers[i].AllowedIPs {
allRoutes[a.Masked()] = true
}
}
for _, a := range other.Interface.Addresses {
if allRoutes[netip.PrefixFrom(a.Addr(), a.Addr().BitLen())] {
return true
}
if allRoutes[a.Masked()] {
return true
}
}
for i := range other.Peers {
for _, a := range other.Peers[i].AllowedIPs {
if allRoutes[a.Masked()] {
return true
}
}
}
return false
}
func (e *Endpoint) String() string {
if strings.IndexByte(e.Host, ':') != -1 {
return fmt.Sprintf("[%s]:%d", e.Host, e.Port)
}
return fmt.Sprintf("%s:%d", e.Host, e.Port)
}
func (e *Endpoint) IsEmpty() bool {
return len(e.Host) == 0
}
func (k *Key) String() string {
return base64.StdEncoding.EncodeToString(k[:])
}
func (k *Key) IsZero() bool {
var zeros Key
return subtle.ConstantTimeCompare(zeros[:], k[:]) == 1
}
func (k *Key) Public() *Key {
var p [KeyLength]byte
curve25519.ScalarBaseMult(&p, (*[KeyLength]byte)(k))
return (*Key)(&p)
}
func NewPresharedKey() (*Key, error) {
var k [KeyLength]byte
_, err := rand.Read(k[:])
if err != nil {
return nil, err
}
return (*Key)(&k), nil
}
func NewPrivateKey() (*Key, error) {
k, err := NewPresharedKey()
if err != nil {
return nil, err
}
k[0] &= 248
k[31] = (k[31] & 127) | 64
return k, nil
}
func NewPrivateKeyFromString(b64 string) (*Key, error) {
return parseKeyBase64(b64)
}
func (t HandshakeTime) IsEmpty() bool {
return t == HandshakeTime(0)
}
func (t HandshakeTime) String() string {
u := time.Unix(0, 0).Add(time.Duration(t)).Unix()
n := time.Now().Unix()
if u == n {
return l18n.Sprintf("Now")
} else if u > n {
return l18n.Sprintf("System clock wound backward!")
}
left := n - u
years := left / (365 * 24 * 60 * 60)
left = left % (365 * 24 * 60 * 60)
days := left / (24 * 60 * 60)
left = left % (24 * 60 * 60)
hours := left / (60 * 60)
left = left % (60 * 60)
minutes := left / 60
seconds := left % 60
s := make([]string, 0, 5)
if years > 0 {
s = append(s, l18n.Sprintf("%d year(s)", years))
}
if days > 0 {
s = append(s, l18n.Sprintf("%d day(s)", days))
}
if hours > 0 {
s = append(s, l18n.Sprintf("%d hour(s)", hours))
}
if minutes > 0 {
s = append(s, l18n.Sprintf("%d minute(s)", minutes))
}
if seconds > 0 {
s = append(s, l18n.Sprintf("%d second(s)", seconds))
}
timestamp := strings.Join(s, l18n.UnitSeparator())
return l18n.Sprintf("%s ago", timestamp)
}
func (b Bytes) String() string {
if b < 1024 {
return l18n.Sprintf("%d\u00a0B", b)
} else if b < 1024*1024 {
return l18n.Sprintf("%.2f\u00a0KiB", float64(b)/1024)
} else if b < 1024*1024*1024 {
return l18n.Sprintf("%.2f\u00a0MiB", float64(b)/(1024*1024))
} else if b < 1024*1024*1024*1024 {
return l18n.Sprintf("%.2f\u00a0GiB", float64(b)/(1024*1024*1024))
}
return l18n.Sprintf("%.2f\u00a0TiB", float64(b)/(1024*1024*1024)/1024)
}
func (conf *Config) DeduplicateNetworkEntries() {
m := make(map[string]bool, len(conf.Interface.Addresses))
i := 0
for _, addr := range conf.Interface.Addresses {
s := addr.String()
if m[s] {
continue
}
m[s] = true
conf.Interface.Addresses[i] = addr
i++
}
conf.Interface.Addresses = conf.Interface.Addresses[:i]
m = make(map[string]bool, len(conf.Interface.DNS))
i = 0
for _, addr := range conf.Interface.DNS {
s := addr.String()
if m[s] {
continue
}
m[s] = true
conf.Interface.DNS[i] = addr
i++
}
conf.Interface.DNS = conf.Interface.DNS[:i]
for _, peer := range conf.Peers {
m = make(map[string]bool, len(peer.AllowedIPs))
i = 0
for _, addr := range peer.AllowedIPs {
s := addr.String()
if m[s] {
continue
}
m[s] = true
peer.AllowedIPs[i] = addr
i++
}
peer.AllowedIPs = peer.AllowedIPs[:i]
}
}
func (conf *Config) Redact() {
conf.Interface.PrivateKey = Key{}
for i := range conf.Peers {
conf.Peers[i].PublicKey = Key{}
conf.Peers[i].PresharedKey = Key{}
}
}

View File

@@ -1,97 +0,0 @@
/* SPDX-License-Identifier: MIT
*
* Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package conf
import (
"log"
"net/netip"
"time"
"unsafe"
"golang.zx2c4.com/wireguard/windows/tunnel/winipcfg"
"golang.org/x/sys/windows"
"golang.zx2c4.com/wireguard/windows/services"
)
func resolveHostname(name string) (resolvedIPString string, err error) {
maxTries := 10
if services.StartedAtBoot() {
maxTries *= 3
}
for i := 0; i < maxTries; i++ {
if i > 0 {
time.Sleep(time.Second * 4)
}
resolvedIPString, err = resolveHostnameOnce(name)
if err == nil {
return
}
if err == windows.WSATRY_AGAIN {
log.Printf("Temporary DNS error when resolving %s, so sleeping for 4 seconds", name)
continue
}
if err == windows.WSAHOST_NOT_FOUND && services.StartedAtBoot() {
log.Printf("Host not found when resolving %s at boot time, so sleeping for 4 seconds", name)
continue
}
return
}
return
}
func resolveHostnameOnce(name string) (resolvedIPString string, err error) {
hints := windows.AddrinfoW{
Family: windows.AF_UNSPEC,
Socktype: windows.SOCK_DGRAM,
Protocol: windows.IPPROTO_IP,
}
var result *windows.AddrinfoW
name16, err := windows.UTF16PtrFromString(name)
if err != nil {
return
}
err = windows.GetAddrInfoW(name16, nil, &hints, &result)
if err != nil {
return
}
if result == nil {
err = windows.WSAHOST_NOT_FOUND
return
}
defer windows.FreeAddrInfoW(result)
var v6 netip.Addr
for ; result != nil; result = result.Next {
if result.Family != windows.AF_INET && result.Family != windows.AF_INET6 {
continue
}
addr := (*winipcfg.RawSockaddrInet)(unsafe.Pointer(result.Addr)).Addr()
if addr.Is4() {
return addr.String(), nil
} else if !v6.IsValid() && addr.Is6() {
v6 = addr
}
}
if v6.IsValid() {
return v6.String(), nil
}
err = windows.WSAHOST_NOT_FOUND
return
}
func (config *Config) ResolveEndpoints() error {
for i := range config.Peers {
if config.Peers[i].Endpoint.IsEmpty() {
continue
}
var err error
config.Peers[i].Endpoint.Host, err = resolveHostname(config.Peers[i].Endpoint.Host)
if err != nil {
return err
}
}
return nil
}

View File

@@ -1,75 +0,0 @@
/* SPDX-License-Identifier: MIT
*
* Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package dpapi
import (
"errors"
"fmt"
"runtime"
"unsafe"
"golang.org/x/sys/windows"
)
func bytesToBlob(bytes []byte) *windows.DataBlob {
blob := &windows.DataBlob{Size: uint32(len(bytes))}
if len(bytes) > 0 {
blob.Data = &bytes[0]
}
return blob
}
func Encrypt(data []byte, name string) ([]byte, error) {
out := windows.DataBlob{}
err := windows.CryptProtectData(bytesToBlob(data), windows.StringToUTF16Ptr(name), nil, 0, nil, windows.CRYPTPROTECT_UI_FORBIDDEN, &out)
if err != nil {
return nil, fmt.Errorf("unable to encrypt DPAPI protected data: %w", err)
}
ret := make([]byte, out.Size)
copy(ret, unsafe.Slice(out.Data, out.Size))
windows.LocalFree(windows.Handle(unsafe.Pointer(out.Data)))
return ret, nil
}
func Decrypt(data []byte, name string) ([]byte, error) {
out := windows.DataBlob{}
var outName *uint16
utf16Name, err := windows.UTF16PtrFromString(name)
if err != nil {
return nil, err
}
err = windows.CryptUnprotectData(bytesToBlob(data), &outName, nil, 0, nil, windows.CRYPTPROTECT_UI_FORBIDDEN, &out)
if err != nil {
return nil, fmt.Errorf("unable to decrypt DPAPI protected data: %w", err)
}
ret := make([]byte, out.Size)
copy(ret, unsafe.Slice(out.Data, out.Size))
windows.LocalFree(windows.Handle(unsafe.Pointer(out.Data)))
// Note: this ridiculous open-coded strcmp is not constant time.
different := false
a := outName
b := utf16Name
for {
if *a != *b {
different = true
break
}
if *a == 0 || *b == 0 {
break
}
a = (*uint16)(unsafe.Add(unsafe.Pointer(a), 2))
b = (*uint16)(unsafe.Add(unsafe.Pointer(b), 2))
}
runtime.KeepAlive(utf16Name)
windows.LocalFree(windows.Handle(unsafe.Pointer(outName)))
if different {
return nil, errors.New("input name does not match the stored name")
}
return ret, nil
}

View File

@@ -1,76 +0,0 @@
/* SPDX-License-Identifier: MIT
*
* Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package dpapi
import (
"bytes"
"testing"
"unsafe"
"golang.org/x/sys/windows"
)
func TestRoundTrip(t *testing.T) {
name := "golang test"
original := []byte("The quick brown fox jumped over the lazy dog")
e, err := Encrypt(original, name)
if err != nil {
t.Errorf("Error encrypting: %s", err.Error())
}
if len(e) < len(original) {
t.Error("Encrypted data is smaller than original data.")
}
d, err := Decrypt(e, name)
if err != nil {
t.Errorf("Error decrypting: %s", err.Error())
}
if !bytes.Equal(d, original) {
t.Error("Decrypted content does not match original")
}
_, err = Decrypt(e, "bad name")
if err == nil {
t.Error("Decryption failed to notice ad mismatch")
}
eCorrupt := make([]byte, len(e))
copy(eCorrupt, e)
eCorrupt[len(original)-1] = 7
_, err = Decrypt(eCorrupt, name)
if err == nil {
t.Error("Decryption failed to notice ciphertext corruption")
}
copy(eCorrupt, e)
nameUtf16, err := windows.UTF16FromString(name)
if err != nil {
t.Errorf("Unable to get utf16 chars for name: %s", err)
}
nameUtf16Bytes := unsafe.Slice((*byte)(unsafe.Pointer(&nameUtf16[0])), len(nameUtf16)*2)
i := bytes.Index(eCorrupt, nameUtf16Bytes)
if i == -1 {
t.Error("Unable to find ad in blob")
} else {
eCorrupt[i] = 7
_, err = Decrypt(eCorrupt, name)
if err == nil {
t.Error("Decryption failed to notice ad corruption")
}
}
// BUG: Actually, Windows doesn't report length extension of the buffer, unfortunately.
//
// eCorrupt = make([]byte, len(e)+1)
// copy(eCorrupt, e)
// _, err = Decrypt(eCorrupt, name)
// if err == nil {
// t.Error("Decryption failed to notice length extension")
// }
}

View File

@@ -1,90 +0,0 @@
/* SPDX-License-Identifier: MIT
*
* Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package conf
import (
"crypto/rand"
"encoding/hex"
"path/filepath"
"sync/atomic"
"unsafe"
"golang.org/x/sys/windows"
)
var encryptedFileSd unsafe.Pointer
func randomFileName() string {
var randBytes [32]byte
_, err := rand.Read(randBytes[:])
if err != nil {
panic(err)
}
return hex.EncodeToString(randBytes[:]) + ".tmp"
}
func writeLockedDownFile(destination string, overwrite bool, contents []byte) error {
var err error
sa := &windows.SecurityAttributes{Length: uint32(unsafe.Sizeof(windows.SecurityAttributes{}))}
sa.SecurityDescriptor = (*windows.SECURITY_DESCRIPTOR)(atomic.LoadPointer(&encryptedFileSd))
if sa.SecurityDescriptor == nil {
sa.SecurityDescriptor, err = windows.SecurityDescriptorFromString("O:SYG:SYD:PAI(A;;FA;;;SY)(A;;SD;;;BA)")
if err != nil {
return err
}
atomic.StorePointer(&encryptedFileSd, unsafe.Pointer(sa.SecurityDescriptor))
}
destination16, err := windows.UTF16FromString(destination)
if err != nil {
return err
}
tmpDestination := filepath.Join(filepath.Dir(destination), randomFileName())
tmpDestination16, err := windows.UTF16PtrFromString(tmpDestination)
if err != nil {
return err
}
handle, err := windows.CreateFile(tmpDestination16, windows.GENERIC_WRITE|windows.DELETE, windows.FILE_SHARE_READ, sa, windows.CREATE_ALWAYS, windows.FILE_ATTRIBUTE_NORMAL, 0)
if err != nil {
return err
}
defer windows.CloseHandle(handle)
deleteIt := func() {
yes := byte(1)
windows.SetFileInformationByHandle(handle, windows.FileDispositionInfo, &yes, 1)
}
n, err := windows.Write(handle, contents)
if err != nil {
deleteIt()
return err
}
if n != len(contents) {
deleteIt()
return windows.ERROR_IO_INCOMPLETE
}
fileRenameInfo := &struct {
replaceIfExists byte
rootDirectory windows.Handle
fileNameLength uint32
fileName [windows.MAX_PATH]uint16
}{replaceIfExists: func() byte {
if overwrite {
return 1
} else {
return 0
}
}(), fileNameLength: uint32(len(destination16) - 1)}
if len(destination16) > len(fileRenameInfo.fileName) {
deleteIt()
return windows.ERROR_BUFFER_OVERFLOW
}
copy(fileRenameInfo.fileName[:], destination16[:])
err = windows.SetFileInformationByHandle(handle, windows.FileRenameInfo, (*byte)(unsafe.Pointer(fileRenameInfo)), uint32(unsafe.Sizeof(*fileRenameInfo)))
if err != nil {
deleteIt()
return err
}
return nil
}

View File

@@ -1,109 +0,0 @@
/* SPDX-License-Identifier: MIT
*
* Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package conf
import (
"errors"
"io"
"log"
"os"
"path/filepath"
"strings"
"sync"
"time"
"golang.org/x/sys/windows"
)
var (
migrating sync.Mutex
lastMigrationTimer *time.Timer
)
type MigrationCallback func(name, oldPath, newPath string)
func MigrateUnencryptedConfigs(migrated MigrationCallback) { migrateUnencryptedConfigs(3, migrated) }
func migrateUnencryptedConfigs(sharingBase int, migrated MigrationCallback) {
if migrated == nil {
migrated = func(_, _, _ string) {}
}
migrating.Lock()
defer migrating.Unlock()
configFileDir, err := tunnelConfigurationsDirectory()
if err != nil {
return
}
files, err := os.ReadDir(configFileDir)
if err != nil {
return
}
ignoreSharingViolations := false
for _, file := range files {
path := filepath.Join(configFileDir, file.Name())
name := filepath.Base(file.Name())
if len(name) <= len(configFileUnencryptedSuffix) || !strings.HasSuffix(name, configFileUnencryptedSuffix) {
continue
}
if !file.Type().IsRegular() {
continue
}
info, err := file.Info()
if err != nil {
continue
}
if info.Mode().Perm()&0o444 == 0 {
continue
}
var bytes []byte
var config *Config
var newPath string
// We don't use os.ReadFile, because we actually want RDWR, so that we can take advantage
// of Windows file locking for ensuring the file is finished being written.
f, err := os.OpenFile(path, os.O_RDWR, 0)
if err != nil {
if errors.Is(err, windows.ERROR_SHARING_VIOLATION) {
if ignoreSharingViolations {
continue
} else if sharingBase > 0 {
if lastMigrationTimer != nil {
lastMigrationTimer.Stop()
}
lastMigrationTimer = time.AfterFunc(time.Second/time.Duration(sharingBase*sharingBase), func() { migrateUnencryptedConfigs(sharingBase-1, migrated) })
ignoreSharingViolations = true
continue
}
}
goto error
}
bytes, err = io.ReadAll(f)
f.Close()
if err != nil {
goto error
}
config, err = FromWgQuickWithUnknownEncoding(string(bytes), strings.TrimSuffix(name, configFileUnencryptedSuffix))
if err != nil {
goto error
}
err = config.Save(false)
if err != nil {
goto error
}
err = os.Remove(path)
if err != nil {
goto error
}
newPath, err = config.Path()
if err != nil {
goto error
}
migrated(config.Name, path, newPath)
continue
error:
log.Printf("Unable to ingest and encrypt %#q: %v", path, err)
}
}

View File

@@ -1,127 +0,0 @@
/* SPDX-License-Identifier: MIT
*
* Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package conf
import (
"errors"
"regexp"
"strconv"
"strings"
)
var reservedNames = []string{
"CON", "PRN", "AUX", "NUL",
"COM1", "COM2", "COM3", "COM4", "COM5", "COM6", "COM7", "COM8", "COM9",
"LPT1", "LPT2", "LPT3", "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", "LPT9",
}
const (
serviceNameForbidden = "$"
netshellDllForbidden = "\\/:*?\"<>|\t"
specialChars = "/\\<>:\"|?*\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x00"
)
var allowedNameFormat = regexp.MustCompile("^[a-zA-Z0-9_=+.-]{1,32}$")
func isReserved(name string) bool {
if len(name) == 0 {
return false
}
for _, reserved := range reservedNames {
if strings.EqualFold(name, reserved) {
return true
}
for i := len(name) - 1; i >= 0; i-- {
if name[i] == '.' {
if strings.EqualFold(name[:i], reserved) {
return true
}
break
}
}
}
return false
}
func hasSpecialChars(name string) bool {
return strings.ContainsAny(name, specialChars) || strings.ContainsAny(name, netshellDllForbidden) || strings.ContainsAny(name, serviceNameForbidden)
}
func TunnelNameIsValid(name string) bool {
// Aside from our own restrictions, let's impose the Windows restrictions first
if isReserved(name) || hasSpecialChars(name) {
return false
}
return allowedNameFormat.MatchString(name)
}
type naturalSortToken struct {
maybeString string
maybeNumber int
}
type naturalSortString struct {
originalString string
tokens []naturalSortToken
}
var naturalSortDigitFinder = regexp.MustCompile(`\d+|\D+`)
func newNaturalSortString(s string) (t naturalSortString) {
t.originalString = s
s = strings.ToLower(strings.Join(strings.Fields(s), " "))
x := naturalSortDigitFinder.FindAllString(s, -1)
t.tokens = make([]naturalSortToken, len(x))
for i, s := range x {
if n, err := strconv.Atoi(s); err == nil {
t.tokens[i].maybeNumber = n
} else {
t.tokens[i].maybeString = s
}
}
return
}
func (f1 naturalSortToken) Cmp(f2 naturalSortToken) int {
if len(f1.maybeString) == 0 {
if len(f2.maybeString) > 0 || f1.maybeNumber < f2.maybeNumber {
return -1
} else if f1.maybeNumber > f2.maybeNumber {
return 1
}
} else if len(f2.maybeString) == 0 || f1.maybeString > f2.maybeString {
return 1
} else if f1.maybeString < f2.maybeString {
return -1
}
return 0
}
func TunnelNameIsLess(a, b string) bool {
if a == b {
return false
}
na, nb := newNaturalSortString(a), newNaturalSortString(b)
for i, t := range nb.tokens {
if i == len(na.tokens) {
return true
}
switch na.tokens[i].Cmp(t) {
case -1:
return true
case 1:
return false
}
}
return false
}
func ServiceNameOfTunnel(tunnelName string) (string, error) {
if !TunnelNameIsValid(tunnelName) {
return "", errors.New("Tunnel name is not valid")
}
return "WireGuardTunnel$" + tunnelName, nil
}

View File

@@ -1,400 +0,0 @@
/* SPDX-License-Identifier: MIT
*
* Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package conf
import (
"encoding/base64"
"net/netip"
"strconv"
"strings"
"golang.org/x/sys/windows"
"golang.org/x/text/encoding/unicode"
"golang.zx2c4.com/wireguard/windows/driver"
"golang.zx2c4.com/wireguard/windows/l18n"
)
type ParseError struct {
why string
offender string
}
func (e *ParseError) Error() string {
return l18n.Sprintf("%s: %q", e.why, e.offender)
}
func parseIPCidr(s string) (netip.Prefix, error) {
ipcidr, err := netip.ParsePrefix(s)
if err == nil {
return ipcidr, nil
}
addr, err := netip.ParseAddr(s)
if err != nil {
return netip.Prefix{}, &ParseError{l18n.Sprintf("Invalid IP address: "), s}
}
return netip.PrefixFrom(addr, addr.BitLen()), nil
}
func parseEndpoint(s string) (*Endpoint, error) {
i := strings.LastIndexByte(s, ':')
if i < 0 {
return nil, &ParseError{l18n.Sprintf("Missing port from endpoint"), s}
}
host, portStr := s[:i], s[i+1:]
if len(host) < 1 {
return nil, &ParseError{l18n.Sprintf("Invalid endpoint host"), host}
}
port, err := parsePort(portStr)
if err != nil {
return nil, err
}
hostColon := strings.IndexByte(host, ':')
if host[0] == '[' || host[len(host)-1] == ']' || hostColon > 0 {
err := &ParseError{l18n.Sprintf("Brackets must contain an IPv6 address"), host}
if len(host) > 3 && host[0] == '[' && host[len(host)-1] == ']' && hostColon > 0 {
end := len(host) - 1
if i := strings.LastIndexByte(host, '%'); i > 1 {
end = i
}
maybeV6, err2 := netip.ParseAddr(host[1:end])
if err2 != nil || !maybeV6.Is6() {
return nil, err
}
} else {
return nil, err
}
host = host[1 : len(host)-1]
}
return &Endpoint{host, port}, nil
}
func parseMTU(s string) (uint16, error) {
m, err := strconv.Atoi(s)
if err != nil {
return 0, err
}
if m < 576 || m > 65535 {
return 0, &ParseError{l18n.Sprintf("Invalid MTU"), s}
}
return uint16(m), nil
}
func parsePort(s string) (uint16, error) {
m, err := strconv.Atoi(s)
if err != nil {
return 0, err
}
if m < 0 || m > 65535 {
return 0, &ParseError{l18n.Sprintf("Invalid port"), s}
}
return uint16(m), nil
}
func parsePersistentKeepalive(s string) (uint16, error) {
if s == "off" {
return 0, nil
}
m, err := strconv.Atoi(s)
if err != nil {
return 0, err
}
if m < 0 || m > 65535 {
return 0, &ParseError{l18n.Sprintf("Invalid persistent keepalive"), s}
}
return uint16(m), nil
}
func parseTableOff(s string) (bool, error) {
if s == "off" {
return true, nil
} else if s == "auto" || s == "main" {
return false, nil
}
_, err := strconv.ParseUint(s, 10, 32)
return false, err
}
func parseKeyBase64(s string) (*Key, error) {
k, err := base64.StdEncoding.DecodeString(s)
if err != nil {
return nil, &ParseError{l18n.Sprintf("Invalid key: %v", err), s}
}
if len(k) != KeyLength {
return nil, &ParseError{l18n.Sprintf("Keys must decode to exactly 32 bytes"), s}
}
var key Key
copy(key[:], k)
return &key, nil
}
func splitList(s string) ([]string, error) {
var out []string
for _, split := range strings.Split(s, ",") {
trim := strings.TrimSpace(split)
if len(trim) == 0 {
return nil, &ParseError{l18n.Sprintf("Two commas in a row"), s}
}
out = append(out, trim)
}
return out, nil
}
type parserState int
const (
inInterfaceSection parserState = iota
inPeerSection
notInASection
)
func (c *Config) maybeAddPeer(p *Peer) {
if p != nil {
c.Peers = append(c.Peers, *p)
}
}
func FromWgQuick(s, name string) (*Config, error) {
if !TunnelNameIsValid(name) {
return nil, &ParseError{l18n.Sprintf("Tunnel name is not valid"), name}
}
lines := strings.Split(s, "\n")
parserState := notInASection
conf := Config{Name: name}
sawPrivateKey := false
var peer *Peer
for _, line := range lines {
line, _, _ = strings.Cut(line, "#")
line = strings.TrimSpace(line)
lineLower := strings.ToLower(line)
if len(line) == 0 {
continue
}
if lineLower == "[interface]" {
conf.maybeAddPeer(peer)
parserState = inInterfaceSection
continue
}
if lineLower == "[peer]" {
conf.maybeAddPeer(peer)
peer = &Peer{}
parserState = inPeerSection
continue
}
if parserState == notInASection {
return nil, &ParseError{l18n.Sprintf("Line must occur in a section"), line}
}
equals := strings.IndexByte(line, '=')
if equals < 0 {
return nil, &ParseError{l18n.Sprintf("Config key is missing an equals separator"), line}
}
key, val := strings.TrimSpace(lineLower[:equals]), strings.TrimSpace(line[equals+1:])
if len(val) == 0 {
return nil, &ParseError{l18n.Sprintf("Key must have a value"), line}
}
if parserState == inInterfaceSection {
switch key {
case "privatekey":
k, err := parseKeyBase64(val)
if err != nil {
return nil, err
}
conf.Interface.PrivateKey = *k
sawPrivateKey = true
case "listenport":
p, err := parsePort(val)
if err != nil {
return nil, err
}
conf.Interface.ListenPort = p
case "mtu":
m, err := parseMTU(val)
if err != nil {
return nil, err
}
conf.Interface.MTU = m
case "address":
addresses, err := splitList(val)
if err != nil {
return nil, err
}
for _, address := range addresses {
a, err := parseIPCidr(address)
if err != nil {
return nil, err
}
conf.Interface.Addresses = append(conf.Interface.Addresses, a)
}
case "dns":
addresses, err := splitList(val)
if err != nil {
return nil, err
}
for _, address := range addresses {
a, err := netip.ParseAddr(address)
if err != nil {
conf.Interface.DNSSearch = append(conf.Interface.DNSSearch, address)
} else {
conf.Interface.DNS = append(conf.Interface.DNS, a)
}
}
case "preup":
conf.Interface.PreUp = val
case "postup":
conf.Interface.PostUp = val
case "predown":
conf.Interface.PreDown = val
case "postdown":
conf.Interface.PostDown = val
case "table":
tableOff, err := parseTableOff(val)
if err != nil {
return nil, err
}
conf.Interface.TableOff = tableOff
default:
return nil, &ParseError{l18n.Sprintf("Invalid key for [Interface] section"), key}
}
} else if parserState == inPeerSection {
switch key {
case "publickey":
k, err := parseKeyBase64(val)
if err != nil {
return nil, err
}
peer.PublicKey = *k
case "presharedkey":
k, err := parseKeyBase64(val)
if err != nil {
return nil, err
}
peer.PresharedKey = *k
case "allowedips":
addresses, err := splitList(val)
if err != nil {
return nil, err
}
for _, address := range addresses {
a, err := parseIPCidr(address)
if err != nil {
return nil, err
}
peer.AllowedIPs = append(peer.AllowedIPs, a)
}
case "persistentkeepalive":
p, err := parsePersistentKeepalive(val)
if err != nil {
return nil, err
}
peer.PersistentKeepalive = p
case "endpoint":
e, err := parseEndpoint(val)
if err != nil {
return nil, err
}
peer.Endpoint = *e
default:
return nil, &ParseError{l18n.Sprintf("Invalid key for [Peer] section"), key}
}
}
}
conf.maybeAddPeer(peer)
if !sawPrivateKey {
return nil, &ParseError{l18n.Sprintf("An interface must have a private key"), l18n.Sprintf("[none specified]")}
}
for _, p := range conf.Peers {
if p.PublicKey.IsZero() {
return nil, &ParseError{l18n.Sprintf("All peers must have public keys"), l18n.Sprintf("[none specified]")}
}
}
return &conf, nil
}
func FromWgQuickWithUnknownEncoding(s, name string) (*Config, error) {
c, firstErr := FromWgQuick(s, name)
if firstErr == nil {
return c, nil
}
for _, encoding := range unicode.All {
decoded, err := encoding.NewDecoder().String(s)
if err == nil {
c, err := FromWgQuick(decoded, name)
if err == nil {
return c, nil
}
}
}
return nil, firstErr
}
func FromDriverConfiguration(interfaze *driver.Interface, existingConfig *Config) *Config {
conf := Config{
Name: existingConfig.Name,
Interface: Interface{
Addresses: existingConfig.Interface.Addresses,
DNS: existingConfig.Interface.DNS,
DNSSearch: existingConfig.Interface.DNSSearch,
MTU: existingConfig.Interface.MTU,
PreUp: existingConfig.Interface.PreUp,
PostUp: existingConfig.Interface.PostUp,
PreDown: existingConfig.Interface.PreDown,
PostDown: existingConfig.Interface.PostDown,
TableOff: existingConfig.Interface.TableOff,
},
}
if interfaze.Flags&driver.InterfaceHasPrivateKey != 0 {
conf.Interface.PrivateKey = interfaze.PrivateKey
}
if interfaze.Flags&driver.InterfaceHasListenPort != 0 {
conf.Interface.ListenPort = interfaze.ListenPort
}
var p *driver.Peer
for i := uint32(0); i < interfaze.PeerCount; i++ {
if p == nil {
p = interfaze.FirstPeer()
} else {
p = p.NextPeer()
}
peer := Peer{}
if p.Flags&driver.PeerHasPublicKey != 0 {
peer.PublicKey = p.PublicKey
}
if p.Flags&driver.PeerHasPresharedKey != 0 {
peer.PresharedKey = p.PresharedKey
}
if p.Flags&driver.PeerHasEndpoint != 0 {
peer.Endpoint.Port = p.Endpoint.Port()
peer.Endpoint.Host = p.Endpoint.Addr().String()
}
if p.Flags&driver.PeerHasPersistentKeepalive != 0 {
peer.PersistentKeepalive = p.PersistentKeepalive
}
peer.TxBytes = Bytes(p.TxBytes)
peer.RxBytes = Bytes(p.RxBytes)
if p.LastHandshake != 0 {
peer.LastHandshakeTime = HandshakeTime((p.LastHandshake - 116444736000000000) * 100)
}
var a *driver.AllowedIP
for j := uint32(0); j < p.AllowedIPsCount; j++ {
if a == nil {
a = p.FirstAllowedIP()
} else {
a = a.NextAllowedIP()
}
var ip netip.Addr
if a.AddressFamily == windows.AF_INET {
ip = netip.AddrFrom4(*(*[4]byte)(a.Address[:4]))
} else if a.AddressFamily == windows.AF_INET6 {
ip = netip.AddrFrom16(*(*[16]byte)(a.Address[:16]))
}
peer.AllowedIPs = append(peer.AllowedIPs, netip.PrefixFrom(ip, int(a.Cidr)))
}
conf.Peers = append(conf.Peers, peer)
}
return &conf
}

View File

@@ -1,129 +0,0 @@
/* SPDX-License-Identifier: MIT
*
* Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package conf
import (
"net/netip"
"reflect"
"runtime"
"testing"
)
const testInput = `
[Interface]
Address = 10.192.122.1/24
Address = 10.10.0.1/16
PrivateKey = yAnz5TF+lXXJte14tji3zlMNq+hd2rYUIgJBgB3fBmk=
ListenPort = 51820 #comments don't matter
[Peer]
PublicKey = xTIBA5rboUvnH4htodjb6e697QjLERt1NAB4mZqp8Dg=
Endpoint = 192.95.5.67:1234
AllowedIPs = 10.192.122.3/32, 10.192.124.1/24
[Peer]
PublicKey = TrMvSoP4jYQlY6RIzBgbssQqY3vxI2Pi+y71lOWWXX0=
Endpoint = [2607:5300:60:6b0::c05f:543]:2468
AllowedIPs = 10.192.122.4/32, 192.168.0.0/16
PersistentKeepalive = 100
[Peer]
PublicKey = gN65BkIKy1eCE9pP1wdc8ROUtkHLF2PfAqYdyYBz6EA=
PresharedKey = TrMvSoP4jYQlY6RIzBgbssQqY3vxI2Pi+y71lOWWXX0=
Endpoint = test.wireguard.com:18981
AllowedIPs = 10.10.10.230/32`
func noError(t *testing.T, err error) bool {
if err == nil {
return true
}
_, fn, line, _ := runtime.Caller(1)
t.Errorf("Error at %s:%d: %#v", fn, line, err)
return false
}
func equal(t *testing.T, expected, actual any) bool {
if reflect.DeepEqual(expected, actual) {
return true
}
_, fn, line, _ := runtime.Caller(1)
t.Errorf("Failed equals at %s:%d\nactual %#v\nexpected %#v", fn, line, actual, expected)
return false
}
func lenTest(t *testing.T, actualO any, expected int) bool {
actual := reflect.ValueOf(actualO).Len()
if reflect.DeepEqual(expected, actual) {
return true
}
_, fn, line, _ := runtime.Caller(1)
t.Errorf("Wrong length at %s:%d\nactual %#v\nexpected %#v", fn, line, actual, expected)
return false
}
func contains(t *testing.T, list, element any) bool {
listValue := reflect.ValueOf(list)
for i := 0; i < listValue.Len(); i++ {
if reflect.DeepEqual(listValue.Index(i).Interface(), element) {
return true
}
}
_, fn, line, _ := runtime.Caller(1)
t.Errorf("Error %s:%d\nelement not found: %#v", fn, line, element)
return false
}
func TestFromWgQuick(t *testing.T) {
conf, err := FromWgQuick(testInput, "test")
if noError(t, err) {
lenTest(t, conf.Interface.Addresses, 2)
contains(t, conf.Interface.Addresses, netip.PrefixFrom(netip.AddrFrom4([4]byte{0, 10, 0, 1}), 16))
contains(t, conf.Interface.Addresses, netip.PrefixFrom(netip.AddrFrom4([4]byte{10, 192, 122, 1}), 24))
equal(t, "yAnz5TF+lXXJte14tji3zlMNq+hd2rYUIgJBgB3fBmk=", conf.Interface.PrivateKey.String())
equal(t, uint16(51820), conf.Interface.ListenPort)
lenTest(t, conf.Peers, 3)
lenTest(t, conf.Peers[0].AllowedIPs, 2)
equal(t, Endpoint{Host: "192.95.5.67", Port: 1234}, conf.Peers[0].Endpoint)
equal(t, "xTIBA5rboUvnH4htodjb6e697QjLERt1NAB4mZqp8Dg=", conf.Peers[0].PublicKey.String())
lenTest(t, conf.Peers[1].AllowedIPs, 2)
equal(t, Endpoint{Host: "2607:5300:60:6b0::c05f:543", Port: 2468}, conf.Peers[1].Endpoint)
equal(t, "TrMvSoP4jYQlY6RIzBgbssQqY3vxI2Pi+y71lOWWXX0=", conf.Peers[1].PublicKey.String())
equal(t, uint16(100), conf.Peers[1].PersistentKeepalive)
lenTest(t, conf.Peers[2].AllowedIPs, 1)
equal(t, Endpoint{Host: "test.wireguard.com", Port: 18981}, conf.Peers[2].Endpoint)
equal(t, "gN65BkIKy1eCE9pP1wdc8ROUtkHLF2PfAqYdyYBz6EA=", conf.Peers[2].PublicKey.String())
equal(t, "TrMvSoP4jYQlY6RIzBgbssQqY3vxI2Pi+y71lOWWXX0=", conf.Peers[2].PresharedKey.String())
}
}
func TestParseEndpoint(t *testing.T) {
_, err := parseEndpoint("[192.168.42.0:]:51880")
if err == nil {
t.Error("Error was expected")
}
e, err := parseEndpoint("192.168.42.0:51880")
if noError(t, err) {
equal(t, "192.168.42.0", e.Host)
equal(t, uint16(51880), e.Port)
}
e, err = parseEndpoint("test.wireguard.com:18981")
if noError(t, err) {
equal(t, "test.wireguard.com", e.Host)
equal(t, uint16(18981), e.Port)
}
e, err = parseEndpoint("[2607:5300:60:6b0::c05f:543]:2468")
if noError(t, err) {
equal(t, "2607:5300:60:6b0::c05f:543", e.Host)
equal(t, uint16(2468), e.Port)
}
_, err = parseEndpoint("[::::::invalid:18981")
if err == nil {
t.Error("Error was expected")
}
}

View File

@@ -1,138 +0,0 @@
/* SPDX-License-Identifier: MIT
*
* Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package conf
import (
"errors"
"os"
"path/filepath"
"strings"
"unsafe"
"golang.org/x/sys/windows"
)
var (
cachedConfigFileDir string
cachedRootDir string
)
func tunnelConfigurationsDirectory() (string, error) {
if cachedConfigFileDir != "" {
return cachedConfigFileDir, nil
}
root, err := RootDirectory(true)
if err != nil {
return "", err
}
c := filepath.Join(root, "Configurations")
err = os.Mkdir(c, os.ModeDir|0o700)
if err != nil && !os.IsExist(err) {
return "", err
}
cachedConfigFileDir = c
return cachedConfigFileDir, nil
}
// PresetRootDirectory causes RootDirectory() to not try any automatic deduction, and instead
// uses what's passed to it. This isn't used by wireguard-windows, but is useful for external
// consumers of our libraries who might want to do strange things.
func PresetRootDirectory(root string) {
cachedRootDir = root
}
func RootDirectory(create bool) (string, error) {
if cachedRootDir != "" {
return cachedRootDir, nil
}
root, err := windows.KnownFolderPath(windows.FOLDERID_ProgramFiles, windows.KF_FLAG_DEFAULT)
if err != nil {
return "", err
}
root = filepath.Join(root, "WireGuard")
if !create {
return filepath.Join(root, "Data"), nil
}
root16, err := windows.UTF16PtrFromString(root)
if err != nil {
return "", err
}
// The root directory inherits its ACL from Program Files; we don't want to mess with that
err = windows.CreateDirectory(root16, nil)
if err != nil && err != windows.ERROR_ALREADY_EXISTS {
return "", err
}
dataDirectorySd, err := windows.SecurityDescriptorFromString("O:SYG:SYD:PAI(A;OICI;FA;;;SY)(A;OICI;FA;;;BA)")
if err != nil {
return "", err
}
dataDirectorySa := &windows.SecurityAttributes{
Length: uint32(unsafe.Sizeof(windows.SecurityAttributes{})),
SecurityDescriptor: dataDirectorySd,
}
data := filepath.Join(root, "Data")
data16, err := windows.UTF16PtrFromString(data)
if err != nil {
return "", err
}
var dataHandle windows.Handle
for {
err = windows.CreateDirectory(data16, dataDirectorySa)
if err != nil && err != windows.ERROR_ALREADY_EXISTS {
return "", err
}
dataHandle, err = windows.CreateFile(data16, windows.READ_CONTROL|windows.WRITE_OWNER|windows.WRITE_DAC, windows.FILE_SHARE_READ|windows.FILE_SHARE_WRITE|windows.FILE_SHARE_DELETE, nil, windows.OPEN_EXISTING, windows.FILE_FLAG_BACKUP_SEMANTICS|windows.FILE_FLAG_OPEN_REPARSE_POINT|windows.FILE_ATTRIBUTE_DIRECTORY, 0)
if err != nil && err != windows.ERROR_FILE_NOT_FOUND {
return "", err
}
if err == nil {
break
}
}
defer windows.CloseHandle(dataHandle)
var fileInfo windows.ByHandleFileInformation
err = windows.GetFileInformationByHandle(dataHandle, &fileInfo)
if err != nil {
return "", err
}
if fileInfo.FileAttributes&windows.FILE_ATTRIBUTE_DIRECTORY == 0 {
return "", errors.New("Data directory is actually a file")
}
if fileInfo.FileAttributes&windows.FILE_ATTRIBUTE_REPARSE_POINT != 0 {
return "", errors.New("Data directory is reparse point")
}
buf := make([]uint16, windows.MAX_PATH+4)
for {
bufLen, err := windows.GetFinalPathNameByHandle(dataHandle, &buf[0], uint32(len(buf)), 0)
if err != nil {
return "", err
}
if bufLen < uint32(len(buf)) {
break
}
buf = make([]uint16, bufLen)
}
if !strings.EqualFold(`\\?\`+data, windows.UTF16ToString(buf[:])) {
return "", errors.New("Data directory jumped to unexpected location")
}
err = windows.SetKernelObjectSecurity(dataHandle, windows.DACL_SECURITY_INFORMATION|windows.GROUP_SECURITY_INFORMATION|windows.OWNER_SECURITY_INFORMATION|windows.PROTECTED_DACL_SECURITY_INFORMATION, dataDirectorySd)
if err != nil {
return "", err
}
cachedRootDir = data
return cachedRootDir, nil
}
func LogFile(createRoot bool) (string, error) {
root, err := RootDirectory(createRoot)
if err != nil {
return "", err
}
return filepath.Join(root, "log.bin"), nil
}

View File

@@ -1,142 +0,0 @@
/* SPDX-License-Identifier: MIT
*
* Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package conf
import (
"errors"
"os"
"path/filepath"
"strings"
"golang.zx2c4.com/wireguard/windows/conf/dpapi"
)
const (
configFileSuffix = ".conf.dpapi"
configFileUnencryptedSuffix = ".conf"
)
func ListConfigNames() ([]string, error) {
configFileDir, err := tunnelConfigurationsDirectory()
if err != nil {
return nil, err
}
files, err := os.ReadDir(configFileDir)
if err != nil {
return nil, err
}
configs := make([]string, len(files))
i := 0
for _, file := range files {
name, err := NameFromPath(file.Name())
if err != nil {
continue
}
if !file.Type().IsRegular() {
continue
}
info, err := file.Info()
if err != nil {
continue
}
if info.Mode().Perm()&0o444 == 0 {
continue
}
configs[i] = name
i++
}
return configs[:i], nil
}
func LoadFromName(name string) (*Config, error) {
configFileDir, err := tunnelConfigurationsDirectory()
if err != nil {
return nil, err
}
return LoadFromPath(filepath.Join(configFileDir, name+configFileSuffix))
}
func LoadFromPath(path string) (*Config, error) {
name, err := NameFromPath(path)
if err != nil {
return nil, err
}
bytes, err := os.ReadFile(path)
if err != nil {
return nil, err
}
if strings.HasSuffix(path, configFileSuffix) {
bytes, err = dpapi.Decrypt(bytes, name)
if err != nil {
return nil, err
}
}
return FromWgQuickWithUnknownEncoding(string(bytes), name)
}
func PathIsEncrypted(path string) bool {
return strings.HasSuffix(filepath.Base(path), configFileSuffix)
}
func NameFromPath(path string) (string, error) {
name := filepath.Base(path)
if !((len(name) > len(configFileSuffix) && strings.HasSuffix(name, configFileSuffix)) ||
(len(name) > len(configFileUnencryptedSuffix) && strings.HasSuffix(name, configFileUnencryptedSuffix))) {
return "", errors.New("Path must end in either " + configFileSuffix + " or " + configFileUnencryptedSuffix)
}
if strings.HasSuffix(path, configFileSuffix) {
name = strings.TrimSuffix(name, configFileSuffix)
} else {
name = strings.TrimSuffix(name, configFileUnencryptedSuffix)
}
if !TunnelNameIsValid(name) {
return "", errors.New("Tunnel name is not valid")
}
return name, nil
}
func (config *Config) Save(overwrite bool) error {
if !TunnelNameIsValid(config.Name) {
return errors.New("Tunnel name is not valid")
}
configFileDir, err := tunnelConfigurationsDirectory()
if err != nil {
return err
}
filename := filepath.Join(configFileDir, config.Name+configFileSuffix)
bytes := []byte(config.ToWgQuick())
bytes, err = dpapi.Encrypt(bytes, config.Name)
if err != nil {
return err
}
return writeLockedDownFile(filename, overwrite, bytes)
}
func (config *Config) Path() (string, error) {
if !TunnelNameIsValid(config.Name) {
return "", errors.New("Tunnel name is not valid")
}
configFileDir, err := tunnelConfigurationsDirectory()
if err != nil {
return "", err
}
return filepath.Join(configFileDir, config.Name+configFileSuffix), nil
}
func DeleteName(name string) error {
if !TunnelNameIsValid(name) {
return errors.New("Tunnel name is not valid")
}
configFileDir, err := tunnelConfigurationsDirectory()
if err != nil {
return err
}
return os.Remove(filepath.Join(configFileDir, name+configFileSuffix))
}
func (config *Config) Delete() error {
return DeleteName(config.Name)
}

View File

@@ -1,95 +0,0 @@
/* SPDX-License-Identifier: MIT
*
* Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package conf
import (
"reflect"
"testing"
)
func TestStorage(t *testing.T) {
c, err := FromWgQuick(testInput, "golangTest")
if err != nil {
t.Errorf("Unable to parse test config: %s", err.Error())
return
}
err = c.Save(true)
if err != nil {
t.Errorf("Unable to save config: %s", err.Error())
}
configs, err := ListConfigNames()
if err != nil {
t.Errorf("Unable to list configs: %s", err.Error())
}
found := false
for _, name := range configs {
if name == "golangTest" {
found = true
break
}
}
if !found {
t.Error("Unable to find saved config in list")
}
loaded, err := LoadFromName("golangTest")
if err != nil {
t.Errorf("Unable to load config: %s", err.Error())
return
}
if !reflect.DeepEqual(loaded, c) {
t.Error("Loaded config is not the same as saved config")
}
k, err := NewPrivateKey()
if err != nil {
t.Errorf("Unable to generate new private key: %s", err.Error())
}
c.Interface.PrivateKey = *k
err = c.Save(false)
if err == nil {
t.Error("Config disappeared or was unexpectedly overwritten")
}
err = c.Save(true)
if err != nil {
t.Errorf("Unable to save config a second time: %s", err.Error())
}
loaded, err = LoadFromName("golangTest")
if err != nil {
t.Errorf("Unable to load config a second time: %s", err.Error())
return
}
if !reflect.DeepEqual(loaded, c) {
t.Error("Second loaded config is not the same as second saved config")
}
err = DeleteName("golangTest")
if err != nil {
t.Errorf("Unable to delete config: %s", err.Error())
}
configs, err = ListConfigNames()
if err != nil {
t.Errorf("Unable to list configs: %s", err.Error())
}
found = false
for _, name := range configs {
if name == "golangTest" {
found = true
break
}
}
if found {
t.Error("Config wasn't actually deleted")
}
}

View File

@@ -1,24 +0,0 @@
/* SPDX-License-Identifier: MIT
*
* Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package conf
type StoreCallback struct {
cb func()
}
var storeCallbacks = make(map[*StoreCallback]bool)
func RegisterStoreChangeCallback(cb func()) *StoreCallback {
startWatchingConfigDir()
cb()
s := &StoreCallback{cb}
storeCallbacks[s] = true
return s
}
func (cb *StoreCallback) Unregister() {
delete(storeCallbacks, cb)
}

View File

@@ -1,61 +0,0 @@
/* SPDX-License-Identifier: MIT
*
* Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package conf
import (
"log"
"golang.org/x/sys/windows"
)
var haveStartedWatchingConfigDir bool
func startWatchingConfigDir() {
if haveStartedWatchingConfigDir {
return
}
haveStartedWatchingConfigDir = true
go func() {
h := windows.InvalidHandle
defer func() {
if h != windows.InvalidHandle {
windows.FindCloseChangeNotification(h)
}
haveStartedWatchingConfigDir = false
}()
startover:
configFileDir, err := tunnelConfigurationsDirectory()
if err != nil {
return
}
h, err = windows.FindFirstChangeNotification(configFileDir, true, windows.FILE_NOTIFY_CHANGE_FILE_NAME|windows.FILE_NOTIFY_CHANGE_DIR_NAME|windows.FILE_NOTIFY_CHANGE_ATTRIBUTES|windows.FILE_NOTIFY_CHANGE_SIZE|windows.FILE_NOTIFY_CHANGE_LAST_WRITE|windows.FILE_NOTIFY_CHANGE_LAST_ACCESS|windows.FILE_NOTIFY_CHANGE_CREATION|windows.FILE_NOTIFY_CHANGE_SECURITY)
if err != nil {
log.Printf("Unable to monitor config directory: %v", err)
return
}
for {
s, err := windows.WaitForSingleObject(h, windows.INFINITE)
if err != nil || s == windows.WAIT_FAILED {
log.Printf("Unable to wait on config directory watcher: %v", err)
windows.FindCloseChangeNotification(h)
h = windows.InvalidHandle
goto startover
}
for cb := range storeCallbacks {
cb.cb()
}
err = windows.FindNextChangeNotification(h)
if err != nil {
log.Printf("Unable to monitor config directory again: %v", err)
windows.FindCloseChangeNotification(h)
h = windows.InvalidHandle
goto startover
}
}
}()
}

View File

@@ -1,140 +0,0 @@
/* SPDX-License-Identifier: MIT
*
* Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package conf
import (
"fmt"
"net/netip"
"strings"
"unsafe"
"golang.org/x/sys/windows"
"golang.zx2c4.com/wireguard/windows/driver"
"golang.zx2c4.com/wireguard/windows/tunnel/winipcfg"
)
func (conf *Config) ToWgQuick() string {
var output strings.Builder
output.WriteString("[Interface]\n")
output.WriteString(fmt.Sprintf("PrivateKey = %s\n", conf.Interface.PrivateKey.String()))
if conf.Interface.ListenPort > 0 {
output.WriteString(fmt.Sprintf("ListenPort = %d\n", conf.Interface.ListenPort))
}
if len(conf.Interface.Addresses) > 0 {
addrStrings := make([]string, len(conf.Interface.Addresses))
for i, address := range conf.Interface.Addresses {
addrStrings[i] = address.String()
}
output.WriteString(fmt.Sprintf("Address = %s\n", strings.Join(addrStrings[:], ", ")))
}
if len(conf.Interface.DNS)+len(conf.Interface.DNSSearch) > 0 {
addrStrings := make([]string, 0, len(conf.Interface.DNS)+len(conf.Interface.DNSSearch))
for _, address := range conf.Interface.DNS {
addrStrings = append(addrStrings, address.String())
}
addrStrings = append(addrStrings, conf.Interface.DNSSearch...)
output.WriteString(fmt.Sprintf("DNS = %s\n", strings.Join(addrStrings[:], ", ")))
}
if conf.Interface.MTU > 0 {
output.WriteString(fmt.Sprintf("MTU = %d\n", conf.Interface.MTU))
}
if len(conf.Interface.PreUp) > 0 {
output.WriteString(fmt.Sprintf("PreUp = %s\n", conf.Interface.PreUp))
}
if len(conf.Interface.PostUp) > 0 {
output.WriteString(fmt.Sprintf("PostUp = %s\n", conf.Interface.PostUp))
}
if len(conf.Interface.PreDown) > 0 {
output.WriteString(fmt.Sprintf("PreDown = %s\n", conf.Interface.PreDown))
}
if len(conf.Interface.PostDown) > 0 {
output.WriteString(fmt.Sprintf("PostDown = %s\n", conf.Interface.PostDown))
}
if conf.Interface.TableOff {
output.WriteString("Table = off\n")
}
for _, peer := range conf.Peers {
output.WriteString("\n[Peer]\n")
output.WriteString(fmt.Sprintf("PublicKey = %s\n", peer.PublicKey.String()))
if !peer.PresharedKey.IsZero() {
output.WriteString(fmt.Sprintf("PresharedKey = %s\n", peer.PresharedKey.String()))
}
if len(peer.AllowedIPs) > 0 {
addrStrings := make([]string, len(peer.AllowedIPs))
for i, address := range peer.AllowedIPs {
addrStrings[i] = address.String()
}
output.WriteString(fmt.Sprintf("AllowedIPs = %s\n", strings.Join(addrStrings[:], ", ")))
}
if !peer.Endpoint.IsEmpty() {
output.WriteString(fmt.Sprintf("Endpoint = %s\n", peer.Endpoint.String()))
}
if peer.PersistentKeepalive > 0 {
output.WriteString(fmt.Sprintf("PersistentKeepalive = %d\n", peer.PersistentKeepalive))
}
}
return output.String()
}
func (config *Config) ToDriverConfiguration() (*driver.Interface, uint32) {
preallocation := unsafe.Sizeof(driver.Interface{}) + uintptr(len(config.Peers))*unsafe.Sizeof(driver.Peer{})
for i := range config.Peers {
preallocation += uintptr(len(config.Peers[i].AllowedIPs)) * unsafe.Sizeof(driver.AllowedIP{})
}
var c driver.ConfigBuilder
c.Preallocate(uint32(preallocation))
c.AppendInterface(&driver.Interface{
Flags: driver.InterfaceHasPrivateKey | driver.InterfaceHasListenPort,
ListenPort: config.Interface.ListenPort,
PrivateKey: config.Interface.PrivateKey,
PeerCount: uint32(len(config.Peers)),
})
for i := range config.Peers {
flags := driver.PeerHasPublicKey | driver.PeerHasPersistentKeepalive
if !config.Peers[i].PresharedKey.IsZero() {
flags |= driver.PeerHasPresharedKey
}
var endpoint winipcfg.RawSockaddrInet
if !config.Peers[i].Endpoint.IsEmpty() {
addr, err := netip.ParseAddr(config.Peers[i].Endpoint.Host)
if err == nil {
flags |= driver.PeerHasEndpoint
endpoint.SetAddrPort(netip.AddrPortFrom(addr, config.Peers[i].Endpoint.Port))
}
}
c.AppendPeer(&driver.Peer{
Flags: flags,
PublicKey: config.Peers[i].PublicKey,
PresharedKey: config.Peers[i].PresharedKey,
PersistentKeepalive: config.Peers[i].PersistentKeepalive,
Endpoint: endpoint,
AllowedIPsCount: uint32(len(config.Peers[i].AllowedIPs)),
})
for j := range config.Peers[i].AllowedIPs {
a := &driver.AllowedIP{Cidr: uint8(config.Peers[i].AllowedIPs[j].Bits())}
copy(a.Address[:], config.Peers[i].AllowedIPs[j].Addr().AsSlice())
if config.Peers[i].AllowedIPs[j].Addr().Is4() {
a.AddressFamily = windows.AF_INET
} else if config.Peers[i].AllowedIPs[j].Addr().Is6() {
a.AddressFamily = windows.AF_INET6
}
c.AppendAllowedIP(a)
}
}
return c.Interface()
}

View File

@@ -1,183 +0,0 @@
/* SPDX-License-Identifier: MIT
*
* Copyright (C) 2017-2022 WireGuard LLC. All Rights Reserved.
*/
package driver
import (
"syscall"
"unsafe"
"golang.org/x/sys/windows"
"golang.zx2c4.com/wireguard/windows/tunnel/winipcfg"
)
type AdapterState uint32
const (
AdapterStateDown AdapterState = 0
AdapterStateUp AdapterState = 1
)
type AllowedIP struct {
Address [16]byte
AddressFamily winipcfg.AddressFamily
Cidr uint8
_ [4]byte
}
type PeerFlag uint32
const (
PeerHasPublicKey PeerFlag = 1 << 0
PeerHasPresharedKey PeerFlag = 1 << 1
PeerHasPersistentKeepalive PeerFlag = 1 << 2
PeerHasEndpoint PeerFlag = 1 << 3
PeerReplaceAllowedIPs PeerFlag = 1 << 5
PeerRemove PeerFlag = 1 << 6
PeerUpdateOnly PeerFlag = 1 << 7
)
type Peer struct {
Flags PeerFlag
_ uint32
PublicKey [32]byte
PresharedKey [32]byte
PersistentKeepalive uint16
_ uint16
Endpoint winipcfg.RawSockaddrInet
TxBytes uint64
RxBytes uint64
LastHandshake uint64
AllowedIPsCount uint32
_ [4]byte
}
type InterfaceFlag uint32
const (
InterfaceHasPublicKey InterfaceFlag = 1 << 0
InterfaceHasPrivateKey InterfaceFlag = 1 << 1
InterfaceHasListenPort InterfaceFlag = 1 << 2
InterfaceReplacePeers InterfaceFlag = 1 << 3
)
type Interface struct {
Flags InterfaceFlag
ListenPort uint16
PrivateKey [32]byte
PublicKey [32]byte
PeerCount uint32
_ [4]byte
}
var (
procWireGuardSetAdapterState = modwireguard.NewProc("WireGuardSetAdapterState")
procWireGuardGetAdapterState = modwireguard.NewProc("WireGuardGetAdapterState")
procWireGuardSetConfiguration = modwireguard.NewProc("WireGuardSetConfiguration")
procWireGuardGetConfiguration = modwireguard.NewProc("WireGuardGetConfiguration")
)
// SetAdapterState sets the adapter either Up or Down.
func (wireguard *Adapter) SetAdapterState(adapterState AdapterState) (err error) {
r0, _, e1 := syscall.SyscallN(procWireGuardSetAdapterState.Addr(), wireguard.handle, uintptr(adapterState))
if r0 == 0 {
err = e1
}
return
}
// AdapterState returns the current state of the adapter.
func (wireguard *Adapter) AdapterState() (adapterState AdapterState, err error) {
r0, _, e1 := syscall.SyscallN(procWireGuardGetAdapterState.Addr(), wireguard.handle, uintptr(unsafe.Pointer(&adapterState)))
if r0 == 0 {
err = e1
}
return
}
// SetConfiguration sets the adapter configuration.
func (wireguard *Adapter) SetConfiguration(interfaze *Interface, size uint32) (err error) {
r0, _, e1 := syscall.SyscallN(procWireGuardSetConfiguration.Addr(), wireguard.handle, uintptr(unsafe.Pointer(interfaze)), uintptr(size))
if r0 == 0 {
err = e1
}
return
}
// Configuration gets the adapter configuration.
func (wireguard *Adapter) Configuration() (interfaze *Interface, err error) {
size := wireguard.lastGetGuessSize
if size == 0 {
size = 512
}
for {
buf := make([]byte, size)
r0, _, e1 := syscall.SyscallN(procWireGuardGetConfiguration.Addr(), wireguard.handle, uintptr(unsafe.Pointer(&buf[0])), uintptr(unsafe.Pointer(&size)))
if r0 != 0 {
wireguard.lastGetGuessSize = size
return (*Interface)(unsafe.Pointer(&buf[0])), nil
}
if e1 != windows.ERROR_MORE_DATA {
return nil, e1
}
}
}
// FirstPeer returns the first peer attached to the interface.
func (interfaze *Interface) FirstPeer() *Peer {
return (*Peer)(unsafe.Add(unsafe.Pointer(interfaze), unsafe.Sizeof(*interfaze)))
}
// NextPeer returns the subsequent peer of the current one.
func (peer *Peer) NextPeer() *Peer {
return (*Peer)(unsafe.Pointer(uintptr(unsafe.Pointer(peer)) + unsafe.Sizeof(*peer) + uintptr(peer.AllowedIPsCount)*unsafe.Sizeof(AllowedIP{})))
}
// FirstAllowedIP returns the first allowed IP attached to the peer.
func (peer *Peer) FirstAllowedIP() *AllowedIP {
return (*AllowedIP)(unsafe.Add(unsafe.Pointer(peer), unsafe.Sizeof(*peer)))
}
// NextAllowedIP returns the subsequent allowed IP of the current one.
func (allowedIP *AllowedIP) NextAllowedIP() *AllowedIP {
return (*AllowedIP)(unsafe.Add(unsafe.Pointer(allowedIP), unsafe.Sizeof(*allowedIP)))
}
type ConfigBuilder struct {
buffer []byte
}
// Preallocate reserves memory in the config builder to reduce allocations of append operations.
func (builder *ConfigBuilder) Preallocate(size uint32) {
if builder.buffer == nil {
builder.buffer = make([]byte, 0, size)
}
}
// AppendInterface appends an interface to the building configuration. This should be called first.
func (builder *ConfigBuilder) AppendInterface(interfaze *Interface) {
newBytes := unsafe.Slice((*byte)(unsafe.Pointer(interfaze)), unsafe.Sizeof(*interfaze))
builder.buffer = append(builder.buffer, newBytes...)
}
// AppendPeer appends a peer to the building configuration. This should be called after an interface has been added.
func (builder *ConfigBuilder) AppendPeer(peer *Peer) {
newBytes := unsafe.Slice((*byte)(unsafe.Pointer(peer)), unsafe.Sizeof(*peer))
builder.buffer = append(builder.buffer, newBytes...)
}
// AppendAllowedIP appends an allowed IP to the building configuration. This should be called after a peer has been added.
func (builder *ConfigBuilder) AppendAllowedIP(allowedIP *AllowedIP) {
newBytes := unsafe.Slice((*byte)(unsafe.Pointer(allowedIP)), unsafe.Sizeof(*allowedIP))
builder.buffer = append(builder.buffer, newBytes...)
}
// Interface assembles the configuration and returns the interface and length to be passed to SetConfiguration.
func (builder *ConfigBuilder) Interface() (*Interface, uint32) {
if builder.buffer == nil {
return nil, 0
}
return (*Interface)(unsafe.Pointer(&builder.buffer[0])), uint32(len(builder.buffer))
}

View File

@@ -1,56 +0,0 @@
//go:build !load_wgnt_from_rsrc
/* SPDX-License-Identifier: MIT
*
* Copyright (C) 2019 WireGuard LLC. All Rights Reserved.
*/
package driver
import (
"fmt"
"sync"
"sync/atomic"
"unsafe"
"golang.org/x/sys/windows"
)
type lazyDLL struct {
Name string
Base windows.Handle
mu sync.Mutex
module windows.Handle
onLoad func(d *lazyDLL)
}
func (d *lazyDLL) Load() error {
if atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(&d.module))) != nil {
return nil
}
d.mu.Lock()
defer d.mu.Unlock()
if d.module != 0 {
return nil
}
const (
LOAD_LIBRARY_SEARCH_APPLICATION_DIR = 0x00000200
LOAD_LIBRARY_SEARCH_SYSTEM32 = 0x00000800
)
module, err := windows.LoadLibraryEx(d.Name, 0, LOAD_LIBRARY_SEARCH_APPLICATION_DIR|LOAD_LIBRARY_SEARCH_SYSTEM32)
if err != nil {
return fmt.Errorf("Unable to load library: %w", err)
}
d.Base = module
atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(&d.module)), unsafe.Pointer(module))
if d.onLoad != nil {
d.onLoad(d)
}
return nil
}
func (p *lazyProc) nameToAddr() (uintptr, error) {
return windows.GetProcAddress(p.dll.module, p.Name)
}

View File

@@ -1,62 +0,0 @@
//go:build load_wgnt_from_rsrc
/* SPDX-License-Identifier: MIT
*
* Copyright (C) 2019 WireGuard LLC. All Rights Reserved.
*/
package driver
import (
"fmt"
"sync"
"sync/atomic"
"unsafe"
"golang.org/x/sys/windows"
"golang.zx2c4.com/wireguard/windows/driver/memmod"
)
type lazyDLL struct {
Name string
Base windows.Handle
mu sync.Mutex
module *memmod.Module
onLoad func(d *lazyDLL)
}
func (d *lazyDLL) Load() error {
if atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(&d.module))) != nil {
return nil
}
d.mu.Lock()
defer d.mu.Unlock()
if d.module != nil {
return nil
}
const ourModule windows.Handle = 0
resInfo, err := windows.FindResource(ourModule, d.Name, windows.RT_RCDATA)
if err != nil {
return fmt.Errorf("Unable to find \"%v\" RCDATA resource: %w", d.Name, err)
}
data, err := windows.LoadResourceData(ourModule, resInfo)
if err != nil {
return fmt.Errorf("Unable to load resource: %w", err)
}
module, err := memmod.LoadLibrary(data)
if err != nil {
return fmt.Errorf("Unable to load library: %w", err)
}
d.Base = windows.Handle(module.BaseAddr())
atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(&d.module)), unsafe.Pointer(module))
if d.onLoad != nil {
d.onLoad(d)
}
return nil
}
func (p *lazyProc) nameToAddr() (uintptr, error) {
return p.dll.module.ProcAddressByName(p.Name)
}

View File

@@ -1,91 +0,0 @@
/* SPDX-License-Identifier: MIT
*
* Copyright (C) 2017-2022 WireGuard LLC. All Rights Reserved.
*/
package driver
import (
"fmt"
"sync"
"sync/atomic"
"unsafe"
"golang.org/x/sys/windows"
)
func newLazyDLL(name string, onLoad func(d *lazyDLL)) *lazyDLL {
return &lazyDLL{Name: name, onLoad: onLoad}
}
func (d *lazyDLL) NewProc(name string) *lazyProc {
return &lazyProc{dll: d, Name: name}
}
type lazyProc struct {
Name string
mu sync.Mutex
dll *lazyDLL
addr uintptr
}
func (p *lazyProc) Find() error {
if atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(&p.addr))) != nil {
return nil
}
p.mu.Lock()
defer p.mu.Unlock()
if p.addr != 0 {
return nil
}
err := p.dll.Load()
if err != nil {
return fmt.Errorf("Error loading %v DLL: %w", p.dll.Name, err)
}
addr, err := p.nameToAddr()
if err != nil {
return fmt.Errorf("Error getting %v address: %w", p.Name, err)
}
atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(&p.addr)), unsafe.Pointer(addr))
return nil
}
func (p *lazyProc) Addr() uintptr {
err := p.Find()
if err != nil {
panic(err)
}
return p.addr
}
// Version returns the version of the driver DLL.
func Version() string {
if modwireguard.Load() != nil {
return "unknown"
}
resInfo, err := windows.FindResource(modwireguard.Base, windows.ResourceID(1), windows.RT_VERSION)
if err != nil {
return "unknown"
}
data, err := windows.LoadResourceData(modwireguard.Base, resInfo)
if err != nil {
return "unknown"
}
var fixedInfo *windows.VS_FIXEDFILEINFO
fixedInfoLen := uint32(unsafe.Sizeof(*fixedInfo))
err = windows.VerQueryValue(unsafe.Pointer(&data[0]), `\`, unsafe.Pointer(&fixedInfo), &fixedInfoLen)
if err != nil {
return "unknown"
}
version := fmt.Sprintf("%d.%d", (fixedInfo.FileVersionMS>>16)&0xff, (fixedInfo.FileVersionMS>>0)&0xff)
if nextNibble := (fixedInfo.FileVersionLS >> 16) & 0xff; nextNibble != 0 {
version += fmt.Sprintf(".%d", nextNibble)
}
if nextNibble := (fixedInfo.FileVersionLS >> 0) & 0xff; nextNibble != 0 {
version += fmt.Sprintf(".%d", nextNibble)
}
return version
}

View File

@@ -1,170 +0,0 @@
/* SPDX-License-Identifier: MIT
*
* Copyright (C) 2017-2022 WireGuard LLC. All Rights Reserved.
*/
package driver
import (
"log"
"runtime"
"syscall"
"unsafe"
"golang.org/x/sys/windows"
"golang.zx2c4.com/wireguard/windows/tunnel/winipcfg"
)
type loggerLevel int
const (
logInfo loggerLevel = iota
logWarn
logErr
)
const AdapterNameMax = 128
type Adapter struct {
handle uintptr
lastGetGuessSize uint32
}
var (
modwireguard = newLazyDLL("wireguard.dll", setupLogger)
procWireGuardCreateAdapter = modwireguard.NewProc("WireGuardCreateAdapter")
procWireGuardOpenAdapter = modwireguard.NewProc("WireGuardOpenAdapter")
procWireGuardCloseAdapter = modwireguard.NewProc("WireGuardCloseAdapter")
procWireGuardDeleteDriver = modwireguard.NewProc("WireGuardDeleteDriver")
procWireGuardGetAdapterLUID = modwireguard.NewProc("WireGuardGetAdapterLUID")
procWireGuardGetRunningDriverVersion = modwireguard.NewProc("WireGuardGetRunningDriverVersion")
procWireGuardSetAdapterLogging = modwireguard.NewProc("WireGuardSetAdapterLogging")
)
type TimestampedWriter interface {
WriteWithTimestamp(p []byte, ts int64) (n int, err error)
}
func logMessage(level loggerLevel, timestamp uint64, msg *uint16) int {
if tw, ok := log.Default().Writer().(TimestampedWriter); ok {
tw.WriteWithTimestamp([]byte(log.Default().Prefix()+windows.UTF16PtrToString(msg)), (int64(timestamp)-116444736000000000)*100)
} else {
log.Println(windows.UTF16PtrToString(msg))
}
return 0
}
func setupLogger(dll *lazyDLL) {
var callback uintptr
if runtime.GOARCH == "386" {
callback = windows.NewCallback(func(level loggerLevel, timestampLow, timestampHigh uint32, msg *uint16) int {
return logMessage(level, uint64(timestampHigh)<<32|uint64(timestampLow), msg)
})
} else if runtime.GOARCH == "arm" {
callback = windows.NewCallback(func(level loggerLevel, _, timestampLow, timestampHigh uint32, msg *uint16) int {
return logMessage(level, uint64(timestampHigh)<<32|uint64(timestampLow), msg)
})
} else if runtime.GOARCH == "amd64" || runtime.GOARCH == "arm64" {
callback = windows.NewCallback(logMessage)
}
syscall.SyscallN(dll.NewProc("WireGuardSetLogger").Addr(), callback)
}
func closeAdapter(wireguard *Adapter) {
syscall.SyscallN(procWireGuardCloseAdapter.Addr(), wireguard.handle)
}
// CreateAdapter creates a WireGuard adapter. name is the cosmetic name of the adapter.
// tunnelType represents the type of adapter and should be "WireGuard". requestedGUID is
// the GUID of the created network adapter, which then influences NLA generation
// deterministically. If it is set to nil, the GUID is chosen by the system at random,
// and hence a new NLA entry is created for each new adapter.
func CreateAdapter(name, tunnelType string, requestedGUID *windows.GUID) (wireguard *Adapter, err error) {
var name16 *uint16
name16, err = windows.UTF16PtrFromString(name)
if err != nil {
return
}
var tunnelType16 *uint16
tunnelType16, err = windows.UTF16PtrFromString(tunnelType)
if err != nil {
return
}
r0, _, e1 := syscall.SyscallN(procWireGuardCreateAdapter.Addr(), uintptr(unsafe.Pointer(name16)), uintptr(unsafe.Pointer(tunnelType16)), uintptr(unsafe.Pointer(requestedGUID)))
if r0 == 0 {
err = e1
return
}
wireguard = &Adapter{handle: r0}
runtime.SetFinalizer(wireguard, closeAdapter)
return
}
// OpenAdapter opens an existing WireGuard adapter by name.
func OpenAdapter(name string) (wireguard *Adapter, err error) {
var name16 *uint16
name16, err = windows.UTF16PtrFromString(name)
if err != nil {
return
}
r0, _, e1 := syscall.SyscallN(procWireGuardOpenAdapter.Addr(), uintptr(unsafe.Pointer(name16)))
if r0 == 0 {
err = e1
return
}
wireguard = &Adapter{handle: r0}
runtime.SetFinalizer(wireguard, closeAdapter)
return
}
// Close closes a WireGuard adapter.
func (wireguard *Adapter) Close() (err error) {
runtime.SetFinalizer(wireguard, nil)
r1, _, e1 := syscall.SyscallN(procWireGuardCloseAdapter.Addr(), wireguard.handle)
if r1 == 0 {
err = e1
}
return
}
// Uninstall removes the driver from the system if no drivers are currently in use.
func Uninstall() (err error) {
r1, _, e1 := syscall.SyscallN(procWireGuardDeleteDriver.Addr())
if r1 == 0 {
err = e1
}
return
}
type AdapterLogState uint32
const (
AdapterLogOff AdapterLogState = 0
AdapterLogOn AdapterLogState = 1
AdapterLogOnWithPrefix AdapterLogState = 2
)
// SetLogging enables or disables logging on the WireGuard adapter.
func (wireguard *Adapter) SetLogging(logState AdapterLogState) (err error) {
r1, _, e1 := syscall.SyscallN(procWireGuardSetAdapterLogging.Addr(), wireguard.handle, uintptr(logState))
if r1 == 0 {
err = e1
}
return
}
// RunningVersion returns the version of the loaded driver.
func RunningVersion() (version uint32, err error) {
r0, _, e1 := syscall.SyscallN(procWireGuardGetRunningDriverVersion.Addr())
version = uint32(r0)
if version == 0 {
err = e1
}
return
}
// LUID returns the LUID of the adapter.
func (wireguard *Adapter) LUID() (luid winipcfg.LUID) {
syscall.SyscallN(procWireGuardGetAdapterLUID.Addr(), wireguard.handle, uintptr(unsafe.Pointer(&luid)))
return
}

View File

@@ -1,698 +0,0 @@
/* SPDX-License-Identifier: MIT
*
* Copyright (C) 2017-2022 WireGuard LLC. All Rights Reserved.
*/
package memmod
import (
"errors"
"fmt"
"strings"
"sync"
"syscall"
"unsafe"
"golang.org/x/sys/windows"
)
type addressList struct {
next *addressList
address uintptr
}
func (head *addressList) free() {
for node := head; node != nil; node = node.next {
windows.VirtualFree(node.address, 0, windows.MEM_RELEASE)
}
}
type Module struct {
headers *IMAGE_NT_HEADERS
codeBase uintptr
modules []windows.Handle
initialized bool
isDLL bool
isRelocated bool
nameExports map[string]uint16
entry uintptr
blockedMemory *addressList
}
func (module *Module) BaseAddr() uintptr {
return module.codeBase
}
func (module *Module) headerDirectory(idx int) *IMAGE_DATA_DIRECTORY {
return &module.headers.OptionalHeader.DataDirectory[idx]
}
func (module *Module) copySections(address, size uintptr, oldHeaders *IMAGE_NT_HEADERS) error {
sections := module.headers.Sections()
for i := range sections {
if sections[i].SizeOfRawData == 0 {
// Section doesn't contain data in the dll itself, but may define uninitialized data.
sectionSize := oldHeaders.OptionalHeader.SectionAlignment
if sectionSize == 0 {
continue
}
dest, err := windows.VirtualAlloc(module.codeBase+uintptr(sections[i].VirtualAddress),
uintptr(sectionSize),
windows.MEM_COMMIT,
windows.PAGE_READWRITE)
if err != nil {
return fmt.Errorf("Error allocating section: %w", err)
}
// Always use position from file to support alignments smaller than page size (allocation above will align to page size).
dest = module.codeBase + uintptr(sections[i].VirtualAddress)
// NOTE: On 64bit systems we truncate to 32bit here but expand again later when "PhysicalAddress" is used.
sections[i].SetPhysicalAddress((uint32)(dest & 0xffffffff))
dst := unsafe.Slice((*byte)(a2p(dest)), sectionSize)
for j := range dst {
dst[j] = 0
}
continue
}
if size < uintptr(sections[i].PointerToRawData+sections[i].SizeOfRawData) {
return errors.New("Incomplete section")
}
// Commit memory block and copy data from dll.
dest, err := windows.VirtualAlloc(module.codeBase+uintptr(sections[i].VirtualAddress),
uintptr(sections[i].SizeOfRawData),
windows.MEM_COMMIT,
windows.PAGE_READWRITE)
if err != nil {
return fmt.Errorf("Error allocating memory block: %w", err)
}
// Always use position from file to support alignments smaller than page size (allocation above will align to page size).
memcpy(
module.codeBase+uintptr(sections[i].VirtualAddress),
address+uintptr(sections[i].PointerToRawData),
uintptr(sections[i].SizeOfRawData))
// NOTE: On 64bit systems we truncate to 32bit here but expand again later when "PhysicalAddress" is used.
sections[i].SetPhysicalAddress((uint32)(dest & 0xffffffff))
}
return nil
}
func (module *Module) realSectionSize(section *IMAGE_SECTION_HEADER) uintptr {
size := section.SizeOfRawData
if size != 0 {
return uintptr(size)
}
if (section.Characteristics & IMAGE_SCN_CNT_INITIALIZED_DATA) != 0 {
return uintptr(module.headers.OptionalHeader.SizeOfInitializedData)
}
if (section.Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA) != 0 {
return uintptr(module.headers.OptionalHeader.SizeOfUninitializedData)
}
return 0
}
type sectionFinalizeData struct {
address uintptr
alignedAddress uintptr
size uintptr
characteristics uint32
last bool
}
func (module *Module) finalizeSection(sectionData *sectionFinalizeData) error {
if sectionData.size == 0 {
return nil
}
if (sectionData.characteristics & IMAGE_SCN_MEM_DISCARDABLE) != 0 {
// Section is not needed any more and can safely be freed.
if sectionData.address == sectionData.alignedAddress &&
(sectionData.last ||
(sectionData.size%uintptr(module.headers.OptionalHeader.SectionAlignment)) == 0) {
// Only allowed to decommit whole pages.
windows.VirtualFree(sectionData.address, sectionData.size, windows.MEM_DECOMMIT)
}
return nil
}
// determine protection flags based on characteristics
ProtectionFlags := [8]uint32{
windows.PAGE_NOACCESS, // not writeable, not readable, not executable
windows.PAGE_EXECUTE, // not writeable, not readable, executable
windows.PAGE_READONLY, // not writeable, readable, not executable
windows.PAGE_EXECUTE_READ, // not writeable, readable, executable
windows.PAGE_WRITECOPY, // writeable, not readable, not executable
windows.PAGE_EXECUTE_WRITECOPY, // writeable, not readable, executable
windows.PAGE_READWRITE, // writeable, readable, not executable
windows.PAGE_EXECUTE_READWRITE, // writeable, readable, executable
}
protect := ProtectionFlags[sectionData.characteristics>>29]
if (sectionData.characteristics & IMAGE_SCN_MEM_NOT_CACHED) != 0 {
protect |= windows.PAGE_NOCACHE
}
// Change memory access flags.
var oldProtect uint32
err := windows.VirtualProtect(sectionData.address, sectionData.size, protect, &oldProtect)
if err != nil {
return fmt.Errorf("Error protecting memory page: %w", err)
}
return nil
}
func (module *Module) registerExceptionHandlers() {
directory := module.headerDirectory(IMAGE_DIRECTORY_ENTRY_EXCEPTION)
if directory.Size == 0 || directory.VirtualAddress == 0 {
return
}
runtimeFuncs := (*windows.RUNTIME_FUNCTION)(unsafe.Pointer(module.codeBase + uintptr(directory.VirtualAddress)))
windows.RtlAddFunctionTable(runtimeFuncs, uint32(uintptr(directory.Size)/unsafe.Sizeof(*runtimeFuncs)), module.codeBase)
}
func (module *Module) finalizeSections() error {
sections := module.headers.Sections()
imageOffset := module.headers.OptionalHeader.imageOffset()
sectionData := sectionFinalizeData{}
sectionData.address = uintptr(sections[0].PhysicalAddress()) | imageOffset
sectionData.alignedAddress = alignDown(sectionData.address, uintptr(module.headers.OptionalHeader.SectionAlignment))
sectionData.size = module.realSectionSize(&sections[0])
sections[0].SetVirtualSize(uint32(sectionData.size))
sectionData.characteristics = sections[0].Characteristics
// Loop through all sections and change access flags.
for i := uint16(1); i < module.headers.FileHeader.NumberOfSections; i++ {
sectionAddress := uintptr(sections[i].PhysicalAddress()) | imageOffset
alignedAddress := alignDown(sectionAddress, uintptr(module.headers.OptionalHeader.SectionAlignment))
sectionSize := module.realSectionSize(&sections[i])
sections[i].SetVirtualSize(uint32(sectionSize))
// Combine access flags of all sections that share a page.
// TODO: We currently share flags of a trailing large section with the page of a first small section. This should be optimized.
if sectionData.alignedAddress == alignedAddress || sectionData.address+sectionData.size > alignedAddress {
// Section shares page with previous.
if (sections[i].Characteristics&IMAGE_SCN_MEM_DISCARDABLE) == 0 || (sectionData.characteristics&IMAGE_SCN_MEM_DISCARDABLE) == 0 {
sectionData.characteristics = (sectionData.characteristics | sections[i].Characteristics) &^ IMAGE_SCN_MEM_DISCARDABLE
} else {
sectionData.characteristics |= sections[i].Characteristics
}
sectionData.size = sectionAddress + sectionSize - sectionData.address
continue
}
err := module.finalizeSection(&sectionData)
if err != nil {
return fmt.Errorf("Error finalizing section: %w", err)
}
sectionData.address = sectionAddress
sectionData.alignedAddress = alignedAddress
sectionData.size = sectionSize
sectionData.characteristics = sections[i].Characteristics
}
sectionData.last = true
err := module.finalizeSection(&sectionData)
if err != nil {
return fmt.Errorf("Error finalizing section: %w", err)
}
return nil
}
func (module *Module) executeTLS() {
directory := module.headerDirectory(IMAGE_DIRECTORY_ENTRY_TLS)
if directory.VirtualAddress == 0 {
return
}
tls := (*IMAGE_TLS_DIRECTORY)(a2p(module.codeBase + uintptr(directory.VirtualAddress)))
callback := tls.AddressOfCallbacks
if callback != 0 {
for {
f := *(*uintptr)(a2p(callback))
if f == 0 {
break
}
syscall.SyscallN(f, module.codeBase, DLL_PROCESS_ATTACH, 0)
callback += unsafe.Sizeof(f)
}
}
}
func (module *Module) performBaseRelocation(delta uintptr) (relocated bool, err error) {
directory := module.headerDirectory(IMAGE_DIRECTORY_ENTRY_BASERELOC)
if directory.Size == 0 {
return delta == 0, nil
}
relocationHdr := (*IMAGE_BASE_RELOCATION)(a2p(module.codeBase + uintptr(directory.VirtualAddress)))
for relocationHdr.VirtualAddress > 0 {
dest := module.codeBase + uintptr(relocationHdr.VirtualAddress)
relInfos := unsafe.Slice(
(*uint16)(a2p(uintptr(unsafe.Pointer(relocationHdr))+unsafe.Sizeof(*relocationHdr))),
(uintptr(relocationHdr.SizeOfBlock)-unsafe.Sizeof(*relocationHdr))/unsafe.Sizeof(uint16(0)))
for _, relInfo := range relInfos {
// The upper 4 bits define the type of relocation.
relType := relInfo >> 12
// The lower 12 bits define the offset.
relOffset := uintptr(relInfo & 0xfff)
switch relType {
case IMAGE_REL_BASED_ABSOLUTE:
// Skip relocation.
case IMAGE_REL_BASED_LOW:
*(*uint16)(a2p(dest + relOffset)) += uint16(delta & 0xffff)
break
case IMAGE_REL_BASED_HIGH:
*(*uint16)(a2p(dest + relOffset)) += uint16(uint32(delta) >> 16)
break
case IMAGE_REL_BASED_HIGHLOW:
*(*uint32)(a2p(dest + relOffset)) += uint32(delta)
case IMAGE_REL_BASED_DIR64:
*(*uint64)(a2p(dest + relOffset)) += uint64(delta)
case IMAGE_REL_BASED_THUMB_MOV32:
inst := *(*uint32)(a2p(dest + relOffset))
imm16 := ((inst << 1) & 0x0800) + ((inst << 12) & 0xf000) +
((inst >> 20) & 0x0700) + ((inst >> 16) & 0x00ff)
if (inst & 0x8000fbf0) != 0x0000f240 {
return false, fmt.Errorf("Wrong Thumb2 instruction %08x, expected MOVW", inst)
}
imm16 += uint32(delta) & 0xffff
hiDelta := (uint32(delta&0xffff0000) >> 16) + ((imm16 & 0xffff0000) >> 16)
*(*uint32)(a2p(dest + relOffset)) = (inst & 0x8f00fbf0) + ((imm16 >> 1) & 0x0400) +
((imm16 >> 12) & 0x000f) +
((imm16 << 20) & 0x70000000) +
((imm16 << 16) & 0xff0000)
if hiDelta != 0 {
inst = *(*uint32)(a2p(dest + relOffset + 4))
imm16 = ((inst << 1) & 0x0800) + ((inst << 12) & 0xf000) +
((inst >> 20) & 0x0700) + ((inst >> 16) & 0x00ff)
if (inst & 0x8000fbf0) != 0x0000f2c0 {
return false, fmt.Errorf("Wrong Thumb2 instruction %08x, expected MOVT", inst)
}
imm16 += hiDelta
if imm16 > 0xffff {
return false, fmt.Errorf("Resulting immediate value won't fit: %08x", imm16)
}
*(*uint32)(a2p(dest + relOffset + 4)) = (inst & 0x8f00fbf0) +
((imm16 >> 1) & 0x0400) +
((imm16 >> 12) & 0x000f) +
((imm16 << 20) & 0x70000000) +
((imm16 << 16) & 0xff0000)
}
default:
return false, fmt.Errorf("Unsupported relocation: %v", relType)
}
}
// Advance to next relocation block.
relocationHdr = (*IMAGE_BASE_RELOCATION)(a2p(uintptr(unsafe.Pointer(relocationHdr)) + uintptr(relocationHdr.SizeOfBlock)))
}
return true, nil
}
func (module *Module) buildImportTable() error {
directory := module.headerDirectory(IMAGE_DIRECTORY_ENTRY_IMPORT)
if directory.Size == 0 {
return nil
}
module.modules = make([]windows.Handle, 0, 16)
importDesc := (*IMAGE_IMPORT_DESCRIPTOR)(a2p(module.codeBase + uintptr(directory.VirtualAddress)))
for importDesc.Name != 0 {
handle, err := windows.LoadLibraryEx(windows.BytePtrToString((*byte)(a2p(module.codeBase+uintptr(importDesc.Name)))), 0, windows.LOAD_LIBRARY_SEARCH_SYSTEM32)
if err != nil {
return fmt.Errorf("Error loading module: %w", err)
}
var thunkRef, funcRef *uintptr
if importDesc.OriginalFirstThunk() != 0 {
thunkRef = (*uintptr)(a2p(module.codeBase + uintptr(importDesc.OriginalFirstThunk())))
funcRef = (*uintptr)(a2p(module.codeBase + uintptr(importDesc.FirstThunk)))
} else {
// No hint table.
thunkRef = (*uintptr)(a2p(module.codeBase + uintptr(importDesc.FirstThunk)))
funcRef = (*uintptr)(a2p(module.codeBase + uintptr(importDesc.FirstThunk)))
}
for *thunkRef != 0 {
if IMAGE_SNAP_BY_ORDINAL(*thunkRef) {
*funcRef, err = windows.GetProcAddressByOrdinal(handle, IMAGE_ORDINAL(*thunkRef))
} else {
thunkData := (*IMAGE_IMPORT_BY_NAME)(a2p(module.codeBase + *thunkRef))
*funcRef, err = windows.GetProcAddress(handle, windows.BytePtrToString(&thunkData.Name[0]))
}
if err != nil {
windows.FreeLibrary(handle)
return fmt.Errorf("Error getting function address: %w", err)
}
thunkRef = (*uintptr)(a2p(uintptr(unsafe.Pointer(thunkRef)) + unsafe.Sizeof(*thunkRef)))
funcRef = (*uintptr)(a2p(uintptr(unsafe.Pointer(funcRef)) + unsafe.Sizeof(*funcRef)))
}
module.modules = append(module.modules, handle)
importDesc = (*IMAGE_IMPORT_DESCRIPTOR)(a2p(uintptr(unsafe.Pointer(importDesc)) + unsafe.Sizeof(*importDesc)))
}
return nil
}
func (module *Module) buildNameExports() error {
directory := module.headerDirectory(IMAGE_DIRECTORY_ENTRY_EXPORT)
if directory.Size == 0 {
return errors.New("No export table found")
}
exports := (*IMAGE_EXPORT_DIRECTORY)(a2p(module.codeBase + uintptr(directory.VirtualAddress)))
if exports.NumberOfNames == 0 || exports.NumberOfFunctions == 0 {
return errors.New("No functions exported")
}
if exports.NumberOfNames == 0 {
return errors.New("No functions exported by name")
}
nameRefs := unsafe.Slice((*uint32)(a2p(module.codeBase+uintptr(exports.AddressOfNames))), exports.NumberOfNames)
ordinals := unsafe.Slice((*uint16)(a2p(module.codeBase+uintptr(exports.AddressOfNameOrdinals))), exports.NumberOfNames)
module.nameExports = make(map[string]uint16)
for i := range nameRefs {
nameArray := windows.BytePtrToString((*byte)(a2p(module.codeBase + uintptr(nameRefs[i]))))
module.nameExports[nameArray] = ordinals[i]
}
return nil
}
type addressRange struct {
start uintptr
end uintptr
}
var (
loadedAddressRanges []addressRange
loadedAddressRangesMu sync.RWMutex
haveHookedRtlPcToFileHeader sync.Once
hookRtlPcToFileHeaderResult error
)
func hookRtlPcToFileHeader() error {
var kernelBase windows.Handle
err := windows.GetModuleHandleEx(windows.GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, windows.StringToUTF16Ptr("kernelbase.dll"), &kernelBase)
if err != nil {
return err
}
imageBase := unsafe.Pointer(kernelBase)
dosHeader := (*IMAGE_DOS_HEADER)(imageBase)
ntHeaders := (*IMAGE_NT_HEADERS)(unsafe.Add(imageBase, dosHeader.E_lfanew))
importsDirectory := ntHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]
importDescriptor := (*IMAGE_IMPORT_DESCRIPTOR)(unsafe.Add(imageBase, importsDirectory.VirtualAddress))
for ; importDescriptor.Name != 0; importDescriptor = (*IMAGE_IMPORT_DESCRIPTOR)(unsafe.Add(unsafe.Pointer(importDescriptor), unsafe.Sizeof(*importDescriptor))) {
libraryName := windows.BytePtrToString((*byte)(unsafe.Add(imageBase, importDescriptor.Name)))
if strings.EqualFold(libraryName, "ntdll.dll") {
break
}
}
if importDescriptor.Name == 0 {
return errors.New("ntdll.dll not found")
}
originalThunk := (*uintptr)(unsafe.Add(imageBase, importDescriptor.OriginalFirstThunk()))
thunk := (*uintptr)(unsafe.Add(imageBase, importDescriptor.FirstThunk))
for ; *originalThunk != 0; originalThunk = (*uintptr)(unsafe.Add(unsafe.Pointer(originalThunk), unsafe.Sizeof(*originalThunk))) {
if *originalThunk&IMAGE_ORDINAL_FLAG == 0 {
function := (*IMAGE_IMPORT_BY_NAME)(unsafe.Add(imageBase, *originalThunk))
name := windows.BytePtrToString(&function.Name[0])
if name == "RtlPcToFileHeader" {
break
}
}
thunk = (*uintptr)(unsafe.Add(unsafe.Pointer(thunk), unsafe.Sizeof(*thunk)))
}
if *originalThunk == 0 {
return errors.New("RtlPcToFileHeader not found")
}
var oldProtect uint32
err = windows.VirtualProtect(uintptr(unsafe.Pointer(thunk)), unsafe.Sizeof(*thunk), windows.PAGE_READWRITE, &oldProtect)
if err != nil {
return err
}
originalRtlPcToFileHeader := *thunk
*thunk = windows.NewCallback(func(pcValue uintptr, baseOfImage *uintptr) uintptr {
loadedAddressRangesMu.RLock()
for i := range loadedAddressRanges {
if pcValue >= loadedAddressRanges[i].start && pcValue < loadedAddressRanges[i].end {
pcValue = *thunk
break
}
}
loadedAddressRangesMu.RUnlock()
ret, _, _ := syscall.SyscallN(originalRtlPcToFileHeader, pcValue, uintptr(unsafe.Pointer(baseOfImage)))
return ret
})
err = windows.VirtualProtect(uintptr(unsafe.Pointer(thunk)), unsafe.Sizeof(*thunk), oldProtect, &oldProtect)
if err != nil {
return err
}
return nil
}
// LoadLibrary loads module image to memory.
func LoadLibrary(data []byte) (module *Module, err error) {
addr := uintptr(unsafe.Pointer(&data[0]))
size := uintptr(len(data))
if size < unsafe.Sizeof(IMAGE_DOS_HEADER{}) {
return nil, errors.New("Incomplete IMAGE_DOS_HEADER")
}
dosHeader := (*IMAGE_DOS_HEADER)(a2p(addr))
if dosHeader.E_magic != IMAGE_DOS_SIGNATURE {
return nil, fmt.Errorf("Not an MS-DOS binary (provided: %x, expected: %x)", dosHeader.E_magic, IMAGE_DOS_SIGNATURE)
}
if (size < uintptr(dosHeader.E_lfanew)+unsafe.Sizeof(IMAGE_NT_HEADERS{})) {
return nil, errors.New("Incomplete IMAGE_NT_HEADERS")
}
oldHeader := (*IMAGE_NT_HEADERS)(a2p(addr + uintptr(dosHeader.E_lfanew)))
if oldHeader.Signature != IMAGE_NT_SIGNATURE {
return nil, fmt.Errorf("Not an NT binary (provided: %x, expected: %x)", oldHeader.Signature, IMAGE_NT_SIGNATURE)
}
if oldHeader.FileHeader.Machine != imageFileProcess {
return nil, fmt.Errorf("Foreign platform (provided: %x, expected: %x)", oldHeader.FileHeader.Machine, imageFileProcess)
}
if (oldHeader.OptionalHeader.SectionAlignment & 1) != 0 {
return nil, errors.New("Unaligned section")
}
lastSectionEnd := uintptr(0)
sections := oldHeader.Sections()
optionalSectionSize := oldHeader.OptionalHeader.SectionAlignment
for i := range sections {
var endOfSection uintptr
if sections[i].SizeOfRawData == 0 {
// Section without data in the DLL
endOfSection = uintptr(sections[i].VirtualAddress) + uintptr(optionalSectionSize)
} else {
endOfSection = uintptr(sections[i].VirtualAddress) + uintptr(sections[i].SizeOfRawData)
}
if endOfSection > lastSectionEnd {
lastSectionEnd = endOfSection
}
}
alignedImageSize := alignUp(uintptr(oldHeader.OptionalHeader.SizeOfImage), uintptr(oldHeader.OptionalHeader.SectionAlignment))
if alignedImageSize != alignUp(lastSectionEnd, uintptr(oldHeader.OptionalHeader.SectionAlignment)) {
return nil, errors.New("Section is not page-aligned")
}
module = &Module{isDLL: (oldHeader.FileHeader.Characteristics & IMAGE_FILE_DLL) != 0}
defer func() {
if err != nil {
module.Free()
module = nil
}
}()
// Reserve memory for image of library.
// TODO: Is it correct to commit the complete memory region at once? Calling DllEntry raises an exception if we don't.
module.codeBase, err = windows.VirtualAlloc(oldHeader.OptionalHeader.ImageBase,
alignedImageSize,
windows.MEM_RESERVE|windows.MEM_COMMIT,
windows.PAGE_READWRITE)
if err != nil {
// Try to allocate memory at arbitrary position.
module.codeBase, err = windows.VirtualAlloc(0,
alignedImageSize,
windows.MEM_RESERVE|windows.MEM_COMMIT,
windows.PAGE_READWRITE)
if err != nil {
err = fmt.Errorf("Error allocating code: %w", err)
return
}
}
err = module.check4GBBoundaries(alignedImageSize)
if err != nil {
err = fmt.Errorf("Error reallocating code: %w", err)
return
}
if size < uintptr(oldHeader.OptionalHeader.SizeOfHeaders) {
err = errors.New("Incomplete headers")
return
}
// Commit memory for headers.
headers, err := windows.VirtualAlloc(module.codeBase,
uintptr(oldHeader.OptionalHeader.SizeOfHeaders),
windows.MEM_COMMIT,
windows.PAGE_READWRITE)
if err != nil {
err = fmt.Errorf("Error allocating headers: %w", err)
return
}
// Copy PE header to code.
memcpy(headers, addr, uintptr(oldHeader.OptionalHeader.SizeOfHeaders))
module.headers = (*IMAGE_NT_HEADERS)(a2p(headers + uintptr(dosHeader.E_lfanew)))
// Update position.
module.headers.OptionalHeader.ImageBase = module.codeBase
// Copy sections from DLL file block to new memory location.
err = module.copySections(addr, size, oldHeader)
if err != nil {
err = fmt.Errorf("Error copying sections: %w", err)
return
}
// Adjust base address of imported data.
locationDelta := module.headers.OptionalHeader.ImageBase - oldHeader.OptionalHeader.ImageBase
if locationDelta != 0 {
module.isRelocated, err = module.performBaseRelocation(locationDelta)
if err != nil {
err = fmt.Errorf("Error relocating module: %w", err)
return
}
} else {
module.isRelocated = true
}
// Load required dlls and adjust function table of imports.
err = module.buildImportTable()
if err != nil {
err = fmt.Errorf("Error building import table: %w", err)
return
}
// Mark memory pages depending on section headers and release sections that are marked as "discardable".
err = module.finalizeSections()
if err != nil {
err = fmt.Errorf("Error finalizing sections: %w", err)
return
}
// Register exception tables, if they exist.
module.registerExceptionHandlers()
// Register function PCs.
loadedAddressRangesMu.Lock()
loadedAddressRanges = append(loadedAddressRanges, addressRange{module.codeBase, module.codeBase + alignedImageSize})
loadedAddressRangesMu.Unlock()
haveHookedRtlPcToFileHeader.Do(func() {
hookRtlPcToFileHeaderResult = hookRtlPcToFileHeader()
})
err = hookRtlPcToFileHeaderResult
if err != nil {
return
}
// TLS callbacks are executed BEFORE the main loading.
module.executeTLS()
// Get entry point of loaded module.
if module.headers.OptionalHeader.AddressOfEntryPoint != 0 {
module.entry = module.codeBase + uintptr(module.headers.OptionalHeader.AddressOfEntryPoint)
if module.isDLL {
// Notify library about attaching to process.
r0, _, _ := syscall.SyscallN(module.entry, module.codeBase, DLL_PROCESS_ATTACH, 0)
successful := r0 != 0
if !successful {
err = windows.ERROR_DLL_INIT_FAILED
return
}
module.initialized = true
}
}
module.buildNameExports()
return
}
// Free releases module resources and unloads it.
func (module *Module) Free() {
if module.initialized {
// Notify library about detaching from process.
syscall.SyscallN(module.entry, module.codeBase, DLL_PROCESS_DETACH, 0)
module.initialized = false
}
if module.modules != nil {
// Free previously opened libraries.
for _, handle := range module.modules {
windows.FreeLibrary(handle)
}
module.modules = nil
}
if module.codeBase != 0 {
windows.VirtualFree(module.codeBase, 0, windows.MEM_RELEASE)
module.codeBase = 0
}
if module.blockedMemory != nil {
module.blockedMemory.free()
module.blockedMemory = nil
}
}
// ProcAddressByName returns function address by exported name.
func (module *Module) ProcAddressByName(name string) (uintptr, error) {
directory := module.headerDirectory(IMAGE_DIRECTORY_ENTRY_EXPORT)
if directory.Size == 0 {
return 0, errors.New("No export table found")
}
exports := (*IMAGE_EXPORT_DIRECTORY)(a2p(module.codeBase + uintptr(directory.VirtualAddress)))
if module.nameExports == nil {
return 0, errors.New("No functions exported by name")
}
if idx, ok := module.nameExports[name]; ok {
if uint32(idx) > exports.NumberOfFunctions {
return 0, errors.New("Ordinal number too high")
}
// AddressOfFunctions contains the RVAs to the "real" functions.
return module.codeBase + uintptr(*(*uint32)(a2p(module.codeBase + uintptr(exports.AddressOfFunctions) + uintptr(idx)*4))), nil
}
return 0, errors.New("Function not found by name")
}
// ProcAddressByOrdinal returns function address by exported ordinal.
func (module *Module) ProcAddressByOrdinal(ordinal uint16) (uintptr, error) {
directory := module.headerDirectory(IMAGE_DIRECTORY_ENTRY_EXPORT)
if directory.Size == 0 {
return 0, errors.New("No export table found")
}
exports := (*IMAGE_EXPORT_DIRECTORY)(a2p(module.codeBase + uintptr(directory.VirtualAddress)))
if uint32(ordinal) < exports.Base {
return 0, errors.New("Ordinal number too low")
}
idx := ordinal - uint16(exports.Base)
if uint32(idx) > exports.NumberOfFunctions {
return 0, errors.New("Ordinal number too high")
}
// AddressOfFunctions contains the RVAs to the "real" functions.
return module.codeBase + uintptr(*(*uint32)(a2p(module.codeBase + uintptr(exports.AddressOfFunctions) + uintptr(idx)*4))), nil
}
func alignDown(value, alignment uintptr) uintptr {
return value & ^(alignment - 1)
}
func alignUp(value, alignment uintptr) uintptr {
return (value + alignment - 1) & ^(alignment - 1)
}
func a2p(addr uintptr) unsafe.Pointer {
return unsafe.Pointer(addr)
}
func memcpy(dst, src, size uintptr) {
copy(unsafe.Slice((*byte)(a2p(dst)), size), unsafe.Slice((*byte)(a2p(src)), size))
}

View File

@@ -1,16 +0,0 @@
//go:build (windows && 386) || (windows && arm)
/* SPDX-License-Identifier: MIT
*
* Copyright (C) 2017-2022 WireGuard LLC. All Rights Reserved.
*/
package memmod
func (opthdr *IMAGE_OPTIONAL_HEADER) imageOffset() uintptr {
return 0
}
func (module *Module) check4GBBoundaries(alignedImageSize uintptr) (err error) {
return
}

View File

@@ -1,8 +0,0 @@
/* SPDX-License-Identifier: MIT
*
* Copyright (C) 2017-2022 WireGuard LLC. All Rights Reserved.
*/
package memmod
const imageFileProcess = IMAGE_FILE_MACHINE_I386

View File

@@ -1,36 +0,0 @@
//go:build (windows && amd64) || (windows && arm64)
/* SPDX-License-Identifier: MIT
*
* Copyright (C) 2017-2022 WireGuard LLC. All Rights Reserved.
*/
package memmod
import (
"fmt"
"golang.org/x/sys/windows"
)
func (opthdr *IMAGE_OPTIONAL_HEADER) imageOffset() uintptr {
return uintptr(opthdr.ImageBase & 0xffffffff00000000)
}
func (module *Module) check4GBBoundaries(alignedImageSize uintptr) (err error) {
for (module.codeBase >> 32) < ((module.codeBase + alignedImageSize) >> 32) {
node := &addressList{
next: module.blockedMemory,
address: module.codeBase,
}
module.blockedMemory = node
module.codeBase, err = windows.VirtualAlloc(0,
alignedImageSize,
windows.MEM_RESERVE|windows.MEM_COMMIT,
windows.PAGE_READWRITE)
if err != nil {
return fmt.Errorf("Error allocating memory block: %w", err)
}
}
return
}

View File

@@ -1,8 +0,0 @@
/* SPDX-License-Identifier: MIT
*
* Copyright (C) 2017-2022 WireGuard LLC. All Rights Reserved.
*/
package memmod
const imageFileProcess = IMAGE_FILE_MACHINE_AMD64

View File

@@ -1,8 +0,0 @@
/* SPDX-License-Identifier: MIT
*
* Copyright (C) 2017-2022 WireGuard LLC. All Rights Reserved.
*/
package memmod
const imageFileProcess = IMAGE_FILE_MACHINE_ARMNT

View File

@@ -1,8 +0,0 @@
/* SPDX-License-Identifier: MIT
*
* Copyright (C) 2017-2022 WireGuard LLC. All Rights Reserved.
*/
package memmod
const imageFileProcess = IMAGE_FILE_MACHINE_ARM64

View File

@@ -1,392 +0,0 @@
/* SPDX-License-Identifier: MIT
*
* Copyright (C) 2017-2022 WireGuard LLC. All Rights Reserved.
*/
package memmod
import "unsafe"
const (
IMAGE_DOS_SIGNATURE = 0x5A4D // MZ
IMAGE_OS2_SIGNATURE = 0x454E // NE
IMAGE_OS2_SIGNATURE_LE = 0x454C // LE
IMAGE_VXD_SIGNATURE = 0x454C // LE
IMAGE_NT_SIGNATURE = 0x00004550 // PE00
)
// DOS .EXE header
type IMAGE_DOS_HEADER struct {
E_magic uint16 // Magic number
E_cblp uint16 // Bytes on last page of file
E_cp uint16 // Pages in file
E_crlc uint16 // Relocations
E_cparhdr uint16 // Size of header in paragraphs
E_minalloc uint16 // Minimum extra paragraphs needed
E_maxalloc uint16 // Maximum extra paragraphs needed
E_ss uint16 // Initial (relative) SS value
E_sp uint16 // Initial SP value
E_csum uint16 // Checksum
E_ip uint16 // Initial IP value
E_cs uint16 // Initial (relative) CS value
E_lfarlc uint16 // File address of relocation table
E_ovno uint16 // Overlay number
E_res [4]uint16 // Reserved words
E_oemid uint16 // OEM identifier (for e_oeminfo)
E_oeminfo uint16 // OEM information; e_oemid specific
E_res2 [10]uint16 // Reserved words
E_lfanew int32 // File address of new exe header
}
// File header format
type IMAGE_FILE_HEADER struct {
Machine uint16
NumberOfSections uint16
TimeDateStamp uint32
PointerToSymbolTable uint32
NumberOfSymbols uint32
SizeOfOptionalHeader uint16
Characteristics uint16
}
const (
IMAGE_SIZEOF_FILE_HEADER = 20
IMAGE_FILE_RELOCS_STRIPPED = 0x0001 // Relocation info stripped from file.
IMAGE_FILE_EXECUTABLE_IMAGE = 0x0002 // File is executable (i.e. no unresolved external references).
IMAGE_FILE_LINE_NUMS_STRIPPED = 0x0004 // Line nunbers stripped from file.
IMAGE_FILE_LOCAL_SYMS_STRIPPED = 0x0008 // Local symbols stripped from file.
IMAGE_FILE_AGGRESIVE_WS_TRIM = 0x0010 // Aggressively trim working set
IMAGE_FILE_LARGE_ADDRESS_AWARE = 0x0020 // App can handle >2gb addresses
IMAGE_FILE_BYTES_REVERSED_LO = 0x0080 // Bytes of machine word are reversed.
IMAGE_FILE_32BIT_MACHINE = 0x0100 // 32 bit word machine.
IMAGE_FILE_DEBUG_STRIPPED = 0x0200 // Debugging info stripped from file in .DBG file
IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP = 0x0400 // If Image is on removable media, copy and run from the swap file.
IMAGE_FILE_NET_RUN_FROM_SWAP = 0x0800 // If Image is on Net, copy and run from the swap file.
IMAGE_FILE_SYSTEM = 0x1000 // System File.
IMAGE_FILE_DLL = 0x2000 // File is a DLL.
IMAGE_FILE_UP_SYSTEM_ONLY = 0x4000 // File should only be run on a UP machine
IMAGE_FILE_BYTES_REVERSED_HI = 0x8000 // Bytes of machine word are reversed.
IMAGE_FILE_MACHINE_UNKNOWN = 0
IMAGE_FILE_MACHINE_TARGET_HOST = 0x0001 // Useful for indicating we want to interact with the host and not a WoW guest.
IMAGE_FILE_MACHINE_I386 = 0x014c // Intel 386.
IMAGE_FILE_MACHINE_R3000 = 0x0162 // MIPS little-endian, 0x160 big-endian
IMAGE_FILE_MACHINE_R4000 = 0x0166 // MIPS little-endian
IMAGE_FILE_MACHINE_R10000 = 0x0168 // MIPS little-endian
IMAGE_FILE_MACHINE_WCEMIPSV2 = 0x0169 // MIPS little-endian WCE v2
IMAGE_FILE_MACHINE_ALPHA = 0x0184 // Alpha_AXP
IMAGE_FILE_MACHINE_SH3 = 0x01a2 // SH3 little-endian
IMAGE_FILE_MACHINE_SH3DSP = 0x01a3
IMAGE_FILE_MACHINE_SH3E = 0x01a4 // SH3E little-endian
IMAGE_FILE_MACHINE_SH4 = 0x01a6 // SH4 little-endian
IMAGE_FILE_MACHINE_SH5 = 0x01a8 // SH5
IMAGE_FILE_MACHINE_ARM = 0x01c0 // ARM Little-Endian
IMAGE_FILE_MACHINE_THUMB = 0x01c2 // ARM Thumb/Thumb-2 Little-Endian
IMAGE_FILE_MACHINE_ARMNT = 0x01c4 // ARM Thumb-2 Little-Endian
IMAGE_FILE_MACHINE_AM33 = 0x01d3
IMAGE_FILE_MACHINE_POWERPC = 0x01F0 // IBM PowerPC Little-Endian
IMAGE_FILE_MACHINE_POWERPCFP = 0x01f1
IMAGE_FILE_MACHINE_IA64 = 0x0200 // Intel 64
IMAGE_FILE_MACHINE_MIPS16 = 0x0266 // MIPS
IMAGE_FILE_MACHINE_ALPHA64 = 0x0284 // ALPHA64
IMAGE_FILE_MACHINE_MIPSFPU = 0x0366 // MIPS
IMAGE_FILE_MACHINE_MIPSFPU16 = 0x0466 // MIPS
IMAGE_FILE_MACHINE_AXP64 = IMAGE_FILE_MACHINE_ALPHA64
IMAGE_FILE_MACHINE_TRICORE = 0x0520 // Infineon
IMAGE_FILE_MACHINE_CEF = 0x0CEF
IMAGE_FILE_MACHINE_EBC = 0x0EBC // EFI Byte Code
IMAGE_FILE_MACHINE_AMD64 = 0x8664 // AMD64 (K8)
IMAGE_FILE_MACHINE_M32R = 0x9041 // M32R little-endian
IMAGE_FILE_MACHINE_ARM64 = 0xAA64 // ARM64 Little-Endian
IMAGE_FILE_MACHINE_CEE = 0xC0EE
)
// Directory format
type IMAGE_DATA_DIRECTORY struct {
VirtualAddress uint32
Size uint32
}
const IMAGE_NUMBEROF_DIRECTORY_ENTRIES = 16
type IMAGE_NT_HEADERS struct {
Signature uint32
FileHeader IMAGE_FILE_HEADER
OptionalHeader IMAGE_OPTIONAL_HEADER
}
func (ntheader *IMAGE_NT_HEADERS) Sections() []IMAGE_SECTION_HEADER {
return (*[0xffff]IMAGE_SECTION_HEADER)(unsafe.Pointer(
(uintptr)(unsafe.Pointer(ntheader)) +
unsafe.Offsetof(ntheader.OptionalHeader) +
uintptr(ntheader.FileHeader.SizeOfOptionalHeader)))[:ntheader.FileHeader.NumberOfSections]
}
const (
IMAGE_DIRECTORY_ENTRY_EXPORT = 0 // Export Directory
IMAGE_DIRECTORY_ENTRY_IMPORT = 1 // Import Directory
IMAGE_DIRECTORY_ENTRY_RESOURCE = 2 // Resource Directory
IMAGE_DIRECTORY_ENTRY_EXCEPTION = 3 // Exception Directory
IMAGE_DIRECTORY_ENTRY_SECURITY = 4 // Security Directory
IMAGE_DIRECTORY_ENTRY_BASERELOC = 5 // Base Relocation Table
IMAGE_DIRECTORY_ENTRY_DEBUG = 6 // Debug Directory
IMAGE_DIRECTORY_ENTRY_COPYRIGHT = 7 // (X86 usage)
IMAGE_DIRECTORY_ENTRY_ARCHITECTURE = 7 // Architecture Specific Data
IMAGE_DIRECTORY_ENTRY_GLOBALPTR = 8 // RVA of GP
IMAGE_DIRECTORY_ENTRY_TLS = 9 // TLS Directory
IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG = 10 // Load Configuration Directory
IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT = 11 // Bound Import Directory in headers
IMAGE_DIRECTORY_ENTRY_IAT = 12 // Import Address Table
IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT = 13 // Delay Load Import Descriptors
IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR = 14 // COM Runtime descriptor
)
const IMAGE_SIZEOF_SHORT_NAME = 8
// Section header format
type IMAGE_SECTION_HEADER struct {
Name [IMAGE_SIZEOF_SHORT_NAME]byte
physicalAddressOrVirtualSize uint32
VirtualAddress uint32
SizeOfRawData uint32
PointerToRawData uint32
PointerToRelocations uint32
PointerToLinenumbers uint32
NumberOfRelocations uint16
NumberOfLinenumbers uint16
Characteristics uint32
}
func (ishdr *IMAGE_SECTION_HEADER) PhysicalAddress() uint32 {
return ishdr.physicalAddressOrVirtualSize
}
func (ishdr *IMAGE_SECTION_HEADER) SetPhysicalAddress(addr uint32) {
ishdr.physicalAddressOrVirtualSize = addr
}
func (ishdr *IMAGE_SECTION_HEADER) VirtualSize() uint32 {
return ishdr.physicalAddressOrVirtualSize
}
func (ishdr *IMAGE_SECTION_HEADER) SetVirtualSize(addr uint32) {
ishdr.physicalAddressOrVirtualSize = addr
}
const (
// Dll characteristics.
IMAGE_DLL_CHARACTERISTICS_HIGH_ENTROPY_VA = 0x0020
IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE = 0x0040
IMAGE_DLL_CHARACTERISTICS_FORCE_INTEGRITY = 0x0080
IMAGE_DLL_CHARACTERISTICS_NX_COMPAT = 0x0100
IMAGE_DLL_CHARACTERISTICS_NO_ISOLATION = 0x0200
IMAGE_DLL_CHARACTERISTICS_NO_SEH = 0x0400
IMAGE_DLL_CHARACTERISTICS_NO_BIND = 0x0800
IMAGE_DLL_CHARACTERISTICS_APPCONTAINER = 0x1000
IMAGE_DLL_CHARACTERISTICS_WDM_DRIVER = 0x2000
IMAGE_DLL_CHARACTERISTICS_GUARD_CF = 0x4000
IMAGE_DLL_CHARACTERISTICS_TERMINAL_SERVER_AWARE = 0x8000
)
const (
// Section characteristics.
IMAGE_SCN_TYPE_REG = 0x00000000 // Reserved.
IMAGE_SCN_TYPE_DSECT = 0x00000001 // Reserved.
IMAGE_SCN_TYPE_NOLOAD = 0x00000002 // Reserved.
IMAGE_SCN_TYPE_GROUP = 0x00000004 // Reserved.
IMAGE_SCN_TYPE_NO_PAD = 0x00000008 // Reserved.
IMAGE_SCN_TYPE_COPY = 0x00000010 // Reserved.
IMAGE_SCN_CNT_CODE = 0x00000020 // Section contains code.
IMAGE_SCN_CNT_INITIALIZED_DATA = 0x00000040 // Section contains initialized data.
IMAGE_SCN_CNT_UNINITIALIZED_DATA = 0x00000080 // Section contains uninitialized data.
IMAGE_SCN_LNK_OTHER = 0x00000100 // Reserved.
IMAGE_SCN_LNK_INFO = 0x00000200 // Section contains comments or some other type of information.
IMAGE_SCN_TYPE_OVER = 0x00000400 // Reserved.
IMAGE_SCN_LNK_REMOVE = 0x00000800 // Section contents will not become part of image.
IMAGE_SCN_LNK_COMDAT = 0x00001000 // Section contents comdat.
IMAGE_SCN_MEM_PROTECTED = 0x00004000 // Obsolete.
IMAGE_SCN_NO_DEFER_SPEC_EXC = 0x00004000 // Reset speculative exceptions handling bits in the TLB entries for this section.
IMAGE_SCN_GPREL = 0x00008000 // Section content can be accessed relative to GP
IMAGE_SCN_MEM_FARDATA = 0x00008000
IMAGE_SCN_MEM_SYSHEAP = 0x00010000 // Obsolete.
IMAGE_SCN_MEM_PURGEABLE = 0x00020000
IMAGE_SCN_MEM_16BIT = 0x00020000
IMAGE_SCN_MEM_LOCKED = 0x00040000
IMAGE_SCN_MEM_PRELOAD = 0x00080000
IMAGE_SCN_ALIGN_1BYTES = 0x00100000 //
IMAGE_SCN_ALIGN_2BYTES = 0x00200000 //
IMAGE_SCN_ALIGN_4BYTES = 0x00300000 //
IMAGE_SCN_ALIGN_8BYTES = 0x00400000 //
IMAGE_SCN_ALIGN_16BYTES = 0x00500000 // Default alignment if no others are specified.
IMAGE_SCN_ALIGN_32BYTES = 0x00600000 //
IMAGE_SCN_ALIGN_64BYTES = 0x00700000 //
IMAGE_SCN_ALIGN_128BYTES = 0x00800000 //
IMAGE_SCN_ALIGN_256BYTES = 0x00900000 //
IMAGE_SCN_ALIGN_512BYTES = 0x00A00000 //
IMAGE_SCN_ALIGN_1024BYTES = 0x00B00000 //
IMAGE_SCN_ALIGN_2048BYTES = 0x00C00000 //
IMAGE_SCN_ALIGN_4096BYTES = 0x00D00000 //
IMAGE_SCN_ALIGN_8192BYTES = 0x00E00000 //
IMAGE_SCN_ALIGN_MASK = 0x00F00000
IMAGE_SCN_LNK_NRELOC_OVFL = 0x01000000 // Section contains extended relocations.
IMAGE_SCN_MEM_DISCARDABLE = 0x02000000 // Section can be discarded.
IMAGE_SCN_MEM_NOT_CACHED = 0x04000000 // Section is not cachable.
IMAGE_SCN_MEM_NOT_PAGED = 0x08000000 // Section is not pageable.
IMAGE_SCN_MEM_SHARED = 0x10000000 // Section is shareable.
IMAGE_SCN_MEM_EXECUTE = 0x20000000 // Section is executable.
IMAGE_SCN_MEM_READ = 0x40000000 // Section is readable.
IMAGE_SCN_MEM_WRITE = 0x80000000 // Section is writeable.
// TLS Characteristic Flags
IMAGE_SCN_SCALE_INDEX = 0x00000001 // Tls index is scaled.
)
// Based relocation format
type IMAGE_BASE_RELOCATION struct {
VirtualAddress uint32
SizeOfBlock uint32
}
const (
IMAGE_REL_BASED_ABSOLUTE = 0
IMAGE_REL_BASED_HIGH = 1
IMAGE_REL_BASED_LOW = 2
IMAGE_REL_BASED_HIGHLOW = 3
IMAGE_REL_BASED_HIGHADJ = 4
IMAGE_REL_BASED_MACHINE_SPECIFIC_5 = 5
IMAGE_REL_BASED_RESERVED = 6
IMAGE_REL_BASED_MACHINE_SPECIFIC_7 = 7
IMAGE_REL_BASED_MACHINE_SPECIFIC_8 = 8
IMAGE_REL_BASED_MACHINE_SPECIFIC_9 = 9
IMAGE_REL_BASED_DIR64 = 10
IMAGE_REL_BASED_IA64_IMM64 = 9
IMAGE_REL_BASED_MIPS_JMPADDR = 5
IMAGE_REL_BASED_MIPS_JMPADDR16 = 9
IMAGE_REL_BASED_ARM_MOV32 = 5
IMAGE_REL_BASED_THUMB_MOV32 = 7
)
// Export Format
type IMAGE_EXPORT_DIRECTORY struct {
Characteristics uint32
TimeDateStamp uint32
MajorVersion uint16
MinorVersion uint16
Name uint32
Base uint32
NumberOfFunctions uint32
NumberOfNames uint32
AddressOfFunctions uint32 // RVA from base of image
AddressOfNames uint32 // RVA from base of image
AddressOfNameOrdinals uint32 // RVA from base of image
}
type IMAGE_IMPORT_BY_NAME struct {
Hint uint16
Name [1]byte
}
func IMAGE_ORDINAL(ordinal uintptr) uintptr {
return ordinal & 0xffff
}
func IMAGE_SNAP_BY_ORDINAL(ordinal uintptr) bool {
return (ordinal & IMAGE_ORDINAL_FLAG) != 0
}
// Thread Local Storage
type IMAGE_TLS_DIRECTORY struct {
StartAddressOfRawData uintptr
EndAddressOfRawData uintptr
AddressOfIndex uintptr // PDWORD
AddressOfCallbacks uintptr // PIMAGE_TLS_CALLBACK *;
SizeOfZeroFill uint32
Characteristics uint32
}
type IMAGE_IMPORT_DESCRIPTOR struct {
characteristicsOrOriginalFirstThunk uint32 // 0 for terminating null import descriptor
// RVA to original unbound IAT (PIMAGE_THUNK_DATA)
TimeDateStamp uint32 // 0 if not bound,
// -1 if bound, and real date\time stamp
// in IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT (new BIND)
// O.W. date/time stamp of DLL bound to (Old BIND)
ForwarderChain uint32 // -1 if no forwarders
Name uint32
FirstThunk uint32 // RVA to IAT (if bound this IAT has actual addresses)
}
func (imgimpdesc *IMAGE_IMPORT_DESCRIPTOR) Characteristics() uint32 {
return imgimpdesc.characteristicsOrOriginalFirstThunk
}
func (imgimpdesc *IMAGE_IMPORT_DESCRIPTOR) OriginalFirstThunk() uint32 {
return imgimpdesc.characteristicsOrOriginalFirstThunk
}
type IMAGE_DELAYLOAD_DESCRIPTOR struct {
Attributes uint32
DllNameRVA uint32
ModuleHandleRVA uint32
ImportAddressTableRVA uint32
ImportNameTableRVA uint32
BoundImportAddressTableRVA uint32
UnloadInformationTableRVA uint32
TimeDateStamp uint32
}
type IMAGE_LOAD_CONFIG_CODE_INTEGRITY struct {
Flags uint16
Catalog uint16
CatalogOffset uint32
Reserved uint32
}
const (
IMAGE_GUARD_CF_INSTRUMENTED = 0x00000100
IMAGE_GUARD_CFW_INSTRUMENTED = 0x00000200
IMAGE_GUARD_CF_FUNCTION_TABLE_PRESENT = 0x00000400
IMAGE_GUARD_SECURITY_COOKIE_UNUSED = 0x00000800
IMAGE_GUARD_PROTECT_DELAYLOAD_IAT = 0x00001000
IMAGE_GUARD_DELAYLOAD_IAT_IN_ITS_OWN_SECTION = 0x00002000
IMAGE_GUARD_CF_EXPORT_SUPPRESSION_INFO_PRESENT = 0x00004000
IMAGE_GUARD_CF_ENABLE_EXPORT_SUPPRESSION = 0x00008000
IMAGE_GUARD_CF_LONGJUMP_TABLE_PRESENT = 0x00010000
IMAGE_GUARD_RF_INSTRUMENTED = 0x00020000
IMAGE_GUARD_RF_ENABLE = 0x00040000
IMAGE_GUARD_RF_STRICT = 0x00080000
IMAGE_GUARD_RETPOLINE_PRESENT = 0x00100000
IMAGE_GUARD_EH_CONTINUATION_TABLE_PRESENT = 0x00400000
IMAGE_GUARD_XFG_ENABLED = 0x00800000
IMAGE_GUARD_CF_FUNCTION_TABLE_SIZE_MASK = 0xF0000000
IMAGE_GUARD_CF_FUNCTION_TABLE_SIZE_SHIFT = 28
)
const (
DLL_PROCESS_ATTACH = 1
DLL_THREAD_ATTACH = 2
DLL_THREAD_DETACH = 3
DLL_PROCESS_DETACH = 0
)
type SYSTEM_INFO struct {
ProcessorArchitecture uint16
Reserved uint16
PageSize uint32
MinimumApplicationAddress uintptr
MaximumApplicationAddress uintptr
ActiveProcessorMask uintptr
NumberOfProcessors uint32
ProcessorType uint32
AllocationGranularity uint32
ProcessorLevel uint16
ProcessorRevision uint16
}

View File

@@ -1,96 +0,0 @@
//go:build (windows && 386) || (windows && arm)
/* SPDX-License-Identifier: MIT
*
* Copyright (C) 2017-2022 WireGuard LLC. All Rights Reserved.
*/
package memmod
// Optional header format
type IMAGE_OPTIONAL_HEADER struct {
Magic uint16
MajorLinkerVersion uint8
MinorLinkerVersion uint8
SizeOfCode uint32
SizeOfInitializedData uint32
SizeOfUninitializedData uint32
AddressOfEntryPoint uint32
BaseOfCode uint32
BaseOfData uint32
ImageBase uintptr
SectionAlignment uint32
FileAlignment uint32
MajorOperatingSystemVersion uint16
MinorOperatingSystemVersion uint16
MajorImageVersion uint16
MinorImageVersion uint16
MajorSubsystemVersion uint16
MinorSubsystemVersion uint16
Win32VersionValue uint32
SizeOfImage uint32
SizeOfHeaders uint32
CheckSum uint32
Subsystem uint16
DllCharacteristics uint16
SizeOfStackReserve uintptr
SizeOfStackCommit uintptr
SizeOfHeapReserve uintptr
SizeOfHeapCommit uintptr
LoaderFlags uint32
NumberOfRvaAndSizes uint32
DataDirectory [IMAGE_NUMBEROF_DIRECTORY_ENTRIES]IMAGE_DATA_DIRECTORY
}
const IMAGE_ORDINAL_FLAG uintptr = 0x80000000
type IMAGE_LOAD_CONFIG_DIRECTORY struct {
Size uint32
TimeDateStamp uint32
MajorVersion uint16
MinorVersion uint16
GlobalFlagsClear uint32
GlobalFlagsSet uint32
CriticalSectionDefaultTimeout uint32
DeCommitFreeBlockThreshold uint32
DeCommitTotalFreeThreshold uint32
LockPrefixTable uint32
MaximumAllocationSize uint32
VirtualMemoryThreshold uint32
ProcessHeapFlags uint32
ProcessAffinityMask uint32
CSDVersion uint16
DependentLoadFlags uint16
EditList uint32
SecurityCookie uint32
SEHandlerTable uint32
SEHandlerCount uint32
GuardCFCheckFunctionPointer uint32
GuardCFDispatchFunctionPointer uint32
GuardCFFunctionTable uint32
GuardCFFunctionCount uint32
GuardFlags uint32
CodeIntegrity IMAGE_LOAD_CONFIG_CODE_INTEGRITY
GuardAddressTakenIatEntryTable uint32
GuardAddressTakenIatEntryCount uint32
GuardLongJumpTargetTable uint32
GuardLongJumpTargetCount uint32
DynamicValueRelocTable uint32
CHPEMetadataPointer uint32
GuardRFFailureRoutine uint32
GuardRFFailureRoutineFunctionPointer uint32
DynamicValueRelocTableOffset uint32
DynamicValueRelocTableSection uint16
Reserved2 uint16
GuardRFVerifyStackPointerFunctionPointer uint32
HotPatchTableOffset uint32
Reserved3 uint32
EnclaveConfigurationPointer uint32
VolatileMetadataPointer uint32
GuardEHContinuationTable uint32
GuardEHContinuationCount uint32
GuardXFGCheckFunctionPointer uint32
GuardXFGDispatchFunctionPointer uint32
GuardXFGTableDispatchFunctionPointer uint32
CastGuardOsDeterminedFailureMode uint32
}

View File

@@ -1,95 +0,0 @@
//go:build (windows && amd64) || (windows && arm64)
/* SPDX-License-Identifier: MIT
*
* Copyright (C) 2017-2022 WireGuard LLC. All Rights Reserved.
*/
package memmod
// Optional header format
type IMAGE_OPTIONAL_HEADER struct {
Magic uint16
MajorLinkerVersion uint8
MinorLinkerVersion uint8
SizeOfCode uint32
SizeOfInitializedData uint32
SizeOfUninitializedData uint32
AddressOfEntryPoint uint32
BaseOfCode uint32
ImageBase uintptr
SectionAlignment uint32
FileAlignment uint32
MajorOperatingSystemVersion uint16
MinorOperatingSystemVersion uint16
MajorImageVersion uint16
MinorImageVersion uint16
MajorSubsystemVersion uint16
MinorSubsystemVersion uint16
Win32VersionValue uint32
SizeOfImage uint32
SizeOfHeaders uint32
CheckSum uint32
Subsystem uint16
DllCharacteristics uint16
SizeOfStackReserve uintptr
SizeOfStackCommit uintptr
SizeOfHeapReserve uintptr
SizeOfHeapCommit uintptr
LoaderFlags uint32
NumberOfRvaAndSizes uint32
DataDirectory [IMAGE_NUMBEROF_DIRECTORY_ENTRIES]IMAGE_DATA_DIRECTORY
}
const IMAGE_ORDINAL_FLAG uintptr = 0x8000000000000000
type IMAGE_LOAD_CONFIG_DIRECTORY struct {
Size uint32
TimeDateStamp uint32
MajorVersion uint16
MinorVersion uint16
GlobalFlagsClear uint32
GlobalFlagsSet uint32
CriticalSectionDefaultTimeout uint32
DeCommitFreeBlockThreshold uint64
DeCommitTotalFreeThreshold uint64
LockPrefixTable uint64
MaximumAllocationSize uint64
VirtualMemoryThreshold uint64
ProcessAffinityMask uint64
ProcessHeapFlags uint32
CSDVersion uint16
DependentLoadFlags uint16
EditList uint64
SecurityCookie uint64
SEHandlerTable uint64
SEHandlerCount uint64
GuardCFCheckFunctionPointer uint64
GuardCFDispatchFunctionPointer uint64
GuardCFFunctionTable uint64
GuardCFFunctionCount uint64
GuardFlags uint32
CodeIntegrity IMAGE_LOAD_CONFIG_CODE_INTEGRITY
GuardAddressTakenIatEntryTable uint64
GuardAddressTakenIatEntryCount uint64
GuardLongJumpTargetTable uint64
GuardLongJumpTargetCount uint64
DynamicValueRelocTable uint64
CHPEMetadataPointer uint64
GuardRFFailureRoutine uint64
GuardRFFailureRoutineFunctionPointer uint64
DynamicValueRelocTableOffset uint32
DynamicValueRelocTableSection uint16
Reserved2 uint16
GuardRFVerifyStackPointerFunctionPointer uint64
HotPatchTableOffset uint32
Reserved3 uint32
EnclaveConfigurationPointer uint64
VolatileMetadataPointer uint64
GuardEHContinuationTable uint64
GuardEHContinuationCount uint64
GuardXFGCheckFunctionPointer uint64
GuardXFGDispatchFunctionPointer uint64
GuardXFGTableDispatchFunctionPointer uint64
CastGuardOsDeterminedFailureMode uint64
}

View File

@@ -1,50 +0,0 @@
/* SPDX-License-Identifier: MIT
*
* Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package driver
import (
"path/filepath"
"golang.org/x/sys/windows"
)
func UninstallLegacyWintun() error {
deviceClassNetGUID := &windows.GUID{0x4d36e972, 0xe325, 0x11ce, [8]byte{0xbf, 0xc1, 0x08, 0x00, 0x2b, 0xe1, 0x03, 0x18}}
devInfo, err := windows.SetupDiCreateDeviceInfoListEx(deviceClassNetGUID, 0, "")
if err != nil {
return err
}
defer devInfo.Close()
devInfoData, err := devInfo.CreateDeviceInfo("Wintun", deviceClassNetGUID, "", 0, windows.DICD_GENERATE_ID)
if err != nil {
return err
}
err = devInfo.SetDeviceRegistryProperty(devInfoData, windows.SPDRP_HARDWAREID, []byte("W\x00i\x00n\x00t\x00u\x00n\x00\x00\x00\x00\x00"))
if err != nil {
return err
}
err = devInfo.BuildDriverInfoList(devInfoData, windows.SPDIT_COMPATDRIVER)
if err != nil {
return err
}
defer devInfo.DestroyDriverInfoList(devInfoData, windows.SPDIT_COMPATDRIVER)
var lastError error
for i := 0; ; i++ {
drvInfoData, err := devInfo.EnumDriverInfo(devInfoData, windows.SPDIT_COMPATDRIVER, i)
if err != nil {
if err == windows.ERROR_NO_MORE_ITEMS {
break
}
continue
}
drvInfoDetailData, err := devInfo.DriverInfoDetail(devInfoData, drvInfoData)
if err != nil {
continue
}
lastError = windows.SetupUninstallOEMInf(filepath.Base(drvInfoDetailData.InfFileName()), 0)
}
return lastError
}

View File

@@ -14,7 +14,7 @@ import (
"golang.org/x/sys/windows"
"golang.org/x/sys/windows/registry"
"golang.zx2c4.com/wireguard/windows/version"
"github.com/amnezia-vpn/amneziawg-windows-client/version"
)
const (

View File

@@ -1,4 +0,0 @@
# Build Output
/x86
/amd64
/arm64

View File

@@ -1,41 +0,0 @@
## 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`, `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:
```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
is absolutely essential; do not forget it.
##### 2. Have your program's main function handle the `/service` switch:
```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.
There is a sample implementation of bits and pieces of this inside of the `csharp\` directory.

View File

@@ -1,48 +0,0 @@
@echo off
rem SPDX-License-Identifier: MIT
rem Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
setlocal
set BUILDDIR=%~dp0
set PATH=%BUILDDIR%..\.deps\llvm-mingw\bin;%BUILDDIR%..\.deps\go\bin;%PATH%
set PATHEXT=.exe
cd /d %BUILDDIR% || exit /b 1
if exist ..\.deps\prepared goto :build
:installdeps
call ..\build.bat || goto :error
: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
call :build_plat x86 i686 386 || goto :error
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 "%SigningCertificate%"=="" goto :success
if "%TimestampServer%"=="" goto :success
echo [+] Signing
signtool sign /sha1 "%SigningCertificate%" /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 CC=%~2-w64-mingw32-gcc
set GOARCH=%~3
mkdir %1 >NUL 2>&1
echo [+] Building library %1
go build -buildmode c-shared -ldflags="-w -s" -trimpath -v -o "%~1/tunnel.dll" || exit /b 1
del "%~1\tunnel.h"
goto :eof
:error
echo [-] Failed with error #%errorlevel%.
cmd /c exit %errorlevel%

View File

@@ -1,3 +0,0 @@
/.vs
/bin
/obj

View File

@@ -1,87 +0,0 @@
/* 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;
}
}

View File

@@ -1,215 +0,0 @@
/* 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;
}
}
}

View File

@@ -1,60 +0,0 @@
<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>

View File

@@ -1,44 +0,0 @@
/* 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());
}
}
}

View File

@@ -1,48 +0,0 @@
<?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>

View File

@@ -1,7 +0,0 @@
# 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).

View File

@@ -1,234 +0,0 @@
/* 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;
}
}
}
}

View File

@@ -1,33 +0,0 @@
/* SPDX-License-Identifier: MIT
*
* Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
using System;
using System.Runtime.InteropServices;
namespace Tunnel
{
public class Keypair
{
public readonly string Public;
public readonly string Private;
public Keypair(string pub, string priv)
{
Public = pub;
Private = priv;
}
[DllImport("tunnel.dll", EntryPoint = "WireGuardGenerateKeypair", CallingConvention = CallingConvention.Cdecl)]
private static extern bool WireGuardGenerateKeypair(byte[] publicKey, byte[] privateKey);
public static Keypair Generate()
{
var publicKey = new byte[32];
var privateKey = new byte[32];
WireGuardGenerateKeypair(publicKey, privateKey);
return new Keypair(Convert.ToBase64String(publicKey), Convert.ToBase64String(privateKey));
}
}
}

View File

@@ -1,205 +0,0 @@
/* SPDX-License-Identifier: MIT
*
* Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
using System;
using System.IO;
using System.IO.MemoryMappedFiles;
using System.Text;
using System.Collections.Generic;
using System.Threading;
using System.Runtime.CompilerServices;
namespace Tunnel
{
public class Ringlogger
{
private struct UnixTimestamp
{
private Int64 _ns;
public UnixTimestamp(Int64 ns) => _ns = ns;
public bool IsEmpty => _ns == 0;
public static UnixTimestamp Empty => new UnixTimestamp(0);
public static UnixTimestamp Now
{
get
{
var now = DateTimeOffset.UtcNow;
var ns = (now.Subtract(DateTimeOffset.FromUnixTimeSeconds(0)).Ticks * 100) % 1000000000;
return new UnixTimestamp(now.ToUnixTimeSeconds() * 1000000000 + ns);
}
}
public Int64 Nanoseconds => _ns;
public override string ToString()
{
return DateTimeOffset.FromUnixTimeSeconds(_ns / 1000000000).LocalDateTime.ToString("yyyy'-'MM'-'dd HH':'mm':'ss'.'") + ((_ns % 1000000000).ToString() + "00000").Substring(0, 6);
}
}
private struct Line
{
private const int maxLineLength = 512;
private const int offsetTimeNs = 0;
private const int offsetLine = 8;
private readonly MemoryMappedViewAccessor _view;
private readonly int _start;
public Line(MemoryMappedViewAccessor view, UInt32 index) => (_view, _start) = (view, (int)(Log.HeaderBytes + index * Bytes));
public static int Bytes => maxLineLength + offsetLine;
public UnixTimestamp Timestamp
{
get => new UnixTimestamp(_view.ReadInt64(_start + offsetTimeNs));
set => _view.Write(_start + offsetTimeNs, value.Nanoseconds);
}
public string Text
{
get
{
var textBytes = new byte[maxLineLength];
_view.ReadArray(_start + offsetLine, textBytes, 0, textBytes.Length);
var nullByte = Array.IndexOf<byte>(textBytes, 0);
if (nullByte <= 0)
return null;
return Encoding.UTF8.GetString(textBytes, 0, nullByte);
}
set
{
if (value == null)
{
_view.WriteArray(_start + offsetLine, new byte[maxLineLength], 0, maxLineLength);
return;
}
var textBytes = Encoding.UTF8.GetBytes(value);
var bytesToWrite = Math.Min(maxLineLength - 1, textBytes.Length);
_view.Write(_start + offsetLine + bytesToWrite, (byte)0);
_view.WriteArray(_start + offsetLine, textBytes, 0, bytesToWrite);
}
}
public override string ToString()
{
var time = Timestamp;
if (time.IsEmpty)
return null;
var text = Text;
if (text == null)
return null;
return string.Format("{0}: {1}", time, text);
}
}
private struct Log
{
private const UInt32 maxLines = 2048;
private const UInt32 magic = 0xbadbabe;
private const int offsetMagic = 0;
private const int offsetNextIndex = 4;
private const int offsetLines = 8;
private readonly MemoryMappedViewAccessor _view;
public Log(MemoryMappedViewAccessor view) => _view = view;
public static int HeaderBytes => offsetLines;
public static int Bytes => (int)(HeaderBytes + Line.Bytes * maxLines);
public UInt32 ExpectedMagic => magic;
public UInt32 Magic
{
get => _view.ReadUInt32(offsetMagic);
set => _view.Write(offsetMagic, value);
}
public UInt32 NextIndex
{
get => _view.ReadUInt32(offsetNextIndex);
set => _view.Write(offsetNextIndex, value);
}
public unsafe UInt32 InsertNextIndex()
{
byte* pointer = null;
_view.SafeMemoryMappedViewHandle.AcquirePointer(ref pointer);
var ret = (UInt32)Interlocked.Increment(ref Unsafe.AsRef<Int32>(pointer + offsetNextIndex));
_view.SafeMemoryMappedViewHandle.ReleasePointer();
return ret;
}
public UInt32 LineCount => maxLines;
public Line this[UInt32 i] => new Line(_view, i % maxLines);
public void Clear() => _view.WriteArray(0, new byte[Bytes], 0, Bytes);
}
private readonly Log _log;
private readonly string _tag;
public Ringlogger(string filename, string tag)
{
var file = File.Open(filename, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite | FileShare.Delete);
file.SetLength(Log.Bytes);
var mmap = MemoryMappedFile.CreateFromFile(file, null, 0, MemoryMappedFileAccess.ReadWrite, HandleInheritability.None, false);
var view = mmap.CreateViewAccessor(0, Log.Bytes, MemoryMappedFileAccess.ReadWrite);
_log = new Log(view);
if (_log.Magic != _log.ExpectedMagic)
{
_log.Clear();
_log.Magic = _log.ExpectedMagic;
}
_tag = tag;
}
public void Write(string line)
{
var time = UnixTimestamp.Now;
var entry = _log[_log.InsertNextIndex() - 1];
entry.Timestamp = UnixTimestamp.Empty;
entry.Text = null;
entry.Text = string.Format("[{0}] {1}", _tag, line.Trim());
entry.Timestamp = time;
}
public void WriteTo(TextWriter writer)
{
var start = _log.NextIndex;
for (UInt32 i = 0; i < _log.LineCount; ++i)
{
var entry = _log[i + start];
if (entry.Timestamp.IsEmpty)
continue;
var text = entry.ToString();
if (text == null)
continue;
writer.WriteLine(text);
}
}
public static readonly UInt32 CursorAll = UInt32.MaxValue;
public List<string> FollowFromCursor(ref UInt32 cursor)
{
var lines = new List<string>((int)_log.LineCount);
var i = cursor;
var all = cursor == CursorAll;
if (all)
i = _log.NextIndex;
for (UInt32 l = 0; l < _log.LineCount; ++l, ++i)
{
if (!all && i % _log.LineCount == _log.NextIndex % _log.LineCount)
break;
var entry = _log[i];
if (entry.Timestamp.IsEmpty)
{
if (all)
continue;
break;
}
cursor = (i + 1) % _log.LineCount;
var text = entry.ToString();
if (text == null)
continue;
lines.Add(text);
}
return lines;
}
}
}

View File

@@ -1,113 +0,0 @@
/* SPDX-License-Identifier: MIT
*
* Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
using System;
using System.IO;
using System.IO.Pipes;
using System.Runtime.InteropServices;
using System.ComponentModel;
using System.Diagnostics;
using System.Threading;
namespace Tunnel
{
public class Service
{
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 Driver.Adapter GetAdapter(string configFile)
{
return new Driver.Adapter(Path.GetFileNameWithoutExtension(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}\" {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)
throw new Win32Exception(Marshal.GetLastWin32Error());
try
{
var service = Win32.OpenService(scm, shortName, Win32.ServiceAccessRights.AllAccess);
if (service != IntPtr.Zero)
{
Win32.CloseServiceHandle(service);
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\0TcpIp\0", null, null);
if (service == IntPtr.Zero)
throw new Win32Exception(Marshal.GetLastWin32Error());
try
{
var sidType = Win32.ServiceSidType.Unrestricted;
if (!Win32.ChangeServiceConfig2(service, Win32.ServiceConfigType.SidInfo, ref sidType))
throw new Win32Exception(Marshal.GetLastWin32Error());
var description = new Win32.ServiceDescription { lpDescription = Description };
if (!Win32.ChangeServiceConfig2(service, Win32.ServiceConfigType.Description, ref description))
throw new Win32Exception(Marshal.GetLastWin32Error());
if (!Win32.StartService(service, 0, null))
throw new Win32Exception(Marshal.GetLastWin32Error());
if (ephemeral && !Win32.DeleteService(service))
throw new Win32Exception(Marshal.GetLastWin32Error());
}
finally
{
Win32.CloseServiceHandle(service);
}
}
finally
{
Win32.CloseServiceHandle(scm);
}
}
public static void Remove(string configFile, bool waitForStop)
{
var tunnelName = Path.GetFileNameWithoutExtension(configFile);
var shortName = String.Format("WireGuardTunnel${0}", tunnelName);
var scm = Win32.OpenSCManager(null, null, Win32.ScmAccessRights.AllAccess);
if (scm == IntPtr.Zero)
throw new Win32Exception(Marshal.GetLastWin32Error());
try
{
var service = Win32.OpenService(scm, shortName, Win32.ServiceAccessRights.AllAccess);
if (service == IntPtr.Zero)
return;
try
{
var serviceStatus = new Win32.ServiceStatus();
Win32.ControlService(service, Win32.ServiceControl.Stop, serviceStatus);
for (int i = 0; waitForStop && i < 180 && Win32.QueryServiceStatus(service, serviceStatus) && serviceStatus.dwCurrentState != Win32.ServiceState.Stopped; ++i)
Thread.Sleep(1000);
if (!Win32.DeleteService(service) && Marshal.GetLastWin32Error() != 0x00000430)
throw new Win32Exception(Marshal.GetLastWin32Error());
}
finally
{
Win32.CloseServiceHandle(service);
}
}
finally
{
Win32.CloseServiceHandle(scm);
}
}
}
}

View File

@@ -1,227 +0,0 @@
/* SPDX-License-Identifier: MIT
*
* Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
using System;
using System.Runtime.InteropServices;
namespace Tunnel
{
static class Win32
{
[Flags]
public enum ScmAccessRights
{
Connect = 0x0001,
CreateService = 0x0002,
EnumerateService = 0x0004,
Lock = 0x0008,
QueryLockStatus = 0x0010,
ModifyBootConfig = 0x0020,
StandardRightsRequired = 0xF0000,
AllAccess = (StandardRightsRequired | Connect | CreateService | EnumerateService | Lock | QueryLockStatus | ModifyBootConfig)
}
[Flags]
public enum ServiceAccessRights
{
QueryConfig = 0x1,
ChangeConfig = 0x2,
QueryStatus = 0x4,
EnumerateDependants = 0x8,
Start = 0x10,
Stop = 0x20,
PauseContinue = 0x40,
Interrogate = 0x80,
UserDefinedControl = 0x100,
Delete = 0x00010000,
StandardRightsRequired = 0xF0000,
AllAccess = (StandardRightsRequired | QueryConfig | ChangeConfig | QueryStatus | EnumerateDependants | Start | Stop | PauseContinue | Interrogate | UserDefinedControl)
}
[Flags]
public enum ServiceStartType
{
Boot = 0x00000000,
System = 0x00000001,
Auto = 0x00000002,
Demand = 0x00000003,
Disabled = 0x00000004
}
[Flags]
public enum ServiceControl
{
Stop = 0x00000001,
Pause = 0x00000002,
Continue = 0x00000003,
Interrogate = 0x00000004,
Shutdown = 0x00000005,
ParamChange = 0x00000006,
NetBindAdd = 0x00000007,
NetBindRemove = 0x00000008,
NetBindEnable = 0x00000009,
NetBindDisable = 0x0000000A
}
[Flags]
public enum ServiceError
{
Ignore = 0x00000000,
Normal = 0x00000001,
Severe = 0x00000002,
Critical = 0x00000003
}
[Flags]
public enum ServiceSidType
{
None = 0x00000000,
Unrestricted = 0x00000001,
Restricted = 0x00000003
}
[Flags]
public enum ServiceType
{
KernelDriver = 0x00000001,
FileSystemDriver = 0x00000002,
Win32OwnProcess = 0x00000010,
Win32ShareProcess = 0x00000020,
InteractiveProcess = 0x00000100
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode, Size = 8192), ComVisible(false)]
public struct ServiceSidInfo
{
public ServiceSidType serviceSidType;
};
public enum ServiceState
{
Unknown = -1,
NotFound = 0,
Stopped = 1,
StartPending = 2,
StopPending = 3,
Running = 4,
ContinuePending = 5,
PausePending = 6,
Paused = 7
}
[StructLayout(LayoutKind.Sequential)]
public class ServiceStatus
{
public int dwServiceType = 0;
public ServiceState dwCurrentState = 0;
public int dwControlsAccepted = 0;
public int dwWin32ExitCode = 0;
public int dwServiceSpecificExitCode = 0;
public int dwCheckPoint = 0;
public int dwWaitHint = 0;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode, Size = 8192), ComVisible(false)]
public struct ServiceDescription
{
public String lpDescription;
};
public enum ServiceConfigType
{
Description = 1,
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);
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern IntPtr OpenService(IntPtr hSCManager, string lpServiceName, ServiceAccessRights dwDesiredAccess);
[DllImport("advapi32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool CloseServiceHandle(IntPtr hSCObject);
[DllImport("advapi32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool StartService(IntPtr hService, int dwNumServiceArgs, string[] lpServiceArgVectors);
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern IntPtr CreateService(IntPtr hSCManager, string lpServiceName, string lpDisplayName, ServiceAccessRights dwDesiredAccess, ServiceType dwServiceType, ServiceStartType dwStartType, ServiceError dwErrorControl, string lpBinaryPathName, string lpLoadOrderGroup, IntPtr lpdwTagId, string lpDependencies, string lp, string lpPassword);
[DllImport("advapi32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool DeleteService(IntPtr hService);
[DllImport("advapi32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool ControlService(IntPtr hService, ServiceControl dwControl, ServiceStatus lpServiceStatus);
[DllImport("advapi32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool QueryServiceStatus(IntPtr hService, ServiceStatus lpServiceStatus);
[DllImport("advapi32.dll", EntryPoint = "ChangeServiceConfig2", CharSet = CharSet.Unicode, SetLastError = true, CallingConvention = CallingConvention.StdCall)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool ChangeServiceConfig2(IntPtr hService, ServiceConfigType dwInfoLevel, ref ServiceSidType lpInfo);
[DllImport("advapi32.dll", EntryPoint = "ChangeServiceConfig2", CharSet = CharSet.Unicode, SetLastError = true, CallingConvention = CallingConvention.StdCall)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool ChangeServiceConfig2(IntPtr hService, ServiceConfigType dwInfoLevel, ref ServiceDescription lpInfo);
}
}

View File

@@ -1,14 +0,0 @@
<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>

View File

@@ -1,8 +0,0 @@
<?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>

View File

@@ -1,25 +0,0 @@
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

View File

@@ -1,48 +0,0 @@
/* SPDX-License-Identifier: MIT
*
* 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"
)
//export WireGuardTunnelService
func WireGuardTunnelService(confFile16 *uint16) bool {
confFile := windows.UTF16PtrToString(confFile16)
conf.PresetRootDirectory(filepath.Dir(confFile))
tunnel.UseFixedGUIDInsteadOfDeterministic = true
err := tunnel.Run(confFile)
if err != nil {
log.Printf("Service run error: %v", err)
}
return err == nil
}
//export WireGuardGenerateKeypair
func WireGuardGenerateKeypair(publicKey, privateKey *byte) {
publicKeyArray := (*[32]byte)(unsafe.Pointer(publicKey))
privateKeyArray := (*[32]byte)(unsafe.Pointer(privateKey))
n, err := rand.Read(privateKeyArray[:])
if err != nil || n != len(privateKeyArray) {
panic("Unable to generate random bytes")
}
privateKeyArray[0] &= 248
privateKeyArray[31] = (privateKeyArray[31] & 127) | 64
curve25519.ScalarBaseMult(publicKeyArray, privateKeyArray)
}
func main() {}

22
go.mod
View File

@@ -1,20 +1,24 @@
module golang.zx2c4.com/wireguard/windows
module github.com/amnezia-vpn/amneziawg-windows-client
go 1.18
go 1.20
require (
github.com/amnezia-vpn/awg-windows v0.1.4-0.20240424161542-e8e067a05ad4
github.com/lxn/walk v0.0.0-20210112085537-c389da54e794
github.com/lxn/win v0.0.0-20210218163916-a377121e959e
golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd
golang.org/x/net v0.0.0-20220225172249-27dd8689420f
golang.org/x/sys v0.0.0-20220315194320-039c03cc5b86
golang.org/x/text v0.3.8-0.20220124021120-d1c84af989ab
golang.org/x/crypto v0.18.0
golang.org/x/sys v0.16.0
golang.org/x/text v0.14.0
golang.zx2c4.com/wireguard/windows v0.5.3
)
require (
golang.org/x/mod v0.4.2 // indirect
golang.org/x/tools v0.1.7 // indirect
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
github.com/amnezia-vpn/amnezia-wg v0.1.8 // indirect
github.com/tevino/abool/v2 v2.1.0 // indirect
golang.org/x/mod v0.8.0 // indirect
golang.org/x/net v0.20.0 // indirect
golang.org/x/tools v0.6.0 // indirect
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 // indirect
)
replace (

50
go.sum
View File

@@ -1,29 +1,31 @@
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd h1:XcWmESyNjXJMLahc3mqVQJcgSTDxFxhETVlfk9uGc38=
golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
github.com/amnezia-vpn/amnezia-wg v0.1.8 h1:CuJ33YIuRbmuN6+Rs6n6qe2sVvDu1v1toRly9BHZgKM=
github.com/amnezia-vpn/amnezia-wg v0.1.8/go.mod h1:vB51g4MZ8nCj3oEF5qg1YN/2JYEgKvd7+knuCFH4Tf0=
github.com/amnezia-vpn/awg-windows v0.1.4-0.20240424161542-e8e067a05ad4 h1:07po/2reK/zDeYiTrkHH3AFV+triJII5s5e/RZ0ryNU=
github.com/amnezia-vpn/awg-windows v0.1.4-0.20240424161542-e8e067a05ad4/go.mod h1:FKM2YNOa0fUgViVGuTMP09p5if/KwHMd9C2aMA+ueRo=
github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4=
github.com/tevino/abool/v2 v2.1.0 h1:7w+Vf9f/5gmKT4m4qkayb33/92M+Um45F2BkHOR+L/c=
github.com/tevino/abool/v2 v2.1.0/go.mod h1:+Lmlqk6bHDWHqN1cbxqhwEAwMPXgc8I1SDEamtseuXY=
golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc=
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
golang.org/x/mod v0.8.0 h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo=
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
golang.org/x/sys v0.0.0-20201018230417-eeed37f84f13/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20220315194320-039c03cc5b86 h1:A9i04dxx7Cribqbs8jf3FQLogkL/CV2YN7hj9KWJCkc=
golang.org/x/sys v0.0.0-20220315194320-039c03cc5b86/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.8-0.20220124021120-d1c84af989ab h1:eHo2TTVBaAPw9lDGK2Gb9GyPMXT6g7O63W6sx3ylbzU=
golang.org/x/text v0.3.8-0.20220124021120-d1c84af989ab/go.mod h1:EFNZuWvGYxIRUEX+K8UmCFwYmZjqcrnq15ZuVldZkZ0=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.7 h1:6j8CgantCy3yc8JGBqkDLMKWqZ0RDU2g1HVgacojGWQ=
golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU=
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 h1:vVKdlvoWBphwdxWKrFZEuM0kGgGLxUOYcY4U/2Vjg44=
golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2 h1:B82qJJgjvYKsXS9jeunTOisW56dUokqW/FOteYJJ/yg=
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2/go.mod h1:deeaetjYA+DHMHg+sMSMI58GrEteJUUzzw7en6TJQcI=
golang.zx2c4.com/wireguard/windows v0.0.0-20210121140954-e7fc19d483bd h1:kAUzMAITME2MCtrXBaUa9P4tndiXGWO674k9gn6ZR28=
golang.zx2c4.com/wireguard/windows v0.0.0-20210121140954-e7fc19d483bd/go.mod h1:Y+FYqVFaQO6a+1uigm0N0GiuaZrLEaBxEiJ8tfH9sMQ=
golang.zx2c4.com/wireguard/windows v0.0.0-20210224134948-620c54ef6199 h1:ogXKLng/Myrt2odYTkleySGzQj/GWg9GV1AQ8P9NnU4=
golang.zx2c4.com/wireguard/windows v0.0.0-20210224134948-620c54ef6199/go.mod h1:KxxjdtRkfNoYDCUP5ryK7XJJNTnpC8atvtmTheChOtk=
golang.zx2c4.com/wireguard/windows v0.5.3 h1:On6j2Rpn3OEMXqBq00QEDC7bWSZrPIHKIus8eIuExIE=
golang.zx2c4.com/wireguard/windows v0.5.3/go.mod h1:9TEe8TJmtwyQebdFwAkEWOPr3prrtqm+REGFifP60hI=
gvisor.dev/gvisor v0.0.0-20230927004350-cbd86285d259 h1:TbRPT0HtzFP3Cno1zZo7yPzEEnfu8EjLfl6IU9VfqkQ=

View File

@@ -21,7 +21,7 @@ if exist .deps\prepared goto :build
rmdir /s /q .deps 2> NUL
mkdir .deps || goto :error
cd .deps || goto :error
call :download wix-binaries.zip https://wixtoolset.org/downloads/v3.14.0.4118/wix314-binaries.zip 34dcbba9952902bfb710161bd45ee2e721ffa878db99f738285a21c9b09c6edb || goto :error
call :download wix-binaries.zip https://github.com/wixtoolset/wix3/releases/download/wix3141rtm/wix314-binaries.zip 6ac824e1642d6f7277d0ed7ea09411a508f6116ba6fae0aa5f2c7daa2ff43d31 || goto :error
echo [+] Extracting wix-binaries.zip
mkdir wix\bin || goto :error
tar -xf wix-binaries.zip -C wix\bin || goto :error
@@ -32,7 +32,7 @@ if exist .deps\prepared goto :build
:build
if exist ..\sign.bat call ..\sign.bat
set PATH=%BUILDDIR%..\.deps\llvm-mingw\bin;%PATH%
set PATH=%BUILDDIR%..\.deps\llvm-mingw-20231128-ucrt-x86_64\bin;%PATH%
set WIX=%BUILDDIR%.deps\wix\
set CFLAGS=-O3 -Wall -std=gnu11 -DWINVER=0x0601 -D_WIN32_WINNT=0x0601 -municode -DUNICODE -D_UNICODE -DNDEBUG
set LDFLAGS=-shared -s -Wl,--kill-at -Wl,--major-os-version=6 -Wl,--minor-os-version=1 -Wl,--major-subsystem-version=6 -Wl,--minor-subsystem-version=1 -Wl,--tsaware -Wl,--dynamicbase -Wl,--nxcompat -Wl,--export-all-symbols

View File

@@ -84,6 +84,9 @@
<File Source="..\$(var.WIREGUARD_PLATFORM)\wg.exe" KeyPath="yes" />
<Environment Id="PATH" Name="PATH" System="yes" Action="set" Part="last" Permanent="no" Value="[WireGuardFolder]" />
</Component>
<Component Directory="WireGuardFolder" Id="WintunLibrary" Guid="ac88e408-9b78-4eb3-9d2a-99305f2e5a51">
<File Source="..\$(var.WIREGUARD_PLATFORM)\wintun.dll" KeyPath="yes" />
</Component>
</ComponentGroup>
<!--

View File

@@ -290,7 +290,7 @@
{
"id": "Bytes",
"string": "%[1]d",
"type": "golang.zx2c4.com/wireguard/windows/conf.Bytes",
"type": "github.com/amnezia-vpn/amneziawg-windows-client/conf.Bytes",
"underlyingType": "uint64",
"argNum": 1,
"expr": "b"

View File

@@ -326,7 +326,7 @@
{
"id": "Bytes",
"string": "%[1]d",
"type": "golang.zx2c4.com/wireguard/windows/conf.Bytes",
"type": "github.com/amnezia-vpn/amneziawg-windows-client/conf.Bytes",
"underlyingType": "uint64",
"argNum": 1,
"expr": "b"

View File

@@ -296,7 +296,7 @@
{
"id": "Bytes",
"string": "%[1]d",
"type": "golang.zx2c4.com/wireguard/windows/conf.Bytes",
"type": "github.com/amnezia-vpn/amneziawg-windows-client/conf.Bytes",
"underlyingType": "uint64",
"argNum": 1,
"expr": "b"

View File

@@ -309,7 +309,7 @@
{
"id": "Bytes",
"string": "%[1]d",
"type": "golang.zx2c4.com/wireguard/windows/conf.Bytes",
"type": "github.com/amnezia-vpn/amneziawg-windows-client/conf.Bytes",
"underlyingType": "uint64",
"argNum": 1,
"expr": "b"

View File

@@ -214,7 +214,7 @@
{
"id": "Bytes",
"string": "%[1]d",
"type": "golang.zx2c4.com/wireguard/windows/conf.Bytes",
"type": "github.com/amnezia-vpn/amneziawg-windows-client/conf.Bytes",
"underlyingType": "uint64",
"argNum": 1,
"expr": "b"

View File

@@ -184,7 +184,7 @@
{
"id": "Bytes",
"string": "%[1]d",
"type": "golang.zx2c4.com/wireguard/windows/conf.Bytes",
"type": "github.com/amnezia-vpn/amneziawg-windows-client/conf.Bytes",
"underlyingType": "uint64",
"argNum": 1,
"expr": "b"

View File

@@ -44,7 +44,7 @@
{
"id": "Bytes",
"string": "%[1]d",
"type": "golang.zx2c4.com/wireguard/windows/conf.Bytes",
"type": "github.com/amnezia-vpn/amneziawg-windows-client/conf.Bytes",
"underlyingType": "uint64",
"argNum": 1,
"expr": "b"

View File

@@ -296,7 +296,7 @@
{
"id": "Bytes",
"string": "%[1]d",
"type": "golang.zx2c4.com/wireguard/windows/conf.Bytes",
"type": "github.com/amnezia-vpn/amneziawg-windows-client/conf.Bytes",
"underlyingType": "uint64",
"argNum": 1,
"expr": "b"

View File

@@ -275,7 +275,7 @@
{
"id": "Bytes",
"string": "%[1]d",
"type": "golang.zx2c4.com/wireguard/windows/conf.Bytes",
"type": "github.com/amnezia-vpn/amneziawg-windows-client/conf.Bytes",
"underlyingType": "uint64",
"argNum": 1,
"expr": "b"

View File

@@ -296,7 +296,7 @@
{
"id": "Bytes",
"string": "%[1]d",
"type": "golang.zx2c4.com/wireguard/windows/conf.Bytes",
"type": "github.com/amnezia-vpn/amneziawg-windows-client/conf.Bytes",
"underlyingType": "uint64",
"argNum": 1,
"expr": "b"

View File

@@ -281,7 +281,7 @@
{
"id": "Bytes",
"string": "%[1]d",
"type": "golang.zx2c4.com/wireguard/windows/conf.Bytes",
"type": "github.com/amnezia-vpn/amneziawg-windows-client/conf.Bytes",
"underlyingType": "uint64",
"argNum": 1,
"expr": "b"

View File

@@ -290,7 +290,7 @@
{
"id": "Bytes",
"string": "%[1]d",
"type": "golang.zx2c4.com/wireguard/windows/conf.Bytes",
"type": "github.com/amnezia-vpn/amneziawg-windows-client/conf.Bytes",
"underlyingType": "uint64",
"argNum": 1,
"expr": "b"

View File

@@ -326,7 +326,7 @@
{
"id": "Bytes",
"string": "%[1]d",
"type": "golang.zx2c4.com/wireguard/windows/conf.Bytes",
"type": "github.com/amnezia-vpn/amneziawg-windows-client/conf.Bytes",
"underlyingType": "uint64",
"argNum": 1,
"expr": "b"

View File

@@ -311,7 +311,7 @@
{
"id": "Bytes",
"string": "%[1]d",
"type": "golang.zx2c4.com/wireguard/windows/conf.Bytes",
"type": "github.com/amnezia-vpn/amneziawg-windows-client/conf.Bytes",
"underlyingType": "uint64",
"argNum": 1,
"expr": "b"

View File

@@ -326,7 +326,7 @@
{
"id": "Bytes",
"string": "%[1]d",
"type": "golang.zx2c4.com/wireguard/windows/conf.Bytes",
"type": "github.com/amnezia-vpn/amneziawg-windows-client/conf.Bytes",
"underlyingType": "uint64",
"argNum": 1,
"expr": "b"

View File

@@ -202,7 +202,7 @@
{
"id": "Bytes",
"string": "%[1]d",
"type": "golang.zx2c4.com/wireguard/windows/conf.Bytes",
"type": "github.com/amnezia-vpn/amneziawg-windows-client/conf.Bytes",
"underlyingType": "uint64",
"argNum": 1,
"expr": "b"

View File

@@ -326,7 +326,7 @@
{
"id": "Bytes",
"string": "%[1]d",
"type": "golang.zx2c4.com/wireguard/windows/conf.Bytes",
"type": "github.com/amnezia-vpn/amneziawg-windows-client/conf.Bytes",
"underlyingType": "uint64",
"argNum": 1,
"expr": "b"

View File

@@ -326,7 +326,7 @@
{
"id": "Bytes",
"string": "%[1]d",
"type": "golang.zx2c4.com/wireguard/windows/conf.Bytes",
"type": "github.com/amnezia-vpn/amneziawg-windows-client/conf.Bytes",
"underlyingType": "uint64",
"argNum": 1,
"expr": "b"

View File

@@ -296,7 +296,7 @@
{
"id": "Bytes",
"string": "%[1]d",
"type": "golang.zx2c4.com/wireguard/windows/conf.Bytes",
"type": "github.com/amnezia-vpn/amneziawg-windows-client/conf.Bytes",
"underlyingType": "uint64",
"argNum": 1,
"expr": "b"

View File

@@ -156,7 +156,7 @@
{
"id": "Bytes",
"string": "%[1]d",
"type": "golang.zx2c4.com/wireguard/windows/conf.Bytes",
"type": "github.com/amnezia-vpn/amneziawg-windows-client/conf.Bytes",
"underlyingType": "uint64",
"argNum": 1,
"expr": "b"

View File

@@ -281,7 +281,7 @@
{
"id": "Bytes",
"string": "%[1]d",
"type": "golang.zx2c4.com/wireguard/windows/conf.Bytes",
"type": "github.com/amnezia-vpn/amneziawg-windows-client/conf.Bytes",
"underlyingType": "uint64",
"argNum": 1,
"expr": "b"

View File

@@ -281,7 +281,7 @@
{
"id": "Bytes",
"string": "%[1]d",
"type": "golang.zx2c4.com/wireguard/windows/conf.Bytes",
"type": "github.com/amnezia-vpn/amneziawg-windows-client/conf.Bytes",
"underlyingType": "uint64",
"argNum": 1,
"expr": "b"

30
main.go
View File

@@ -18,15 +18,14 @@ import (
"golang.org/x/sys/windows"
"golang.zx2c4.com/wireguard/windows/conf"
"golang.zx2c4.com/wireguard/windows/driver"
"golang.zx2c4.com/wireguard/windows/elevate"
"golang.zx2c4.com/wireguard/windows/l18n"
"golang.zx2c4.com/wireguard/windows/manager"
"golang.zx2c4.com/wireguard/windows/ringlogger"
"golang.zx2c4.com/wireguard/windows/tunnel"
"golang.zx2c4.com/wireguard/windows/ui"
"golang.zx2c4.com/wireguard/windows/updater"
"github.com/amnezia-vpn/awg-windows/tunnel"
"github.com/amnezia-vpn/amneziawg-windows-client/elevate"
"github.com/amnezia-vpn/amneziawg-windows-client/l18n"
"github.com/amnezia-vpn/amneziawg-windows-client/manager"
"github.com/amnezia-vpn/amneziawg-windows-client/ringlogger"
"github.com/amnezia-vpn/amneziawg-windows-client/ui"
"github.com/amnezia-vpn/amneziawg-windows-client/updater"
)
func setLogFile() {
@@ -74,7 +73,6 @@ func usage() {
"/ui CMD_READ_HANDLE CMD_WRITE_HANDLE CMD_EVENT_HANDLE LOG_MAPPING_HANDLE",
"/dumplog [/tail]",
"/update",
"/removedriver",
}
builder := strings.Builder{}
for _, flag := range flags {
@@ -281,7 +279,7 @@ func main() {
}
file := os.NewFile(uintptr(outputHandle), "stdout")
defer file.Close()
logPath, err := conf.LogFile(false)
logPath, err := manager.LogFile(false)
if err != nil {
fatal(err)
}
@@ -314,16 +312,6 @@ func main() {
}
}
return
case "/removedriver":
if len(os.Args) != 2 {
usage()
}
_ = driver.UninstallLegacyWintun() // Best effort
err := driver.Uninstall()
if err != nil {
fatal(err)
}
return
}
usage()
}

View File

@@ -16,7 +16,8 @@ import (
"golang.org/x/sys/windows/svc"
"golang.org/x/sys/windows/svc/mgr"
"golang.zx2c4.com/wireguard/windows/conf"
"github.com/amnezia-vpn/awg-windows/conf"
"github.com/amnezia-vpn/awg-windows/services"
)
var cachedServiceManager *mgr.Mgr
@@ -129,7 +130,7 @@ func InstallTunnel(configPath string) error {
return err
}
serviceName, err := conf.ServiceNameOfTunnel(name)
serviceName, err := services.ServiceNameOfTunnel(name)
if err != nil {
return err
}
@@ -182,7 +183,7 @@ func UninstallTunnel(name string) error {
if err != nil {
return err
}
serviceName, err := conf.ServiceNameOfTunnel(name)
serviceName, err := services.ServiceNameOfTunnel(name)
if err != nil {
return err
}
@@ -210,7 +211,7 @@ func changeTunnelServiceConfigFilePath(name, oldPath, newPath string) {
if err != nil {
return
}
serviceName, err := conf.ServiceNameOfTunnel(name)
serviceName, err := services.ServiceNameOfTunnel(name)
if err != nil {
return
}

View File

@@ -11,8 +11,8 @@ import (
"os"
"sync"
"golang.zx2c4.com/wireguard/windows/conf"
"golang.zx2c4.com/wireguard/windows/updater"
"github.com/amnezia-vpn/amneziawg-windows-client/updater"
"github.com/amnezia-vpn/awg-windows/conf"
)
type Tunnel struct {

View File

@@ -19,8 +19,9 @@ import (
"golang.org/x/sys/windows"
"golang.org/x/sys/windows/svc"
"golang.zx2c4.com/wireguard/windows/conf"
"golang.zx2c4.com/wireguard/windows/updater"
"github.com/amnezia-vpn/amneziawg-windows-client/updater"
"github.com/amnezia-vpn/awg-windows/conf"
"github.com/amnezia-vpn/awg-windows/services"
)
var (
@@ -48,7 +49,9 @@ func (s *ManagerService) StoredConfig(tunnelName string) (*conf.Config, error) {
}
func (s *ManagerService) RuntimeConfig(tunnelName string) (*conf.Config, error) {
storedConfig, err := conf.LoadFromName(tunnelName)
log.Printf("[%s] RuntimeConfig", tunnelName)
return nil, nil
/*storedConfig, err := conf.LoadFromName(tunnelName)
if err != nil {
return nil, err
}
@@ -67,7 +70,7 @@ func (s *ManagerService) RuntimeConfig(tunnelName string) (*conf.Config, error)
if s.elevatedToken == 0 {
conf.Redact()
}
return conf, nil
return conf, nil*/
}
func (s *ManagerService) Start(tunnelName string) error {
@@ -81,11 +84,11 @@ func (s *ManagerService) Start(tunnelName string) error {
tt := make([]string, 0, len(trackedTunnels))
var inTransition string
for t, state := range trackedTunnels {
c2, err := conf.LoadFromName(t)
/*c2, err := conf.LoadFromName(t)
if err != nil || !c.IntersectsWith(c2) {
// If we can't get the config, assume it doesn't intersect.
continue
}
}*/
tt = append(tt, t)
if len(t) > 0 && (state == TunnelStarting || state == TunnelUnknown) {
inTransition = t
@@ -131,7 +134,7 @@ func (s *ManagerService) Stop(tunnelName string) error {
}
func (s *ManagerService) WaitForStop(tunnelName string) error {
serviceName, err := conf.ServiceNameOfTunnel(tunnelName)
serviceName, err := services.ServiceNameOfTunnel(tunnelName)
if err != nil {
return err
}
@@ -162,7 +165,7 @@ func (s *ManagerService) Delete(tunnelName string) error {
}
func (s *ManagerService) State(tunnelName string) (TunnelState, error) {
serviceName, err := conf.ServiceNameOfTunnel(tunnelName)
serviceName, err := services.ServiceNameOfTunnel(tunnelName)
if err != nil {
return 0, err
}

View File

@@ -9,6 +9,7 @@ import (
"errors"
"log"
"os"
"path/filepath"
"runtime"
"strconv"
"sync"
@@ -19,10 +20,10 @@ import (
"golang.org/x/sys/windows/svc"
"golang.zx2c4.com/wireguard/windows/driver"
"golang.zx2c4.com/wireguard/windows/conf"
"golang.zx2c4.com/wireguard/windows/elevate"
"golang.zx2c4.com/wireguard/windows/ringlogger"
"golang.zx2c4.com/wireguard/windows/services"
"github.com/amnezia-vpn/amneziawg-windows-client/elevate"
"github.com/amnezia-vpn/amneziawg-windows-client/ringlogger"
"github.com/amnezia-vpn/amneziawg-windows-client/services"
"github.com/amnezia-vpn/awg-windows/conf"
)
type managerService struct{}
@@ -43,7 +44,7 @@ func (service *managerService) Execute(args []string, r <-chan svc.ChangeRequest
}()
var logFile string
logFile, err = conf.LogFile(true)
logFile, err = LogFile(true)
if err != nil {
serviceError = services.ErrorRingloggerOpen
return
@@ -353,3 +354,11 @@ loop:
func Run() error {
return svc.Run("WireGuardManager", &managerService{})
}
func LogFile(createRoot bool) (string, error) {
root, err := conf.RootDirectory(createRoot)
if err != nil {
return "", err
}
return filepath.Join(root, "log.bin"), nil
}

View File

@@ -20,8 +20,8 @@ import (
"golang.org/x/sys/windows/svc"
"golang.org/x/sys/windows/svc/mgr"
"golang.zx2c4.com/wireguard/windows/conf"
"golang.zx2c4.com/wireguard/windows/services"
"github.com/amnezia-vpn/awg-windows/conf"
"github.com/amnezia-vpn/awg-windows/services"
)
var (
@@ -280,7 +280,7 @@ func trackExistingTunnels() error {
continue
}
trackedTunnelsLock.Unlock()
serviceName, err := conf.ServiceNameOfTunnel(name)
serviceName, err := services.ServiceNameOfTunnel(name)
if err != nil {
continue
}

View File

@@ -10,9 +10,9 @@ import (
"time"
_ "unsafe"
"golang.zx2c4.com/wireguard/windows/services"
"golang.zx2c4.com/wireguard/windows/updater"
"golang.zx2c4.com/wireguard/windows/version"
"github.com/amnezia-vpn/amneziawg-windows-client/services"
"github.com/amnezia-vpn/amneziawg-windows-client/updater"
"github.com/amnezia-vpn/amneziawg-windows-client/version"
)
//go:linkname fastrandn runtime.fastrandn

View File

@@ -14,7 +14,6 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST manifest.xml
7 ICON ui/icon/wireguard.ico
8 ICON ui/icon/dot.ico
wireguard.dll RCDATA wireguard.dll
#define VERSIONINFO_TEMPLATE(block_id, lang_id, codepage_id, file_desc, comments) \
VS_VERSION_INFO VERSIONINFO \

View File

@@ -1,158 +0,0 @@
/* SPDX-License-Identifier: MIT
*
* Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package tunnel
import (
"fmt"
"log"
"net/netip"
"time"
"golang.org/x/sys/windows"
"golang.zx2c4.com/wireguard/windows/conf"
"golang.zx2c4.com/wireguard/windows/services"
"golang.zx2c4.com/wireguard/windows/tunnel/firewall"
"golang.zx2c4.com/wireguard/windows/tunnel/winipcfg"
)
func cleanupAddressesOnDisconnectedInterfaces(family winipcfg.AddressFamily, addresses []netip.Prefix) {
if len(addresses) == 0 {
return
}
addrHash := make(map[netip.Addr]bool, len(addresses))
for i := range addresses {
addrHash[addresses[i].Addr()] = true
}
interfaces, err := winipcfg.GetAdaptersAddresses(family, winipcfg.GAAFlagDefault)
if err != nil {
return
}
for _, iface := range interfaces {
if iface.OperStatus == winipcfg.IfOperStatusUp {
continue
}
for address := iface.FirstUnicastAddress; address != nil; address = address.Next {
if ip, _ := netip.AddrFromSlice(address.Address.IP()); addrHash[ip] {
prefix := netip.PrefixFrom(ip, int(address.OnLinkPrefixLength))
log.Printf("Cleaning up stale address %s from interface %s", prefix.String(), iface.FriendlyName())
iface.LUID.DeleteIPAddress(prefix)
}
}
}
}
func configureInterface(family winipcfg.AddressFamily, conf *conf.Config, luid winipcfg.LUID) error {
retryOnFailure := services.StartedAtBoot()
tryTimes := 0
startOver:
var err error
if tryTimes > 0 {
log.Printf("Retrying interface configuration after failure because system just booted (T+%v): %v", windows.DurationSinceBoot(), err)
time.Sleep(time.Second)
retryOnFailure = retryOnFailure && tryTimes < 15
}
tryTimes++
estimatedRouteCount := 0
for _, peer := range conf.Peers {
estimatedRouteCount += len(peer.AllowedIPs)
}
routes := make(map[winipcfg.RouteData]bool, estimatedRouteCount)
foundDefault4 := false
foundDefault6 := false
for _, peer := range conf.Peers {
for _, allowedip := range peer.AllowedIPs {
route := winipcfg.RouteData{
Destination: allowedip.Masked(),
Metric: 0,
}
if allowedip.Addr().Is4() {
if allowedip.Bits() == 0 {
foundDefault4 = true
}
route.NextHop = netip.IPv4Unspecified()
} else if allowedip.Addr().Is6() {
if allowedip.Bits() == 0 {
foundDefault6 = true
}
route.NextHop = netip.IPv6Unspecified()
}
routes[route] = true
}
}
deduplicatedRoutes := make([]*winipcfg.RouteData, 0, len(routes))
for route := range routes {
r := route
deduplicatedRoutes = append(deduplicatedRoutes, &r)
}
if !conf.Interface.TableOff {
err = luid.SetRoutesForFamily(family, deduplicatedRoutes)
if err == windows.ERROR_NOT_FOUND && retryOnFailure {
goto startOver
} else if err != nil {
return fmt.Errorf("unable to set routes: %w", err)
}
}
err = luid.SetIPAddressesForFamily(family, conf.Interface.Addresses)
if err == windows.ERROR_OBJECT_ALREADY_EXISTS {
cleanupAddressesOnDisconnectedInterfaces(family, conf.Interface.Addresses)
err = luid.SetIPAddressesForFamily(family, conf.Interface.Addresses)
}
if err == windows.ERROR_NOT_FOUND && retryOnFailure {
goto startOver
} else if err != nil {
return fmt.Errorf("unable to set ips: %w", err)
}
var ipif *winipcfg.MibIPInterfaceRow
ipif, err = luid.IPInterface(family)
if err != nil {
return err
}
ipif.RouterDiscoveryBehavior = winipcfg.RouterDiscoveryDisabled
ipif.DadTransmits = 0
ipif.ManagedAddressConfigurationSupported = false
ipif.OtherStatefulConfigurationSupported = false
if conf.Interface.MTU > 0 {
ipif.NLMTU = uint32(conf.Interface.MTU)
}
if (family == windows.AF_INET && foundDefault4) || (family == windows.AF_INET6 && foundDefault6) {
ipif.UseAutomaticMetric = false
ipif.Metric = 0
}
err = ipif.Set()
if err == windows.ERROR_NOT_FOUND && retryOnFailure {
goto startOver
} else if err != nil {
return fmt.Errorf("unable to set metric and MTU: %w", err)
}
err = luid.SetDNS(family, conf.Interface.DNS, conf.Interface.DNSSearch)
if err == windows.ERROR_NOT_FOUND && retryOnFailure {
goto startOver
} else if err != nil {
return fmt.Errorf("unable to set DNS: %w", err)
}
return nil
}
func enableFirewall(conf *conf.Config, luid winipcfg.LUID) error {
doNotRestrict := true
if len(conf.Peers) == 1 && !conf.Interface.TableOff {
for _, allowedip := range conf.Peers[0].AllowedIPs {
if allowedip.Bits() == 0 && allowedip == allowedip.Masked() {
doNotRestrict = false
break
}
}
}
log.Println("Enabling firewall rules")
return firewall.EnableFirewall(uint64(luid), doNotRestrict, conf.Interface.DNS)
}

View File

@@ -1,99 +0,0 @@
/* SPDX-License-Identifier: MIT
*
* Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package tunnel
import (
"bytes"
"encoding/binary"
"sort"
"unsafe"
"golang.org/x/crypto/blake2s"
"golang.org/x/sys/windows"
"golang.org/x/text/unicode/norm"
"golang.zx2c4.com/wireguard/windows/conf"
)
const (
deterministicGUIDLabel = "Deterministic WireGuard Windows GUID v1 jason@zx2c4.com"
fixedGUIDLabel = "Fixed WireGuard Windows GUID v1 jason@zx2c4.com"
)
// Escape hatch for external consumers, not us.
var UseFixedGUIDInsteadOfDeterministic = false
/* All peer public keys and allowed ips are sorted. Length/number fields are
* little endian 32-bit. Hash input is:
*
* label || len(interface name) || interface name ||
* interface public key || number of peers ||
* peer public key || number of peer allowed ips ||
* len(allowed ip string) || allowed ip/cidr in canonical string notation ||
* len(allowed ip string) || allowed ip/cidr in canonical string notation ||
* len(allowed ip string) || allowed ip/cidr in canonical string notation ||
* ...
* peer public key || number of peer allowed ips ||
* len(allowed ip string) || allowed ip/cidr in canonical string notation ||
* len(allowed ip string) || allowed ip/cidr in canonical string notation ||
* len(allowed ip string) || allowed ip/cidr in canonical string notation ||
* ...
* ...
*/
func deterministicGUID(c *conf.Config) *windows.GUID {
b2, _ := blake2s.New256(nil)
if !UseFixedGUIDInsteadOfDeterministic {
b2.Write([]byte(deterministicGUIDLabel))
} else {
b2.Write([]byte(fixedGUIDLabel))
}
b2Number := func(i int) {
if uint(i) > uint(^uint32(0)) {
panic("length out of bounds")
}
var bytes [4]byte
binary.LittleEndian.PutUint32(bytes[:], uint32(i))
b2.Write(bytes[:])
}
b2String := func(s string) {
bytes := []byte(s)
bytes = norm.NFC.Bytes(bytes)
b2Number(len(bytes))
b2.Write(bytes)
}
b2Key := func(k *conf.Key) {
b2.Write(k[:])
}
b2String(c.Name)
if !UseFixedGUIDInsteadOfDeterministic {
b2Key(c.Interface.PrivateKey.Public())
b2Number(len(c.Peers))
sortedPeers := c.Peers
sort.Slice(sortedPeers, func(i, j int) bool {
return bytes.Compare(sortedPeers[i].PublicKey[:], sortedPeers[j].PublicKey[:]) < 0
})
for _, peer := range sortedPeers {
b2Key(&peer.PublicKey)
b2Number(len(peer.AllowedIPs))
sortedAllowedIPs := peer.AllowedIPs
sort.Slice(sortedAllowedIPs, func(i, j int) bool {
if bi, bj := sortedAllowedIPs[i].Addr().BitLen(), sortedAllowedIPs[j].Addr().BitLen(); bi != bj {
return bi < bj
}
if sortedAllowedIPs[i].Bits() != sortedAllowedIPs[j].Bits() {
return sortedAllowedIPs[i].Bits() < sortedAllowedIPs[j].Bits()
}
return sortedAllowedIPs[i].Addr().Compare(sortedAllowedIPs[j].Addr()) < 0
})
for _, allowedip := range sortedAllowedIPs {
b2String(allowedip.String())
}
}
}
return (*windows.GUID)(unsafe.Pointer(&b2.Sum(nil)[0]))
}

View File

@@ -1,190 +0,0 @@
/* SPDX-License-Identifier: MIT
*
* Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package firewall
import (
"errors"
"net/netip"
"unsafe"
"golang.org/x/sys/windows"
)
type wfpObjectInstaller func(uintptr) error
//
// Fundamental WireGuard specific WFP objects.
//
type baseObjects struct {
provider windows.GUID
filters windows.GUID
}
var wfpSession uintptr
func createWfpSession() (uintptr, error) {
sessionDisplayData, err := createWtFwpmDisplayData0("WireGuard", "WireGuard dynamic session")
if err != nil {
return 0, wrapErr(err)
}
session := wtFwpmSession0{
displayData: *sessionDisplayData,
flags: cFWPM_SESSION_FLAG_DYNAMIC,
txnWaitTimeoutInMSec: windows.INFINITE,
}
sessionHandle := uintptr(0)
err = fwpmEngineOpen0(nil, cRPC_C_AUTHN_WINNT, nil, &session, unsafe.Pointer(&sessionHandle))
if err != nil {
return 0, wrapErr(err)
}
return sessionHandle, nil
}
func registerBaseObjects(session uintptr) (*baseObjects, error) {
bo := &baseObjects{}
var err error
bo.provider, err = windows.GenerateGUID()
if err != nil {
return nil, wrapErr(err)
}
bo.filters, err = windows.GenerateGUID()
if err != nil {
return nil, wrapErr(err)
}
//
// Register provider.
//
{
displayData, err := createWtFwpmDisplayData0("WireGuard", "WireGuard provider")
if err != nil {
return nil, wrapErr(err)
}
provider := wtFwpmProvider0{
providerKey: bo.provider,
displayData: *displayData,
}
err = fwpmProviderAdd0(session, &provider, 0)
if err != nil {
// TODO: cleanup entire call chain of these if failure?
return nil, wrapErr(err)
}
}
//
// Register filters sublayer.
//
{
displayData, err := createWtFwpmDisplayData0("WireGuard filters", "Permissive and blocking filters")
if err != nil {
return nil, wrapErr(err)
}
sublayer := wtFwpmSublayer0{
subLayerKey: bo.filters,
displayData: *displayData,
providerKey: &bo.provider,
weight: ^uint16(0),
}
err = fwpmSubLayerAdd0(session, &sublayer, 0)
if err != nil {
return nil, wrapErr(err)
}
}
return bo, nil
}
func EnableFirewall(luid uint64, doNotRestrict bool, restrictToDNSServers []netip.Addr) error {
if wfpSession != 0 {
return errors.New("The firewall has already been enabled")
}
session, err := createWfpSession()
if err != nil {
return wrapErr(err)
}
objectInstaller := func(session uintptr) error {
baseObjects, err := registerBaseObjects(session)
if err != nil {
return wrapErr(err)
}
err = permitWireGuardService(session, baseObjects, 15)
if err != nil {
return wrapErr(err)
}
if !doNotRestrict {
if len(restrictToDNSServers) > 0 {
err = blockDNS(restrictToDNSServers, session, baseObjects, 15, 14)
if err != nil {
return wrapErr(err)
}
}
err = permitLoopback(session, baseObjects, 13)
if err != nil {
return wrapErr(err)
}
err = permitTunInterface(session, baseObjects, 12, luid)
if err != nil {
return wrapErr(err)
}
err = permitDHCPIPv4(session, baseObjects, 12)
if err != nil {
return wrapErr(err)
}
err = permitDHCPIPv6(session, baseObjects, 12)
if err != nil {
return wrapErr(err)
}
err = permitNdp(session, baseObjects, 12)
if err != nil {
return wrapErr(err)
}
/* TODO: actually evaluate if this does anything and if we need this. It's layer 2; our other rules are layer 3.
* In other words, if somebody complains, try enabling it. For now, keep it off.
err = permitHyperV(session, baseObjects, 12)
if err != nil {
return wrapErr(err)
}
*/
err = blockAll(session, baseObjects, 0)
if err != nil {
return wrapErr(err)
}
}
return nil
}
err = runTransaction(session, objectInstaller)
if err != nil {
fwpmEngineClose0(session)
return wrapErr(err)
}
wfpSession = session
return nil
}
func DisableFirewall() {
if wfpSession != 0 {
fwpmEngineClose0(wfpSession)
wfpSession = 0
}
}

View File

@@ -1,148 +0,0 @@
/* SPDX-License-Identifier: MIT
*
* Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package firewall
import (
"fmt"
"os"
"runtime"
"syscall"
"unsafe"
"golang.org/x/sys/windows"
)
func runTransaction(session uintptr, operation wfpObjectInstaller) error {
err := fwpmTransactionBegin0(session, 0)
if err != nil {
return wrapErr(err)
}
err = operation(session)
if err != nil {
fwpmTransactionAbort0(session)
return wrapErr(err)
}
err = fwpmTransactionCommit0(session)
if err != nil {
fwpmTransactionAbort0(session)
return wrapErr(err)
}
return nil
}
func createWtFwpmDisplayData0(name, description string) (*wtFwpmDisplayData0, error) {
namePtr, err := windows.UTF16PtrFromString(name)
if err != nil {
return nil, wrapErr(err)
}
descriptionPtr, err := windows.UTF16PtrFromString(description)
if err != nil {
return nil, wrapErr(err)
}
return &wtFwpmDisplayData0{
name: namePtr,
description: descriptionPtr,
}, nil
}
func filterWeight(weight uint8) wtFwpValue0 {
return wtFwpValue0{
_type: cFWP_UINT8,
value: uintptr(weight),
}
}
func wrapErr(err error) error {
if _, ok := err.(syscall.Errno); !ok {
return err
}
_, file, line, ok := runtime.Caller(1)
if !ok {
return fmt.Errorf("Firewall error at unknown location: %w", err)
}
return fmt.Errorf("Firewall error at %s:%d: %w", file, line, err)
}
func getCurrentProcessSecurityDescriptor() (*windows.SECURITY_DESCRIPTOR, error) {
var processToken windows.Token
err := windows.OpenProcessToken(windows.CurrentProcess(), windows.TOKEN_QUERY, &processToken)
if err != nil {
return nil, wrapErr(err)
}
defer processToken.Close()
gs, err := processToken.GetTokenGroups()
if err != nil {
return nil, wrapErr(err)
}
var sid *windows.SID
for _, g := range gs.AllGroups() {
if g.Attributes != windows.SE_GROUP_ENABLED|windows.SE_GROUP_ENABLED_BY_DEFAULT|windows.SE_GROUP_OWNER {
continue
}
// We could be checking != 6, but hopefully Microsoft will update
// RtlCreateServiceSid to use SHA2, which will then likely bump
// this up. So instead just roll with a minimum.
if !g.Sid.IsValid() || g.Sid.IdentifierAuthority() != windows.SECURITY_NT_AUTHORITY || g.Sid.SubAuthorityCount() < 6 || g.Sid.SubAuthority(0) != 80 {
continue
}
sid = g.Sid
break
}
if sid == nil {
return nil, wrapErr(windows.ERROR_NO_SUCH_GROUP)
}
access := []windows.EXPLICIT_ACCESS{{
AccessPermissions: cFWP_ACTRL_MATCH_FILTER,
AccessMode: windows.GRANT_ACCESS,
Trustee: windows.TRUSTEE{
TrusteeForm: windows.TRUSTEE_IS_SID,
TrusteeType: windows.TRUSTEE_IS_GROUP,
TrusteeValue: windows.TrusteeValueFromSID(sid),
},
}}
dacl, err := windows.ACLFromEntries(access, nil)
if err != nil {
return nil, wrapErr(err)
}
sd, err := windows.NewSecurityDescriptor()
if err != nil {
return nil, wrapErr(err)
}
err = sd.SetDACL(dacl, true, false)
if err != nil {
return nil, wrapErr(err)
}
sd, err = sd.ToSelfRelative()
if err != nil {
return nil, wrapErr(err)
}
return sd, nil
}
func getCurrentProcessAppID() (*wtFwpByteBlob, error) {
currentFile, err := os.Executable()
if err != nil {
return nil, wrapErr(err)
}
curFilePtr, err := windows.UTF16PtrFromString(currentFile)
if err != nil {
return nil, wrapErr(err)
}
var appID *wtFwpByteBlob
err = fwpmGetAppIdFromFileName0(curFilePtr, unsafe.Pointer(&appID))
if err != nil {
return nil, wrapErr(err)
}
return appID, nil
}

View File

@@ -1,8 +0,0 @@
/* SPDX-License-Identifier: MIT
*
* Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package firewall
//go:generate go run golang.org/x/sys/windows/mkwinsyscall -output zsyscall_windows.go syscall_windows.go

File diff suppressed because it is too large Load Diff

View File

@@ -1,36 +0,0 @@
/* SPDX-License-Identifier: MIT
*
* Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package firewall
// https://docs.microsoft.com/en-us/windows/desktop/api/fwpmu/nf-fwpmu-fwpmengineopen0
//sys fwpmEngineOpen0(serverName *uint16, authnService wtRpcCAuthN, authIdentity *uintptr, session *wtFwpmSession0, engineHandle unsafe.Pointer) (err error) [failretval!=0] = fwpuclnt.FwpmEngineOpen0
// https://docs.microsoft.com/en-us/windows/desktop/api/fwpmu/nf-fwpmu-fwpmengineclose0
//sys fwpmEngineClose0(engineHandle uintptr) (err error) [failretval!=0] = fwpuclnt.FwpmEngineClose0
// https://docs.microsoft.com/en-us/windows/desktop/api/fwpmu/nf-fwpmu-fwpmsublayeradd0
//sys fwpmSubLayerAdd0(engineHandle uintptr, subLayer *wtFwpmSublayer0, sd uintptr) (err error) [failretval!=0] = fwpuclnt.FwpmSubLayerAdd0
// https://docs.microsoft.com/en-us/windows/desktop/api/fwpmu/nf-fwpmu-fwpmgetappidfromfilename0
//sys fwpmGetAppIdFromFileName0(fileName *uint16, appID unsafe.Pointer) (err error) [failretval!=0] = fwpuclnt.FwpmGetAppIdFromFileName0
// https://docs.microsoft.com/en-us/windows/desktop/api/fwpmu/nf-fwpmu-fwpmfreememory0
//sys fwpmFreeMemory0(p unsafe.Pointer) = fwpuclnt.FwpmFreeMemory0
// https://docs.microsoft.com/en-us/windows/desktop/api/fwpmu/nf-fwpmu-fwpmfilteradd0
//sys fwpmFilterAdd0(engineHandle uintptr, filter *wtFwpmFilter0, sd uintptr, id *uint64) (err error) [failretval!=0] = fwpuclnt.FwpmFilterAdd0
// https://docs.microsoft.com/en-us/windows/desktop/api/Fwpmu/nf-fwpmu-fwpmtransactionbegin0
//sys fwpmTransactionBegin0(engineHandle uintptr, flags uint32) (err error) [failretval!=0] = fwpuclnt.FwpmTransactionBegin0
// https://docs.microsoft.com/en-us/windows/desktop/api/fwpmu/nf-fwpmu-fwpmtransactioncommit0
//sys fwpmTransactionCommit0(engineHandle uintptr) (err error) [failretval!=0] = fwpuclnt.FwpmTransactionCommit0
// https://docs.microsoft.com/en-us/windows/desktop/api/fwpmu/nf-fwpmu-fwpmtransactionabort0
//sys fwpmTransactionAbort0(engineHandle uintptr) (err error) [failretval!=0] = fwpuclnt.FwpmTransactionAbort0
// https://docs.microsoft.com/en-us/windows/desktop/api/fwpmu/nf-fwpmu-fwpmprovideradd0
//sys fwpmProviderAdd0(engineHandle uintptr, provider *wtFwpmProvider0, sd uintptr) (err error) [failretval!=0] = fwpuclnt.FwpmProviderAdd0

View File

@@ -1,412 +0,0 @@
/* SPDX-License-Identifier: MIT
*
* Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package firewall
import "golang.org/x/sys/windows"
const (
anysizeArray = 1 // ANYSIZE_ARRAY defined in winnt.h
wtFwpBitmapArray64_Size = 8
wtFwpByteArray16_Size = 16
wtFwpByteArray6_Size = 6
wtFwpmAction0_Size = 20
wtFwpmAction0_filterType_Offset = 4
wtFwpV4AddrAndMask_Size = 8
wtFwpV4AddrAndMask_mask_Offset = 4
wtFwpV6AddrAndMask_Size = 17
wtFwpV6AddrAndMask_prefixLength_Offset = 16
)
type wtFwpActionFlag uint32
const (
cFWP_ACTION_FLAG_TERMINATING wtFwpActionFlag = 0x00001000
cFWP_ACTION_FLAG_NON_TERMINATING wtFwpActionFlag = 0x00002000
cFWP_ACTION_FLAG_CALLOUT wtFwpActionFlag = 0x00004000
)
// FWP_ACTION_TYPE defined in fwptypes.h
type wtFwpActionType uint32
const (
cFWP_ACTION_BLOCK wtFwpActionType = wtFwpActionType(0x00000001 | cFWP_ACTION_FLAG_TERMINATING)
cFWP_ACTION_PERMIT wtFwpActionType = wtFwpActionType(0x00000002 | cFWP_ACTION_FLAG_TERMINATING)
cFWP_ACTION_CALLOUT_TERMINATING wtFwpActionType = wtFwpActionType(0x00000003 | cFWP_ACTION_FLAG_CALLOUT | cFWP_ACTION_FLAG_TERMINATING)
cFWP_ACTION_CALLOUT_INSPECTION wtFwpActionType = wtFwpActionType(0x00000004 | cFWP_ACTION_FLAG_CALLOUT | cFWP_ACTION_FLAG_NON_TERMINATING)
cFWP_ACTION_CALLOUT_UNKNOWN wtFwpActionType = wtFwpActionType(0x00000005 | cFWP_ACTION_FLAG_CALLOUT)
cFWP_ACTION_CONTINUE wtFwpActionType = wtFwpActionType(0x00000006 | cFWP_ACTION_FLAG_NON_TERMINATING)
cFWP_ACTION_NONE wtFwpActionType = 0x00000007
cFWP_ACTION_NONE_NO_MATCH wtFwpActionType = 0x00000008
cFWP_ACTION_BITMAP_INDEX_SET wtFwpActionType = 0x00000009
)
// FWP_BYTE_BLOB defined in fwptypes.h
// (https://docs.microsoft.com/en-us/windows/desktop/api/fwptypes/ns-fwptypes-fwp_byte_blob_)
type wtFwpByteBlob struct {
size uint32
data *uint8
}
// FWP_MATCH_TYPE defined in fwptypes.h
// (https://docs.microsoft.com/en-us/windows/desktop/api/fwptypes/ne-fwptypes-fwp_match_type_)
type wtFwpMatchType uint32
const (
cFWP_MATCH_EQUAL wtFwpMatchType = 0
cFWP_MATCH_GREATER wtFwpMatchType = cFWP_MATCH_EQUAL + 1
cFWP_MATCH_LESS wtFwpMatchType = cFWP_MATCH_GREATER + 1
cFWP_MATCH_GREATER_OR_EQUAL wtFwpMatchType = cFWP_MATCH_LESS + 1
cFWP_MATCH_LESS_OR_EQUAL wtFwpMatchType = cFWP_MATCH_GREATER_OR_EQUAL + 1
cFWP_MATCH_RANGE wtFwpMatchType = cFWP_MATCH_LESS_OR_EQUAL + 1
cFWP_MATCH_FLAGS_ALL_SET wtFwpMatchType = cFWP_MATCH_RANGE + 1
cFWP_MATCH_FLAGS_ANY_SET wtFwpMatchType = cFWP_MATCH_FLAGS_ALL_SET + 1
cFWP_MATCH_FLAGS_NONE_SET wtFwpMatchType = cFWP_MATCH_FLAGS_ANY_SET + 1
cFWP_MATCH_EQUAL_CASE_INSENSITIVE wtFwpMatchType = cFWP_MATCH_FLAGS_NONE_SET + 1
cFWP_MATCH_NOT_EQUAL wtFwpMatchType = cFWP_MATCH_EQUAL_CASE_INSENSITIVE + 1
cFWP_MATCH_PREFIX wtFwpMatchType = cFWP_MATCH_NOT_EQUAL + 1
cFWP_MATCH_NOT_PREFIX wtFwpMatchType = cFWP_MATCH_PREFIX + 1
cFWP_MATCH_TYPE_MAX wtFwpMatchType = cFWP_MATCH_NOT_PREFIX + 1
)
// FWPM_ACTION0 defined in fwpmtypes.h
// (https://docs.microsoft.com/en-us/windows/desktop/api/fwpmtypes/ns-fwpmtypes-fwpm_action0_)
type wtFwpmAction0 struct {
_type wtFwpActionType
filterType windows.GUID // Windows type: GUID
}
// Defined in fwpmu.h. 4cd62a49-59c3-4969-b7f3-bda5d32890a4
var cFWPM_CONDITION_IP_LOCAL_INTERFACE = windows.GUID{
Data1: 0x4cd62a49,
Data2: 0x59c3,
Data3: 0x4969,
Data4: [8]byte{0xb7, 0xf3, 0xbd, 0xa5, 0xd3, 0x28, 0x90, 0xa4},
}
// Defined in fwpmu.h. b235ae9a-1d64-49b8-a44c-5ff3d9095045
var cFWPM_CONDITION_IP_REMOTE_ADDRESS = windows.GUID{
Data1: 0xb235ae9a,
Data2: 0x1d64,
Data3: 0x49b8,
Data4: [8]byte{0xa4, 0x4c, 0x5f, 0xf3, 0xd9, 0x09, 0x50, 0x45},
}
// Defined in fwpmu.h. 3971ef2b-623e-4f9a-8cb1-6e79b806b9a7
var cFWPM_CONDITION_IP_PROTOCOL = windows.GUID{
Data1: 0x3971ef2b,
Data2: 0x623e,
Data3: 0x4f9a,
Data4: [8]byte{0x8c, 0xb1, 0x6e, 0x79, 0xb8, 0x06, 0xb9, 0xa7},
}
// Defined in fwpmu.h. 0c1ba1af-5765-453f-af22-a8f791ac775b
var cFWPM_CONDITION_IP_LOCAL_PORT = windows.GUID{
Data1: 0x0c1ba1af,
Data2: 0x5765,
Data3: 0x453f,
Data4: [8]byte{0xaf, 0x22, 0xa8, 0xf7, 0x91, 0xac, 0x77, 0x5b},
}
// Defined in fwpmu.h. c35a604d-d22b-4e1a-91b4-68f674ee674b
var cFWPM_CONDITION_IP_REMOTE_PORT = windows.GUID{
Data1: 0xc35a604d,
Data2: 0xd22b,
Data3: 0x4e1a,
Data4: [8]byte{0x91, 0xb4, 0x68, 0xf6, 0x74, 0xee, 0x67, 0x4b},
}
// Defined in fwpmu.h. d78e1e87-8644-4ea5-9437-d809ecefc971
var cFWPM_CONDITION_ALE_APP_ID = windows.GUID{
Data1: 0xd78e1e87,
Data2: 0x8644,
Data3: 0x4ea5,
Data4: [8]byte{0x94, 0x37, 0xd8, 0x09, 0xec, 0xef, 0xc9, 0x71},
}
// af043a0a-b34d-4f86-979c-c90371af6e66
var cFWPM_CONDITION_ALE_USER_ID = windows.GUID{
Data1: 0xaf043a0a,
Data2: 0xb34d,
Data3: 0x4f86,
Data4: [8]byte{0x97, 0x9c, 0xc9, 0x03, 0x71, 0xaf, 0x6e, 0x66},
}
// d9ee00de-c1ef-4617-bfe3-ffd8f5a08957
var cFWPM_CONDITION_IP_LOCAL_ADDRESS = windows.GUID{
Data1: 0xd9ee00de,
Data2: 0xc1ef,
Data3: 0x4617,
Data4: [8]byte{0xbf, 0xe3, 0xff, 0xd8, 0xf5, 0xa0, 0x89, 0x57},
}
var (
cFWPM_CONDITION_ICMP_TYPE = cFWPM_CONDITION_IP_LOCAL_PORT
cFWPM_CONDITION_ICMP_CODE = cFWPM_CONDITION_IP_REMOTE_PORT
)
// 7bc43cbf-37ba-45f1-b74a-82ff518eeb10
var cFWPM_CONDITION_L2_FLAGS = windows.GUID{
Data1: 0x7bc43cbf,
Data2: 0x37ba,
Data3: 0x45f1,
Data4: [8]byte{0xb7, 0x4a, 0x82, 0xff, 0x51, 0x8e, 0xeb, 0x10},
}
type wtFwpmL2Flags uint32
const cFWP_CONDITION_L2_IS_VM2VM wtFwpmL2Flags = 0x00000010
var cFWPM_CONDITION_FLAGS = windows.GUID{
Data1: 0x632ce23b,
Data2: 0x5167,
Data3: 0x435c,
Data4: [8]byte{0x86, 0xd7, 0xe9, 0x03, 0x68, 0x4a, 0xa8, 0x0c},
}
type wtFwpmFlags uint32
const cFWP_CONDITION_FLAG_IS_LOOPBACK wtFwpmFlags = 0x00000001
// Defined in fwpmtypes.h
type wtFwpmFilterFlags uint32
const (
cFWPM_FILTER_FLAG_NONE wtFwpmFilterFlags = 0x00000000
cFWPM_FILTER_FLAG_PERSISTENT wtFwpmFilterFlags = 0x00000001
cFWPM_FILTER_FLAG_BOOTTIME wtFwpmFilterFlags = 0x00000002
cFWPM_FILTER_FLAG_HAS_PROVIDER_CONTEXT wtFwpmFilterFlags = 0x00000004
cFWPM_FILTER_FLAG_CLEAR_ACTION_RIGHT wtFwpmFilterFlags = 0x00000008
cFWPM_FILTER_FLAG_PERMIT_IF_CALLOUT_UNREGISTERED wtFwpmFilterFlags = 0x00000010
cFWPM_FILTER_FLAG_DISABLED wtFwpmFilterFlags = 0x00000020
cFWPM_FILTER_FLAG_INDEXED wtFwpmFilterFlags = 0x00000040
cFWPM_FILTER_FLAG_HAS_SECURITY_REALM_PROVIDER_CONTEXT wtFwpmFilterFlags = 0x00000080
cFWPM_FILTER_FLAG_SYSTEMOS_ONLY wtFwpmFilterFlags = 0x00000100
cFWPM_FILTER_FLAG_GAMEOS_ONLY wtFwpmFilterFlags = 0x00000200
cFWPM_FILTER_FLAG_SILENT_MODE wtFwpmFilterFlags = 0x00000400
cFWPM_FILTER_FLAG_IPSEC_NO_ACQUIRE_INITIATE wtFwpmFilterFlags = 0x00000800
)
// FWPM_LAYER_ALE_AUTH_CONNECT_V4 (c38d57d1-05a7-4c33-904f-7fbceee60e82) defined in fwpmu.h
var cFWPM_LAYER_ALE_AUTH_CONNECT_V4 = windows.GUID{
Data1: 0xc38d57d1,
Data2: 0x05a7,
Data3: 0x4c33,
Data4: [8]byte{0x90, 0x4f, 0x7f, 0xbc, 0xee, 0xe6, 0x0e, 0x82},
}
// e1cd9fe7-f4b5-4273-96c0-592e487b8650
var cFWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V4 = windows.GUID{
Data1: 0xe1cd9fe7,
Data2: 0xf4b5,
Data3: 0x4273,
Data4: [8]byte{0x96, 0xc0, 0x59, 0x2e, 0x48, 0x7b, 0x86, 0x50},
}
// FWPM_LAYER_ALE_AUTH_CONNECT_V6 (4a72393b-319f-44bc-84c3-ba54dcb3b6b4) defined in fwpmu.h
var cFWPM_LAYER_ALE_AUTH_CONNECT_V6 = windows.GUID{
Data1: 0x4a72393b,
Data2: 0x319f,
Data3: 0x44bc,
Data4: [8]byte{0x84, 0xc3, 0xba, 0x54, 0xdc, 0xb3, 0xb6, 0xb4},
}
// a3b42c97-9f04-4672-b87e-cee9c483257f
var cFWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V6 = windows.GUID{
Data1: 0xa3b42c97,
Data2: 0x9f04,
Data3: 0x4672,
Data4: [8]byte{0xb8, 0x7e, 0xce, 0xe9, 0xc4, 0x83, 0x25, 0x7f},
}
// 94c44912-9d6f-4ebf-b995-05ab8a088d1b
var cFWPM_LAYER_OUTBOUND_MAC_FRAME_NATIVE = windows.GUID{
Data1: 0x94c44912,
Data2: 0x9d6f,
Data3: 0x4ebf,
Data4: [8]byte{0xb9, 0x95, 0x05, 0xab, 0x8a, 0x08, 0x8d, 0x1b},
}
// d4220bd3-62ce-4f08-ae88-b56e8526df50
var cFWPM_LAYER_INBOUND_MAC_FRAME_NATIVE = windows.GUID{
Data1: 0xd4220bd3,
Data2: 0x62ce,
Data3: 0x4f08,
Data4: [8]byte{0xae, 0x88, 0xb5, 0x6e, 0x85, 0x26, 0xdf, 0x50},
}
// FWP_BITMAP_ARRAY64 defined in fwtypes.h
type wtFwpBitmapArray64 struct {
bitmapArray64 [8]uint8 // Windows type: [8]UINT8
}
// FWP_BYTE_ARRAY6 defined in fwtypes.h
// (https://docs.microsoft.com/en-us/windows/desktop/api/fwptypes/ns-fwptypes-fwp_byte_array6_)
type wtFwpByteArray6 struct {
byteArray6 [6]uint8 // Windows type: [6]UINT8
}
// FWP_BYTE_ARRAY16 defined in fwptypes.h
// (https://docs.microsoft.com/en-us/windows/desktop/api/fwptypes/ns-fwptypes-fwp_byte_array16_)
type wtFwpByteArray16 struct {
byteArray16 [16]uint8 // Windows type [16]UINT8
}
// FWP_CONDITION_VALUE0 defined in fwptypes.h
// (https://docs.microsoft.com/en-us/windows/desktop/api/fwptypes/ns-fwptypes-fwp_condition_value0).
type wtFwpConditionValue0 wtFwpValue0
// FWP_DATA_TYPE defined in fwptypes.h
// (https://docs.microsoft.com/en-us/windows/desktop/api/fwptypes/ne-fwptypes-fwp_data_type_)
type wtFwpDataType uint
const (
cFWP_EMPTY wtFwpDataType = 0
cFWP_UINT8 wtFwpDataType = cFWP_EMPTY + 1
cFWP_UINT16 wtFwpDataType = cFWP_UINT8 + 1
cFWP_UINT32 wtFwpDataType = cFWP_UINT16 + 1
cFWP_UINT64 wtFwpDataType = cFWP_UINT32 + 1
cFWP_INT8 wtFwpDataType = cFWP_UINT64 + 1
cFWP_INT16 wtFwpDataType = cFWP_INT8 + 1
cFWP_INT32 wtFwpDataType = cFWP_INT16 + 1
cFWP_INT64 wtFwpDataType = cFWP_INT32 + 1
cFWP_FLOAT wtFwpDataType = cFWP_INT64 + 1
cFWP_DOUBLE wtFwpDataType = cFWP_FLOAT + 1
cFWP_BYTE_ARRAY16_TYPE wtFwpDataType = cFWP_DOUBLE + 1
cFWP_BYTE_BLOB_TYPE wtFwpDataType = cFWP_BYTE_ARRAY16_TYPE + 1
cFWP_SID wtFwpDataType = cFWP_BYTE_BLOB_TYPE + 1
cFWP_SECURITY_DESCRIPTOR_TYPE wtFwpDataType = cFWP_SID + 1
cFWP_TOKEN_INFORMATION_TYPE wtFwpDataType = cFWP_SECURITY_DESCRIPTOR_TYPE + 1
cFWP_TOKEN_ACCESS_INFORMATION_TYPE wtFwpDataType = cFWP_TOKEN_INFORMATION_TYPE + 1
cFWP_UNICODE_STRING_TYPE wtFwpDataType = cFWP_TOKEN_ACCESS_INFORMATION_TYPE + 1
cFWP_BYTE_ARRAY6_TYPE wtFwpDataType = cFWP_UNICODE_STRING_TYPE + 1
cFWP_BITMAP_INDEX_TYPE wtFwpDataType = cFWP_BYTE_ARRAY6_TYPE + 1
cFWP_BITMAP_ARRAY64_TYPE wtFwpDataType = cFWP_BITMAP_INDEX_TYPE + 1
cFWP_SINGLE_DATA_TYPE_MAX wtFwpDataType = 0xff
cFWP_V4_ADDR_MASK wtFwpDataType = cFWP_SINGLE_DATA_TYPE_MAX + 1
cFWP_V6_ADDR_MASK wtFwpDataType = cFWP_V4_ADDR_MASK + 1
cFWP_RANGE_TYPE wtFwpDataType = cFWP_V6_ADDR_MASK + 1
cFWP_DATA_TYPE_MAX wtFwpDataType = cFWP_RANGE_TYPE + 1
)
// FWP_V4_ADDR_AND_MASK defined in fwptypes.h
// (https://docs.microsoft.com/en-us/windows/desktop/api/fwptypes/ns-fwptypes-fwp_v4_addr_and_mask).
type wtFwpV4AddrAndMask struct {
addr uint32
mask uint32
}
// FWP_V6_ADDR_AND_MASK defined in fwptypes.h
// (https://docs.microsoft.com/en-us/windows/desktop/api/fwptypes/ns-fwptypes-fwp_v6_addr_and_mask).
type wtFwpV6AddrAndMask struct {
addr [16]uint8
prefixLength uint8
}
// FWP_VALUE0 defined in fwptypes.h
// (https://docs.microsoft.com/en-us/windows/desktop/api/fwptypes/ns-fwptypes-fwp_value0_)
type wtFwpValue0 struct {
_type wtFwpDataType
value uintptr
}
// FWPM_DISPLAY_DATA0 defined in fwptypes.h
// (https://docs.microsoft.com/en-us/windows/desktop/api/fwptypes/ns-fwptypes-fwpm_display_data0).
type wtFwpmDisplayData0 struct {
name *uint16 // Windows type: *wchar_t
description *uint16 // Windows type: *wchar_t
}
// FWPM_FILTER_CONDITION0 defined in fwpmtypes.h
// (https://docs.microsoft.com/en-us/windows/desktop/api/fwpmtypes/ns-fwpmtypes-fwpm_filter_condition0).
type wtFwpmFilterCondition0 struct {
fieldKey windows.GUID // Windows type: GUID
matchType wtFwpMatchType
conditionValue wtFwpConditionValue0
}
// FWPM_PROVIDER0 defined in fwpmtypes.h
// (https://docs.microsoft.com/en-us/windows/desktop/api/fwpmtypes/ns-fwpmtypes-fwpm_provider0_)
type wtFwpProvider0 struct {
providerKey windows.GUID // Windows type: GUID
displayData wtFwpmDisplayData0
flags uint32
providerData wtFwpByteBlob
serviceName *uint16 // Windows type: *wchar_t
}
type wtFwpmSessionFlagsValue uint32
const (
cFWPM_SESSION_FLAG_DYNAMIC wtFwpmSessionFlagsValue = 0x00000001 // FWPM_SESSION_FLAG_DYNAMIC defined in fwpmtypes.h
)
// FWPM_SESSION0 defined in fwpmtypes.h
// (https://docs.microsoft.com/en-us/windows/desktop/api/fwpmtypes/ns-fwpmtypes-fwpm_session0).
type wtFwpmSession0 struct {
sessionKey windows.GUID // Windows type: GUID
displayData wtFwpmDisplayData0
flags wtFwpmSessionFlagsValue // Windows type UINT32
txnWaitTimeoutInMSec uint32
processId uint32 // Windows type: DWORD
sid *windows.SID
username *uint16 // Windows type: *wchar_t
kernelMode uint8 // Windows type: BOOL
}
type wtFwpmSublayerFlags uint32
const (
cFWPM_SUBLAYER_FLAG_PERSISTENT wtFwpmSublayerFlags = 0x00000001 // FWPM_SUBLAYER_FLAG_PERSISTENT defined in fwpmtypes.h
)
// FWPM_SUBLAYER0 defined in fwpmtypes.h
// (https://docs.microsoft.com/en-us/windows/desktop/api/fwpmtypes/ns-fwpmtypes-fwpm_sublayer0_)
type wtFwpmSublayer0 struct {
subLayerKey windows.GUID // Windows type: GUID
displayData wtFwpmDisplayData0
flags wtFwpmSublayerFlags
providerKey *windows.GUID // Windows type: *GUID
providerData wtFwpByteBlob
weight uint16
}
// Defined in rpcdce.h
type wtRpcCAuthN uint32
const (
cRPC_C_AUTHN_NONE wtRpcCAuthN = 0
cRPC_C_AUTHN_WINNT wtRpcCAuthN = 10
cRPC_C_AUTHN_DEFAULT wtRpcCAuthN = 0xFFFFFFFF
)
// FWPM_PROVIDER0 defined in fwpmtypes.h
// (https://docs.microsoft.com/sv-se/windows/desktop/api/fwpmtypes/ns-fwpmtypes-fwpm_provider0).
type wtFwpmProvider0 struct {
providerKey windows.GUID
displayData wtFwpmDisplayData0
flags uint32
providerData wtFwpByteBlob
serviceName *uint16
}
type wtIPProto uint32
const (
cIPPROTO_ICMP wtIPProto = 1
cIPPROTO_ICMPV6 wtIPProto = 58
cIPPROTO_TCP wtIPProto = 6
cIPPROTO_UDP wtIPProto = 17
)
const (
cFWP_ACTRL_MATCH_FILTER = 1
)

View File

@@ -1,90 +0,0 @@
//go:build 386 || arm
/* SPDX-License-Identifier: MIT
*
* Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package firewall
import "golang.org/x/sys/windows"
const (
wtFwpByteBlob_Size = 8
wtFwpByteBlob_data_Offset = 4
wtFwpConditionValue0_Size = 8
wtFwpConditionValue0_uint8_Offset = 4
wtFwpmDisplayData0_Size = 8
wtFwpmDisplayData0_description_Offset = 4
wtFwpmFilter0_Size = 152
wtFwpmFilter0_displayData_Offset = 16
wtFwpmFilter0_flags_Offset = 24
wtFwpmFilter0_providerKey_Offset = 28
wtFwpmFilter0_providerData_Offset = 32
wtFwpmFilter0_layerKey_Offset = 40
wtFwpmFilter0_subLayerKey_Offset = 56
wtFwpmFilter0_weight_Offset = 72
wtFwpmFilter0_numFilterConditions_Offset = 80
wtFwpmFilter0_filterCondition_Offset = 84
wtFwpmFilter0_action_Offset = 88
wtFwpmFilter0_providerContextKey_Offset = 112
wtFwpmFilter0_reserved_Offset = 128
wtFwpmFilter0_filterID_Offset = 136
wtFwpmFilter0_effectiveWeight_Offset = 144
wtFwpmFilterCondition0_Size = 28
wtFwpmFilterCondition0_matchType_Offset = 16
wtFwpmFilterCondition0_conditionValue_Offset = 20
wtFwpmSession0_Size = 48
wtFwpmSession0_displayData_Offset = 16
wtFwpmSession0_flags_Offset = 24
wtFwpmSession0_txnWaitTimeoutInMSec_Offset = 28
wtFwpmSession0_processId_Offset = 32
wtFwpmSession0_sid_Offset = 36
wtFwpmSession0_username_Offset = 40
wtFwpmSession0_kernelMode_Offset = 44
wtFwpmSublayer0_Size = 44
wtFwpmSublayer0_displayData_Offset = 16
wtFwpmSublayer0_flags_Offset = 24
wtFwpmSublayer0_providerKey_Offset = 28
wtFwpmSublayer0_providerData_Offset = 32
wtFwpmSublayer0_weight_Offset = 40
wtFwpProvider0_Size = 40
wtFwpProvider0_displayData_Offset = 16
wtFwpProvider0_flags_Offset = 24
wtFwpProvider0_providerData_Offset = 28
wtFwpProvider0_serviceName_Offset = 36
wtFwpTokenInformation_Size = 16
wtFwpValue0_Size = 8
wtFwpValue0_value_Offset = 4
)
// FWPM_FILTER0 defined in fwpmtypes.h
// (https://docs.microsoft.com/en-us/windows/desktop/api/fwpmtypes/ns-fwpmtypes-fwpm_filter0).
type wtFwpmFilter0 struct {
filterKey windows.GUID // Windows type: GUID
displayData wtFwpmDisplayData0
flags wtFwpmFilterFlags
providerKey *windows.GUID // Windows type: *GUID
providerData wtFwpByteBlob
layerKey windows.GUID // Windows type: GUID
subLayerKey windows.GUID // Windows type: GUID
weight wtFwpValue0
numFilterConditions uint32
filterCondition *wtFwpmFilterCondition0
action wtFwpmAction0
offset1 [4]byte // Layout correction field
providerContextKey windows.GUID // Windows type: GUID
reserved *windows.GUID // Windows type: *GUID
offset2 [4]byte // Layout correction field
filterID uint64
effectiveWeight wtFwpValue0
}

View File

@@ -1,87 +0,0 @@
//go:build amd64 || arm64
/* SPDX-License-Identifier: MIT
*
* Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package firewall
import "golang.org/x/sys/windows"
const (
wtFwpByteBlob_Size = 16
wtFwpByteBlob_data_Offset = 8
wtFwpConditionValue0_Size = 16
wtFwpConditionValue0_uint8_Offset = 8
wtFwpmDisplayData0_Size = 16
wtFwpmDisplayData0_description_Offset = 8
wtFwpmFilter0_Size = 200
wtFwpmFilter0_displayData_Offset = 16
wtFwpmFilter0_flags_Offset = 32
wtFwpmFilter0_providerKey_Offset = 40
wtFwpmFilter0_providerData_Offset = 48
wtFwpmFilter0_layerKey_Offset = 64
wtFwpmFilter0_subLayerKey_Offset = 80
wtFwpmFilter0_weight_Offset = 96
wtFwpmFilter0_numFilterConditions_Offset = 112
wtFwpmFilter0_filterCondition_Offset = 120
wtFwpmFilter0_action_Offset = 128
wtFwpmFilter0_providerContextKey_Offset = 152
wtFwpmFilter0_reserved_Offset = 168
wtFwpmFilter0_filterID_Offset = 176
wtFwpmFilter0_effectiveWeight_Offset = 184
wtFwpmFilterCondition0_Size = 40
wtFwpmFilterCondition0_matchType_Offset = 16
wtFwpmFilterCondition0_conditionValue_Offset = 24
wtFwpmSession0_Size = 72
wtFwpmSession0_displayData_Offset = 16
wtFwpmSession0_flags_Offset = 32
wtFwpmSession0_txnWaitTimeoutInMSec_Offset = 36
wtFwpmSession0_processId_Offset = 40
wtFwpmSession0_sid_Offset = 48
wtFwpmSession0_username_Offset = 56
wtFwpmSession0_kernelMode_Offset = 64
wtFwpmSublayer0_Size = 72
wtFwpmSublayer0_displayData_Offset = 16
wtFwpmSublayer0_flags_Offset = 32
wtFwpmSublayer0_providerKey_Offset = 40
wtFwpmSublayer0_providerData_Offset = 48
wtFwpmSublayer0_weight_Offset = 64
wtFwpProvider0_Size = 64
wtFwpProvider0_displayData_Offset = 16
wtFwpProvider0_flags_Offset = 32
wtFwpProvider0_providerData_Offset = 40
wtFwpProvider0_serviceName_Offset = 56
wtFwpValue0_Size = 16
wtFwpValue0_value_Offset = 8
)
// FWPM_FILTER0 defined in fwpmtypes.h
// (https://docs.microsoft.com/en-us/windows/desktop/api/fwpmtypes/ns-fwpmtypes-fwpm_filter0).
type wtFwpmFilter0 struct {
filterKey windows.GUID // Windows type: GUID
displayData wtFwpmDisplayData0
flags wtFwpmFilterFlags // Windows type: UINT32
providerKey *windows.GUID // Windows type: *GUID
providerData wtFwpByteBlob
layerKey windows.GUID // Windows type: GUID
subLayerKey windows.GUID // Windows type: GUID
weight wtFwpValue0
numFilterConditions uint32
filterCondition *wtFwpmFilterCondition0
action wtFwpmAction0
offset1 [4]byte // Layout correction field
providerContextKey windows.GUID // Windows type: GUID
reserved *windows.GUID // Windows type: *GUID
filterID uint64
effectiveWeight wtFwpValue0
}

View File

@@ -1,511 +0,0 @@
/* SPDX-License-Identifier: MIT
*
* Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package firewall
import (
"testing"
"unsafe"
)
func TestWtFwpByteBlobSize(t *testing.T) {
const actualWtFwpByteBlobSize = unsafe.Sizeof(wtFwpByteBlob{})
if actualWtFwpByteBlobSize != wtFwpByteBlob_Size {
t.Errorf("Size of FwpByteBlob is %d, although %d is expected.", actualWtFwpByteBlobSize,
wtFwpByteBlob_Size)
}
}
func TestWtFwpByteBlobOffsets(t *testing.T) {
s := wtFwpByteBlob{}
sp := uintptr(unsafe.Pointer(&s))
offset := uintptr(unsafe.Pointer(&s.data)) - sp
if offset != wtFwpByteBlob_data_Offset {
t.Errorf("FwpByteBlob.data offset is %d although %d is expected", offset, wtFwpByteBlob_data_Offset)
return
}
}
func TestWtFwpmAction0Size(t *testing.T) {
const actualWtFwpmAction0Size = unsafe.Sizeof(wtFwpmAction0{})
if actualWtFwpmAction0Size != wtFwpmAction0_Size {
t.Errorf("Size of wtFwpmAction0 is %d, although %d is expected.", actualWtFwpmAction0Size,
wtFwpmAction0_Size)
}
}
func TestWtFwpmAction0Offsets(t *testing.T) {
s := wtFwpmAction0{}
sp := uintptr(unsafe.Pointer(&s))
offset := uintptr(unsafe.Pointer(&s.filterType)) - sp
if offset != wtFwpmAction0_filterType_Offset {
t.Errorf("wtFwpmAction0.filterType offset is %d although %d is expected", offset,
wtFwpmAction0_filterType_Offset)
return
}
}
func TestWtFwpBitmapArray64Size(t *testing.T) {
const actualWtFwpBitmapArray64Size = unsafe.Sizeof(wtFwpBitmapArray64{})
if actualWtFwpBitmapArray64Size != wtFwpBitmapArray64_Size {
t.Errorf("Size of wtFwpBitmapArray64 is %d, although %d is expected.", actualWtFwpBitmapArray64Size,
wtFwpBitmapArray64_Size)
}
}
func TestWtFwpByteArray6Size(t *testing.T) {
const actualWtFwpByteArray6Size = unsafe.Sizeof(wtFwpByteArray6{})
if actualWtFwpByteArray6Size != wtFwpByteArray6_Size {
t.Errorf("Size of wtFwpByteArray6 is %d, although %d is expected.", actualWtFwpByteArray6Size,
wtFwpByteArray6_Size)
}
}
func TestWtFwpByteArray16Size(t *testing.T) {
const actualWtFwpByteArray16Size = unsafe.Sizeof(wtFwpByteArray16{})
if actualWtFwpByteArray16Size != wtFwpByteArray16_Size {
t.Errorf("Size of wtFwpByteArray16 is %d, although %d is expected.", actualWtFwpByteArray16Size,
wtFwpByteArray16_Size)
}
}
func TestWtFwpConditionValue0Size(t *testing.T) {
const actualWtFwpConditionValue0Size = unsafe.Sizeof(wtFwpConditionValue0{})
if actualWtFwpConditionValue0Size != wtFwpConditionValue0_Size {
t.Errorf("Size of wtFwpConditionValue0 is %d, although %d is expected.", actualWtFwpConditionValue0Size,
wtFwpConditionValue0_Size)
}
}
func TestWtFwpConditionValue0Offsets(t *testing.T) {
s := wtFwpConditionValue0{}
sp := uintptr(unsafe.Pointer(&s))
offset := uintptr(unsafe.Pointer(&s.value)) - sp
if offset != wtFwpConditionValue0_uint8_Offset {
t.Errorf("wtFwpConditionValue0.value offset is %d although %d is expected", offset, wtFwpConditionValue0_uint8_Offset)
return
}
}
func TestWtFwpV4AddrAndMaskSize(t *testing.T) {
const actualWtFwpV4AddrAndMaskSize = unsafe.Sizeof(wtFwpV4AddrAndMask{})
if actualWtFwpV4AddrAndMaskSize != wtFwpV4AddrAndMask_Size {
t.Errorf("Size of wtFwpV4AddrAndMask is %d, although %d is expected.", actualWtFwpV4AddrAndMaskSize,
wtFwpV4AddrAndMask_Size)
}
}
func TestWtFwpV4AddrAndMaskOffsets(t *testing.T) {
s := wtFwpV4AddrAndMask{}
sp := uintptr(unsafe.Pointer(&s))
offset := uintptr(unsafe.Pointer(&s.mask)) - sp
if offset != wtFwpV4AddrAndMask_mask_Offset {
t.Errorf("wtFwpV4AddrAndMask.mask offset is %d although %d is expected", offset,
wtFwpV4AddrAndMask_mask_Offset)
return
}
}
func TestWtFwpV6AddrAndMaskSize(t *testing.T) {
const actualWtFwpV6AddrAndMaskSize = unsafe.Sizeof(wtFwpV6AddrAndMask{})
if actualWtFwpV6AddrAndMaskSize != wtFwpV6AddrAndMask_Size {
t.Errorf("Size of wtFwpV6AddrAndMask is %d, although %d is expected.", actualWtFwpV6AddrAndMaskSize,
wtFwpV6AddrAndMask_Size)
}
}
func TestWtFwpV6AddrAndMaskOffsets(t *testing.T) {
s := wtFwpV6AddrAndMask{}
sp := uintptr(unsafe.Pointer(&s))
offset := uintptr(unsafe.Pointer(&s.prefixLength)) - sp
if offset != wtFwpV6AddrAndMask_prefixLength_Offset {
t.Errorf("wtFwpV6AddrAndMask.prefixLength offset is %d although %d is expected", offset,
wtFwpV6AddrAndMask_prefixLength_Offset)
return
}
}
func TestWtFwpValue0Size(t *testing.T) {
const actualWtFwpValue0Size = unsafe.Sizeof(wtFwpValue0{})
if actualWtFwpValue0Size != wtFwpValue0_Size {
t.Errorf("Size of wtFwpValue0 is %d, although %d is expected.", actualWtFwpValue0Size, wtFwpValue0_Size)
}
}
func TestWtFwpValue0Offsets(t *testing.T) {
s := wtFwpValue0{}
sp := uintptr(unsafe.Pointer(&s))
offset := uintptr(unsafe.Pointer(&s.value)) - sp
if offset != wtFwpValue0_value_Offset {
t.Errorf("wtFwpValue0.value offset is %d although %d is expected", offset, wtFwpValue0_value_Offset)
return
}
}
func TestWtFwpmDisplayData0Size(t *testing.T) {
const actualWtFwpmDisplayData0Size = unsafe.Sizeof(wtFwpmDisplayData0{})
if actualWtFwpmDisplayData0Size != wtFwpmDisplayData0_Size {
t.Errorf("Size of wtFwpmDisplayData0 is %d, although %d is expected.", actualWtFwpmDisplayData0Size,
wtFwpmDisplayData0_Size)
}
}
func TestWtFwpmDisplayData0Offsets(t *testing.T) {
s := wtFwpmDisplayData0{}
sp := uintptr(unsafe.Pointer(&s))
offset := uintptr(unsafe.Pointer(&s.description)) - sp
if offset != wtFwpmDisplayData0_description_Offset {
t.Errorf("wtFwpmDisplayData0.description offset is %d although %d is expected", offset,
wtFwpmDisplayData0_description_Offset)
return
}
}
func TestWtFwpmFilterCondition0Size(t *testing.T) {
const actualWtFwpmFilterCondition0Size = unsafe.Sizeof(wtFwpmFilterCondition0{})
if actualWtFwpmFilterCondition0Size != wtFwpmFilterCondition0_Size {
t.Errorf("Size of wtFwpmFilterCondition0 is %d, although %d is expected.",
actualWtFwpmFilterCondition0Size, wtFwpmFilterCondition0_Size)
}
}
func TestWtFwpmFilterCondition0Offsets(t *testing.T) {
s := wtFwpmFilterCondition0{}
sp := uintptr(unsafe.Pointer(&s))
offset := uintptr(unsafe.Pointer(&s.matchType)) - sp
if offset != wtFwpmFilterCondition0_matchType_Offset {
t.Errorf("wtFwpmFilterCondition0.matchType offset is %d although %d is expected", offset,
wtFwpmFilterCondition0_matchType_Offset)
return
}
offset = uintptr(unsafe.Pointer(&s.conditionValue)) - sp
if offset != wtFwpmFilterCondition0_conditionValue_Offset {
t.Errorf("wtFwpmFilterCondition0.conditionValue offset is %d although %d is expected", offset,
wtFwpmFilterCondition0_conditionValue_Offset)
return
}
}
func TestWtFwpmFilter0Size(t *testing.T) {
const actualWtFwpmFilter0Size = unsafe.Sizeof(wtFwpmFilter0{})
if actualWtFwpmFilter0Size != wtFwpmFilter0_Size {
t.Errorf("Size of wtFwpmFilter0 is %d, although %d is expected.", actualWtFwpmFilter0Size,
wtFwpmFilter0_Size)
}
}
func TestWtFwpmFilter0Offsets(t *testing.T) {
s := wtFwpmFilter0{}
sp := uintptr(unsafe.Pointer(&s))
offset := uintptr(unsafe.Pointer(&s.displayData)) - sp
if offset != wtFwpmFilter0_displayData_Offset {
t.Errorf("wtFwpmFilter0.displayData offset is %d although %d is expected", offset,
wtFwpmFilter0_displayData_Offset)
return
}
offset = uintptr(unsafe.Pointer(&s.flags)) - sp
if offset != wtFwpmFilter0_flags_Offset {
t.Errorf("wtFwpmFilter0.flags offset is %d although %d is expected", offset, wtFwpmFilter0_flags_Offset)
return
}
offset = uintptr(unsafe.Pointer(&s.providerKey)) - sp
if offset != wtFwpmFilter0_providerKey_Offset {
t.Errorf("wtFwpmFilter0.providerKey offset is %d although %d is expected", offset,
wtFwpmFilter0_providerKey_Offset)
return
}
offset = uintptr(unsafe.Pointer(&s.providerData)) - sp
if offset != wtFwpmFilter0_providerData_Offset {
t.Errorf("wtFwpmFilter0.providerData offset is %d although %d is expected", offset,
wtFwpmFilter0_providerData_Offset)
return
}
offset = uintptr(unsafe.Pointer(&s.layerKey)) - sp
if offset != wtFwpmFilter0_layerKey_Offset {
t.Errorf("wtFwpmFilter0.layerKey offset is %d although %d is expected", offset,
wtFwpmFilter0_layerKey_Offset)
return
}
offset = uintptr(unsafe.Pointer(&s.subLayerKey)) - sp
if offset != wtFwpmFilter0_subLayerKey_Offset {
t.Errorf("wtFwpmFilter0.subLayerKey offset is %d although %d is expected", offset,
wtFwpmFilter0_subLayerKey_Offset)
return
}
offset = uintptr(unsafe.Pointer(&s.weight)) - sp
if offset != wtFwpmFilter0_weight_Offset {
t.Errorf("wtFwpmFilter0.weight offset is %d although %d is expected", offset,
wtFwpmFilter0_weight_Offset)
return
}
offset = uintptr(unsafe.Pointer(&s.numFilterConditions)) - sp
if offset != wtFwpmFilter0_numFilterConditions_Offset {
t.Errorf("wtFwpmFilter0.numFilterConditions offset is %d although %d is expected", offset,
wtFwpmFilter0_numFilterConditions_Offset)
return
}
offset = uintptr(unsafe.Pointer(&s.filterCondition)) - sp
if offset != wtFwpmFilter0_filterCondition_Offset {
t.Errorf("wtFwpmFilter0.filterCondition offset is %d although %d is expected", offset,
wtFwpmFilter0_filterCondition_Offset)
return
}
offset = uintptr(unsafe.Pointer(&s.action)) - sp
if offset != wtFwpmFilter0_action_Offset {
t.Errorf("wtFwpmFilter0.action offset is %d although %d is expected", offset,
wtFwpmFilter0_action_Offset)
return
}
offset = uintptr(unsafe.Pointer(&s.providerContextKey)) - sp
if offset != wtFwpmFilter0_providerContextKey_Offset {
t.Errorf("wtFwpmFilter0.providerContextKey offset is %d although %d is expected", offset,
wtFwpmFilter0_providerContextKey_Offset)
return
}
offset = uintptr(unsafe.Pointer(&s.reserved)) - sp
if offset != wtFwpmFilter0_reserved_Offset {
t.Errorf("wtFwpmFilter0.reserved offset is %d although %d is expected", offset,
wtFwpmFilter0_reserved_Offset)
return
}
offset = uintptr(unsafe.Pointer(&s.filterID)) - sp
if offset != wtFwpmFilter0_filterID_Offset {
t.Errorf("wtFwpmFilter0.filterID offset is %d although %d is expected", offset,
wtFwpmFilter0_filterID_Offset)
return
}
offset = uintptr(unsafe.Pointer(&s.effectiveWeight)) - sp
if offset != wtFwpmFilter0_effectiveWeight_Offset {
t.Errorf("wtFwpmFilter0.effectiveWeight offset is %d although %d is expected", offset,
wtFwpmFilter0_effectiveWeight_Offset)
return
}
}
func TestWtFwpProvider0Size(t *testing.T) {
const actualWtFwpProvider0Size = unsafe.Sizeof(wtFwpProvider0{})
if actualWtFwpProvider0Size != wtFwpProvider0_Size {
t.Errorf("Size of wtFwpProvider0 is %d, although %d is expected.", actualWtFwpProvider0Size,
wtFwpProvider0_Size)
}
}
func TestWtFwpProvider0Offsets(t *testing.T) {
s := wtFwpProvider0{}
sp := uintptr(unsafe.Pointer(&s))
offset := uintptr(unsafe.Pointer(&s.displayData)) - sp
if offset != wtFwpProvider0_displayData_Offset {
t.Errorf("wtFwpProvider0.displayData offset is %d although %d is expected", offset,
wtFwpProvider0_displayData_Offset)
return
}
offset = uintptr(unsafe.Pointer(&s.flags)) - sp
if offset != wtFwpProvider0_flags_Offset {
t.Errorf("wtFwpProvider0.flags offset is %d although %d is expected", offset,
wtFwpProvider0_flags_Offset)
return
}
offset = uintptr(unsafe.Pointer(&s.providerData)) - sp
if offset != wtFwpProvider0_providerData_Offset {
t.Errorf("wtFwpProvider0.providerData offset is %d although %d is expected", offset,
wtFwpProvider0_providerData_Offset)
return
}
offset = uintptr(unsafe.Pointer(&s.serviceName)) - sp
if offset != wtFwpProvider0_serviceName_Offset {
t.Errorf("wtFwpProvider0.serviceName offset is %d although %d is expected", offset,
wtFwpProvider0_serviceName_Offset)
return
}
}
func TestWtFwpmSession0Size(t *testing.T) {
const actualWtFwpmSession0Size = unsafe.Sizeof(wtFwpmSession0{})
if actualWtFwpmSession0Size != wtFwpmSession0_Size {
t.Errorf("Size of wtFwpmSession0 is %d, although %d is expected.", actualWtFwpmSession0Size,
wtFwpmSession0_Size)
}
}
func TestWtFwpmSession0Offsets(t *testing.T) {
s := wtFwpmSession0{}
sp := uintptr(unsafe.Pointer(&s))
offset := uintptr(unsafe.Pointer(&s.displayData)) - sp
if offset != wtFwpmSession0_displayData_Offset {
t.Errorf("wtFwpmSession0.displayData offset is %d although %d is expected", offset,
wtFwpmSession0_displayData_Offset)
return
}
offset = uintptr(unsafe.Pointer(&s.flags)) - sp
if offset != wtFwpmSession0_flags_Offset {
t.Errorf("wtFwpmSession0.flags offset is %d although %d is expected", offset, wtFwpmSession0_flags_Offset)
return
}
offset = uintptr(unsafe.Pointer(&s.txnWaitTimeoutInMSec)) - sp
if offset != wtFwpmSession0_txnWaitTimeoutInMSec_Offset {
t.Errorf("wtFwpmSession0.txnWaitTimeoutInMSec offset is %d although %d is expected", offset,
wtFwpmSession0_txnWaitTimeoutInMSec_Offset)
return
}
offset = uintptr(unsafe.Pointer(&s.processId)) - sp
if offset != wtFwpmSession0_processId_Offset {
t.Errorf("wtFwpmSession0.processId offset is %d although %d is expected", offset,
wtFwpmSession0_processId_Offset)
return
}
offset = uintptr(unsafe.Pointer(&s.sid)) - sp
if offset != wtFwpmSession0_sid_Offset {
t.Errorf("wtFwpmSession0.sid offset is %d although %d is expected", offset, wtFwpmSession0_sid_Offset)
return
}
offset = uintptr(unsafe.Pointer(&s.username)) - sp
if offset != wtFwpmSession0_username_Offset {
t.Errorf("wtFwpmSession0.username offset is %d although %d is expected", offset,
wtFwpmSession0_username_Offset)
return
}
offset = uintptr(unsafe.Pointer(&s.kernelMode)) - sp
if offset != wtFwpmSession0_kernelMode_Offset {
t.Errorf("wtFwpmSession0.kernelMode offset is %d although %d is expected", offset,
wtFwpmSession0_kernelMode_Offset)
return
}
}
func TestWtFwpmSublayer0Size(t *testing.T) {
const actualWtFwpmSublayer0Size = unsafe.Sizeof(wtFwpmSublayer0{})
if actualWtFwpmSublayer0Size != wtFwpmSublayer0_Size {
t.Errorf("Size of wtFwpmSublayer0 is %d, although %d is expected.", actualWtFwpmSublayer0Size,
wtFwpmSublayer0_Size)
}
}
func TestWtFwpmSublayer0Offsets(t *testing.T) {
s := wtFwpmSublayer0{}
sp := uintptr(unsafe.Pointer(&s))
offset := uintptr(unsafe.Pointer(&s.displayData)) - sp
if offset != wtFwpmSublayer0_displayData_Offset {
t.Errorf("wtFwpmSublayer0.displayData offset is %d although %d is expected", offset,
wtFwpmSublayer0_displayData_Offset)
return
}
offset = uintptr(unsafe.Pointer(&s.flags)) - sp
if offset != wtFwpmSublayer0_flags_Offset {
t.Errorf("wtFwpmSublayer0.flags offset is %d although %d is expected", offset,
wtFwpmSublayer0_flags_Offset)
return
}
offset = uintptr(unsafe.Pointer(&s.providerKey)) - sp
if offset != wtFwpmSublayer0_providerKey_Offset {
t.Errorf("wtFwpmSublayer0.providerKey offset is %d although %d is expected", offset,
wtFwpmSublayer0_providerKey_Offset)
return
}
offset = uintptr(unsafe.Pointer(&s.providerData)) - sp
if offset != wtFwpmSublayer0_providerData_Offset {
t.Errorf("wtFwpmSublayer0.providerData offset is %d although %d is expected", offset,
wtFwpmSublayer0_providerData_Offset)
return
}
offset = uintptr(unsafe.Pointer(&s.weight)) - sp
if offset != wtFwpmSublayer0_weight_Offset {
t.Errorf("wtFwpmSublayer0.weight offset is %d although %d is expected", offset,
wtFwpmSublayer0_weight_Offset)
return
}
}

View File

@@ -1,130 +0,0 @@
// Code generated by 'go generate'; DO NOT EDIT.
package firewall
import (
"syscall"
"unsafe"
"golang.org/x/sys/windows"
)
var _ unsafe.Pointer
// Do the interface allocations only once for common
// Errno values.
const (
errnoERROR_IO_PENDING = 997
)
var (
errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING)
errERROR_EINVAL error = syscall.EINVAL
)
// errnoErr returns common boxed Errno values, to prevent
// allocations at runtime.
func errnoErr(e syscall.Errno) error {
switch e {
case 0:
return errERROR_EINVAL
case errnoERROR_IO_PENDING:
return errERROR_IO_PENDING
}
// TODO: add more here, after collecting data on the common
// error values see on Windows. (perhaps when running
// all.bat?)
return e
}
var (
modfwpuclnt = windows.NewLazySystemDLL("fwpuclnt.dll")
procFwpmEngineClose0 = modfwpuclnt.NewProc("FwpmEngineClose0")
procFwpmEngineOpen0 = modfwpuclnt.NewProc("FwpmEngineOpen0")
procFwpmFilterAdd0 = modfwpuclnt.NewProc("FwpmFilterAdd0")
procFwpmFreeMemory0 = modfwpuclnt.NewProc("FwpmFreeMemory0")
procFwpmGetAppIdFromFileName0 = modfwpuclnt.NewProc("FwpmGetAppIdFromFileName0")
procFwpmProviderAdd0 = modfwpuclnt.NewProc("FwpmProviderAdd0")
procFwpmSubLayerAdd0 = modfwpuclnt.NewProc("FwpmSubLayerAdd0")
procFwpmTransactionAbort0 = modfwpuclnt.NewProc("FwpmTransactionAbort0")
procFwpmTransactionBegin0 = modfwpuclnt.NewProc("FwpmTransactionBegin0")
procFwpmTransactionCommit0 = modfwpuclnt.NewProc("FwpmTransactionCommit0")
)
func fwpmEngineClose0(engineHandle uintptr) (err error) {
r1, _, e1 := syscall.Syscall(procFwpmEngineClose0.Addr(), 1, uintptr(engineHandle), 0, 0)
if r1 != 0 {
err = errnoErr(e1)
}
return
}
func fwpmEngineOpen0(serverName *uint16, authnService wtRpcCAuthN, authIdentity *uintptr, session *wtFwpmSession0, engineHandle unsafe.Pointer) (err error) {
r1, _, e1 := syscall.Syscall6(procFwpmEngineOpen0.Addr(), 5, uintptr(unsafe.Pointer(serverName)), uintptr(authnService), uintptr(unsafe.Pointer(authIdentity)), uintptr(unsafe.Pointer(session)), uintptr(engineHandle), 0)
if r1 != 0 {
err = errnoErr(e1)
}
return
}
func fwpmFilterAdd0(engineHandle uintptr, filter *wtFwpmFilter0, sd uintptr, id *uint64) (err error) {
r1, _, e1 := syscall.Syscall6(procFwpmFilterAdd0.Addr(), 4, uintptr(engineHandle), uintptr(unsafe.Pointer(filter)), uintptr(sd), uintptr(unsafe.Pointer(id)), 0, 0)
if r1 != 0 {
err = errnoErr(e1)
}
return
}
func fwpmFreeMemory0(p unsafe.Pointer) {
syscall.Syscall(procFwpmFreeMemory0.Addr(), 1, uintptr(p), 0, 0)
return
}
func fwpmGetAppIdFromFileName0(fileName *uint16, appID unsafe.Pointer) (err error) {
r1, _, e1 := syscall.Syscall(procFwpmGetAppIdFromFileName0.Addr(), 2, uintptr(unsafe.Pointer(fileName)), uintptr(appID), 0)
if r1 != 0 {
err = errnoErr(e1)
}
return
}
func fwpmProviderAdd0(engineHandle uintptr, provider *wtFwpmProvider0, sd uintptr) (err error) {
r1, _, e1 := syscall.Syscall(procFwpmProviderAdd0.Addr(), 3, uintptr(engineHandle), uintptr(unsafe.Pointer(provider)), uintptr(sd))
if r1 != 0 {
err = errnoErr(e1)
}
return
}
func fwpmSubLayerAdd0(engineHandle uintptr, subLayer *wtFwpmSublayer0, sd uintptr) (err error) {
r1, _, e1 := syscall.Syscall(procFwpmSubLayerAdd0.Addr(), 3, uintptr(engineHandle), uintptr(unsafe.Pointer(subLayer)), uintptr(sd))
if r1 != 0 {
err = errnoErr(e1)
}
return
}
func fwpmTransactionAbort0(engineHandle uintptr) (err error) {
r1, _, e1 := syscall.Syscall(procFwpmTransactionAbort0.Addr(), 1, uintptr(engineHandle), 0, 0)
if r1 != 0 {
err = errnoErr(e1)
}
return
}
func fwpmTransactionBegin0(engineHandle uintptr, flags uint32) (err error) {
r1, _, e1 := syscall.Syscall(procFwpmTransactionBegin0.Addr(), 2, uintptr(engineHandle), uintptr(flags), 0)
if r1 != 0 {
err = errnoErr(e1)
}
return
}
func fwpmTransactionCommit0(engineHandle uintptr) (err error) {
r1, _, e1 := syscall.Syscall(procFwpmTransactionCommit0.Addr(), 1, uintptr(engineHandle), 0, 0)
if r1 != 0 {
err = errnoErr(e1)
}
return
}

Some files were not shown because too many files have changed in this diff Show More