2014-12-30 18:25:32 +00:00
|
|
|
#!/usr/bin/env python
|
|
|
|
# -*- coding: utf-8 -*-
|
|
|
|
#
|
|
|
|
# Analyze CRLs stored in a directory and dump a JSON
|
|
|
|
#
|
|
|
|
# Software is free software released under the GNU General Public License version 3 and later
|
|
|
|
#
|
|
|
|
# Copyright (c) 2014 Alexandre Dulaunoy - a@foo.be
|
|
|
|
|
|
|
|
import argparse
|
|
|
|
import sys
|
|
|
|
import os
|
|
|
|
from pyasn1_modules import rfc2459
|
|
|
|
crlspec = rfc2459.CertificateList()
|
|
|
|
from pyasn1.codec.der import decoder
|
|
|
|
import OpenSSL
|
|
|
|
import json
|
|
|
|
import binascii
|
|
|
|
import datetime
|
|
|
|
|
|
|
|
argParser = argparse.ArgumentParser(description='Analyze CRLs stored in a directory')
|
|
|
|
argParser.add_argument('-v', action='store_true', help='Verbose output')
|
|
|
|
argParser.add_argument('-d', help='Path where CRLs are stored')
|
|
|
|
argParser.add_argument('-j', action='store_false', default=True, help='Toggle JSON output (default)')
|
|
|
|
args = argParser.parse_args()
|
|
|
|
|
|
|
|
if not args.d:
|
|
|
|
argParser.print_help()
|
|
|
|
sys.exit()
|
|
|
|
|
|
|
|
def DNToString(dn):
|
|
|
|
ret = ""
|
|
|
|
for x in dn:
|
|
|
|
for y in x:
|
|
|
|
ret = ret + " " + str(y[0][1])
|
|
|
|
return ret
|
|
|
|
|
|
|
|
for crl in os.listdir(args.d):
|
|
|
|
crlpath = os.path.join(args.d,crl)
|
|
|
|
f = open(crlpath, 'rb')
|
|
|
|
crlfile = f.read()
|
|
|
|
try:
|
|
|
|
crlp = OpenSSL.crypto.load_crl(OpenSSL.crypto.FILETYPE_ASN1, crlfile)
|
|
|
|
except Exception, err:
|
|
|
|
if args.v:
|
|
|
|
print err
|
|
|
|
continue
|
|
|
|
|
|
|
|
fx = open(crlpath, 'rb')
|
|
|
|
crlfileasn = fx.read()
|
|
|
|
try:
|
|
|
|
cert, rest = decoder.decode(crlfileasn, asn1Spec=crlspec)
|
|
|
|
except Exception, err:
|
|
|
|
if args.v:
|
|
|
|
print err
|
|
|
|
continue
|
|
|
|
a = cert['tbsCertList']
|
|
|
|
if a.getComponentByName('thisUpdate') is not None:
|
|
|
|
thisUpdate = str(a.getComponentByName('thisUpdate')[0])
|
|
|
|
else:
|
|
|
|
thisUpdate = None
|
|
|
|
if a.getComponentByName('nextUpdate') is not None:
|
|
|
|
nextUpdate = str(a.getComponentByName('nextUpdate')[0])
|
|
|
|
else:
|
|
|
|
nextUpdate = None
|
|
|
|
issuer = DNToString(a.getComponentByName('issuer'))
|
|
|
|
fx.close()
|
|
|
|
|
|
|
|
if crlp.get_revoked() is None:
|
|
|
|
o = {'crlpath': crlpath, 'revoked': None, 'issuer' : issuer, 'thisUpdate': thisUpdate, 'nextUpdate': nextUpdate}
|
|
|
|
else:
|
|
|
|
o = {'crlpath': crlpath, 'revoked': [], 'issuer' : issuer, 'thisUpdate': thisUpdate, 'nextUpdate': nextUpdate}
|
|
|
|
for revoked in crlp.get_revoked():
|
|
|
|
o['revoked'].append({'serial':revoked.get_serial(), 'rev_date':revoked.get_rev_date(), 'reason':revoked.get_reason()})
|
|
|
|
if args.j:
|
2014-12-30 20:21:45 +00:00
|
|
|
print json.dumps(o, ensure_ascii=False)
|