@@ -0,0 +1,142 @@
1+{-# LANGUAGE TemplateHaskell #-}
9+import Data.ByteString as BS
10+import qualified Data.Char as C
12+import Data.Isoparsec.ByteString
13+import Data.Isoparsec.Debugger
15+import Prelude as P hiding ((.), id)
26+ deriving (Eq, Show, Ord)
28+instance ToIsoparsec MessageNumber ByteString a where
32+ [ (1, DisconnectMsg),
34+ (3, UnimplementedMsg),
36+ (5, ServiceRequestMsg),
37+ (6, ServiceAcceptMsg),
42+newtype DisconnectReasonCode
43+ = DisconnectReasonCode {unDisconnectReasonCode :: Byte32 'BE}
44+ deriving (Eq, Ord, Show, Generic)
46+instance ToIsoparsec DisconnectReasonCode ByteString a
48+newtype AlwaysDisplay = AlwaysDisplay {unAlwaysDisplay :: Bool}
49+ deriving (Eq, Ord, Show, Generic)
51+instance ToIsoparsec AlwaysDisplay ByteString a
53+newtype PacketSequenceNumber
54+ = PacketSequenceNumber {unPacketSequenceNumber :: Byte32 'BE}
55+ deriving (Eq, Ord, Show, Generic)
57+instance ToIsoparsec PacketSequenceNumber ByteString a
60+ = VersionPayload String
61+ | IgnorePayload ByteString
62+ | ServiceRequest SSHString
63+ | DebugPayload AlwaysDisplay SSHString
64+ | DisconnectPayload DisconnectReasonCode String
65+ | ServiceAccept SSHString
66+ | UnimplementedPayload PacketSequenceNumber
71+instance ToIsoparsec Payload ByteString a where
74+ <.> specific DisconnectMsg
75+ &&& auto @DisconnectReasonCode
76+ &&& (tokensWhile (const True) >>> utf8)
78+ <+> ( _ServiceRequest <.> specific ServiceRequestMsg
81+ <+> ( _VersionPayload <.> chunk "SSH-2.0-"
82+ &&& (tokensWhile (`BS.notElem` " \n\r") >>> utf8)
83+ &&& ( (chunk " " >>> takeUntil "\r\n" >>^ (maskr . turn . konst $ ""))
87+ <+> (_IgnorePayload <.> specific IgnoreMsg &&& tokensWhile (const True))
88+ <+> ( _DebugPayload <.> specific DebugMsg
89+ &&& auto @AlwaysDisplay
92+ <+> ( _UnimplementedPayload <.> specific UnimplementedMsg
93+ &&& auto @PacketSequenceNumber
95+ <+> ( _ServiceAccept <.> specific ServiceAcceptMsg
99+newtype Padding = Padding {unPadding :: ByteString}
100+ deriving (Eq, Ord, Show, Generic)
102+newtype ZeroPadding = ZeroPadding {zeroPaddingLength :: Byte8}
103+ deriving (Eq, Ord, Show, Generic)
105+badZeroPadding :: Isoparsec m ByteString => m Byte8 ZeroPadding
110+ (ZeroPadding . fromIntegral . BS.length)
111+ (flip BS.replicate 0 . fromIntegral . zeroPaddingLength)
113+newtype MAC = MAC {unMAC :: ByteString}
114+ deriving (Eq, Ord, Show, Generic)
116+data NoneMAC = NoneMAC
117+ deriving (Eq, Ord, Show, Generic)
119+instance ToIsoparsec NoneMAC b a where
120+ toIsoparsec = arr $ konst NoneMAC
123+ = Packet Payload ZeroPadding mac
128+instance ToIsoparsec mac ByteString a => ToIsoparsec (Packet mac) ByteString a where
130+ ( auto @(Byte32 'BE) &&& auto @Byte8
131+ >>> throughIntegral *** throughIntegral
133+ (\(packetL, paddingL) -> (packetL - paddingL - 1, paddingL))
134+ (\(payloadL, paddingL) -> (payloadL + paddingL + 1, paddingL))
135+ >>> manyTokens *** throughIntegral
136+ >>> tuck (auto @Payload) *** badZeroPadding
139+ >>^ siPure (\((a, b), c) -> Packet a b c) (\(Packet a b c) -> ((a, b), c))
142+main = debug @ByteString (auto @(Packet NoneMAC))