clientupdate: fix auto-update on Windows over RDP (#10242)

`winutil.WTSGetActiveConsoleSessionId` only works for physical desktop
logins and does not return the session ID for RDP logins. We need to
`windows.WTSEnumerateSessions` and find the active session.

Fixes https://github.com/tailscale/corp/issues/15772

Signed-off-by: Andrew Lytvynov <awly@tailscale.com>
pull/10251/head
Andrew Lytvynov 7 months ago committed by GitHub
parent 60957e1077
commit c3f1bd4c0a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -7,13 +7,15 @@
package clientupdate package clientupdate
import ( import (
"errors"
"fmt"
"os/exec" "os/exec"
"os/user" "os/user"
"path/filepath" "path/filepath"
"syscall" "syscall"
"unsafe"
"golang.org/x/sys/windows" "golang.org/x/sys/windows"
"tailscale.com/util/winutil"
"tailscale.com/util/winutil/authenticode" "tailscale.com/util/winutil/authenticode"
) )
@ -39,13 +41,14 @@ func launchTailscaleAsGUIUser(exePath string) error {
var token windows.Token var token windows.Token
if u, err := user.Current(); err == nil && u.Name == "SYSTEM" { if u, err := user.Current(); err == nil && u.Name == "SYSTEM" {
sessionID := winutil.WTSGetActiveConsoleSessionId() sessionID, err := wtsGetActiveSessionID()
if sessionID != 0xFFFFFFFF { if err != nil {
if err := windows.WTSQueryUserToken(sessionID, &token); err != nil { return fmt.Errorf("wtsGetActiveSessionID(): %w", err)
return err
}
defer token.Close()
} }
if err := windows.WTSQueryUserToken(sessionID, &token); err != nil {
return fmt.Errorf("WTSQueryUserToken (0x%x): %w", sessionID, err)
}
defer token.Close()
} }
cmd := exec.Command(exePath) cmd := exec.Command(exePath)
@ -55,3 +58,27 @@ func launchTailscaleAsGUIUser(exePath string) error {
} }
return cmd.Start() return cmd.Start()
} }
func wtsGetActiveSessionID() (uint32, error) {
var (
sessionInfo *windows.WTS_SESSION_INFO
count uint32 = 0
)
const WTS_CURRENT_SERVER_HANDLE = 0
if err := windows.WTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE, 0, 1, &sessionInfo, &count); err != nil {
return 0, fmt.Errorf("WTSEnumerateSessions: %w", err)
}
defer windows.WTSFreeMemory(uintptr(unsafe.Pointer(sessionInfo)))
current := unsafe.Pointer(sessionInfo)
for i := uint32(0); i < count; i++ {
session := (*windows.WTS_SESSION_INFO)(current)
if session.State == windows.WTSActive {
return session.SessionID, nil
}
current = unsafe.Add(current, unsafe.Sizeof(windows.WTS_SESSION_INFO{}))
}
return 0, errors.New("no active desktop sessions found")
}

@ -76,7 +76,7 @@ tailscale.com/cmd/tailscale dependencies: (generated by github.com/tailscale/dep
tailscale.com/client/tailscale from tailscale.com/cmd/tailscale/cli+ tailscale.com/client/tailscale from tailscale.com/cmd/tailscale/cli+
tailscale.com/client/tailscale/apitype from tailscale.com/cmd/tailscale/cli+ tailscale.com/client/tailscale/apitype from tailscale.com/cmd/tailscale/cli+
tailscale.com/client/web from tailscale.com/cmd/tailscale/cli tailscale.com/client/web from tailscale.com/cmd/tailscale/cli
tailscale.com/clientupdate from tailscale.com/cmd/tailscale/cli 💣 tailscale.com/clientupdate from tailscale.com/cmd/tailscale/cli
tailscale.com/clientupdate/distsign from tailscale.com/clientupdate tailscale.com/clientupdate/distsign from tailscale.com/clientupdate
tailscale.com/cmd/tailscale/cli from tailscale.com/cmd/tailscale tailscale.com/cmd/tailscale/cli from tailscale.com/cmd/tailscale
tailscale.com/control/controlbase from tailscale.com/control/controlhttp tailscale.com/control/controlbase from tailscale.com/control/controlhttp

@ -228,7 +228,7 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de
tailscale.com/client/tailscale from tailscale.com/derp+ tailscale.com/client/tailscale from tailscale.com/derp+
tailscale.com/client/tailscale/apitype from tailscale.com/ipn/ipnlocal+ tailscale.com/client/tailscale/apitype from tailscale.com/ipn/ipnlocal+
tailscale.com/client/web from tailscale.com/ipn/ipnlocal tailscale.com/client/web from tailscale.com/ipn/ipnlocal
tailscale.com/clientupdate from tailscale.com/ipn/ipnlocal+ 💣 tailscale.com/clientupdate from tailscale.com/ipn/ipnlocal+
tailscale.com/clientupdate/distsign from tailscale.com/clientupdate tailscale.com/clientupdate/distsign from tailscale.com/clientupdate
tailscale.com/cmd/tailscaled/childproc from tailscale.com/ssh/tailssh+ tailscale.com/cmd/tailscaled/childproc from tailscale.com/ssh/tailssh+
tailscale.com/control/controlbase from tailscale.com/control/controlclient+ tailscale.com/control/controlbase from tailscale.com/control/controlclient+

Loading…
Cancel
Save