diff options
Diffstat (limited to 'manager')
-rw-r--r-- | manager/ipc_server.go | 45 | ||||
-rw-r--r-- | manager/service.go | 57 |
2 files changed, 77 insertions, 25 deletions
diff --git a/manager/ipc_server.go b/manager/ipc_server.go index 98d4ffd1..38b29336 100644 --- a/manager/ipc_server.go +++ b/manager/ipc_server.go @@ -38,7 +38,14 @@ type ManagerService struct { } func (s *ManagerService) StoredConfig(tunnelName string) (*conf.Config, error) { - return conf.LoadFromName(tunnelName) + conf, err := conf.LoadFromName(tunnelName) + if err != nil { + return nil, err + } + if s.elevatedToken == 0 { + conf.Redact() + } + return conf, nil } func (s *ManagerService) RuntimeConfig(tunnelName string) (*conf.Config, error) { @@ -69,7 +76,14 @@ func (s *ManagerService) RuntimeConfig(tunnelName string) (*conf.Config, error) if err != nil { return nil, err } - return conf.FromUAPI(string(resp), storedConfig) + conf, err := conf.FromUAPI(string(resp), storedConfig) + if err != nil { + return nil, err + } + if s.elevatedToken == 0 { + conf.Redact() + } + return conf, nil } func (s *ManagerService) Start(tunnelName string) error { @@ -149,6 +163,9 @@ func (s *ManagerService) WaitForStop(tunnelName string) error { } func (s *ManagerService) Delete(tunnelName string) error { + if s.elevatedToken == 0 { + return windows.ERROR_ACCESS_DENIED + } err := s.Stop(tunnelName) if err != nil { return err @@ -193,6 +210,9 @@ func (s *ManagerService) GlobalState() TunnelState { } func (s *ManagerService) Create(tunnelConfig *conf.Config) (*Tunnel, error) { + if s.elevatedToken == 0 { + return nil, windows.ERROR_ACCESS_DENIED + } err := tunnelConfig.Save() if err != nil { return nil, err @@ -216,6 +236,9 @@ func (s *ManagerService) Tunnels() ([]Tunnel, error) { } func (s *ManagerService) Quit(stopTunnelsOnQuit bool) (alreadyQuit bool, err error) { + if s.elevatedToken == 0 { + return false, windows.ERROR_ACCESS_DENIED + } if !atomic.CompareAndSwapUint32(&haveQuit, 0, 1) { return true, nil } @@ -244,6 +267,9 @@ func (s *ManagerService) UpdateState() UpdateState { } func (s *ManagerService) Update() { + if s.elevatedToken == 0 { + return + } progress := updater.DownloadVerifyAndExecute(uintptr(s.elevatedToken)) go func() { for { @@ -443,7 +469,7 @@ func IPCServerListen(reader *os.File, writer *os.File, events *os.File, elevated }() } -func notifyAll(notificationType NotificationType, ifaces ...interface{}) { +func notifyAll(notificationType NotificationType, adminOnly bool, ifaces ...interface{}) { if len(managerServices) == 0 { return } @@ -463,6 +489,9 @@ func notifyAll(notificationType NotificationType, ifaces ...interface{}) { managerServicesLock.RLock() for m := range managerServices { + if m.elevatedToken == 0 && adminOnly { + continue + } m.events.SetWriteDeadline(time.Now().Add(time.Second)) m.events.Write(buf.Bytes()) } @@ -477,22 +506,22 @@ func errToString(err error) string { } func IPCServerNotifyTunnelChange(name string, state TunnelState, err error) { - notifyAll(TunnelChangeNotificationType, name, state, trackedTunnelsGlobalState(), errToString(err)) + notifyAll(TunnelChangeNotificationType, false, name, state, trackedTunnelsGlobalState(), errToString(err)) } func IPCServerNotifyTunnelsChange() { - notifyAll(TunnelsChangeNotificationType) + notifyAll(TunnelsChangeNotificationType, false) } func IPCServerNotifyUpdateFound(state UpdateState) { - notifyAll(UpdateFoundNotificationType, state) + notifyAll(UpdateFoundNotificationType, true, state) } func IPCServerNotifyUpdateProgress(dp updater.DownloadProgress) { - notifyAll(UpdateProgressNotificationType, dp.Activity, dp.BytesDownloaded, dp.BytesTotal, errToString(dp.Error), dp.Complete) + notifyAll(UpdateProgressNotificationType, true, dp.Activity, dp.BytesDownloaded, dp.BytesTotal, errToString(dp.Error), dp.Complete) } func IPCServerNotifyManagerStopping() { - notifyAll(ManagerStoppingNotificationType) + notifyAll(ManagerStoppingNotificationType, false) time.Sleep(time.Millisecond * 200) } 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, |