ipn/ipnauth: improve the Windows token administrator check

(*Token).IsAdministrator is supposed to return true even when the user is
running with a UAC limited token. The idea is that, for the purposes of
this check, we don't care whether the user is *currently* running with
full Admin rights, we just want to know whether the user can
*potentially* do so.

We accomplish this by querying for the token's "linked token," which
should be the fully-elevated variant, and checking its group memberships.

We also switch ipn/ipnserver/(*Server).connIsLocalAdmin to use the elevation
check to preserve those semantics for tailscale serve; I want the
IsAdministrator check to be used for less sensitive things like toggling
auto-update on and off.

Fixes #10036

Signed-off-by: Aaron Klotz <aaron@tailscale.com>
This commit is contained in:
Aaron Klotz
2023-10-31 14:37:04 -06:00
parent e5dcf7bdde
commit fbc18410ad
3 changed files with 49 additions and 9 deletions

View File

@@ -367,6 +367,30 @@ func getTokenPrimaryGroupInfo(token windows.Token) (*windows.Tokenprimarygroup,
return (*windows.Tokenprimarygroup)(unsafe.Pointer(&buf[0])), nil
}
type tokenElevationType int32
const (
tokenElevationTypeDefault tokenElevationType = 1
tokenElevationTypeFull tokenElevationType = 2
tokenElevationTypeLimited tokenElevationType = 3
)
func getTokenElevationType(token windows.Token) (result tokenElevationType, err error) {
var actualLen uint32
p := (*byte)(unsafe.Pointer(&result))
err = windows.GetTokenInformation(token, windows.TokenElevationType, p, uint32(unsafe.Sizeof(result)), &actualLen)
return result, err
}
// IsTokenLimited returns whether token is a limited UAC token.
func IsTokenLimited(token windows.Token) (bool, error) {
elevationType, err := getTokenElevationType(token)
if err != nil {
return false, err
}
return elevationType == tokenElevationTypeLimited, nil
}
// UserSIDs contains the SIDs for a Windows NT token object's associated user
// as well as its primary group.
type UserSIDs struct {