diff --git a/htest/Test/Ganeti/Confd/Utils.hs b/htest/Test/Ganeti/Confd/Utils.hs index 8c1590e01bba3c5fcc92508ccfd0c91e240c00be..9d27debd624dc76f90ebb63a38eeb3c6250b7e1f 100644 --- a/htest/Test/Ganeti/Confd/Utils.hs +++ b/htest/Test/Ganeti/Confd/Utils.hs @@ -67,6 +67,21 @@ prop_req_sign key (NonNegative timestamp) (Positive bad_delta) \ timestamp, got " ++ show ts_bad) (ts_bad ==? BasicTypes.Bad "Too old/too new timestamp or clock skew") +-- | Tests that a ConfdReply can be properly encoded, signed and parsed using +-- the proper salt, but fails parsing with the wrong salt. +prop_rep_salt :: Hash.HashKey -- ^ The hash key + -> Confd.ConfdReply -- ^ A Confd reply + -> Property +prop_rep_salt hmac reply = + forAll arbitrary $ \salt1 -> + forAll (arbitrary `suchThat` (/= salt1)) $ \salt2 -> + let innerMsg = J.encode reply + msg = J.encode $ Confd.Utils.signMessage hmac salt1 innerMsg + in + Confd.Utils.parseReply hmac msg salt1 ==? BasicTypes.Ok (innerMsg, reply) + .&&. Confd.Utils.parseReply hmac msg salt2 ==? + BasicTypes.Bad "The received salt differs from the expected salt" + -- | Tests that signing with a different key fails detects failure -- correctly. prop_bad_key :: String -- ^ Salt @@ -88,5 +103,6 @@ prop_bad_key salt crq = testSuite "Confd/Utils" [ 'prop_req_sign + , 'prop_rep_salt , 'prop_bad_key ] diff --git a/htools/Ganeti/Confd/Utils.hs b/htools/Ganeti/Confd/Utils.hs index d19c9cfd6692a4da3431a2396496f1169900042c..770c6f647b5b44dd9ec9dd5dcef715fa5f2e07c5 100644 --- a/htools/Ganeti/Confd/Utils.hs +++ b/htools/Ganeti/Confd/Utils.hs @@ -30,6 +30,7 @@ module Ganeti.Confd.Utils ( getClusterHmac , parseSignedMessage , parseRequest + , parseReply , signMessage , getCurrentTime ) where @@ -65,8 +66,8 @@ parseSignedMessage key str = do else Bad "HMAC verification failed" return (salt, msg, parsedMsg) --- | Message parsing. This can either result in a good, valid message, --- or fail in the Result monad. +-- | Message parsing. This can either result in a good, valid request +-- message, or fail in the Result monad. parseRequest :: HashKey -> String -> Integer -> Result (String, ConfdRequest) parseRequest hmac msg curtime = do @@ -76,6 +77,17 @@ parseRequest hmac msg curtime = do then fail "Too old/too new timestamp or clock skew" else return (origmsg, request) +-- | Message parsing. This can either result in a good, valid reply +-- message, or fail in the Result monad. +-- It also checks that the salt in the message corresponds to the one +-- that is expected +parseReply :: HashKey -> String -> String -> Result (String, ConfdReply) +parseReply hmac msg expSalt = do + (salt, origmsg, reply) <- parseSignedMessage hmac msg + if salt /= expSalt + then fail "The received salt differs from the expected salt" + else return (origmsg, reply) + -- | Signs a message with a given key and salt. signMessage :: HashKey -> String -> String -> SignedMessage signMessage key salt msg =