blob: a7c744e3a908aeb7225f164d4dee1986ece178d4 [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())
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -040046 client.setblocking(True)
Rick Deanb1ccd562009-07-09 23:52:39 -050047 server = port.accept()[0]
Rick Deanb1ccd562009-07-09 23:52:39 -050048
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
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -040057 # All our callers want non-blocking sockets, make it easy for them.
58 server.setblocking(False)
59 client.setblocking(False)
60
Rick Deanb1ccd562009-07-09 23:52:39 -050061 return (server, client)
62
63
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -040064
Jean-Paul Calderone18808652009-07-05 12:54:05 -040065class ContextTests(TestCase):
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -040066 """
67 Unit tests for L{OpenSSL.SSL.Context}.
68 """
69 def test_method(self):
70 """
71 L{Context} can be instantiated with one of L{SSLv2_METHOD},
72 L{SSLv3_METHOD}, L{SSLv23_METHOD}, or L{TLSv1_METHOD}.
73 """
74 for meth in [SSLv2_METHOD, SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD]:
75 Context(meth)
76 self.assertRaises(TypeError, Context, "")
77 self.assertRaises(ValueError, Context, 10)
78
79
80 def test_use_privatekey(self):
81 """
82 L{Context.use_privatekey} takes an L{OpenSSL.crypto.PKey} instance.
83 """
84 key = PKey()
85 key.generate_key(TYPE_RSA, 128)
86 ctx = Context(TLSv1_METHOD)
87 ctx.use_privatekey(key)
88 self.assertRaises(TypeError, ctx.use_privatekey, "")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -040089
90
91 def test_set_passwd_cb(self):
92 """
93 L{Context.set_passwd_cb} accepts a callable which will be invoked when
94 a private key is loaded from an encrypted PEM.
95 """
96 key = PKey()
97 key.generate_key(TYPE_RSA, 128)
98 pemFile = self.mktemp()
99 fObj = file(pemFile, 'w')
100 passphrase = "foobar"
101 fObj.write(dump_privatekey(FILETYPE_PEM, key, "blowfish", passphrase))
102 fObj.close()
103
104 calledWith = []
105 def passphraseCallback(maxlen, verify, extra):
106 calledWith.append((maxlen, verify, extra))
107 return passphrase
108 context = Context(TLSv1_METHOD)
109 context.set_passwd_cb(passphraseCallback)
110 context.use_privatekey_file(pemFile)
111 self.assertTrue(len(calledWith), 1)
112 self.assertTrue(isinstance(calledWith[0][0], int))
113 self.assertTrue(isinstance(calledWith[0][1], int))
114 self.assertEqual(calledWith[0][2], None)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400115
116
117 def test_set_info_callback(self):
118 """
119 L{Context.set_info_callback} accepts a callable which will be invoked
120 when certain information about an SSL connection is available.
121 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500122 (server, client) = socket_pair()
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400123
124 clientSSL = Connection(Context(TLSv1_METHOD), client)
125 clientSSL.set_connect_state()
126
127 called = []
128 def info(conn, where, ret):
129 called.append((conn, where, ret))
130 context = Context(TLSv1_METHOD)
131 context.set_info_callback(info)
132 context.use_certificate(
133 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
134 context.use_privatekey(
135 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
136
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400137 serverSSL = Connection(context, server)
138 serverSSL.set_accept_state()
139
140 while not called:
141 for ssl in clientSSL, serverSSL:
142 try:
143 ssl.do_handshake()
144 except WantReadError:
145 pass
146
147 # Kind of lame. Just make sure it got called somehow.
148 self.assertTrue(called)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400149
150
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400151 def _load_verify_locations_test(self, *args):
Rick Deanb1ccd562009-07-09 23:52:39 -0500152 (server, client) = socket_pair()
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400153
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400154 clientContext = Context(TLSv1_METHOD)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400155 clientContext.load_verify_locations(*args)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400156 # Require that the server certificate verify properly or the
157 # connection will fail.
158 clientContext.set_verify(
159 VERIFY_PEER,
160 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
161
162 clientSSL = Connection(clientContext, client)
163 clientSSL.set_connect_state()
164
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400165 serverContext = Context(TLSv1_METHOD)
166 serverContext.use_certificate(
167 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
168 serverContext.use_privatekey(
169 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
170
171 serverSSL = Connection(serverContext, server)
172 serverSSL.set_accept_state()
173
174 for i in range(3):
175 for ssl in clientSSL, serverSSL:
176 try:
177 # Without load_verify_locations above, the handshake
178 # will fail:
179 # Error: [('SSL routines', 'SSL3_GET_SERVER_CERTIFICATE',
180 # 'certificate verify failed')]
181 ssl.do_handshake()
182 except WantReadError:
183 pass
184
185 cert = clientSSL.get_peer_certificate()
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400186 self.assertEqual(cert.get_subject().CN, 'Testing Root CA')
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400187
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400188 def test_load_verify_file(self):
189 """
190 L{Context.load_verify_locations} accepts a file name and uses the
191 certificates within for verification purposes.
192 """
193 cafile = self.mktemp()
194 fObj = file(cafile, 'w')
195 fObj.write(cleartextCertificatePEM)
196 fObj.close()
197
198 self._load_verify_locations_test(cafile)
199
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400200
201 def test_load_verify_invalid_file(self):
202 """
203 L{Context.load_verify_locations} raises L{Error} when passed a
204 non-existent cafile.
205 """
206 clientContext = Context(TLSv1_METHOD)
207 self.assertRaises(
208 Error, clientContext.load_verify_locations, self.mktemp())
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400209
210
211 def test_load_verify_directory(self):
212 """
213 L{Context.load_verify_locations} accepts a directory name and uses
214 the certificates within for verification purposes.
215 """
216 capath = self.mktemp()
217 makedirs(capath)
218 cafile = join(capath, 'cert.pem')
219 fObj = file(cafile, 'w')
220 fObj.write(cleartextCertificatePEM)
221 fObj.close()
222
223 # Hash value computed manually with c_rehash to avoid depending on
224 # c_rehash in the test suite.
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400225 symlink('cert.pem', join(capath, 'c7adac82.0'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400226
227 self._load_verify_locations_test(None, capath)
228
229
230 def test_set_default_verify_paths(self):
231 """
232 L{Context.set_default_verify_paths} causes the platform-specific CA
233 certificate locations to be used for verification purposes.
234 """
235 # Testing this requires a server with a certificate signed by one of
236 # the CAs in the platform CA location. Getting one of those costs
237 # money. Fortunately (or unfortunately, depending on your
238 # perspective), it's easy to think of a public server on the
239 # internet which has such a certificate. Connecting to the network
240 # in a unit test is bad, but it's the only way I can think of to
241 # really test this. -exarkun
242
243 # Arg, verisign.com doesn't speak TLSv1
244 context = Context(SSLv3_METHOD)
245 context.set_default_verify_paths()
246 context.set_verify(
247 VERIFY_PEER,
248 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
249
250 client = socket()
251 client.connect(('verisign.com', 443))
252 clientSSL = Connection(context, client)
253 clientSSL.set_connect_state()
254 clientSSL.do_handshake()
255 clientSSL.send('GET / HTTP/1.0\r\n\r\n')
256 self.assertTrue(clientSSL.recv(1024))
Jean-Paul Calderone52f0d8b2009-03-07 09:10:19 -0500257 if platform == "darwin":
Jean-Paul Calderone1d287e52009-03-07 09:09:07 -0500258 test_set_default_verify_paths.todo = (
259 "set_default_verify_paths appears not to work on OS X - a "
260 "problem with the supplied OpenSSL, perhaps?")
Jean-Paul Calderone9eadb962008-09-07 21:20:44 -0400261
262
263 def test_set_default_verify_paths_signature(self):
264 """
265 L{Context.set_default_verify_paths} takes no arguments and raises
266 L{TypeError} if given any.
267 """
268 context = Context(TLSv1_METHOD)
269 self.assertRaises(TypeError, context.set_default_verify_paths, None)
270 self.assertRaises(TypeError, context.set_default_verify_paths, 1)
271 self.assertRaises(TypeError, context.set_default_verify_paths, "")
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -0500272
273
274
275class ConstantsTests(TestCase):
276 """
277 Tests for the values of constants exposed in L{OpenSSL.SSL}.
278
279 These are values defined by OpenSSL intended only to be used as flags to
280 OpenSSL APIs. The only assertions it seems can be made about them is
281 their values.
282 """
Jean-Paul Calderoned811b682008-12-28 22:59:15 -0500283 # unittest.TestCase has no skip mechanism
284 if OP_NO_QUERY_MTU is not None:
285 def test_op_no_query_mtu(self):
286 """
287 The value of L{OpenSSL.SSL.OP_NO_QUERY_MTU} is 0x1000, the value of
288 I{SSL_OP_NO_QUERY_MTU} defined by I{openssl/ssl.h}.
289 """
290 self.assertEqual(OP_NO_QUERY_MTU, 0x1000)
291 else:
292 "OP_NO_QUERY_MTU unavailable - OpenSSL version may be too old"
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -0500293
294
Jean-Paul Calderoned811b682008-12-28 22:59:15 -0500295 if OP_COOKIE_EXCHANGE is not None:
296 def test_op_cookie_exchange(self):
297 """
298 The value of L{OpenSSL.SSL.OP_COOKIE_EXCHANGE} is 0x2000, the value
299 of I{SSL_OP_COOKIE_EXCHANGE} defined by I{openssl/ssl.h}.
300 """
301 self.assertEqual(OP_COOKIE_EXCHANGE, 0x2000)
302 else:
303 "OP_COOKIE_EXCHANGE unavailable - OpenSSL version may be too old"
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -0500304
305
Jean-Paul Calderoned811b682008-12-28 22:59:15 -0500306 if OP_NO_TICKET is not None:
307 def test_op_no_ticket(self):
308 """
309 The value of L{OpenSSL.SSL.OP_NO_TICKET} is 0x4000, the value of
310 I{SSL_OP_NO_TICKET} defined by I{openssl/ssl.h}.
311 """
312 self.assertEqual(OP_NO_TICKET, 0x4000)
313 else:
314 "OP_NO_TICKET unavailable - OpenSSL version may be too old"
Rick Dean5b7b6372009-04-01 11:34:06 -0500315
316
Jean-Paul Calderoneeeee26a2009-04-27 11:24:30 -0400317
Rick Deanb71c0d22009-04-01 14:09:23 -0500318root_cert_pem = """-----BEGIN CERTIFICATE-----
319MIIC7TCCAlagAwIBAgIIPQzE4MbeufQwDQYJKoZIhvcNAQEFBQAwWDELMAkGA1UE
320BhMCVVMxCzAJBgNVBAgTAklMMRAwDgYDVQQHEwdDaGljYWdvMRAwDgYDVQQKEwdU
321ZXN0aW5nMRgwFgYDVQQDEw9UZXN0aW5nIFJvb3QgQ0EwIhgPMjAwOTAzMjUxMjM2
322NThaGA8yMDE3MDYxMTEyMzY1OFowWDELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAklM
323MRAwDgYDVQQHEwdDaGljYWdvMRAwDgYDVQQKEwdUZXN0aW5nMRgwFgYDVQQDEw9U
324ZXN0aW5nIFJvb3QgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAPmaQumL
325urpE527uSEHdL1pqcDRmWzu+98Y6YHzT/J7KWEamyMCNZ6fRW1JCR782UQ8a07fy
3262xXsKy4WdKaxyG8CcatwmXvpvRQ44dSANMihHELpANTdyVp6DCysED6wkQFurHlF
3271dshEaJw8b/ypDhmbVIo6Ci1xvCJqivbLFnbAgMBAAGjgbswgbgwHQYDVR0OBBYE
328FINVdy1eIfFJDAkk51QJEo3IfgSuMIGIBgNVHSMEgYAwfoAUg1V3LV4h8UkMCSTn
329VAkSjch+BK6hXKRaMFgxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJJTDEQMA4GA1UE
330BxMHQ2hpY2FnbzEQMA4GA1UEChMHVGVzdGluZzEYMBYGA1UEAxMPVGVzdGluZyBS
331b290IENBggg9DMTgxt659DAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4GB
332AGGCDazMJGoWNBpc03u6+smc95dEead2KlZXBATOdFT1VesY3+nUOqZhEhTGlDMi
333hkgaZnzoIq/Uamidegk4hirsCT/R+6vsKAAxNTcBjUeZjlykCJWy5ojShGftXIKY
334w/njVbKMXrvc83qmTdGl3TAM0fxQIpqgcglFLveEBgzn
335-----END CERTIFICATE-----
336"""
337
338root_key_pem = """-----BEGIN RSA PRIVATE KEY-----
339MIICXQIBAAKBgQD5mkLpi7q6ROdu7khB3S9aanA0Zls7vvfGOmB80/yeylhGpsjA
340jWen0VtSQke/NlEPGtO38tsV7CsuFnSmschvAnGrcJl76b0UOOHUgDTIoRxC6QDU
3413claegwsrBA+sJEBbqx5RdXbIRGicPG/8qQ4Zm1SKOgotcbwiaor2yxZ2wIDAQAB
342AoGBAPCgMpmLxzwDaUmcFbTJUvlLW1hoxNNYSu2jIZm1k/hRAcE60JYwvBkgz3UB
343yMEh0AtLxYe0bFk6EHah11tMUPgscbCq73snJ++8koUw+csk22G65hOs51bVb7Aa
3446JBe67oLzdtvgCUFAA2qfrKzWRZzAdhUirQUZgySZk+Xq1pBAkEA/kZG0A6roTSM
345BVnx7LnPfsycKUsTumorpXiylZJjTi9XtmzxhrYN6wgZlDOOwOLgSQhszGpxVoMD
346u3gByT1b2QJBAPtL3mSKdvwRu/+40zaZLwvSJRxaj0mcE4BJOS6Oqs/hS1xRlrNk
347PpQ7WJ4yM6ZOLnXzm2mKyxm50Mv64109FtMCQQDOqS2KkjHaLowTGVxwC0DijMfr
348I9Lf8sSQk32J5VWCySWf5gGTfEnpmUa41gKTMJIbqZZLucNuDcOtzUaeWZlZAkA8
349ttXigLnCqR486JDPTi9ZscoZkZ+w7y6e/hH8t6d5Vjt48JVyfjPIaJY+km58LcN3
3506AWSeGAdtRFHVzR7oHjVAkB4hutvxiOeiIVQNBhM6RSI9aBPMI21DoX2JRoxvNW2
351cbvAhow217X9V0dVerEOKxnNYspXRrh36h7k4mQA+sDq
352-----END RSA PRIVATE KEY-----
353"""
354
355server_cert_pem = """-----BEGIN CERTIFICATE-----
356MIICKDCCAZGgAwIBAgIJAJn/HpR21r/8MA0GCSqGSIb3DQEBBQUAMFgxCzAJBgNV
357BAYTAlVTMQswCQYDVQQIEwJJTDEQMA4GA1UEBxMHQ2hpY2FnbzEQMA4GA1UEChMH
358VGVzdGluZzEYMBYGA1UEAxMPVGVzdGluZyBSb290IENBMCIYDzIwMDkwMzI1MTIz
359NzUzWhgPMjAxNzA2MTExMjM3NTNaMBgxFjAUBgNVBAMTDWxvdmVseSBzZXJ2ZXIw
360gZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAL6m+G653V0tpBC/OKl22VxOi2Cv
361lK4TYu9LHSDP9uDVTe7V5D5Tl6qzFoRRx5pfmnkqT5B+W9byp2NU3FC5hLm5zSAr
362b45meUhjEJ/ifkZgbNUjHdBIGP9MAQUHZa5WKdkGIJvGAvs8UzUqlr4TBWQIB24+
363lJ+Ukk/CRgasrYwdAgMBAAGjNjA0MB0GA1UdDgQWBBS4kC7Ij0W1TZXZqXQFAM2e
364gKEG2DATBgNVHSUEDDAKBggrBgEFBQcDATANBgkqhkiG9w0BAQUFAAOBgQBh30Li
365dJ+NlxIOx5343WqIBka3UbsOb2kxWrbkVCrvRapCMLCASO4FqiKWM+L0VDBprqIp
3662mgpFQ6FHpoIENGvJhdEKpptQ5i7KaGhnDNTfdy3x1+h852G99f1iyj0RmbuFcM8
367uzujnS8YXWvM7DM1Ilozk4MzPug8jzFp5uhKCQ==
368-----END CERTIFICATE-----
369"""
370
371server_key_pem = """-----BEGIN RSA PRIVATE KEY-----
372MIICWwIBAAKBgQC+pvhuud1dLaQQvzipdtlcTotgr5SuE2LvSx0gz/bg1U3u1eQ+
373U5eqsxaEUceaX5p5Kk+QflvW8qdjVNxQuYS5uc0gK2+OZnlIYxCf4n5GYGzVIx3Q
374SBj/TAEFB2WuVinZBiCbxgL7PFM1Kpa+EwVkCAduPpSflJJPwkYGrK2MHQIDAQAB
375AoGAbwuZ0AR6JveahBaczjfnSpiFHf+mve2UxoQdpyr6ROJ4zg/PLW5K/KXrC48G
376j6f3tXMrfKHcpEoZrQWUfYBRCUsGD5DCazEhD8zlxEHahIsqpwA0WWssJA2VOLEN
377j6DuV2pCFbw67rfTBkTSo32ahfXxEKev5KswZk0JIzH3ooECQQDgzS9AI89h0gs8
378Dt+1m11Rzqo3vZML7ZIyGApUzVan+a7hbc33nbGRkAXjHaUBJO31it/H6dTO+uwX
379msWwNG5ZAkEA2RyFKs5xR5USTFaKLWCgpH/ydV96KPOpBND7TKQx62snDenFNNbn
380FwwOhpahld+vqhYk+pfuWWUpQciE+Bu7ZQJASjfT4sQv4qbbKK/scePicnDdx9th
3814e1EeB9xwb+tXXXUo/6Bor/AcUNwfiQ6Zt9PZOK9sR3lMZSsP7rMi7kzuQJABie6
3821sXXjFH7nNJvRG4S39cIxq8YRYTy68II/dlB2QzGpKxV/POCxbJ/zu0CU79tuYK7
383NaeNCFfH3aeTrX0LyQJAMBWjWmeKM2G2sCExheeQK0ROnaBC8itCECD4Jsve4nqf
384r50+LF74iLXFwqysVCebPKMOpDWp/qQ1BbJQIPs7/A==
385-----END RSA PRIVATE KEY-----
386"""
387
388client_cert_pem = """-----BEGIN CERTIFICATE-----
389MIICJjCCAY+gAwIBAgIJAKxpFI5lODkjMA0GCSqGSIb3DQEBBQUAMFgxCzAJBgNV
390BAYTAlVTMQswCQYDVQQIEwJJTDEQMA4GA1UEBxMHQ2hpY2FnbzEQMA4GA1UEChMH
391VGVzdGluZzEYMBYGA1UEAxMPVGVzdGluZyBSb290IENBMCIYDzIwMDkwMzI1MTIz
392ODA1WhgPMjAxNzA2MTExMjM4MDVaMBYxFDASBgNVBAMTC3VnbHkgY2xpZW50MIGf
393MA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDAZh/SRtNm5ntMT4qb6YzEpTroMlq2
394rn+GrRHRiZ+xkCw/CGNhbtPir7/QxaUj26BSmQrHw1bGKEbPsWiW7bdXSespl+xK
395iku4G/KvnnmWdeJHqsiXeUZtqurMELcPQAw9xPHEuhqqUJvvEoMTsnCEqGM+7Dtb
396oCRajYyHfluARQIDAQABozYwNDAdBgNVHQ4EFgQUNQB+qkaOaEVecf1J3TTUtAff
3970fAwEwYDVR0lBAwwCgYIKwYBBQUHAwIwDQYJKoZIhvcNAQEFBQADgYEAyv/Jh7gM
398Q3OHvmsFEEvRI+hsW8y66zK4K5de239Y44iZrFYkt7Q5nBPMEWDj4F2hLYWL/qtI
3999Zdr0U4UDCU9SmmGYh4o7R4TZ5pGFvBYvjhHbkSFYFQXZxKUi+WUxplP6I0wr2KJ
400PSTJCjJOn3xo2NTKRgV1gaoTf2EhL+RG8TQ=
401-----END CERTIFICATE-----
402"""
403
404client_key_pem = """-----BEGIN RSA PRIVATE KEY-----
405MIICXgIBAAKBgQDAZh/SRtNm5ntMT4qb6YzEpTroMlq2rn+GrRHRiZ+xkCw/CGNh
406btPir7/QxaUj26BSmQrHw1bGKEbPsWiW7bdXSespl+xKiku4G/KvnnmWdeJHqsiX
407eUZtqurMELcPQAw9xPHEuhqqUJvvEoMTsnCEqGM+7DtboCRajYyHfluARQIDAQAB
408AoGATkZ+NceY5Glqyl4mD06SdcKfV65814vg2EL7V9t8+/mi9rYL8KztSXGlQWPX
409zuHgtRoMl78yQ4ZJYOBVo+nsx8KZNRCEBlE19bamSbQLCeQMenWnpeYyQUZ908gF
410h6L9qsFVJepgA9RDgAjyDoS5CaWCdCCPCH2lDkdcqC54SVUCQQDseuduc4wi8h4t
411V8AahUn9fn9gYfhoNuM0gdguTA0nPLVWz4hy1yJiWYQe0H7NLNNTmCKiLQaJpAbb
412TC6vE8C7AkEA0Ee8CMJUc20BnGEmxwgWcVuqFWaKCo8jTH1X38FlATUsyR3krjW2
413dL3yDD9NwHxsYP7nTKp/U8MV7U9IBn4y/wJBAJl7H0/BcLeRmuJk7IqJ7b635iYB
414D/9beFUw3MUXmQXZUfyYz39xf6CDZsu1GEdEC5haykeln3Of4M9d/4Kj+FcCQQCY
415si6xwT7GzMDkk/ko684AV3KPc/h6G0yGtFIrMg7J3uExpR/VdH2KgwMkZXisSMvw
416JJEQjOMCVsEJlRk54WWjAkEAzoZNH6UhDdBK5F38rVt/y4SEHgbSfJHIAmPS32Kq
417f6GGcfNpip0Uk7q7udTKuX7Q/buZi/C4YW7u3VKAquv9NA==
418-----END RSA PRIVATE KEY-----
419"""
420
421def verify_cb(conn, cert, errnum, depth, ok):
422 return ok
423
Jean-Paul Calderone958299e2009-04-27 12:59:12 -0400424class MemoryBIOTests(TestCase):
Rick Deanb71c0d22009-04-01 14:09:23 -0500425 """
Jean-Paul Calderone958299e2009-04-27 12:59:12 -0400426 Tests for L{OpenSSL.SSL.Connection} using a memory BIO.
Rick Deanb71c0d22009-04-01 14:09:23 -0500427 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -0400428 def _server(self, sock):
429 """
430 Create a new server-side SSL L{Connection} object wrapped around
431 C{sock}.
432 """
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -0400433 # Create the server side Connection. This is mostly setup boilerplate
434 # - use TLSv1, use a particular certificate, etc.
435 server_ctx = Context(TLSv1_METHOD)
436 server_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE )
437 server_ctx.set_verify(VERIFY_PEER|VERIFY_FAIL_IF_NO_PEER_CERT|VERIFY_CLIENT_ONCE, verify_cb)
438 server_store = server_ctx.get_cert_store()
439 server_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
440 server_ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
441 server_ctx.check_privatekey()
442 server_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -0500443 # Here the Connection is actually created. If None is passed as the 2nd
444 # parameter, it indicates a memory BIO should be created.
445 server_conn = Connection(server_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -0400446 server_conn.set_accept_state()
447 return server_conn
448
449
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -0400450 def _client(self, sock):
451 """
452 Create a new client-side SSL L{Connection} object wrapped around
453 C{sock}.
454 """
455 # Now create the client side Connection. Similar boilerplate to the
456 # above.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -0400457 client_ctx = Context(TLSv1_METHOD)
458 client_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE )
459 client_ctx.set_verify(VERIFY_PEER|VERIFY_FAIL_IF_NO_PEER_CERT|VERIFY_CLIENT_ONCE, verify_cb)
460 client_store = client_ctx.get_cert_store()
461 client_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, client_key_pem))
462 client_ctx.use_certificate(load_certificate(FILETYPE_PEM, client_cert_pem))
463 client_ctx.check_privatekey()
464 client_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -0500465 client_conn = Connection(client_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -0400466 client_conn.set_connect_state()
467 return client_conn
468
469
Jean-Paul Calderone958299e2009-04-27 12:59:12 -0400470 def _loopback(self, client_conn, server_conn):
471 """
472 Try to read application bytes from each of the two L{Connection}
473 objects. Copy bytes back and forth between their send/receive buffers
474 for as long as there is anything to copy. When there is nothing more
475 to copy, return C{None}. If one of them actually manages to deliver
476 some application bytes, return a two-tuple of the connection from which
477 the bytes were read and the bytes themselves.
478 """
479 wrote = True
480 while wrote:
481 # Loop until neither side has anything to say
482 wrote = False
483
484 # Copy stuff from each side's send buffer to the other side's
485 # receive buffer.
486 for (read, write) in [(client_conn, server_conn),
487 (server_conn, client_conn)]:
488
489 # Give the side a chance to generate some more bytes, or
490 # succeed.
491 try:
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -0400492 bytes = read.recv(2 ** 16)
Jean-Paul Calderone958299e2009-04-27 12:59:12 -0400493 except WantReadError:
494 # It didn't succeed, so we'll hope it generated some
495 # output.
496 pass
497 else:
498 # It did succeed, so we'll stop now and let the caller deal
499 # with it.
500 return (read, bytes)
501
502 while True:
503 # Keep copying as long as there's more stuff there.
504 try:
505 dirty = read.bio_read(4096)
506 except WantReadError:
507 # Okay, nothing more waiting to be sent. Stop
508 # processing this send buffer.
509 break
510 else:
511 # Keep track of the fact that someone generated some
512 # output.
513 wrote = True
514 write.bio_write(dirty)
515
516
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -0400517 def test_memoryConnect(self):
Jean-Paul Calderone958299e2009-04-27 12:59:12 -0400518 """
519 Two L{Connection}s which use memory BIOs can be manually connected by
520 reading from the output of each and writing those bytes to the input of
521 the other and in this way establish a connection and exchange
522 application-level bytes with each other.
523 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -0400524 server_conn = self._server(None)
525 client_conn = self._client(None)
Rick Deanb71c0d22009-04-01 14:09:23 -0500526
Jean-Paul Calderone958299e2009-04-27 12:59:12 -0400527 # There should be no key or nonces yet.
528 self.assertIdentical(server_conn.master_key(), None)
529 self.assertIdentical(server_conn.client_random(), None)
530 self.assertIdentical(server_conn.server_random(), None)
Rick Deanb71c0d22009-04-01 14:09:23 -0500531
Jean-Paul Calderone958299e2009-04-27 12:59:12 -0400532 # First, the handshake needs to happen. We'll deliver bytes back and
533 # forth between the client and server until neither of them feels like
534 # speaking any more.
535 self.assertIdentical(self._loopback(client_conn, server_conn), None)
536
537 # Now that the handshake is done, there should be a key and nonces.
538 self.assertNotIdentical(server_conn.master_key(), None)
539 self.assertNotIdentical(server_conn.client_random(), None)
540 self.assertNotIdentical(server_conn.server_random(), None)
Jean-Paul Calderone6c051e62009-07-05 13:50:34 -0400541 self.assertEquals(server_conn.client_random(), client_conn.client_random())
542 self.assertEquals(server_conn.server_random(), client_conn.server_random())
543 self.assertNotEquals(server_conn.client_random(), server_conn.server_random())
544 self.assertNotEquals(client_conn.client_random(), client_conn.server_random())
Jean-Paul Calderone958299e2009-04-27 12:59:12 -0400545
546 # Here are the bytes we'll try to send.
Rick Deanb71c0d22009-04-01 14:09:23 -0500547 important_message = 'One if by land, two if by sea.'
548
Jean-Paul Calderone958299e2009-04-27 12:59:12 -0400549 server_conn.write(important_message)
550 self.assertEquals(
551 self._loopback(client_conn, server_conn),
552 (client_conn, important_message))
553
554 client_conn.write(important_message[::-1])
555 self.assertEquals(
556 self._loopback(client_conn, server_conn),
557 (server_conn, important_message[::-1]))
Rick Deanb71c0d22009-04-01 14:09:23 -0500558
559
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -0400560 def test_socketConnect(self):
Rick Deanb1ccd562009-07-09 23:52:39 -0500561 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -0400562 Just like L{test_memoryConnect} but with an actual socket.
563
564 This is primarily to rule out the memory BIO code as the source of
565 any problems encountered while passing data over a L{Connection} (if
566 this test fails, there must be a problem outside the memory BIO
567 code, as no memory BIO is involved here). Even though this isn't a
568 memory BIO test, it's convenient to have it here.
Rick Deanb1ccd562009-07-09 23:52:39 -0500569 """
570 (server, client) = socket_pair()
571
572 # Let the encryption begin...
573 client_conn = self._client(client)
Rick Deanb1ccd562009-07-09 23:52:39 -0500574 server_conn = self._server(server)
Jean-Paul Calderone7903cbd2009-07-16 12:23:34 -0400575
Rick Deanb1ccd562009-07-09 23:52:39 -0500576 # Establish the connection
577 established = False
578 while not established:
579 established = True # assume the best
580 for ssl in client_conn, server_conn:
581 try:
582 # Generally a recv() or send() could also work instead
583 # of do_handshake(), and we would stop on the first
584 # non-exception.
585 ssl.do_handshake()
586 except WantReadError:
587 established = False
588
589 important_message = "Help me Obi Wan Kenobi, you're my only hope."
590 client_conn.send(important_message)
591 msg = server_conn.recv(1024)
592 self.assertEqual(msg, important_message)
593
594 # Again in the other direction, just for fun.
595 important_message = important_message[::-1]
596 server_conn.send(important_message)
597 msg = client_conn.recv(1024)
598 self.assertEqual(msg, important_message)
599
600
Jean-Paul Calderonefc4ed0f2009-04-27 11:51:27 -0400601 def test_socketOverridesMemory(self):
Rick Deanb71c0d22009-04-01 14:09:23 -0500602 """
603 Test that L{OpenSSL.SSL.bio_read} and L{OpenSSL.SSL.bio_write} don't
604 work on L{OpenSSL.SSL.Connection}() that use sockets.
605 """
606 context = Context(SSLv3_METHOD)
607 client = socket()
608 clientSSL = Connection(context, client)
609 self.assertRaises( TypeError, clientSSL.bio_read, 100)
610 self.assertRaises( TypeError, clientSSL.bio_write, "foo")
Jean-Paul Calderone07acf3f2009-05-05 13:23:28 -0400611 self.assertRaises( TypeError, clientSSL.bio_shutdown )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -0400612
613
614 def test_outgoingOverflow(self):
615 """
616 If more bytes than can be written to the memory BIO are passed to
617 L{Connection.send} at once, the number of bytes which were written is
618 returned and that many bytes from the beginning of the input can be
619 read from the other end of the connection.
620 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -0400621 server = self._server(None)
622 client = self._client(None)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -0400623
624 self._loopback(client, server)
625
626 size = 2 ** 15
627 sent = client.send("x" * size)
628 # Sanity check. We're trying to test what happens when the entire
629 # input can't be sent. If the entire input was sent, this test is
630 # meaningless.
631 self.assertTrue(sent < size)
632
633 receiver, received = self._loopback(client, server)
634 self.assertIdentical(receiver, server)
635
636 # We can rely on all of these bytes being received at once because
637 # _loopback passes 2 ** 16 to recv - more than 2 ** 15.
638 self.assertEquals(len(received), sent)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -0400639
640
641 def test_shutdown(self):
642 """
643 L{Connection.bio_shutdown} signals the end of the data stream from
644 which the L{Connection} reads.
645 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -0400646 server = self._server(None)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -0400647 server.bio_shutdown()
648 e = self.assertRaises(Error, server.recv, 1024)
649 # We don't want WantReadError or ZeroReturnError or anything - it's a
650 # handshake failure.
651 self.assertEquals(e.__class__, Error)
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -0400652
653
654
655if __name__ == '__main__':
656 main()