Skip to content
Closed
Show file tree
Hide file tree
Changes from all 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
124 changes: 124 additions & 0 deletions Formula/ca-certificates.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
class CaCertificates < Formula
desc "Mozilla CA certificate store"
homepage "https://curl.se/docs/caextract.html"
url "https://curl.se/ca/cacert-2021-09-30.pem"
# Ideally we'd have a HTTP mirror, but a GitHub-hosted one is second best.
mirror "https://raw.githubusercontent.com/Homebrew/formula-patches/7b48d2482eecb5aa64f591f79eda46565d0da29d/ca-certificates/cacert-2021-09-30.pem"
sha256 "f524fc21859b776e18df01a87880efa198112214e13494275dbcbd9bcb71d976"
license "MPL-2.0"

def install
pkgshare.install "cacert-#{version}.pem" => "cacert.pem"
end

def post_install
if OS.mac?
macos_post_install
else
linux_post_install
Comment on lines +16 to +18
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd be tempted to just inline these.

end
end

def macos_post_install
ohai "Regenerating CA certificate bundle from keychain, this may take a while..."

keychains = %w[
/Library/Keychains/System.keychain
/System/Library/Keychains/SystemRootCertificates.keychain
]

certs_list = Utils.safe_popen_read("/usr/bin/security", "find-certificate", "-a", "-p", *keychains)
certs = certs_list.scan(
/-----BEGIN CERTIFICATE-----.*?-----END CERTIFICATE-----/m,
)

# Check that the certificate has not expired
valid_certs = certs.select do |cert|
begin
Utils.safe_popen_write("/usr/bin/openssl", "x509", "-inform", "pem",
"-checkend", "0",
"-noout") do |openssl_io|
openssl_io.write(cert)
end
rescue ErrorDuringExecution
# Expired likely.
next
end

# Only include certs that have are designed to act as a SSL root.
purpose = Utils.safe_popen_write("/usr/bin/openssl", "x509", "-inform", "pem",
"-purpose",
"-noout") do |openssl_io|
openssl_io.write(cert)
end
purpose.include?("SSL server CA : Yes")
end

# Check that the certificate is trusted in keychain
trusted_certs = begin
tmpfile = Tempfile.new

verify_args = %W[
-l -L
-c #{tmpfile.path}
]
verify_args << "-R" << "offline" if MacOS.version >= :high_sierra

valid_certs.select do |cert|
tmpfile.rewind
tmpfile.write cert
tmpfile.truncate cert.size
tmpfile.flush
Utils.safe_popen_read("/usr/bin/security", "verify-cert", *verify_args)
true
rescue ErrorDuringExecution
# Invalid.
false
end
ensure
tmpfile&.close!
end

# Get SHA256 fingerprints for all trusted certs
fingerprints = trusted_certs.map do |cert|
Utils.safe_popen_write("/usr/bin/openssl", "x509", "-inform", "pem",
"-fingerprint",
"-sha256",
"-noout") do |openssl_io|
openssl_io.write(cert)
end
end.to_set

# Now process Mozilla certs we downloaded.
pem_certs_list = File.read(pkgshare/"cacert.pem")
pem_certs = pem_certs_list.scan(
/-----BEGIN CERTIFICATE-----.*?-----END CERTIFICATE-----/m,
)

# Append anything new.
trusted_certs += pem_certs.select do |cert|
fingerprint = Utils.safe_popen_write("/usr/bin/openssl", "x509", "-inform", "pem",
"-fingerprint",
"-sha256",
"-noout") do |openssl_io|
openssl_io.write(cert)
end
fingerprints.add?(fingerprint)
end

pkgetc.mkpath
(pkgetc/"cert.pem").atomic_write(trusted_certs.join("\n") << "\n")
end

def linux_post_install
rm_f pkgetc/"cert.pem"
pkgetc.mkpath
cp pkgshare/"cacert.pem", pkgetc/"cert.pem"
end

test do
assert_path_exists pkgshare/"cacert.pem"
assert_path_exists pkgetc/"cert.pem"
assert compare_file(pkgshare/"cacert.pem", pkgetc/"cert.pem") if OS.linux?
end
end
68 changes: 4 additions & 64 deletions Formula/openssl@1.1.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ class OpensslAT11 < Formula
mirror "https://www.openssl.org/source/old/1.1.1/openssl-1.1.1l.tar.gz"
sha256 "0b7a3e5e59c34827fe0c3a74b7ec8baef302b98fa80088d7f9153aa16fa76bd1"
license "OpenSSL"
revision 1
version_scheme 1

livecheck do
Expand All @@ -23,14 +24,9 @@ class OpensslAT11 < Formula

keg_only :shadowed_by_macos, "macOS provides LibreSSL"

on_linux do
resource "cacert" do
# homepage "http://curl.haxx.se/docs/caextract.html"
url "https://curl.haxx.se/ca/cacert-2020-01-01.pem"
mirror "https://gist.githubusercontent.com/dawidd6/16d94180a019f31fd31bc679365387bc/raw/ef02c78b9d6427585d756528964d18a2b9e318f7/cacert-2020-01-01.pem"
sha256 "adf770dfd574a0d6026bfaa270cb6879b063957177a991d453ff1d302c02081f"
end
depends_on "ca-certificates"
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's bump the revision here. Will we need to stop setting HOMEBREW_FORCE_BREWED_CURL on Mojave for things to work here?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will we need to stop setting HOMEBREW_FORCE_BREWED_CURL on Mojave for things to work here?

Yes.

Was hoping to bump the revision at the same time as making it keg-only, but that's going to be a bit of work since OpenSSL dependent testing is busted right now.


on_linux do
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can probably be dealt with in a separate PR, but I wonder about these resources. Does OpenSSL really need these at runtime? These look like build dependencies to me.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, but I think there's some dependents that are. This should be moved elsewhere but that's going to be out of scope for this PR.

resource "Test::Harness" do
url "https://cpan.metacpan.org/authors/id/L/LE/LEONT/Test-Harness-3.42.tar.gz"
sha256 "0fd90d4efea82d6e262e6933759e85d27cbcfa4091b14bf4042ae20bab528e53"
Expand Down Expand Up @@ -123,64 +119,8 @@ def openssldir
end

def post_install
if OS.mac?
macos_post_install
else
linux_post_install
end
end

def macos_post_install
ohai "Regenerating CA certificate bundle from keychain, this may take a while..."

keychains = %w[
/Library/Keychains/System.keychain
/System/Library/Keychains/SystemRootCertificates.keychain
]

certs_list = `/usr/bin/security find-certificate -a -p #{keychains.join(" ")}`
certs = certs_list.scan(
/-----BEGIN CERTIFICATE-----.*?-----END CERTIFICATE-----/m,
)

# Check that the certificate has not expired
valid_certs = certs.select do |cert|
IO.popen("#{bin}/openssl x509 -inform pem -checkend 0 -noout &>/dev/null", "w") do |openssl_io|
openssl_io.write(cert)
openssl_io.close_write
end

$CHILD_STATUS.success?
end

# Check that the certificate is trusted in keychain
trusted_certs = begin
tmpfile = Tempfile.new

valid_certs.select do |cert|
tmpfile.rewind
tmpfile.write cert
tmpfile.truncate cert.size
tmpfile.flush
IO.popen("/usr/bin/security verify-cert -l -L -R offline -c #{tmpfile.path} &>/dev/null")

$CHILD_STATUS.success?
end
ensure
tmpfile&.close!
end

openssldir.mkpath
(openssldir/"cert.pem").atomic_write(trusted_certs.join("\n") << "\n")
end

def linux_post_install
# Download and install cacert.pem from curl.haxx.se
cacert = resource("cacert")
cacert.fetch
rm_f openssldir/"cert.pem"
filename = Pathname.new(cacert.url).basename
openssldir.install cacert.files(filename => "cert.pem")
openssldir.install_symlink Formula["ca-certificates"].pkgetc/"cert.pem"
end

def caveats
Expand Down