HTTPieはシステム証明書を無視します
http --debug -j https://example_using_my_ca.com
HTTPie 0.9.3
HTTPie data: /home/lukas/.httpie
Requests 2.10.0
Pygments 1.6
Python 3.4.3 (default, Oct 14 2015, 20:28:29)
[GCC 4.8.4] linux
>>> requests.request(**{'allow_redirects': False,
'auth': None,
'cert': None,
'data': '',
'files': DataDict(),
'headers': {'Accept': b'application/json',
'Content-Type': b'application/json',
'User-Agent': b'HTTPie/0.9.3'},
'method': 'get',
'params': ParamsDict(),
'proxies': {},
'stream': True,
'timeout': 30,
'url': 'https://example_using_my_ca.com',
'verify': True})
Traceback (most recent call last):
File "/usr/local/lib/python3.4/dist-packages/requests/packages/urllib3/connectionpool.py", line 578, in urlopen
chunked=chunked)
File "/usr/local/lib/python3.4/dist-packages/requests/packages/urllib3/connectionpool.py", line 351, in _make_request
self._validate_conn(conn)
File "/usr/local/lib/python3.4/dist-packages/requests/packages/urllib3/connectionpool.py", line 814, in _validate_conn
conn.connect()
File "/usr/local/lib/python3.4/dist-packages/requests/packages/urllib3/connection.py", line 289, in connect
ssl_version=resolved_ssl_version)
File "/usr/local/lib/python3.4/dist-packages/requests/packages/urllib3/util/ssl_.py", line 308, in ssl_wrap_socket
return context.wrap_socket(sock, server_hostname=server_hostname)
File "/usr/lib/python3.4/ssl.py", line 365, in wrap_socket
_context=self)
File "/usr/lib/python3.4/ssl.py", line 601, in __init__
self.do_handshake()
File "/usr/lib/python3.4/ssl.py", line 828, in do_handshake
self._sslobj.do_handshake()
ssl.SSLError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:600)
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/usr/local/lib/python3.4/dist-packages/requests/adapters.py", line 403, in send
timeout=timeout
File "/usr/local/lib/python3.4/dist-packages/requests/packages/urllib3/connectionpool.py", line 604, in urlopen
raise SSLError(e)
requests.packages.urllib3.exceptions.SSLError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:600)
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/usr/local/bin/http", line 11, in <module>
sys.exit(main())
File "/usr/local/lib/python3.4/dist-packages/httpie/core.py", line 115, in main
response = get_response(args, config_dir=env.config.directory)
File "/usr/local/lib/python3.4/dist-packages/httpie/client.py", line 48, in get_response
response = requests_session.request(**kwargs)
File "/usr/local/lib/python3.4/dist-packages/requests/sessions.py", line 475, in request
resp = self.send(prep, **send_kwargs)
File "/usr/local/lib/python3.4/dist-packages/requests/sessions.py", line 585, in send
r = adapter.send(request, **kwargs)
File "/usr/local/lib/python3.4/dist-packages/requests/adapters.py", line 477, in send
raise SSLError(e, request=request)
requests.exceptions.SSLError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:600)
参考までに、curlは正常に機能します: curl https://example_using_my_ca.com
ssl.get_default_verify_paths()を使用してデフォルトのパスを取得することは意味がありますか?
私は次の行動を提案します:
--verifyにnoまたはyes以外のパラメーターが渡された場合は、パラメーターをリクエストに渡します。
--verifyがyesに設定されている場合:
1)REQUESTS_CA_BUNDLEが設定されている場合は、検証要求にTrueを渡します。
2)elif環境変数ssl.get_default_verify_paths()。openssl_cafile_envが設定されている場合は、それをリクエストに渡します。
4)elif環境変数ssl.get_default_verify_paths()。openssl_capath_envが設定され、それをリクエストに渡します。
5)elif ssl.get_default_verify_paths()。capathがNoneでない場合は、それをリクエストに渡します。
6)それ以外の場合はTrueをリクエスト検証に渡します
ただし、ssl.get_default_verify_pathsはpython3.4以降でのみ使用可能であることに注意してください
@luvは、3.4以降と2.7.10以降でのみ利用できるだけでなく、すべてのプラットフォームで機能するとは
@ sigmavirus24 wtf man? 絶えずコメントすることの意味はわかりませんが、何であれ、あなたはhttpieの寄稿者でさえありません。 私はただの愚かなトロールを想定しています:/
curlソースコードをざっと見て、動作する実装がどのように見えるかを確認してください...。
これらすべてのamigaおよびVMSifdefと、多くの異なるsslライブラリのサポートを無視すると、実際にはかなりばかげており、openssl X509_ *ルックアップメソッドを使用していません(たとえば、Python SSLモジュールのget_default_verify_paths()で使用されます)。
代わりに、curlはコンパイル時に既知の場所の束を単純に繰り返し(このm4dness https://github.com/curl/curl/blob/master/acinclude.m4#L2560を参照)、(CURL_CA_BUNDLEおよび)実行時のSSL_CERT_DIRおよびSSL_CERT_FILE環境変数(ここでもX509_get_default_cert_file_env()などを使用していません)。 それでおしまい。
では、純粋なPythonで同じアプローチを実装するのはどうですか? (はい、それは地獄のように速くて汚いように見えますが、カールには機能します!)しかし、Windows(ssl.enum_certificates?)とOS X(ここではわかりませんが、PythonはOS X10.6 +でアップル提供のopensslライブラリを使用しているようですだからそれはすでに大丈夫なはずです!)。
@luvレポートに感謝しますが、他のメンバーにもっと敬意を払ってください。 @ sigmavirus24は、
これは3.0.0リリースまでリクエストで修正されないことに注意してください...互換性の問題が発生する可能性があるため、SSL_CERT_FILEもサポートされませんhttps://github.com/kennethreitz/requests/pull/2903
ところで。 私は彼/彼がトローリングしていると本当に思っていたので失礼なことを意味しませんでした:)私は問題の修正とプロジェクトに一度も貢献したことがない誰かを見つけるのを手伝うために道を外しました(そのような敵対的な反応に本当に驚いた)基本的に私に黙るように言っていた:/
@luv私はあなたに
最後に、コードの貢献だけがプロジェクトへの貢献ではありません。 プロジェクトのすべての貢献を確認したい場合は、 octohatrackのようなプロジェクトを使用できます。 httpie for @jkbrztのバグに関連するいくつかのリクエストに対応しました。リクエストの開発をフォローする時間があまりないためです。 ここでリクエスト関連のバグを見つけたら、99%の確率ですでに処理されているため、応答します。 @jkbrztにとって幸運なことに、私は以前は貧弱な(そして数倍悪い)扱いを受けていたので、肌が厚くなっています。
ちなみに、「彼ら」は「彼/彼」と同じ数の文字であり、1人の人物を指すためにも使用できるため、はるかに一般的に適用できます。
だから私たちはこれを修正していますか?
@jkbrztこれをバグではなく機能と呼びます。 リクエストがWindows、* nix、およびBSD間で同じように機能することは意図的であり、実際、リクエストの多くのシステムディストリビューションはその動作を積極的に削除し、システム証明書ストア/バンドルを指し示します。 したがって、ユーザーがこの動作を必要とする場合は、システムディストリビューターによってパッケージ化されたバージョンのリクエストをHTTPie(および場合によってはシステムパッケージ化されたHTTPie)とともに使用できます。
「これを修正する」に関しては、修正の定義によって異なります。 これは、リクエストに追加される機能です。 その時点で、HTTPieは無料で動作を取得します。 代わりにHTTPieがこれをより高い優先度と見なす場合( 適切と行う可能性があります)、開発作業を複製して、これをより早く行うリリースを作成できます。
Linux、 @ luvを使用しているように見えるので、Linuxのディストリビューションには、今日のシステム証明書ストアを使用するバージョンのRequestsがほぼ確実に含まれているという事実を利用できます。 リクエストは、私がチェックしたLinuxのすべてのディストリビューションにパッケージ化されており、それらのディストリビューションのほとんどすべてがシステム証明書ストアを使用しています。 そうでない場合は、おそらくそのディストリビューションのRequestsパッケージメンテナにバグを報告する必要があります。
apt(ubuntu 14.04lts)を介してインストールされたHTTPieと同じ確率
@luvは、14.04と16.04のリクエストがシステム証明書ストアを使用することを知っているので、驚くべきことです。 Requestsをどのようにインストールしましたか?
httpieのubuntuディストリビューションが使用されていることを確認するために、すべての「リクエスト」バージョンと「httpie」バージョンを削除しました。これは、PyPIのhttpieをまだ使用していたことです。 Ubuntu httpieは、既知の問題である「ImportError:cannot importnameis_windows」で失敗します。
そもそもsslを動作させるためにpython3を使用する必要があったため、「pip3アンインストール」を実行するのを忘れて「pipアンインストール」のみを実行したと思います。
私のhttpie設定の説明を付けて、761人に「スパム」を送信してしまったことをお詫びします。
私はGentooLinux、httpie-0.9.9およびrequests-2.18.4(Gentooで利用可能な最新)をパッケージマネージャーによってシステム全体にインストールし、他のバージョンはインストールしていません(pipもインストールしていません)。 他のツール(openssl s_client、sslclient、curl)は、インストールされているローカルCA証明書を検出して正常に動作しますが、httpieは失敗します。
$ openssl s_client -quiet -connect localhost:8082
depth=1 CN = Local CA home.lan
verify return:1
depth=0 CN = localhost
verify return:1
^C
$ http -v https://localhost:8082/
http: error: SSLError: HTTPSConnectionPool(host='localhost', port=8082): Max retries exceeded with url: / (Caused by SSLError(SSLError("bad handshake: Error([('SSL routines', 'ssl3_get_server_certificate', 'certificate verify failed')],)",),)) while doing GET request to URL: https://localhost:8082/
それを機能させるために何かを更新する必要がありますか?
@powermanこれは、これらのパッケージのgentoo再配布者にとってより適切な質問です。
@ sigmavirus24それはなぜですか? 私の質問は、これらのリクエスト/ httpieバージョンがシステムCAリストを処理することになっているのかどうかです。 はいの場合、システムで何かが正しく構成されていないか、バグがある可能性があります。 いいえの場合、それを機能させるために必要なバージョン。
@powerman何も変わっていません。 どちらもシステム証明書バンドルをサポートしていませんが、ディストリビューションのパッケージマネージャーから両方をインストールした場合は、それらを使用するようにソフトウェアにパッチが適用されている可能性があります。 Gentooで利用可能なパッケージを使用していて、それらがシステム証明書を使用していない場合、それはGentooの問題です。
これについてもう1つコメントを追加します。SSL要求を行うときに、プロキシと宛先の間に別のトンネルを確立するように特別に設計されたプロキシを使用します。 これは、プロキシを通過するトラフィックを安全に監視して、だれも厄介なことをしてそれを隠そうとしないようにするためです。 残念ながら、これはhttpieが取得する証明書が信頼されていないことを意味します(システムルートにあるが、httpieはそれを使用しないため)。
NixOSでも同じ問題を実際に再現できます。
4年以上後..。