guiconfiguration.go 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. // Copyright (C) 2014 The Syncthing Authors.
  2. //
  3. // This Source Code Form is subject to the terms of the Mozilla Public
  4. // License, v. 2.0. If a copy of the MPL was not distributed with this file,
  5. // You can obtain one at https://mozilla.org/MPL/2.0/.
  6. package config
  7. import (
  8. "net/url"
  9. "os"
  10. "strconv"
  11. "strings"
  12. "golang.org/x/crypto/bcrypt"
  13. "github.com/syncthing/syncthing/lib/rand"
  14. )
  15. func (c GUIConfiguration) IsAuthEnabled() bool {
  16. return c.AuthMode == AuthModeLDAP || (len(c.User) > 0 && len(c.Password) > 0)
  17. }
  18. func (c GUIConfiguration) IsOverridden() bool {
  19. return os.Getenv("STGUIADDRESS") != ""
  20. }
  21. func (c GUIConfiguration) Address() string {
  22. if override := os.Getenv("STGUIADDRESS"); override != "" {
  23. // This value may be of the form "scheme://address:port" or just
  24. // "address:port". We need to chop off the scheme. We try to parse it as
  25. // an URL if it contains a slash. If that fails, return it as is and let
  26. // some other error handling handle it.
  27. if strings.Contains(override, "/") {
  28. url, err := url.Parse(override)
  29. if err != nil {
  30. return override
  31. }
  32. if strings.HasPrefix(url.Scheme, "unix") {
  33. return url.Path
  34. }
  35. return url.Host
  36. }
  37. return override
  38. }
  39. return c.RawAddress
  40. }
  41. func (c GUIConfiguration) UnixSocketPermissions() os.FileMode {
  42. perm, err := strconv.ParseUint(c.RawUnixSocketPermissions, 8, 32)
  43. if err != nil {
  44. // ignore incorrectly formatted permissions
  45. return 0
  46. }
  47. return os.FileMode(perm) & os.ModePerm
  48. }
  49. func (c GUIConfiguration) Network() string {
  50. if override := os.Getenv("STGUIADDRESS"); strings.Contains(override, "/") {
  51. url, err := url.Parse(override)
  52. if err != nil {
  53. return "tcp"
  54. }
  55. if strings.HasPrefix(url.Scheme, "unix") {
  56. return "unix"
  57. }
  58. }
  59. if strings.HasPrefix(c.RawAddress, "/") {
  60. return "unix"
  61. }
  62. return "tcp"
  63. }
  64. func (c GUIConfiguration) UseTLS() bool {
  65. if override := os.Getenv("STGUIADDRESS"); override != "" {
  66. if strings.HasPrefix(override, "http") {
  67. return strings.HasPrefix(override, "https:")
  68. }
  69. if strings.HasPrefix(override, "unix") {
  70. return strings.HasPrefix(override, "unixs:")
  71. }
  72. }
  73. return c.RawUseTLS
  74. }
  75. func (c GUIConfiguration) URL() string {
  76. if strings.HasPrefix(c.RawAddress, "/") {
  77. return "unix://" + c.RawAddress
  78. }
  79. u := url.URL{
  80. Scheme: "http",
  81. Host: c.Address(),
  82. Path: "/",
  83. }
  84. if c.UseTLS() {
  85. u.Scheme = "https"
  86. }
  87. if strings.HasPrefix(u.Host, ":") {
  88. // Empty host, i.e. ":port", use IPv4 localhost
  89. u.Host = "127.0.0.1" + u.Host
  90. } else if strings.HasPrefix(u.Host, "0.0.0.0:") {
  91. // IPv4 all zeroes host, convert to IPv4 localhost
  92. u.Host = "127.0.0.1" + u.Host[7:]
  93. } else if strings.HasPrefix(u.Host, "[::]:") {
  94. // IPv6 all zeroes host, convert to IPv6 localhost
  95. u.Host = "[::1]" + u.Host[4:]
  96. }
  97. return u.String()
  98. }
  99. // SetHashedPassword hashes the given plaintext password and stores the new hash.
  100. func (c *GUIConfiguration) HashAndSetPassword(password string) error {
  101. hash, err := bcrypt.GenerateFromPassword([]byte(password), 0)
  102. if err != nil {
  103. return err
  104. }
  105. c.Password = string(hash)
  106. return nil
  107. }
  108. // CompareHashedPassword returns nil when the given plaintext password matches the stored hash.
  109. func (c GUIConfiguration) CompareHashedPassword(password string) error {
  110. configPasswordBytes := []byte(c.Password)
  111. passwordBytes := []byte(password)
  112. return bcrypt.CompareHashAndPassword(configPasswordBytes, passwordBytes)
  113. }
  114. // IsValidAPIKey returns true when the given API key is valid, including both
  115. // the value in config and any overrides
  116. func (c GUIConfiguration) IsValidAPIKey(apiKey string) bool {
  117. switch apiKey {
  118. case "":
  119. return false
  120. case c.APIKey, os.Getenv("STGUIAPIKEY"):
  121. return true
  122. default:
  123. return false
  124. }
  125. }
  126. func (c *GUIConfiguration) prepare() {
  127. if c.APIKey == "" {
  128. c.APIKey = rand.String(32)
  129. }
  130. }
  131. func (c GUIConfiguration) Copy() GUIConfiguration {
  132. return c
  133. }