andrewtimberlake / mailroom

Mail handling for Elixir
MIT License
21 stars 18 forks source link

Warning: "Authenticity is not established by certificate path validation" #13

Closed Flying-Toast closed 1 year ago

Flying-Toast commented 1 year ago

When running Mailroom.IMAP.connect() in elixir 1.14.1, I get the following warning:

12:18:20.433 [warning] Description: 'Authenticity is not established by certificate path validation'
     Reason: 'Option {verify, verify_peer} and cacertfile/cacerts is missing'
eriknaslund commented 1 year ago

I'm experiencing the same issue, and couldn't find an easy way to fix it.

The important code paths are outlined below.

defmodule Mailroom.IMAP do
    ....
    def connect(server, username, password, options \\ []) do
        opts = parse_opts(options)
        {:ok, pid} = GenServer.start_link(__MODULE__, opts)
        GenServer.call(pid, {:connect, server, opts.port})

    ...

    def handle_call({:connect, server, port}, from, state) do
        {:ok, socket} = Socket.connect(server, port, ssl: state.ssl, debug: state.debug, active: true)
    ....
defmodule Mailroom.Socket do
    ...
    @connect_opts [packet: :line, reuseaddr: true, active: false, keepalive: true]
    @ssl_connect_opts [depth: 0]
    def connect(server, port, opts \\ []) do
        ...
        case do_connect(addr, state.ssl, port, [:binary | connect_opts], state.timeout) do
        ...

    defp do_connect(addr, true, port, opts, timeout),
        do: :ssl.connect(addr, port, opts, timeout)

We would probably either need to properly set up certification using certifi (or similar):

CaCerts = certifi:cacerts(),
SslOptions = [
    {verify, verify_peer},
    {cacerts, CaCerts}
]

and then pass this into :ssl.connect opts, or at least allow us to pass in [{verify, verify_none}] as opts.

andrewtimberlake commented 1 year ago

I have made a change in #16 that allows you to pass ssl_opts: [verify: :verify_none] or other ssl specific options into the connect function of each sub-library The tests all use ssl_opts: [verify: :verify_none] which removes the warnings.

eriknaslund commented 1 year ago

@andrewtimberlake Thanks a bunch for this!

I started using it in my app today, and both verify_peer (actually doing a verification) and verify_none (skipping verification, but getting rid of the logged warning) works great.

Here are two examples in case anyone else wonders how to do it:

# verify_peer
Mailroom.IMAP.connect(
    ...
    ssl: true,
    ssl_opts: [
        cacerts: :certifi.cacerts(),
        depth: 10,
        verify: :verify_peer
    ]
)

# verify_none
Mailroom.IMAP.connect(
    ...
    ssl: true,
    ssl_opts: [
        verify: :verify_none
    ]
)