aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/service/service_manager.go
diff options
context:
space:
mode:
Diffstat (limited to 'service/service_manager.go')
-rw-r--r--service/service_manager.go182
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)