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

curl-ca-bundle: dump CA certs from Keychain #26060

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

laggardkernel
Copy link
Contributor

@laggardkernel laggardkernel commented Oct 3, 2024

Description

Steal Borrow the CA certs handling from Homebrew's ca-certificates: download CA certs from Mozilla, dump CA certs (installed by user) from Keychain, and merge them together.

In the intranet of my worksplace, we have internal sites with self-signed certs, thru everyone download and trust a CA. Without change in this PR, i need to add the public key of intranet CA into curl-ca-bundle.crt every time it gets updated. And after some investigation, I found the solution from Homebrew and I think it perfect to my situation.

I noticed there is a certsync package, which sync CAs from Keychain. But it only uses CAs from the Keychain. While the curl-ca-bundle fetches CAs maintained by Mozilla, which is more up-to-update.

Anyway, I think highly of this merge strategy and it deserves being mentioned, and made this PR.

The code is a line to line adaption from the ruby code from Homebrew ca-certificates, except the ui_debug msg I added and kept here.

BTW, since MacPorts is run by user macports during installation, only CA certs in "System Keychains -> System", those CA installed for all users on the computer will be dumped. While, Homebrew is run by current user, the certs get dumped may differ with MacPorts.

Type(s)
  • bugfix
  • enhancement
  • security fix
Tested on

macOS 12.7 21G816 arm64
Command Line Tools 14.2.0.0.1.1668646533

Verification

Have you

  • followed our Commit Message Guidelines?
  • squashed and minimized your commits?
  • checked that there aren't other open pull requests for the same change?
  • referenced existing tickets on Trac with full URL in commit message?
  • checked your Portfile with port lint --nitpick?
  • tried existing tests with sudo port test?
  • tried a full install with sudo port -vst install? (no trace mode enabled)
  • tested basic functionality of all binary files?
  • checked that the Portfile's most important variants haven't been broken?

@macportsbot
Copy link

Notifying maintainers:
@ryandesign for port curl.

@@ -352,10 +352,110 @@ subport curl-ca-bundle {
set ca_bundle_dir ${prefix}/share/curl
set openssl_dir ${prefix}/etc/openssl
xinstall -d ${destroot}${ca_bundle_dir} ${destroot}${openssl_dir}
xinstall -m 644 ${worksrcpath}/lib/ca-bundle.crt ${destroot}${ca_bundle_dir}/curl-ca-bundle.crt
foreach dst [list mozilla-ca-bundle.crt curl-ca-bundle.crt] {
Copy link
Contributor Author

@laggardkernel laggardkernel Oct 3, 2024

Choose a reason for hiding this comment

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

mozilla-ca-bundle.crt is the downloaded CAs. curl-ca-bundle.crt serves as the merge file, and should be overridden in activate stage. I duplicate it here in case activate stage is interrupted by the user.

Copy link
Contributor

@ryandesign ryandesign left a comment

Choose a reason for hiding this comment

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

I have not reviewed the code changes and have no comment on whether these changes are desirable. I'll just say that https://trac.macports.org/ticket/35474 is an alternate suggestion to save each certificate in its own file. That ticket is also where the certsync software originated, and was thought to be a solution to the problem.

net/curl/Portfile Outdated Show resolved Hide resolved

set keychains {
/Library/Keychains/System.keychain
/System/Library/Keychains/SystemRootCertificates.keychain
Copy link
Contributor

Choose a reason for hiding this comment

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

Are these paths identical for all macOS versions starting from 10.4?

set certs [regexp -inline -all -- {-----BEGIN CERTIFICATE-----.*?-----END CERTIFICATE-----} $certs_list]

ui_debug "Filter valid certificates: not expired, SSL root"
set checkend_cmd "/usr/bin/openssl x509 -inform pem -checkend 0 -noout"
Copy link
Contributor

Choose a reason for hiding this comment

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

I cannot check right now, but this may fail on older macOS.
curl is a fundamental port, so this should be confirmed prior to merging.


ui_debug "Filter certificates trusted in keychain"
file tempfile tmpfile_path /tmp/macports-${name}.txt
set verify_cmd "/usr/bin/security verify-cert -l -L -c $tmpfile_path -p ssl"
Copy link
Contributor

@barracuda156 barracuda156 Oct 7, 2024

Choose a reason for hiding this comment

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

Same question: does this work on 10.4+?

Co-authored-by: Ryan Carsten Schmidt <[email protected]>
@laggardkernel
Copy link
Contributor Author

I'll just say that https://trac.macports.org/ticket/35474 is an alternate suggestion to save each certificate in its own file.

@ryandesign I have read the trac ticket. It seems to me the key difference between these solutions is not whether split cert into its own file, but what place is used as the trusted source of CA certs:

- ticket 35474 certsync this PR
Public CAs Mozilla Keychain Mozilla
Self-signed CAs CA in ${prefix}/etc/openssl/certs/ Keychain Keychain

It doesn't matter we separate each CA cert into its own file or not. Cuz a merged CA bundle is always need, the bundle file is the very file provided to other apps and used by them. (Like specifiying ca for curl using CURL_CA_BUNDLE.)

Putting self-signed CAs into a /path/certs/ path does work, but macOS defined another entry for self-signed CAs.

As far as I've known, GUI apps like Charles install self-signed CA into Keychain. /usr/bin/curl, the one shipped with macOS, can also access self-signed CA in Keychain thru "Secure Transport". It is the Keychain but not the ${prefix}/etc/openssl/certs/ folder that is used as the official place to trust self-signed CAs.

@barracuda156
Copy link
Contributor

@kencu Ken, could you please confirm if this works on 10.5.8? (I am away from my hardware now.)

@neverpanic
Copy link
Member

What advantage does this approach have over recommending users to install certsync?

One potential issue I see with this is that distrusting a CA now requires doing that in two locations (but then again, removing a CA from the Mozilla bundle wasn't something we ever supported in the first place).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

Successfully merging this pull request may close these issues.

5 participants