aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorJason A. Donenfeld <Jason@zx2c4.com>2019-08-28 22:30:35 -0600
committerJason A. Donenfeld <Jason@zx2c4.com>2019-08-30 08:47:21 -0600
commit2bbd162221e56e0312593cb05956c100f253ff98 (patch)
tree2dab80c185282b6cb9270836cef88f852afe5a40
parentelevate: use more strict check for admin group (diff)
downloadwireguard-windows-2bbd162221e56e0312593cb05956c100f253ff98.tar.xz
wireguard-windows-2bbd162221e56e0312593cb05956c100f253ff98.zip
elevate: check for desktop admin ownership
-rw-r--r--elevate/membership.go24
-rw-r--r--elevate/syscall_windows.go3
-rw-r--r--elevate/zsyscall_windows.go38
-rw-r--r--main.go11
-rw-r--r--manager/install.go4
5 files changed, 71 insertions, 9 deletions
diff --git a/elevate/membership.go b/elevate/membership.go
index ccd0b60e..131c6d97 100644
--- a/elevate/membership.go
+++ b/elevate/membership.go
@@ -35,3 +35,27 @@ func TokenIsElevatedOrElevatable(token windows.Token) bool {
defer linked.Close()
return linked.IsElevated() && isAdmin(linked)
}
+
+func IsAdminDesktop() (bool, error) {
+ hwnd := getShellWindow()
+ if hwnd == 0 {
+ return false, windows.ERROR_INVALID_WINDOW_HANDLE
+ }
+ var pid uint32
+ _, err := getWindowThreadProcessId(hwnd, &pid)
+ if err != nil {
+ return false, err
+ }
+ process, err := windows.OpenProcess(windows.PROCESS_QUERY_INFORMATION, false, pid)
+ if err != nil {
+ return false, err
+ }
+ defer windows.CloseHandle(process)
+ var token windows.Token
+ err = windows.OpenProcessToken(process, windows.TOKEN_QUERY | windows.TOKEN_IMPERSONATE, &token)
+ if err != nil {
+ return false, err
+ }
+ defer token.Close()
+ return TokenIsElevatedOrElevatable(token), nil
+} \ No newline at end of file
diff --git a/elevate/syscall_windows.go b/elevate/syscall_windows.go
index dba56375..1957dea2 100644
--- a/elevate/syscall_windows.go
+++ b/elevate/syscall_windows.go
@@ -84,3 +84,6 @@ const (
//sys coInitializeEx(reserved uintptr, coInit uint32) (ret error) = ole32.CoInitializeEx
//sys coUninitialize() = ole32.CoUninitialize
//sys coGetObject(name *uint16, bindOpts *cBIND_OPTS3, guid *windows.GUID, functionTable ***[0xffff]uintptr) (ret error) = ole32.CoGetObject
+
+//sys getWindowThreadProcessId(hwnd uintptr, pid *uint32) (tid uint32, err error) = user32.GetWindowThreadProcessId
+//sys getShellWindow() (hwnd uintptr) = user32.GetShellWindow
diff --git a/elevate/zsyscall_windows.go b/elevate/zsyscall_windows.go
index 0ed13233..afff428f 100644
--- a/elevate/zsyscall_windows.go
+++ b/elevate/zsyscall_windows.go
@@ -37,14 +37,17 @@ func errnoErr(e syscall.Errno) error {
}
var (
- modntdll = windows.NewLazySystemDLL("ntdll.dll")
- modole32 = windows.NewLazySystemDLL("ole32.dll")
-
- procRtlInitUnicodeString = modntdll.NewProc("RtlInitUnicodeString")
- procRtlGetCurrentPeb = modntdll.NewProc("RtlGetCurrentPeb")
- procCoInitializeEx = modole32.NewProc("CoInitializeEx")
- procCoUninitialize = modole32.NewProc("CoUninitialize")
- procCoGetObject = modole32.NewProc("CoGetObject")
+ modntdll = windows.NewLazySystemDLL("ntdll.dll")
+ modole32 = windows.NewLazySystemDLL("ole32.dll")
+ moduser32 = windows.NewLazySystemDLL("user32.dll")
+
+ procRtlInitUnicodeString = modntdll.NewProc("RtlInitUnicodeString")
+ procRtlGetCurrentPeb = modntdll.NewProc("RtlGetCurrentPeb")
+ procCoInitializeEx = modole32.NewProc("CoInitializeEx")
+ procCoUninitialize = modole32.NewProc("CoUninitialize")
+ procCoGetObject = modole32.NewProc("CoGetObject")
+ procGetWindowThreadProcessId = moduser32.NewProc("GetWindowThreadProcessId")
+ procGetShellWindow = moduser32.NewProc("GetShellWindow")
)
func rtlInitUnicodeString(destinationString *cUNICODE_STRING, sourceString *uint16) {
@@ -78,3 +81,22 @@ func coGetObject(name *uint16, bindOpts *cBIND_OPTS3, guid *windows.GUID, functi
}
return
}
+
+func getWindowThreadProcessId(hwnd uintptr, pid *uint32) (tid uint32, err error) {
+ r0, _, e1 := syscall.Syscall(procGetWindowThreadProcessId.Addr(), 2, uintptr(hwnd), uintptr(unsafe.Pointer(pid)), 0)
+ tid = uint32(r0)
+ if tid == 0 {
+ if e1 != 0 {
+ err = errnoErr(e1)
+ } else {
+ err = syscall.EINVAL
+ }
+ }
+ return
+}
+
+func getShellWindow() (hwnd uintptr) {
+ r0, _, _ := syscall.Syscall(procGetShellWindow.Addr(), 0, 0, 0, 0)
+ hwnd = uintptr(r0)
+ return
+}
diff --git a/main.go b/main.go
index e7070335..ef14afde 100644
--- a/main.go
+++ b/main.go
@@ -80,6 +80,13 @@ func checkForAdminGroup() {
}
}
+func checkForAdminDesktop() {
+ adminDesktop, err := elevate.IsAdminDesktop()
+ if !adminDesktop && err == nil {
+ fatal("WireGuard is running, but the UI is only accessible from desktops of the Builtin Administrators group.")
+ }
+}
+
func execElevatedManagerServiceInstaller() error {
path, err := os.Executable()
if err != nil {
@@ -123,8 +130,12 @@ func main() {
go ui.WaitForRaiseUIThenQuit()
err := manager.InstallManager()
if err != nil {
+ if err == manager.ErrManagerAlreadyRunning {
+ checkForAdminDesktop()
+ }
fatal(err)
}
+ checkForAdminDesktop()
time.Sleep(30 * time.Second)
fatal("WireGuard system tray icon did not appear after 30 seconds.")
return
diff --git a/manager/install.go b/manager/install.go
index cff1289a..f84a96ae 100644
--- a/manager/install.go
+++ b/manager/install.go
@@ -32,6 +32,8 @@ func serviceManager() (*mgr.Mgr, error) {
return cachedServiceManager, nil
}
+var ErrManagerAlreadyRunning = errors.New("Manager already installed and running")
+
func InstallManager() error {
m, err := serviceManager()
if err != nil {
@@ -54,7 +56,7 @@ func InstallManager() error {
}
if status.State != svc.Stopped {
service.Close()
- return errors.New("Manager already installed and running")
+ return ErrManagerAlreadyRunning
}
err = service.Delete()
service.Close()