From 8c40f0d8c4a376d6b4feeeb0807678e3c2e2692f Mon Sep 17 00:00:00 2001 From: Greg V Date: Wed, 24 Jul 2019 01:46:56 +0300 Subject: [PATCH] Enable TLS certificate verification by default --- README.md | 2 ++ config/config.exs | 4 ++-- lib/httpotion.ex | 14 +++++++++++++- mix.exs | 1 + mix.lock | 1 + 5 files changed, 19 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index f315c34..0ba9f71 100644 --- a/README.md +++ b/README.md @@ -40,6 +40,8 @@ $ mix deps.get $ iex -S mix ``` +*Note*: HTTPotion now enables certificate verification by default, using a few default CA bundle paths (`/etc/ssl/cert.pem` etc.) or the [certifi](https://hex.pm/packages/certifi) package (which is not a mandatory dependency). + Some basic examples: ```elixir diff --git a/config/config.exs b/config/config.exs index 8dc390c..1a4c157 100644 --- a/config/config.exs +++ b/config/config.exs @@ -1,7 +1,7 @@ use Mix.Config config :httpotion, :default_headers, [] # NOTE: Must be a keyword list here -config :httpotion, :default_timeout, 5000 -config :httpotion, :default_ibrowse, [] +config :httpotion, :default_timeout, 10000 +# config :httpotion, :default_ibrowse, [.. dynamic TLS conf by default ..] config :httpotion, :default_auto_sni, true config :httpotion, :default_follow_redirects, false diff --git a/lib/httpotion.ex b/lib/httpotion.ex index 836c0a1..708f2f2 100644 --- a/lib/httpotion.ex +++ b/lib/httpotion.ex @@ -152,7 +152,8 @@ defmodule HTTPotion.Base do |> Enum.map(fn ({k, v}) -> { (if is_atom(k), do: k, else: String.to_atom(to_string(k))), to_string(v) } end)) |> process_request_headers(body, options) timeout = Keyword.get(options, :timeout, Application.get_env(:httpotion, :default_timeout, 5000)) - ib_options = Application.get_env(:httpotion, :default_ibrowse, []) + ib_options = Application.get_env(:httpotion, :default_ibrowse, [ssl_options: [ + verify: :verify_peer, verify_fun: &:ssl_verify_hostname.verify_fun/3, depth: 69, cacertfile: HTTPotion.default_cert_bundle()]]) |> Keyword.merge(Keyword.get(options, :ibrowse, [])) stream_to = Keyword.get(options, :stream_to) auto_sni = Keyword.get(options, :auto_sni, Application.get_env(:httpotion, :default_auto_sni, true)) @@ -454,5 +455,16 @@ defmodule HTTPotion do defexception [:message] end + def default_cert_bundle() do + cond do + File.exists?("/etc/ssl/cert.pem") -> "/etc/ssl/cert.pem" + File.exists?("/etc/pki/tls/cert.pem") -> "/etc/pki/tls/cert.pem" + File.exists?("/usr/lib/ssl/cert.pem") -> "/usr/lib/ssl/cert.pem" + File.exists?("/etc/ssl/certs/ca-certificates.crt") -> "/etc/ssl/certs/ca-certificates.crt" + Code.ensure_loaded(:certifi) == {:module, :certifi} -> apply(:certifi, :cacertfile, []) + true -> nil + end + end + use HTTPotion.Base end diff --git a/mix.exs b/mix.exs index 05cc285..7946063 100644 --- a/mix.exs +++ b/mix.exs @@ -30,6 +30,7 @@ defmodule HTTPotion.Mixfile do defp deps do [ {:ibrowse, "== 4.4.0"}, + {:ssl_verify_fun, "~> 1.1"}, {:ex_doc, "~> 0.18", only: [:dev, :test, :docs]} ] end diff --git a/mix.lock b/mix.lock index 1ba5d3b..a4f226b 100644 --- a/mix.lock +++ b/mix.lock @@ -5,4 +5,5 @@ "makeup": {:hex, :makeup, "0.8.0", "9cf32aea71c7fe0a4b2e9246c2c4978f9070257e5c9ce6d4a28ec450a839b55f", [:mix], [{:nimble_parsec, "~> 0.5.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm"}, "makeup_elixir": {:hex, :makeup_elixir, "0.13.0", "be7a477997dcac2e48a9d695ec730b2d22418292675c75aa2d34ba0909dcdeda", [:mix], [{:makeup, "~> 0.8", [hex: :makeup, repo: "hexpm", optional: false]}], "hexpm"}, "nimble_parsec": {:hex, :nimble_parsec, "0.5.0", "90e2eca3d0266e5c53f8fbe0079694740b9c91b6747f2b7e3c5d21966bba8300", [:mix], [], "hexpm"}, + "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.5", "6eaf7ad16cb568bb01753dbbd7a95ff8b91c7979482b95f38443fe2c8852a79b", [:make, :mix, :rebar3], [], "hexpm"}, }