diff --git a/ICCC/HTTPConnector.go b/ICCC/HTTPConnector.go index d40fde5..edf9d8f 100644 --- a/ICCC/HTTPConnector.go +++ b/ICCC/HTTPConnector.go @@ -9,8 +9,8 @@ import ( "net/url" ) -// The HTTP handler for the local ICCC commands. Will used in case, that another server -// want to utelise an command from this server. +// The HTTP handler for the local ICCC listeners. Will used in case, that another server +// want to utelise an listener from this server. func ICCCHandler(response http.ResponseWriter, request *http.Request) { // Cannot parse the form? @@ -23,9 +23,9 @@ func ICCCHandler(response http.ResponseWriter, request *http.Request) { // Read the data out of the request: messageData := map[string][]string(request.PostForm) - // The data must contain at least three fields (command, channel & communication password) + // The data must contain at least three fields (command, channel & checksum) if len(messageData) < 3 { - Log.LogFull(senderName, LM.CategorySYSTEM, LM.LevelERROR, LM.SeverityCritical, LM.ImpactCritical, LM.MessageNameNETWORK, `The ICCC message contains not enough data: At least the channel, command and password is required!`) + Log.LogFull(senderName, LM.CategorySYSTEM, LM.LevelERROR, LM.SeverityCritical, LM.ImpactCritical, LM.MessageNameNETWORK, `The ICCC message contains not enough data: At least the channel, command and checksum is required!`) http.NotFound(response, request) return } @@ -33,11 +33,17 @@ func ICCCHandler(response http.ResponseWriter, request *http.Request) { // Read the meta data: channel := messageData[`channel`][0] command := messageData[`command`][0] - password := messageData[`InternalCommPassword`][0] + receivedChecksum := messageData[`checksum`][0] - // Check the password: - if password != Tools.InternalCommPassword() { - Log.LogFull(senderName, LM.CategorySYSTEM, LM.LevelSECURITY, LM.SeverityCritical, LM.ImpactNone, LM.MessageNamePASSWORD, `Received a ICCC message with wrong password!`, request.RemoteAddr) + // Remove the checksum as preparation for the re-hash: + delete(messageData, `checksum`) + + // Re-hash the received message: + receivedMessageHash := signMessage(messageData).Get(`checksum`) + + // Check the checksums: + if receivedChecksum != receivedMessageHash { + Log.LogFull(senderName, LM.CategorySYSTEM, LM.LevelSECURITY, LM.SeverityCritical, LM.ImpactNone, LM.MessageNamePASSWORD, `Received a ICCC message with wrong checksum!`, request.RemoteAddr, fmt.Sprintf("channel=%s", channel), fmt.Sprintf("command=%s", command)) http.NotFound(response, request) return } diff --git a/ICCC/Send.go b/ICCC/Send.go index dc41a50..ab150c1 100644 --- a/ICCC/Send.go +++ b/ICCC/Send.go @@ -4,7 +4,6 @@ import ( "github.com/SommerEngineering/Ocean/ICCC/Scheme" "github.com/SommerEngineering/Ocean/Log" LM "github.com/SommerEngineering/Ocean/Log/Meta" - "github.com/SommerEngineering/Ocean/Tools" "io/ioutil" "net/http" "net/url" @@ -12,11 +11,9 @@ import ( // Send a message to a listener. func sendMessage(listener Scheme.Listener, data map[string][]string) (result map[string][]string) { - // Convert the data and encode it: - valuesHTTP := url.Values(data) - // Add the communication password: - valuesHTTP.Add(`InternalCommPassword`, Tools.InternalCommPassword()) + // Lets sign the data: + valuesHTTP := signMessage(data) // Try to deliver the message: if response, err := http.PostForm(`http://`+listener.IPAddressPort+`/ICCC`, valuesHTTP); err != nil { diff --git a/ICCC/SignMessage.go b/ICCC/SignMessage.go new file mode 100644 index 0000000..f938b01 --- /dev/null +++ b/ICCC/SignMessage.go @@ -0,0 +1,47 @@ +package ICCC + +import ( + "crypto/sha512" + "fmt" + "github.com/SommerEngineering/Ocean/Tools" + "net/url" + "sort" +) + +// Sign a message to secure it. +func signMessage(data map[string][]string) (result url.Values) { + // Create the hash generator: + hash := sha512.New() + + // To the start, we hash the password: + fmt.Fprintf(hash, "%s", Tools.InternalCommPassword()) + + // Because the order of a map is random, we have to sort + // the keys beforehand. Next, we can use the ordered keys + // to access the data: + keys := []string{} + + // Get all keys: + for key := range data { + keys = append(keys, key) + } + + // Sort the keys: + sort.Strings(keys) + + // Now, loop over all the data: + for _, key := range keys { + // Get the value: + value := data[key] + + // Hash each key and value: + fmt.Fprintf(hash, "key=%s :: value=%s\n", key, value) + } + + // Create the result: + result = url.Values(data) + + // Append the sign: + result.Add(`checksum`, fmt.Sprintf("%x", hash.Sum(nil))) + return +}