blob: e3dcecc57214ef68f05d87f10bda0eba06a212cb [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
Rick Deanb1ccd562009-07-09 23:52:39 -050034def socket_pair():
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -040035 """
36 Establish and return a pair of network sockets connected
37 to each other.
38 """
39 # Connect a pair of sockets
Rick Deanb1ccd562009-07-09 23:52:39 -050040 port = socket()
41 port.bind(('', 0))
42 port.listen(1)
43 client = socket()
44 client.setblocking(False)
45 client.connect_ex(port.getsockname())
46 server = port.accept()[0]
47 server.setblocking(False)
48
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -040049 # Let's pass some unencrypted data to make sure our socket connection is
50 # fine. Just one byte, so we don't have to worry about buffers getting
51 # filled up or fragmentation.
52 server.send("x")
53 assert client.recv(1024) == "x"
54 client.send("y")
55 assert server.recv(1024) == "y"
Rick Deanb1ccd562009-07-09 23:52:39 -050056
57 return (server, client)
58
59
Jean-Paul Calderone18808652009-07-05 12:54:05 -040060class ContextTests(TestCase):
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -040061 """
62 Unit tests for L{OpenSSL.SSL.Context}.
63 """
64 def test_method(self):
65 """
66 L{Context} can be instantiated with one of L{SSLv2_METHOD},
67 L{SSLv3_METHOD}, L{SSLv23_METHOD}, or L{TLSv1_METHOD}.
68 """
69 for meth in [SSLv2_METHOD, SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD]:
70 Context(meth)
71 self.assertRaises(TypeError, Context, "")
72 self.assertRaises(ValueError, Context, 10)
73
74
75 def test_use_privatekey(self):
76 """
77 L{Context.use_privatekey} takes an L{OpenSSL.crypto.PKey} instance.
78 """
79 key = PKey()
80 key.generate_key(TYPE_RSA, 128)
81 ctx = Context(TLSv1_METHOD)
82 ctx.use_privatekey(key)
83 self.assertRaises(TypeError, ctx.use_privatekey, "")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -040084
85
86 def test_set_passwd_cb(self):
87 """
88 L{Context.set_passwd_cb} accepts a callable which will be invoked when
89 a private key is loaded from an encrypted PEM.
90 """
91 key = PKey()
92 key.generate_key(TYPE_RSA, 128)
93 pemFile = self.mktemp()
94 fObj = file(pemFile, 'w')
95 passphrase = "foobar"
96 fObj.write(dump_privatekey(FILETYPE_PEM, key, "blowfish", passphrase))
97 fObj.close()
98
99 calledWith = []
100 def passphraseCallback(maxlen, verify, extra):
101 calledWith.append((maxlen, verify, extra))
102 return passphrase
103 context = Context(TLSv1_METHOD)
104 context.set_passwd_cb(passphraseCallback)
105 context.use_privatekey_file(pemFile)
106 self.assertTrue(len(calledWith), 1)
107 self.assertTrue(isinstance(calledWith[0][0], int))
108 self.assertTrue(isinstance(calledWith[0][1], int))
109 self.assertEqual(calledWith[0][2], None)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400110
111
112 def test_set_info_callback(self):
113 """
114 L{Context.set_info_callback} accepts a callable which will be invoked
115 when certain information about an SSL connection is available.
116 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500117 (server, client) = socket_pair()
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400118
119 clientSSL = Connection(Context(TLSv1_METHOD), client)
120 clientSSL.set_connect_state()
121
122 called = []
123 def info(conn, where, ret):
124 called.append((conn, where, ret))
125 context = Context(TLSv1_METHOD)
126 context.set_info_callback(info)
127 context.use_certificate(
128 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
129 context.use_privatekey(
130 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
131
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400132 serverSSL = Connection(context, server)
133 serverSSL.set_accept_state()
134
135 while not called:
136 for ssl in clientSSL, serverSSL:
137 try:
138 ssl.do_handshake()
139 except WantReadError:
140 pass
141
142 # Kind of lame. Just make sure it got called somehow.
143 self.assertTrue(called)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400144
145
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400146 def _load_verify_locations_test(self, *args):
Rick Deanb1ccd562009-07-09 23:52:39 -0500147 (server, client) = socket_pair()
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400148
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400149 clientContext = Context(TLSv1_METHOD)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400150 clientContext.load_verify_locations(*args)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400151 # Require that the server certificate verify properly or the
152 # connection will fail.
153 clientContext.set_verify(
154 VERIFY_PEER,
155 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
156
157 clientSSL = Connection(clientContext, client)
158 clientSSL.set_connect_state()
159
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400160 serverContext = Context(TLSv1_METHOD)
161 serverContext.use_certificate(
162 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
163 serverContext.use_privatekey(
164 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
165
166 serverSSL = Connection(serverContext, server)
167 serverSSL.set_accept_state()
168
169 for i in range(3):
170 for ssl in clientSSL, serverSSL:
171 try:
172 # Without load_verify_locations above, the handshake
173 # will fail:
174 # Error: [('SSL routines', 'SSL3_GET_SERVER_CERTIFICATE',
175 # 'certificate verify failed')]
176 ssl.do_handshake()
177 except WantReadError:
178 pass
179
180 cert = clientSSL.get_peer_certificate()
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400181 self.assertEqual(cert.get_subject().CN, 'Testing Root CA')
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400182
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400183 def test_load_verify_file(self):
184 """
185 L{Context.load_verify_locations} accepts a file name and uses the
186 certificates within for verification purposes.
187 """
188 cafile = self.mktemp()
189 fObj = file(cafile, 'w')
190 fObj.write(cleartextCertificatePEM)
191 fObj.close()
192
193 self._load_verify_locations_test(cafile)
194
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400195
196 def test_load_verify_invalid_file(self):
197 """
198 L{Context.load_verify_locations} raises L{Error} when passed a
199 non-existent cafile.
200 """
201 clientContext = Context(TLSv1_METHOD)
202 self.assertRaises(
203 Error, clientContext.load_verify_locations, self.mktemp())
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400204
205
206 def test_load_verify_directory(self):
207 """
208 L{Context.load_verify_locations} accepts a directory name and uses
209 the certificates within for verification purposes.
210 """
211 capath = self.mktemp()
212 makedirs(capath)
213 cafile = join(capath, 'cert.pem')
214 fObj = file(cafile, 'w')
215 fObj.write(cleartextCertificatePEM)
216 fObj.close()
217
218 # Hash value computed manually with c_rehash to avoid depending on
219 # c_rehash in the test suite.
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400220 symlink('cert.pem', join(capath, 'c7adac82.0'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400221
222 self._load_verify_locations_test(None, capath)
223
224
225 def test_set_default_verify_paths(self):
226 """
227 L{Context.set_default_verify_paths} causes the platform-specific CA
228 certificate locations to be used for verification purposes.
229 """
230 # Testing this requires a server with a certificate signed by one of
231 # the CAs in the platform CA location. Getting one of those costs
232 # money. Fortunately (or unfortunately, depending on your
233 # perspective), it's easy to think of a public server on the
234 # internet which has such a certificate. Connecting to the network
235 # in a unit test is bad, but it's the only way I can think of to
236 # really test this. -exarkun
237
238 # Arg, verisign.com doesn't speak TLSv1
239 context = Context(SSLv3_METHOD)
240 context.set_default_verify_paths()
241 context.set_verify(
242 VERIFY_PEER,
243 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
244
245 client = socket()
246 client.connect(('verisign.com', 443))
247 clientSSL = Connection(context, client)
248 clientSSL.set_connect_state()
249 clientSSL.do_handshake()
250 clientSSL.send('GET / HTTP/1.0\r\n\r\n')
251 self.assertTrue(clientSSL.recv(1024))
Jean-Paul Calderone52f0d8b2009-03-07 09:10:19 -0500252 if platform == "darwin":
Jean-Paul Calderone1d287e52009-03-07 09:09:07 -0500253 test_set_default_verify_paths.todo = (
254 "set_default_verify_paths appears not to work on OS X - a "
255 "problem with the supplied OpenSSL, perhaps?")
Jean-Paul Calderone9eadb962008-09-07 21:20:44 -0400256
257
258 def test_set_default_verify_paths_signature(self):
259 """
260 L{Context.set_default_verify_paths} takes no arguments and raises
261 L{TypeError} if given any.
262 """
263 context = Context(TLSv1_METHOD)
264 self.assertRaises(TypeError, context.set_default_verify_paths, None)
265 self.assertRaises(TypeError, context.set_default_verify_paths, 1)
266 self.assertRaises(TypeError, context.set_default_verify_paths, "")
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -0500267
268
269
270class ConstantsTests(TestCase):
271 """
272 Tests for the values of constants exposed in L{OpenSSL.SSL}.
273
274 These are values defined by OpenSSL intended only to be used as flags to
275 OpenSSL APIs. The only assertions it seems can be made about them is
276 their values.
277 """
Jean-Paul Calderoned811b682008-12-28 22:59:15 -0500278 # unittest.TestCase has no skip mechanism
279 if OP_NO_QUERY_MTU is not None:
280 def test_op_no_query_mtu(self):
281 """
282 The value of L{OpenSSL.SSL.OP_NO_QUERY_MTU} is 0x1000, the value of
283 I{SSL_OP_NO_QUERY_MTU} defined by I{openssl/ssl.h}.
284 """
285 self.assertEqual(OP_NO_QUERY_MTU, 0x1000)
286 else:
287 "OP_NO_QUERY_MTU unavailable - OpenSSL version may be too old"
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -0500288
289
Jean-Paul Calderoned811b682008-12-28 22:59:15 -0500290 if OP_COOKIE_EXCHANGE is not None:
291 def test_op_cookie_exchange(self):
292 """
293 The value of L{OpenSSL.SSL.OP_COOKIE_EXCHANGE} is 0x2000, the value
294 of I{SSL_OP_COOKIE_EXCHANGE} defined by I{openssl/ssl.h}.
295 """
296 self.assertEqual(OP_COOKIE_EXCHANGE, 0x2000)
297 else:
298 "OP_COOKIE_EXCHANGE unavailable - OpenSSL version may be too old"
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -0500299
300
Jean-Paul Calderoned811b682008-12-28 22:59:15 -0500301 if OP_NO_TICKET is not None:
302 def test_op_no_ticket(self):
303 """
304 The value of L{OpenSSL.SSL.OP_NO_TICKET} is 0x4000, the value of
305 I{SSL_OP_NO_TICKET} defined by I{openssl/ssl.h}.
306 """
307 self.assertEqual(OP_NO_TICKET, 0x4000)
308 else:
309 "OP_NO_TICKET unavailable - OpenSSL version may be too old"
Rick Dean5b7b6372009-04-01 11:34:06 -0500310
311
Jean-Paul Calderoneeeee26a2009-04-27 11:24:30 -0400312
Rick Deanb71c0d22009-04-01 14:09:23 -0500313root_cert_pem = """-----BEGIN CERTIFICATE-----
314MIIC7TCCAlagAwIBAgIIPQzE4MbeufQwDQYJKoZIhvcNAQEFBQAwWDELMAkGA1UE
315BhMCVVMxCzAJBgNVBAgTAklMMRAwDgYDVQQHEwdDaGljYWdvMRAwDgYDVQQKEwdU
316ZXN0aW5nMRgwFgYDVQQDEw9UZXN0aW5nIFJvb3QgQ0EwIhgPMjAwOTAzMjUxMjM2
317NThaGA8yMDE3MDYxMTEyMzY1OFowWDELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAklM
318MRAwDgYDVQQHEwdDaGljYWdvMRAwDgYDVQQKEwdUZXN0aW5nMRgwFgYDVQQDEw9U
319ZXN0aW5nIFJvb3QgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAPmaQumL
320urpE527uSEHdL1pqcDRmWzu+98Y6YHzT/J7KWEamyMCNZ6fRW1JCR782UQ8a07fy
3212xXsKy4WdKaxyG8CcatwmXvpvRQ44dSANMihHELpANTdyVp6DCysED6wkQFurHlF
3221dshEaJw8b/ypDhmbVIo6Ci1xvCJqivbLFnbAgMBAAGjgbswgbgwHQYDVR0OBBYE
323FINVdy1eIfFJDAkk51QJEo3IfgSuMIGIBgNVHSMEgYAwfoAUg1V3LV4h8UkMCSTn
324VAkSjch+BK6hXKRaMFgxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJJTDEQMA4GA1UE
325BxMHQ2hpY2FnbzEQMA4GA1UEChMHVGVzdGluZzEYMBYGA1UEAxMPVGVzdGluZyBS
326b290IENBggg9DMTgxt659DAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GB
327AGGCDazMJGoWNBpc03u6+smc95dEead2KlZXBATOdFT1VesY3+nUOqZhEhTGlDMi
328hkgaZnzoIq/Uamidegk4hirsCT/R+6vsKAAxNTcBjUeZjlykCJWy5ojShGftXIKY
329w/njVbKMXrvc83qmTdGl3TAM0fxQIpqgcglFLveEBgzn
330-----END CERTIFICATE-----
331"""
332
333root_key_pem = """-----BEGIN RSA PRIVATE KEY-----
334MIICXQIBAAKBgQD5mkLpi7q6ROdu7khB3S9aanA0Zls7vvfGOmB80/yeylhGpsjA
335jWen0VtSQke/NlEPGtO38tsV7CsuFnSmschvAnGrcJl76b0UOOHUgDTIoRxC6QDU
3363claegwsrBA+sJEBbqx5RdXbIRGicPG/8qQ4Zm1SKOgotcbwiaor2yxZ2wIDAQAB
337AoGBAPCgMpmLxzwDaUmcFbTJUvlLW1hoxNNYSu2jIZm1k/hRAcE60JYwvBkgz3UB
338yMEh0AtLxYe0bFk6EHah11tMUPgscbCq73snJ++8koUw+csk22G65hOs51bVb7Aa
3396JBe67oLzdtvgCUFAA2qfrKzWRZzAdhUirQUZgySZk+Xq1pBAkEA/kZG0A6roTSM
340BVnx7LnPfsycKUsTumorpXiylZJjTi9XtmzxhrYN6wgZlDOOwOLgSQhszGpxVoMD
341u3gByT1b2QJBAPtL3mSKdvwRu/+40zaZLwvSJRxaj0mcE4BJOS6Oqs/hS1xRlrNk
342PpQ7WJ4yM6ZOLnXzm2mKyxm50Mv64109FtMCQQDOqS2KkjHaLowTGVxwC0DijMfr
343I9Lf8sSQk32J5VWCySWf5gGTfEnpmUa41gKTMJIbqZZLucNuDcOtzUaeWZlZAkA8
344ttXigLnCqR486JDPTi9ZscoZkZ+w7y6e/hH8t6d5Vjt48JVyfjPIaJY+km58LcN3
3456AWSeGAdtRFHVzR7oHjVAkB4hutvxiOeiIVQNBhM6RSI9aBPMI21DoX2JRoxvNW2
346cbvAhow217X9V0dVerEOKxnNYspXRrh36h7k4mQA+sDq
347-----END RSA PRIVATE KEY-----
348"""
349
350server_cert_pem = """-----BEGIN CERTIFICATE-----
351MIICKDCCAZGgAwIBAgIJAJn/HpR21r/8MA0GCSqGSIb3DQEBBQUAMFgxCzAJBgNV
352BAYTAlVTMQswCQYDVQQIEwJJTDEQMA4GA1UEBxMHQ2hpY2FnbzEQMA4GA1UEChMH
353VGVzdGluZzEYMBYGA1UEAxMPVGVzdGluZyBSb290IENBMCIYDzIwMDkwMzI1MTIz
354NzUzWhgPMjAxNzA2MTExMjM3NTNaMBgxFjAUBgNVBAMTDWxvdmVseSBzZXJ2ZXIw
355gZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAL6m+G653V0tpBC/OKl22VxOi2Cv
356lK4TYu9LHSDP9uDVTe7V5D5Tl6qzFoRRx5pfmnkqT5B+W9byp2NU3FC5hLm5zSAr
357b45meUhjEJ/ifkZgbNUjHdBIGP9MAQUHZa5WKdkGIJvGAvs8UzUqlr4TBWQIB24+
358lJ+Ukk/CRgasrYwdAgMBAAGjNjA0MB0GA1UdDgQWBBS4kC7Ij0W1TZXZqXQFAM2e
359gKEG2DATBgNVHSUEDDAKBggrBgEFBQcDATANBgkqhkiG9w0BAQUFAAOBgQBh30Li
360dJ+NlxIOx5343WqIBka3UbsOb2kxWrbkVCrvRapCMLCASO4FqiKWM+L0VDBprqIp
3612mgpFQ6FHpoIENGvJhdEKpptQ5i7KaGhnDNTfdy3x1+h852G99f1iyj0RmbuFcM8
362uzujnS8YXWvM7DM1Ilozk4MzPug8jzFp5uhKCQ==
363-----END CERTIFICATE-----
364"""
365
366server_key_pem = """-----BEGIN RSA PRIVATE KEY-----
367MIICWwIBAAKBgQC+pvhuud1dLaQQvzipdtlcTotgr5SuE2LvSx0gz/bg1U3u1eQ+
368U5eqsxaEUceaX5p5Kk+QflvW8qdjVNxQuYS5uc0gK2+OZnlIYxCf4n5GYGzVIx3Q
369SBj/TAEFB2WuVinZBiCbxgL7PFM1Kpa+EwVkCAduPpSflJJPwkYGrK2MHQIDAQAB
370AoGAbwuZ0AR6JveahBaczjfnSpiFHf+mve2UxoQdpyr6ROJ4zg/PLW5K/KXrC48G
371j6f3tXMrfKHcpEoZrQWUfYBRCUsGD5DCazEhD8zlxEHahIsqpwA0WWssJA2VOLEN
372j6DuV2pCFbw67rfTBkTSo32ahfXxEKev5KswZk0JIzH3ooECQQDgzS9AI89h0gs8
373Dt+1m11Rzqo3vZML7ZIyGApUzVan+a7hbc33nbGRkAXjHaUBJO31it/H6dTO+uwX
374msWwNG5ZAkEA2RyFKs5xR5USTFaKLWCgpH/ydV96KPOpBND7TKQx62snDenFNNbn
375FwwOhpahld+vqhYk+pfuWWUpQciE+Bu7ZQJASjfT4sQv4qbbKK/scePicnDdx9th
3764e1EeB9xwb+tXXXUo/6Bor/AcUNwfiQ6Zt9PZOK9sR3lMZSsP7rMi7kzuQJABie6
3771sXXjFH7nNJvRG4S39cIxq8YRYTy68II/dlB2QzGpKxV/POCxbJ/zu0CU79tuYK7
378NaeNCFfH3aeTrX0LyQJAMBWjWmeKM2G2sCExheeQK0ROnaBC8itCECD4Jsve4nqf
379r50+LF74iLXFwqysVCebPKMOpDWp/qQ1BbJQIPs7/A==
380-----END RSA PRIVATE KEY-----
381"""
382
383client_cert_pem = """-----BEGIN CERTIFICATE-----
384MIICJjCCAY+gAwIBAgIJAKxpFI5lODkjMA0GCSqGSIb3DQEBBQUAMFgxCzAJBgNV
385BAYTAlVTMQswCQYDVQQIEwJJTDEQMA4GA1UEBxMHQ2hpY2FnbzEQMA4GA1UEChMH
386VGVzdGluZzEYMBYGA1UEAxMPVGVzdGluZyBSb290IENBMCIYDzIwMDkwMzI1MTIz
387ODA1WhgPMjAxNzA2MTExMjM4MDVaMBYxFDASBgNVBAMTC3VnbHkgY2xpZW50MIGf
388MA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDAZh/SRtNm5ntMT4qb6YzEpTroMlq2
389rn+GrRHRiZ+xkCw/CGNhbtPir7/QxaUj26BSmQrHw1bGKEbPsWiW7bdXSespl+xK
390iku4G/KvnnmWdeJHqsiXeUZtqurMELcPQAw9xPHEuhqqUJvvEoMTsnCEqGM+7Dtb
391oCRajYyHfluARQIDAQABozYwNDAdBgNVHQ4EFgQUNQB+qkaOaEVecf1J3TTUtAff
3920fAwEwYDVR0lBAwwCgYIKwYBBQUHAwIwDQYJKoZIhvcNAQEFBQADgYEAyv/Jh7gM
393Q3OHvmsFEEvRI+hsW8y66zK4K5de239Y44iZrFYkt7Q5nBPMEWDj4F2hLYWL/qtI
3949Zdr0U4UDCU9SmmGYh4o7R4TZ5pGFvBYvjhHbkSFYFQXZxKUi+WUxplP6I0wr2KJ
395PSTJCjJOn3xo2NTKRgV1gaoTf2EhL+RG8TQ=
396-----END CERTIFICATE-----
397"""
398
399client_key_pem = """-----BEGIN RSA PRIVATE KEY-----
400MIICXgIBAAKBgQDAZh/SRtNm5ntMT4qb6YzEpTroMlq2rn+GrRHRiZ+xkCw/CGNh
401btPir7/QxaUj26BSmQrHw1bGKEbPsWiW7bdXSespl+xKiku4G/KvnnmWdeJHqsiX
402eUZtqurMELcPQAw9xPHEuhqqUJvvEoMTsnCEqGM+7DtboCRajYyHfluARQIDAQAB
403AoGATkZ+NceY5Glqyl4mD06SdcKfV65814vg2EL7V9t8+/mi9rYL8KztSXGlQWPX
404zuHgtRoMl78yQ4ZJYOBVo+nsx8KZNRCEBlE19bamSbQLCeQMenWnpeYyQUZ908gF
405h6L9qsFVJepgA9RDgAjyDoS5CaWCdCCPCH2lDkdcqC54SVUCQQDseuduc4wi8h4t
406V8AahUn9fn9gYfhoNuM0gdguTA0nPLVWz4hy1yJiWYQe0H7NLNNTmCKiLQaJpAbb
407TC6vE8C7AkEA0Ee8CMJUc20BnGEmxwgWcVuqFWaKCo8jTH1X38FlATUsyR3krjW2
408dL3yDD9NwHxsYP7nTKp/U8MV7U9IBn4y/wJBAJl7H0/BcLeRmuJk7IqJ7b635iYB
409D/9beFUw3MUXmQXZUfyYz39xf6CDZsu1GEdEC5haykeln3Of4M9d/4Kj+FcCQQCY
410si6xwT7GzMDkk/ko684AV3KPc/h6G0yGtFIrMg7J3uExpR/VdH2KgwMkZXisSMvw
411JJEQjOMCVsEJlRk54WWjAkEAzoZNH6UhDdBK5F38rVt/y4SEHgbSfJHIAmPS32Kq
412f6GGcfNpip0Uk7q7udTKuX7Q/buZi/C4YW7u3VKAquv9NA==
413-----END RSA PRIVATE KEY-----
414"""
415
416def verify_cb(conn, cert, errnum, depth, ok):
417 return ok
418
Jean-Paul Calderone958299e2009-04-27 12:59:12 -0400419class MemoryBIOTests(TestCase):
Rick Deanb71c0d22009-04-01 14:09:23 -0500420 """
Jean-Paul Calderone958299e2009-04-27 12:59:12 -0400421 Tests for L{OpenSSL.SSL.Connection} using a memory BIO.
Rick Deanb71c0d22009-04-01 14:09:23 -0500422 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -0400423 def _server(self, sock):
424 """
425 Create a new server-side SSL L{Connection} object wrapped around
426 C{sock}.
427 """
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -0400428 # Create the server side Connection. This is mostly setup boilerplate
429 # - use TLSv1, use a particular certificate, etc.
430 server_ctx = Context(TLSv1_METHOD)
431 server_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE )
432 server_ctx.set_verify(VERIFY_PEER|VERIFY_FAIL_IF_NO_PEER_CERT|VERIFY_CLIENT_ONCE, verify_cb)
433 server_store = server_ctx.get_cert_store()
434 server_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
435 server_ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
436 server_ctx.check_privatekey()
437 server_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -0500438 # Here the Connection is actually created. If None is passed as the 2nd
439 # parameter, it indicates a memory BIO should be created.
440 server_conn = Connection(server_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -0400441 server_conn.set_accept_state()
442 return server_conn
443
444
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -0400445 def _client(self, sock):
446 """
447 Create a new client-side SSL L{Connection} object wrapped around
448 C{sock}.
449 """
450 # Now create the client side Connection. Similar boilerplate to the
451 # above.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -0400452 client_ctx = Context(TLSv1_METHOD)
453 client_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE )
454 client_ctx.set_verify(VERIFY_PEER|VERIFY_FAIL_IF_NO_PEER_CERT|VERIFY_CLIENT_ONCE, verify_cb)
455 client_store = client_ctx.get_cert_store()
456 client_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, client_key_pem))
457 client_ctx.use_certificate(load_certificate(FILETYPE_PEM, client_cert_pem))
458 client_ctx.check_privatekey()
459 client_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -0500460 client_conn = Connection(client_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -0400461 client_conn.set_connect_state()
462 return client_conn
463
464
Jean-Paul Calderone958299e2009-04-27 12:59:12 -0400465 def _loopback(self, client_conn, server_conn):
466 """
467 Try to read application bytes from each of the two L{Connection}
468 objects. Copy bytes back and forth between their send/receive buffers
469 for as long as there is anything to copy. When there is nothing more
470 to copy, return C{None}. If one of them actually manages to deliver
471 some application bytes, return a two-tuple of the connection from which
472 the bytes were read and the bytes themselves.
473 """
474 wrote = True
475 while wrote:
476 # Loop until neither side has anything to say
477 wrote = False
478
479 # Copy stuff from each side's send buffer to the other side's
480 # receive buffer.
481 for (read, write) in [(client_conn, server_conn),
482 (server_conn, client_conn)]:
483
484 # Give the side a chance to generate some more bytes, or
485 # succeed.
486 try:
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -0400487 bytes = read.recv(2 ** 16)
Jean-Paul Calderone958299e2009-04-27 12:59:12 -0400488 except WantReadError:
489 # It didn't succeed, so we'll hope it generated some
490 # output.
491 pass
492 else:
493 # It did succeed, so we'll stop now and let the caller deal
494 # with it.
495 return (read, bytes)
496
497 while True:
498 # Keep copying as long as there's more stuff there.
499 try:
500 dirty = read.bio_read(4096)
501 except WantReadError:
502 # Okay, nothing more waiting to be sent. Stop
503 # processing this send buffer.
504 break
505 else:
506 # Keep track of the fact that someone generated some
507 # output.
508 wrote = True
509 write.bio_write(dirty)
510
511
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -0400512 def test_memoryConnect(self):
Jean-Paul Calderone958299e2009-04-27 12:59:12 -0400513 """
514 Two L{Connection}s which use memory BIOs can be manually connected by
515 reading from the output of each and writing those bytes to the input of
516 the other and in this way establish a connection and exchange
517 application-level bytes with each other.
518 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -0400519 server_conn = self._server(None)
520 client_conn = self._client(None)
Rick Deanb71c0d22009-04-01 14:09:23 -0500521
Jean-Paul Calderone958299e2009-04-27 12:59:12 -0400522 # There should be no key or nonces yet.
523 self.assertIdentical(server_conn.master_key(), None)
524 self.assertIdentical(server_conn.client_random(), None)
525 self.assertIdentical(server_conn.server_random(), None)
Rick Deanb71c0d22009-04-01 14:09:23 -0500526
Jean-Paul Calderone958299e2009-04-27 12:59:12 -0400527 # First, the handshake needs to happen. We'll deliver bytes back and
528 # forth between the client and server until neither of them feels like
529 # speaking any more.
530 self.assertIdentical(self._loopback(client_conn, server_conn), None)
531
532 # Now that the handshake is done, there should be a key and nonces.
533 self.assertNotIdentical(server_conn.master_key(), None)
534 self.assertNotIdentical(server_conn.client_random(), None)
535 self.assertNotIdentical(server_conn.server_random(), None)
Jean-Paul Calderone6c051e62009-07-05 13:50:34 -0400536 self.assertEquals(server_conn.client_random(), client_conn.client_random())
537 self.assertEquals(server_conn.server_random(), client_conn.server_random())
538 self.assertNotEquals(server_conn.client_random(), server_conn.server_random())
539 self.assertNotEquals(client_conn.client_random(), client_conn.server_random())
Jean-Paul Calderone958299e2009-04-27 12:59:12 -0400540
541 # Here are the bytes we'll try to send.
Rick Deanb71c0d22009-04-01 14:09:23 -0500542 important_message = 'One if by land, two if by sea.'
543
Jean-Paul Calderone958299e2009-04-27 12:59:12 -0400544 server_conn.write(important_message)
545 self.assertEquals(
546 self._loopback(client_conn, server_conn),
547 (client_conn, important_message))
548
549 client_conn.write(important_message[::-1])
550 self.assertEquals(
551 self._loopback(client_conn, server_conn),
552 (server_conn, important_message[::-1]))
Rick Deanb71c0d22009-04-01 14:09:23 -0500553
554
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -0400555 def test_socketConnect(self):
Rick Deanb1ccd562009-07-09 23:52:39 -0500556 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -0400557 Just like L{test_memoryConnect} but with an actual socket.
558
559 This is primarily to rule out the memory BIO code as the source of
560 any problems encountered while passing data over a L{Connection} (if
561 this test fails, there must be a problem outside the memory BIO
562 code, as no memory BIO is involved here). Even though this isn't a
563 memory BIO test, it's convenient to have it here.
Rick Deanb1ccd562009-07-09 23:52:39 -0500564 """
565 (server, client) = socket_pair()
566
567 # Let the encryption begin...
568 client_conn = self._client(client)
569 client_conn.set_connect_state()
570 server_conn = self._server(server)
571 server_conn.set_accept_state()
572 # Establish the connection
573 established = False
574 while not established:
575 established = True # assume the best
576 for ssl in client_conn, server_conn:
577 try:
578 # Generally a recv() or send() could also work instead
579 # of do_handshake(), and we would stop on the first
580 # non-exception.
581 ssl.do_handshake()
582 except WantReadError:
583 established = False
584
585 important_message = "Help me Obi Wan Kenobi, you're my only hope."
586 client_conn.send(important_message)
587 msg = server_conn.recv(1024)
588 self.assertEqual(msg, important_message)
589
590 # Again in the other direction, just for fun.
591 important_message = important_message[::-1]
592 server_conn.send(important_message)
593 msg = client_conn.recv(1024)
594 self.assertEqual(msg, important_message)
595
596
Jean-Paul Calderonefc4ed0f2009-04-27 11:51:27 -0400597 def test_socketOverridesMemory(self):
Rick Deanb71c0d22009-04-01 14:09:23 -0500598 """
599 Test that L{OpenSSL.SSL.bio_read} and L{OpenSSL.SSL.bio_write} don't
600 work on L{OpenSSL.SSL.Connection}() that use sockets.
601 """
602 context = Context(SSLv3_METHOD)
603 client = socket()
604 clientSSL = Connection(context, client)
605 self.assertRaises( TypeError, clientSSL.bio_read, 100)
606 self.assertRaises( TypeError, clientSSL.bio_write, "foo")
Jean-Paul Calderone07acf3f2009-05-05 13:23:28 -0400607 self.assertRaises( TypeError, clientSSL.bio_shutdown )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -0400608
609
610 def test_outgoingOverflow(self):
611 """
612 If more bytes than can be written to the memory BIO are passed to
613 L{Connection.send} at once, the number of bytes which were written is
614 returned and that many bytes from the beginning of the input can be
615 read from the other end of the connection.
616 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -0400617 server = self._server(None)
618 client = self._client(None)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -0400619
620 self._loopback(client, server)
621
622 size = 2 ** 15
623 sent = client.send("x" * size)
624 # Sanity check. We're trying to test what happens when the entire
625 # input can't be sent. If the entire input was sent, this test is
626 # meaningless.
627 self.assertTrue(sent < size)
628
629 receiver, received = self._loopback(client, server)
630 self.assertIdentical(receiver, server)
631
632 # We can rely on all of these bytes being received at once because
633 # _loopback passes 2 ** 16 to recv - more than 2 ** 15.
634 self.assertEquals(len(received), sent)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -0400635
636
637 def test_shutdown(self):
638 """
639 L{Connection.bio_shutdown} signals the end of the data stream from
640 which the L{Connection} reads.
641 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -0400642 server = self._server(None)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -0400643 server.bio_shutdown()
644 e = self.assertRaises(Error, server.recv, 1024)
645 # We don't want WantReadError or ZeroReturnError or anything - it's a
646 # handshake failure.
647 self.assertEquals(e.__class__, Error)
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -0400648
649
650
651if __name__ == '__main__':
652 main()