packages feed

hssh-0.1.0.0: test/Spec/Message.hs

{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE OverloadedStrings          #-}
{-# LANGUAGE StandaloneDeriving         #-}
module Spec.Message ( tests ) where

import           Crypto.Error
import qualified Crypto.PubKey.Curve25519 as Curve25519
import qualified Crypto.PubKey.Ed25519    as Ed25519
import qualified Crypto.PubKey.RSA        as RSA
import qualified Data.ByteString          as BS
import qualified Data.ByteString.Short    as SBS
import           System.Exit

import           Test.Tasty
import           Test.Tasty.QuickCheck    as QC

import           Network.SSH.Internal

tests :: TestTree
tests = testGroup "Network.SSH.Message"
    [ testParserIdentity
    ]

testParserIdentity :: TestTree
testParserIdentity = testGroup "put . get == id"
    [ QC.testProperty ":: Disconnected"               (parserIdentity :: Disconnected               -> Property)
    , QC.testProperty ":: DisconnectReason"           (parserIdentity :: DisconnectReason           -> Property)
    , QC.testProperty ":: Ignore"                     (parserIdentity :: Ignore                     -> Property)
    , QC.testProperty ":: Unimplemented"              (parserIdentity :: Unimplemented              -> Property)
    , QC.testProperty ":: Debug"                      (parserIdentity :: Debug                      -> Property)
    , QC.testProperty ":: ServiceRequest"             (parserIdentity :: ServiceRequest             -> Property)
    , QC.testProperty ":: ServiceAccept"              (parserIdentity :: ServiceAccept              -> Property)
    , QC.testProperty ":: KexInit"                    (parserIdentity :: KexInit                    -> Property)
    , QC.testProperty ":: KexNewKeys"                 (parserIdentity :: KexNewKeys                 -> Property)
    , QC.testProperty ":: KexEcdhInit"                (parserIdentity :: KexEcdhInit                -> Property)
    , QC.testProperty ":: KexEcdhReply"               (parserIdentity :: KexEcdhReply               -> Property)
    , QC.testProperty ":: UserAuthRequest"            (parserIdentity :: UserAuthRequest            -> Property)
    , QC.testProperty ":: UserAuthFailure"            (parserIdentity :: UserAuthFailure            -> Property)
    , QC.testProperty ":: UserAuthSuccess"            (parserIdentity :: UserAuthSuccess            -> Property)
    , QC.testProperty ":: UserAuthBanner"             (parserIdentity :: UserAuthBanner             -> Property)
    , QC.testProperty ":: UserAuthPublicKeyOk"        (parserIdentity :: UserAuthPublicKeyOk        -> Property)
    , QC.testProperty ":: ChannelOpen"                (parserIdentity :: ChannelOpen                -> Property)
    , QC.testProperty ":: ChannelOpenConfirmation"    (parserIdentity :: ChannelOpenConfirmation    -> Property)
    , QC.testProperty ":: ChannelOpenFailure"         (parserIdentity :: ChannelOpenFailure         -> Property)
    , QC.testProperty ":: ChannelOpenFailureReason"   (parserIdentity :: ChannelOpenFailureReason   -> Property)
    , QC.testProperty ":: ChannelWindowAdjust"        (parserIdentity :: ChannelWindowAdjust        -> Property)
    , QC.testProperty ":: ChannelData"                (parserIdentity :: ChannelData                -> Property)
    , QC.testProperty ":: ChannelExtendedData"        (parserIdentity :: ChannelExtendedData        -> Property)
    , QC.testProperty ":: ChannelEof"                 (parserIdentity :: ChannelEof                 -> Property)
    , QC.testProperty ":: ChannelClose"               (parserIdentity :: ChannelClose               -> Property)
    , QC.testProperty ":: ChannelRequest"             (parserIdentity :: ChannelRequest             -> Property)
    , QC.testProperty ":: ChannelRequestEnv"          (parserIdentity :: ChannelRequestEnv          -> Property)
    , QC.testProperty ":: ChannelRequestPty"          (parserIdentity :: ChannelRequestPty          -> Property)
    , QC.testProperty ":: ChannelRequestWindowChange" (parserIdentity :: ChannelRequestWindowChange -> Property)
    , QC.testProperty ":: ChannelRequestShell"        (parserIdentity :: ChannelRequestShell        -> Property)
    , QC.testProperty ":: ChannelRequestExec"         (parserIdentity :: ChannelRequestExec         -> Property)
    , QC.testProperty ":: ChannelRequestSignal"       (parserIdentity :: ChannelRequestSignal       -> Property)
    , QC.testProperty ":: ChannelRequestExitSignal"   (parserIdentity :: ChannelRequestExitSignal   -> Property)
    , QC.testProperty ":: ChannelRequestExitStatus"   (parserIdentity :: ChannelRequestExitStatus   -> Property)
    , QC.testProperty ":: ChannelSuccess"             (parserIdentity :: ChannelSuccess             -> Property)
    , QC.testProperty ":: ChannelFailure"             (parserIdentity :: ChannelFailure             -> Property)
    , QC.testProperty ":: Version"                    (parserIdentity :: Version                    -> Property)
    , QC.testProperty ":: PublicKey"                  (parserIdentity :: PublicKey                  -> Property)
    , QC.testProperty ":: Signature"                  (parserIdentity :: Signature                  -> Property)
    , QC.testProperty ":: Message"                    (parserIdentity :: Message                    -> Property)
    ]
    where
        parserIdentity :: (Encoding a, Eq a, Show a) => a -> Property
        parserIdentity x = Just x === runGet (runPut $ put x)

instance Arbitrary BS.ByteString where
    arbitrary = elements
        [ ""
        , "1"
        , "1234567890"
        ]

instance Arbitrary SBS.ShortByteString where
    arbitrary = elements
        [ ""
        , "1"
        , "1234567890"
        ]

instance Arbitrary Command where
    arbitrary = elements
        [ Command ""
        , Command "foobar --xyz fasel"
        , Command "ls"
        ]

instance Arbitrary Message where
    arbitrary = oneof
        [ MsgDisconnect              <$> arbitrary
        , MsgIgnore                  <$> arbitrary
        , MsgUnimplemented           <$> arbitrary
        , MsgDebug                   <$> arbitrary
        , MsgServiceRequest          <$> arbitrary
        , MsgServiceAccept           <$> arbitrary
        , MsgKexInit                 <$> arbitrary
        , MsgKexNewKeys              <$> arbitrary
        , MsgKexEcdhInit             <$> arbitrary
        , MsgKexEcdhReply            <$> arbitrary
        , MsgUserAuthRequest         <$> arbitrary
        , MsgUserAuthFailure         <$> arbitrary
        , MsgUserAuthSuccess         <$> arbitrary
        , MsgUserAuthBanner          <$> arbitrary
        , MsgUserAuthPublicKeyOk     <$> arbitrary
        , MsgChannelOpen             <$> arbitrary
        , MsgChannelOpenConfirmation <$> arbitrary
        , MsgChannelOpenFailure      <$> arbitrary
        , MsgChannelData             <$> arbitrary
        , MsgChannelExtendedData     <$> arbitrary
        , MsgChannelEof              <$> arbitrary
        , MsgChannelClose            <$> arbitrary
        , MsgChannelRequest          <$> arbitrary
        , MsgChannelSuccess          <$> arbitrary
        , MsgChannelFailure          <$> arbitrary
        , MsgUnknown                 <$> elements [ 128, 255 ]
        ]

instance Arbitrary Disconnected where
    arbitrary = Disconnected <$> arbitrary <*> arbitrary <*> arbitrary

instance Arbitrary DisconnectReason where
    arbitrary = elements
        [ DisconnectHostNotAllowedToConnect
        , DisconnectProtocolError
        , DisconnectKeyExchangeFailed
        , DisconnectReserved
        , DisconnectMacError
        , DisconnectCompressionError
        , DisconnectServiceNotAvailable
        , DisconnectProtocolVersionNotSupported
        , DisconnectHostKeyNotVerifiable
        , DisconnectConnectionLost
        , DisconnectByApplication
        , DisconnectTooManyConnection
        , DisconnectAuthCancelledByUser
        , DisconnectNoMoreAuthMethodsAvailable
        , DisconnectIllegalUsername
        ]

instance Arbitrary Ignore where
    arbitrary = pure Ignore

instance Arbitrary Unimplemented where
    arbitrary = Unimplemented <$> arbitrary

instance Arbitrary Debug where
    arbitrary = Debug
        <$> arbitrary
        <*> elements [ "", "debug message", "debug message containing\n linefeeds\n\r" ]
        <*> elements [ "", "de_DE", "en_US" ]

instance Arbitrary ServiceRequest where
    arbitrary = ServiceRequest <$> arbitrary

instance Arbitrary ServiceAccept where
    arbitrary = ServiceAccept <$> arbitrary

instance Arbitrary KexInit where
    arbitrary = KexInit <$> arbitrary <*> nameList  <*> nameList  <*> nameList
                        <*> nameList  <*> nameList  <*> nameList  <*> nameList
                        <*> nameList  <*> nameList  <*> nameList  <*> arbitrary
        where
            nameList = elements [ [], ["abc"], ["abc","def"] ]

instance Arbitrary KexNewKeys where
    arbitrary = pure KexNewKeys

instance Arbitrary KexEcdhInit where
    arbitrary = KexEcdhInit <$> arbitrary

instance Arbitrary KexEcdhReply where
    arbitrary = KexEcdhReply <$> arbitrary <*> arbitrary <*> arbitrary

instance Arbitrary UserAuthRequest where
    arbitrary = UserAuthRequest <$> arbitrary <*> arbitrary <*> arbitrary

instance Arbitrary UserAuthFailure where
    arbitrary = UserAuthFailure <$> arbitrary <*> arbitrary

instance Arbitrary UserAuthSuccess where
    arbitrary = pure UserAuthSuccess

instance Arbitrary UserAuthBanner where
    arbitrary = UserAuthBanner <$> arbitrary <*> arbitrary

instance Arbitrary UserAuthPublicKeyOk where
    arbitrary = UserAuthPublicKeyOk <$> arbitrary

instance Arbitrary ChannelOpen where
    arbitrary = ChannelOpen <$> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary

instance Arbitrary ChannelOpenType where
    arbitrary = elements
        [ ChannelOpenSession
        , ChannelOpenDirectTcpIp "localhost" 8080 "10.0.0.1" 73594
        , ChannelOpenOther (ChannelType "other")
        ]

instance Arbitrary ChannelOpenConfirmation where
    arbitrary = ChannelOpenConfirmation <$> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary

instance Arbitrary ChannelOpenFailure where
    arbitrary = ChannelOpenFailure <$> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary

instance Arbitrary ChannelOpenFailureReason where
    arbitrary = elements
        [ ChannelOpenAdministrativelyProhibited
        , ChannelOpenConnectFailed
        , ChannelOpenUnknownChannelType
        , ChannelOpenResourceShortage
        ]

instance Arbitrary ChannelWindowAdjust where
    arbitrary = ChannelWindowAdjust <$> arbitrary <*> arbitrary

instance Arbitrary ChannelData where
    arbitrary = ChannelData <$> arbitrary <*> elements
        [ ""
        , "abc"
        , "asdhaskdjhaskhdkjahsdkjahsdkjhasdkjahdkj"
        ]

instance Arbitrary ChannelExtendedData where
    arbitrary = ChannelExtendedData <$> arbitrary <*> arbitrary <*> arbitrary

instance Arbitrary ChannelEof where
    arbitrary = ChannelEof <$> arbitrary

instance Arbitrary ChannelClose where
    arbitrary = ChannelClose <$> arbitrary

instance Arbitrary ChannelRequest where
    arbitrary = ChannelRequest <$> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary

instance Arbitrary ChannelRequestEnv where
    arbitrary = ChannelRequestEnv <$> arbitrary <*> arbitrary

instance Arbitrary ChannelRequestPty where
    arbitrary = ChannelRequestPty <$> arbitrary

instance Arbitrary ChannelRequestWindowChange where
    arbitrary = ChannelRequestWindowChange <$> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary

instance Arbitrary ChannelRequestShell where
    arbitrary = pure ChannelRequestShell

instance Arbitrary ChannelRequestExec where
    arbitrary = ChannelRequestExec <$> arbitrary

instance Arbitrary ChannelRequestSignal where
    arbitrary = ChannelRequestSignal <$> arbitrary

instance Arbitrary ChannelRequestExitStatus where
    arbitrary = ChannelRequestExitStatus <$> (arbitrary >>= \i-> pure $ if i == 0 then ExitSuccess else ExitFailure (abs i))

instance Arbitrary ChannelRequestExitSignal where
    arbitrary = ChannelRequestExitSignal <$> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary

instance Arbitrary ChannelSuccess where
    arbitrary = ChannelSuccess <$> arbitrary

instance Arbitrary ChannelFailure where
    arbitrary = ChannelFailure <$> arbitrary

instance Arbitrary Version where
    arbitrary = elements
        [ Version "SSH-2.0-OpenSSH_4.3"
        , Version "SSH-2.0-hssh_0.1"
        ]

instance Arbitrary PtySettings where
    arbitrary = PtySettings
        <$> elements [ "xterm", "urxvt-unicode", "urxvt-unicode-color256" ]
        <*> elements [ 80 ]
        <*> elements [ 24 ]
        <*> elements [ 640 ]
        <*> elements [ 480 ]
        <*> elements [ "\129\NUL\NUL\150\NUL\128\NUL\NUL\150\NUL\SOH\NUL\NUL\NUL\ETX\STX\NUL\NUL\NUL\FS\ETX\NUL\NUL\NUL\DEL\EOT\NUL\NUL\NUL\NAK\ENQ\NUL\NUL\NUL\EOT\ACK\NUL\NUL\NUL\NUL\a\NUL\NUL\NUL\NUL\b\NUL\NUL\NUL\DC1\t\NUL\NUL\NUL\DC3\n\NUL\NUL\NUL\SUB\f\NUL\NUL\NUL\DC2\r\NUL\NUL\NUL\ETB\SO\NUL\NUL\NUL\SYN\DC2\NUL\NUL\NUL\SI\RS\NUL\NUL\NUL\SOH\US\NUL\NUL\NUL\NUL \NUL\NUL\NUL\NUL!\NUL\NUL\NUL\NUL\"\NUL\NUL\NUL\NUL#\NUL\NUL\NUL\NUL$\NUL\NUL\NUL\SOH%\NUL\NUL\NUL\NUL&\NUL\NUL\NUL\SOH'\NUL\NUL\NUL\NUL(\NUL\NUL\NUL\NUL)\NUL\NUL\NUL\SOH*\NUL\NUL\NUL\SOH2\NUL\NUL\NUL\SOH3\NUL\NUL\NUL\SOH4\NUL\NUL\NUL\NUL5\NUL\NUL\NUL\SOH6\NUL\NUL\NUL\SOH7\NUL\NUL\NUL\SOH8\NUL\NUL\NUL\NUL9\NUL\NUL\NUL\NUL:\NUL\NUL\NUL\NUL;\NUL\NUL\NUL\SOH<\NUL\NUL\NUL\SOH=\NUL\NUL\NUL\SOH>\NUL\NUL\NUL\NULF\NUL\NUL\NUL\SOHG\NUL\NUL\NUL\NULH\NUL\NUL\NUL\SOHI\NUL\NUL\NUL\NULJ\NUL\NUL\NUL\NULK\NUL\NUL\NUL\NULZ\NUL\NUL\NUL\SOH[\NUL\NUL\NUL\SOH\\\NUL\NUL\NUL\NUL]\NUL\NUL\NUL\NUL\NUL" ]

deriving instance Arbitrary ChannelId
deriving instance Arbitrary ChannelType

instance Arbitrary Cookie where
    arbitrary = pure nilCookie

instance Arbitrary Password where
    arbitrary = elements $ fmap Password
        [ "1234567890"
        ]

instance Arbitrary AuthMethod where
    arbitrary = oneof
        [ pure AuthNone
        , pure AuthHostBased
        , AuthPassword  <$> arbitrary
        , AuthPublicKey <$> arbitrary <*> arbitrary
        ]

instance Arbitrary Name where
    arbitrary = elements [ "abc" ]

instance Arbitrary PublicKey where
    arbitrary = oneof
        [ PublicKeyEd25519           <$> x1
        , PublicKeyRSA               <$> x2
        , PublicKeyOther             <$> x3
        ]
        where
            x1 = pure $ case Ed25519.publicKey ("$\149\229m\164\ETB\GSA\ESC\185ThTc8\212\219\158\249\CAN\202\245\133\140a\bZQ\v\234\247x" :: BS.ByteString) of
              CryptoPassed pk -> pk
              CryptoFailed _  -> undefined
            x2 = pure $ RSA.PublicKey 24 65537 2834792
            x3 = pure "PUBLIC_KEY_OTHER"

instance Arbitrary Signature where
    arbitrary = oneof
        [ SignatureEd25519           <$> x1
        , SignatureRSA               <$> x2
        , pure (SignatureOther "ssh-other")
        ]
        where
            x1 = pure $ case Ed25519.signature ("\169\150V0\235\151\ENQ\149w\DC1\172wKV]W|\b\ETB\f@\158\178\254\158\168\v>\180&\164D\DELF\204\133p\186\195(\169\177\144\168\STX\DC2\153!B\252\154o\251\230\154\164T\223\243\148'i\a\EOT" :: BS.ByteString) of
              CryptoPassed sig -> sig
              CryptoFailed _   -> undefined
            x2 = pure "SIGNATURE_RSA"

instance Arbitrary Curve25519.PublicKey where
    arbitrary = pure $ case Curve25519.publicKey ("\179g~\181\170\169\154\205\211\ft\162\&0@0dO\FS\DLEA\166@[r\150t~W\221cOF" :: BS.ByteString) of
        CryptoPassed pk -> pk
        CryptoFailed _  -> undefined