fix(http): reject Hackney's certifi partial chains
Hackney 4 merges given ssl_options into its defaults and keeps its own partial_chain, which trusts any certificate in the peer chain that is in certifi. A peer could send the emSign ECC Root CA - G3 root in its chain and pass. Set partial_chain so certifi is never a trust anchor.
This commit is contained in:
parent
92a112cf15
commit
65076aa2f8
2 changed files with 15 additions and 3 deletions
|
|
@ -6,9 +6,11 @@ defmodule Pleroma.HTTP.TLS do
|
|||
@moduledoc """
|
||||
TLS client options that trust the CAStore bundle.
|
||||
|
||||
Hackney otherwise trusts its own certifi bundle, and it drops all of its
|
||||
Hackney otherwise trusts its own certifi bundle. Hackney 1 drops all of its
|
||||
default TLS options, including certificate checks, as soon as any
|
||||
`ssl_options` are given.
|
||||
`ssl_options` are given. Hackney 4 merges them, so `partial_chain` must be
|
||||
set too: Hackney's own one trusts any certificate in the peer chain that is
|
||||
in certifi.
|
||||
"""
|
||||
|
||||
@spec ssl_options(keyword()) :: keyword()
|
||||
|
|
@ -18,12 +20,16 @@ defmodule Pleroma.HTTP.TLS do
|
|||
verify: :verify_peer,
|
||||
cacertfile: CAStore.file_path(),
|
||||
depth: 20,
|
||||
customize_hostname_check: [match_fun: :public_key.pkix_verify_hostname_match_fun(:https)]
|
||||
customize_hostname_check: [match_fun: :public_key.pkix_verify_hostname_match_fun(:https)],
|
||||
partial_chain: &__MODULE__.reject_partial_chain/1
|
||||
],
|
||||
overrides
|
||||
)
|
||||
end
|
||||
|
||||
@doc false
|
||||
def reject_partial_chain(_certs), do: :unknown_ca
|
||||
|
||||
@spec put_hackney_ssl_options(keyword()) :: keyword()
|
||||
def put_hackney_ssl_options(opts) do
|
||||
if opts[:insecure] do
|
||||
|
|
|
|||
|
|
@ -17,6 +17,12 @@ defmodule Pleroma.HTTP.TLSTest do
|
|||
assert is_function(match_fun, 2)
|
||||
end
|
||||
|
||||
test "does not accept certificates from the peer chain as trust anchors" do
|
||||
partial_chain = TLS.ssl_options()[:partial_chain]
|
||||
|
||||
assert partial_chain.([:certificate]) == :unknown_ca
|
||||
end
|
||||
|
||||
test "keeps the CA bundle when other options are given" do
|
||||
opts = TLS.ssl_options(versions: [:"tlsv1.2"])
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue