Skip to content

Instantly share code, notes, and snippets.

@creichert
Last active January 9, 2020 19:39
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save creichert/4f8adbfcf165191e90c94c5bd1d2e4d9 to your computer and use it in GitHub Desktop.
Save creichert/4f8adbfcf165191e90c94c5bd1d2e4d9 to your computer and use it in GitHub Desktop.
Customize haskell http-client supported TLS ciphers
#!/usr/bin/env stack
-- stack -v runghc --package connection --package http-client --package http-client-tls --package tls --package data-default
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ViewPatterns #-}
{-# OPTIONS_GHC -fno-warn-deprecations #-}
import qualified Network.Connection as NC
import qualified Network.HTTP.Client as Http
import qualified Network.HTTP.Client.TLS as Http
import qualified Network.TLS as TLS
import qualified Network.TLS.Extra as TLS (ciphersuite_all)
import qualified System.X509 as TLS
import Data.Default
import Data.Maybe
import Network.HTTP.Client
import Network.HTTP.Client.TLS
import System.Environment
import Prelude
main :: IO ()
main = do
murl <- getArgs
case listToMaybe murl of
(fmap parseUrl -> Just (Just req)) -> do
mgr <- mkHttpManager True
res <- httpLbs req mgr
print (show (responseStatus res))
_ -> error "usage: fetch-url [URL] (must include http:// or https://"
-- | Create an HTTP 'Manager' for running a 'Test'
mkHttpManager :: Bool -- ^ validate ssl
-> IO Manager
mkHttpManager validateSsl = do
scs <- TLS.getSystemCertificateStore
let tlsSettings = NC.TLSSettings (cp scs)
mngrCfg = Http.mkManagerSettings tlsSettings Nothing
Http.newManager mngrCfg
where
cp scs = (TLS.defaultParamsClient "" "") {
TLS.clientSupported = def {
TLS.supportedCiphers = TLS.ciphersuite_all
, TLS.supportedHashSignatures = hashSignatures
-- , TLS.supportedVersions [TLS10, TLS11, TLS12]
}
, TLS.clientShared = def {
TLS.sharedCAStore = scs
, TLS.sharedValidationCache = validationCache
}
}
hashSignatures =
[ (TLS.HashSHA512, TLS.SignatureRSA)
, (TLS.HashSHA384, TLS.SignatureRSA)
, (TLS.HashSHA256, TLS.SignatureRSA)
, (TLS.HashSHA224, TLS.SignatureRSA)
, (TLS.HashSHA1, TLS.SignatureRSA)
, (TLS.HashSHA1, TLS.SignatureDSS)
, (TLS.HashSHA512, TLS.SignatureECDSA) -- "bad SignatureECDSA for ecdhparams"
, (TLS.HashSHA384, TLS.SignatureECDSA) -- "bad SignatureECDSA for ecdhparams"
, (TLS.HashSHA256, TLS.SignatureECDSA)
, (TLS.HashSHA224, TLS.SignatureECDSA)
, (TLS.HashSHA1, TLS.SignatureECDSA)
]
validationCache =
if not validateSsl then
TLS.ValidationCache
(\_ _ _ -> return TLS.ValidationCachePass)
(\_ _ _ -> return ())
else
def
@creichert
Copy link
Author

Keep in mind two ciphers in this list may not work as expected for now:

        , (TLS.HashSHA512, TLS.SignatureECDSA) -- "bad SignatureECDSA for ecdhparams"
        , (TLS.HashSHA384, TLS.SignatureECDSA) -- "bad SignatureECDSA for ecdhparams"

@delanoe
Copy link

delanoe commented Dec 1, 2016

Thanks for this example.
If one uncomments and adapts the line number 49 of the script above like this:
, TLS.supportedVersions = [TLS10, TLS11]
do you confirm that the client will use these versions only ?
(I am trying to debug an error of TLS version with a server which supports TLS10 or TLS11 only).
Thanks for your confirmation.
(I can confirm that it compiles and can be run like this by the way but wonder about the expected behavior since I still notice my bug that may deal with something else).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment