-
Notifications
You must be signed in to change notification settings - Fork 1
/
main.py
156 lines (115 loc) · 4.47 KB
/
main.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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
__author__ = 'ettore'
import openssl
import os
from bottle import install, route, run, request, response, jinja2_template as template, redirect
from bottle_sqlite import SQLitePlugin
install(SQLitePlugin(dbfile='certificates.db'))
# SPKAC challenge i.e. certificate request challenge
challenge = "Should be a random generated string"
@route('/')
def index(db):
certs = []
# Retrieve certificate serials
res = db.execute('SELECT serial,type,common_name FROM certificates')
row = res.fetchone()
while row:
certs.append(row)
row = res.fetchone()
return template('index', challenge=challenge, certs=certs)
@route('/generate', method='POST')
def generate(db):
type = request.forms.get('type')
email = request.forms.get('email')
dns = request.forms.get('dns')
commonName = request.forms.get('common_name')
organization = request.forms.get('organization')
locality = request.forms.get('locality')
country = request.forms.get('country')
# PEM encoded
spkac = request.forms.get('key')
# Calculate serial
res = db.execute('SELECT COUNT(*) AS count FROM certificates')
certSerial = '{:02d}'.format(int(res.fetchone()['count']) + 1, 'utf-8')
print('Serial: {}'.format(certSerial))
PEMCertificate = openssl.signSPKAC(spkac, type, certSerial, email=email, DNS=dns, CN=commonName, O=organization,
L=locality, C=country)
certFingerprint = openssl.x509Fingerprint(PEMCertificate)
certHash = openssl.x509SubjectHash(PEMCertificate)
# Store into the database
if type == "sslserver":
commonName = dns
elif type == "smime":
commonName = email
db.execute(
'INSERT INTO certificates (serial,fingerprint,subject_hash,type,common_name,certificate)' +
'VALUES(?, ?, ?, ?, ?, ?)', (certSerial, certFingerprint, certHash, type, commonName, PEMCertificate))
# Make the browser install the certificate in DER format
DERCertificate = openssl.PEMtoDER(PEMCertificate)
response.content_type = 'application/x-x509-user-cert'
return DERCertificate
@route('/download/:serial')
def download(serial, db):
# Split serial and extension/format
serial, certFormat = os.path.splitext(serial)
# Strip point
certFormat = certFormat.lstrip('.')
res = db.execute('SELECT * FROM certificates WHERE serial = ?', (serial,))
row = res.fetchone()
PEMCertificate = row['certificate']
# http://pki-tutorial.readthedocs.org/en/latest/mime.html
if certFormat == "pem":
# Set MIME header
response.content_type = 'application/x-pem-file'
return PEMCertificate
elif certFormat == "cer":
DERCertificate = openssl.PEMtoDER(PEMCertificate)
# Set MIME header
response.content_type = 'application/pkix-cert'
return DERCertificate
elif certFormat == "p7c":
PKCS7Certificate = openssl.PEMtoPKCS7(PEMCertificate)
# Set MIME header
response.content_type = 'application/pkcs7-mime'
return PKCS7Certificate
elif certFormat == "p12":
PKCS12Certificate = openssl.PEMtoPKCS12(PEMCertificate)
# Set MIME header
response.content_type = 'application/x-pkcs12'
return PKCS12Certificate
else:
raise Exception('Unknown certificate type {}'.format(certFormat))
@route('/pyki.crl')
def showCRL():
crl = ''
try:
crl = openssl.generateCRL()
except BaseException as e:
print(e)
# http://www.rfc-editor.org/rfc/rfc2585.txt
response.content_type = 'application/pkix-crl'
return crl
@route('/clear')
def clearCA(db):
try:
if os.path.exists('conf/CA/index.txt.attr'):
os.remove('conf/CA/index.txt.attr')
if os.path.exists('conf/CA/index.txt.attr.old'):
os.remove('conf/CA/index.txt.attr.old')
if os.path.exists('conf/CA/index.txt.old'):
os.remove('conf/CA/index.txt.old')
if os.path.exists('conf/CA/serial.old'):
os.remove('conf/CA/serial.old')
for cert in os.listdir('conf/CA/newcerts'):
if not cert.endswith('.pem'):
continue
os.remove('conf/CA/newcerts/{}'.format(cert))
except FileNotFoundError as e:
print(e)
# Clear index file
indexFile = open('conf/CA/index.txt', 'w')
indexFile.write('')
indexFile.close()
# Clear database
db.execute('DELETE FROM certificates')
return 'Done'
run(host='localhost', port='8080', debug=True)