aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/service
diff options
context:
space:
mode:
authorJason A. Donenfeld <Jason@zx2c4.com>2019-04-27 09:30:50 +0200
committerJason A. Donenfeld <Jason@zx2c4.com>2019-04-27 11:49:50 +0200
commitde0beb2520dda821e8c376e318841e3eb949c2af (patch)
treeafddee66dc01e3925938e4d53a280a372c87e830 /service
parentui: simplify everything (diff)
downloadwireguard-windows-de0beb2520dda821e8c376e318841e3eb949c2af.tar.xz
wireguard-windows-de0beb2520dda821e8c376e318841e3eb949c2af.zip
service: create environment for user
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
Diffstat (limited to 'service')
-rw-r--r--service/service_manager.go36
-rw-r--r--service/zsyscall_windows.go33
2 files changed, 69 insertions, 0 deletions
diff --git a/service/service_manager.go b/service/service_manager.go
index 3d7449bd..b3752d31 100644
--- a/service/service_manager.go
+++ b/service/service_manager.go
@@ -15,6 +15,7 @@ import (
"runtime/debug"
"sync"
"syscall"
+ "unicode/utf16"
"unsafe"
)
@@ -55,6 +56,34 @@ type wellKnownSidType uint32
//sys wtsEnumerateSessions(handle windows.Handle, reserved uint32, version uint32, sessions **wtsSessionInfo, count *uint32) (err error) = wtsapi32.WTSEnumerateSessionsW
//sys wtsFreeMemory(ptr uintptr) = wtsapi32.WTSFreeMemory
+//sys createEnvironmentBlock(block *uintptr, token windows.Token, inheritExisting bool) (err error) = userenv.CreateEnvironmentBlock
+//sys destroyEnvironmentBlock(block uintptr) (err error) = userenv.DestroyEnvironmentBlock
+
+func userEnviron(token windows.Token) (env []string, err error) {
+ var block uintptr
+ err = createEnvironmentBlock(&block, token, false)
+ if err != nil {
+ return
+ }
+ offset := uintptr(0)
+ for {
+ entry := (*[1<<30 - 1]uint16)(unsafe.Pointer(block + offset))[:]
+ for i, v := range entry {
+ if v == 0 {
+ entry = entry[:i]
+ break
+ }
+ }
+ if len(entry) == 0 {
+ break
+ }
+ env = append(env, string(utf16.Decode(entry)))
+ offset += 2 * (uintptr(len(entry)) + 1)
+ }
+ destroyEnvironmentBlock(block)
+ return
+}
+
type managerService struct{}
func (service *managerService) Execute(args []string, r <-chan svc.ChangeRequest, changes chan<- svc.Status) (svcSpecificEC bool, exitCode uint32) {
@@ -175,12 +204,19 @@ func (service *managerService) Execute(args []string, r <-chan svc.ChangeRequest
return
}
+ env, err := userEnviron(userToken)
+ if err != nil {
+ log.Printf("Unable to determine user environment: %v", err)
+ return
+ }
+
log.Printf("Starting UI process for user: '%s@%s'", username, domain)
attr := &os.ProcAttr{
Sys: &syscall.SysProcAttr{
Token: syscall.Token(userToken),
},
Files: []*os.File{devNull, devNull, devNull},
+ Env: env,
}
proc, err := os.StartProcess(path, []string{path, "/ui", theirReaderStr, theirWriterStr, theirEventStr, theirLogMapping}, attr)
theirReader.Close()
diff --git a/service/zsyscall_windows.go b/service/zsyscall_windows.go
index d3ca8ddd..40bac8ff 100644
--- a/service/zsyscall_windows.go
+++ b/service/zsyscall_windows.go
@@ -38,12 +38,15 @@ func errnoErr(e syscall.Errno) error {
var (
modwtsapi32 = windows.NewLazySystemDLL("wtsapi32.dll")
+ moduserenv = windows.NewLazySystemDLL("userenv.dll")
modadvapi32 = windows.NewLazySystemDLL("advapi32.dll")
modkernel32 = windows.NewLazySystemDLL("kernel32.dll")
procWTSQueryUserToken = modwtsapi32.NewProc("WTSQueryUserToken")
procWTSEnumerateSessionsW = modwtsapi32.NewProc("WTSEnumerateSessionsW")
procWTSFreeMemory = modwtsapi32.NewProc("WTSFreeMemory")
+ procCreateEnvironmentBlock = moduserenv.NewProc("CreateEnvironmentBlock")
+ procDestroyEnvironmentBlock = moduserenv.NewProc("DestroyEnvironmentBlock")
procNotifyServiceStatusChangeW = modadvapi32.NewProc("NotifyServiceStatusChangeW")
procSleepEx = modkernel32.NewProc("SleepEx")
)
@@ -77,6 +80,36 @@ func wtsFreeMemory(ptr uintptr) {
return
}
+func createEnvironmentBlock(block *uintptr, token windows.Token, inheritExisting bool) (err error) {
+ var _p0 uint32
+ if inheritExisting {
+ _p0 = 1
+ } else {
+ _p0 = 0
+ }
+ r1, _, e1 := syscall.Syscall(procCreateEnvironmentBlock.Addr(), 3, uintptr(unsafe.Pointer(block)), uintptr(token), uintptr(_p0))
+ if r1 == 0 {
+ if e1 != 0 {
+ err = errnoErr(e1)
+ } else {
+ err = syscall.EINVAL
+ }
+ }
+ return
+}
+
+func destroyEnvironmentBlock(block uintptr) (err error) {
+ r1, _, e1 := syscall.Syscall(procDestroyEnvironmentBlock.Addr(), 1, uintptr(block), 0, 0)
+ if r1 == 0 {
+ if e1 != 0 {
+ err = errnoErr(e1)
+ } else {
+ err = syscall.EINVAL
+ }
+ }
+ return
+}
+
func notifyServiceStatusChange(service windows.Handle, notifyMask uint32, notifyBuffer uintptr) (status uint32) {
r0, _, _ := syscall.Syscall(procNotifyServiceStatusChangeW.Addr(), 3, uintptr(service), uintptr(notifyMask), uintptr(notifyBuffer))
status = uint32(r0)