Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Skip expired certs in partial chain hook #328

Merged
merged 4 commits into from
Sep 2, 2021
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 42 additions & 1 deletion lib/mint/core/transport/ssl.ex
Original file line number Diff line number Diff line change
Expand Up @@ -623,7 +623,10 @@ defmodule Mint.Core.Transport.SSL do
def partial_chain(cacerts, certs) do
# TODO: Shim this with OTP 21.1 implementation?

certs = Enum.map(certs, &{&1, :public_key.pkix_decode_cert(&1, :plain)})
certs =
certs
|> Enum.map(&{&1, :public_key.pkix_decode_cert(&1, :plain)})
|> Enum.drop_while(&cert_expired?/1)

trusted =
Enum.find_value(certs, fn {der, cert} ->
Expand All @@ -642,12 +645,50 @@ defmodule Mint.Core.Transport.SSL do
end
end

defp cert_expired?({_der, cert}) do
now = DateTime.utc_now()
{not_before, not_after} = extract_validity(cert)

DateTime.compare(now, not_before) == :lt or
DateTime.compare(now, not_after) == :gt
end

defp extract_validity(cert) do
{:Validity, not_before, not_after} =
cert
|> certificate(:tbsCertificate)
|> tbs_certificate(:validity)

{to_datetime!(not_before), to_datetime!(not_after)}
end

defp extract_public_key_info(cert) do
cert
|> certificate(:tbsCertificate)
|> tbs_certificate(:subjectPublicKeyInfo)
end

defp to_datetime!({:utcTime, time}) do
"20#{time}"
|> to_datetime!()
end

defp to_datetime!({:generalTime, time}) do
time
|> to_string()
|> to_datetime!()
end

defp to_datetime!(
<<year::binary-size(4), month::binary-size(2), day::binary-size(2), hour::binary-size(2),
minute::binary-size(2), second::binary-size(2), "Z"::binary>>
) do
{:ok, datetime, _} =
DateTime.from_iso8601("#{year}-#{month}-#{day}T#{hour}:#{minute}:#{second}Z")

datetime
voltone marked this conversation as resolved.
Show resolved Hide resolved
end

defp blocked_cipher?(%{cipher: cipher, key_exchange: kex, prf: prf}),
do: blocked_cipher?({kex, cipher, prf})

Expand Down
30 changes: 30 additions & 0 deletions test/mint/core/transport/ssl_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,20 @@ defmodule Mint.Core.Transport.SSLTest do
end
end

# Certificate chain rooted in an expired root CA, and CA store containing
# expired and alternate root CAs
@chain Path.expand("../../../support/mint/chain.pem", __DIR__)
@ca_store Path.expand("../../../support/mint/ca_store.pem", __DIR__)

describe "partial_chain/2" do
setup [:chain_with_expired_root]

test "ignore expired CA cert(s)", %{chain: chain, ca_store: ca_store} do
[_, cross_signed | _] = chain
assert {:trusted_ca, ^cross_signed} = SSL.partial_chain(ca_store, chain)
end
end

describe "controlling_process/2" do
setup do
parent = self()
Expand Down Expand Up @@ -270,11 +284,27 @@ defmodule Mint.Core.Transport.SSLTest do
[cert: load_cert(@wildcard_san)]
end

defp chain_with_expired_root(_context) do
[
chain: load_all_certs(@chain),
ca_store:
load_all_certs(@ca_store)
|> Enum.map(&:public_key.pkix_decode_cert(&1, :plain))
voltone marked this conversation as resolved.
Show resolved Hide resolved
]
end

defp load_cert(path) do
[{_, binary, _} | _] = path |> File.read!() |> :public_key.pem_decode()
:public_key.pkix_decode_cert(binary, :otp)
end

defp load_all_certs(path) do
path
|> File.read!()
|> :public_key.pem_decode()
|> Enum.map(&elem(&1, 1))
end

defp process_mirror(parent, ref) do
receive do
message ->
Expand Down
39 changes: 39 additions & 0 deletions test/support/mint/ca_store.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
-----BEGIN CERTIFICATE-----
MIIDHDCCAgSgAwIBAgIIOv+oU5CKFNQwDQYJKoZIhvcNAQELBQAwGjEYMBYGA1UE
AwwPRXhwaXJlZCBSb290IENBMB4XDTkxMDEwMTAwMDAwMFoXDTIwMTIzMTIzNTk1
OVowGjEYMBYGA1UEAwwPRXhwaXJlZCBSb290IENBMIIBIjANBgkqhkiG9w0BAQEF
AAOCAQ8AMIIBCgKCAQEAzgT9rV+trFuWiiJ6PmEspLW70iX5khyWGTZJu745uQB8
iba2al76dna05eItiwigPs6sAg3kWOeW6FOYeQzH89OlFfdKrDke2EazAz4aCghH
pjRpTywQINAnT38Yn1UK63klC8a877s+NdzgE5jWAzKVuviY2NBKOqXVqg2fhh4m
Bk1mYfzxmqeBoFRp/rVgz5fnNo78lkHsItdQPxi2GFiKjfWsyail1wz6GL4XCOpX
5KnulvDg124FaxUe4uuOWcRMTAtMBuYQ91gDLkcIpilpdfjnQOFfh067u1UGugw3
clpVYHby0Wfgln2FHuNHCUOCkdEZEkslV/o7nhAqlQIDAQABo2YwZDASBgNVHRMB
Af8ECDAGAQH/AgEBMA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUFbNIcEBp4gRU
LCQb5IUZJZyl+ykwHwYDVR0jBBgwFoAUFbNIcEBp4gRULCQb5IUZJZyl+ykwDQYJ
KoZIhvcNAQELBQADggEBAApd3c0IMgguRiz0K2EnlgCst+a7x4LRLfAa4VSKzzDf
knsR8BT16UahLT2b6jO/hG919tqokWqOC3CjC0PUp0C/zHKGI45waOJrryTfER+P
spTQZFqTjVJIEhLOQi3nlnBynanrzkBlzH87YgSEzkmDudrJGw1Twar/ZJmtjpn7
eGefvK9BH7PiM2ykHweIgWyzE+HU50CxLFzM2HOx5Tha8FCYgKukTehF0h1hM/Mn
bSAPqcF1d40lcY28HTNbPLOIPKP66mEo3f1i6x5JVyQcrZZChUpsKl1CGmp1e/vy
9KPpXycvWIGzb6PmHBZ39XdKIv8JLBAdfPNHjuHmpa0=
-----END CERTIFICATE-----

-----BEGIN CERTIFICATE-----
MIIDFjCCAf6gAwIBAgIIJ9/iR+IyCLwwDQYJKoZIhvcNAQELBQAwFjEUMBIGA1UE
AwwLTmV3IFJvb3QgQ0EwIBcNMjAwMTAxMDAwMDAwWhgPMjA1MTEyMzEyMzU5NTla
MBYxFDASBgNVBAMMC05ldyBSb290IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
MIIBCgKCAQEAxxrIbH4LRM87hwLN7CQbvauFsVgfSonoe2+P3RJcvpZhCwEPBUTB
YRv15x+D2zJ/I25Pltx9e6X1QMSeBzifVYhELKBBkVB+AkHtOCp+cvUl8GrccZmC
rKQUmPei/Z1/k+HvAhMzKKWNUgLXpRr+Nw+0uhxJoP90ynSxcjB14DrKHaC+Vu7h
Fm/a8BGY+k2o0DKOmeKfMIcRmEhEwWwmRqBceBAmvCc6QJxHew/hCQe7/J9yJk6Y
E5NjLUVFsJqt3EVfnWtVl0Ph8ruha7VioXFwA0zPN1qG84n66mBN+i86QlOugNFQ
8E9Mb6blgSry9x6cBUOGTASpfO9xsFWCXQIDAQABo2YwZDASBgNVHRMBAf8ECDAG
AQH/AgEBMA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUy0Qn7LGa53gz9Hy1x9fE
93b20fwwHwYDVR0jBBgwFoAUy0Qn7LGa53gz9Hy1x9fE93b20fwwDQYJKoZIhvcN
AQELBQADggEBADlWclXsV1iO6TzYF9Fs6LRJZthe2iHIYIh4e3rMLC8twpw1cyTq
tTNRlQBadzZwhTaODjDB9oUPvu+cVfNt6T710tjb5kIgO9fCTIUmKqZ2NHRKdl5E
kisdiqdIjmb4BLuMmm2i7zTYVAKfB9GTU6VeSud0FCn9PCMJgE3Cy4AE+zUEqw3i
4Nyd48SJO+z9fVkt852JJlYYodyuvhvW8Lk0HA2VQms7MvR7QP5PPOsfiB3ZxxVa
fhR6yCqHaDsmE8/h4eA/jX3bJBgaDxkhgfdtVQhJzNzWOZj5OPM61LdZJFE4Ya7h
ZpJO9CqeXHVhIecLFu7LTBIENXi672xgyxg=
-----END CERTIFICATE-----
81 changes: 81 additions & 0 deletions test/support/mint/chain.pem
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
-----BEGIN CERTIFICATE-----
MIIDHDCCAgSgAwIBAgIIOv+oU5CKFNQwDQYJKoZIhvcNAQELBQAwGjEYMBYGA1UE
AwwPRXhwaXJlZCBSb290IENBMB4XDTkxMDEwMTAwMDAwMFoXDTIwMTIzMTIzNTk1
OVowGjEYMBYGA1UEAwwPRXhwaXJlZCBSb290IENBMIIBIjANBgkqhkiG9w0BAQEF
AAOCAQ8AMIIBCgKCAQEAzgT9rV+trFuWiiJ6PmEspLW70iX5khyWGTZJu745uQB8
iba2al76dna05eItiwigPs6sAg3kWOeW6FOYeQzH89OlFfdKrDke2EazAz4aCghH
pjRpTywQINAnT38Yn1UK63klC8a877s+NdzgE5jWAzKVuviY2NBKOqXVqg2fhh4m
Bk1mYfzxmqeBoFRp/rVgz5fnNo78lkHsItdQPxi2GFiKjfWsyail1wz6GL4XCOpX
5KnulvDg124FaxUe4uuOWcRMTAtMBuYQ91gDLkcIpilpdfjnQOFfh067u1UGugw3
clpVYHby0Wfgln2FHuNHCUOCkdEZEkslV/o7nhAqlQIDAQABo2YwZDASBgNVHRMB
Af8ECDAGAQH/AgEBMA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUFbNIcEBp4gRU
LCQb5IUZJZyl+ykwHwYDVR0jBBgwFoAUFbNIcEBp4gRULCQb5IUZJZyl+ykwDQYJ
KoZIhvcNAQELBQADggEBAApd3c0IMgguRiz0K2EnlgCst+a7x4LRLfAa4VSKzzDf
knsR8BT16UahLT2b6jO/hG919tqokWqOC3CjC0PUp0C/zHKGI45waOJrryTfER+P
spTQZFqTjVJIEhLOQi3nlnBynanrzkBlzH87YgSEzkmDudrJGw1Twar/ZJmtjpn7
eGefvK9BH7PiM2ykHweIgWyzE+HU50CxLFzM2HOx5Tha8FCYgKukTehF0h1hM/Mn
bSAPqcF1d40lcY28HTNbPLOIPKP66mEo3f1i6x5JVyQcrZZChUpsKl1CGmp1e/vy
9KPpXycvWIGzb6PmHBZ39XdKIv8JLBAdfPNHjuHmpa0=
-----END CERTIFICATE-----

-----BEGIN CERTIFICATE-----
MIIDOzCCAiOgAwIBAgIICGNdx0mQQh0wDQYJKoZIhvcNAQELBQAwGjEYMBYGA1UE
AwwPRXhwaXJlZCBSb290IENBMCAXDTIwMDEwMTAwMDAwMFoYDzIwNTExMjMxMjM1
OTU5WjAWMRQwEgYDVQQDDAtOZXcgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQAD
ggEPADCCAQoCggEBAMcayGx+C0TPO4cCzewkG72rhbFYH0qJ6Htvj90SXL6WYQsB
DwVEwWEb9ecfg9syfyNuT5bcfXul9UDEngc4n1WIRCygQZFQfgJB7TgqfnL1JfBq
3HGZgqykFJj3ov2df5Ph7wITMyiljVIC16Ua/jcPtLocSaD/dMp0sXIwdeA6yh2g
vlbu4RZv2vARmPpNqNAyjpninzCHEZhIRMFsJkagXHgQJrwnOkCcR3sP4QkHu/yf
ciZOmBOTYy1FRbCardxFX51rVZdD4fK7oWu1YqFxcANMzzdahvOJ+upgTfovOkJT
roDRUPBPTG+m5YEq8vcenAVDhkwEqXzvcbBVgl0CAwEAAaOBhjCBgzASBgNVHRMB
Af8ECDAGAQH/AgEAMA4GA1UdDwEB/wQEAwIBhjAdBgNVHSUEFjAUBggrBgEFBQcD
AQYIKwYBBQUHAwIwHQYDVR0OBBYEFMtEJ+yxmud4M/R8tcfXxPd29tH8MB8GA1Ud
IwQYMBaAFBWzSHBAaeIEVCwkG+SFGSWcpfspMA0GCSqGSIb3DQEBCwUAA4IBAQCp
hs3difsZKhg5htEYyINdvcZKT2ujZVXGalrdFt7Jjlnn9OFPTNQQkJZ/nD1bnmJ2
oalSa5Gd1XW89IQp0Jo0CcLDJ2fKWFH05Oj/gq35GZ6qqjydLfQ7yUuQdh+F7MEG
IrJwyR/qRdIQJSspIr6HM1D6FAVbbztvQyMgfuTVfjDu+mG78J6R05Kc+SFmzob9
o5evG2DIdgaYp+uwZ/7rSzSymsZIEXwMtbCPkeI1IVMC/pZbUHcbWsCrVMRasyHg
mnIFeBrg0/fs9xXYHZ/shx7G1EfSuLkcAkk41sOcfH3cBSTWM3OqlbyCkdVMK1qU
A3q4haNcXe3HkO1IfICx
-----END CERTIFICATE-----

-----BEGIN CERTIFICATE-----
MIIDOTCCAiGgAwIBAgIIfYtvBLi9/sAwDQYJKoZIhvcNAQELBQAwFjEUMBIGA1UE
AwwLTmV3IFJvb3QgQ0EwHhcNMjAwMTAxMDAwMDAwWhcNMzkxMjMxMjM1OTU5WjAa
MRgwFgYDVQQDDA9JbnRlcm1lZGlhdGUgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IB
DwAwggEKAoIBAQCrgTp/u3fM0ID0UqAjcOw2NwVCzlcZ7n79+6O1N82xBAZu2YhP
aHuuJO6IAL845y+Kzx5S01FSuNGi/ULt0XMSzFAmG11fhJm6ee01NzocrPFofEeh
83zXH/3098Iu2PPh2P2L2tK0O3Or05EbFRnQd6JqBVmrfqnFZtzjzFEIP6jBNUhr
+BlZN5FeC2oI5kjhg3DojolRy1duF7tj37S9c6vbKyjajcKkeOkRPhiPX2q/zTUc
mcL8+q4Vv1eEKlgyVaXMZLJjF5S8xZ09Y9J6U6m8OqOeeCAVrYzC7EqLFMXQybOr
NK5l4QCz/SOqCcNc31dtL/O1ujdrWPB3DQ/xAgMBAAGjgYYwgYMwEgYDVR0TAQH/
BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0lBBYwFAYIKwYBBQUHAwEG
CCsGAQUFBwMCMB0GA1UdDgQWBBQK1jjin3KVPrIn8w9Gi0sfPHnRLzAfBgNVHSME
GDAWgBTLRCfssZrneDP0fLXH18T3dvbR/DANBgkqhkiG9w0BAQsFAAOCAQEAFrfR
puO3qfvyN57norKOL7UsLsNQwKVRCbfLuFwBITFJuflzSzTeY6byf0br/01wf8He
0Bbs7nKqWCC0FA8Feqield68ohFo8n0ZFNhWwq2ZB+oA9frJED2XHQ5JWbH1CXbZ
mdk3jT0weWB+VnvsnKYXpD0x0CKdAM4I71ikH0fOiOnHtqRGFUJ11s7kb+Ns55du
9m5Gsw8ebc+vnEUVi7WZWBcgZdX7N3UDutLWnCEBBQxHdlQK2Q3M5gXRwQbDekEt
1QSpAD7keDagVQjbRj+Ly1hpWSpg0P6sTyf0QRdSG0kqkH/+K6syQOa4TofScKVJ
nLJUkRMcKsvVd+weEg==
-----END CERTIFICATE-----

-----BEGIN CERTIFICATE-----
MIIDKjCCAhKgAwIBAgIJAKwUSyPXOrFVMA0GCSqGSIb3DQEBCwUAMBoxGDAWBgNV
BAMMD0ludGVybWVkaWF0ZSBDQTAeFw0yMDAxMDEwMDAwMDBaFw0zOTEyMzEyMzU5
NTlaMBExDzANBgNVBAMMBlNlcnZlcjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
AQoCggEBALRa/e8acLATiP4DpbR3+Hzz6TOZ+oPgedl/fxizd1BIKOYFuYA2y/QO
y76xvkq5A4ZZSU0UG9RZ4fV6LBRr9rJBAS0SaoMWGRuw7HbDyHj0heLd8i9omfpd
29wEg6ok5WVIYDsEA9LRf/GfPw48i5x0uitafpcomt1onpBsajAoYWoITSgYXWU2
Eqco73VFJtJHey7vkfFBwHc67g+9eNSM3FcsWLBB+E62ZeWF3+Pm/e7plac3/ywK
5672h5/wR9ihsv1bM0KCqFHWPjulq00TAYDVBTVMgA5SGN8HpBf6zAup302ozAck
ad7CNTHPNtd3xtepv4VnEzTzKmFkc3kCAwEAAaN8MHowCQYDVR0TBAIwADAOBgNV
HQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMB0GA1Ud
DgQWBBTkfN4ApwUkcV56j0kBZMjGAD1AjzAfBgNVHSMEGDAWgBQK1jjin3KVPrIn
8w9Gi0sfPHnRLzANBgkqhkiG9w0BAQsFAAOCAQEAL2KvOziXCt5a9cdbN9TZntqV
xJXElHzr9K9DGFg7YZaBMaYYlytih/9BQFy2tWkrI0UY+aVsndNhUpfOlCAJ7MSs
X2sS8n2oZ0prvaKLzBtnkZpMPy9NwwfIrLp5S6sfFQv/IT7DBTv2+0n7y0thRdZ1
2OFQ5jNIXH6guSSHphDwBnYOz5ecsTbCvHcqt4eYykrZLnM7vw8+6QWY6rzJ4dsh
GypEX0Zcog73Mgv2V4RGYogxkDKVD783fFjRm/NEfF6j67DjDaqgivhSjt8B/GQQ
JRCuVxXz/K6gpy9kdI5zqi0nmYkQJsGxo4njLZ6fSHbhH4bFpgWtYf5mdrG3IA==
-----END CERTIFICATE-----