aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/manager
diff options
context:
space:
mode:
Diffstat (limited to 'manager')
-rw-r--r--manager/ipc_server.go45
-rw-r--r--manager/service.go57
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,