diff --git a/changelog.d/hackney-castore.security b/changelog.d/hackney-castore.security index 44cb90ce6..8d1a0cf4a 100644 --- a/changelog.d/hackney-castore.security +++ b/changelog.d/hackney-castore.security @@ -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 diff --git a/lib/pleroma/emails/mailer.ex b/lib/pleroma/emails/mailer.ex index fa6fd8020..e6abf4456 100644 --- a/lib/pleroma/emails/mailer.ex +++ b/lib/pleroma/emails/mailer.ex @@ -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 diff --git a/test/pleroma/emails/mailer_test.exs b/test/pleroma/emails/mailer_test.exs index 2c2b5a4af..d42e8b723 100644 --- a/test/pleroma/emails/mailer_test.exs +++ b/test/pleroma/emails/mailer_test.exs @@ -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