82 lines
2 KiB
Go
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
|
|
}
|