10

I am using http-client-tls to connect to a TLS-enabled server that requires a client certificate. I suspect I need to tweak TLSSettings with a loaded certificate and correct cypher-suites parameters but it is definitely not clear how to do this.

Does anybody have some example code that uses client-side certificates?

insitu
  • 4,488
  • 3
  • 25
  • 42
  • Currently trying to follow hints in this thread: https://groups.google.com/forum/#!topic/yesodweb/yJliYgU-NE4 – insitu Oct 17 '16 at 08:17

1 Answers1

9

Thanks to Moritz Agerman for sharing his code. Here is a full Haskell module that can use crt.pem and key.pem files to provide client-side certificate as requested by server:

 {-# LANGUAGE OverloadedStrings #-}
 module TLS where

 import           Data.Default
 import           Network.Connection
 import           Network.HTTP.Client
 import           Network.HTTP.Client.TLS
 import           Network.TLS
 import           Network.TLS.Extra.Cipher
 import           Servant.Client

 makeClientManager :: String -> Scheme -> IO Manager
 makeClientManager hostname Https = mkMngr hostname "crt.pem" "key.pem"
 makeClientManager _        Http  = newManager defaultManagerSettings

 mkMngr :: String -> FilePath -> FilePath -> IO Manager
 mkMngr hostName crtFile keyFile = do
   creds <- either error Just `fmap` credentialLoadX509 crtFile keyFile
   let hooks = def
               { onCertificateRequest = \_ -> return creds
               , onServerCertificate = \_ _ _ _ -> return []
               }
       clientParams = (defaultParamsClient hostName  "")
                      { clientHooks = hooks
                      , clientSupported = def { supportedCiphers = ciphersuite_all }
                      }
       tlsSettings = TLSSettings clientParams

   newManager $ mkManagerSettings tlsSettings Nothing

Not sure if this does bypass server certificate validation or not as onServerCertificate hook is a constant [].

insitu
  • 4,488
  • 3
  • 25
  • 42
  • 5
    To answer your question, your code does bypass server certificate validation. Anyone using this code should remove the `onServerCertificate` line unless they know what they're doing. As it is, this code is dangerous. – mmalone Jan 24 '17 at 01:47
  • Thanks, I am aware of this shortcoming. – insitu Jan 24 '17 at 09:33
  • 2
    Why is there a `hostname`? How does the manager use this name when connecting to different servers? – Yuri Syro Feb 06 '19 at 16:02