diff --git a/Library/Homebrew/brew.sh b/Library/Homebrew/brew.sh index 93b2fe0d45..558f818a55 100644 --- a/Library/Homebrew/brew.sh +++ b/Library/Homebrew/brew.sh @@ -433,6 +433,20 @@ then printf "\\n" >&2 fi + # Versions before Sierra don't handle custom cert files correctly, so need a full brewed curl. + if [[ "${HOMEBREW_MACOS_VERSION_NUMERIC}" -lt "101200" ]] + then + HOMEBREW_SYSTEM_CURL_TOO_OLD="1" + HOMEBREW_FORCE_BREWED_CURL="1" + fi + + # The system libressl has a bug before macOS 10.15.6 where it incorrectly handles expired roots. + if [[ -z "${HOMEBREW_SYSTEM_CURL_TOO_OLD}" && "${HOMEBREW_MACOS_VERSION_NUMERIC}" -lt "101506" ]] + then + HOMEBREW_SYSTEM_CA_CERTIFICATES_TOO_OLD="1" + HOMEBREW_FORCE_BREWED_CA_CERTIFICATES="1" + fi + # The system Git on macOS versions before Sierra is too old for some Homebrew functionality we rely on. HOMEBREW_MINIMUM_GIT_VERSION="2.14.3" if [[ "${HOMEBREW_MACOS_VERSION_NUMERIC}" -lt "101200" ]] @@ -534,6 +548,12 @@ Your Git executable: $(unset git && type -p ${HOMEBREW_GIT})" fi fi +if [[ -n "${HOMEBREW_FORCE_BREWED_CA_CERTIFICATES}" && -f "${HOMEBREW_PREFIX}/etc/ca-certificates/cert.pem" ]] +then + export SSL_CERT_FILE="${HOMEBREW_PREFIX}/etc/ca-certificates/cert.pem" + export GIT_SSL_CAINFO="${HOMEBREW_PREFIX}/etc/ca-certificates/cert.pem" +fi + # A bug in the auto-update process prior to 3.1.2 means $HOMEBREW_BOTTLE_DOMAIN # could be passed down with the default domain. # This is problematic as this is will be the old bottle domain. @@ -571,6 +591,7 @@ export HOMEBREW_DEFAULT_TEMP export HOMEBREW_TEMP export HOMEBREW_CELLAR export HOMEBREW_SYSTEM +export HOMEBREW_SYSTEM_CA_CERTIFICATES_TOO_OLD export HOMEBREW_CURL export HOMEBREW_CURL_WARNING export HOMEBREW_SYSTEM_CURL_TOO_OLD diff --git a/Library/Homebrew/cmd/update.sh b/Library/Homebrew/cmd/update.sh index 308149ffa5..e8f8a4dee7 100644 --- a/Library/Homebrew/cmd/update.sh +++ b/Library/Homebrew/cmd/update.sh @@ -383,11 +383,21 @@ user account: EOS fi + # we may want to use Homebrew CA certificates + if [[ -n "${HOMEBREW_FORCE_BREWED_CA_CERTIFICATES}" && ! -f "${HOMEBREW_PREFIX}/etc/ca-certificates/cert.pem" ]] + then + # we cannot install Homebrew CA certificates if homebrew/core is unavailable. + if [[ -d "${HOMEBREW_LIBRARY}/Taps/homebrew/homebrew-core" || -n "${HOMEBREW_INSTALL_FROM_API}" ]] + then + brew install ca-certificates || true + fi + fi + # we may want to use a Homebrew curl if [[ -n "${HOMEBREW_FORCE_BREWED_CURL}" && ! -x "${HOMEBREW_PREFIX}/opt/curl/bin/curl" ]] then # we cannot install a Homebrew cURL if homebrew/core is unavailable. - if [[ ! -d "${HOMEBREW_LIBRARY}/Taps/homebrew/homebrew-core" ]] || ! brew install curl + if [[ ! -d "${HOMEBREW_LIBRARY}/Taps/homebrew/homebrew-core" && -z "${HOMEBREW_INSTALL_FROM_API}" ]] || ! brew install curl then odie "'curl' must be installed and in your PATH!" fi @@ -397,7 +407,7 @@ EOS [[ -n "${HOMEBREW_FORCE_BREWED_GIT}" && ! -x "${HOMEBREW_PREFIX}/opt/git/bin/git" ]] then # we cannot install a Homebrew Git if homebrew/core is unavailable. - if [[ ! -d "${HOMEBREW_LIBRARY}/Taps/homebrew/homebrew-core" ]] || ! brew install git + if [[ ! -d "${HOMEBREW_LIBRARY}/Taps/homebrew/homebrew-core" && -z "${HOMEBREW_INSTALL_FROM_API}" ]] || ! brew install git then odie "'git' must be installed and in your PATH!" fi diff --git a/Library/Homebrew/development_tools.rb b/Library/Homebrew/development_tools.rb index 89fd30e568..2d3ab61043 100644 --- a/Library/Homebrew/development_tools.rb +++ b/Library/Homebrew/development_tools.rb @@ -98,6 +98,11 @@ class DevelopmentTools @non_apple_gcc_version = {} end + sig { returns(T::Boolean) } + def ca_file_handles_most_https_certificates? + true + end + sig { returns(T::Boolean) } def curl_handles_most_https_certificates? true diff --git a/Library/Homebrew/env_config.rb b/Library/Homebrew/env_config.rb index 26ef31b11a..f75e3eeace 100644 --- a/Library/Homebrew/env_config.rb +++ b/Library/Homebrew/env_config.rb @@ -138,6 +138,11 @@ module Homebrew description: "A space-separated list of licenses. Homebrew will refuse to install a " \ "formula if it or any of its dependencies has a license on this list.", }, + HOMEBREW_FORCE_BREWED_CA_CERTIFICATES: { + description: "If set, always use a Homebrew-installed `ca-certificates` rather than the system version. " \ + "Automatically set if the system version is too old.", + boolean: true, + }, HOMEBREW_FORCE_BREWED_CURL: { description: "If set, always use a Homebrew-installed `curl`(1) rather than the system version. " \ "Automatically set if the system version of `curl` is too old.", diff --git a/Library/Homebrew/extend/os/mac/development_tools.rb b/Library/Homebrew/extend/os/mac/development_tools.rb index 353ae30428..f7c49645c1 100644 --- a/Library/Homebrew/extend/os/mac/development_tools.rb +++ b/Library/Homebrew/extend/os/mac/development_tools.rb @@ -10,7 +10,7 @@ class DevelopmentTools alias generic_locate locate undef installed?, default_compiler, curl_handles_most_https_certificates?, - subversion_handles_most_https_certificates? + ca_file_handles_most_https_certificates?, subversion_handles_most_https_certificates? sig { params(tool: String).returns(T.nilable(Pathname)) } def locate(tool) @@ -37,6 +37,13 @@ class DevelopmentTools :clang end + sig { returns(T::Boolean) } + def ca_file_handles_most_https_certificates? + # The system CA file is too old for some modern HTTPS certificates on + # older macOS versions. + ENV["HOMEBREW_SYSTEM_CA_CERTIFICATES_TOO_OLD"].nil? + end + sig { returns(T::Boolean) } def curl_handles_most_https_certificates? # The system Curl is too old for some modern HTTPS certificates on diff --git a/Library/Homebrew/formula_installer.rb b/Library/Homebrew/formula_installer.rb index dc4975b617..0fbee44fca 100644 --- a/Library/Homebrew/formula_installer.rb +++ b/Library/Homebrew/formula_installer.rb @@ -796,6 +796,12 @@ class FormulaInstaller # let's reset Utils::Git.available? if we just installed git Utils::Git.clear_available_cache if formula.name == "git" + # use installed ca-certificates when it's needed and available + if formula.name == "ca-certificates" && + !DevelopmentTools.ca_file_handles_most_https_certificates? + ENV["SSL_CERT_FILE"] = ENV["GIT_SSL_CAINFO"] = formula.pkgetc/"cert.pem" + end + # use installed curl when it's needed and available if formula.name == "curl" && !DevelopmentTools.curl_handles_most_https_certificates? diff --git a/Library/Homebrew/sorbet/rbi/hidden-definitions/hidden.rbi b/Library/Homebrew/sorbet/rbi/hidden-definitions/hidden.rbi index 2f3ce5b65d..c2568cc90c 100644 --- a/Library/Homebrew/sorbet/rbi/hidden-definitions/hidden.rbi +++ b/Library/Homebrew/sorbet/rbi/hidden-definitions/hidden.rbi @@ -4626,6 +4626,8 @@ module Homebrew::EnvConfig def self.forbidden_licenses(); end + def self.force_brewed_ca_certificates?(); end + def self.force_brewed_curl?(); end def self.force_brewed_git?(); end diff --git a/Library/Homebrew/utils/curl.rb b/Library/Homebrew/utils/curl.rb index 35f6b2651e..97eb98373d 100644 --- a/Library/Homebrew/utils/curl.rb +++ b/Library/Homebrew/utils/curl.rb @@ -100,11 +100,9 @@ module Utils verbose: verbose, }.compact - # SSL_CERT_FILE can be incorrectly set by users or portable-ruby and screw - # with SSL downloads so unset it here. result = system_command curl_executable(use_homebrew_curl: use_homebrew_curl), args: curl_args(*args, **options), - env: { "SSL_CERT_FILE" => nil }.merge(env), + env: env, timeout: end_time&.remaining, **command_options diff --git a/docs/Manpage.md b/docs/Manpage.md index f539da429f..e56fd566b7 100644 --- a/docs/Manpage.md +++ b/docs/Manpage.md @@ -1976,6 +1976,9 @@ example, run `export HOMEBREW_NO_INSECURE_REDIRECT=1` rather than just - `HOMEBREW_FORBIDDEN_LICENSES`
A space-separated list of licenses. Homebrew will refuse to install a formula if it or any of its dependencies has a license on this list. +- `HOMEBREW_FORCE_BREWED_CA_CERTIFICATES` +
If set, always use a Homebrew-installed `ca-certificates` rather than the system version. Automatically set if the system version is too old. + - `HOMEBREW_FORCE_BREWED_CURL`
If set, always use a Homebrew-installed `curl`(1) rather than the system version. Automatically set if the system version of `curl` is too old. diff --git a/manpages/brew.1 b/manpages/brew.1 index 1ec0872291..94d48a3d6b 100644 --- a/manpages/brew.1 +++ b/manpages/brew.1 @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . -.TH "BREW" "1" "September 2021" "Homebrew" "brew" +.TH "BREW" "1" "October 2021" "Homebrew" "brew" . .SH "NAME" \fBbrew\fR \- The Missing Package Manager for macOS (or Linux) @@ -2826,6 +2826,12 @@ Output this many lines of output on formula \fBsystem\fR failures\. A space\-separated list of licenses\. Homebrew will refuse to install a formula if it or any of its dependencies has a license on this list\. . .TP +\fBHOMEBREW_FORCE_BREWED_CA_CERTIFICATES\fR +. +.br +If set, always use a Homebrew\-installed \fBca\-certificates\fR rather than the system version\. Automatically set if the system version is too old\. +. +.TP \fBHOMEBREW_FORCE_BREWED_CURL\fR . .br