Changes to allow us to specify the hostname we want to use for cert creation,
[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):
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 subj.emailAddress = 'root@%s' % subj.CN
57
58 req.set_pubkey(pkey)
59 req.sign(pkey, 'md5')
60 if dest:
61 destfd = os.open(dest, os.O_RDWR|os.O_CREAT, 0644)
62 os.write(destfd, crypto.dump_certificate_request(crypto.FILETYPE_PEM, req))
63 os.close(destfd)
64
65 return req
66
67
68 def retrieve_key_from_file(keyfile):
69 fo = open(keyfile, 'r')
70 buf = fo.read()
71 keypair = crypto.load_privatekey(crypto.FILETYPE_PEM, buf)
72 return keypair
73
74
75 def retrieve_csr_from_file(csrfile):
76 fo = open(csrfile, 'r')
77 buf = fo.read()
78 csrreq = crypto.load_certificate_request(crypto.FILETYPE_PEM, buf)
79 return csrreq
80
81
82 def retrieve_cert_from_file(certfile):
83 fo = open(certfile, 'r')
84 buf = fo.read()
85 cert = crypto.load_certificate(crypto.FILETYPE_PEM, buf)
86 return cert
87
88
89 def create_ca(CN="Certmaster Certificate Authority", ca_key_file=None, ca_cert_file=None):
90 cakey = make_keypair(dest=ca_key_file)
91 careq = make_csr(cakey, cn=CN)
92 cacert = crypto.X509()
93 cacert.set_serial_number(0)
94 cacert.gmtime_adj_notBefore(0)
95 cacert.gmtime_adj_notAfter(60*60*24*365*10) # 10 yrs - hard to beat this kind of cert!
96 cacert.set_issuer(careq.get_subject())
97 cacert.set_subject(careq.get_subject())
98 cacert.set_pubkey(careq.get_pubkey())
99 cacert.sign(cakey, 'md5')
100 if ca_cert_file:
101 destfo = open(ca_cert_file, 'w')
102 destfo.write(crypto.dump_certificate(crypto.FILETYPE_PEM, cacert))
103 destfo.close()
104
105
106 def _get_serial_number(cadir):
107 serial = '%s/serial.txt' % cadir
108 i = 1
109 if os.path.exists(serial):
110 f = open(serial, 'r').read()
111 f = f.replace('\n','')
112 try:
113 i = int(f)
114 i+=1
115 except ValueError, e:
116 i = 1
117
118 _set_serial_number(cadir, i)
119 return i
120
121
122 def _set_serial_number(cadir, last):
123 serial = '%s/serial.txt' % cadir
124 f = open(serial, 'w')
125 f.write(str(last) + '\n')
126 f.close()
127
128
129 def create_slave_certificate(csr, cakey, cacert, cadir, slave_cert_file=None):
130 cert = crypto.X509()
131 cert.set_serial_number(_get_serial_number(cadir))
132 cert.gmtime_adj_notBefore(0)
133 cert.gmtime_adj_notAfter(60*60*24*365*10) # 10 yrs - hard to beat this kind of cert!
134 cert.set_issuer(cacert.get_subject())
135 cert.set_subject(csr.get_subject())
136 cert.set_pubkey(csr.get_pubkey())
137 cert.sign(cakey, 'md5')
138 if slave_cert_file:
139 destfo = open(slave_cert_file, 'w')
140 destfo.write(crypto.dump_certificate(crypto.FILETYPE_PEM, cert))
141 destfo.close()
142 return cert
143
144 def check_cert_key_match(cert, key):
145 if not isinstance(cert, crypto.X509Type):
146 cert = crypto.load_certificate(crypto.FILETYPE_PEM, cert)
147 if not isinstance(key, crypto.PKeyType):
148 key = crypto.load_privatekey(crypto.FILETYPE_PEM, key)
149
150 from OpenSSL import SSL
151 context = SSL.Context(SSL.SSLv3_METHOD)
152 try:
153 context.use_certificate(cert)
154 context.use_privatekey(key)
155 return True
156 except:
157 return False