|
| 1 | +class CaCertificates < Formula |
| 2 | + desc "Mozilla CA certificate store" |
| 3 | + homepage "https://curl.se/docs/caextract.html" |
| 4 | + url "https://curl.se/ca/cacert-2024-07-02.pem" |
| 5 | + sha256 "1bf458412568e134a4514f5e170a328d11091e071c7110955c9884ed87972ac9" |
| 6 | + license "MPL-2.0" |
| 7 | + |
| 8 | + livecheck do |
| 9 | + url :homepage |
| 10 | + regex(/href=.*?cacert[._-](\d{4}-\d{2}-\d{2})\.pem/i) |
| 11 | + end |
| 12 | + |
| 13 | + bottle do |
| 14 | + root_url "https://github.com/gromgit/homebrew-core-aarch64_linux/releases/download/ca-certificates-2024-07-02" |
| 15 | + sha256 cellar: :any_skip_relocation, aarch64_linux: "242b4df0d9160ecc027c7d0519b3d6c6e67699c0e6c3eb417ad87f44421b8e8f" |
| 16 | + end |
| 17 | + |
| 18 | + def install |
| 19 | + pkgshare.install "cacert-#{version}.pem" => "cacert.pem" |
| 20 | + end |
| 21 | + |
| 22 | + def post_install |
| 23 | + if OS.mac? |
| 24 | + macos_post_install |
| 25 | + else |
| 26 | + linux_post_install |
| 27 | + end |
| 28 | + end |
| 29 | + |
| 30 | + def macos_post_install |
| 31 | + ohai "Regenerating CA certificate bundle from keychain, this may take a while..." |
| 32 | + |
| 33 | + keychains = %w[ |
| 34 | + /Library/Keychains/System.keychain |
| 35 | + /System/Library/Keychains/SystemRootCertificates.keychain |
| 36 | + ] |
| 37 | + |
| 38 | + certs_list = Utils.safe_popen_read("/usr/bin/security", "find-certificate", "-a", "-p", *keychains) |
| 39 | + certs = certs_list.scan( |
| 40 | + /-----BEGIN CERTIFICATE-----.*?-----END CERTIFICATE-----/m, |
| 41 | + ) |
| 42 | + |
| 43 | + # Check that the certificate has not expired |
| 44 | + valid_certs = certs.select do |cert| |
| 45 | + begin |
| 46 | + Utils.safe_popen_write("/usr/bin/openssl", "x509", "-inform", "pem", |
| 47 | + "-checkend", "0", |
| 48 | + "-noout") do |openssl_io| |
| 49 | + openssl_io.write(cert) |
| 50 | + end |
| 51 | + rescue ErrorDuringExecution |
| 52 | + # Expired likely. |
| 53 | + next |
| 54 | + end |
| 55 | + |
| 56 | + # Only include certs that have are designed to act as a SSL root. |
| 57 | + purpose = Utils.safe_popen_write("/usr/bin/openssl", "x509", "-inform", "pem", |
| 58 | + "-purpose", |
| 59 | + "-noout") do |openssl_io| |
| 60 | + openssl_io.write(cert) |
| 61 | + end |
| 62 | + purpose.include?("SSL server CA : Yes") |
| 63 | + end |
| 64 | + |
| 65 | + # Check that the certificate is trusted in keychain |
| 66 | + trusted_certs = begin |
| 67 | + tmpfile = Tempfile.new |
| 68 | + |
| 69 | + verify_args = %W[ |
| 70 | + -l -L |
| 71 | + -c #{tmpfile.path} |
| 72 | + -p ssl |
| 73 | + ] |
| 74 | + on_high_sierra :or_newer do |
| 75 | + verify_args << "-R" << "offline" |
| 76 | + end |
| 77 | + |
| 78 | + valid_certs.select do |cert| |
| 79 | + tmpfile.rewind |
| 80 | + tmpfile.write cert |
| 81 | + tmpfile.truncate cert.size |
| 82 | + tmpfile.flush |
| 83 | + Utils.safe_popen_read("/usr/bin/security", "verify-cert", *verify_args) |
| 84 | + true |
| 85 | + rescue ErrorDuringExecution |
| 86 | + # Invalid. |
| 87 | + false |
| 88 | + end |
| 89 | + ensure |
| 90 | + tmpfile&.close! |
| 91 | + end |
| 92 | + |
| 93 | + # Get SHA256 fingerprints for all trusted certs |
| 94 | + fingerprints = trusted_certs.to_set do |cert| |
| 95 | + Utils.safe_popen_write("/usr/bin/openssl", "x509", "-inform", "pem", |
| 96 | + "-fingerprint", |
| 97 | + "-sha256", |
| 98 | + "-noout") do |openssl_io| |
| 99 | + openssl_io.write(cert) |
| 100 | + end |
| 101 | + end |
| 102 | + |
| 103 | + # Now process Mozilla certs we downloaded. |
| 104 | + pem_certs_list = File.read(pkgshare/"cacert.pem") |
| 105 | + pem_certs = pem_certs_list.scan( |
| 106 | + /-----BEGIN CERTIFICATE-----.*?-----END CERTIFICATE-----/m, |
| 107 | + ) |
| 108 | + |
| 109 | + # Append anything new. |
| 110 | + trusted_certs += pem_certs.select do |cert| |
| 111 | + fingerprint = Utils.safe_popen_write("/usr/bin/openssl", "x509", "-inform", "pem", |
| 112 | + "-fingerprint", |
| 113 | + "-sha256", |
| 114 | + "-noout") do |openssl_io| |
| 115 | + openssl_io.write(cert) |
| 116 | + end |
| 117 | + fingerprints.add?(fingerprint) |
| 118 | + end |
| 119 | + |
| 120 | + pkgetc.mkpath |
| 121 | + (pkgetc/"cert.pem").atomic_write(trusted_certs.join("\n") << "\n") |
| 122 | + end |
| 123 | + |
| 124 | + def linux_post_install |
| 125 | + rm(pkgetc/"cert.pem") if (pkgetc/"cert.pem").exist? |
| 126 | + pkgetc.mkpath |
| 127 | + cp pkgshare/"cacert.pem", pkgetc/"cert.pem" |
| 128 | + end |
| 129 | + |
| 130 | + test do |
| 131 | + assert_path_exists pkgshare/"cacert.pem" |
| 132 | + assert_path_exists pkgetc/"cert.pem" |
| 133 | + assert compare_file(pkgshare/"cacert.pem", pkgetc/"cert.pem") if OS.linux? |
| 134 | + end |
| 135 | +end |
0 commit comments