"crypto/x509"
"encoding/json"
"fmt"
+ "hash/crc32"
+ "os"
+ "regexp"
"io/ioutil"
"strings"
return deliveries, err
}
+func validateCRC32(checkMap map[string]interface{}, data []byte, enforce bool) bool {
+ // constant polynomial that's used by micropython for crc32 calc
+ crc32table := crc32.MakeTable(0xEDB88320)
+ _, crcPresent := checkMap["crc32"]
+ if !crcPresent {
+ logger.V(3).Info("No CRC32 present in action body", "action", checkMap, "enforce", enforce)
+ // returns invalid if enforce is set, otherwise true - ignores the crc
+ return !enforce
+ } else {
+ // crc32 is present, now we have to check the map appropriately
+ // first, strip off the crc itself
+ targetHash := checkMap["crc32"].(string)
+ regexp, err := regexp.Compile("(, )?\"crc32\"[^\"]+\"[^\"]+\"")
+ if err != nil {
+ logger.Error(nil, "Not able to compile regex matcher")
+ os.Exit(1)
+ }
+ match := regexp.ReplaceAllString(string(data), "")
+
+ //delete(checkMap, "crc32")
+ // remarshal, now without the crc key
+ /*targetJson, err := json.MarshalIndent(checkMap, "", " ")
+ if err != nil {
+ logger.Error(err, "we got an error remarshalling action map data, just like exit", "action", checkMap)
+ os.Exit(1)
+ }*/
+ targetJson := []byte(match)
+ // calculate the hash itself, and output as a lowercase hex string
+ checkHash := fmt.Sprintf("%x", crc32.Checksum(targetJson, crc32table))
+ if targetHash == checkHash {
+ // hashes match!
+ logger.V(3).Info("Hashes match", "targetHash", targetHash, "checkHash", checkHash, "action", checkMap)
+ return true
+ } else {
+ logger.Error(nil, "CRC32 hashes do not match", "targetHash", targetHash, "checkHash", checkHash, "action", targetJson, "data", match)
+ return false
+ }
+ }
+
+}
+
// DecodeDelivery - takes a presumably byte-formatted json stream and makes it a map for us
// will return errors if things don't actually work out that well
func DecodeDelivery(delivery amqp.Delivery) (map[string]interface{}, error) {
var decode map[string]interface{}
err := json.Unmarshal([]byte(result["action"].(string)), &decode)
if err == nil {
- result["action"] = decode
+ // if we do have a CRC32 present, check its validity, otherwise enforce and return error
+ if validateCRC32(decode, []byte(result["action"].(string)), true) {
+ result["action"] = decode
+ } else {
+ return result, err
+ }
}
// otherwise, just leave it alone and return as-is
}