diff options
Diffstat (limited to 'manager/service.go')
-rw-r--r-- | manager/service.go | 57 |
1 files changed, 40 insertions, 17 deletions
diff --git a/manager/service.go b/manager/service.go index 6c3b039b..48ecd129 100644 --- a/manager/service.go +++ b/manager/service.go @@ -90,6 +90,7 @@ func (service *managerService) Execute(args []string, r <-chan svc.ChangeRequest aliveSessions := make(map[uint32]bool) procsLock := sync.Mutex{} stoppingManager := false + operatorGroupSid, _ := windows.CreateWellKnownSid(windows.WinBuiltinNetworkConfigurationOperatorsSid) startProcess := func(session uint32) { defer func() { @@ -104,7 +105,24 @@ func (service *managerService) Execute(args []string, r <-chan svc.ChangeRequest if err != nil { return } - if !elevate.TokenIsElevatedOrElevatable(userToken) { + isAdmin := elevate.TokenIsElevatedOrElevatable(userToken) + isOperator := false + if !isAdmin && conf.AdminBool("LimitedOperatorUI") && operatorGroupSid != nil { + linkedToken, err := userToken.GetLinkedToken() + var impersonationToken windows.Token + if err == nil { + err = windows.DuplicateTokenEx(linkedToken, windows.TOKEN_QUERY, nil, windows.SecurityImpersonation, windows.TokenImpersonation, &impersonationToken) + linkedToken.Close() + } else { + err = windows.DuplicateTokenEx(userToken, windows.TOKEN_QUERY, nil, windows.SecurityImpersonation, windows.TokenImpersonation, &impersonationToken) + } + if err == nil { + isOperator, err = impersonationToken.IsMember(operatorGroupSid) + isOperator = isOperator && err == nil + impersonationToken.Close() + } + } + if !isAdmin && !isOperator { userToken.Close() return } @@ -125,23 +143,28 @@ func (service *managerService) Execute(args []string, r <-chan svc.ChangeRequest return } userProfileDirectory, _ := userToken.GetUserProfileDirectory() - var elevatedToken windows.Token - if userToken.IsElevated() { - elevatedToken = userToken - } else { - elevatedToken, err = userToken.GetLinkedToken() - userToken.Close() - if err != nil { - log.Printf("Unable to elevate token: %v", err) - return - } - if !elevatedToken.IsElevated() { - elevatedToken.Close() - log.Println("Linked token is not elevated") - return + var elevatedToken, runToken windows.Token + if isAdmin { + if userToken.IsElevated() { + elevatedToken = userToken + } else { + elevatedToken, err = userToken.GetLinkedToken() + userToken.Close() + if err != nil { + log.Printf("Unable to elevate token: %v", err) + return + } + if !elevatedToken.IsElevated() { + elevatedToken.Close() + log.Println("Linked token is not elevated") + return + } } + runToken = elevatedToken + } else { + runToken = userToken } - defer elevatedToken.Close() + defer runToken.Close() userToken = 0 first := true for { @@ -186,7 +209,7 @@ func (service *managerService) Execute(args []string, r <-chan svc.ChangeRequest log.Printf("Starting UI process for user ā%s@%sā for session %d", username, domain, session) attr := &os.ProcAttr{ Sys: &syscall.SysProcAttr{ - Token: syscall.Token(elevatedToken), + Token: syscall.Token(runToken), }, Files: []*os.File{devNull, devNull, devNull}, Dir: userProfileDirectory, |