dogweather
HTTP SSL error: "Unknown CA"—going down a Rabbit hole. Maybe an asdf Erlang issue?
I get this error with both :httpc and HTTPoison.get. Here’s HTTPoison:
iex(1)> HTTPoison.get! "https://grad.tamu.edu/"
22:15:54.179 [notice] TLS :client: In state :certify at ssl_handshake.erl:2138 generated CLIENT ALERT: Fatal - Unknown CA
** (HTTPoison.Error) {:tls_alert, {:unknown_ca, ~c"TLS client: In state certify at ssl_handshake.erl:2138 generated CLIENT ALERT: Fatal - Unknown CA\n"}}
(httpoison 2.2.0) lib/httpoison/base.ex:451: HTTPoison.request!/5
iex:1: (file)
Same with this:
iex(1)> :httpc.request(:get, {'https://grad.tamu.edu/', []}, [], [])
22:24:10.836 [notice] TLS :client: In state :certify at ssl_handshake.erl:2138 generated CLIENT ALERT: Fatal - Unknown CA
{:error,
{:failed_connect,
[
{:to_address, {~c"grad.tamu.edu", 443}},
{:inet, [:inet],
{:tls_alert,
{:unknown_ca,
~c"TLS client: In state certify at ssl_handshake.erl:2138 generated CLIENT ALERT: Fatal - Unknown CA\n"}}}
]}}
.tool-versions:
elixir 1.15.2-otp-26
erlang 26.0.2
I’ve seen this pop up periodically over the years. What’s the root cause?
I’m thinking of making an elixir lib that simply shells out to curl, which has no problems:
$ curl --head https://grad.tamu.edu/
HTTP/2 200
cache-control: private
content-length: 46798
content-type: text/html; charset=utf-8
server: Microsoft-IIS/10.0
x-aspnetmvc-version: 5.2
x-aspnet-version: 4.0.30319
x-powered-by: ASP.NET
date: Wed, 15 Nov 2023 05:20:20 GMT
strict-transport-security: max-age=4294967294
EDIT: I made this dead simple Hex Package.
CurlEx.get!(url)
Marked As Solved
voltone
Looks like the server only sends its own certificate, not any intermediary CAs that would allow it to be traced to a trusted root CA. Instead it relies on the client to fetch the intermediate CA(s) from the URL in the Authority Information Access extension. This is supported by browsers and by some CLI tools, but not by Erlang’s ssl. I suspect they would have issues with other non-browser clients too.
For maximum compatibility they should consider adding the trust chain to their server, so it sends all the intermediate CA certificates and the client can complete the trust chain locally without additional network requests.
Also Liked
dch
a few handy tricks for next time:
> curl -v --cert-status https://grad.tamu.edu/
* Trying 128.194.14.62:443...
* Connected to grad.tamu.edu (128.194.14.62) port 443
* ALPN: curl offers h2,http/1.1
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (OUT), TLS alert, handshake failure (552):
* OpenSSL/3.0.12: error:0A000152:SSL routines::unsafe legacy renegotiation disabled
* Closing connection
curl: (35) OpenSSL/3.0.12: error:0A000152:SSL routines::unsafe legacy renegotiation disabled
TLDR, their system is broken. Your client tries to negotiate downwards until it finds a common TLS standard that it can work with, but eventually gives up, as TLS<1.1 is defacto broken and is generally excluded across the public internet now, if configured correctly.
But why?
> openssl s_client -showcerts -connect grad.tamu.edu:443
CONNECTED(00000003)
0020014A48190000:error:0A000152:SSL routines:final_renegotiate:unsafe legacy renegotiation disabled:/usr/src/crypto/openssl/ssl/statem/extensions.c:894:
---
no peer certificate available
---
No client certificate CA names sent
---
SSL handshake has read 7297 bytes and written 326 bytes
Verification: OK
---
New, (NONE), Cipher is (NONE)
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
Protocol : TLSv1.2
Cipher : 0000
Session-ID: 509160C19F5059FAA272B38986056F4DF3C0EB536516F4E14EA934EB708E1A32
Session-ID-ctx:
Master-Key:
PSK identity: None
PSK identity hint: None
SRP username: None
Start Time: 1700654113
Timeout : 7200 (sec)
Verify return code: 0 (ok)
Extended master secret: no
---
Compare that to connecting with s_client again but to tamu.edu and you’ll see that a pile of intermediate certs are sent along with the response for the parent site, which is correct.
For other neat libraries, katipo is a high-performance NIF to libcurl.
voltone
I think you may be trying to call :public_key.pkix_decode_cert on a PEM encoded certificate, but it expect a DER binary. Try one of these:
pem |> :public_key.pem_decode() |> hd() |> elem(1) |> :public_key.pkix_decode_cert(:otp)
pem |> :public_key.pem_decode() |> hd() |> :public_key.pem_entry_decode()
Or try x509 | Hex for a convenient high-level API for working with certificates and other PKI data structures…
dogweather
Texas A&M fixed their configuration. I’m not used to large orgs like this taking outside reports seriously. Pretty nice.
Last Post!
dogweather
Texas A&M fixed their configuration. I’m not used to large orgs like this taking outside reports seriously. Pretty nice.
Popular in Questions
Other popular topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #elixirconf-us
- #advent-of-code
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #security
- #hex










