| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192 |
- // Copyright (c) Tailscale Inc & AUTHORS
- // SPDX-License-Identifier: BSD-3-Clause
- package syspolicy
- import (
- "errors"
- "fmt"
- "os/user"
- "tailscale.com/util/syspolicy/internal"
- "tailscale.com/util/syspolicy/rsop"
- "tailscale.com/util/syspolicy/setting"
- "tailscale.com/util/syspolicy/source"
- "tailscale.com/util/testenv"
- )
- func init() {
- // On Windows, we should automatically register the Registry-based policy
- // store for the device. If we are running in a user's security context
- // (e.g., we're the GUI), we should also register the Registry policy store for
- // the user. In the future, we should register (and unregister) user policy
- // stores whenever a user connects to (or disconnects from) the local backend.
- // This ensures the backend is aware of the user's policy settings and can send
- // them to the GUI/CLI/Web clients on demand or whenever they change.
- //
- // Other platforms, such as macOS, iOS and Android, should register their
- // platform-specific policy stores via [RegisterStore]
- // (or [RegisterHandler] until they implement the [source.Store] interface).
- //
- // External code, such as the ipnlocal package, may choose to register
- // additional policy stores, such as config files and policies received from
- // the control plane.
- internal.Init.MustDefer(func() error {
- // Do not register or use default policy stores during tests.
- // Each test should set up its own necessary configurations.
- if testenv.InTest() {
- return nil
- }
- return configureSyspolicy(nil)
- })
- }
- // configureSyspolicy configures syspolicy for use on Windows,
- // either in test or regular builds depending on whether tb has a non-nil value.
- func configureSyspolicy(tb testenv.TB) error {
- const localSystemSID = "S-1-5-18"
- // Always create and register a machine policy store that reads
- // policy settings from the HKEY_LOCAL_MACHINE registry hive.
- machineStore, err := source.NewMachinePlatformPolicyStore()
- if err != nil {
- return fmt.Errorf("failed to create the machine policy store: %v", err)
- }
- if tb == nil {
- _, err = rsop.RegisterStore("Platform", setting.DeviceScope, machineStore)
- } else {
- _, err = rsop.RegisterStoreForTest(tb, "Platform", setting.DeviceScope, machineStore)
- }
- if err != nil {
- return err
- }
- // Check whether the current process is running as Local System or not.
- u, err := user.Current()
- if err != nil {
- return err
- }
- if u.Uid == localSystemSID {
- return nil
- }
- // If it's not a Local System's process (e.g., it's the GUI rather than the tailscaled service),
- // we should create and use a policy store for the current user that reads
- // policy settings from that user's registry hive (HKEY_CURRENT_USER).
- userStore, err := source.NewUserPlatformPolicyStore(0)
- if err != nil {
- return fmt.Errorf("failed to create the current user's policy store: %v", err)
- }
- if tb == nil {
- _, err = rsop.RegisterStore("Platform", setting.CurrentUserScope, userStore)
- } else {
- _, err = rsop.RegisterStoreForTest(tb, "Platform", setting.CurrentUserScope, userStore)
- }
- if err != nil {
- return err
- }
- // And also set [setting.CurrentUserScope] as the [setting.DefaultScope], so [GetString],
- // [GetVisibility] and similar functions would be returning a merged result
- // of the machine's and user's policies.
- if !setting.SetDefaultScope(setting.CurrentUserScope) {
- return errors.New("current scope already set")
- }
- return nil
- }
|