Sfoglia il codice sorgente

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 <[email protected]>
Andrew Lytvynov 2 anni fa
parent
commit
c3f1bd4c0a

+ 34 - 7
clientupdate/clientupdate_windows.go

@@ -7,13 +7,15 @@
 package clientupdate
 
 import (
+	"errors"
+	"fmt"
 	"os/exec"
 	"os/user"
 	"path/filepath"
 	"syscall"
+	"unsafe"
 
 	"golang.org/x/sys/windows"
-	"tailscale.com/util/winutil"
 	"tailscale.com/util/winutil/authenticode"
 )
 
@@ -39,13 +41,14 @@ func launchTailscaleAsGUIUser(exePath string) error {
 
 	var token windows.Token
 	if u, err := user.Current(); err == nil && u.Name == "SYSTEM" {
-		sessionID := winutil.WTSGetActiveConsoleSessionId()
-		if sessionID != 0xFFFFFFFF {
-			if err := windows.WTSQueryUserToken(sessionID, &token); err != nil {
-				return err
-			}
-			defer token.Close()
+		sessionID, err := wtsGetActiveSessionID()
+		if err != nil {
+			return fmt.Errorf("wtsGetActiveSessionID(): %w", err)
 		}
+		if err := windows.WTSQueryUserToken(sessionID, &token); err != nil {
+			return fmt.Errorf("WTSQueryUserToken (0x%x): %w", sessionID, err)
+		}
+		defer token.Close()
 	}
 
 	cmd := exec.Command(exePath)
@@ -55,3 +58,27 @@ func launchTailscaleAsGUIUser(exePath string) error {
 	}
 	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")
+}

+ 1 - 1
cmd/tailscale/depaware.txt

@@ -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/apitype                       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/cmd/tailscale/cli                              from tailscale.com/cmd/tailscale
         tailscale.com/control/controlbase                            from tailscale.com/control/controlhttp

+ 1 - 1
cmd/tailscaled/depaware.txt

@@ -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/apitype                       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/cmd/tailscaled/childproc                       from tailscale.com/ssh/tailssh+
         tailscale.com/control/controlbase                            from tailscale.com/control/controlclient+