/
fetch_crl.py
121 lines (107 loc) · 3.81 KB
/
fetch_crl.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
from OpenSSL import SSL, crypto
from StringIO import StringIO
import sys
import ldap
from urlparse import urlparse
import urllib
from pyasn1.codec.der import decoder
from pyasn1.codec.der import encoder
from pyasn1_modules import rfc2459
from base64 import b64encode
from ldif import LDIFRecordList
import pycurl
extType = rfc2459.Extension()
crlType = rfc2459.CertificateList()
context = SSL.Context(SSL.TLSv1_METHOD) # Use TLS Method
context.set_options(SSL.OP_NO_SSLv2) # Don't accept SSLv2
#context.set_options(SSL.OP_NO_SSLv3) # Don't accept SSLv2
# we don't need to verify (yet)
#context.set_verify(SSL.VERIFY_NONE, callback)
#context.load_verify_locations(ca_file, ca_path)
from socket import socket
def extract_URIs(extension):
# TODO: extract the URI properly from ASN.1
urls = []
#try:
# asn = decoder.decode(extension.get_data(),asn1Spec=extType)
# print 'asn was',asn
#except Exception as e:
# print 'oops!', e
for line in str(extension).split('\n'):
if 'URI:' in line:
urls.append(line.split(':',1)[1])
return urls
def get_chain(host, port):
sock = socket()
ssl_sock = SSL.Connection(context, sock)
ssl_sock.connect((host, port))
ssl_sock.do_handshake()
return ssl_sock.get_peer_cert_chain()
def fetchCRL(crlURI):
crlLocation = urlparse(crlURI)
if 'ldap' == crlLocation.scheme:
buffer = StringIO()
c = pycurl.Curl()
c.setopt(c.URL, crlURI)
c.setopt(c.WRITEDATA, buffer)
c.perform()
c.close()
body = buffer.getvalue()
buffer = StringIO(body)
parser = LDIFRecordList(buffer)
parser.parse()
dn, entry = parser.all_records[0]
crl = entry[entry.keys()[-1]][0]
return crl
else:
return urllib.urlopen(crlURI).read()
def parseCRL(crlData):
try:
if None != crlData:
stuff = decoder.decode(crlData,asn1Spec=crlType)
for crl in stuff:
#print crl.prettyPrint()
return stuff
except Exception as e:
print 'parsing failed',e
def getRevokedSerials(crl):
serials = []
if None != crl[0]['tbsCertList'] and None != crl[0]['tbsCertList']['revokedCertificates']:
print b64encode(encoder.encode(crl[0]['tbsCertList']['issuer']))
for cert in crl[0]['tbsCertList']['revokedCertificates']:
serials.append(b64encode(encoder.encode(cert['userCertificate'])))
return serials
if __name__ == '__main__':
for line in sys.stdin.readlines():
try:
url = urlparse(line.rstrip())
host = url.hostname
port = 443
print host
try:
port = int(url.port)
except:
pass
try:
#if True:
#for cert in get_chain(host, port):
chain = get_chain(host, port)
if len(chain) > 2:
#cert = chain[1]
#if True:
for cert in chain[1:-1]:
print cert.get_subject()
count = cert.get_extension_count()
for index in range(0,count):
extension = cert.get_extension(index)
if 'crlDistributionPoints' == extension.get_short_name():
for crlURI in extract_URIs(extension):
print 'crl uri is', crlURI,"\n\n\n"
crlData = fetchCRL(crlURI)
f = open('crls/'+host+'.crl','w')
f.write(crlData)
f.close()
except:
print 'problem getting cert for '+line
except:
print line,'was a bad url'