Merge branch 'fix/emudhra-ca-trust' (#77) into release/2.11

# Conflicts:
#	lib/pleroma/http/adapter_helper/hackney.ex
#	mix.lock
This commit is contained in:
Lain Soykaf 2026-10-22 10:05:45 +04:00
commit e0ed6b5d39
No known key found for this signature in database
12 changed files with 144 additions and 12 deletions

View file

@ -66,6 +66,7 @@ defmodule Pleroma.Application do
if match?({Tesla.Adapter.Finch, _}, adapter) do
Logger.info("Starting Finch")
use_castore_for_otp_cacerts()
Finch.start_link(name: MyFinch)
end
@ -304,6 +305,15 @@ defmodule Pleroma.Application do
end
end
# Mint trusts the OTP CA store, which comes from the OS. Make it the CAStore
# bundle that the other adapters trust. OTP 24 has no such store and Mint
# uses CAStore there anyway.
defp use_castore_for_otp_cacerts do
if Code.ensure_loaded?(:public_key) and function_exported?(:public_key, :cacerts_load, 1) do
:ok = :public_key.cacerts_load(CAStore.file_path())
end
end
defp http_children_hackney do
pools = [:federation, :media]

View file

@ -36,10 +36,11 @@ defmodule Pleroma.Emails.Mailer do
def deliver(email, config \\ [])
def deliver(email, config) do
# temporary hackney fix until hackney max_connections bug is fixed
# https://git.pleroma.social/pleroma/pleroma/-/issues/2101
# Swoosh HTTP adapters use Hackney, which otherwise trusts its certifi bundle
email =
Swoosh.Email.put_private(email, :hackney_options, ssl_options: [versions: [:"tlsv1.2"]])
Swoosh.Email.put_private(email, :hackney_options,
ssl_options: Pleroma.HTTP.TLS.ssl_options()
)
case enabled?() do
true -> Swoosh.Mailer.deliver(email, parse_config(config))

View file

@ -30,6 +30,7 @@ defmodule Pleroma.HTTP.AdapterHelper.Hackney do
|> Pleroma.HTTP.AdapterHelper.maybe_add_proxy(proxy)
|> Keyword.put(:follow_redirect, false)
|> Keyword.put(:force_redirect, false)
|> Pleroma.HTTP.TLS.put_hackney_ssl_options()
end
defp add_scheme_opts(opts, _), do: opts

41
lib/pleroma/http/tls.ex Normal file
View file

@ -0,0 +1,41 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.HTTP.TLS do
@moduledoc """
TLS client options that trust the CAStore bundle.
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. 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()
def ssl_options(overrides \\ []) do
Keyword.merge(
[
verify: :verify_peer,
cacertfile: CAStore.file_path(),
depth: 20,
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
opts
else
Keyword.put(opts, :ssl_options, ssl_options(Keyword.get(opts, :ssl_options, [])))
end
end
end

View file

@ -28,9 +28,9 @@ defmodule Pleroma.ReverseProxy.Client.Hackney do
@impl true
def request(method, url, headers, body, opts \\ []) do
opts =
Keyword.put_new(opts, :path_encode_fun, fn path ->
path
end)
opts
|> Keyword.put_new(:path_encode_fun, fn path -> path end)
|> Pleroma.HTTP.TLS.put_hackney_ssl_options()
if opts[:follow_redirect] != false do
{_state, req_opts} = Access.get_and_update(opts, :follow_redirect, fn a -> {a, false} end)