#!/usr/bin/python2.7 # # Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. # # # Generate OpenSSL hash links to CA certificates stored in /etc/certs/CA. # import os import sys import pwd import grp import smf_include from tempfile import mkstemp import OpenSSL.crypto as cert CERTS = '/etc/certs/CA' RELCDIR = '../../certs/CA' LINKDIR = '/etc/openssl/certs' CERTSFILE = '/etc/certs/ca-certificates.crt' def generate_links(): # Empty the link directory and recreate it all for linkfile in os.listdir(LINKDIR): try: os.unlink(os.path.join(LINKDIR, linkfile)) except: pass print "Re-generating OpenSSL hash Links" for cfile in os.listdir(CERTS): try: pembuf = cert.load_certificate(cert.FILETYPE_PEM, file( os.path.join(CERTS, cfile)).read()) except (cert.Error, IOError): print "File: %s is not a valid PEM file; skipping" % \ os.path.join(CERTS, cfile) continue # hash filename is hex without leading 0x but with a .0 suffix shash = "%08x.0" % pembuf.subject_name_hash() os.symlink(os.path.join(RELCDIR, cfile), os.path.join(LINKDIR, shash)) def generate_ca_pem(): print "Re-generating OpenSSL PEM file" certs = os.listdir(CERTS) cacrt = ''.join((open(os.path.join(CERTS, cert)).read() for cert in certs)) _, tmpfile = mkstemp(dir=os.path.dirname(CERTSFILE)) with open(tmpfile, "w") as outfile: outfile.write(cacrt) os.chmod(tmpfile, 0644) os.rename(tmpfile, CERTSFILE) def check_prereq(): # # The LINKDIR and CERTS dir are packaged so they should exist. # We can recover from a missing LINKDIR but not a missing CERTS dir if not os.path.isdir(LINKDIR): # # Ideally we should 'pkg fix' or at least look at the pkg. # However we just hard code the root:sys 755 # os.mkdir(LINKDIR, 0755) os.chown(LINKDIR, pwd.getpwnam("root").pw_uid, grp.getgrnam("sys").gr_gid) print "Missing directory %s re-created" % LINKDIR if not os.path.isdir(CERTS): print CERTS + "is missing. Run 'pkg fix ca-certificates'" return smf_include.SMF_EXIT_ERR_CONFIG def start(): check_prereq() # # Update LINKDIR and CERTSFILE only if they are older than # the CERTS dir or its newest certificate. # newest = 0 for cfile in os.listdir(CERTS): certage = os.path.getmtime(os.path.join(CERTS, cfile)) if certage > newest: newest = certage if (len(os.listdir(LINKDIR)) != len(os.listdir(CERTS)) or os.path.getmtime(LINKDIR) < newest): generate_links() if not os.path.isfile(CERTSFILE) or os.path.getmtime(CERTSFILE) < newest: generate_ca_pem() return smf_include.SMF_EXIT_OK def stop(): return smf_include.SMF_EXIT_OK def refresh(): check_prereq() # Forced full update on refresh. generate_links() generate_ca_pem() return smf_include.SMF_EXIT_OK smf_include.smf_main()