server.go 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  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. package node
  11. import (
  12. "bytes"
  13. "crypto/sha256"
  14. "crypto/sha512"
  15. "fmt"
  16. "net/rpc"
  17. "devt.de/krotik/common/errorutil"
  18. )
  19. func init() {
  20. // Create singleton Server instance.
  21. rufsServer = &RufsServer{make(map[string]*RufsNode)}
  22. // Register the cluster API as RPC server
  23. errorutil.AssertOk(rpc.Register(rufsServer))
  24. }
  25. /*
  26. RPCFunction is used to identify the called function in a RPC call
  27. */
  28. type RPCFunction string
  29. /*
  30. List of all possible RPC functions. The list includes all RPC callable functions
  31. in this file.
  32. */
  33. const (
  34. // General functions
  35. RPCPing RPCFunction = "Ping"
  36. RPCData RPCFunction = "Data"
  37. )
  38. /*
  39. RequestArgument is used to identify arguments in a RPC call
  40. */
  41. type RequestArgument int
  42. /*
  43. List of all possible arguments in a RPC request. There are usually no checks which
  44. give back an error if a required argument is missing. The RPC API is an internal
  45. API and might change without backwards compatibility.
  46. */
  47. const (
  48. // General arguments
  49. RequestTARGET RequestArgument = iota // Required argument which identifies the target node
  50. RequestTOKEN // Client token which is used for authorization checks
  51. RequestCTRL // Control object (i.e. what to do with the data)
  52. RequestDATA // Data object
  53. )
  54. /*
  55. rufsServer is the Server instance which serves rpc calls
  56. */
  57. var rufsServer *RufsServer
  58. /*
  59. RufsServer is the RPC exposed Rufs API of a machine. Server is a singleton and will
  60. route incoming (authenticated) requests to registered RufsNodes. The calling
  61. node is referred to as source node and the called node is referred to as
  62. target node.
  63. */
  64. type RufsServer struct {
  65. nodes map[string]*RufsNode // Map of local RufsNodes
  66. }
  67. // General functions
  68. // =================
  69. /*
  70. Ping answers with a Pong if the given client token was verified and the local
  71. node exists.
  72. */
  73. func (s *RufsServer) Ping(request map[RequestArgument]interface{},
  74. response *interface{}) error {
  75. // Verify the given token and retrieve the target member
  76. if _, err := s.checkToken(request); err != nil {
  77. return err
  78. }
  79. // Send a simple response
  80. res := []string{"Pong"}
  81. *response = res
  82. return nil
  83. }
  84. /*
  85. Data handles data requests.
  86. */
  87. func (s *RufsServer) Data(request map[RequestArgument]interface{},
  88. response *interface{}) error {
  89. // Verify the given token and retrieve the target member
  90. node, err := s.checkToken(request)
  91. if err != nil || node.DataHandler == nil {
  92. return err
  93. }
  94. // Forward to the registered data handler
  95. res, err := node.DataHandler(request[RequestCTRL].(map[string]string),
  96. request[RequestDATA].([]byte))
  97. if err == nil {
  98. *response = res
  99. }
  100. return err
  101. }
  102. // Helper functions
  103. // ================
  104. /*
  105. checkToken checks the member token in a given request.
  106. */
  107. func (s *RufsServer) checkToken(request map[RequestArgument]interface{}) (*RufsNode, error) {
  108. err := ErrUnknownTarget
  109. // Get the target member
  110. target := request[RequestTARGET].(string)
  111. token := request[RequestTOKEN].(*RufsNodeToken)
  112. if node, ok := s.nodes[target]; ok {
  113. err = ErrInvalidToken
  114. // Generate expected auth from given requesting node name in token and secret of target
  115. expectedAuth := fmt.Sprintf("%X", sha512.Sum512_224([]byte(token.NodeName+node.secret)))
  116. if token.NodeAuth == expectedAuth {
  117. return node, nil
  118. }
  119. }
  120. return nil, err
  121. }
  122. /*
  123. fingerprint converts a given set of bytes to a fingerprint.
  124. */
  125. func fingerprint(b []byte) string {
  126. var buf bytes.Buffer
  127. hs := fmt.Sprintf("%x", sha256.Sum256(b))
  128. for i, c := range hs {
  129. buf.WriteByte(byte(c))
  130. if (i+1)%2 == 0 && i != len(hs)-1 {
  131. buf.WriteByte(byte(':'))
  132. }
  133. }
  134. return buf.String()
  135. }