{-# LANGUAGE PackageImports, OverloadedStrings #-} module Network.PeyoTLS.Codec.Alert (Alert(..), AlertLevel(..), AlertDesc(..)) where import Control.Applicative import "monads-tf" Control.Monad.Error.Class (Error(..)) import Data.Word (Word8) import qualified Data.ByteString as BS import qualified Codec.Bytable.BigEndian as B modNm :: String modNm = "Network.PeyoTLS.Codec.Alert" -- | RFC 5246 7.2. Alert Protocol -- -- @ -- struct { -- AlertLevel level; -- AlertDescription description; -- } Alert; -- @ data Alert = Alert AlertLevel AlertDesc String | ExternalAlert String | NotDetected String deriving Show instance B.Bytable Alert where encode (Alert al ad _) = B.encode al `BS.append` B.encode ad encode _ = error "Alert.encode" decode alad = let (al, ad) = BS.splitAt 1 alad in Alert <$> B.decode al <*> B.decode ad <*> return "" -- | RFC 5246 7.2. Alert Protocol -- -- @ -- enum { warning(1), fatal(2), (255) } AlertLevel; -- @ data AlertLevel = ALWarning | ALFtl | ALRaw Word8 deriving Show instance B.Bytable AlertLevel where encode ALWarning = "\x01" encode ALFtl = "\x02" encode (ALRaw w) = BS.pack [w] decode bs = case BS.unpack bs of [al] -> Right $ case al of 1 -> ALWarning; 2 -> ALFtl; _ -> ALRaw al _ -> Left $ modNm ++ ": AlertLevel.decode" -- | RFC 5246 7.2. Alert Protocol -- -- @ -- enum { -- close_notify(0), -- unexpected_message(10), -- bad_record_mac(20), -- decryption_failed_RESERVED(21), -- record_overflow(22), -- decompression_failure(30), -- handshake_failure(40), -- no_certificate_RESERVED(41), -- bad_certificate(42), -- unsupported_certificate(43), -- certificate_revoked(44), -- certificate_expired(45), -- certificate_unknown(46), -- illegal_parameter(47), -- unknown_ca(48), -- access_denied(49), -- decode_error(50), -- decrypt_error(51), -- export_restriction_RESERVED(60), -- protocol_version(70), -- insufficient_security(71), -- internal_error(80), -- user_canceled(90), -- no_renegotiation(100), -- unsupported_extension(110), -- (255) -- } AlertDescription; -- @ data AlertDesc = ADCloseNotify | ADUnexMsg | ADBadRecMac | ADRecOverflow | ADDecFail | ADHsFailure | ADUnsCert | ADCertEx | ADCertUnk | ADIllParam | ADUnkCa | ADDecodeErr | ADDecryptErr | ADProtoVer | ADInsSec | ADInternalErr | ADUnk | ADRaw Word8 deriving Show instance B.Bytable AlertDesc where encode ADCloseNotify = "\0" encode ADUnexMsg = "\10" encode ADBadRecMac = "\20" encode ADRecOverflow = "\22" encode ADDecFail = "\30" encode ADHsFailure = "\40" encode ADUnsCert = "\43" encode ADCertEx = "\45" encode ADCertUnk = "\46" encode ADIllParam = "\47" encode ADUnkCa = "\48" encode ADDecodeErr = "\50" encode ADDecryptErr = "\51" encode ADProtoVer = "\70" encode ADInsSec = "\71" encode ADInternalErr = "\80" encode ADUnk = error $ modNm ++ ": AlertDesc,encode" encode (ADRaw w) = BS.pack [w] decode bs = case BS.unpack bs of [ad] -> Right $ case ad of 0 -> ADCloseNotify 10 -> ADUnexMsg 20 -> ADBadRecMac 22 -> ADRecOverflow 30 -> ADDecFail 40 -> ADHsFailure 43 -> ADUnsCert 45 -> ADCertEx 46 -> ADCertUnk 47 -> ADIllParam 48 -> ADUnkCa 50 -> ADDecodeErr 51 -> ADDecryptErr 70 -> ADProtoVer 71 -> ADInsSec 80 -> ADInternalErr w -> ADRaw w _ -> Left $ modNm ++ ": AlertDesc.decode" instance Error Alert where strMsg = NotDetected