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

@@ -13,6 +13,7 @@ import (
"tailscale.com/ipn"
"tailscale.com/safesocket"
"tailscale.com/types/logger"
"tailscale.com/util/winutil"
)
// GetConnIdentity extracts the identity information from the connection
@@ -64,7 +65,28 @@ func (t *token) IsAdministrator() (bool, error) {
return false, err
}
return t.t.IsMember(baSID)
isMember, err := t.t.IsMember(baSID)
if err != nil {
return false, err
}
if isMember {
return true, nil
}
isLimited, err := winutil.IsTokenLimited(t.t)
if err != nil || !isLimited {
return false, err
}
// Try to obtain a linked token, and if present, check it.
// (This should be the elevated token associated with limited UAC accounts.)
linkedToken, err := t.t.GetLinkedToken()
if err != nil {
return false, err
}
defer linkedToken.Close()
return linkedToken.IsMember(baSID)
}
func (t *token) IsElevated() bool {