ca-certificates/certdata2pem.py
Kai Engert d538ada99c * Fri Mar 08 2013 Kai Engert <kaie@redhat.com> - 2012.87-9
- Major rework for the Fedora SharedSystemCertificates feature.
- Only ship a PEM bundle file using the BEGIN TRUSTED CERTIFICATE file format.
- Require the p11-kit package that contains tools to automatically create
  other file format bundles.
- Convert old file locations to symbolic links that point to dynamically
  generated files.
- Old files, which might have been locally modified, will be saved in backup
  files with .rpmsave extension.
- Added a update-ca-certificates script which can be used to regenerate
  the merged trusted output.
- Refer to the various README files that have been added for more detailed
  explanation of the new system.
- No longer require rsc for building.
- Add explanation for the future version numbering scheme,
  because the old numbering scheme was based on upstream using cvs,
  which is no longer true, and therefore can no longer be used.
- Includes changes from rhbz#873369.
2013-03-09 00:09:26 +01:00

161 lines
5.5 KiB
Python

#!/usr/bin/python
# vim:set et sw=4:
#
# certdata2pem.py - splits certdata.txt into multiple files
#
# Copyright (C) 2009 Philipp Kern <pkern@debian.org>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301,
# USA.
import base64
import os.path
import re
import sys
import textwrap
objects = []
# Dirty file parser.
in_data, in_multiline, in_obj = False, False, False
field, type, value, obj = None, None, None, dict()
for line in open('certdata.txt', 'r'):
# Ignore the file header.
if not in_data:
if line.startswith('BEGINDATA'):
in_data = True
continue
# Ignore comment lines.
if line.startswith('#'):
continue
# Empty lines are significant if we are inside an object.
if in_obj and len(line.strip()) == 0:
objects.append(obj)
obj = dict()
in_obj = False
continue
if len(line.strip()) == 0:
continue
if in_multiline:
if not line.startswith('END'):
if type == 'MULTILINE_OCTAL':
line = line.strip()
for i in re.finditer(r'\\([0-3][0-7][0-7])', line):
value += chr(int(i.group(1), 8))
else:
value += line
continue
obj[field] = value
in_multiline = False
continue
if line.startswith('CKA_CLASS'):
in_obj = True
line_parts = line.strip().split(' ', 2)
if len(line_parts) > 2:
field, type = line_parts[0:2]
value = ' '.join(line_parts[2:])
elif len(line_parts) == 2:
field, type = line_parts
value = None
else:
raise NotImplementedError, 'line_parts < 2 not supported.'
if type == 'MULTILINE_OCTAL':
in_multiline = True
value = ""
continue
obj[field] = value
if len(obj.items()) > 0:
objects.append(obj)
# Build up trust database.
trustmap = dict()
for obj in objects:
if obj['CKA_CLASS'] != 'CKO_NSS_TRUST':
continue
label = obj['CKA_LABEL']
trustmap[label] = obj
print " added cert", label
def obj_to_filename(obj):
label = obj['CKA_LABEL'][1:-1]
label = label.replace('/', '_')\
.replace(' ', '_')\
.replace('(', '=')\
.replace(')', '=')\
.replace(',', '_')
label = re.sub(r'\\x[0-9a-fA-F]{2}', lambda m:chr(int(m.group(0)[2:], 16)), label)
serial = ".".join(map(lambda x:str(ord(x)), obj['CKA_SERIAL_NUMBER']))
return label + ":" + serial + ".crt"
trust_types = {
"CKA_TRUST_DIGITAL_SIGNATURE": "digital-signature",
"CKA_TRUST_NON_REPUDIATION": "non-repudiation",
"CKA_TRUST_KEY_ENCIPHERMENT": "key-encipherment",
"CKA_TRUST_DATA_ENCIPHERMENT": "data-encipherment",
"CKA_TRUST_KEY_AGREEMENT": "key-agreement",
"CKA_TRUST_KEY_CERT_SIGN": "cert-sign",
"CKA_TRUST_CRL_SIGN": "crl-sign",
"CKA_TRUST_SERVER_AUTH": "server-auth",
"CKA_TRUST_CLIENT_AUTH": "client-auth",
"CKA_TRUST_CODE_SIGNING": "code-signing",
"CKA_TRUST_EMAIL_PROTECTION": "email-protection",
"CKA_TRUST_IPSEC_END_SYSTEM": "ipsec-end-system",
"CKA_TRUST_IPSEC_TUNNEL": "ipsec-tunnel",
"CKA_TRUST_IPSEC_USER": "ipsec-user",
"CKA_TRUST_TIME_STAMPING": "time-stamping",
"CKA_TRUST_STEP_UP_APPROVED": "step-up-approved",
}
openssl_trust = {
"CKA_TRUST_SERVER_AUTH": "serverAuth",
"CKA_TRUST_CLIENT_AUTH": "clientAuth",
"CKA_TRUST_CODE_SIGNING": "codeSigning",
"CKA_TRUST_EMAIL_PROTECTION": "emailProtection",
}
for obj in objects:
if obj['CKA_CLASS'] == 'CKO_CERTIFICATE':
print "producing cert file for " + obj['CKA_LABEL']
fname = obj_to_filename(obj)
f = open(fname, 'w')
trustbits = []
distrustbits = []
openssl_trustflags = []
openssl_distrustflags = []
tobj = trustmap[obj['CKA_LABEL']]
for t in trust_types.keys():
if tobj.has_key(t) and tobj[t] == 'CKT_NSS_TRUSTED_DELEGATOR':
trustbits.append(t)
if t in openssl_trust:
openssl_trustflags.append(openssl_trust[t])
if tobj.has_key(t) and tobj[t] == 'CKT_NSS_NOT_TRUSTED':
distrustbits.append(t)
if t in openssl_trust:
openssl_distrustflags.append(openssl_trust[t])
f.write("# trust=" + " ".join(trustbits) + "\n")
f.write("# distrust=" + " ".join(distrustbits) + "\n")
if openssl_trustflags:
f.write("# openssl-trust=" + " ".join(openssl_trustflags) + "\n")
if openssl_distrustflags:
f.write("# openssl-distrust=" + " ".join(openssl_distrustflags) + "\n")
f.write("-----BEGIN CERTIFICATE-----\n")
f.write("\n".join(textwrap.wrap(base64.b64encode(obj['CKA_VALUE']), 64)))
f.write("\n-----END CERTIFICATE-----\n")
print " -> written as '%s', trust = %s, openssl-trust = %s, distrust = %s, openssl-distrust = %s" % (fname, trustbits, openssl_trustflags, distrustbits, openssl_distrustflags)