Adding unknown ca tests
[certmaster.git] / certmaster / certs.py
1 # This program is free software; you can redistribute it and/or modify
2 # it under the terms of the GNU General Public License as published by
3 # the Free Software Foundation; either version 2 of the License, or
4 # (at your option) any later version.
5 #
6 # This program is distributed in the hope that it will be useful,
7 # but WITHOUT ANY WARRANTY; without even the implied warranty of
8 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 # GNU Library General Public License for more details.
10 #
11 # You should have received a copy of the GNU General Public License
12 # along with this program; if not, write to the Free Software
13 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
14 # Copyright (c) 2007 Red Hat, inc
15 #- Written by Seth Vidal skvidal @ fedoraproject.org
16
17 from OpenSSL import crypto
18 import socket
19 import os
20 import utils
21
22 def_country = 'UN'
23 def_state = 'FC'
24 def_local = 'Certmaster-town'
25 def_org = 'certmaster'
26 def_ou = 'slave-key'
27
28
29 def make_keypair(dest=None):
30 pkey = crypto.PKey()
31 pkey.generate_key(crypto.TYPE_RSA, 2048)
32 if dest:
33 destfd = os.open(dest, os.O_RDWR|os.O_CREAT, 0600)
34 os.write(destfd, (crypto.dump_privatekey(crypto.FILETYPE_PEM, pkey)))
35 os.close(destfd)
36
37 return pkey
38
39
40 def make_csr(pkey, dest=None, cn=None, hostname=None, emailaddr=None):
41 req = crypto.X509Req()
42 req.get_subject()
43 subj = req.get_subject()
44 subj.C = def_country
45 subj.ST = def_state
46 subj.L = def_local
47 subj.O = def_org
48 subj.OU = def_ou
49 if cn:
50 subj.CN = cn
51 elif hostname:
52 subj.CN = hostname
53 else:
54 subj.CN = utils.gethostname()
55
56 if emailaddr:
57 subj.emailAddress = emailaddr
58 else:
59 subj.emailAddress = 'root@%s' % subj.CN
60
61 req.set_pubkey(pkey)
62 req.sign(pkey, 'md5')
63 if dest:
64 destfd = os.open(dest, os.O_RDWR|os.O_CREAT, 0644)
65 os.write(destfd, crypto.dump_certificate_request(crypto.FILETYPE_PEM, req))
66 os.close(destfd)
67
68 return req
69
70
71 def retrieve_key_from_file(keyfile):
72 fo = open(keyfile, 'r')
73 buf = fo.read()
74 keypair = crypto.load_privatekey(crypto.FILETYPE_PEM, buf)
75 return keypair
76
77
78 def retrieve_csr_from_file(csrfile):
79 fo = open(csrfile, 'r')
80 buf = fo.read()
81 csrreq = crypto.load_certificate_request(crypto.FILETYPE_PEM, buf)
82 return csrreq
83
84
85 def retrieve_cert_from_file(certfile):
86 fo = open(certfile, 'r')
87 buf = fo.read()
88 cert = crypto.load_certificate(crypto.FILETYPE_PEM, buf)
89 return cert
90
91
92 def create_ca(CN="Certmaster Certificate Authority", ca_key_file=None, ca_cert_file=None):
93 cakey = make_keypair(dest=ca_key_file)
94 careq = make_csr(cakey, cn=CN)
95 cacert = crypto.X509()
96 cacert.set_serial_number(0)
97 cacert.gmtime_adj_notBefore(0)
98 cacert.gmtime_adj_notAfter(60*60*24*365*10) # 10 yrs - hard to beat this kind of cert!
99 cacert.set_issuer(careq.get_subject())
100 cacert.set_subject(careq.get_subject())
101 cacert.set_pubkey(careq.get_pubkey())
102 cacert.set_version(2)
103 xt = crypto.X509Extension('basicConstraints',1,'CA:TRUE')
104 # FIXME - add subjectkeyidentifier and authoritykeyidentifier extensions, too)
105 cacert.add_extensions((xt,))
106 cacert.sign(cakey, 'sha1')
107 if ca_cert_file:
108 destfo = open(ca_cert_file, 'w')
109 destfo.write(crypto.dump_certificate(crypto.FILETYPE_PEM, cacert))
110 destfo.close()
111
112
113 def _get_serial_number(cadir):
114 serial = '%s/serial.txt' % cadir
115 i = 1
116 if os.path.exists(serial):
117 f = open(serial, 'r').read()
118 f = f.replace('\n','')
119 try:
120 i = int(f)
121 i+=1
122 except ValueError, e:
123 i = 1
124
125 _set_serial_number(cadir, i)
126 return i
127
128
129 def _set_serial_number(cadir, last):
130 serial = '%s/serial.txt' % cadir
131 f = open(serial, 'w')
132 f.write(str(last) + '\n')
133 f.close()
134
135
136 def create_slave_certificate(csr, cakey, cacert, cadir, slave_cert_file=None):
137 cert = crypto.X509()
138 cert.set_serial_number(_get_serial_number(cadir))
139 cert.gmtime_adj_notBefore(0)
140 cert.gmtime_adj_notAfter(60*60*24*365*10) # 10 yrs - hard to beat this kind of cert!
141 cert.set_issuer(cacert.get_subject())
142 cert.set_subject(csr.get_subject())
143 cert.set_pubkey(csr.get_pubkey())
144 cert.set_version(2)
145 xt = crypto.X509Extension('basicConstraints', False ,'CA:FALSE')
146 # FIXME - add subjectkeyidentifier and authoritykeyidentifier extensions, too)
147 cert.add_extensions((xt,))
148 cert.sign(cakey, 'sha1')
149 if slave_cert_file:
150 destfo = open(slave_cert_file, 'w')
151 destfo.write(crypto.dump_certificate(crypto.FILETYPE_PEM, cert))
152 destfo.close()
153 return cert
154
155 def check_cert_key_match(cert, key):
156 if not isinstance(cert, crypto.X509Type):
157 cert = crypto.load_certificate(crypto.FILETYPE_PEM, cert)
158 if not isinstance(key, crypto.PKeyType):
159 key = crypto.load_privatekey(crypto.FILETYPE_PEM, key)
160
161 from OpenSSL import SSL
162 context = SSL.Context(SSL.SSLv3_METHOD)
163 try:
164 context.use_certificate(cert)
165 context.use_privatekey(key)
166 return True
167 except:
168 return False