summaryrefslogtreecommitdiffhomepage
path: root/ipn/ipnauth
AgeCommit message (Collapse)AuthorFilesLines
2026-01-23all: remove AUTHORS file and references to itWill Norris10-10/+10
This file was never truly necessary and has never actually been used in the history of Tailscale's open source releases. A Brief History of AUTHORS files --- The AUTHORS file was a pattern developed at Google, originally for Chromium, then adopted by Go and a bunch of other projects. The problem was that Chromium originally had a copyright line only recognizing Google as the copyright holder. Because Google (and most open source projects) do not require copyright assignemnt for contributions, each contributor maintains their copyright. Some large corporate contributors then tried to add their own name to the copyright line in the LICENSE file or in file headers. This quickly becomes unwieldy, and puts a tremendous burden on anyone building on top of Chromium, since the license requires that they keep all copyright lines intact. The compromise was to create an AUTHORS file that would list all of the copyright holders. The LICENSE file and source file headers would then include that list by reference, listing the copyright holder as "The Chromium Authors". This also become cumbersome to simply keep the file up to date with a high rate of new contributors. Plus it's not always obvious who the copyright holder is. Sometimes it is the individual making the contribution, but many times it may be their employer. There is no way for the proejct maintainer to know. Eventually, Google changed their policy to no longer recommend trying to keep the AUTHORS file up to date proactively, and instead to only add to it when requested: https://opensource.google/docs/releasing/authors. They are also clear that: > Adding contributors to the AUTHORS file is entirely within the > project's discretion and has no implications for copyright ownership. It was primarily added to appease a small number of large contributors that insisted that they be recognized as copyright holders (which was entirely their right to do). But it's not truly necessary, and not even the most accurate way of identifying contributors and/or copyright holders. In practice, we've never added anyone to our AUTHORS file. It only lists Tailscale, so it's not really serving any purpose. It also causes confusion because Tailscalars put the "Tailscale Inc & AUTHORS" header in other open source repos which don't actually have an AUTHORS file, so it's ambiguous what that means. Instead, we just acknowledge that the contributors to Tailscale (whoever they are) are copyright holders for their individual contributions. We also have the benefit of using the DCO (developercertificate.org) which provides some additional certification of their right to make the contribution. The source file changes were purely mechanical with: git ls-files | xargs sed -i -e 's/\(Tailscale Inc &\) AUTHORS/\1 contributors/g' Updates #cleanup Change-Id: Ia101a4a3005adb9118051b3416f5a64a4a45987d Signed-off-by: Will Norris <will@tailscale.com>
2025-12-23ipn/ipnauth, safesocket: defer named pipe client's token retrieval until ↵Nick Khyl1-18/+11
ipnserver needs it An error returned by net.Listener.Accept() causes the owning http.Server to shut down. With the deprecation of net.Error.Temporary(), there's no way for the http.Server to test whether the returned error is temporary / retryable or not (see golang/go#66252). Because of that, errors returned by (*safesocket.winIOPipeListener).Accept() cause the LocalAPI server (aka ipnserver.Server) to shut down, and tailscaled process to exit. While this might be acceptable in the case of non-recoverable errors, such as programmer errors, we shouldn't shut down the entire tailscaled process for client- or connection-specific errors, such as when we couldn't obtain the client's access token because the client attempts to connect at the Anonymous impersonation level. Instead, the LocalAPI server should gracefully handle these errors by denying access and returning a 401 Unauthorized to the client. In tailscale/tscert#15, we fixed a known bug where Caddy and other apps using tscert would attempt to connect at the Anonymous impersonation level and fail. However, we should also fix this on the tailscaled side to prevent a potential DoS, where a local app could deliberately open the Tailscale LocalAPI named pipe at the Anonymous impersonation level and cause tailscaled to exit. In this PR, we defer token retrieval until (*WindowsClientConn).Token() is called and propagate the returned token or error via ipnauth.GetConnIdentity() to ipnserver, which handles it the same way as other ipnauth-related errors. Fixes #18212 Fixes tailscale/tscert#13 Signed-off-by: Nick Khyl <nickk@tailscale.com>
2025-10-03all: use buildfeature constants in a few more placesBrad Fitzpatrick2-0/+12
Saves 21 KB. Updates #12614 Change-Id: I0cd3e735937b0f5c0fcc9f09a24476b1c4ac9a15 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
2025-10-03ipn/ipnauth: fix a null pointer panic in GetConnIdentityAlex Chan1-2/+3
When running integration tests on macOS, we get a panic from a nil pointer dereference when calling `ci.creds.PID()`. This panic occurs because the `ci.creds != nil` check is insufficient after a recent refactoring (c45f881) that changed `ci.creds` from a pointer to the `PeerCreds` interface. Now `ci.creds` always compares as non-nil, so we enter this block even when the underlying value is nil. The integration tests fail on macOS when `peercred.Get()` returns the error `unix.GetsockoptInt: socket is not connected`. This error isn't new, and the previous code was ignoring it correctly. Since we trust that `peercred` returns either a usable value or an error, checking for a nil error is a sufficient and correct gate to prevent the method call and avoid the panic. Fixes #17421 Signed-off-by: Alex Chan <alexc@tailscale.com>
2025-10-02feature/featuretags, all: add build features, use existing ones in more placesBrad Fitzpatrick3-7/+40
Saves 270 KB. Updates #12614 Change-Id: I4c3fe06d32c49edb3a4bb0758a8617d83f291cf5 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
2025-09-21ipn/ipnauth: don't crash on OpenBSD trying to log username of unknown peerBrad Fitzpatrick2-2/+7
We never implemented the peercred package on OpenBSD (and I just tried again and failed), but we've always documented that the creds pointer can be nil for operating systems where we can't map the unix socket back to its UID. On those platforms, we set the default unix socket permissions such that only the admin can open it anyway and we don't have a read-only vs read-write distinction. OpenBSD was always in that camp, where any access to Tailscale's unix socket meant full access. But during some refactoring, we broke OpenBSD in that we started assuming during one logging path (during login) that Creds was non-nil when looking up an ipnauth.Actor's username, which wasn't relevant (it was called from a function "maybeUsernameOf" anyway, which threw away errors). Verified on an OpenBSD VM. We don't have any OpenBSD integration tests yet. Fixes #17209 Updates #17221 Change-Id: I473c5903dfaa645694bcc75e7f5d484f3dd6044d Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
2025-09-02util/syspolicy: finish plumbing policyclient, add feature/syspolicy, move ↵Brad Fitzpatrick1-3/+3
global impl This is step 4 of making syspolicy a build-time feature. This adds a policyclient.Get() accessor to return the correct implementation to use: either the real one, or the no-op one. (A third type, a static one for testing, also exists, so in general a policyclient.Client should be plumbed around and not always fetched via policyclient.Get whenever possible, especially if tests need to use alternate syspolicy) Updates #16998 Updates #12614 Change-Id: Iaf19670744a596d5918acfa744f5db4564272978 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
2025-08-31util/syspolicy/*: move syspolicy keys to new const leaf "pkey" packageBrad Fitzpatrick1-2/+3
This is step 1 of ~3, breaking up #14720 into reviewable chunks, with the aim to make syspolicy be a build-time configurable feature. In this first (very noisy) step, all the syspolicy string key constants move to a new constant-only (code-free) package. This will make future steps more reviewable, without this movement noise. There are no code or behavior changes here. The future steps of this series can be seen in #14720: removing global funcs from syspolicy resolution and using an interface that's plumbed around instead. Then adding build tags. Updates #12614 Change-Id: If73bf2c28b9c9b1a408fe868b0b6a25b03eeabd1 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
2025-07-07ipn/{ipnauth,ipnlocal,localapi}: make EditPrefs return an error if changing ↵Nick Khyl1-0/+12
exit node is restricted by policy We extract checkEditPrefsAccessLocked, adjustEditPrefsLocked, and onEditPrefsLocked from the EditPrefs execution path, defining when each step is performed and what behavior is allowed at each stage. Currently, this is primarily used to support Always On mode, to handle the Exit Node enablement toggle, and to report prefs edit metrics. We then use it to enforce Exit Node policy settings by preventing users from setting an exit node and making EditPrefs return an error when an exit node is restricted by policy. This enforcement is also extended to the Exit Node toggle. These changes prepare for supporting Exit Node overrides when permitted by policy and preventing logout while Always On mode is enabled. In the future, implementation of these methods can be delegated to ipnext extensions via the feature hooks. Updates tailscale/corp#29969 Updates tailscale/corp#26249 Signed-off-by: Nick Khyl <nickk@tailscale.com>
2025-03-12control/controlclient, ipn: add client audit logging (#14950)Jonathan Nobels2-8/+9
updates tailscale/corp#26435 Adds client support for sending audit logs to control via /machine/audit-log. Specifically implements audit logging for user initiated disconnections. This will require further work to optimize the peristant storage and exclusion via build tags for mobile: tailscale/corp#27011 tailscale/corp#27012 Signed-off-by: Jonathan Nobels <jonathan@tailscale.com>
2025-02-11ipn/ipnauth: implement WindowsActorNick Khyl2-3/+109
WindowsActor is an ipnauth.Actor implementation that represents a logged-in Windows user by wrapping their Windows user token. Updates #14823 Signed-off-by: Nick Khyl <nickk@tailscale.com>
2025-02-11ipn/ipn{auth,server}: update ipnauth.Actor to carry a contextNick Khyl4-6/+74
The context carries additional information about the actor, such as the request reason, and is canceled when the actor is done. Additionally, we implement three new ipn.Actor types that wrap other actors to modify their behavior: - WithRequestReason, which adds a request reason to the actor; - WithoutClose, which narrows the actor's interface to prevent it from being closed; - WithPolicyChecks, which adds policy checks to the actor's CheckProfileAccess method. Updates #14823 Signed-off-by: Nick Khyl <nickk@tailscale.com>
2025-02-04ipn/{ipnauth,ipnlocal,ipnserver}: move the AlwaysOn policy check from ↵Nick Khyl4-3/+57
ipnserver to ipnauth In this PR, we move the code that checks the AlwaysOn policy from ipnserver.actor to ipnauth. It is intended to be used by ipnauth.Actor implementations, and we temporarily make it exported while these implementations reside in ipnserver and in corp. We'll unexport it later. We also update [ipnauth.Actor.CheckProfileAccess] to accept an auditLogger, which is called to write details about the action to the audit log when required by the policy, and update LocalBackend.EditPrefsAs to use an auditLogger that writes to the regular backend log. Updates tailscale/corp#26146 Signed-off-by: Nick Khyl <nickk@tailscale.com>
2025-01-31ipn/ipnauth,util/syspolicy: improve commentsNick Khyl2-3/+7
Updates #cleanup Updates #14823 Signed-off-by: Nick Khyl <nickk@tailscale.com>
2025-01-31ipn/ipn{auth,server,local}: initial support for the always-on modeNick Khyl1-0/+6
In this PR, we update LocalBackend to set WantRunning=true when applying policy settings to the current profile's prefs, if the "always-on" mode is enabled. We also implement a new (*LocalBackend).EditPrefsAs() method, which is like EditPrefs but accepts an actor (e.g., a LocalAPI client's identity) that initiated the change. If WantRunning is being set to false, the new EditPrefsAs method checks whether the actor has ipnauth.Disconnect access to the profile and propagates an error if they do not. Finally, we update (*ipnserver.actor).CheckProfileAccess to allow a disconnect only if the "always-on" mode is not enabled by the AlwaysOn policy setting. This is not a comprehensive solution to the "always-on" mode across platforms, as instead of disconnecting a user could achieve the same effect by creating a new empty profile, initiating a reauth, or by deleting the profile. These are the things we should address in future PRs. Updates #14823 Signed-off-by: Nick Khyl <nickk@tailscale.com>
2025-01-31ipn/ipnauth: implement an Actor representing tailscaled itselfNick Khyl1-0/+46
Updates #14823 Signed-off-by: Nick Khyl <nickk@tailscale.com>
2025-01-31ipn/{ipnauth, ipnserver}: extend the ipnauth.Actor interface with a ↵Nick Khyl3-1/+19
CheckProfileAccess method The implementations define it to verify whether the actor has the requested access to a login profile. Updates #14823 Signed-off-by: Nick Khyl <nickk@tailscale.com>
2025-01-14ipn/{ipnauth,ipnlocal,ipnserver}, client/tailscale: make ipnserver.Server ↵Nick Khyl1-0/+13
testable We update client/tailscale.LocalClient to allow specifying an optional Transport (http.RoundTripper) for LocalAPI HTTP requests, and implement one that injects an ipnauth.TestActor via request headers. We also add several functions and types to make testing an ipn/ipnserver.Server possible (or at least easier). We then use these updates to write basic tests for ipnserver.Server, ensuring it works on non-Windows platforms and correctly sets and unsets the LocalBackend's current user when a Windows user connects and disconnects. We intentionally omit tests for switching between different OS users and will add them in follow-up commits. Updates tailscale/corp#25804 Signed-off-by: Nick Khyl <nickk@tailscale.com>
2024-10-18ipn/{ipnauth,ipnlocal,ipnserver}: send the auth URL to the user who started ↵Nick Khyl3-1/+70
interactive login We add the ClientID() method to the ipnauth.Actor interface and updated ipnserver.actor to implement it. This method returns a unique ID of the connected client if the actor represents one. It helps link a series of interactions initiated by the client, such as when a notification needs to be sent back to a specific session, rather than all active sessions, in response to a certain request. We also add LocalBackend.WatchNotificationsAs and LocalBackend.StartLoginInteractiveAs methods, which are like WatchNotifications and StartLoginInteractive but accept an additional parameter specifying an ipnauth.Actor who initiates the operation. We store these actor identities in watchSession.owner and LocalBackend.authActor, respectively,and implement LocalBackend.sendTo and related helper methods to enable sending notifications to watchSessions associated with actors (or, more broadly, identifiable recipients). We then use the above to change who receives the BrowseToURL notifications: - For user-initiated, interactive logins, the notification is delivered only to the user who initiated the process. If the initiating actor represents a specific connected client, the URL notification is sent back to the same LocalAPI client that called StartLoginInteractive. Otherwise, the notification is sent to all clients connected as that user. Currently, we only differentiate between users on Windows, as it is inherently a multi-user OS. - In all other cases (e.g., node key expiration), we send the notification to all connected users. Updates tailscale/corp#18342 Signed-off-by: Nick Khyl <nickk@tailscale.com>
2024-08-28ipn/{ipnauth,ipnlocal,ipnserver,localapi}: start baby step toward moving ↵Nick Khyl1-0/+47
access checks from the localapi.Handler to the LocalBackend Currently, we use PermitRead/PermitWrite/PermitCert permission flags to determine which operations are allowed for a LocalAPI client. These checks are performed when localapi.Handler handles a request. Additionally, certain operations (e.g., changing the serve config) requires the connected user to be a local admin. This approach is inherently racey and is subject to TOCTOU issues. We consider it to be more critical on Windows environments, which are inherently multi-user, and therefore we prevent more than one OS user from connecting and utilizing the LocalBackend at the same time. However, the same type of issues is also applicable to other platforms when switching between profiles that have different OperatorUser values in ipn.Prefs. We'd like to allow more than one Windows user to connect, but limit what they can see and do based on their access rights on the device (e.g., an local admin or not) and to the currently active LoginProfile (e.g., owner/operator or not), while preventing TOCTOU issues on Windows and other platforms. Therefore, we'd like to pass an actor from the LocalAPI to the LocalBackend to represent the user performing the operation. The LocalBackend, or the profileManager down the line, will then check the actor's access rights to perform a given operation on the device and against the current (and/or the target) profile. This PR does not change the current permission model in any way, but it introduces the concept of an actor and includes some preparatory work to pass it around. Temporarily, the ipnauth.Actor interface has methods like IsLocalSystem and IsLocalAdmin, which are only relevant to the current permission model. It also lacks methods that will actually be used in the new model. We'll be adding these gradually in the next PRs and removing the deprecated methods and the Permit* flags at the end of the transition. Updates tailscale/corp#18342 Signed-off-by: Nick Khyl <nickk@tailscale.com>
2024-02-13go.mod, all: move away from inet.af domain seized by TalibanBrad Fitzpatrick2-2/+2
Updates inetaf/tcpproxy#39 Change-Id: I7fee276b116bd08397347c6c949011d76a2842cf Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
2024-01-12ipn/ipnserver: always allow Windows SYSTEM user to connectWill Norris2-0/+8
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>
2023-12-21all: cleanup unused code, part 2 (#10670)Andrew Lytvynov2-12/+1
And enable U1000 check in staticcheck. Updates #cleanup Signed-off-by: Andrew Lytvynov <awly@tailscale.com>
2023-11-03ipn/ipnauth: improve the Windows token administrator checkAaron Klotz1-1/+23
(*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>
2023-10-26ipn, safesocket: use Windows token in LocalAPIAaron Klotz3-35/+176
On Windows, the idiomatic way to check access on a named pipe is for the server to impersonate the client on its current OS thread, perform access checks using the client's access token, and then revert the OS thread's access token back to its true self. The access token is a better representation of the client's rights than just a username/userid check, as it represents the client's effective rights at connection time, which might differ from their normal rights. This patch updates safesocket to do the aforementioned impersonation, extract the token handle, and then revert the impersonation. We retain the token handle for the remaining duration of the connection (the token continues to be valid even after we have reverted back to self). Since the token is a property of the connection, I changed ipnauth to wrap the concrete net.Conn to include the token. I then plumbed that change through ipnlocal, ipnserver, and localapi as necessary. I also added a PermitLocalAdmin flag to the localapi Handler which I intend to use for controlling access to a few new localapi endpoints intended for configuring auto-update. Updates https://github.com/tailscale/tailscale/issues/755 Signed-off-by: Aaron Klotz <aaron@tailscale.com>
2023-01-27all: update copyright and license headersWill Norris3-9/+6
This updates all source files to use a new standard header for copyright and license declaration. Notably, copyright no longer includes a date, and we now use the standard SPDX-License-Identifier header. This commit was done almost entirely mechanically with perl, and then some minimal manual fixes. Updates #6865 Signed-off-by: Will Norris <will@tailscale.com>
2022-11-30all: use named pipes on windowsMaisem Ali3-51/+83
Signed-off-by: Maisem Ali <maisem@tailscale.com>
2022-11-28ipn/ipnauth, util/winutil: add temporary LookupPseudoUser workaround to ↵Aaron Klotz1-2/+15
address os/user.LookupId errors on Windows I added util/winutil/LookupPseudoUser, which essentially consists of the bits that I am in the process of adding to Go's standard library. We check the provided SID for "S-1-5-x" where 17 <= x <= 20 (which are the known pseudo-users) and then manually populate a os/user.User struct with the correct information. Fixes https://github.com/tailscale/tailscale/issues/869 Fixes https://github.com/tailscale/tailscale/issues/2894 Signed-off-by: Aaron Klotz <aaron@tailscale.com>
2022-11-27ipn/*: make new WindowsUserID type to consolidate docsBrad Fitzpatrick1-8/+22
The "userID is empty everywhere but Windows" docs on lots of places but not everywhere while using just a string type was getting confusing. This makes a new type to wrap up those rules, however weird/historical they might be. Change-Id: I142e85a8e38760988d6c0c91d0efecedade81b9b Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
2022-11-26ipn/ipnserver: remove protoSwitchConn shenanigans; just use http.Server earlyBrad Fitzpatrick1-1/+0
Now that everything's just HTTP, there's no longer a need to have a header-sniffing net.Conn wraper that dispatches which route to take. Refactor to just use an http.Server earlier instead. Updates #6417 Change-Id: I12a2054db4e56f48660c46f81233db224fdc77cb Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
2022-11-25ipn/ipnserver: move more connection acceptance logic to LocalBackendBrad Fitzpatrick1-1/+10
Follow-up to #6467 and #6506. LocalBackend knows the server-mode state, so move more auth checking there, removing some bookkeeping from ipnserver.Server. Updates #6417 Updates tailscale/corp#8051 Change-Id: Ic5d14a077bf0dccc92a3621bd2646bab2cc5b837 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
2022-11-23ipn/ipnauth: start splitting ipnserver into new ipnauth packageBrad Fitzpatrick1-0/+204
We're trying to gut 90% of the ipnserver package. A lot will get deleted, some will move to LocalBackend, and a lot is being moved into this new ipn/ipnauth package which will be leaf-y and testable. This is a baby step towards moving some stuff to ipnauth. Update #6417 Updates tailscale/corp#8051 Change-Id: I28bc2126764f46597d92a2d72565009dc6927ee0 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>