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

This commit is contained in:
Lain Soykaf 2026-10-22 11:27:15 +04:00
commit fc91131892
No known key found for this signature in database
6 changed files with 100 additions and 4 deletions

View file

@ -1 +1 @@
Hackney and Finch now trust only the CAStore certificate bundle, which rejects the compromised eMudhra intermediate CAs
Hackney, Finch, Mua and the Swoosh HTTP mail adapters now trust only the CAStore certificate bundle, which rejects the compromised eMudhra intermediate CAs

View file

@ -68,6 +68,21 @@ defmodule Pleroma.Emails.Mailer do
end
defp parse_config(config) do
Swoosh.Mailer.parse_config(@otp_app, __MODULE__, @mailer_config, config)
@otp_app
|> Swoosh.Mailer.parse_config(__MODULE__, @mailer_config, config)
|> put_mua_cacertfile()
end
@doc false
# Mua otherwise trusts the OS CA store. Keep a CA that the admin set.
def put_mua_cacertfile(config) do
ssl = Keyword.get(config, :ssl, [])
if config[:adapter] == Swoosh.Adapters.Mua and
not Keyword.has_key?(ssl, :cacertfile) and not Keyword.has_key?(ssl, :cacerts) do
Keyword.put(config, :ssl, [{:cacertfile, CAStore.file_path()} | ssl])
else
config
end
end
end

View file

@ -46,6 +46,24 @@ defmodule Pleroma.HTTP.AdapterHelper do
|> adapter_helper().options(uri)
end
@doc """
The configured Tesla adapter with TLS options, for clients that do not go
through `Pleroma.HTTP`.
"""
@spec tesla_adapter() :: module() | {module(), keyword()}
def tesla_adapter do
case adapter() do
Tesla.Adapter.Hackney ->
{Tesla.Adapter.Hackney, Pleroma.HTTP.TLS.put_hackney_ssl_options([])}
Tesla.Adapter.Gun ->
{Tesla.Adapter.Gun, certificates_verification: true}
adapter ->
adapter
end
end
defp adapter, do: Application.get_env(:tesla, :adapter)
defp adapter_helper do

View file

@ -160,7 +160,7 @@ defmodule Pleroma.Search.QdrantSearch.OpenAIClient do
end
defp client do
Tesla.client(middleware())
Tesla.client(middleware(), Pleroma.HTTP.AdapterHelper.tesla_adapter())
end
defp middleware do
@ -191,7 +191,7 @@ defmodule Pleroma.Search.QdrantSearch.QdrantClient do
end
defp client do
Tesla.client(middleware())
Tesla.client(middleware(), Pleroma.HTTP.AdapterHelper.tesla_adapter())
end
defp middleware do

View file

@ -61,4 +61,33 @@ defmodule Pleroma.Emails.MailerTest do
assert hackney_options[:ssl_options] ==
Pleroma.HTTP.TLS.ssl_options()
end
describe "put_mua_cacertfile/1" do
test "makes Mua trust the CAStore bundle" do
config = Mailer.put_mua_cacertfile(adapter: Swoosh.Adapters.Mua, relay: "mail.example.com")
assert config[:ssl] == [cacertfile: CAStore.file_path()]
assert config[:relay] == "mail.example.com"
end
test "keeps other ssl options" do
config = Mailer.put_mua_cacertfile(adapter: Swoosh.Adapters.Mua, ssl: [depth: 3])
assert config[:ssl] == [cacertfile: CAStore.file_path(), depth: 3]
end
test "keeps a CA that the admin set" do
config = [adapter: Swoosh.Adapters.Mua, ssl: [cacertfile: "/etc/ssl/smtp.pem"]]
assert Mailer.put_mua_cacertfile(config) == config
config = [adapter: Swoosh.Adapters.Mua, ssl: [cacerts: []]]
assert Mailer.put_mua_cacertfile(config) == config
end
test "leaves other adapters alone" do
config = [adapter: Swoosh.Adapters.SMTP, relay: "mail.example.com"]
assert Mailer.put_mua_cacertfile(config) == config
end
end
end

View file

@ -0,0 +1,34 @@
# Pleroma: A lightweight social networking server
# Copyright © 2017-2022 Pleroma Authors <https://pleroma.social/>
# SPDX-License-Identifier: AGPL-3.0-only
defmodule Pleroma.HTTP.AdapterHelper.TeslaAdapterTest do
use ExUnit.Case, async: false
alias Pleroma.HTTP.AdapterHelper
alias Pleroma.HTTP.TLS
setup do
adapter = Application.get_env(:tesla, :adapter)
on_exit(fn -> Application.put_env(:tesla, :adapter, adapter) end)
end
test "adds the TLS options to Hackney" do
Application.put_env(:tesla, :adapter, Tesla.Adapter.Hackney)
assert AdapterHelper.tesla_adapter() ==
{Tesla.Adapter.Hackney, ssl_options: TLS.ssl_options()}
end
test "turns on certificate checks for Gun" do
Application.put_env(:tesla, :adapter, Tesla.Adapter.Gun)
assert AdapterHelper.tesla_adapter() == {Tesla.Adapter.Gun, certificates_verification: true}
end
test "keeps other adapters" do
Application.put_env(:tesla, :adapter, {Tesla.Adapter.Finch, name: MyFinch})
assert AdapterHelper.tesla_adapter() == {Tesla.Adapter.Finch, name: MyFinch}
end
end