5 Helper script for CRL (certificate revocation list) file extraction
6 to a directory containing files named as decimal serial numbers of
7 the revoked certificates, to be used with OpenVPN CRL directory
8 verify mode. To enable this mode, directory and 'dir' flag needs to
9 be specified as parameters of '--crl-verify' option.
10 For more information refer OpenVPN tls-options.rst.
13 extractcrl.py -f pem /path/to/crl.pem /path/to/outdir
14 extractcrl.py -f der /path/to/crl.crl /path/to/outdir
15 cat /path/to/crl.pem | extractcrl.py -f pem - /path/to/outdir
16 cat /path/to/crl.crl | extractcrl.py -f der - /path/to/outdir
19 Loaded: 309797 revoked certs in 4.136s
20 Scanned: 312006 files in 0.61s
21 Created: 475 files in 0.05s
22 Removed: 2684 files in 0.116s
29 from subprocess
import check_output
35 def elapsed(*args, **kwargs):
37 result = method(*args, **kwargs)
38 return result, round(time.time() - start, 3)
44 def try_openssl_module(filename, format):
45 from OpenSSL
import crypto
47 FILETYPE_PEM: crypto.FILETYPE_PEM,
48 FILETYPE_DER: crypto.FILETYPE_ASN1
51 crl = crypto.load_crl(types[format], sys.stdin.buffer.read())
53 with open(filename,
'rb')
as f:
54 crl = crypto.load_crl(types[format], f.read())
55 return set(int(r.get_serial(), 16)
for r
in crl.get_revoked())
57 def try_openssl_exec(filename, format):
58 args = [
'openssl',
'crl',
'-inform', format,
'-text']
60 args += [
'-in', filename]
62 for line
in check_output(args, universal_newlines=
True).splitlines():
63 _, _, serial = line.partition(
'Serial Number:')
65 serials.add(int(serial.strip(), 16))
69 return try_openssl_module(filename, format)
71 return try_openssl_exec(filename, format)
75 _, _, files = next(os.walk(dirname))
76 return set(int(f)
for f
in files
if f.isdigit())
80 addset = newset.difference(oldset)
83 with open(os.path.join(dirname, str(serial)),
'xb'):
pass
84 except FileExistsError:
90 delset = oldset.difference(newset)
93 os.remove(os.path.join(dirname, str(serial)))
94 except FileNotFoundError:
99 if arg ==
'-' or os.path.isfile(arg):
101 raise argparse.ArgumentTypeError(
'No such file "{}"'.format(arg))
104 if os.path.isdir(arg):
106 raise argparse.ArgumentTypeError(
'No such directory: "{}"'.format(arg))
109 parser = argparse.ArgumentParser(description=
'OpenVPN CRL extractor')
110 parser.add_argument(
'-f',
'--format',
112 default=FILETYPE_PEM, choices=[FILETYPE_PEM, FILETYPE_DER],
113 help=
'input CRL format - default {}'.format(FILETYPE_PEM)
115 parser.add_argument(
'crlfile', metavar=
'CRLFILE|-',
117 help=
'input CRL file or "-" for stdin'
119 parser.add_argument(
'outdir', metavar=
'OUTDIR',
121 help=
'output directory for serials numbers'
123 args = parser.parse_args()
125 certs, t =
load_crl(args.crlfile, args.format)
126 print(
'Loaded: {} revoked certs in {}s'.format(len(certs), t))
129 print(
'Scanned: {} files in {}s'.format(len(files), t))
132 print(
'Created: {} files in {}s'.format(len(created), t))
135 print(
'Removed: {} files in {}s'.format(len(removed), t))
137 if __name__ ==
"__main__":