Search code examples
haskellsslconduithttp-conduit

Disable SSL/TLS certificate validation in Network.HTTP.Conduit


I use the http-conduit library version 2.0+ to fetch the contents from a http:// URL:

import Network.HTTP.Conduit
myurl = ... -- Your URL goes here
main = do content <- simpleHttp myurl
          print $ content

When running this program, I get this error:

*** Exception: TlsException (HandshakeFailed (Error_Protocol
      ("certificate rejected: certificate is not allowed to sign another certificate",
        True,CertificateUnknown)))

As can be told from the error message, the problem is the inability of Network.HTTP.Conduit to validate the server certificate appropriately (in this case, there seem to be problems in the certificate chain)

How can I change the above code to ignore the certificate error (i.e. by not verifying certificates at all)?


Solution

  • simpleHttp itself does not support this feature. You'll need to create a manager with modified ManagerSettings and then use that to fetch the URL.

    Note that this code only applies for http-conduits version 2.0+ -- the library version 1 has a similar yet different API for this purpose.

    import Network.HTTP.Conduit
    import Network.Connection
    import qualified Data.ByteString.Lazy.Char8 as LB
    
    myurl = ... -- Your URL goes here
    
    -- | Get a new Manager that doesn't verify SSL certificates
    noSSLVerifyManager :: IO Manager
    noSSLVerifyManager = let tlsSettings = TLSSettingsSimple {
                                -- This is where we disable certificate verification
                                settingDisableCertificateValidation = True,
                                settingDisableSession=False,
                                settingUseServerName=True}
                         in newManager $ mkManagerSettings tlsSettings Nothing
    
    -- | Download like with simpleHttp, but using an existing manager for the task
    simpleHttpWithManager :: Manager -> String -> IO LB.ByteString
    simpleHttpWithManager manager url = do url' <- parseUrl url
                                           fmap responseBody $ httpLbs url' manager
    
    main = do manager <- noSSLVerifyManager
              content <- simpleHttpWithManager manager myurl
              print $ content
    

    Note that you should only disable SSL certificate verification if absolutely neccessary, as it makes you vulnerable for man-in-the-middle attacks