syspolicy_windows.go 3.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. // Copyright (c) Tailscale Inc & AUTHORS
  2. // SPDX-License-Identifier: BSD-3-Clause
  3. package syspolicy
  4. import (
  5. "errors"
  6. "fmt"
  7. "os/user"
  8. "tailscale.com/util/syspolicy/internal"
  9. "tailscale.com/util/syspolicy/rsop"
  10. "tailscale.com/util/syspolicy/setting"
  11. "tailscale.com/util/syspolicy/source"
  12. "tailscale.com/util/testenv"
  13. )
  14. func init() {
  15. // On Windows, we should automatically register the Registry-based policy
  16. // store for the device. If we are running in a user's security context
  17. // (e.g., we're the GUI), we should also register the Registry policy store for
  18. // the user. In the future, we should register (and unregister) user policy
  19. // stores whenever a user connects to (or disconnects from) the local backend.
  20. // This ensures the backend is aware of the user's policy settings and can send
  21. // them to the GUI/CLI/Web clients on demand or whenever they change.
  22. //
  23. // Other platforms, such as macOS, iOS and Android, should register their
  24. // platform-specific policy stores via [RegisterStore]
  25. // (or [RegisterHandler] until they implement the [source.Store] interface).
  26. //
  27. // External code, such as the ipnlocal package, may choose to register
  28. // additional policy stores, such as config files and policies received from
  29. // the control plane.
  30. internal.Init.MustDefer(func() error {
  31. // Do not register or use default policy stores during tests.
  32. // Each test should set up its own necessary configurations.
  33. if testenv.InTest() {
  34. return nil
  35. }
  36. return configureSyspolicy(nil)
  37. })
  38. }
  39. // configureSyspolicy configures syspolicy for use on Windows,
  40. // either in test or regular builds depending on whether tb has a non-nil value.
  41. func configureSyspolicy(tb testenv.TB) error {
  42. const localSystemSID = "S-1-5-18"
  43. // Always create and register a machine policy store that reads
  44. // policy settings from the HKEY_LOCAL_MACHINE registry hive.
  45. machineStore, err := source.NewMachinePlatformPolicyStore()
  46. if err != nil {
  47. return fmt.Errorf("failed to create the machine policy store: %v", err)
  48. }
  49. if tb == nil {
  50. _, err = rsop.RegisterStore("Platform", setting.DeviceScope, machineStore)
  51. } else {
  52. _, err = rsop.RegisterStoreForTest(tb, "Platform", setting.DeviceScope, machineStore)
  53. }
  54. if err != nil {
  55. return err
  56. }
  57. // Check whether the current process is running as Local System or not.
  58. u, err := user.Current()
  59. if err != nil {
  60. return err
  61. }
  62. if u.Uid == localSystemSID {
  63. return nil
  64. }
  65. // If it's not a Local System's process (e.g., it's the GUI rather than the tailscaled service),
  66. // we should create and use a policy store for the current user that reads
  67. // policy settings from that user's registry hive (HKEY_CURRENT_USER).
  68. userStore, err := source.NewUserPlatformPolicyStore(0)
  69. if err != nil {
  70. return fmt.Errorf("failed to create the current user's policy store: %v", err)
  71. }
  72. if tb == nil {
  73. _, err = rsop.RegisterStore("Platform", setting.CurrentUserScope, userStore)
  74. } else {
  75. _, err = rsop.RegisterStoreForTest(tb, "Platform", setting.CurrentUserScope, userStore)
  76. }
  77. if err != nil {
  78. return err
  79. }
  80. // And also set [setting.CurrentUserScope] as the [setting.DefaultScope], so [GetString],
  81. // [GetVisibility] and similar functions would be returning a merged result
  82. // of the machine's and user's policies.
  83. if !setting.SetDefaultScope(setting.CurrentUserScope) {
  84. return errors.New("current scope already set")
  85. }
  86. return nil
  87. }