# -*- coding: utf-8 -*- """ A script to initialize our bundled openssl CA trust store based on your System's keychain Released under the same licence as gPodder (GPL3 or later) Copyright (c) 2016 Eric Le Lay """ import argparse import re import subprocess import sys import traceback from subprocess import PIPE, CalledProcessError, Popen def is_valid_cert(openssl, cert): """ check if cert is valid according to openssl""" cmd = [openssl, "x509", "-inform", "pem", "-checkend", "0", "-noout"] # print("D: is_valid_cert %r" % cmd) proc = Popen(cmd, stdin=PIPE, stdout=PIPE, stderr=PIPE) stdout, stderr = proc.communicate(cert) # print("out: %s; err:%s; ret:%i" % (stdout, stderr, proc.returncode)) return proc.returncode == 0 def get_certs(openssl): """ extract System's certificates then filter them by validity and return a list of text of valid certs """ cmd = ["security", "find-certificate", "-a", "-p", "/System/Library/Keychains/SystemRootCertificates.keychain"] cert_re = re.compile(b"^-----BEGIN CERTIFICATE-----$" + b".+?" + b"^-----END CERTIFICATE-----$", re.M | re.S) try: certs_str = subprocess.check_output(cmd) all_certs = cert_re.findall(certs_str) print("I: extracted %i certificates" % len(all_certs)) valid_certs = [cert for cert in all_certs if is_valid_cert(openssl, cert)] print("I: of which %i are valid certificates" % len(valid_certs)) return valid_certs except OSError: print("E: extracting certificates using %r" % cmd) traceback.print_exc() except CalledProcessError as err: print(("E: extracting certificates using %r, exit=%i" % (cmd, err.returncode))) def write_certs(certs, dest): """ write concatenated certs to dest """ with open(dest, "wb") as output: output.write(b"\n".join(certs)) def main(openssl, dest): """ main program """ print("I: make_cert_pem.py %s %s" % (openssl, dest)) certs = get_certs(openssl) if certs is None: print("E: no certificate extracted") return -1 else: write_certs(certs, dest) print("I: updated %s with %i certificates" % (dest, len(certs))) return 0 PARSER = argparse.ArgumentParser( description='Extract system certificates for openssl') PARSER.add_argument("openssl", metavar="OPENSSL_EXE", help="absolute path to the openssl executable") PARSER.add_argument("dest", metavar="DEST_FILE", help="absolute path to the certs.pem file to write to") if __name__ == "__main__": ARGS = PARSER.parse_args() sys.exit(main(ARGS.openssl, ARGS.dest))