rufs.go 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. /*
  2. * Rufs - Remote Union File System
  3. *
  4. * Copyright 2017 Matthias Ladkau. All rights reserved.
  5. *
  6. * This Source Code Form is subject to the terms of the MIT
  7. * License, If a copy of the MIT License was not distributed with this
  8. * file, You can obtain one at https://opensource.org/licenses/MIT.
  9. */
  10. /*
  11. Rufs main entry point for the standalone server.
  12. */
  13. package main
  14. import (
  15. "crypto/tls"
  16. "errors"
  17. "flag"
  18. "fmt"
  19. "io/ioutil"
  20. "net"
  21. "os"
  22. "path/filepath"
  23. "time"
  24. "devt.de/krotik/common/cryptutil"
  25. "devt.de/krotik/common/fileutil"
  26. "devt.de/krotik/rufs/config"
  27. )
  28. /*
  29. DefaultSecretFile is the default secret file which is used in server and client mode
  30. */
  31. const DefaultSecretFile = "rufs.secret"
  32. /*
  33. DefaultSSLDir is the default directory containing the ssl key.pem and cert.pem files
  34. */
  35. const DefaultSSLDir = "ssl"
  36. /*
  37. Main entry point for Rufs.
  38. */
  39. func main() {
  40. var err error
  41. fmt.Println(fmt.Sprintf("Rufs %v", config.ProductVersion))
  42. flag.Usage = func() {
  43. // Print usage for tool selection
  44. fmt.Println()
  45. fmt.Println(fmt.Sprintf("Usage of %s [tool]", os.Args[0]))
  46. fmt.Println()
  47. fmt.Println("The tools are:")
  48. fmt.Println()
  49. fmt.Println(" server Run as a server")
  50. fmt.Println(" client Run as a client")
  51. fmt.Println()
  52. fmt.Println(fmt.Sprintf("Use %s [tool] --help for more information about a tool.", os.Args[0]))
  53. fmt.Println()
  54. }
  55. flag.Parse()
  56. if len(flag.Args()) == 0 {
  57. flag.Usage()
  58. return
  59. }
  60. if flag.Args()[0] == "server" {
  61. err = serverCli()
  62. } else if flag.Args()[0] == "client" {
  63. err = clientCli()
  64. } else {
  65. err = fmt.Errorf("Invalid tool")
  66. }
  67. if err != nil {
  68. fmt.Println(fmt.Sprintf("Error: %v", err))
  69. }
  70. }
  71. // Common code
  72. // ===========
  73. /*
  74. commonCliOptions returns common command line options which are relevant
  75. for both server and client.
  76. */
  77. func commonCliOptions() (*string, *string) {
  78. secretFile := flag.String("secret", DefaultSecretFile, "Secret file containing the secret token")
  79. certDir := flag.String("ssl-dir", DefaultSSLDir, "Directory containing the ssl key.pem and cert.pem files")
  80. return secretFile, certDir
  81. }
  82. /*
  83. loadSecretAndCert loads the secret string and the SSL key and certificate.
  84. */
  85. func loadSecretAndCert(secretFile, certDir string) ([]byte, *tls.Certificate, error) {
  86. var ok bool
  87. var err error
  88. // Load secret
  89. if ok, _ = fileutil.PathExists(secretFile); !ok {
  90. uuid := cryptutil.GenerateUUID()
  91. err = ioutil.WriteFile(secretFile, uuid[:], 0600)
  92. }
  93. if err == nil {
  94. var secret []byte
  95. if secret, err = ioutil.ReadFile(secretFile); err == nil {
  96. fmt.Println(fmt.Sprintf("Using secret from: %s", secretFile))
  97. // Load ssl key and certificate
  98. if ok, _ = fileutil.PathExists(certDir); !ok {
  99. if err = os.MkdirAll(certDir, 0700); err == nil {
  100. err = cryptutil.GenCert(certDir, "cert.pem", "key.pem", "localhost",
  101. "", 365*24*time.Hour, false, 4096, "")
  102. }
  103. }
  104. if err == nil {
  105. var cert tls.Certificate
  106. cert, err = tls.LoadX509KeyPair(filepath.Join(certDir, "cert.pem"),
  107. filepath.Join(certDir, "key.pem"))
  108. if err == nil {
  109. fmt.Println(fmt.Sprintf("Using ssl key.pem and cert.pem from: %s", certDir))
  110. return secret, &cert, nil
  111. }
  112. }
  113. }
  114. }
  115. return nil, nil, err
  116. }
  117. /*
  118. externalIP returns the first found external IP
  119. */
  120. func externalIP() (string, error) {
  121. var ipstr string
  122. ifaces, err := net.Interfaces()
  123. if err == nil {
  124. Loop:
  125. for _, iface := range ifaces {
  126. var addrs []net.Addr
  127. if iface.Flags&net.FlagUp == 0 || iface.Flags&net.FlagLoopback != 0 {
  128. // Ignore interfaces which are down or loopback devices
  129. continue
  130. }
  131. if addrs, err = iface.Addrs(); err == nil {
  132. // Go through all found addresses
  133. for _, addr := range addrs {
  134. var ip net.IP
  135. switch v := addr.(type) {
  136. case *net.IPNet:
  137. ip = v.IP
  138. case *net.IPAddr:
  139. ip = v.IP
  140. default:
  141. continue
  142. }
  143. if !ip.IsLoopback() {
  144. if ip = ip.To4(); ip != nil {
  145. ipstr = ip.String()
  146. break Loop
  147. }
  148. }
  149. }
  150. }
  151. }
  152. }
  153. if ipstr == "" {
  154. err = errors.New("No external interface found")
  155. }
  156. return ipstr, err
  157. }