better error handling in ASN.1 message parser

This commit is contained in:
Trolli Schmittlauch 2020-05-08 11:23:36 +02:00
parent 6dc9650da5
commit 28254a9f83

View file

@ -284,12 +284,17 @@ encodeMessage
parseMessage :: ParseASN1 FediChordMessage parseMessage :: ParseASN1 FediChordMessage
parseMessage = do parseMessage = do
begin <- getNext
case begin of
Start Sequence -> return ()
x -> throwParseError $ "unexpected ASN.1 element " ++ show x
-- request and response messages are distiguishable by their structure, -- request and response messages are distiguishable by their structure,
-- see ASN.1 schema -- see ASN.1 schema
first <- getNext first <- getNext
case first of case first of
Enumerated a -> parseRequest . toEnum . fromIntegral $ a Enumerated a -> parseRequest . toEnum . fromIntegral $ a
IntVal i -> parseResponse i IntVal i -> parseResponse i
other -> throwParseError $ "unexpected first ASN1 element: " ++ show other
parseRequest :: Action -> ParseASN1 FediChordMessage parseRequest :: Action -> ParseASN1 FediChordMessage
parseRequest action = do parseRequest action = do
@ -304,6 +309,11 @@ parseRequest action = do
Leave -> parseLeaveRequest Leave -> parseLeaveRequest
Stabilise -> parseStabiliseRequest Stabilise -> parseStabiliseRequest
Ping -> parsePingRequest Ping -> parsePingRequest
-- consume sequence end
end <- getNext
case end of
End Sequence -> return ()
x -> throwParseError $ "unexpected ASN.1 element " ++ show x
return $ Request requestID sender parts part action payload return $ Request requestID sender parts part action payload
@ -320,35 +330,48 @@ parseResponse responseTo = do
Leave -> parseLeaveResponse Leave -> parseLeaveResponse
Stabilise -> parseStabiliseResponse Stabilise -> parseStabiliseResponse
Ping -> parsePingResponse Ping -> parsePingResponse
-- consume sequence end
end <- getNext
case end of
End Sequence -> return ()
x -> throwParseError $ "unexpected ASN.1 element " ++ show x
return $ Response responseTo senderID parts part action payload return $ Response responseTo senderID parts part action payload
parseInteger :: ParseASN1 Integer parseInteger :: ParseASN1 Integer
parseInteger = do parseInteger = do
IntVal parsed <- getNext i <- getNext
return parsed case i of
IntVal parsed -> return parsed
x -> throwParseError $ "Expected IntVal but got " ++ show x
parseEnum :: Enum a => ParseASN1 a parseEnum :: Enum a => ParseASN1 a
parseEnum = do parseEnum = do
Enumerated en <- getNext e <- getNext
return $ toEnum . fromIntegral $ en case e of
Enumerated en -> return $ toEnum . fromIntegral $ en
x -> throwParseError $ "Expected Enumerated but got " ++ show x
parseString :: ParseASN1 String parseString :: ParseASN1 String
parseString = do parseString = do
ASN1String toBeParsed <- getNext s <- getNext
maybe (throwParseError "string parsing failed") return $ asn1CharacterToString toBeParsed case s of
ASN1String toBeParsed -> maybe (throwParseError "string parsing failed") return $ asn1CharacterToString toBeParsed
x -> throwParseError $ "Expected a ASN1String but got " ++ show x
parseOctets :: ParseASN1 BS.ByteString parseOctets :: ParseASN1 BS.ByteString
parseOctets = do parseOctets = do
OctetString bs <- getNext os <- getNext
return bs case os of
OctetString bs -> return bs
x -> throwParseError $ "Expected an OctetString but got " ++ show x
parseNull :: ParseASN1 () parseNull :: ParseASN1 ()
parseNull = do parseNull = do
-- ToDo: figure out how this fails on wrong inputs, n <- getNext
-- maybe a case distinction + throwParseError is better? case n of
Null <- getNext Null -> return ()
return () x -> throwParseError $ "Expected Null but got " ++ show x
parseNodeState :: ParseASN1 NodeState parseNodeState :: ParseASN1 NodeState
parseNodeState = do parseNodeState = do