bastion 0.53.2
This commit is contained in:
@@ -0,0 +1,92 @@
|
||||
//go:build windows
|
||||
|
||||
package main
|
||||
|
||||
// WHO STANDS BEHIND THE ANCHOR, ON WINDOWS.
|
||||
//
|
||||
// Every machine-authority decision in this binary asks one question: does the
|
||||
// caller administer this box? On Unix that is euid 0. On Windows there is no
|
||||
// euid at all — Go's syscall package answers `Geteuid() (euid int) { return -1 }`
|
||||
// unconditionally (syscall_windows.go), so the historic `os.Geteuid() != 0` gate
|
||||
// was not "needs admin" on Windows, it was PERMANENTLY CLOSED. Running as
|
||||
// Administrator made no difference; nothing could ever satisfy it.
|
||||
//
|
||||
// That silently made three things impossible on every Windows install:
|
||||
// `set-mode networked`, `claim-anchor`, and `claim-owner`. A Windows machine
|
||||
// could therefore never be a networked bastion and never be anchored — so the
|
||||
// whole anchor-governed model (a machine several hosts share, later pairings
|
||||
// held pending until the anchor approves) was Linux-only by accident rather than
|
||||
// by decision.
|
||||
//
|
||||
// The Windows equivalent of "root on this machine" is a process that is BOTH
|
||||
// running elevated AND whose token carries the local Administrators group. Both
|
||||
// halves are needed and neither implies the other:
|
||||
//
|
||||
// - IsElevated alone would accept a token that was elevated in some other
|
||||
// context but is not an administrator of THIS machine.
|
||||
// - IsMember alone would accept an un-elevated admin user. On such a token the
|
||||
// Administrators group is present but DENY-only, which is exactly the UAC
|
||||
// split-token state — the user COULD administer the box but this process is
|
||||
// not doing so. Treating that as authority would let any admin-account
|
||||
// process anchor a machine without ever passing a UAC prompt, which is the
|
||||
// consent step that makes "root stands behind the anchor" mean anything.
|
||||
//
|
||||
// LocalSystem (a service) satisfies both, which is correct: a machine-wide
|
||||
// service is exactly the networked bastion's shape.
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
// processIsRoot reports whether this process administers the machine.
|
||||
//
|
||||
// Fails CLOSED: any error asking the question answers "no". An authority check
|
||||
// that cannot be completed has not been passed.
|
||||
func processIsRoot() bool {
|
||||
ok, err := machineAuthority()
|
||||
if err != nil {
|
||||
// SAY SO. A silent "no" here is the exact bug this file exists to fix,
|
||||
// one layer down: an administrator would read "run as Administrator"
|
||||
// while already in an elevated terminal, with nothing anywhere saying
|
||||
// the check itself failed to run.
|
||||
fmt.Printf("privilege: cannot determine machine authority on this system: %v\n", err)
|
||||
return false
|
||||
}
|
||||
return ok
|
||||
}
|
||||
|
||||
// machineAuthority is the check itself, with its failure kept distinguishable
|
||||
// from a plain "no".
|
||||
func machineAuthority() (bool, error) {
|
||||
// TokenElevation off the process pseudo-handle is a GetTokenInformation
|
||||
// read, which a PRIMARY token answers fine.
|
||||
if !windows.GetCurrentProcessToken().IsElevated() {
|
||||
return false, nil
|
||||
}
|
||||
sid, err := windows.CreateWellKnownSid(windows.WinBuiltinAdministratorsSid)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("cannot build the Administrators SID: %w", err)
|
||||
}
|
||||
// Token(0) — a NULL handle — NOT GetCurrentProcessToken().
|
||||
//
|
||||
// IsMember hands its receiver straight to CheckTokenMembership
|
||||
// (x/sys@v0.46.0/windows/security_windows.go:832-838), and that API takes an
|
||||
// IMPERSONATION token; a primary token is refused with
|
||||
// ERROR_NO_IMPERSONATION_TOKEN. GetCurrentProcessToken returns the PRIMARY
|
||||
// token's pseudo-handle (:664-669) — so asking it this way would have
|
||||
// errored for a genuine elevated administrator and, under the fail-closed
|
||||
// rule above, answered "no". The gate this whole change exists to OPEN would
|
||||
// have stayed shut, indistinguishably from a real refusal.
|
||||
//
|
||||
// Passing NULL is the documented way to avoid that: the API duplicates the
|
||||
// calling thread's token into an impersonation token itself. It is also what
|
||||
// .NET's WindowsIdentity.IsInRole does internally, which is why the
|
||||
// PowerShell check in install.ps1 works while this one would not have.
|
||||
member, err := windows.Token(0).IsMember(sid)
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("CheckTokenMembership failed: %w", err)
|
||||
}
|
||||
return member, nil
|
||||
}
|
||||
Reference in New Issue
Block a user