ninenines / gun

HTTP/1.1, HTTP/2, Websocket client (and more) for Erlang/OTP.
ISC License
891 stars 232 forks source link

Terminate early with TLS certificate errors #192

Open danschultzer opened 5 years ago

danschultzer commented 5 years ago

I'm building an adapter to one of my libraries to use Gun, and testing with badssl.com for expired certificate.

I use the following SSL verification setup (elixir):

opts =
  %{transport_opts: [
    verify: :verify_peer,
    depth: 99,
    cacerts: :certifi.cacerts(),
    verify_fun: {&:ssl_verify_hostname.verify_fun/3, check_hostname: to_charlist(host)}
  ]}

However there's no way to monitor errors in the transport_connect/2 method, and it just keeps on retrying until it fails. I think it should be possible to monitor the process there, and it should probably always terminate early if {bad_cert, Reason} error is returned for the gun_tls transport.

essen commented 5 years ago

Hmm I wonder. On the one hand if the certificate is wrong there's no point retrying. On the other hand if the certificate is in a file the file may be updated and Gun can then reconnect successfully. So I suppose it depends on the setup. I would be OK with adding an option retry_on_bad_cert = boolean() that defaults to true.

danschultzer commented 5 years ago

I agree, adding that option is the best solution. It won't break any existing setup 👍

Though from my personal experience working with SSL in elixir, I do think that most devs would want it to stop retrying since there is only a 5 second timeout by default and the majority would use something like :certifi.cacerts/0 to package certs with their erlang/elixir releases.

essen commented 5 years ago

If your main concern is cacerts I don't disagree, but don't forget the case of client certificates for things like authentication. If we could distinguish perhaps the default behavior could be improved.