5
(c) by Michael Stroeder <michael@stroeder.com>
7
CGI-BIN for revoking client certificates
11
- Name of CA in openssl.cnf (section [ca] of openssl.cnf)
13
- Serial number of certificate to revoke
14
max. 8 digits hexadecimal (32 Bit)
17
ns-revoke.py/Persona?01
18
revokes client certificate with serial 0x01 of CA "Persona"
20
The following checks are made to avoid denial of service attacks:
21
- The client software must provide the client certificate.
22
- The issuer of the client and the server certificates must match
27
import sys, os, string, re, pycacnf, htmlbase, openssl, cgissl, certhelper
29
from pycacnf import opensslcnf, pyca_section
31
# Wir lesen rein gar nix von Standardeingabe => gleich dicht machen
34
# Path to openssl executable
35
openssl.bin_filename = pyca_section.get('OpenSSLExec','/usr/bin/openssl')
37
# Ein paar Umgebungsvariablen auslesen, welche der Apache liefert
38
request_method = os.environ.get('REQUEST_METHOD','')
39
query_string = os.environ.get('QUERY_STRING','')
40
script_name = os.environ.get('SCRIPT_NAME','')
41
path_info = os.environ.get('PATH_INFO','')[1:]
43
rm = (re.compile('[0-9a-fA-F]+(&yes)*')).match(query_string)
45
# Hier die ueblichen Paranoid-Pruefungen der Parameter
46
if request_method!='GET':
47
# Skript nicht mit GET aufgerufen
48
htmlbase.PrintErrorMsg('Wrong method.')
51
# Angabe der CA pruefen
52
ca_name = os.environ.get('PATH_INFO','')[1:]
55
htmlbase.PrintErrorMsg('No certificate authority.')
59
if not opensslcnf.data['ca'].has_key(ca_name):
60
# CA-Definition nicht in openssl-Konfiguration enthalten
61
htmlbase.PrintErrorMsg('Unknown certificate authority "%s".' % ca_name)
64
ca = opensslcnf.getcadata(ca_name)
66
# Abruf eines Zertifikates mittels Seriennummer
68
serial,yes = string.split(query_string,'_')
72
serialnumber=string.atoi(serial,16)
74
ca_db = openssl.db.OpenSSLcaDatabaseClass(ca.database)
75
entry = ca_db.GetEntrybySerial(serialnumber)
77
# Kein entsprechender Eintrag gefunden
79
htmlbase.PrintErrorMsg('Certificate not found.')
82
# Zertifikat ist ungueltig
83
if entry[openssl.db.DB_type]!=openssl.db.DB_TYPE_VAL:
84
htmlbase.PrintErrorMsg('Certificate invalid.')
87
certfilename = os.path.join(ca.certs,'%s.pem' % (entry[openssl.db.DB_serial]))
89
# Does the certificate file exist?
90
if not os.path.isfile(certfilename):
91
htmlbase.PrintErrorMsg('Certificate file not found.')
94
# Kein Zertifikat mit angegebener Nummer gefunden
96
htmlbase.PrintErrorMsg('Certificate not found.')
99
if entry[openssl.db.DB_type]!=openssl.db.DB_TYPE_VAL:
100
htmlbase.PrintErrorMsg('Certificate invalid.')
103
ssl_env = cgissl.GetAllSSLEnviron()
105
if not ssl_env.has_key('SSL_CLIENT_S_DN'):
106
htmlbase.PrintErrorMsg('No client certificate present.')
109
cacert = openssl.cert.X509CertificateClass(ca.certificate)
111
#if ssl_env['SSL_CLIENT_I_DN']!=ssl_env['SSL_SERVER_I_DN']:
112
# htmlbase.PrintErrorMsg('Wrong issuer of client certificate.')
115
if ssl_env['SSL_CLIENT_S_DN']!=entry[openssl.db.DB_name]:
116
htmlbase.PrintErrorMsg('Wrong client certificate.')
119
cert = openssl.cert.X509CertificateClass(certfilename)
121
if query_string[-4:]!='_yes':
122
htmlbase.PrintHeader('Confirmation of certificate revocation.')
123
print """The following certificate will be revoked:
125
Are you really sure that you want to revoke your certificate?
126
The following reasons can make revoking necessary:
128
<LI>Your private key was compromised (stolen, the password was sniffed etc.)</LI>
129
<LI>The content of the certificate attributes has become wrong.</LI>
131
<A HREF="%s/%s?%s_yes">YES</A>
132
""" % (cert.htmlprint(),script_name,ca_name,serialnumber)
133
htmlbase.PrintFooter()
136
ca_db.Revoke(serialnumber)
137
htmlbase.PrintHeader('Revoked certificate.')
138
print 'The following certificate was revoked by you: %s' % (cert.htmlprint())