Skip to content

Instantly share code, notes, and snippets.

@geoff-nixon
Created September 22, 2015 13:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save geoff-nixon/4af746ca0b8aa5624a41 to your computer and use it in GitHub Desktop.
Save geoff-nixon/4af746ca0b8aa5624a41 to your computer and use it in GitHub Desktop.
#!/bin/sh
# How to "bake in" root certs in OpenSSL libcrypto (for OS X, etc), like node.js?
#
# https://hynek.me/articles/apple-openssl-verification-surprises/
#
# https://developer.apple.com/library/mac/documentation/Security/Conceptual/cryptoservices/SecureNetworkCommunicationAPIs/SecureNetworkCommunicationAPIs.html
#
# http://daniel.haxx.se/blog/2011/11/05/apples-modified-ca-cert-handling-and-curl/
#
# https://github.com/nodejs/node/commit/3beb880716654dbb2bbb9e333758825172951775
here=$(pwd)
sslver=1.0.2d
ssltgz=https://www.openssl.org/source/openssl-$sslver.tar.gz
# The node.js version of mk-ca-bundle.pl (different than the curl one).
nodemkca=https://raw.github.com/nodejs/node/master/tools/mk-ca-bundle.pl
# curlmkca=http://curl.haxx.se/cvssource/lib/mk-ca-bundle.pl
# The latest root certs from Mozilla, and the CNNIC whitelist.
mozsec=https://hg.mozilla.org/mozilla-central/raw-file/tip/security/
nsscerts=$mozsec/nss/lib/ckfw/builtins/certdata.txt
cnniclst=$mozsec/certverifier/CNNICHashWhitelist.inc
# Download the latest OpenSSL, then create a root_certs.h, containing the
# properly formatted PEMs and the CNNIC whitelist.
echo "Downloading OpenSSL $sslver..." >&2
curl -L\# $ssltgz | tar xz
cd openssl-*/include/openssl
echo "Downloading Mozilla Root Certificates..." >&2
# mk-ca-bundle.pl wants certdata.txt in $PWD.
curl -ORL\# $nsscerts
echo 'Creating `openssl/root_certs.h` using mk-ca-bundle.pl from node.js...' >&2
echo '#ifndef HEADER_ROOT_CERTS_H' > root_certs.h
echo '# define HEADER_ROOT_CERTS_H' >> root_certs.h
echo >> root_certs.h
# As at https://github.com/nodejs/node/blob/master/src/node_crypto.cc#L128
echo 'const char* const root_certs[] = {' >> root_certs.h
curl -L\# $nodemkca | perl - -- - >> root_certs.h
echo '};' >> root_certs.h
echo >> root_certs.h
rm certdata.txt
echo "Appending root_certs.h with whitelist of CNNIC-issued certificates..." >&2
# Need to take out the uint8_t because OpenSSL is purely C89.
curl -L\# $cnniclst | sed 's|uint8_t|unsigned char|' >> root_certs.h
echo '#endif /* HEADER_ROOT_CERTS_H */' >> root_certs.h
echo >> root_certs.h
cd "$here"
echo >&2
echo 'Now patch relevant file(s) with `#include <openssl/root_certs.h>`,' >&2
echo ' ...and the magic code to make this actually work. Can you help?' >&2
# The OS X system keychains, as processed by Homebrew openssl formula.
# I'm not sure why, but there are significantly more CA's in this list.
# For reference only; I'm sure the Mozilla list is fine.
# ruby -e 'keychains = %w[
# /Library/Keychains/System.keychain
# /System/Library/Keychains/SystemRootCertificates.keychain
# ]
#
# certs_list = `security find-certificate -a -p #{keychains.join(" ")}`
# certs = certs_list.scan(
# /-----BEGIN CERTIFICATE-----.*?-----END CERTIFICATE-----/m
# )
#
# valid_certs = certs.select do |cert|
# IO.popen("openssl x509 -inform pem -checkend 0 -noout", "w") do |openssl_io|
# openssl_io.write(cert)
# openssl_io.close_write
# end
#
# $?.success?
# end
#
# puts valid_certs'
# This could, I suppose, combined with the Mozilla list by piping the output and
# the output of the curl version of mk-ca-bundle.pl (stripped of comments) to
# something like:
# tr -d \n | sed 's|-----B|,-----B|g' | tr , \n | sed '/^$/d' | sort | uniq
#
# ... but I digress.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment