blob: a51cfc4982bb8118d586f19a1a06c0ebec20576f [file] [log] [blame]
Jean-Paul Calderone8b63d452008-03-21 18:31:12 -04001# Copyright (C) Jean-Paul Calderone 2008, All rights reserved
2
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -04003"""
4Unit tests for L{OpenSSL.SSL}.
5"""
6
Jean-Paul Calderone52f0d8b2009-03-07 09:10:19 -05007from sys import platform
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -04008from socket import socket
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04009from os import makedirs, symlink
10from os.path import join
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -040011from unittest import main
Jean-Paul Calderone460cc1f2009-03-07 11:31:12 -050012
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -040013from OpenSSL.crypto import TYPE_RSA, FILETYPE_PEM, PKey, dump_privatekey, load_certificate, load_privatekey
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -040014from OpenSSL.SSL import WantReadError, Context, Connection, Error
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -040015from OpenSSL.SSL import SSLv2_METHOD, SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD
Rick Deanb71c0d22009-04-01 14:09:23 -050016from OpenSSL.SSL import OP_NO_SSLv2, OP_NO_SSLv3, OP_SINGLE_DH_USE
17from OpenSSL.SSL import VERIFY_PEER, VERIFY_FAIL_IF_NO_PEER_CERT, VERIFY_CLIENT_ONCE
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -040018from OpenSSL.test.util import TestCase
Jean-Paul Calderone18808652009-07-05 12:54:05 -040019from OpenSSL.test.test_crypto import cleartextCertificatePEM, cleartextPrivateKeyPEM
Jean-Paul Calderone4bccf5e2008-12-28 22:50:42 -050020try:
21 from OpenSSL.SSL import OP_NO_QUERY_MTU
22except ImportError:
23 OP_NO_QUERY_MTU = None
24try:
25 from OpenSSL.SSL import OP_COOKIE_EXCHANGE
26except ImportError:
27 OP_COOKIE_EXCHANGE = None
28try:
29 from OpenSSL.SSL import OP_NO_TICKET
30except ImportError:
31 OP_NO_TICKET = None
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -040032
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -040033
Jean-Paul Calderone18808652009-07-05 12:54:05 -040034class ContextTests(TestCase):
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -040035 """
36 Unit tests for L{OpenSSL.SSL.Context}.
37 """
38 def test_method(self):
39 """
40 L{Context} can be instantiated with one of L{SSLv2_METHOD},
41 L{SSLv3_METHOD}, L{SSLv23_METHOD}, or L{TLSv1_METHOD}.
42 """
43 for meth in [SSLv2_METHOD, SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD]:
44 Context(meth)
45 self.assertRaises(TypeError, Context, "")
46 self.assertRaises(ValueError, Context, 10)
47
48
49 def test_use_privatekey(self):
50 """
51 L{Context.use_privatekey} takes an L{OpenSSL.crypto.PKey} instance.
52 """
53 key = PKey()
54 key.generate_key(TYPE_RSA, 128)
55 ctx = Context(TLSv1_METHOD)
56 ctx.use_privatekey(key)
57 self.assertRaises(TypeError, ctx.use_privatekey, "")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -040058
59
60 def test_set_passwd_cb(self):
61 """
62 L{Context.set_passwd_cb} accepts a callable which will be invoked when
63 a private key is loaded from an encrypted PEM.
64 """
65 key = PKey()
66 key.generate_key(TYPE_RSA, 128)
67 pemFile = self.mktemp()
68 fObj = file(pemFile, 'w')
69 passphrase = "foobar"
70 fObj.write(dump_privatekey(FILETYPE_PEM, key, "blowfish", passphrase))
71 fObj.close()
72
73 calledWith = []
74 def passphraseCallback(maxlen, verify, extra):
75 calledWith.append((maxlen, verify, extra))
76 return passphrase
77 context = Context(TLSv1_METHOD)
78 context.set_passwd_cb(passphraseCallback)
79 context.use_privatekey_file(pemFile)
80 self.assertTrue(len(calledWith), 1)
81 self.assertTrue(isinstance(calledWith[0][0], int))
82 self.assertTrue(isinstance(calledWith[0][1], int))
83 self.assertEqual(calledWith[0][2], None)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -040084
85
86 def test_set_info_callback(self):
87 """
88 L{Context.set_info_callback} accepts a callable which will be invoked
89 when certain information about an SSL connection is available.
90 """
91 port = socket()
92 port.bind(('', 0))
93 port.listen(1)
94
95 client = socket()
96 client.setblocking(False)
97 client.connect_ex(port.getsockname())
98
99 clientSSL = Connection(Context(TLSv1_METHOD), client)
100 clientSSL.set_connect_state()
101
102 called = []
103 def info(conn, where, ret):
104 called.append((conn, where, ret))
105 context = Context(TLSv1_METHOD)
106 context.set_info_callback(info)
107 context.use_certificate(
108 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
109 context.use_privatekey(
110 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
111
112 server, ignored = port.accept()
113 server.setblocking(False)
114
115 serverSSL = Connection(context, server)
116 serverSSL.set_accept_state()
117
118 while not called:
119 for ssl in clientSSL, serverSSL:
120 try:
121 ssl.do_handshake()
122 except WantReadError:
123 pass
124
125 # Kind of lame. Just make sure it got called somehow.
126 self.assertTrue(called)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400127
128
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400129 def _load_verify_locations_test(self, *args):
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400130 port = socket()
131 port.bind(('', 0))
132 port.listen(1)
133
134 client = socket()
135 client.setblocking(False)
136 client.connect_ex(port.getsockname())
137
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400138 clientContext = Context(TLSv1_METHOD)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400139 clientContext.load_verify_locations(*args)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400140 # Require that the server certificate verify properly or the
141 # connection will fail.
142 clientContext.set_verify(
143 VERIFY_PEER,
144 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
145
146 clientSSL = Connection(clientContext, client)
147 clientSSL.set_connect_state()
148
149 server, _ = port.accept()
150 server.setblocking(False)
151
152 serverContext = Context(TLSv1_METHOD)
153 serverContext.use_certificate(
154 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
155 serverContext.use_privatekey(
156 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
157
158 serverSSL = Connection(serverContext, server)
159 serverSSL.set_accept_state()
160
161 for i in range(3):
162 for ssl in clientSSL, serverSSL:
163 try:
164 # Without load_verify_locations above, the handshake
165 # will fail:
166 # Error: [('SSL routines', 'SSL3_GET_SERVER_CERTIFICATE',
167 # 'certificate verify failed')]
168 ssl.do_handshake()
169 except WantReadError:
170 pass
171
172 cert = clientSSL.get_peer_certificate()
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400173 self.assertEqual(cert.get_subject().CN, 'Testing Root CA')
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400174
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400175 def test_load_verify_file(self):
176 """
177 L{Context.load_verify_locations} accepts a file name and uses the
178 certificates within for verification purposes.
179 """
180 cafile = self.mktemp()
181 fObj = file(cafile, 'w')
182 fObj.write(cleartextCertificatePEM)
183 fObj.close()
184
185 self._load_verify_locations_test(cafile)
186
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400187
188 def test_load_verify_invalid_file(self):
189 """
190 L{Context.load_verify_locations} raises L{Error} when passed a
191 non-existent cafile.
192 """
193 clientContext = Context(TLSv1_METHOD)
194 self.assertRaises(
195 Error, clientContext.load_verify_locations, self.mktemp())
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400196
197
198 def test_load_verify_directory(self):
199 """
200 L{Context.load_verify_locations} accepts a directory name and uses
201 the certificates within for verification purposes.
202 """
203 capath = self.mktemp()
204 makedirs(capath)
205 cafile = join(capath, 'cert.pem')
206 fObj = file(cafile, 'w')
207 fObj.write(cleartextCertificatePEM)
208 fObj.close()
209
210 # Hash value computed manually with c_rehash to avoid depending on
211 # c_rehash in the test suite.
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400212 symlink('cert.pem', join(capath, 'c7adac82.0'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400213
214 self._load_verify_locations_test(None, capath)
215
216
217 def test_set_default_verify_paths(self):
218 """
219 L{Context.set_default_verify_paths} causes the platform-specific CA
220 certificate locations to be used for verification purposes.
221 """
222 # Testing this requires a server with a certificate signed by one of
223 # the CAs in the platform CA location. Getting one of those costs
224 # money. Fortunately (or unfortunately, depending on your
225 # perspective), it's easy to think of a public server on the
226 # internet which has such a certificate. Connecting to the network
227 # in a unit test is bad, but it's the only way I can think of to
228 # really test this. -exarkun
229
230 # Arg, verisign.com doesn't speak TLSv1
231 context = Context(SSLv3_METHOD)
232 context.set_default_verify_paths()
233 context.set_verify(
234 VERIFY_PEER,
235 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
236
237 client = socket()
238 client.connect(('verisign.com', 443))
239 clientSSL = Connection(context, client)
240 clientSSL.set_connect_state()
241 clientSSL.do_handshake()
242 clientSSL.send('GET / HTTP/1.0\r\n\r\n')
243 self.assertTrue(clientSSL.recv(1024))
Jean-Paul Calderone52f0d8b2009-03-07 09:10:19 -0500244 if platform == "darwin":
Jean-Paul Calderone1d287e52009-03-07 09:09:07 -0500245 test_set_default_verify_paths.todo = (
246 "set_default_verify_paths appears not to work on OS X - a "
247 "problem with the supplied OpenSSL, perhaps?")
Jean-Paul Calderone9eadb962008-09-07 21:20:44 -0400248
249
250 def test_set_default_verify_paths_signature(self):
251 """
252 L{Context.set_default_verify_paths} takes no arguments and raises
253 L{TypeError} if given any.
254 """
255 context = Context(TLSv1_METHOD)
256 self.assertRaises(TypeError, context.set_default_verify_paths, None)
257 self.assertRaises(TypeError, context.set_default_verify_paths, 1)
258 self.assertRaises(TypeError, context.set_default_verify_paths, "")
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -0500259
260
261
262class ConstantsTests(TestCase):
263 """
264 Tests for the values of constants exposed in L{OpenSSL.SSL}.
265
266 These are values defined by OpenSSL intended only to be used as flags to
267 OpenSSL APIs. The only assertions it seems can be made about them is
268 their values.
269 """
Jean-Paul Calderoned811b682008-12-28 22:59:15 -0500270 # unittest.TestCase has no skip mechanism
271 if OP_NO_QUERY_MTU is not None:
272 def test_op_no_query_mtu(self):
273 """
274 The value of L{OpenSSL.SSL.OP_NO_QUERY_MTU} is 0x1000, the value of
275 I{SSL_OP_NO_QUERY_MTU} defined by I{openssl/ssl.h}.
276 """
277 self.assertEqual(OP_NO_QUERY_MTU, 0x1000)
278 else:
279 "OP_NO_QUERY_MTU unavailable - OpenSSL version may be too old"
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -0500280
281
Jean-Paul Calderoned811b682008-12-28 22:59:15 -0500282 if OP_COOKIE_EXCHANGE is not None:
283 def test_op_cookie_exchange(self):
284 """
285 The value of L{OpenSSL.SSL.OP_COOKIE_EXCHANGE} is 0x2000, the value
286 of I{SSL_OP_COOKIE_EXCHANGE} defined by I{openssl/ssl.h}.
287 """
288 self.assertEqual(OP_COOKIE_EXCHANGE, 0x2000)
289 else:
290 "OP_COOKIE_EXCHANGE unavailable - OpenSSL version may be too old"
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -0500291
292
Jean-Paul Calderoned811b682008-12-28 22:59:15 -0500293 if OP_NO_TICKET is not None:
294 def test_op_no_ticket(self):
295 """
296 The value of L{OpenSSL.SSL.OP_NO_TICKET} is 0x4000, the value of
297 I{SSL_OP_NO_TICKET} defined by I{openssl/ssl.h}.
298 """
299 self.assertEqual(OP_NO_TICKET, 0x4000)
300 else:
301 "OP_NO_TICKET unavailable - OpenSSL version may be too old"
Rick Dean5b7b6372009-04-01 11:34:06 -0500302
303
Jean-Paul Calderoneeeee26a2009-04-27 11:24:30 -0400304
Rick Deanb71c0d22009-04-01 14:09:23 -0500305root_cert_pem = """-----BEGIN CERTIFICATE-----
306MIIC7TCCAlagAwIBAgIIPQzE4MbeufQwDQYJKoZIhvcNAQEFBQAwWDELMAkGA1UE
307BhMCVVMxCzAJBgNVBAgTAklMMRAwDgYDVQQHEwdDaGljYWdvMRAwDgYDVQQKEwdU
308ZXN0aW5nMRgwFgYDVQQDEw9UZXN0aW5nIFJvb3QgQ0EwIhgPMjAwOTAzMjUxMjM2
309NThaGA8yMDE3MDYxMTEyMzY1OFowWDELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAklM
310MRAwDgYDVQQHEwdDaGljYWdvMRAwDgYDVQQKEwdUZXN0aW5nMRgwFgYDVQQDEw9U
311ZXN0aW5nIFJvb3QgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAPmaQumL
312urpE527uSEHdL1pqcDRmWzu+98Y6YHzT/J7KWEamyMCNZ6fRW1JCR782UQ8a07fy
3132xXsKy4WdKaxyG8CcatwmXvpvRQ44dSANMihHELpANTdyVp6DCysED6wkQFurHlF
3141dshEaJw8b/ypDhmbVIo6Ci1xvCJqivbLFnbAgMBAAGjgbswgbgwHQYDVR0OBBYE
315FINVdy1eIfFJDAkk51QJEo3IfgSuMIGIBgNVHSMEgYAwfoAUg1V3LV4h8UkMCSTn
316VAkSjch+BK6hXKRaMFgxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJJTDEQMA4GA1UE
317BxMHQ2hpY2FnbzEQMA4GA1UEChMHVGVzdGluZzEYMBYGA1UEAxMPVGVzdGluZyBS
318b290IENBggg9DMTgxt659DAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GB
319AGGCDazMJGoWNBpc03u6+smc95dEead2KlZXBATOdFT1VesY3+nUOqZhEhTGlDMi
320hkgaZnzoIq/Uamidegk4hirsCT/R+6vsKAAxNTcBjUeZjlykCJWy5ojShGftXIKY
321w/njVbKMXrvc83qmTdGl3TAM0fxQIpqgcglFLveEBgzn
322-----END CERTIFICATE-----
323"""
324
325root_key_pem = """-----BEGIN RSA PRIVATE KEY-----
326MIICXQIBAAKBgQD5mkLpi7q6ROdu7khB3S9aanA0Zls7vvfGOmB80/yeylhGpsjA
327jWen0VtSQke/NlEPGtO38tsV7CsuFnSmschvAnGrcJl76b0UOOHUgDTIoRxC6QDU
3283claegwsrBA+sJEBbqx5RdXbIRGicPG/8qQ4Zm1SKOgotcbwiaor2yxZ2wIDAQAB
329AoGBAPCgMpmLxzwDaUmcFbTJUvlLW1hoxNNYSu2jIZm1k/hRAcE60JYwvBkgz3UB
330yMEh0AtLxYe0bFk6EHah11tMUPgscbCq73snJ++8koUw+csk22G65hOs51bVb7Aa
3316JBe67oLzdtvgCUFAA2qfrKzWRZzAdhUirQUZgySZk+Xq1pBAkEA/kZG0A6roTSM
332BVnx7LnPfsycKUsTumorpXiylZJjTi9XtmzxhrYN6wgZlDOOwOLgSQhszGpxVoMD
333u3gByT1b2QJBAPtL3mSKdvwRu/+40zaZLwvSJRxaj0mcE4BJOS6Oqs/hS1xRlrNk
334PpQ7WJ4yM6ZOLnXzm2mKyxm50Mv64109FtMCQQDOqS2KkjHaLowTGVxwC0DijMfr
335I9Lf8sSQk32J5VWCySWf5gGTfEnpmUa41gKTMJIbqZZLucNuDcOtzUaeWZlZAkA8
336ttXigLnCqR486JDPTi9ZscoZkZ+w7y6e/hH8t6d5Vjt48JVyfjPIaJY+km58LcN3
3376AWSeGAdtRFHVzR7oHjVAkB4hutvxiOeiIVQNBhM6RSI9aBPMI21DoX2JRoxvNW2
338cbvAhow217X9V0dVerEOKxnNYspXRrh36h7k4mQA+sDq
339-----END RSA PRIVATE KEY-----
340"""
341
342server_cert_pem = """-----BEGIN CERTIFICATE-----
343MIICKDCCAZGgAwIBAgIJAJn/HpR21r/8MA0GCSqGSIb3DQEBBQUAMFgxCzAJBgNV
344BAYTAlVTMQswCQYDVQQIEwJJTDEQMA4GA1UEBxMHQ2hpY2FnbzEQMA4GA1UEChMH
345VGVzdGluZzEYMBYGA1UEAxMPVGVzdGluZyBSb290IENBMCIYDzIwMDkwMzI1MTIz
346NzUzWhgPMjAxNzA2MTExMjM3NTNaMBgxFjAUBgNVBAMTDWxvdmVseSBzZXJ2ZXIw
347gZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAL6m+G653V0tpBC/OKl22VxOi2Cv
348lK4TYu9LHSDP9uDVTe7V5D5Tl6qzFoRRx5pfmnkqT5B+W9byp2NU3FC5hLm5zSAr
349b45meUhjEJ/ifkZgbNUjHdBIGP9MAQUHZa5WKdkGIJvGAvs8UzUqlr4TBWQIB24+
350lJ+Ukk/CRgasrYwdAgMBAAGjNjA0MB0GA1UdDgQWBBS4kC7Ij0W1TZXZqXQFAM2e
351gKEG2DATBgNVHSUEDDAKBggrBgEFBQcDATANBgkqhkiG9w0BAQUFAAOBgQBh30Li
352dJ+NlxIOx5343WqIBka3UbsOb2kxWrbkVCrvRapCMLCASO4FqiKWM+L0VDBprqIp
3532mgpFQ6FHpoIENGvJhdEKpptQ5i7KaGhnDNTfdy3x1+h852G99f1iyj0RmbuFcM8
354uzujnS8YXWvM7DM1Ilozk4MzPug8jzFp5uhKCQ==
355-----END CERTIFICATE-----
356"""
357
358server_key_pem = """-----BEGIN RSA PRIVATE KEY-----
359MIICWwIBAAKBgQC+pvhuud1dLaQQvzipdtlcTotgr5SuE2LvSx0gz/bg1U3u1eQ+
360U5eqsxaEUceaX5p5Kk+QflvW8qdjVNxQuYS5uc0gK2+OZnlIYxCf4n5GYGzVIx3Q
361SBj/TAEFB2WuVinZBiCbxgL7PFM1Kpa+EwVkCAduPpSflJJPwkYGrK2MHQIDAQAB
362AoGAbwuZ0AR6JveahBaczjfnSpiFHf+mve2UxoQdpyr6ROJ4zg/PLW5K/KXrC48G
363j6f3tXMrfKHcpEoZrQWUfYBRCUsGD5DCazEhD8zlxEHahIsqpwA0WWssJA2VOLEN
364j6DuV2pCFbw67rfTBkTSo32ahfXxEKev5KswZk0JIzH3ooECQQDgzS9AI89h0gs8
365Dt+1m11Rzqo3vZML7ZIyGApUzVan+a7hbc33nbGRkAXjHaUBJO31it/H6dTO+uwX
366msWwNG5ZAkEA2RyFKs5xR5USTFaKLWCgpH/ydV96KPOpBND7TKQx62snDenFNNbn
367FwwOhpahld+vqhYk+pfuWWUpQciE+Bu7ZQJASjfT4sQv4qbbKK/scePicnDdx9th
3684e1EeB9xwb+tXXXUo/6Bor/AcUNwfiQ6Zt9PZOK9sR3lMZSsP7rMi7kzuQJABie6
3691sXXjFH7nNJvRG4S39cIxq8YRYTy68II/dlB2QzGpKxV/POCxbJ/zu0CU79tuYK7
370NaeNCFfH3aeTrX0LyQJAMBWjWmeKM2G2sCExheeQK0ROnaBC8itCECD4Jsve4nqf
371r50+LF74iLXFwqysVCebPKMOpDWp/qQ1BbJQIPs7/A==
372-----END RSA PRIVATE KEY-----
373"""
374
375client_cert_pem = """-----BEGIN CERTIFICATE-----
376MIICJjCCAY+gAwIBAgIJAKxpFI5lODkjMA0GCSqGSIb3DQEBBQUAMFgxCzAJBgNV
377BAYTAlVTMQswCQYDVQQIEwJJTDEQMA4GA1UEBxMHQ2hpY2FnbzEQMA4GA1UEChMH
378VGVzdGluZzEYMBYGA1UEAxMPVGVzdGluZyBSb290IENBMCIYDzIwMDkwMzI1MTIz
379ODA1WhgPMjAxNzA2MTExMjM4MDVaMBYxFDASBgNVBAMTC3VnbHkgY2xpZW50MIGf
380MA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDAZh/SRtNm5ntMT4qb6YzEpTroMlq2
381rn+GrRHRiZ+xkCw/CGNhbtPir7/QxaUj26BSmQrHw1bGKEbPsWiW7bdXSespl+xK
382iku4G/KvnnmWdeJHqsiXeUZtqurMELcPQAw9xPHEuhqqUJvvEoMTsnCEqGM+7Dtb
383oCRajYyHfluARQIDAQABozYwNDAdBgNVHQ4EFgQUNQB+qkaOaEVecf1J3TTUtAff
3840fAwEwYDVR0lBAwwCgYIKwYBBQUHAwIwDQYJKoZIhvcNAQEFBQADgYEAyv/Jh7gM
385Q3OHvmsFEEvRI+hsW8y66zK4K5de239Y44iZrFYkt7Q5nBPMEWDj4F2hLYWL/qtI
3869Zdr0U4UDCU9SmmGYh4o7R4TZ5pGFvBYvjhHbkSFYFQXZxKUi+WUxplP6I0wr2KJ
387PSTJCjJOn3xo2NTKRgV1gaoTf2EhL+RG8TQ=
388-----END CERTIFICATE-----
389"""
390
391client_key_pem = """-----BEGIN RSA PRIVATE KEY-----
392MIICXgIBAAKBgQDAZh/SRtNm5ntMT4qb6YzEpTroMlq2rn+GrRHRiZ+xkCw/CGNh
393btPir7/QxaUj26BSmQrHw1bGKEbPsWiW7bdXSespl+xKiku4G/KvnnmWdeJHqsiX
394eUZtqurMELcPQAw9xPHEuhqqUJvvEoMTsnCEqGM+7DtboCRajYyHfluARQIDAQAB
395AoGATkZ+NceY5Glqyl4mD06SdcKfV65814vg2EL7V9t8+/mi9rYL8KztSXGlQWPX
396zuHgtRoMl78yQ4ZJYOBVo+nsx8KZNRCEBlE19bamSbQLCeQMenWnpeYyQUZ908gF
397h6L9qsFVJepgA9RDgAjyDoS5CaWCdCCPCH2lDkdcqC54SVUCQQDseuduc4wi8h4t
398V8AahUn9fn9gYfhoNuM0gdguTA0nPLVWz4hy1yJiWYQe0H7NLNNTmCKiLQaJpAbb
399TC6vE8C7AkEA0Ee8CMJUc20BnGEmxwgWcVuqFWaKCo8jTH1X38FlATUsyR3krjW2
400dL3yDD9NwHxsYP7nTKp/U8MV7U9IBn4y/wJBAJl7H0/BcLeRmuJk7IqJ7b635iYB
401D/9beFUw3MUXmQXZUfyYz39xf6CDZsu1GEdEC5haykeln3Of4M9d/4Kj+FcCQQCY
402si6xwT7GzMDkk/ko684AV3KPc/h6G0yGtFIrMg7J3uExpR/VdH2KgwMkZXisSMvw
403JJEQjOMCVsEJlRk54WWjAkEAzoZNH6UhDdBK5F38rVt/y4SEHgbSfJHIAmPS32Kq
404f6GGcfNpip0Uk7q7udTKuX7Q/buZi/C4YW7u3VKAquv9NA==
405-----END RSA PRIVATE KEY-----
406"""
407
408def verify_cb(conn, cert, errnum, depth, ok):
409 return ok
410
Jean-Paul Calderone958299e2009-04-27 12:59:12 -0400411class MemoryBIOTests(TestCase):
Rick Deanb71c0d22009-04-01 14:09:23 -0500412 """
Jean-Paul Calderone958299e2009-04-27 12:59:12 -0400413 Tests for L{OpenSSL.SSL.Connection} using a memory BIO.
Rick Deanb71c0d22009-04-01 14:09:23 -0500414 """
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -0400415 def _server(self):
416 # Create the server side Connection. This is mostly setup boilerplate
417 # - use TLSv1, use a particular certificate, etc.
418 server_ctx = Context(TLSv1_METHOD)
419 server_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE )
420 server_ctx.set_verify(VERIFY_PEER|VERIFY_FAIL_IF_NO_PEER_CERT|VERIFY_CLIENT_ONCE, verify_cb)
421 server_store = server_ctx.get_cert_store()
422 server_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
423 server_ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
424 server_ctx.check_privatekey()
425 server_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
426 # Here the Connection is actually created. None is passed as the 2nd
427 # parameter, indicating a memory BIO should be created.
428 server_conn = Connection(server_ctx, None)
429 server_conn.set_accept_state()
430 return server_conn
431
432
433 def _client(self):
434 # Now create the client side Connection. Similar boilerplate to the above.
435 client_ctx = Context(TLSv1_METHOD)
436 client_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE )
437 client_ctx.set_verify(VERIFY_PEER|VERIFY_FAIL_IF_NO_PEER_CERT|VERIFY_CLIENT_ONCE, verify_cb)
438 client_store = client_ctx.get_cert_store()
439 client_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, client_key_pem))
440 client_ctx.use_certificate(load_certificate(FILETYPE_PEM, client_cert_pem))
441 client_ctx.check_privatekey()
442 client_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
443 # Again, None to create a new memory BIO.
444 client_conn = Connection(client_ctx, None)
445 client_conn.set_connect_state()
446 return client_conn
447
448
Jean-Paul Calderone958299e2009-04-27 12:59:12 -0400449 def _loopback(self, client_conn, server_conn):
450 """
451 Try to read application bytes from each of the two L{Connection}
452 objects. Copy bytes back and forth between their send/receive buffers
453 for as long as there is anything to copy. When there is nothing more
454 to copy, return C{None}. If one of them actually manages to deliver
455 some application bytes, return a two-tuple of the connection from which
456 the bytes were read and the bytes themselves.
457 """
458 wrote = True
459 while wrote:
460 # Loop until neither side has anything to say
461 wrote = False
462
463 # Copy stuff from each side's send buffer to the other side's
464 # receive buffer.
465 for (read, write) in [(client_conn, server_conn),
466 (server_conn, client_conn)]:
467
468 # Give the side a chance to generate some more bytes, or
469 # succeed.
470 try:
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -0400471 bytes = read.recv(2 ** 16)
Jean-Paul Calderone958299e2009-04-27 12:59:12 -0400472 except WantReadError:
473 # It didn't succeed, so we'll hope it generated some
474 # output.
475 pass
476 else:
477 # It did succeed, so we'll stop now and let the caller deal
478 # with it.
479 return (read, bytes)
480
481 while True:
482 # Keep copying as long as there's more stuff there.
483 try:
484 dirty = read.bio_read(4096)
485 except WantReadError:
486 # Okay, nothing more waiting to be sent. Stop
487 # processing this send buffer.
488 break
489 else:
490 # Keep track of the fact that someone generated some
491 # output.
492 wrote = True
493 write.bio_write(dirty)
494
495
Rick Deanb71c0d22009-04-01 14:09:23 -0500496 def test_connect(self):
Jean-Paul Calderone958299e2009-04-27 12:59:12 -0400497 """
498 Two L{Connection}s which use memory BIOs can be manually connected by
499 reading from the output of each and writing those bytes to the input of
500 the other and in this way establish a connection and exchange
501 application-level bytes with each other.
502 """
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -0400503 server_conn = self._server()
504 client_conn = self._client()
Rick Deanb71c0d22009-04-01 14:09:23 -0500505
Jean-Paul Calderone958299e2009-04-27 12:59:12 -0400506 # There should be no key or nonces yet.
507 self.assertIdentical(server_conn.master_key(), None)
508 self.assertIdentical(server_conn.client_random(), None)
509 self.assertIdentical(server_conn.server_random(), None)
Rick Deanb71c0d22009-04-01 14:09:23 -0500510
Jean-Paul Calderone958299e2009-04-27 12:59:12 -0400511 # First, the handshake needs to happen. We'll deliver bytes back and
512 # forth between the client and server until neither of them feels like
513 # speaking any more.
514 self.assertIdentical(self._loopback(client_conn, server_conn), None)
515
516 # Now that the handshake is done, there should be a key and nonces.
517 self.assertNotIdentical(server_conn.master_key(), None)
518 self.assertNotIdentical(server_conn.client_random(), None)
519 self.assertNotIdentical(server_conn.server_random(), None)
Jean-Paul Calderone6c051e62009-07-05 13:50:34 -0400520 self.assertEquals(server_conn.client_random(), client_conn.client_random())
521 self.assertEquals(server_conn.server_random(), client_conn.server_random())
522 self.assertNotEquals(server_conn.client_random(), server_conn.server_random())
523 self.assertNotEquals(client_conn.client_random(), client_conn.server_random())
Jean-Paul Calderone958299e2009-04-27 12:59:12 -0400524
525 # Here are the bytes we'll try to send.
Rick Deanb71c0d22009-04-01 14:09:23 -0500526 important_message = 'One if by land, two if by sea.'
527
Jean-Paul Calderone958299e2009-04-27 12:59:12 -0400528 server_conn.write(important_message)
529 self.assertEquals(
530 self._loopback(client_conn, server_conn),
531 (client_conn, important_message))
532
533 client_conn.write(important_message[::-1])
534 self.assertEquals(
535 self._loopback(client_conn, server_conn),
536 (server_conn, important_message[::-1]))
Rick Deanb71c0d22009-04-01 14:09:23 -0500537
538
Jean-Paul Calderonefc4ed0f2009-04-27 11:51:27 -0400539 def test_socketOverridesMemory(self):
Rick Deanb71c0d22009-04-01 14:09:23 -0500540 """
541 Test that L{OpenSSL.SSL.bio_read} and L{OpenSSL.SSL.bio_write} don't
542 work on L{OpenSSL.SSL.Connection}() that use sockets.
543 """
544 context = Context(SSLv3_METHOD)
545 client = socket()
546 clientSSL = Connection(context, client)
547 self.assertRaises( TypeError, clientSSL.bio_read, 100)
548 self.assertRaises( TypeError, clientSSL.bio_write, "foo")
Jean-Paul Calderone07acf3f2009-05-05 13:23:28 -0400549 self.assertRaises( TypeError, clientSSL.bio_shutdown )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -0400550
551
552 def test_outgoingOverflow(self):
553 """
554 If more bytes than can be written to the memory BIO are passed to
555 L{Connection.send} at once, the number of bytes which were written is
556 returned and that many bytes from the beginning of the input can be
557 read from the other end of the connection.
558 """
559 server = self._server()
560 client = self._client()
561
562 self._loopback(client, server)
563
564 size = 2 ** 15
565 sent = client.send("x" * size)
566 # Sanity check. We're trying to test what happens when the entire
567 # input can't be sent. If the entire input was sent, this test is
568 # meaningless.
569 self.assertTrue(sent < size)
570
571 receiver, received = self._loopback(client, server)
572 self.assertIdentical(receiver, server)
573
574 # We can rely on all of these bytes being received at once because
575 # _loopback passes 2 ** 16 to recv - more than 2 ** 15.
576 self.assertEquals(len(received), sent)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -0400577
578
579 def test_shutdown(self):
580 """
581 L{Connection.bio_shutdown} signals the end of the data stream from
582 which the L{Connection} reads.
583 """
584 server = self._server()
585 server.bio_shutdown()
586 e = self.assertRaises(Error, server.recv, 1024)
587 # We don't want WantReadError or ZeroReturnError or anything - it's a
588 # handshake failure.
589 self.assertEquals(e.__class__, Error)
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -0400590
591
592
593if __name__ == '__main__':
594 main()