jdennis%redhat.com d60083d124 Invoke nss_init_nodb() when nss modules loads, this prevents segfaults
in NSS if Python programmer forgot to call one of the NSS
initialization routines.

Rename the classes X500Name, X500RDN, X500AVA to DN, RDN, AVA
respectively.

DN and RDN objects now return a list of their contents when indexed by
type, this is to support multi-valued items.

Fix bug where AVA object's string representation did not include it's
type.

Enhance test/test_cert_components.py unit test to test for above
changes.


git-svn-id: svn://10.0.0.236/trunk@260568 18797224-902f-48f8-a5cc-f745e15eee43
2010-06-24 19:26:08 +00:00

196 lines
7.6 KiB
Python
Executable File

#!/usr/bin/python
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla Public License Version
# 1.1 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is a Python binding for Network Security Services (NSS).
#
# The Initial Developer of the Original Code is Red Hat, Inc.
# (Author: John Dennis <jdennis@redhat.com>)
#
# Portions created by the Initial Developer are Copyright (C) 2008,2009
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
#
# Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later (the "GPL"), or
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL, and not to allow others to
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****
'''
This example will pretty print the contents of a certificate loaded from a
file. This is not the easiest or best way to print a certificate, the nss
module has internal code to do that, all you need to invoke the str()
method of the certificate, or it's format, or format_lines()
method. Something as simple as the following will work:
print cert
print "Certificate is %s" % cert
What this example really aims to do is illustrate how to access the various
components of a cert.
'''
import os
import sys
import getopt
import getpass
from nss.error import NSPRError
import nss.io as io
import nss.nss as nss
# -----------------------------------------------------------------------------
def print_extension(level, extension):
print nss.indented_format([(level, 'Name: %s' % extension.name),
(level, 'Critical: %s' % extension.critical)])
oid_tag = extension.oid_tag
if oid_tag == nss.SEC_OID_PKCS12_KEY_USAGE:
print nss.indented_format([(level, 'Usages:')])
print nss.indented_format(nss.make_line_pairs(level+1, nss.x509_key_usage(extension.value)))
elif oid_tag == nss.SEC_OID_X509_SUBJECT_KEY_ID:
print nss.indented_format([(level, 'Data:')])
print nss.indented_format(nss.make_line_pairs(level+1,
extension.value.der_to_hex(nss.OCTETS_PER_LINE_DEFAULT)))
elif oid_tag == nss.SEC_OID_X509_CRL_DIST_POINTS:
pts = nss.CRLDistributionPts(extension.value)
i = 1
print nss.indented_format([(level, 'CRL Distribution Points: [%d total]' % len(pts))])
for pt in pts:
print nss.indented_format([(level+1, 'Point[%d]:' % i)])
names = pt.get_general_names()
print nss.indented_format([(level+2, 'General Names: [%d total]' % len(names))])
for name in names:
print nss.indented_format([(level+3, '%s:' % name)])
print nss.indented_format([(level+2, 'Reasons: %s' % (pt.get_reasons(),))])
print nss.indented_format([(level+2, 'Issuer: %s' % pt.issuer)])
elif oid_tag == nss.SEC_OID_X509_AUTH_KEY_ID:
auth_key_id = nss.AuthKeyID(extension.value)
print nss.indented_format([(level+1, 'Key ID:')])
print nss.indented_format(nss.make_line_pairs(level+2,
auth_key_id.key_id.to_hex(nss.OCTETS_PER_LINE_DEFAULT)))
print nss.indented_format([(level+1, 'Serial Number: %s' % (auth_key_id.serial_number))])
print nss.indented_format([(level+1, 'Issuer:' % auth_key_id.get_general_names())])
elif oid_tag == nss.SEC_OID_X509_BASIC_CONSTRAINTS:
bc = nss.BasicConstraints(extension.value)
print nss.indented_format([(level, '%s' % str(bc))])
elif oid_tag == nss.SEC_OID_X509_EXT_KEY_USAGE:
print nss.indented_format([(level, 'Usages:')])
print nss.indented_format(nss.make_line_pairs(level+1, nss.x509_ext_key_usage(extension.value)))
elif oid_tag in (nss.SEC_OID_X509_SUBJECT_ALT_NAME, nss.SEC_OID_X509_ISSUER_ALT_NAME):
names = nss.x509_alt_name(extension.value)
print nss.indented_format([(level+2, 'Alternate Names: [%d total]' % len(names))])
for name in names:
print nss.indented_format([(level+3, '%s:' % name)])
print
# -----------------------------------------------------------------------------
usage_str = '''
-p --pem read the certifcate in PEM ascii format (default)
-d --der read the certifcate in DER binary format
'''
def usage():
print usage_str
try:
opts, args = getopt.getopt(sys.argv[1:], "hpd",
["help", "pem", "der"])
except getopt.GetoptError:
# print help information and exit:
usage()
sys.exit(2)
filename = 'cert.der'
is_pem_format = True
for o, a in opts:
if o in ("-H", "--help"):
usage()
sys.exit()
elif o in ("-p", "--pem"):
is_pem_format = True
elif o in ("-d", "--der"):
is_pem_format = False
filename = sys.argv[1]
# Perform basic configuration and setup
nss.nss_init_nodb()
if len(args):
filename = args[0]
print "certificate filename=%s" % (filename)
# Read the certificate as DER encoded data
si = nss.read_der_from_file(filename, is_pem_format)
# Parse the DER encoded data returning a Certificate object
cert = nss.Certificate(si)
# Get the extension list from the certificate
extensions = cert.extensions
print nss.indented_format([(0, 'Certificate:'),
(1, 'Data:')])
print nss.indented_format([(2, 'Version: %d (%#x)' % (cert.version+1, cert.version))])
print nss.indented_format([(2, 'Serial Number: %d (%#x)' % (cert.serial_number, cert.serial_number))])
print nss.indented_format([(2, 'Signature Algorithm: %s' % cert.signature_algorithm)])
print nss.indented_format([(2, 'Issuer: "%s"' % cert.issuer)])
print nss.indented_format([(2, 'Validity:'),
(3, 'Not Before: %s' % cert.valid_not_before_str),
(3, 'Not After: %s' % cert.valid_not_after_str)])
print nss.indented_format([(2, 'Subject: "%s"' % cert.subject)])
print nss.indented_format([(2, 'Subject Public Key Info:')])
print nss.indented_format(cert.subject_public_key_info.format_lines(3))
if len(extensions) > 0:
print nss.indented_format([(1, 'Signed Extensions: (%d)' % len(extensions))])
for extension in extensions:
print_extension(2, extension)
print nss.indented_format(cert.signed_data.format_lines(1))
print nss.indented_format([(1, 'Fingerprint (MD5):')])
print nss.indented_format(nss.make_line_pairs(2,
nss.data_to_hex(nss.md5_digest(cert.der_data),
nss.OCTETS_PER_LINE_DEFAULT)))
print nss.indented_format([(1, 'Fingerprint (SHA1):')])
print nss.indented_format(nss.make_line_pairs(2,
nss.data_to_hex(nss.sha1_digest(cert.der_data),
nss.OCTETS_PER_LINE_DEFAULT)))