50 |
50 |
, testSsconf
|
51 |
51 |
, testRpc
|
52 |
52 |
, testQlang
|
|
53 |
, testConfd
|
53 |
54 |
) where
|
54 |
55 |
|
55 |
56 |
import qualified Test.HUnit as HUnit
|
... | ... | |
2089 |
2090 |
testSuite "Qlang"
|
2090 |
2091 |
[ 'prop_Qlang_Serialisation
|
2091 |
2092 |
]
|
|
2093 |
|
|
2094 |
|
|
2095 |
-- * Confd tests (generic library)
|
|
2096 |
|
|
2097 |
instance Arbitrary Confd.ConfdRequestType where
|
|
2098 |
arbitrary = elements [minBound..maxBound]
|
|
2099 |
|
|
2100 |
instance Arbitrary Confd.ConfdReqField where
|
|
2101 |
arbitrary = elements [minBound..maxBound]
|
|
2102 |
|
|
2103 |
instance Arbitrary Confd.ConfdReqQ where
|
|
2104 |
arbitrary = Confd.ConfdReqQ <$> arbitrary <*> arbitrary <*>
|
|
2105 |
arbitrary <*> arbitrary
|
|
2106 |
|
|
2107 |
instance Arbitrary Confd.ConfdQuery where
|
|
2108 |
arbitrary = oneof [ pure Confd.EmptyQuery
|
|
2109 |
, Confd.PlainQuery <$> getName
|
|
2110 |
, Confd.DictQuery <$> arbitrary
|
|
2111 |
]
|
|
2112 |
|
|
2113 |
instance Arbitrary Confd.ConfdRequest where
|
|
2114 |
arbitrary = Confd.ConfdRequest <$> arbitrary <*> arbitrary <*> arbitrary
|
|
2115 |
<*> arbitrary
|
|
2116 |
|
|
2117 |
-- | Test that signing messages and checking signatures is correct. It
|
|
2118 |
-- also tests, indirectly the serialisation of messages so we don't
|
|
2119 |
-- need a separate test for that.
|
|
2120 |
prop_Confd_req_sign :: Hash.HashKey -- ^ The hash key
|
|
2121 |
-> NonNegative Integer -- ^ The base timestamp
|
|
2122 |
-> Positive Integer -- ^ Delta for out of window
|
|
2123 |
-> Bool -- ^ Whether delta should be + or -
|
|
2124 |
-> Confd.ConfdRequest
|
|
2125 |
-> Property
|
|
2126 |
prop_Confd_req_sign key (NonNegative timestamp) (Positive bad_delta) pm crq =
|
|
2127 |
forAll (choose (0, fromIntegral C.confdMaxClockSkew)) $ \ good_delta ->
|
|
2128 |
let encoded = J.encode crq
|
|
2129 |
salt = show timestamp
|
|
2130 |
signed = J.encode $ Confd.Utils.signMessage key salt encoded
|
|
2131 |
good_timestamp = timestamp + if pm then good_delta else (-good_delta)
|
|
2132 |
bad_delta' = fromIntegral C.confdMaxClockSkew + bad_delta
|
|
2133 |
bad_timestamp = timestamp + if pm then bad_delta' else (-bad_delta')
|
|
2134 |
ts_ok = Confd.Utils.parseMessage key signed good_timestamp
|
|
2135 |
ts_bad = Confd.Utils.parseMessage key signed bad_timestamp
|
|
2136 |
in printTestCase "Failed to parse good message"
|
|
2137 |
(ts_ok ==? Types.Ok (encoded, crq)) .&&.
|
|
2138 |
printTestCase ("Managed to deserialise message with bad\
|
|
2139 |
\ timestamp, got " ++ show ts_bad)
|
|
2140 |
(ts_bad ==? Types.Bad "Too old/too new timestamp or clock skew")
|
|
2141 |
|
|
2142 |
-- | Tests that signing with a different key fails detects failure
|
|
2143 |
-- correctly.
|
|
2144 |
prop_Confd_bad_key :: String -- ^ Salt
|
|
2145 |
-> Confd.ConfdRequest -- ^ Request
|
|
2146 |
-> Property
|
|
2147 |
prop_Confd_bad_key salt crq =
|
|
2148 |
-- fixme: we hardcode here the expected length of a sha1 key, as
|
|
2149 |
-- otherwise we could have two short keys that differ only in the
|
|
2150 |
-- final zero elements count, and those will be expanded to be the
|
|
2151 |
-- same
|
|
2152 |
forAll (vector 20) $ \key_sign ->
|
|
2153 |
forAll (vector 20 `suchThat` (/= key_sign)) $ \key_verify ->
|
|
2154 |
let signed = Confd.Utils.signMessage key_sign salt (J.encode crq)
|
|
2155 |
encoded = J.encode signed
|
|
2156 |
in printTestCase ("Accepted message signed with different key" ++ encoded) $
|
|
2157 |
Types.Bad "HMAC verification failed" ==?
|
|
2158 |
Confd.Utils.parseRequest key_verify encoded
|
|
2159 |
|
|
2160 |
testSuite "Confd"
|
|
2161 |
[ 'prop_Confd_req_sign
|
|
2162 |
, 'prop_Confd_bad_key
|
|
2163 |
]
|