gpodder/tools/mac-osx/make_cert_pem.py

88 lines
2.8 KiB
Python

# -*- 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))