mirror of
https://github.com/tailscale/tailscale.git
synced 2025-08-21 18:42:36 +00:00
util/winutil: add package for logging into Windows via Service-for-User (S4U)
This PR ties together pseudoconsoles, user profiles, s4u logons, and process creation into what is (hopefully) a simple API for various Tailscale services to obtain Windows access tokens without requiring knowledge of any Windows passwords. It works both for domain-joined machines (Kerberos) and non-domain-joined machines. The former case is fairly straightforward as it is fully documented. OTOH, the latter case is not documented, though it is fully defined in the C headers in the Windows SDK. The documentation blanks were filled in by reading the source code of Microsoft's Win32 port of OpenSSH. We need to do a bit of acrobatics to make conpty work correctly while creating a child process with an s4u token; see the doc comments above startProcessInternal for details. Updates #12383 Signed-off-by: Aaron Klotz <aaron@tailscale.com>
This commit is contained in:
@@ -23,8 +23,7 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrDefunctProcess is returned by (*UniqueProcess).AsRestartableProcess
|
||||
// when the process no longer exists.
|
||||
// ErrDefunctProcess is returned when the process no longer exists.
|
||||
ErrDefunctProcess = errors.New("process is defunct")
|
||||
// ErrProcessNotRestartable is returned by (*UniqueProcess).AsRestartableProcess
|
||||
// when the process has previously indicated that it must not be restarted
|
||||
@@ -799,7 +798,7 @@ func startProcessInSessionInternal(sessID SessionID, cmdLineInfo CommandLineInfo
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("token environment: %w", err)
|
||||
}
|
||||
env16 := newEnvBlock(env)
|
||||
env16 := NewEnvBlock(env)
|
||||
|
||||
// The privileges in privNames are required for CreateProcessAsUser to be
|
||||
// able to start processes as other users in other logon sessions.
|
||||
@@ -826,7 +825,11 @@ func startProcessInSessionInternal(sessID SessionID, cmdLineInfo CommandLineInfo
|
||||
return &pi, nil
|
||||
}
|
||||
|
||||
func newEnvBlock(env []string) *uint16 {
|
||||
// NewEnvBlock processes a slice of strings containing "NAME=value" pairs
|
||||
// representing a process envionment into the environment block format used by
|
||||
// Windows APIs such as CreateProcess. env must be sorted case-insensitively
|
||||
// by variable name.
|
||||
func NewEnvBlock(env []string) *uint16 {
|
||||
// Intentionally using bytes.Buffer here because we're writing nul bytes (the standard library does this too).
|
||||
var buf bytes.Buffer
|
||||
for _, v := range env {
|
||||
|
Reference in New Issue
Block a user