mirror of
https://github.com/tailscale/tailscale.git
synced 2024-11-30 05:25:35 +00:00
095d3edd33
This fix does not seem ideal, but the test infrastructure using a local goos doesn't seem to avoid all of the associated challenges, but is somewhat deeply tied to the setup. The core issue this addresses for now is that when run on Windows there can be no code paths that attempt to use an invalid UID string, which on Windows is described in [1]. For the goos="linux" tests, we now explicitly skip the affected migration code if runtime.GOOS=="windows", and for the Windows test we explicitly use the running users uid, rather than just the string "user1". We also now make the case where a profile exists and has already been migrated a non-error condition toward the outer API. Updates #7876 [1] https://learn.microsoft.com/en-us/windows-server/identity/ad-ds/manage/understand-security-identifiers Signed-off-by: James Tucker <jftucker@gmail.com>
87 lines
2.5 KiB
Go
87 lines
2.5 KiB
Go
// Copyright (c) Tailscale Inc & AUTHORS
|
|
// SPDX-License-Identifier: BSD-3-Clause
|
|
|
|
package ipnlocal
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"io/fs"
|
|
"os"
|
|
"os/user"
|
|
"path/filepath"
|
|
|
|
"tailscale.com/atomicfile"
|
|
"tailscale.com/ipn"
|
|
"tailscale.com/util/winutil/policy"
|
|
)
|
|
|
|
const (
|
|
legacyPrefsFile = "prefs"
|
|
legacyPrefsMigrationSentinelFile = "_migrated-to-profiles"
|
|
legacyPrefsExt = ".conf"
|
|
)
|
|
|
|
func legacyPrefsDir(uid ipn.WindowsUserID) (string, error) {
|
|
// TODO(aaron): Ideally we'd have the impersonation token for the pipe's
|
|
// client and use it to call SHGetKnownFolderPath, thus yielding the correct
|
|
// path without having to make gross assumptions about directory names.
|
|
usr, err := user.LookupId(string(uid))
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
if usr.HomeDir == "" {
|
|
return "", fmt.Errorf("user %q does not have a home directory", uid)
|
|
}
|
|
userLegacyPrefsDir := filepath.Join(usr.HomeDir, "AppData", "Local", "Tailscale")
|
|
return userLegacyPrefsDir, nil
|
|
}
|
|
|
|
func (pm *profileManager) loadLegacyPrefs() (string, ipn.PrefsView, error) {
|
|
userLegacyPrefsDir, err := legacyPrefsDir(pm.currentUserID)
|
|
if err != nil {
|
|
return "", ipn.PrefsView{}, err
|
|
}
|
|
|
|
migrationSentinel := filepath.Join(userLegacyPrefsDir, legacyPrefsMigrationSentinelFile+legacyPrefsExt)
|
|
// verify that migration sentinel is not present
|
|
_, err = os.Stat(migrationSentinel)
|
|
if err == nil {
|
|
return "", ipn.PrefsView{}, errAlreadyMigrated
|
|
}
|
|
if !os.IsNotExist(err) {
|
|
return "", ipn.PrefsView{}, err
|
|
}
|
|
|
|
prefsPath := filepath.Join(userLegacyPrefsDir, legacyPrefsFile+legacyPrefsExt)
|
|
prefs, err := ipn.LoadPrefs(prefsPath)
|
|
if errors.Is(err, fs.ErrNotExist) {
|
|
return "", ipn.PrefsView{}, errAlreadyMigrated
|
|
}
|
|
if err != nil {
|
|
return "", ipn.PrefsView{}, err
|
|
}
|
|
|
|
prefs.ControlURL = policy.SelectControlURL(defaultPrefs.ControlURL(), prefs.ControlURL)
|
|
prefs.ExitNodeIP = resolveExitNodeIP(prefs.ExitNodeIP)
|
|
prefs.ShieldsUp = resolveShieldsUp(prefs.ShieldsUp)
|
|
prefs.ForceDaemon = resolveForceDaemon(prefs.ForceDaemon)
|
|
|
|
pm.logf("migrating Windows profile to new format")
|
|
return migrationSentinel, prefs.View(), nil
|
|
}
|
|
|
|
func (pm *profileManager) completeMigration(migrationSentinel string) {
|
|
atomicfile.WriteFile(migrationSentinel, []byte{}, 0600)
|
|
}
|
|
|
|
func resolveShieldsUp(defval bool) bool {
|
|
pol := policy.GetPreferenceOptionPolicy("AllowIncomingConnections")
|
|
return !pol.ShouldEnable(!defval)
|
|
}
|
|
|
|
func resolveForceDaemon(defval bool) bool {
|
|
pol := policy.GetPreferenceOptionPolicy("UnattendedMode")
|
|
return pol.ShouldEnable(defval)
|
|
}
|