keksvpn/vendor/golang.zx2c4.com/wireguard/wgctrl/internal/wguser/conn_windows.go
2022-02-27 04:22:11 +01:00

82 lines
2 KiB
Go

//go:build windows
// +build windows
package wguser
import (
"net"
"strings"
"time"
"golang.org/x/sys/windows"
"golang.zx2c4.com/wireguard/ipc/namedpipe"
)
// Expected prefixes when dealing with named pipes.
const (
pipePrefix = `\\.\pipe\`
wgPrefix = `ProtectedPrefix\Administrators\WireGuard\`
)
// dial is the default implementation of Client.dial.
func dial(device string) (net.Conn, error) {
localSystem, err := windows.CreateWellKnownSid(windows.WinLocalSystemSid)
if err != nil {
return nil, err
}
return (&namedpipe.DialConfig{
ExpectedOwner: localSystem,
}).DialTimeout(device, time.Duration(0))
}
// find is the default implementation of Client.find.
func find() ([]string, error) {
return findNamedPipes(wgPrefix)
}
// findNamedPipes looks for Windows named pipes that match the specified
// search string prefix.
func findNamedPipes(search string) ([]string, error) {
var (
pipes []string
data windows.Win32finddata
)
// Thanks @zx2c4 for the tips on the appropriate Windows APIs here:
// https://א.cc/dHGpnhxX/c.
h, err := windows.FindFirstFile(
// Append * to find all named pipes.
windows.StringToUTF16Ptr(pipePrefix+"*"),
&data,
)
if err != nil {
return nil, err
}
// FindClose is used to close file search handles instead of the typical
// CloseHandle used elsewhere, see:
// https://docs.microsoft.com/en-us/windows/desktop/api/fileapi/nf-fileapi-findclose.
defer windows.FindClose(h)
// Check the first file's name for a match, but also keep searching for
// WireGuard named pipes until no more files can be iterated.
for {
name := windows.UTF16ToString(data.FileName[:])
if strings.HasPrefix(name, search) {
// Concatenate strings directly as filepath.Join appears to break the
// named pipe prefix convention.
pipes = append(pipes, pipePrefix+name)
}
if err := windows.FindNextFile(h, &data); err != nil {
if err == windows.ERROR_NO_MORE_FILES {
break
}
return nil, err
}
}
return pipes, nil
}