mirror of
https://github.com/tailscale/tailscale.git
synced 2025-01-08 09:07:44 +00:00
ipn/ipnserver: always allow Windows SYSTEM user to connect
When establishing connections to the ipnserver, we validate that the local user is allowed to connect. If Tailscale is currently being managed by a different user (primarily for multi-user Windows installs), we don't allow the connection. With the new device web UI, the inbound connection is coming from tailscaled itself, which is often running as "NT AUTHORITY\SYSTEM". In this case, we still want to allow the connection, even though it doesn't match the user running the Tailscale GUI. The SYSTEM user has full access to everything on the system anyway, so this doesn't escalate privileges. Eventually, we want the device web UI to run outside of the tailscaled process, at which point this exception would probably not be needed. Updates tailscale/corp#16393 Signed-off-by: Will Norris <will@tailscale.com>
This commit is contained in:
parent
7100b6e721
commit
236531c5fc
@ -46,6 +46,8 @@ type WindowsToken interface {
|
|||||||
// IsElevated reports whether the receiver is currently executing as an
|
// IsElevated reports whether the receiver is currently executing as an
|
||||||
// elevated administrative user.
|
// elevated administrative user.
|
||||||
IsElevated() bool
|
IsElevated() bool
|
||||||
|
// IsLocalSystem reports whether the receiver is the built-in SYSTEM user.
|
||||||
|
IsLocalSystem() bool
|
||||||
// UserDir returns the special directory identified by folderID as associated
|
// UserDir returns the special directory identified by folderID as associated
|
||||||
// with the receiver. folderID must be one of the KNOWNFOLDERID values from
|
// with the receiver. folderID must be one of the KNOWNFOLDERID values from
|
||||||
// the x/sys/windows package, serialized as a stringified GUID.
|
// the x/sys/windows package, serialized as a stringified GUID.
|
||||||
|
@ -93,6 +93,12 @@ func (t *token) IsElevated() bool {
|
|||||||
return t.t.IsElevated()
|
return t.t.IsElevated()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t *token) IsLocalSystem() bool {
|
||||||
|
// https://web.archive.org/web/2024/https://learn.microsoft.com/en-us/windows-server/identity/ad-ds/manage/understand-security-identifiers
|
||||||
|
const systemUID = ipn.WindowsUserID("S-1-5-18")
|
||||||
|
return t.IsUID(systemUID)
|
||||||
|
}
|
||||||
|
|
||||||
func (t *token) UserDir(folderID string) (string, error) {
|
func (t *token) UserDir(folderID string) (string, error) {
|
||||||
guid, err := windows.GUIDFromString(folderID)
|
guid, err := windows.GUIDFromString(folderID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -2735,6 +2735,16 @@ func (b *LocalBackend) CheckIPNConnectionAllowed(ci *ipnauth.ConnIdentity) error
|
|||||||
if !b.pm.CurrentPrefs().ForceDaemon() {
|
if !b.pm.CurrentPrefs().ForceDaemon() {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Always allow Windows SYSTEM user to connect,
|
||||||
|
// even if Tailscale is currently being used by another user.
|
||||||
|
if tok, err := ci.WindowsToken(); err == nil {
|
||||||
|
defer tok.Close()
|
||||||
|
if tok.IsLocalSystem() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
uid := ci.WindowsUserID()
|
uid := ci.WindowsUserID()
|
||||||
if uid == "" {
|
if uid == "" {
|
||||||
return errors.New("empty user uid in connection identity")
|
return errors.New("empty user uid in connection identity")
|
||||||
|
@ -251,6 +251,12 @@ func (s *Server) checkConnIdentityLocked(ci *ipnauth.ConnIdentity) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Always allow Windows SYSTEM user to connect,
|
||||||
|
// even if Tailscale is currently being used by another user.
|
||||||
|
if chkTok != nil && chkTok.IsLocalSystem() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
activeTok, err := active.WindowsToken()
|
activeTok, err := active.WindowsToken()
|
||||||
if err == nil {
|
if err == nil {
|
||||||
defer activeTok.Close()
|
defer activeTok.Close()
|
||||||
@ -401,8 +407,10 @@ func (s *Server) addActiveHTTPRequest(req *http.Request, ci *ipnauth.ConnIdentit
|
|||||||
if !errors.Is(err, ipnauth.ErrNotImplemented) {
|
if !errors.Is(err, ipnauth.ErrNotImplemented) {
|
||||||
s.logf("error obtaining access token: %v", err)
|
s.logf("error obtaining access token: %v", err)
|
||||||
}
|
}
|
||||||
} else {
|
} else if !token.IsLocalSystem() {
|
||||||
// Tell the LocalBackend about the identity we're now running as.
|
// Tell the LocalBackend about the identity we're now running as,
|
||||||
|
// unless its the SYSTEM user. That user is not a real account and
|
||||||
|
// doesn't have a home directory.
|
||||||
uid, err := lb.SetCurrentUser(token)
|
uid, err := lb.SetCurrentUser(token)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
token.Close()
|
token.Close()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user