blob: 5d386a997bb709ff8545c680291880472fff9498 [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 Calderonea65cf6c2009-07-19 10:26:52 -04009from os import makedirs
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -040010from 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
Rick Deane15b1472009-07-09 15:53:42 -050014from OpenSSL.SSL import WantReadError, Context, ContextType, Connection, ConnectionType, Error
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -040015from OpenSSL.SSL import SSLv2_METHOD, SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD
Jean-Paul Calderone68649052009-07-17 21:14:27 -040016from OpenSSL.SSL import OP_NO_SSLv2, OP_NO_SSLv3, OP_SINGLE_DH_USE
Rick Deanb71c0d22009-04-01 14:09:23 -050017from 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 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -040037 Establish and return a pair of network sockets connected to each other.
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -040038 """
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)
Jean-Paul Calderonef23c5d92009-07-23 17:58:15 -040045 client.connect_ex(("127.0.0.1", port.getsockname()[1]))
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
Rick Deane15b1472009-07-09 15:53:42 -050080 def test_type(self):
81 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -040082 L{Context} and L{ContextType} refer to the same type object and can be
83 used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -050084 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -040085 self.assertIdentical(Context, ContextType)
86 self.assertConsistentType(Context, 'Context', TLSv1_METHOD)
Rick Deane15b1472009-07-09 15:53:42 -050087
88
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -040089 def test_use_privatekey(self):
90 """
91 L{Context.use_privatekey} takes an L{OpenSSL.crypto.PKey} instance.
92 """
93 key = PKey()
94 key.generate_key(TYPE_RSA, 128)
95 ctx = Context(TLSv1_METHOD)
96 ctx.use_privatekey(key)
97 self.assertRaises(TypeError, ctx.use_privatekey, "")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -040098
99
100 def test_set_passwd_cb(self):
101 """
102 L{Context.set_passwd_cb} accepts a callable which will be invoked when
103 a private key is loaded from an encrypted PEM.
104 """
105 key = PKey()
106 key.generate_key(TYPE_RSA, 128)
107 pemFile = self.mktemp()
108 fObj = file(pemFile, 'w')
109 passphrase = "foobar"
110 fObj.write(dump_privatekey(FILETYPE_PEM, key, "blowfish", passphrase))
111 fObj.close()
112
113 calledWith = []
114 def passphraseCallback(maxlen, verify, extra):
115 calledWith.append((maxlen, verify, extra))
116 return passphrase
117 context = Context(TLSv1_METHOD)
118 context.set_passwd_cb(passphraseCallback)
119 context.use_privatekey_file(pemFile)
120 self.assertTrue(len(calledWith), 1)
121 self.assertTrue(isinstance(calledWith[0][0], int))
122 self.assertTrue(isinstance(calledWith[0][1], int))
123 self.assertEqual(calledWith[0][2], None)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400124
125
126 def test_set_info_callback(self):
127 """
128 L{Context.set_info_callback} accepts a callable which will be invoked
129 when certain information about an SSL connection is available.
130 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500131 (server, client) = socket_pair()
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400132
133 clientSSL = Connection(Context(TLSv1_METHOD), client)
134 clientSSL.set_connect_state()
135
136 called = []
137 def info(conn, where, ret):
138 called.append((conn, where, ret))
139 context = Context(TLSv1_METHOD)
140 context.set_info_callback(info)
141 context.use_certificate(
142 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
143 context.use_privatekey(
144 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
145
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400146 serverSSL = Connection(context, server)
147 serverSSL.set_accept_state()
148
149 while not called:
150 for ssl in clientSSL, serverSSL:
151 try:
152 ssl.do_handshake()
153 except WantReadError:
154 pass
155
156 # Kind of lame. Just make sure it got called somehow.
157 self.assertTrue(called)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400158
159
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400160 def _load_verify_locations_test(self, *args):
Rick Deanb1ccd562009-07-09 23:52:39 -0500161 (server, client) = socket_pair()
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400162
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400163 clientContext = Context(TLSv1_METHOD)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400164 clientContext.load_verify_locations(*args)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400165 # Require that the server certificate verify properly or the
166 # connection will fail.
167 clientContext.set_verify(
168 VERIFY_PEER,
169 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
170
171 clientSSL = Connection(clientContext, client)
172 clientSSL.set_connect_state()
173
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400174 serverContext = Context(TLSv1_METHOD)
175 serverContext.use_certificate(
176 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
177 serverContext.use_privatekey(
178 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
179
180 serverSSL = Connection(serverContext, server)
181 serverSSL.set_accept_state()
182
183 for i in range(3):
184 for ssl in clientSSL, serverSSL:
185 try:
186 # Without load_verify_locations above, the handshake
187 # will fail:
188 # Error: [('SSL routines', 'SSL3_GET_SERVER_CERTIFICATE',
189 # 'certificate verify failed')]
190 ssl.do_handshake()
191 except WantReadError:
192 pass
193
194 cert = clientSSL.get_peer_certificate()
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400195 self.assertEqual(cert.get_subject().CN, 'Testing Root CA')
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400196
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400197 def test_load_verify_file(self):
198 """
199 L{Context.load_verify_locations} accepts a file name and uses the
200 certificates within for verification purposes.
201 """
202 cafile = self.mktemp()
203 fObj = file(cafile, 'w')
204 fObj.write(cleartextCertificatePEM)
205 fObj.close()
206
207 self._load_verify_locations_test(cafile)
208
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400209
210 def test_load_verify_invalid_file(self):
211 """
212 L{Context.load_verify_locations} raises L{Error} when passed a
213 non-existent cafile.
214 """
215 clientContext = Context(TLSv1_METHOD)
216 self.assertRaises(
217 Error, clientContext.load_verify_locations, self.mktemp())
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400218
219
220 def test_load_verify_directory(self):
221 """
222 L{Context.load_verify_locations} accepts a directory name and uses
223 the certificates within for verification purposes.
224 """
225 capath = self.mktemp()
226 makedirs(capath)
Jean-Paul Calderonea65cf6c2009-07-19 10:26:52 -0400227 # Hash value computed manually with c_rehash to avoid depending on
228 # c_rehash in the test suite.
229 cafile = join(capath, 'c7adac82.0')
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400230 fObj = file(cafile, 'w')
231 fObj.write(cleartextCertificatePEM)
232 fObj.close()
233
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400234 self._load_verify_locations_test(None, capath)
235
236
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400237 if platform in ("darwin", "win32"):
238 "set_default_verify_paths appears not to work on OS X or Windows"
239 "See LP#404343 and LP#404344."
240 else:
241 def test_set_default_verify_paths(self):
242 """
243 L{Context.set_default_verify_paths} causes the platform-specific CA
244 certificate locations to be used for verification purposes.
245 """
246 # Testing this requires a server with a certificate signed by one of
247 # the CAs in the platform CA location. Getting one of those costs
248 # money. Fortunately (or unfortunately, depending on your
249 # perspective), it's easy to think of a public server on the
250 # internet which has such a certificate. Connecting to the network
251 # in a unit test is bad, but it's the only way I can think of to
252 # really test this. -exarkun
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400253
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400254 # Arg, verisign.com doesn't speak TLSv1
255 context = Context(SSLv3_METHOD)
256 context.set_default_verify_paths()
257 context.set_verify(
258 VERIFY_PEER,
259 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400260
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400261 client = socket()
262 client.connect(('verisign.com', 443))
263 clientSSL = Connection(context, client)
264 clientSSL.set_connect_state()
265 clientSSL.do_handshake()
266 clientSSL.send('GET / HTTP/1.0\r\n\r\n')
267 self.assertTrue(clientSSL.recv(1024))
Jean-Paul Calderone9eadb962008-09-07 21:20:44 -0400268
269
270 def test_set_default_verify_paths_signature(self):
271 """
272 L{Context.set_default_verify_paths} takes no arguments and raises
273 L{TypeError} if given any.
274 """
275 context = Context(TLSv1_METHOD)
276 self.assertRaises(TypeError, context.set_default_verify_paths, None)
277 self.assertRaises(TypeError, context.set_default_verify_paths, 1)
278 self.assertRaises(TypeError, context.set_default_verify_paths, "")
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -0500279
280
281
Rick Deane15b1472009-07-09 15:53:42 -0500282class ConnectionTests(TestCase):
283 """
284 Unit tests for L{OpenSSL.SSL.Connection}.
285 """
286 def test_type(self):
287 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400288 L{Connection} and L{ConnectionType} refer to the same type object and
289 can be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -0500290 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400291 self.assertIdentical(Connection, ConnectionType)
Rick Deane15b1472009-07-09 15:53:42 -0500292 ctx = Context(TLSv1_METHOD)
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400293 self.assertConsistentType(Connection, 'Connection', ctx, None)
Rick Deane15b1472009-07-09 15:53:42 -0500294
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400295
296
297class ErrorTests(TestCase):
298 """
299 Unit tests for L{OpenSSL.SSL.Error}.
300 """
301 def test_type(self):
302 """
303 L{Error} is an exception type.
304 """
305 self.assertTrue(issubclass(Error, Exception))
Rick Deane15b1472009-07-09 15:53:42 -0500306 self.assertEqual(Error.__name__, 'Error')
Rick Deane15b1472009-07-09 15:53:42 -0500307
308
309
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -0500310class ConstantsTests(TestCase):
311 """
312 Tests for the values of constants exposed in L{OpenSSL.SSL}.
313
314 These are values defined by OpenSSL intended only to be used as flags to
315 OpenSSL APIs. The only assertions it seems can be made about them is
316 their values.
317 """
Jean-Paul Calderoned811b682008-12-28 22:59:15 -0500318 # unittest.TestCase has no skip mechanism
319 if OP_NO_QUERY_MTU is not None:
320 def test_op_no_query_mtu(self):
321 """
322 The value of L{OpenSSL.SSL.OP_NO_QUERY_MTU} is 0x1000, the value of
323 I{SSL_OP_NO_QUERY_MTU} defined by I{openssl/ssl.h}.
324 """
325 self.assertEqual(OP_NO_QUERY_MTU, 0x1000)
326 else:
327 "OP_NO_QUERY_MTU unavailable - OpenSSL version may be too old"
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -0500328
329
Jean-Paul Calderoned811b682008-12-28 22:59:15 -0500330 if OP_COOKIE_EXCHANGE is not None:
331 def test_op_cookie_exchange(self):
332 """
333 The value of L{OpenSSL.SSL.OP_COOKIE_EXCHANGE} is 0x2000, the value
334 of I{SSL_OP_COOKIE_EXCHANGE} defined by I{openssl/ssl.h}.
335 """
336 self.assertEqual(OP_COOKIE_EXCHANGE, 0x2000)
337 else:
338 "OP_COOKIE_EXCHANGE unavailable - OpenSSL version may be too old"
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -0500339
340
Jean-Paul Calderoned811b682008-12-28 22:59:15 -0500341 if OP_NO_TICKET is not None:
342 def test_op_no_ticket(self):
343 """
344 The value of L{OpenSSL.SSL.OP_NO_TICKET} is 0x4000, the value of
345 I{SSL_OP_NO_TICKET} defined by I{openssl/ssl.h}.
346 """
347 self.assertEqual(OP_NO_TICKET, 0x4000)
348 else:
349 "OP_NO_TICKET unavailable - OpenSSL version may be too old"
Rick Dean5b7b6372009-04-01 11:34:06 -0500350
351
Jean-Paul Calderoneeeee26a2009-04-27 11:24:30 -0400352
Rick Deanb71c0d22009-04-01 14:09:23 -0500353def verify_cb(conn, cert, errnum, depth, ok):
354 return ok
355
Jean-Paul Calderone958299e2009-04-27 12:59:12 -0400356class MemoryBIOTests(TestCase):
Rick Deanb71c0d22009-04-01 14:09:23 -0500357 """
Jean-Paul Calderone958299e2009-04-27 12:59:12 -0400358 Tests for L{OpenSSL.SSL.Connection} using a memory BIO.
Rick Deanb71c0d22009-04-01 14:09:23 -0500359 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -0400360 def _server(self, sock):
361 """
362 Create a new server-side SSL L{Connection} object wrapped around
363 C{sock}.
364 """
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -0400365 # Create the server side Connection. This is mostly setup boilerplate
366 # - use TLSv1, use a particular certificate, etc.
367 server_ctx = Context(TLSv1_METHOD)
368 server_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE )
369 server_ctx.set_verify(VERIFY_PEER|VERIFY_FAIL_IF_NO_PEER_CERT|VERIFY_CLIENT_ONCE, verify_cb)
370 server_store = server_ctx.get_cert_store()
371 server_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
372 server_ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
373 server_ctx.check_privatekey()
374 server_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -0500375 # Here the Connection is actually created. If None is passed as the 2nd
376 # parameter, it indicates a memory BIO should be created.
377 server_conn = Connection(server_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -0400378 server_conn.set_accept_state()
379 return server_conn
380
381
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -0400382 def _client(self, sock):
383 """
384 Create a new client-side SSL L{Connection} object wrapped around
385 C{sock}.
386 """
387 # Now create the client side Connection. Similar boilerplate to the
388 # above.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -0400389 client_ctx = Context(TLSv1_METHOD)
390 client_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE )
391 client_ctx.set_verify(VERIFY_PEER|VERIFY_FAIL_IF_NO_PEER_CERT|VERIFY_CLIENT_ONCE, verify_cb)
392 client_store = client_ctx.get_cert_store()
393 client_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, client_key_pem))
394 client_ctx.use_certificate(load_certificate(FILETYPE_PEM, client_cert_pem))
395 client_ctx.check_privatekey()
396 client_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -0500397 client_conn = Connection(client_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -0400398 client_conn.set_connect_state()
399 return client_conn
400
401
Jean-Paul Calderone958299e2009-04-27 12:59:12 -0400402 def _loopback(self, client_conn, server_conn):
403 """
404 Try to read application bytes from each of the two L{Connection}
405 objects. Copy bytes back and forth between their send/receive buffers
406 for as long as there is anything to copy. When there is nothing more
407 to copy, return C{None}. If one of them actually manages to deliver
408 some application bytes, return a two-tuple of the connection from which
409 the bytes were read and the bytes themselves.
410 """
411 wrote = True
412 while wrote:
413 # Loop until neither side has anything to say
414 wrote = False
415
416 # Copy stuff from each side's send buffer to the other side's
417 # receive buffer.
418 for (read, write) in [(client_conn, server_conn),
419 (server_conn, client_conn)]:
420
421 # Give the side a chance to generate some more bytes, or
422 # succeed.
423 try:
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -0400424 bytes = read.recv(2 ** 16)
Jean-Paul Calderone958299e2009-04-27 12:59:12 -0400425 except WantReadError:
426 # It didn't succeed, so we'll hope it generated some
427 # output.
428 pass
429 else:
430 # It did succeed, so we'll stop now and let the caller deal
431 # with it.
432 return (read, bytes)
433
434 while True:
435 # Keep copying as long as there's more stuff there.
436 try:
437 dirty = read.bio_read(4096)
438 except WantReadError:
439 # Okay, nothing more waiting to be sent. Stop
440 # processing this send buffer.
441 break
442 else:
443 # Keep track of the fact that someone generated some
444 # output.
445 wrote = True
446 write.bio_write(dirty)
447
448
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -0400449 def test_memoryConnect(self):
Jean-Paul Calderone958299e2009-04-27 12:59:12 -0400450 """
451 Two L{Connection}s which use memory BIOs can be manually connected by
452 reading from the output of each and writing those bytes to the input of
453 the other and in this way establish a connection and exchange
454 application-level bytes with each other.
455 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -0400456 server_conn = self._server(None)
457 client_conn = self._client(None)
Rick Deanb71c0d22009-04-01 14:09:23 -0500458
Jean-Paul Calderone958299e2009-04-27 12:59:12 -0400459 # There should be no key or nonces yet.
460 self.assertIdentical(server_conn.master_key(), None)
461 self.assertIdentical(server_conn.client_random(), None)
462 self.assertIdentical(server_conn.server_random(), None)
Rick Deanb71c0d22009-04-01 14:09:23 -0500463
Jean-Paul Calderone958299e2009-04-27 12:59:12 -0400464 # First, the handshake needs to happen. We'll deliver bytes back and
465 # forth between the client and server until neither of them feels like
466 # speaking any more.
467 self.assertIdentical(self._loopback(client_conn, server_conn), None)
468
469 # Now that the handshake is done, there should be a key and nonces.
470 self.assertNotIdentical(server_conn.master_key(), None)
471 self.assertNotIdentical(server_conn.client_random(), None)
472 self.assertNotIdentical(server_conn.server_random(), None)
Jean-Paul Calderone6c051e62009-07-05 13:50:34 -0400473 self.assertEquals(server_conn.client_random(), client_conn.client_random())
474 self.assertEquals(server_conn.server_random(), client_conn.server_random())
475 self.assertNotEquals(server_conn.client_random(), server_conn.server_random())
476 self.assertNotEquals(client_conn.client_random(), client_conn.server_random())
Jean-Paul Calderone958299e2009-04-27 12:59:12 -0400477
478 # Here are the bytes we'll try to send.
Rick Deanb71c0d22009-04-01 14:09:23 -0500479 important_message = 'One if by land, two if by sea.'
480
Jean-Paul Calderone958299e2009-04-27 12:59:12 -0400481 server_conn.write(important_message)
482 self.assertEquals(
483 self._loopback(client_conn, server_conn),
484 (client_conn, important_message))
485
486 client_conn.write(important_message[::-1])
487 self.assertEquals(
488 self._loopback(client_conn, server_conn),
489 (server_conn, important_message[::-1]))
Rick Deanb71c0d22009-04-01 14:09:23 -0500490
491
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -0400492 def test_socketConnect(self):
Rick Deanb1ccd562009-07-09 23:52:39 -0500493 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -0400494 Just like L{test_memoryConnect} but with an actual socket.
495
496 This is primarily to rule out the memory BIO code as the source of
497 any problems encountered while passing data over a L{Connection} (if
498 this test fails, there must be a problem outside the memory BIO
499 code, as no memory BIO is involved here). Even though this isn't a
500 memory BIO test, it's convenient to have it here.
Rick Deanb1ccd562009-07-09 23:52:39 -0500501 """
502 (server, client) = socket_pair()
503
504 # Let the encryption begin...
505 client_conn = self._client(client)
Rick Deanb1ccd562009-07-09 23:52:39 -0500506 server_conn = self._server(server)
Jean-Paul Calderone7903cbd2009-07-16 12:23:34 -0400507
Rick Deanb1ccd562009-07-09 23:52:39 -0500508 # Establish the connection
509 established = False
510 while not established:
511 established = True # assume the best
512 for ssl in client_conn, server_conn:
513 try:
514 # Generally a recv() or send() could also work instead
515 # of do_handshake(), and we would stop on the first
516 # non-exception.
517 ssl.do_handshake()
518 except WantReadError:
519 established = False
520
521 important_message = "Help me Obi Wan Kenobi, you're my only hope."
522 client_conn.send(important_message)
523 msg = server_conn.recv(1024)
524 self.assertEqual(msg, important_message)
525
526 # Again in the other direction, just for fun.
527 important_message = important_message[::-1]
528 server_conn.send(important_message)
529 msg = client_conn.recv(1024)
530 self.assertEqual(msg, important_message)
531
532
Jean-Paul Calderonefc4ed0f2009-04-27 11:51:27 -0400533 def test_socketOverridesMemory(self):
Rick Deanb71c0d22009-04-01 14:09:23 -0500534 """
535 Test that L{OpenSSL.SSL.bio_read} and L{OpenSSL.SSL.bio_write} don't
536 work on L{OpenSSL.SSL.Connection}() that use sockets.
537 """
538 context = Context(SSLv3_METHOD)
539 client = socket()
540 clientSSL = Connection(context, client)
541 self.assertRaises( TypeError, clientSSL.bio_read, 100)
542 self.assertRaises( TypeError, clientSSL.bio_write, "foo")
Jean-Paul Calderone07acf3f2009-05-05 13:23:28 -0400543 self.assertRaises( TypeError, clientSSL.bio_shutdown )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -0400544
545
546 def test_outgoingOverflow(self):
547 """
548 If more bytes than can be written to the memory BIO are passed to
549 L{Connection.send} at once, the number of bytes which were written is
550 returned and that many bytes from the beginning of the input can be
551 read from the other end of the connection.
552 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -0400553 server = self._server(None)
554 client = self._client(None)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -0400555
556 self._loopback(client, server)
557
558 size = 2 ** 15
559 sent = client.send("x" * size)
560 # Sanity check. We're trying to test what happens when the entire
561 # input can't be sent. If the entire input was sent, this test is
562 # meaningless.
563 self.assertTrue(sent < size)
564
565 receiver, received = self._loopback(client, server)
566 self.assertIdentical(receiver, server)
567
568 # We can rely on all of these bytes being received at once because
569 # _loopback passes 2 ** 16 to recv - more than 2 ** 15.
570 self.assertEquals(len(received), sent)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -0400571
572
573 def test_shutdown(self):
574 """
575 L{Connection.bio_shutdown} signals the end of the data stream from
576 which the L{Connection} reads.
577 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -0400578 server = self._server(None)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -0400579 server.bio_shutdown()
580 e = self.assertRaises(Error, server.recv, 1024)
581 # We don't want WantReadError or ZeroReturnError or anything - it's a
582 # handshake failure.
583 self.assertEquals(e.__class__, Error)
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -0400584
585
586
587if __name__ == '__main__':
588 main()