diff options
author | Jason A. Donenfeld <Jason@zx2c4.com> | 2019-05-06 09:46:10 +0200 |
---|---|---|
committer | Jason A. Donenfeld <Jason@zx2c4.com> | 2019-05-06 15:55:02 +0200 |
commit | 568528c747afe3ae991b0340d15cd6a897fd5c9d (patch) | |
tree | dd08e02b053b0cf27a75ed2e428701b1799e3bf1 /service/service_manager.go | |
parent | ui: do tray click action when popup clicked (diff) | |
download | wireguard-windows-568528c747afe3ae991b0340d15cd6a897fd5c9d.tar.xz wireguard-windows-568528c747afe3ae991b0340d15cd6a897fd5c9d.zip |
updater: move into manager
Diffstat (limited to 'service/service_manager.go')
-rw-r--r-- | service/service_manager.go | 182 |
1 files changed, 45 insertions, 137 deletions
diff --git a/service/service_manager.go b/service/service_manager.go index 715b4257..e8818ae4 100644 --- a/service/service_manager.go +++ b/service/service_manager.go @@ -16,82 +16,9 @@ import ( "runtime/debug" "sync" "syscall" - "unicode/utf16" "unsafe" ) -const ( - wtsSessionLogon uint32 = 5 - wtsSessionLogoff uint32 = 6 -) - -type wtsState int - -const ( - wtsActive wtsState = iota - wtsConnected - wtsConnectQuery - wtsShadow - wtsDisconnected - wtsIdle - wtsListen - wtsReset - wtsDown - wtsInit -) - -type wtsSessionNotification struct { - size uint32 - sessionID uint32 -} - -type wtsSessionInfo struct { - sessionID uint32 - windowStationName *uint16 - state wtsState -} - -//sys wtsQueryUserToken(session uint32, token *windows.Token) (err error) = wtsapi32.WTSQueryUserToken -//sys wtsEnumerateSessions(handle windows.Handle, reserved uint32, version uint32, sessions **wtsSessionInfo, count *uint32) (err error) = wtsapi32.WTSEnumerateSessionsW -//sys wtsFreeMemory(ptr uintptr) = wtsapi32.WTSFreeMemory - -const ( - SE_KERNEL_OBJECT = 6 - DACL_SECURITY_INFORMATION = 4 - ATTRIBUTE_SECURITY_INFORMATION = 16 -) - -//sys getSecurityInfo(handle windows.Handle, objectType uint32, si uint32, sidOwner *windows.SID, sidGroup *windows.SID, dacl *uintptr, sacl *uintptr, securityDescriptor *uintptr) (err error) [failretval!=0] = advapi32.GetSecurityInfo -//sys getSecurityDescriptorLength(securityDescriptor uintptr) (len uint32) = advapi32.GetSecurityDescriptorLength - -//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) { @@ -126,29 +53,12 @@ func (service *managerService) Execute(args []string, r <-chan svc.ChangeRequest serviceError = ErrorDetermineExecutablePath return } - - adminSid, err := windows.CreateWellKnownSid(windows.WinBuiltinAdministratorsSid) - if err != nil { - serviceError = ErrorFindAdministratorsSID - return - } - - currentProcess, err := windows.GetCurrentProcess() - if err != nil { - panic(err) - } - var securityAttributes syscall.SecurityAttributes - err = getSecurityInfo(currentProcess, SE_KERNEL_OBJECT, DACL_SECURITY_INFORMATION, nil, nil, nil, nil, &securityAttributes.SecurityDescriptor) + securityAttributes, err := getCurrentSecurityAttributes() if err != nil { serviceError = ErrorCreateSecurityDescriptor return } defer windows.LocalFree(windows.Handle(securityAttributes.SecurityDescriptor)) - securityAttributes.Length = getSecurityDescriptorLength(securityAttributes.SecurityDescriptor) - if securityAttributes.Length == 0 { - serviceError = ErrorCreateSecurityDescriptor - return - } devNull, err := os.OpenFile(os.DevNull, os.O_RDWR, 0) if err != nil { @@ -172,49 +82,51 @@ func (service *managerService) Execute(args []string, r <-chan svc.ChangeRequest startProcess = func(session uint32) { defer runtime.UnlockOSThread() + + var userToken windows.Token + err := wtsQueryUserToken(session, &userToken) + if err != nil { + return + } + defer userToken.Close() + if !tokenIsMemberOfBuiltInAdministrator(userToken) { + return + } + user, err := userToken.GetTokenUser() + if err != nil { + log.Printf("Unable to lookup user from token: %v", err) + return + } + username, domain, accType, err := user.User.Sid.LookupAccount("") + if err != nil { + log.Printf("Unable to lookup username from sid: %v", err) + return + } + if accType != windows.SidTypeUser { + return + } + env, err := userEnviron(userToken) + if err != nil { + log.Printf("Unable to determine user environment: %v", err) + return + } + userTokenInfo := &UserTokenInfo{} + userTokenInfo.elevatedToken, err = getElevatedToken(userToken) + if err != nil { + log.Printf("Unable to elevate token: %v", err) + } + if userTokenInfo.elevatedToken != userToken { + defer userTokenInfo.elevatedToken.Close() + } + userTokenInfo.elevatedEnvironment, err = userEnviron(userTokenInfo.elevatedToken) + if err != nil { + log.Printf("Unable to determine elevated environment: %v", err) + return + } for { if stoppingManager { return } - var userToken windows.Token - err := wtsQueryUserToken(session, &userToken) - if err != nil { - return - } - - //TODO: SECURITY CRITICIAL! - //TODO: Isn't it better to use an impersonation token and userToken.IsMember instead? - gs, err := userToken.GetTokenGroups() - if err != nil { - log.Printf("Unable to lookup user groups from token: %v", err) - return - } - p := unsafe.Pointer(&gs.Groups[0]) - groups := (*[(1 << 28) - 1]windows.SIDAndAttributes)(p)[:gs.GroupCount] - isAdmin := false - for _, g := range groups { - if windows.EqualSid(g.Sid, adminSid) { - isAdmin = true - break - } - } - if !isAdmin { - return - } - - user, err := userToken.GetTokenUser() - if err != nil { - log.Printf("Unable to lookup user from token: %v", err) - return - } - username, domain, accType, err := user.User.Sid.LookupAccount("") - if err != nil { - log.Printf("Unable to lookup username from sid: %v", err) - return - } - if accType != windows.SidTypeUser { - return - } //TODO: we lock the OS thread so that these inheritable handles don't escape into other processes that // might be running in parallel Go routines. But the Go runtime is strange and who knows what's really @@ -226,7 +138,7 @@ func (service *managerService) Execute(args []string, r <-chan svc.ChangeRequest return } ourEvents, theirEvents, theirEventStr, err := inheritableEvents() - err = IPCServerListen(ourReader, ourWriter, ourEvents) + err = IPCServerListen(ourReader, ourWriter, ourEvents, userTokenInfo) if err != nil { log.Printf("Unable to listen on IPC pipes: %v", err) return @@ -237,12 +149,6 @@ 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{ @@ -286,6 +192,8 @@ func (service *managerService) Execute(args []string, r <-chan svc.ChangeRequest } } + go checkForUpdates() + var sessionsPointer *wtsSessionInfo var count uint32 err = wtsEnumerateSessions(0, 0, 1, &sessionsPointer, &count) |