2016-05-20 14 views
1

私はhttp-conduitを使用してプログラムを作成しました。有効なTLS証明書を持っていないサーバーと通信する必要があります。この場合、自己署名証明書です。http-conduitで自己署名証明書を受け入れる方法を教えてください。

HTTPS-test.hs

#!/usr/bin/env stack 
-- stack --install-ghc --resolver lts-5.13 runghc --package http-conduit 
{-# LANGUAGE OverloadedStrings #-} 
import qualified Data.ByteString.Char8 as S8 
import qualified Data.ByteString.Lazy.Char8 as L8 
import   Network.HTTP.Client 
import   Network.HTTP.Simple 
import   Network.Connection 
       (TLSSettings(..)) 

main :: IO() 
main = do 
    authenticate "self-signed.badssl.com" "" "" 

authenticate :: S8.ByteString 
      -> L8.ByteString 
      -> L8.ByteString 
      -> IO() 
authenticate hostname username password = do 
    let request 
     = setRequestMethod "GET" 
     $ setRequestSecure True 
     $ setRequestPort 443 
     $ setRequestHost hostname 
     $ setRequestPath "/" 
     $ defaultRequest 
    response <- httpLBS request 
    putStrLn $ "The status code was: " ++ 
      show (getResponseStatusCode response) 
    print $ getResponseHeader "Content-Type" response 
    L8.putStrLn $ getResponseBody response 

の予想される出力

The status code was: 200 
["text/html"] 
<!DOCTYPE html> 
<html> 
<head> 
    <meta name="viewport" content="width=device-width, initial-scale=1"> 
    <link rel="shortcut icon" href="/icons/favicon-red.ico"/> 
    <link rel="apple-touch-icon" href="/icons/icon-red.png"/> 
    <title>self-signed.badssl.com</title> 
    <link rel="stylesheet" href="/style.css"> 
    <style>body { background: red; }</style> 
</head> 
<body> 
<div id="content"> 
    <h1 style="font-size: 12vw;"> 
    self-signed.<br>badssl.com 
    </h1> 
</div> 

</body> 
</html> 

実際の出力:

https-test.hs: TlsExceptionHostPort (HandshakeFailed (Error_Protocol ("certificate rejected: [SelfSigned]",True,CertificateUnknown))) "self-signed.badssl.com" 443 

答えて

2

これは多くの理由のため非常に悪い考えです。あなたはサーバを修理するよりはるかに良い(できれば)か、それを修理するためにそれを実行する人々を励ます。

TLS証明書の検証をバイパスすると、中間者の人間の姿勢の攻撃者がサーバーとなり、データを操作することが簡単になるため、TLSのすべての有用な側面が削除されます。すべての攻撃者は、傍受され操作されたコンテンツを別の悪い自己署名証明書で再暗号化する必要があります。お客様のクライアントソフトウェアは誰にも賢明ではありません。

http-conduitは、要求マネージャの概念をサポートしています。リクエストマネージャを使用すると、代替機能を提供できます。

まずサーバー証明書の検証(TLSSettingsSimple is defined in Network.Connection in the connection package)を無効にTLSSettingsSimpleを構築することができます。

noVerifyTlsSettings :: TLSSettings 
noVerifyTlsSettings = TLSSettingsSimple 
    { settingDisableCertificateValidation = True 
    , settingDisableSession = True 
    , settingUseServerName = False 
    } 

その後、あなたはそれ(mkManagerSettings comes from the Network.HTTP.Client.TLS module in the http-client-tls package)を使用して、要求管理を行うことができます。

noVerifyTlsManagerSettings :: ManagerSettings 
noVerifyTlsManagerSettings = mkManagerSettings noVerifyTlsSettings Nothing 

次に、あなたがすることができますこのリクエストマネージャを初期化し、リクエストで設定します。

manager <- newManager noVerifyTlsManagerSettings 
-- ... 
$ setRequestManager manager 
-- ... 

また、あなたがこれを含めるようにスタックの引数を変更する必要があり、このためパッケージで提供HTTPクライアント-TLSを持っている必要があります:

--package http-client-tls 

ここで完全なソリューションがあります:

#!/usr/bin/env stack 
-- stack --install-ghc --resolver lts-5.13 runghc --package http-client-tls 
{-# LANGUAGE OverloadedStrings #-} 
import qualified Data.ByteString.Char8 as S8 
import qualified Data.ByteString.Lazy.Char8 as L8 
import   Network.HTTP.Client 
import   Network.HTTP.Client.TLS (mkManagerSettings) 
import   Network.HTTP.Simple 
import   Network.Connection (TLSSettings(..)) 

main :: IO() 
main = do 
    authenticate "self-signed.badssl.com" "" "" 

authenticate :: S8.ByteString 
      -> L8.ByteString 
      -> L8.ByteString 
      -> IO() 
authenticate hostname username password = do 
    manager <- newManager noVerifyTlsManagerSettings 
    let request 
     = setRequestMethod "GET" 
     $ setRequestSecure True 
     $ setRequestPort 443 
     $ setRequestHost hostname 
     $ setRequestPath "/" 
     $ setRequestManager manager 
     $ defaultRequest 
    response <- httpLBS request 
    putStrLn $ "The status code was: " ++ 
      show (getResponseStatusCode response) 
    print $ getResponseHeader "Content-Type" response 
    L8.putStrLn $ getResponseBody response 

noVerifyTlsManagerSettings :: ManagerSettings 
noVerifyTlsManagerSettings = mkManagerSettings noVerifyTlsSettings Nothing 

noVerifyTlsSettings :: TLSSettings 
noVerifyTlsSettings = TLSSettingsSimple 
    { settingDisableCertificateValidation = True 
    , settingDisableSession = True 
    , settingUseServerName = False 
    } 
関連する問題