blob: 6698e0218a3d04a2c9df59c4773cb9d39e2d6a18 [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
Ziga Seilnacht44611bf2009-08-31 20:49:30 +020013from OpenSSL import SSL
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -040014from OpenSSL.crypto import TYPE_RSA, FILETYPE_PEM, PKey, dump_privatekey, load_certificate, load_privatekey
Rick Deane15b1472009-07-09 15:53:42 -050015from OpenSSL.SSL import WantReadError, Context, ContextType, Connection, ConnectionType, Error
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -040016from OpenSSL.SSL import SSLv2_METHOD, SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD
Jean-Paul Calderone68649052009-07-17 21:14:27 -040017from OpenSSL.SSL import OP_NO_SSLv2, OP_NO_SSLv3, OP_SINGLE_DH_USE
Rick Deanb71c0d22009-04-01 14:09:23 -050018from OpenSSL.SSL import VERIFY_PEER, VERIFY_FAIL_IF_NO_PEER_CERT, VERIFY_CLIENT_ONCE
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -040019from OpenSSL.test.util import TestCase
Jean-Paul Calderone18808652009-07-05 12:54:05 -040020from OpenSSL.test.test_crypto import cleartextCertificatePEM, cleartextPrivateKeyPEM
Rick Dean94e46fd2009-07-18 14:51:24 -050021from 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 -050022try:
23 from OpenSSL.SSL import OP_NO_QUERY_MTU
24except ImportError:
25 OP_NO_QUERY_MTU = None
26try:
27 from OpenSSL.SSL import OP_COOKIE_EXCHANGE
28except ImportError:
29 OP_COOKIE_EXCHANGE = None
30try:
31 from OpenSSL.SSL import OP_NO_TICKET
32except ImportError:
33 OP_NO_TICKET = None
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -040034
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -040035
Rick Deanb1ccd562009-07-09 23:52:39 -050036def socket_pair():
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -040037 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -040038 Establish and return a pair of network sockets connected to each other.
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -040039 """
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)
Jean-Paul Calderonef23c5d92009-07-23 17:58:15 -040046 client.connect_ex(("127.0.0.1", port.getsockname()[1]))
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
Rick Deane15b1472009-07-09 15:53:42 -050081 def test_type(self):
82 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -040083 L{Context} and L{ContextType} refer to the same type object and can be
84 used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -050085 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -040086 self.assertIdentical(Context, ContextType)
87 self.assertConsistentType(Context, 'Context', TLSv1_METHOD)
Rick Deane15b1472009-07-09 15:53:42 -050088
89
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -040090 def test_use_privatekey(self):
91 """
92 L{Context.use_privatekey} takes an L{OpenSSL.crypto.PKey} instance.
93 """
94 key = PKey()
95 key.generate_key(TYPE_RSA, 128)
96 ctx = Context(TLSv1_METHOD)
97 ctx.use_privatekey(key)
98 self.assertRaises(TypeError, ctx.use_privatekey, "")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -040099
100
101 def test_set_passwd_cb(self):
102 """
103 L{Context.set_passwd_cb} accepts a callable which will be invoked when
104 a private key is loaded from an encrypted PEM.
105 """
106 key = PKey()
107 key.generate_key(TYPE_RSA, 128)
108 pemFile = self.mktemp()
109 fObj = file(pemFile, 'w')
110 passphrase = "foobar"
111 fObj.write(dump_privatekey(FILETYPE_PEM, key, "blowfish", passphrase))
112 fObj.close()
113
114 calledWith = []
115 def passphraseCallback(maxlen, verify, extra):
116 calledWith.append((maxlen, verify, extra))
117 return passphrase
118 context = Context(TLSv1_METHOD)
119 context.set_passwd_cb(passphraseCallback)
120 context.use_privatekey_file(pemFile)
121 self.assertTrue(len(calledWith), 1)
122 self.assertTrue(isinstance(calledWith[0][0], int))
123 self.assertTrue(isinstance(calledWith[0][1], int))
124 self.assertEqual(calledWith[0][2], None)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400125
126
127 def test_set_info_callback(self):
128 """
129 L{Context.set_info_callback} accepts a callable which will be invoked
130 when certain information about an SSL connection is available.
131 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500132 (server, client) = socket_pair()
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400133
134 clientSSL = Connection(Context(TLSv1_METHOD), client)
135 clientSSL.set_connect_state()
136
137 called = []
138 def info(conn, where, ret):
139 called.append((conn, where, ret))
140 context = Context(TLSv1_METHOD)
141 context.set_info_callback(info)
142 context.use_certificate(
143 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
144 context.use_privatekey(
145 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
146
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400147 serverSSL = Connection(context, server)
148 serverSSL.set_accept_state()
149
150 while not called:
151 for ssl in clientSSL, serverSSL:
152 try:
153 ssl.do_handshake()
154 except WantReadError:
155 pass
156
157 # Kind of lame. Just make sure it got called somehow.
158 self.assertTrue(called)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400159
160
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400161 def _load_verify_locations_test(self, *args):
Rick Deanb1ccd562009-07-09 23:52:39 -0500162 (server, client) = socket_pair()
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400163
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400164 clientContext = Context(TLSv1_METHOD)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400165 clientContext.load_verify_locations(*args)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400166 # Require that the server certificate verify properly or the
167 # connection will fail.
168 clientContext.set_verify(
169 VERIFY_PEER,
170 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
171
172 clientSSL = Connection(clientContext, client)
173 clientSSL.set_connect_state()
174
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400175 serverContext = Context(TLSv1_METHOD)
176 serverContext.use_certificate(
177 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
178 serverContext.use_privatekey(
179 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
180
181 serverSSL = Connection(serverContext, server)
182 serverSSL.set_accept_state()
183
184 for i in range(3):
185 for ssl in clientSSL, serverSSL:
186 try:
187 # Without load_verify_locations above, the handshake
188 # will fail:
189 # Error: [('SSL routines', 'SSL3_GET_SERVER_CERTIFICATE',
190 # 'certificate verify failed')]
191 ssl.do_handshake()
192 except WantReadError:
193 pass
194
195 cert = clientSSL.get_peer_certificate()
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400196 self.assertEqual(cert.get_subject().CN, 'Testing Root CA')
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400197
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400198 def test_load_verify_file(self):
199 """
200 L{Context.load_verify_locations} accepts a file name and uses the
201 certificates within for verification purposes.
202 """
203 cafile = self.mktemp()
204 fObj = file(cafile, 'w')
205 fObj.write(cleartextCertificatePEM)
206 fObj.close()
207
208 self._load_verify_locations_test(cafile)
209
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400210
211 def test_load_verify_invalid_file(self):
212 """
213 L{Context.load_verify_locations} raises L{Error} when passed a
214 non-existent cafile.
215 """
216 clientContext = Context(TLSv1_METHOD)
217 self.assertRaises(
218 Error, clientContext.load_verify_locations, self.mktemp())
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400219
220
221 def test_load_verify_directory(self):
222 """
223 L{Context.load_verify_locations} accepts a directory name and uses
224 the certificates within for verification purposes.
225 """
226 capath = self.mktemp()
227 makedirs(capath)
Jean-Paul Calderonea65cf6c2009-07-19 10:26:52 -0400228 # Hash value computed manually with c_rehash to avoid depending on
229 # c_rehash in the test suite.
230 cafile = join(capath, 'c7adac82.0')
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400231 fObj = file(cafile, 'w')
232 fObj.write(cleartextCertificatePEM)
233 fObj.close()
234
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400235 self._load_verify_locations_test(None, capath)
236
237
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400238 if platform in ("darwin", "win32"):
239 "set_default_verify_paths appears not to work on OS X or Windows"
240 "See LP#404343 and LP#404344."
241 else:
242 def test_set_default_verify_paths(self):
243 """
244 L{Context.set_default_verify_paths} causes the platform-specific CA
245 certificate locations to be used for verification purposes.
246 """
247 # Testing this requires a server with a certificate signed by one of
248 # the CAs in the platform CA location. Getting one of those costs
249 # money. Fortunately (or unfortunately, depending on your
250 # perspective), it's easy to think of a public server on the
251 # internet which has such a certificate. Connecting to the network
252 # in a unit test is bad, but it's the only way I can think of to
253 # really test this. -exarkun
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400254
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400255 # Arg, verisign.com doesn't speak TLSv1
256 context = Context(SSLv3_METHOD)
257 context.set_default_verify_paths()
258 context.set_verify(
Ziga Seilnacht44611bf2009-08-31 20:49:30 +0200259 VERIFY_PEER,
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400260 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400261
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400262 client = socket()
263 client.connect(('verisign.com', 443))
264 clientSSL = Connection(context, client)
265 clientSSL.set_connect_state()
266 clientSSL.do_handshake()
267 clientSSL.send('GET / HTTP/1.0\r\n\r\n')
268 self.assertTrue(clientSSL.recv(1024))
Jean-Paul Calderone9eadb962008-09-07 21:20:44 -0400269
270
271 def test_set_default_verify_paths_signature(self):
272 """
273 L{Context.set_default_verify_paths} takes no arguments and raises
274 L{TypeError} if given any.
275 """
276 context = Context(TLSv1_METHOD)
277 self.assertRaises(TypeError, context.set_default_verify_paths, None)
278 self.assertRaises(TypeError, context.set_default_verify_paths, 1)
279 self.assertRaises(TypeError, context.set_default_verify_paths, "")
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -0500280
281
282
Rick Deane15b1472009-07-09 15:53:42 -0500283class ConnectionTests(TestCase):
284 """
285 Unit tests for L{OpenSSL.SSL.Connection}.
286 """
287 def test_type(self):
288 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400289 L{Connection} and L{ConnectionType} refer to the same type object and
290 can be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -0500291 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400292 self.assertIdentical(Connection, ConnectionType)
Rick Deane15b1472009-07-09 15:53:42 -0500293 ctx = Context(TLSv1_METHOD)
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400294 self.assertConsistentType(Connection, 'Connection', ctx, None)
Rick Deane15b1472009-07-09 15:53:42 -0500295
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400296
297
298class ErrorTests(TestCase):
299 """
300 Unit tests for L{OpenSSL.SSL.Error}.
301 """
302 def test_type(self):
303 """
304 L{Error} is an exception type.
305 """
306 self.assertTrue(issubclass(Error, Exception))
Rick Deane15b1472009-07-09 15:53:42 -0500307 self.assertEqual(Error.__name__, 'Error')
Rick Deane15b1472009-07-09 15:53:42 -0500308
309
310
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -0500311class ConstantsTests(TestCase):
312 """
313 Tests for the values of constants exposed in L{OpenSSL.SSL}.
314
315 These are values defined by OpenSSL intended only to be used as flags to
316 OpenSSL APIs. The only assertions it seems can be made about them is
317 their values.
318 """
Jean-Paul Calderoned811b682008-12-28 22:59:15 -0500319 # unittest.TestCase has no skip mechanism
320 if OP_NO_QUERY_MTU is not None:
321 def test_op_no_query_mtu(self):
322 """
323 The value of L{OpenSSL.SSL.OP_NO_QUERY_MTU} is 0x1000, the value of
324 I{SSL_OP_NO_QUERY_MTU} defined by I{openssl/ssl.h}.
325 """
326 self.assertEqual(OP_NO_QUERY_MTU, 0x1000)
327 else:
328 "OP_NO_QUERY_MTU unavailable - OpenSSL version may be too old"
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -0500329
330
Jean-Paul Calderoned811b682008-12-28 22:59:15 -0500331 if OP_COOKIE_EXCHANGE is not None:
332 def test_op_cookie_exchange(self):
333 """
334 The value of L{OpenSSL.SSL.OP_COOKIE_EXCHANGE} is 0x2000, the value
335 of I{SSL_OP_COOKIE_EXCHANGE} defined by I{openssl/ssl.h}.
336 """
337 self.assertEqual(OP_COOKIE_EXCHANGE, 0x2000)
338 else:
339 "OP_COOKIE_EXCHANGE unavailable - OpenSSL version may be too old"
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -0500340
341
Jean-Paul Calderoned811b682008-12-28 22:59:15 -0500342 if OP_NO_TICKET is not None:
343 def test_op_no_ticket(self):
344 """
345 The value of L{OpenSSL.SSL.OP_NO_TICKET} is 0x4000, the value of
346 I{SSL_OP_NO_TICKET} defined by I{openssl/ssl.h}.
347 """
348 self.assertEqual(OP_NO_TICKET, 0x4000)
349 else:
350 "OP_NO_TICKET unavailable - OpenSSL version may be too old"
Rick Dean5b7b6372009-04-01 11:34:06 -0500351
352
Jean-Paul Calderoneeeee26a2009-04-27 11:24:30 -0400353
Rick Deanb71c0d22009-04-01 14:09:23 -0500354def verify_cb(conn, cert, errnum, depth, ok):
355 return ok
356
Jean-Paul Calderone958299e2009-04-27 12:59:12 -0400357class MemoryBIOTests(TestCase):
Rick Deanb71c0d22009-04-01 14:09:23 -0500358 """
Jean-Paul Calderone958299e2009-04-27 12:59:12 -0400359 Tests for L{OpenSSL.SSL.Connection} using a memory BIO.
Rick Deanb71c0d22009-04-01 14:09:23 -0500360 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -0400361 def _server(self, sock):
362 """
363 Create a new server-side SSL L{Connection} object wrapped around
364 C{sock}.
365 """
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -0400366 # Create the server side Connection. This is mostly setup boilerplate
367 # - use TLSv1, use a particular certificate, etc.
368 server_ctx = Context(TLSv1_METHOD)
369 server_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE )
370 server_ctx.set_verify(VERIFY_PEER|VERIFY_FAIL_IF_NO_PEER_CERT|VERIFY_CLIENT_ONCE, verify_cb)
371 server_store = server_ctx.get_cert_store()
372 server_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
373 server_ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
374 server_ctx.check_privatekey()
375 server_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -0500376 # Here the Connection is actually created. If None is passed as the 2nd
377 # parameter, it indicates a memory BIO should be created.
378 server_conn = Connection(server_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -0400379 server_conn.set_accept_state()
380 return server_conn
381
382
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -0400383 def _client(self, sock):
384 """
385 Create a new client-side SSL L{Connection} object wrapped around
386 C{sock}.
387 """
388 # Now create the client side Connection. Similar boilerplate to the
389 # above.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -0400390 client_ctx = Context(TLSv1_METHOD)
391 client_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE )
392 client_ctx.set_verify(VERIFY_PEER|VERIFY_FAIL_IF_NO_PEER_CERT|VERIFY_CLIENT_ONCE, verify_cb)
393 client_store = client_ctx.get_cert_store()
394 client_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, client_key_pem))
395 client_ctx.use_certificate(load_certificate(FILETYPE_PEM, client_cert_pem))
396 client_ctx.check_privatekey()
397 client_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -0500398 client_conn = Connection(client_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -0400399 client_conn.set_connect_state()
400 return client_conn
401
402
Jean-Paul Calderone958299e2009-04-27 12:59:12 -0400403 def _loopback(self, client_conn, server_conn):
404 """
405 Try to read application bytes from each of the two L{Connection}
406 objects. Copy bytes back and forth between their send/receive buffers
407 for as long as there is anything to copy. When there is nothing more
408 to copy, return C{None}. If one of them actually manages to deliver
409 some application bytes, return a two-tuple of the connection from which
410 the bytes were read and the bytes themselves.
411 """
412 wrote = True
413 while wrote:
414 # Loop until neither side has anything to say
415 wrote = False
416
417 # Copy stuff from each side's send buffer to the other side's
418 # receive buffer.
419 for (read, write) in [(client_conn, server_conn),
420 (server_conn, client_conn)]:
421
422 # Give the side a chance to generate some more bytes, or
423 # succeed.
424 try:
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -0400425 bytes = read.recv(2 ** 16)
Jean-Paul Calderone958299e2009-04-27 12:59:12 -0400426 except WantReadError:
427 # It didn't succeed, so we'll hope it generated some
428 # output.
429 pass
430 else:
431 # It did succeed, so we'll stop now and let the caller deal
432 # with it.
433 return (read, bytes)
434
435 while True:
436 # Keep copying as long as there's more stuff there.
437 try:
438 dirty = read.bio_read(4096)
439 except WantReadError:
440 # Okay, nothing more waiting to be sent. Stop
441 # processing this send buffer.
442 break
443 else:
444 # Keep track of the fact that someone generated some
445 # output.
446 wrote = True
447 write.bio_write(dirty)
448
449
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -0400450 def test_memoryConnect(self):
Jean-Paul Calderone958299e2009-04-27 12:59:12 -0400451 """
452 Two L{Connection}s which use memory BIOs can be manually connected by
453 reading from the output of each and writing those bytes to the input of
454 the other and in this way establish a connection and exchange
455 application-level bytes with each other.
456 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -0400457 server_conn = self._server(None)
458 client_conn = self._client(None)
Rick Deanb71c0d22009-04-01 14:09:23 -0500459
Jean-Paul Calderone958299e2009-04-27 12:59:12 -0400460 # There should be no key or nonces yet.
461 self.assertIdentical(server_conn.master_key(), None)
462 self.assertIdentical(server_conn.client_random(), None)
463 self.assertIdentical(server_conn.server_random(), None)
Rick Deanb71c0d22009-04-01 14:09:23 -0500464
Jean-Paul Calderone958299e2009-04-27 12:59:12 -0400465 # First, the handshake needs to happen. We'll deliver bytes back and
466 # forth between the client and server until neither of them feels like
467 # speaking any more.
468 self.assertIdentical(self._loopback(client_conn, server_conn), None)
469
470 # Now that the handshake is done, there should be a key and nonces.
471 self.assertNotIdentical(server_conn.master_key(), None)
472 self.assertNotIdentical(server_conn.client_random(), None)
473 self.assertNotIdentical(server_conn.server_random(), None)
Jean-Paul Calderone6c051e62009-07-05 13:50:34 -0400474 self.assertEquals(server_conn.client_random(), client_conn.client_random())
475 self.assertEquals(server_conn.server_random(), client_conn.server_random())
476 self.assertNotEquals(server_conn.client_random(), server_conn.server_random())
477 self.assertNotEquals(client_conn.client_random(), client_conn.server_random())
Jean-Paul Calderone958299e2009-04-27 12:59:12 -0400478
479 # Here are the bytes we'll try to send.
Rick Deanb71c0d22009-04-01 14:09:23 -0500480 important_message = 'One if by land, two if by sea.'
481
Jean-Paul Calderone958299e2009-04-27 12:59:12 -0400482 server_conn.write(important_message)
483 self.assertEquals(
484 self._loopback(client_conn, server_conn),
485 (client_conn, important_message))
486
487 client_conn.write(important_message[::-1])
488 self.assertEquals(
489 self._loopback(client_conn, server_conn),
490 (server_conn, important_message[::-1]))
Rick Deanb71c0d22009-04-01 14:09:23 -0500491
492
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -0400493 def test_socketConnect(self):
Rick Deanb1ccd562009-07-09 23:52:39 -0500494 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -0400495 Just like L{test_memoryConnect} but with an actual socket.
496
497 This is primarily to rule out the memory BIO code as the source of
498 any problems encountered while passing data over a L{Connection} (if
499 this test fails, there must be a problem outside the memory BIO
500 code, as no memory BIO is involved here). Even though this isn't a
501 memory BIO test, it's convenient to have it here.
Rick Deanb1ccd562009-07-09 23:52:39 -0500502 """
503 (server, client) = socket_pair()
504
505 # Let the encryption begin...
506 client_conn = self._client(client)
Rick Deanb1ccd562009-07-09 23:52:39 -0500507 server_conn = self._server(server)
Jean-Paul Calderone7903cbd2009-07-16 12:23:34 -0400508
Rick Deanb1ccd562009-07-09 23:52:39 -0500509 # Establish the connection
510 established = False
511 while not established:
512 established = True # assume the best
513 for ssl in client_conn, server_conn:
514 try:
Ziga Seilnacht44611bf2009-08-31 20:49:30 +0200515 # Generally a recv() or send() could also work instead
516 # of do_handshake(), and we would stop on the first
Rick Deanb1ccd562009-07-09 23:52:39 -0500517 # non-exception.
518 ssl.do_handshake()
519 except WantReadError:
520 established = False
521
522 important_message = "Help me Obi Wan Kenobi, you're my only hope."
523 client_conn.send(important_message)
524 msg = server_conn.recv(1024)
525 self.assertEqual(msg, important_message)
526
527 # Again in the other direction, just for fun.
528 important_message = important_message[::-1]
529 server_conn.send(important_message)
530 msg = client_conn.recv(1024)
531 self.assertEqual(msg, important_message)
532
533
Jean-Paul Calderonefc4ed0f2009-04-27 11:51:27 -0400534 def test_socketOverridesMemory(self):
Rick Deanb71c0d22009-04-01 14:09:23 -0500535 """
536 Test that L{OpenSSL.SSL.bio_read} and L{OpenSSL.SSL.bio_write} don't
537 work on L{OpenSSL.SSL.Connection}() that use sockets.
538 """
539 context = Context(SSLv3_METHOD)
540 client = socket()
541 clientSSL = Connection(context, client)
542 self.assertRaises( TypeError, clientSSL.bio_read, 100)
543 self.assertRaises( TypeError, clientSSL.bio_write, "foo")
Jean-Paul Calderone07acf3f2009-05-05 13:23:28 -0400544 self.assertRaises( TypeError, clientSSL.bio_shutdown )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -0400545
546
547 def test_outgoingOverflow(self):
548 """
549 If more bytes than can be written to the memory BIO are passed to
550 L{Connection.send} at once, the number of bytes which were written is
551 returned and that many bytes from the beginning of the input can be
552 read from the other end of the connection.
553 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -0400554 server = self._server(None)
555 client = self._client(None)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -0400556
557 self._loopback(client, server)
558
559 size = 2 ** 15
560 sent = client.send("x" * size)
561 # Sanity check. We're trying to test what happens when the entire
562 # input can't be sent. If the entire input was sent, this test is
563 # meaningless.
564 self.assertTrue(sent < size)
565
566 receiver, received = self._loopback(client, server)
567 self.assertIdentical(receiver, server)
568
569 # We can rely on all of these bytes being received at once because
570 # _loopback passes 2 ** 16 to recv - more than 2 ** 15.
571 self.assertEquals(len(received), sent)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -0400572
573
574 def test_shutdown(self):
575 """
576 L{Connection.bio_shutdown} signals the end of the data stream from
577 which the L{Connection} reads.
578 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -0400579 server = self._server(None)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -0400580 server.bio_shutdown()
581 e = self.assertRaises(Error, server.recv, 1024)
582 # We don't want WantReadError or ZeroReturnError or anything - it's a
583 # handshake failure.
584 self.assertEquals(e.__class__, Error)
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -0400585
586
587
Ziga Seilnacht44611bf2009-08-31 20:49:30 +0200588class ModuleTests(TestCase):
589 """
590 Tests for all objects in L{OpenSSL.crypto} module.
591 """
592
593 def test_type_module_name(self):
594 """
595 Test that all types have a sane C{__module__} attribute.
596 """
597 for name, obj in vars(SSL).items():
598 if isinstance(obj, type):
599 self.assertEqual(obj.__module__, "OpenSSL.SSL", name)
600
601
602
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -0400603if __name__ == '__main__':
604 main()