blob: 9eb8946746c1ce422ab6c8bc75072259ce1c8d51 [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
Rick Dean94e46fd2009-07-18 14:51:24 -050020from OpenSSL.test.test_crypto import client_cert_pem, client_key_pem, server_cert_pem, server_key_pem, root_cert_pem
Jean-Paul Calderone4bccf5e2008-12-28 22:50:42 -050021try:
22 from OpenSSL.SSL import OP_NO_QUERY_MTU
23except ImportError:
24 OP_NO_QUERY_MTU = None
25try:
26 from OpenSSL.SSL import OP_COOKIE_EXCHANGE
27except ImportError:
28 OP_COOKIE_EXCHANGE = None
29try:
30 from OpenSSL.SSL import OP_NO_TICKET
31except ImportError:
32 OP_NO_TICKET = None
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -040033
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -040034
Rick Deanb1ccd562009-07-09 23:52:39 -050035def socket_pair():
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -040036 """
37 Establish and return a pair of network sockets connected
38 to each other.
39 """
40 # Connect a pair of sockets
Rick Deanb1ccd562009-07-09 23:52:39 -050041 port = socket()
42 port.bind(('', 0))
43 port.listen(1)
44 client = socket()
45 client.setblocking(False)
46 client.connect_ex(port.getsockname())
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -040047 client.setblocking(True)
Rick Deanb1ccd562009-07-09 23:52:39 -050048 server = port.accept()[0]
Rick Deanb1ccd562009-07-09 23:52:39 -050049
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -040050 # Let's pass some unencrypted data to make sure our socket connection is
51 # fine. Just one byte, so we don't have to worry about buffers getting
52 # filled up or fragmentation.
53 server.send("x")
54 assert client.recv(1024) == "x"
55 client.send("y")
56 assert server.recv(1024) == "y"
Rick Deanb1ccd562009-07-09 23:52:39 -050057
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -040058 # All our callers want non-blocking sockets, make it easy for them.
59 server.setblocking(False)
60 client.setblocking(False)
61
Rick Deanb1ccd562009-07-09 23:52:39 -050062 return (server, client)
63
64
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -040065
Jean-Paul Calderone18808652009-07-05 12:54:05 -040066class ContextTests(TestCase):
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -040067 """
68 Unit tests for L{OpenSSL.SSL.Context}.
69 """
70 def test_method(self):
71 """
72 L{Context} can be instantiated with one of L{SSLv2_METHOD},
73 L{SSLv3_METHOD}, L{SSLv23_METHOD}, or L{TLSv1_METHOD}.
74 """
75 for meth in [SSLv2_METHOD, SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD]:
76 Context(meth)
77 self.assertRaises(TypeError, Context, "")
78 self.assertRaises(ValueError, Context, 10)
79
80
81 def test_use_privatekey(self):
82 """
83 L{Context.use_privatekey} takes an L{OpenSSL.crypto.PKey} instance.
84 """
85 key = PKey()
86 key.generate_key(TYPE_RSA, 128)
87 ctx = Context(TLSv1_METHOD)
88 ctx.use_privatekey(key)
89 self.assertRaises(TypeError, ctx.use_privatekey, "")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -040090
91
92 def test_set_passwd_cb(self):
93 """
94 L{Context.set_passwd_cb} accepts a callable which will be invoked when
95 a private key is loaded from an encrypted PEM.
96 """
97 key = PKey()
98 key.generate_key(TYPE_RSA, 128)
99 pemFile = self.mktemp()
100 fObj = file(pemFile, 'w')
101 passphrase = "foobar"
102 fObj.write(dump_privatekey(FILETYPE_PEM, key, "blowfish", passphrase))
103 fObj.close()
104
105 calledWith = []
106 def passphraseCallback(maxlen, verify, extra):
107 calledWith.append((maxlen, verify, extra))
108 return passphrase
109 context = Context(TLSv1_METHOD)
110 context.set_passwd_cb(passphraseCallback)
111 context.use_privatekey_file(pemFile)
112 self.assertTrue(len(calledWith), 1)
113 self.assertTrue(isinstance(calledWith[0][0], int))
114 self.assertTrue(isinstance(calledWith[0][1], int))
115 self.assertEqual(calledWith[0][2], None)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400116
117
118 def test_set_info_callback(self):
119 """
120 L{Context.set_info_callback} accepts a callable which will be invoked
121 when certain information about an SSL connection is available.
122 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500123 (server, client) = socket_pair()
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400124
125 clientSSL = Connection(Context(TLSv1_METHOD), client)
126 clientSSL.set_connect_state()
127
128 called = []
129 def info(conn, where, ret):
130 called.append((conn, where, ret))
131 context = Context(TLSv1_METHOD)
132 context.set_info_callback(info)
133 context.use_certificate(
134 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
135 context.use_privatekey(
136 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
137
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400138 serverSSL = Connection(context, server)
139 serverSSL.set_accept_state()
140
141 while not called:
142 for ssl in clientSSL, serverSSL:
143 try:
144 ssl.do_handshake()
145 except WantReadError:
146 pass
147
148 # Kind of lame. Just make sure it got called somehow.
149 self.assertTrue(called)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400150
151
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400152 def _load_verify_locations_test(self, *args):
Rick Deanb1ccd562009-07-09 23:52:39 -0500153 (server, client) = socket_pair()
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400154
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400155 clientContext = Context(TLSv1_METHOD)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400156 clientContext.load_verify_locations(*args)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400157 # Require that the server certificate verify properly or the
158 # connection will fail.
159 clientContext.set_verify(
160 VERIFY_PEER,
161 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
162
163 clientSSL = Connection(clientContext, client)
164 clientSSL.set_connect_state()
165
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400166 serverContext = Context(TLSv1_METHOD)
167 serverContext.use_certificate(
168 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
169 serverContext.use_privatekey(
170 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
171
172 serverSSL = Connection(serverContext, server)
173 serverSSL.set_accept_state()
174
175 for i in range(3):
176 for ssl in clientSSL, serverSSL:
177 try:
178 # Without load_verify_locations above, the handshake
179 # will fail:
180 # Error: [('SSL routines', 'SSL3_GET_SERVER_CERTIFICATE',
181 # 'certificate verify failed')]
182 ssl.do_handshake()
183 except WantReadError:
184 pass
185
186 cert = clientSSL.get_peer_certificate()
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400187 self.assertEqual(cert.get_subject().CN, 'Testing Root CA')
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400188
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400189 def test_load_verify_file(self):
190 """
191 L{Context.load_verify_locations} accepts a file name and uses the
192 certificates within for verification purposes.
193 """
194 cafile = self.mktemp()
195 fObj = file(cafile, 'w')
196 fObj.write(cleartextCertificatePEM)
197 fObj.close()
198
199 self._load_verify_locations_test(cafile)
200
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400201
202 def test_load_verify_invalid_file(self):
203 """
204 L{Context.load_verify_locations} raises L{Error} when passed a
205 non-existent cafile.
206 """
207 clientContext = Context(TLSv1_METHOD)
208 self.assertRaises(
209 Error, clientContext.load_verify_locations, self.mktemp())
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400210
211
212 def test_load_verify_directory(self):
213 """
214 L{Context.load_verify_locations} accepts a directory name and uses
215 the certificates within for verification purposes.
216 """
217 capath = self.mktemp()
218 makedirs(capath)
219 cafile = join(capath, 'cert.pem')
220 fObj = file(cafile, 'w')
221 fObj.write(cleartextCertificatePEM)
222 fObj.close()
223
224 # Hash value computed manually with c_rehash to avoid depending on
225 # c_rehash in the test suite.
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400226 symlink('cert.pem', join(capath, 'c7adac82.0'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400227
228 self._load_verify_locations_test(None, capath)
229
230
231 def test_set_default_verify_paths(self):
232 """
233 L{Context.set_default_verify_paths} causes the platform-specific CA
234 certificate locations to be used for verification purposes.
235 """
236 # Testing this requires a server with a certificate signed by one of
237 # the CAs in the platform CA location. Getting one of those costs
238 # money. Fortunately (or unfortunately, depending on your
239 # perspective), it's easy to think of a public server on the
240 # internet which has such a certificate. Connecting to the network
241 # in a unit test is bad, but it's the only way I can think of to
242 # really test this. -exarkun
243
244 # Arg, verisign.com doesn't speak TLSv1
245 context = Context(SSLv3_METHOD)
246 context.set_default_verify_paths()
247 context.set_verify(
248 VERIFY_PEER,
249 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
250
251 client = socket()
252 client.connect(('verisign.com', 443))
253 clientSSL = Connection(context, client)
254 clientSSL.set_connect_state()
255 clientSSL.do_handshake()
256 clientSSL.send('GET / HTTP/1.0\r\n\r\n')
257 self.assertTrue(clientSSL.recv(1024))
Jean-Paul Calderone52f0d8b2009-03-07 09:10:19 -0500258 if platform == "darwin":
Jean-Paul Calderone1d287e52009-03-07 09:09:07 -0500259 test_set_default_verify_paths.todo = (
260 "set_default_verify_paths appears not to work on OS X - a "
261 "problem with the supplied OpenSSL, perhaps?")
Jean-Paul Calderone9eadb962008-09-07 21:20:44 -0400262
263
264 def test_set_default_verify_paths_signature(self):
265 """
266 L{Context.set_default_verify_paths} takes no arguments and raises
267 L{TypeError} if given any.
268 """
269 context = Context(TLSv1_METHOD)
270 self.assertRaises(TypeError, context.set_default_verify_paths, None)
271 self.assertRaises(TypeError, context.set_default_verify_paths, 1)
272 self.assertRaises(TypeError, context.set_default_verify_paths, "")
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -0500273
274
275
276class ConstantsTests(TestCase):
277 """
278 Tests for the values of constants exposed in L{OpenSSL.SSL}.
279
280 These are values defined by OpenSSL intended only to be used as flags to
281 OpenSSL APIs. The only assertions it seems can be made about them is
282 their values.
283 """
Jean-Paul Calderoned811b682008-12-28 22:59:15 -0500284 # unittest.TestCase has no skip mechanism
285 if OP_NO_QUERY_MTU is not None:
286 def test_op_no_query_mtu(self):
287 """
288 The value of L{OpenSSL.SSL.OP_NO_QUERY_MTU} is 0x1000, the value of
289 I{SSL_OP_NO_QUERY_MTU} defined by I{openssl/ssl.h}.
290 """
291 self.assertEqual(OP_NO_QUERY_MTU, 0x1000)
292 else:
293 "OP_NO_QUERY_MTU unavailable - OpenSSL version may be too old"
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -0500294
295
Jean-Paul Calderoned811b682008-12-28 22:59:15 -0500296 if OP_COOKIE_EXCHANGE is not None:
297 def test_op_cookie_exchange(self):
298 """
299 The value of L{OpenSSL.SSL.OP_COOKIE_EXCHANGE} is 0x2000, the value
300 of I{SSL_OP_COOKIE_EXCHANGE} defined by I{openssl/ssl.h}.
301 """
302 self.assertEqual(OP_COOKIE_EXCHANGE, 0x2000)
303 else:
304 "OP_COOKIE_EXCHANGE unavailable - OpenSSL version may be too old"
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -0500305
306
Jean-Paul Calderoned811b682008-12-28 22:59:15 -0500307 if OP_NO_TICKET is not None:
308 def test_op_no_ticket(self):
309 """
310 The value of L{OpenSSL.SSL.OP_NO_TICKET} is 0x4000, the value of
311 I{SSL_OP_NO_TICKET} defined by I{openssl/ssl.h}.
312 """
313 self.assertEqual(OP_NO_TICKET, 0x4000)
314 else:
315 "OP_NO_TICKET unavailable - OpenSSL version may be too old"
Rick Dean5b7b6372009-04-01 11:34:06 -0500316
317
Jean-Paul Calderoneeeee26a2009-04-27 11:24:30 -0400318
Rick Deanb71c0d22009-04-01 14:09:23 -0500319def verify_cb(conn, cert, errnum, depth, ok):
320 return ok
321
Jean-Paul Calderone958299e2009-04-27 12:59:12 -0400322class MemoryBIOTests(TestCase):
Rick Deanb71c0d22009-04-01 14:09:23 -0500323 """
Jean-Paul Calderone958299e2009-04-27 12:59:12 -0400324 Tests for L{OpenSSL.SSL.Connection} using a memory BIO.
Rick Deanb71c0d22009-04-01 14:09:23 -0500325 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -0400326 def _server(self, sock):
327 """
328 Create a new server-side SSL L{Connection} object wrapped around
329 C{sock}.
330 """
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -0400331 # Create the server side Connection. This is mostly setup boilerplate
332 # - use TLSv1, use a particular certificate, etc.
333 server_ctx = Context(TLSv1_METHOD)
334 server_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE )
335 server_ctx.set_verify(VERIFY_PEER|VERIFY_FAIL_IF_NO_PEER_CERT|VERIFY_CLIENT_ONCE, verify_cb)
336 server_store = server_ctx.get_cert_store()
337 server_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
338 server_ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
339 server_ctx.check_privatekey()
340 server_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -0500341 # Here the Connection is actually created. If None is passed as the 2nd
342 # parameter, it indicates a memory BIO should be created.
343 server_conn = Connection(server_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -0400344 server_conn.set_accept_state()
345 return server_conn
346
347
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -0400348 def _client(self, sock):
349 """
350 Create a new client-side SSL L{Connection} object wrapped around
351 C{sock}.
352 """
353 # Now create the client side Connection. Similar boilerplate to the
354 # above.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -0400355 client_ctx = Context(TLSv1_METHOD)
356 client_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE )
357 client_ctx.set_verify(VERIFY_PEER|VERIFY_FAIL_IF_NO_PEER_CERT|VERIFY_CLIENT_ONCE, verify_cb)
358 client_store = client_ctx.get_cert_store()
359 client_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, client_key_pem))
360 client_ctx.use_certificate(load_certificate(FILETYPE_PEM, client_cert_pem))
361 client_ctx.check_privatekey()
362 client_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -0500363 client_conn = Connection(client_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -0400364 client_conn.set_connect_state()
365 return client_conn
366
367
Jean-Paul Calderone958299e2009-04-27 12:59:12 -0400368 def _loopback(self, client_conn, server_conn):
369 """
370 Try to read application bytes from each of the two L{Connection}
371 objects. Copy bytes back and forth between their send/receive buffers
372 for as long as there is anything to copy. When there is nothing more
373 to copy, return C{None}. If one of them actually manages to deliver
374 some application bytes, return a two-tuple of the connection from which
375 the bytes were read and the bytes themselves.
376 """
377 wrote = True
378 while wrote:
379 # Loop until neither side has anything to say
380 wrote = False
381
382 # Copy stuff from each side's send buffer to the other side's
383 # receive buffer.
384 for (read, write) in [(client_conn, server_conn),
385 (server_conn, client_conn)]:
386
387 # Give the side a chance to generate some more bytes, or
388 # succeed.
389 try:
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -0400390 bytes = read.recv(2 ** 16)
Jean-Paul Calderone958299e2009-04-27 12:59:12 -0400391 except WantReadError:
392 # It didn't succeed, so we'll hope it generated some
393 # output.
394 pass
395 else:
396 # It did succeed, so we'll stop now and let the caller deal
397 # with it.
398 return (read, bytes)
399
400 while True:
401 # Keep copying as long as there's more stuff there.
402 try:
403 dirty = read.bio_read(4096)
404 except WantReadError:
405 # Okay, nothing more waiting to be sent. Stop
406 # processing this send buffer.
407 break
408 else:
409 # Keep track of the fact that someone generated some
410 # output.
411 wrote = True
412 write.bio_write(dirty)
413
414
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -0400415 def test_memoryConnect(self):
Jean-Paul Calderone958299e2009-04-27 12:59:12 -0400416 """
417 Two L{Connection}s which use memory BIOs can be manually connected by
418 reading from the output of each and writing those bytes to the input of
419 the other and in this way establish a connection and exchange
420 application-level bytes with each other.
421 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -0400422 server_conn = self._server(None)
423 client_conn = self._client(None)
Rick Deanb71c0d22009-04-01 14:09:23 -0500424
Jean-Paul Calderone958299e2009-04-27 12:59:12 -0400425 # There should be no key or nonces yet.
426 self.assertIdentical(server_conn.master_key(), None)
427 self.assertIdentical(server_conn.client_random(), None)
428 self.assertIdentical(server_conn.server_random(), None)
Rick Deanb71c0d22009-04-01 14:09:23 -0500429
Jean-Paul Calderone958299e2009-04-27 12:59:12 -0400430 # First, the handshake needs to happen. We'll deliver bytes back and
431 # forth between the client and server until neither of them feels like
432 # speaking any more.
433 self.assertIdentical(self._loopback(client_conn, server_conn), None)
434
435 # Now that the handshake is done, there should be a key and nonces.
436 self.assertNotIdentical(server_conn.master_key(), None)
437 self.assertNotIdentical(server_conn.client_random(), None)
438 self.assertNotIdentical(server_conn.server_random(), None)
Jean-Paul Calderone6c051e62009-07-05 13:50:34 -0400439 self.assertEquals(server_conn.client_random(), client_conn.client_random())
440 self.assertEquals(server_conn.server_random(), client_conn.server_random())
441 self.assertNotEquals(server_conn.client_random(), server_conn.server_random())
442 self.assertNotEquals(client_conn.client_random(), client_conn.server_random())
Jean-Paul Calderone958299e2009-04-27 12:59:12 -0400443
444 # Here are the bytes we'll try to send.
Rick Deanb71c0d22009-04-01 14:09:23 -0500445 important_message = 'One if by land, two if by sea.'
446
Jean-Paul Calderone958299e2009-04-27 12:59:12 -0400447 server_conn.write(important_message)
448 self.assertEquals(
449 self._loopback(client_conn, server_conn),
450 (client_conn, important_message))
451
452 client_conn.write(important_message[::-1])
453 self.assertEquals(
454 self._loopback(client_conn, server_conn),
455 (server_conn, important_message[::-1]))
Rick Deanb71c0d22009-04-01 14:09:23 -0500456
457
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -0400458 def test_socketConnect(self):
Rick Deanb1ccd562009-07-09 23:52:39 -0500459 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -0400460 Just like L{test_memoryConnect} but with an actual socket.
461
462 This is primarily to rule out the memory BIO code as the source of
463 any problems encountered while passing data over a L{Connection} (if
464 this test fails, there must be a problem outside the memory BIO
465 code, as no memory BIO is involved here). Even though this isn't a
466 memory BIO test, it's convenient to have it here.
Rick Deanb1ccd562009-07-09 23:52:39 -0500467 """
468 (server, client) = socket_pair()
469
470 # Let the encryption begin...
471 client_conn = self._client(client)
Rick Deanb1ccd562009-07-09 23:52:39 -0500472 server_conn = self._server(server)
Jean-Paul Calderone7903cbd2009-07-16 12:23:34 -0400473
Rick Deanb1ccd562009-07-09 23:52:39 -0500474 # Establish the connection
475 established = False
476 while not established:
477 established = True # assume the best
478 for ssl in client_conn, server_conn:
479 try:
480 # Generally a recv() or send() could also work instead
481 # of do_handshake(), and we would stop on the first
482 # non-exception.
483 ssl.do_handshake()
484 except WantReadError:
485 established = False
486
487 important_message = "Help me Obi Wan Kenobi, you're my only hope."
488 client_conn.send(important_message)
489 msg = server_conn.recv(1024)
490 self.assertEqual(msg, important_message)
491
492 # Again in the other direction, just for fun.
493 important_message = important_message[::-1]
494 server_conn.send(important_message)
495 msg = client_conn.recv(1024)
496 self.assertEqual(msg, important_message)
497
498
Jean-Paul Calderonefc4ed0f2009-04-27 11:51:27 -0400499 def test_socketOverridesMemory(self):
Rick Deanb71c0d22009-04-01 14:09:23 -0500500 """
501 Test that L{OpenSSL.SSL.bio_read} and L{OpenSSL.SSL.bio_write} don't
502 work on L{OpenSSL.SSL.Connection}() that use sockets.
503 """
504 context = Context(SSLv3_METHOD)
505 client = socket()
506 clientSSL = Connection(context, client)
507 self.assertRaises( TypeError, clientSSL.bio_read, 100)
508 self.assertRaises( TypeError, clientSSL.bio_write, "foo")
Jean-Paul Calderone07acf3f2009-05-05 13:23:28 -0400509 self.assertRaises( TypeError, clientSSL.bio_shutdown )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -0400510
511
512 def test_outgoingOverflow(self):
513 """
514 If more bytes than can be written to the memory BIO are passed to
515 L{Connection.send} at once, the number of bytes which were written is
516 returned and that many bytes from the beginning of the input can be
517 read from the other end of the connection.
518 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -0400519 server = self._server(None)
520 client = self._client(None)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -0400521
522 self._loopback(client, server)
523
524 size = 2 ** 15
525 sent = client.send("x" * size)
526 # Sanity check. We're trying to test what happens when the entire
527 # input can't be sent. If the entire input was sent, this test is
528 # meaningless.
529 self.assertTrue(sent < size)
530
531 receiver, received = self._loopback(client, server)
532 self.assertIdentical(receiver, server)
533
534 # We can rely on all of these bytes being received at once because
535 # _loopback passes 2 ** 16 to recv - more than 2 ** 15.
536 self.assertEquals(len(received), sent)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -0400537
538
539 def test_shutdown(self):
540 """
541 L{Connection.bio_shutdown} signals the end of the data stream from
542 which the L{Connection} reads.
543 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -0400544 server = self._server(None)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -0400545 server.bio_shutdown()
546 e = self.assertRaises(Error, server.recv, 1024)
547 # We don't want WantReadError or ZeroReturnError or anything - it's a
548 # handshake failure.
549 self.assertEquals(e.__class__, Error)
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -0400550
551
552
553if __name__ == '__main__':
554 main()