blob: 94ff66ccbd82048a8c85f40935d63584238e3b09 [file] [log] [blame]
Jean-Paul Calderone7526d172010-09-09 17:55:31 -04001# Copyright (C) Jean-Paul Calderone 2008-2010, All rights reserved
Jean-Paul Calderone8b63d452008-03-21 18:31:12 -04002
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -04003"""
4Unit tests for L{OpenSSL.SSL}.
5"""
6
Jean-Paul Calderone8322d782010-09-17 19:22:31 -04007from errno import ECONNREFUSED, EINPROGRESS, EWOULDBLOCK
Jean-Paul Calderone52f0d8b2009-03-07 09:10:19 -05008from sys import platform
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04009from socket import error, socket
Jean-Paul Calderonea65cf6c2009-07-19 10:26:52 -040010from os import makedirs
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -040011from os.path import join
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -040012from unittest import main
Jean-Paul Calderone460cc1f2009-03-07 11:31:12 -050013
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040014from OpenSSL.crypto import TYPE_RSA, FILETYPE_PEM, FILETYPE_ASN1
15from OpenSSL.crypto import PKey, X509, X509Extension
16from OpenSSL.crypto import dump_privatekey, load_privatekey
17from OpenSSL.crypto import dump_certificate, load_certificate
18
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -040019from OpenSSL.SSL import SENT_SHUTDOWN, RECEIVED_SHUTDOWN
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -040020from OpenSSL.SSL import SSLv2_METHOD, SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD
Jean-Paul Calderone68649052009-07-17 21:14:27 -040021from OpenSSL.SSL import OP_NO_SSLv2, OP_NO_SSLv3, OP_SINGLE_DH_USE
Rick Deanb71c0d22009-04-01 14:09:23 -050022from OpenSSL.SSL import VERIFY_PEER, VERIFY_FAIL_IF_NO_PEER_CERT, VERIFY_CLIENT_ONCE
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040023from OpenSSL.SSL import Error, SysCallError, WantReadError, ZeroReturnError
24from OpenSSL.SSL import Context, ContextType, Connection, ConnectionType
25
Jean-Paul Calderone9e4eeae2010-08-22 21:32:52 -040026from OpenSSL.test.util import TestCase, bytes, b
Jean-Paul Calderone18808652009-07-05 12:54:05 -040027from OpenSSL.test.test_crypto import cleartextCertificatePEM, cleartextPrivateKeyPEM
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040028from OpenSSL.test.test_crypto import client_cert_pem, client_key_pem
29from OpenSSL.test.test_crypto import server_cert_pem, server_key_pem, root_cert_pem
30
Jean-Paul Calderone4bccf5e2008-12-28 22:50:42 -050031try:
32 from OpenSSL.SSL import OP_NO_QUERY_MTU
33except ImportError:
34 OP_NO_QUERY_MTU = None
35try:
36 from OpenSSL.SSL import OP_COOKIE_EXCHANGE
37except ImportError:
38 OP_COOKIE_EXCHANGE = None
39try:
40 from OpenSSL.SSL import OP_NO_TICKET
41except ImportError:
42 OP_NO_TICKET = None
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -040043
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -040044
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -040045# openssl dhparam 128 -out dh-128.pem (note that 128 is a small number of bits
46# to use)
47dhparam = """\
48-----BEGIN DH PARAMETERS-----
49MBYCEQCobsg29c9WZP/54oAPcwiDAgEC
50-----END DH PARAMETERS-----
51"""
52
53
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -040054def verify_cb(conn, cert, errnum, depth, ok):
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -040055 return ok
56
Rick Deanb1ccd562009-07-09 23:52:39 -050057def socket_pair():
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -040058 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -040059 Establish and return a pair of network sockets connected to each other.
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -040060 """
61 # Connect a pair of sockets
Rick Deanb1ccd562009-07-09 23:52:39 -050062 port = socket()
63 port.bind(('', 0))
64 port.listen(1)
65 client = socket()
66 client.setblocking(False)
Jean-Paul Calderonef23c5d92009-07-23 17:58:15 -040067 client.connect_ex(("127.0.0.1", port.getsockname()[1]))
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -040068 client.setblocking(True)
Rick Deanb1ccd562009-07-09 23:52:39 -050069 server = port.accept()[0]
Rick Deanb1ccd562009-07-09 23:52:39 -050070
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -040071 # Let's pass some unencrypted data to make sure our socket connection is
72 # fine. Just one byte, so we don't have to worry about buffers getting
73 # filled up or fragmentation.
Jean-Paul Calderone9e4eeae2010-08-22 21:32:52 -040074 server.send(b("x"))
75 assert client.recv(1024) == b("x")
76 client.send(b("y"))
77 assert server.recv(1024) == b("y")
Rick Deanb1ccd562009-07-09 23:52:39 -050078
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -040079 # Most of our callers want non-blocking sockets, make it easy for them.
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -040080 server.setblocking(False)
81 client.setblocking(False)
82
Rick Deanb1ccd562009-07-09 23:52:39 -050083 return (server, client)
84
85
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -040086
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -040087class _LoopbackMixin:
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -040088 """
89 Helper mixin which defines methods for creating a connected socket pair and
90 for forcing two connected SSL sockets to talk to each other via memory BIOs.
91 """
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -040092 def _loopback(self):
93 (server, client) = socket_pair()
94
95 ctx = Context(TLSv1_METHOD)
96 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
97 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
98 server = Connection(ctx, server)
99 server.set_accept_state()
100 client = Connection(Context(TLSv1_METHOD), client)
101 client.set_connect_state()
102
Jean-Paul Calderonef19fade2010-09-24 23:42:57 -0400103 conns = [client, server]
104 while conns:
105 for conn in conns:
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400106 try:
107 conn.do_handshake()
108 except WantReadError:
109 pass
Jean-Paul Calderonef19fade2010-09-24 23:42:57 -0400110 else:
111 conns.remove(conn)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400112
113 server.setblocking(True)
114 client.setblocking(True)
115 return server, client
116
117
118 def _interactInMemory(self, client_conn, server_conn):
119 """
120 Try to read application bytes from each of the two L{Connection}
121 objects. Copy bytes back and forth between their send/receive buffers
122 for as long as there is anything to copy. When there is nothing more
123 to copy, return C{None}. If one of them actually manages to deliver
124 some application bytes, return a two-tuple of the connection from which
125 the bytes were read and the bytes themselves.
126 """
127 wrote = True
128 while wrote:
129 # Loop until neither side has anything to say
130 wrote = False
131
132 # Copy stuff from each side's send buffer to the other side's
133 # receive buffer.
134 for (read, write) in [(client_conn, server_conn),
135 (server_conn, client_conn)]:
136
137 # Give the side a chance to generate some more bytes, or
138 # succeed.
139 try:
140 bytes = read.recv(2 ** 16)
141 except WantReadError:
142 # It didn't succeed, so we'll hope it generated some
143 # output.
144 pass
145 else:
146 # It did succeed, so we'll stop now and let the caller deal
147 # with it.
148 return (read, bytes)
149
150 while True:
151 # Keep copying as long as there's more stuff there.
152 try:
153 dirty = read.bio_read(4096)
154 except WantReadError:
155 # Okay, nothing more waiting to be sent. Stop
156 # processing this send buffer.
157 break
158 else:
159 # Keep track of the fact that someone generated some
160 # output.
161 wrote = True
162 write.bio_write(dirty)
163
164
165
166class ContextTests(TestCase, _LoopbackMixin):
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400167 """
168 Unit tests for L{OpenSSL.SSL.Context}.
169 """
170 def test_method(self):
171 """
172 L{Context} can be instantiated with one of L{SSLv2_METHOD},
173 L{SSLv3_METHOD}, L{SSLv23_METHOD}, or L{TLSv1_METHOD}.
174 """
175 for meth in [SSLv2_METHOD, SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD]:
176 Context(meth)
177 self.assertRaises(TypeError, Context, "")
178 self.assertRaises(ValueError, Context, 10)
179
180
Rick Deane15b1472009-07-09 15:53:42 -0500181 def test_type(self):
182 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400183 L{Context} and L{ContextType} refer to the same type object and can be
184 used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -0500185 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400186 self.assertIdentical(Context, ContextType)
187 self.assertConsistentType(Context, 'Context', TLSv1_METHOD)
Rick Deane15b1472009-07-09 15:53:42 -0500188
189
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400190 def test_use_privatekey(self):
191 """
192 L{Context.use_privatekey} takes an L{OpenSSL.crypto.PKey} instance.
193 """
194 key = PKey()
195 key.generate_key(TYPE_RSA, 128)
196 ctx = Context(TLSv1_METHOD)
197 ctx.use_privatekey(key)
198 self.assertRaises(TypeError, ctx.use_privatekey, "")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400199
200
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400201 def test_set_app_data_wrong_args(self):
202 """
203 L{Context.set_app_data} raises L{TypeError} if called with other than
204 one argument.
205 """
206 context = Context(TLSv1_METHOD)
207 self.assertRaises(TypeError, context.set_app_data)
208 self.assertRaises(TypeError, context.set_app_data, None, None)
209
210
211 def test_get_app_data_wrong_args(self):
212 """
213 L{Context.get_app_data} raises L{TypeError} if called with any
214 arguments.
215 """
216 context = Context(TLSv1_METHOD)
217 self.assertRaises(TypeError, context.get_app_data, None)
218
219
220 def test_app_data(self):
221 """
222 L{Context.set_app_data} stores an object for later retrieval using
223 L{Context.get_app_data}.
224 """
225 app_data = object()
226 context = Context(TLSv1_METHOD)
227 context.set_app_data(app_data)
228 self.assertIdentical(context.get_app_data(), app_data)
229
230
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400231 def test_set_options_wrong_args(self):
232 """
233 L{Context.set_options} raises L{TypeError} if called with the wrong
234 number of arguments or a non-C{int} argument.
235 """
236 context = Context(TLSv1_METHOD)
237 self.assertRaises(TypeError, context.set_options)
238 self.assertRaises(TypeError, context.set_options, None)
239 self.assertRaises(TypeError, context.set_options, 1, None)
240
241
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400242 def test_set_timeout_wrong_args(self):
243 """
244 L{Context.set_timeout} raises L{TypeError} if called with the wrong
245 number of arguments or a non-C{int} argument.
246 """
247 context = Context(TLSv1_METHOD)
248 self.assertRaises(TypeError, context.set_timeout)
249 self.assertRaises(TypeError, context.set_timeout, None)
250 self.assertRaises(TypeError, context.set_timeout, 1, None)
251
252
253 def test_get_timeout_wrong_args(self):
254 """
255 L{Context.get_timeout} raises L{TypeError} if called with any arguments.
256 """
257 context = Context(TLSv1_METHOD)
258 self.assertRaises(TypeError, context.get_timeout, None)
259
260
261 def test_timeout(self):
262 """
263 L{Context.set_timeout} sets the session timeout for all connections
264 created using the context object. L{Context.get_timeout} retrieves this
265 value.
266 """
267 context = Context(TLSv1_METHOD)
268 context.set_timeout(1234)
269 self.assertEquals(context.get_timeout(), 1234)
270
271
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400272 def test_set_verify_depth_wrong_args(self):
273 """
274 L{Context.set_verify_depth} raises L{TypeError} if called with the wrong
275 number of arguments or a non-C{int} argument.
276 """
277 context = Context(TLSv1_METHOD)
278 self.assertRaises(TypeError, context.set_verify_depth)
279 self.assertRaises(TypeError, context.set_verify_depth, None)
280 self.assertRaises(TypeError, context.set_verify_depth, 1, None)
281
282
283 def test_get_verify_depth_wrong_args(self):
284 """
285 L{Context.get_verify_depth} raises L{TypeError} if called with any arguments.
286 """
287 context = Context(TLSv1_METHOD)
288 self.assertRaises(TypeError, context.get_verify_depth, None)
289
290
291 def test_verify_depth(self):
292 """
293 L{Context.set_verify_depth} sets the number of certificates in a chain
294 to follow before giving up. The value can be retrieved with
295 L{Context.get_verify_depth}.
296 """
297 context = Context(TLSv1_METHOD)
298 context.set_verify_depth(11)
299 self.assertEquals(context.get_verify_depth(), 11)
300
301
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400302 def _write_encrypted_pem(self, passphrase):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400303 """
304 Write a new private key out to a new file, encrypted using the given
305 passphrase. Return the path to the new file.
306 """
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400307 key = PKey()
308 key.generate_key(TYPE_RSA, 128)
309 pemFile = self.mktemp()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400310 fObj = open(pemFile, 'w')
311 pem = dump_privatekey(FILETYPE_PEM, key, "blowfish", passphrase)
312 fObj.write(pem.decode('ascii'))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400313 fObj.close()
314 return pemFile
315
316
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400317 def test_set_passwd_cb_wrong_args(self):
318 """
319 L{Context.set_passwd_cb} raises L{TypeError} if called with the
320 wrong arguments or with a non-callable first argument.
321 """
322 context = Context(TLSv1_METHOD)
323 self.assertRaises(TypeError, context.set_passwd_cb)
324 self.assertRaises(TypeError, context.set_passwd_cb, None)
325 self.assertRaises(TypeError, context.set_passwd_cb, lambda: None, None, None)
326
327
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400328 def test_set_passwd_cb(self):
329 """
330 L{Context.set_passwd_cb} accepts a callable which will be invoked when
331 a private key is loaded from an encrypted PEM.
332 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400333 passphrase = b("foobar")
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400334 pemFile = self._write_encrypted_pem(passphrase)
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400335 calledWith = []
336 def passphraseCallback(maxlen, verify, extra):
337 calledWith.append((maxlen, verify, extra))
338 return passphrase
339 context = Context(TLSv1_METHOD)
340 context.set_passwd_cb(passphraseCallback)
341 context.use_privatekey_file(pemFile)
342 self.assertTrue(len(calledWith), 1)
343 self.assertTrue(isinstance(calledWith[0][0], int))
344 self.assertTrue(isinstance(calledWith[0][1], int))
345 self.assertEqual(calledWith[0][2], None)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400346
347
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400348 def test_passwd_callback_exception(self):
349 """
350 L{Context.use_privatekey_file} propagates any exception raised by the
351 passphrase callback.
352 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400353 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400354 def passphraseCallback(maxlen, verify, extra):
355 raise RuntimeError("Sorry, I am a fail.")
356
357 context = Context(TLSv1_METHOD)
358 context.set_passwd_cb(passphraseCallback)
359 self.assertRaises(RuntimeError, context.use_privatekey_file, pemFile)
360
361
362 def test_passwd_callback_false(self):
363 """
364 L{Context.use_privatekey_file} raises L{OpenSSL.SSL.Error} if the
365 passphrase callback returns a false value.
366 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400367 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400368 def passphraseCallback(maxlen, verify, extra):
369 return None
370
371 context = Context(TLSv1_METHOD)
372 context.set_passwd_cb(passphraseCallback)
373 self.assertRaises(Error, context.use_privatekey_file, pemFile)
374
375
376 def test_passwd_callback_non_string(self):
377 """
378 L{Context.use_privatekey_file} raises L{OpenSSL.SSL.Error} if the
379 passphrase callback returns a true non-string value.
380 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400381 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400382 def passphraseCallback(maxlen, verify, extra):
383 return 10
384
385 context = Context(TLSv1_METHOD)
386 context.set_passwd_cb(passphraseCallback)
387 self.assertRaises(Error, context.use_privatekey_file, pemFile)
388
389
390 def test_passwd_callback_too_long(self):
391 """
392 If the passphrase returned by the passphrase callback returns a string
393 longer than the indicated maximum length, it is truncated.
394 """
395 # A priori knowledge!
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400396 passphrase = b("x") * 1024
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400397 pemFile = self._write_encrypted_pem(passphrase)
398 def passphraseCallback(maxlen, verify, extra):
399 assert maxlen == 1024
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400400 return passphrase + b("y")
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400401
402 context = Context(TLSv1_METHOD)
403 context.set_passwd_cb(passphraseCallback)
404 # This shall succeed because the truncated result is the correct
405 # passphrase.
406 context.use_privatekey_file(pemFile)
407
408
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400409 def test_set_info_callback(self):
410 """
411 L{Context.set_info_callback} accepts a callable which will be invoked
412 when certain information about an SSL connection is available.
413 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500414 (server, client) = socket_pair()
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400415
416 clientSSL = Connection(Context(TLSv1_METHOD), client)
417 clientSSL.set_connect_state()
418
419 called = []
420 def info(conn, where, ret):
421 called.append((conn, where, ret))
422 context = Context(TLSv1_METHOD)
423 context.set_info_callback(info)
424 context.use_certificate(
425 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
426 context.use_privatekey(
427 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
428
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400429 serverSSL = Connection(context, server)
430 serverSSL.set_accept_state()
431
432 while not called:
433 for ssl in clientSSL, serverSSL:
434 try:
435 ssl.do_handshake()
436 except WantReadError:
437 pass
438
439 # Kind of lame. Just make sure it got called somehow.
440 self.assertTrue(called)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400441
442
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400443 def _load_verify_locations_test(self, *args):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400444 """
445 Create a client context which will verify the peer certificate and call
446 its C{load_verify_locations} method with C{*args}. Then connect it to a
447 server and ensure that the handshake succeeds.
448 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500449 (server, client) = socket_pair()
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400450
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400451 clientContext = Context(TLSv1_METHOD)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400452 clientContext.load_verify_locations(*args)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400453 # Require that the server certificate verify properly or the
454 # connection will fail.
455 clientContext.set_verify(
456 VERIFY_PEER,
457 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
458
459 clientSSL = Connection(clientContext, client)
460 clientSSL.set_connect_state()
461
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400462 serverContext = Context(TLSv1_METHOD)
463 serverContext.use_certificate(
464 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
465 serverContext.use_privatekey(
466 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
467
468 serverSSL = Connection(serverContext, server)
469 serverSSL.set_accept_state()
470
471 for i in range(3):
472 for ssl in clientSSL, serverSSL:
473 try:
474 # Without load_verify_locations above, the handshake
475 # will fail:
476 # Error: [('SSL routines', 'SSL3_GET_SERVER_CERTIFICATE',
477 # 'certificate verify failed')]
478 ssl.do_handshake()
479 except WantReadError:
480 pass
481
482 cert = clientSSL.get_peer_certificate()
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400483 self.assertEqual(cert.get_subject().CN, 'Testing Root CA')
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400484
Jean-Paul Calderone12608a82009-11-07 10:35:15 -0500485
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400486 def test_load_verify_file(self):
487 """
488 L{Context.load_verify_locations} accepts a file name and uses the
489 certificates within for verification purposes.
490 """
491 cafile = self.mktemp()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400492 fObj = open(cafile, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400493 fObj.write(cleartextCertificatePEM.decode('ascii'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400494 fObj.close()
495
496 self._load_verify_locations_test(cafile)
497
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400498
499 def test_load_verify_invalid_file(self):
500 """
501 L{Context.load_verify_locations} raises L{Error} when passed a
502 non-existent cafile.
503 """
504 clientContext = Context(TLSv1_METHOD)
505 self.assertRaises(
506 Error, clientContext.load_verify_locations, self.mktemp())
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400507
508
509 def test_load_verify_directory(self):
510 """
511 L{Context.load_verify_locations} accepts a directory name and uses
512 the certificates within for verification purposes.
513 """
514 capath = self.mktemp()
515 makedirs(capath)
Jean-Paul Calderonea65cf6c2009-07-19 10:26:52 -0400516 # Hash value computed manually with c_rehash to avoid depending on
517 # c_rehash in the test suite.
518 cafile = join(capath, 'c7adac82.0')
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400519 fObj = open(cafile, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400520 fObj.write(cleartextCertificatePEM.decode('ascii'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400521 fObj.close()
522
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400523 self._load_verify_locations_test(None, capath)
524
525
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400526 def test_load_verify_locations_wrong_args(self):
527 """
528 L{Context.load_verify_locations} raises L{TypeError} if called with
529 the wrong number of arguments or with non-C{str} arguments.
530 """
531 context = Context(TLSv1_METHOD)
532 self.assertRaises(TypeError, context.load_verify_locations)
533 self.assertRaises(TypeError, context.load_verify_locations, object())
534 self.assertRaises(TypeError, context.load_verify_locations, object(), object())
535 self.assertRaises(TypeError, context.load_verify_locations, None, None, None)
536
537
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -0400538 if platform == "win32":
539 "set_default_verify_paths appears not to work on Windows. "
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400540 "See LP#404343 and LP#404344."
541 else:
542 def test_set_default_verify_paths(self):
543 """
544 L{Context.set_default_verify_paths} causes the platform-specific CA
545 certificate locations to be used for verification purposes.
546 """
547 # Testing this requires a server with a certificate signed by one of
548 # the CAs in the platform CA location. Getting one of those costs
549 # money. Fortunately (or unfortunately, depending on your
550 # perspective), it's easy to think of a public server on the
551 # internet which has such a certificate. Connecting to the network
552 # in a unit test is bad, but it's the only way I can think of to
553 # really test this. -exarkun
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400554
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400555 # Arg, verisign.com doesn't speak TLSv1
556 context = Context(SSLv3_METHOD)
557 context.set_default_verify_paths()
558 context.set_verify(
Ziga Seilnacht44611bf2009-08-31 20:49:30 +0200559 VERIFY_PEER,
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400560 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400561
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400562 client = socket()
563 client.connect(('verisign.com', 443))
564 clientSSL = Connection(context, client)
565 clientSSL.set_connect_state()
566 clientSSL.do_handshake()
567 clientSSL.send('GET / HTTP/1.0\r\n\r\n')
568 self.assertTrue(clientSSL.recv(1024))
Jean-Paul Calderone9eadb962008-09-07 21:20:44 -0400569
570
571 def test_set_default_verify_paths_signature(self):
572 """
573 L{Context.set_default_verify_paths} takes no arguments and raises
574 L{TypeError} if given any.
575 """
576 context = Context(TLSv1_METHOD)
577 self.assertRaises(TypeError, context.set_default_verify_paths, None)
578 self.assertRaises(TypeError, context.set_default_verify_paths, 1)
579 self.assertRaises(TypeError, context.set_default_verify_paths, "")
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -0500580
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400581
Jean-Paul Calderone12608a82009-11-07 10:35:15 -0500582 def test_add_extra_chain_cert_invalid_cert(self):
583 """
584 L{Context.add_extra_chain_cert} raises L{TypeError} if called with
585 other than one argument or if called with an object which is not an
586 instance of L{X509}.
587 """
588 context = Context(TLSv1_METHOD)
589 self.assertRaises(TypeError, context.add_extra_chain_cert)
590 self.assertRaises(TypeError, context.add_extra_chain_cert, object())
591 self.assertRaises(TypeError, context.add_extra_chain_cert, object(), object())
592
593
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400594 def _create_certificate_chain(self):
Jean-Paul Calderone12608a82009-11-07 10:35:15 -0500595 """
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400596 Construct and return a chain of certificates.
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400597
598 1. A new self-signed certificate authority certificate (cacert)
599 2. A new intermediate certificate signed by cacert (icert)
600 3. A new server certificate signed by icert (scert)
Jean-Paul Calderone12608a82009-11-07 10:35:15 -0500601 """
Jean-Paul Calderone9b0744c2010-09-14 18:11:01 -0400602 caext = X509Extension(b('basicConstraints'), False, b('CA:true'))
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -0500603
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400604 # Step 1
605 cakey = PKey()
606 cakey.generate_key(TYPE_RSA, 512)
607 cacert = X509()
Jean-Paul Calderone16cf03d2010-09-08 18:53:39 -0400608 cacert.get_subject().commonName = "Authority Certificate"
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400609 cacert.set_issuer(cacert.get_subject())
610 cacert.set_pubkey(cakey)
Jean-Paul Calderone4e6aed62010-09-19 10:05:34 -0400611 cacert.set_notBefore(b("20000101000000Z"))
612 cacert.set_notAfter(b("20200101000000Z"))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400613 cacert.add_extensions([caext])
Jean-Paul Calderone16cf03d2010-09-08 18:53:39 -0400614 cacert.set_serial_number(0)
615 cacert.sign(cakey, "sha1")
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -0500616
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400617 # Step 2
618 ikey = PKey()
619 ikey.generate_key(TYPE_RSA, 512)
620 icert = X509()
621 icert.get_subject().commonName = "Intermediate Certificate"
622 icert.set_issuer(cacert.get_subject())
623 icert.set_pubkey(ikey)
Jean-Paul Calderone4e6aed62010-09-19 10:05:34 -0400624 icert.set_notBefore(b("20000101000000Z"))
625 icert.set_notAfter(b("20200101000000Z"))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400626 icert.add_extensions([caext])
Jean-Paul Calderone16cf03d2010-09-08 18:53:39 -0400627 icert.set_serial_number(0)
628 icert.sign(cakey, "sha1")
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -0400629
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400630 # Step 3
631 skey = PKey()
632 skey.generate_key(TYPE_RSA, 512)
633 scert = X509()
634 scert.get_subject().commonName = "Server Certificate"
635 scert.set_issuer(icert.get_subject())
636 scert.set_pubkey(skey)
Jean-Paul Calderone4e6aed62010-09-19 10:05:34 -0400637 scert.set_notBefore(b("20000101000000Z"))
638 scert.set_notAfter(b("20200101000000Z"))
Jean-Paul Calderone2db1de52010-09-19 10:08:13 -0400639 scert.add_extensions([
640 X509Extension(b('basicConstraints'), True, b('CA:false'))])
Jean-Paul Calderone16cf03d2010-09-08 18:53:39 -0400641 scert.set_serial_number(0)
642 scert.sign(ikey, "sha1")
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -0400643
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400644 return [(cakey, cacert), (ikey, icert), (skey, scert)]
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400645
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400646
647 def _handshake_test(self, serverContext, clientContext):
648 """
649 Verify that a client and server created with the given contexts can
650 successfully handshake and communicate.
651 """
652 serverSocket, clientSocket = socket_pair()
653
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400654 server = Connection(serverContext, serverSocket)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -0400655 server.set_accept_state()
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400656
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400657 client = Connection(clientContext, clientSocket)
658 client.set_connect_state()
659
660 # Make them talk to each other.
661 # self._interactInMemory(client, server)
662 for i in range(3):
663 for s in [client, server]:
664 try:
665 s.do_handshake()
666 except WantReadError:
667 pass
668
669
670 def test_add_extra_chain_cert(self):
671 """
672 L{Context.add_extra_chain_cert} accepts an L{X509} instance to add to
673 the certificate chain.
674
675 See L{_create_certificate_chain} for the details of the certificate
676 chain tested.
677
678 The chain is tested by starting a server with scert and connecting
679 to it with a client which trusts cacert and requires verification to
680 succeed.
681 """
682 chain = self._create_certificate_chain()
683 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
684
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400685 # Dump the CA certificate to a file because that's the only way to load
686 # it as a trusted CA in the client context.
687 for cert, name in [(cacert, 'ca.pem'), (icert, 'i.pem'), (scert, 's.pem')]:
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400688 fObj = open(name, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400689 fObj.write(dump_certificate(FILETYPE_PEM, cert).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400690 fObj.close()
691
692 for key, name in [(cakey, 'ca.key'), (ikey, 'i.key'), (skey, 's.key')]:
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400693 fObj = open(name, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400694 fObj.write(dump_privatekey(FILETYPE_PEM, key).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400695 fObj.close()
696
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400697 # Create the server context
698 serverContext = Context(TLSv1_METHOD)
699 serverContext.use_privatekey(skey)
700 serverContext.use_certificate(scert)
Jean-Paul Calderone16cf03d2010-09-08 18:53:39 -0400701 # The client already has cacert, we only need to give them icert.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400702 serverContext.add_extra_chain_cert(icert)
703
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400704 # Create the client
705 clientContext = Context(TLSv1_METHOD)
706 clientContext.set_verify(
707 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
708 clientContext.load_verify_locations('ca.pem')
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -0400709
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400710 # Try it out.
711 self._handshake_test(serverContext, clientContext)
712
713
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400714 def test_use_certificate_chain_file(self):
715 """
716 L{Context.use_certificate_chain_file} reads a certificate chain from
717 the specified file.
718
719 The chain is tested by starting a server with scert and connecting
720 to it with a client which trusts cacert and requires verification to
721 succeed.
722 """
723 chain = self._create_certificate_chain()
724 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
725
726 # Write out the chain file.
727 chainFile = self.mktemp()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400728 fObj = open(chainFile, 'w')
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400729 # Most specific to least general.
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400730 fObj.write(dump_certificate(FILETYPE_PEM, scert).decode('ascii'))
731 fObj.write(dump_certificate(FILETYPE_PEM, icert).decode('ascii'))
732 fObj.write(dump_certificate(FILETYPE_PEM, cacert).decode('ascii'))
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400733 fObj.close()
734
735 serverContext = Context(TLSv1_METHOD)
736 serverContext.use_certificate_chain_file(chainFile)
737 serverContext.use_privatekey(skey)
738
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400739 fObj = open('ca.pem', 'w')
740 fObj.write(dump_certificate(FILETYPE_PEM, cacert).decode('ascii'))
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400741 fObj.close()
742
743 clientContext = Context(TLSv1_METHOD)
744 clientContext.set_verify(
745 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
746 clientContext.load_verify_locations('ca.pem')
747
748 self._handshake_test(serverContext, clientContext)
749
Jean-Paul Calderonee0d79362010-08-03 18:46:46 -0400750 # XXX load_client_ca
751 # XXX set_session_id
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -0400752
753 def test_get_verify_mode_wrong_args(self):
754 """
755 L{Context.get_verify_mode} raises L{TypeError} if called with any
756 arguments.
757 """
758 context = Context(TLSv1_METHOD)
759 self.assertRaises(TypeError, context.get_verify_mode, None)
760
761
762 def test_get_verify_mode(self):
763 """
764 L{Context.get_verify_mode} returns the verify mode flags previously
765 passed to L{Context.set_verify}.
766 """
767 context = Context(TLSv1_METHOD)
768 self.assertEquals(context.get_verify_mode(), 0)
769 context.set_verify(
770 VERIFY_PEER | VERIFY_CLIENT_ONCE, lambda *args: None)
771 self.assertEquals(
772 context.get_verify_mode(), VERIFY_PEER | VERIFY_CLIENT_ONCE)
773
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -0400774
775 def test_load_tmp_dh_wrong_args(self):
776 """
777 L{Context.load_tmp_dh} raises L{TypeError} if called with the wrong
778 number of arguments or with a non-C{str} argument.
779 """
780 context = Context(TLSv1_METHOD)
781 self.assertRaises(TypeError, context.load_tmp_dh)
782 self.assertRaises(TypeError, context.load_tmp_dh, "foo", None)
783 self.assertRaises(TypeError, context.load_tmp_dh, object())
784
785
786 def test_load_tmp_dh_missing_file(self):
787 """
788 L{Context.load_tmp_dh} raises L{OpenSSL.SSL.Error} if the specified file
789 does not exist.
790 """
791 context = Context(TLSv1_METHOD)
792 self.assertRaises(Error, context.load_tmp_dh, "hello")
793
794
795 def test_load_tmp_dh(self):
796 """
797 L{Context.load_tmp_dh} loads Diffie-Hellman parameters from the
798 specified file.
799 """
800 context = Context(TLSv1_METHOD)
801 dhfilename = self.mktemp()
802 dhfile = open(dhfilename, "w")
803 dhfile.write(dhparam)
804 dhfile.close()
805 context.load_tmp_dh(dhfilename)
806 # XXX What should I assert here? -exarkun
807
808
809 def test_set_cipher_list(self):
810 """
811 L{Context.set_cipher_list} accepts a C{str} naming the ciphers which
812 connections created with the context object will be able to choose from.
813 """
814 context = Context(TLSv1_METHOD)
815 context.set_cipher_list("hello world:EXP-RC4-MD5")
816 conn = Connection(context, None)
817 self.assertEquals(conn.get_cipher_list(), ["EXP-RC4-MD5"])
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -0400818
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -0400819
820
821class ConnectionTests(TestCase, _LoopbackMixin):
Rick Deane15b1472009-07-09 15:53:42 -0500822 """
823 Unit tests for L{OpenSSL.SSL.Connection}.
824 """
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -0400825 # XXX want_write
826 # XXX want_read
827 # XXX get_peer_certificate -> None
828 # XXX sock_shutdown
829 # XXX master_key -> TypeError
830 # XXX server_random -> TypeError
831 # XXX state_string
832 # XXX connect -> TypeError
833 # XXX connect_ex -> TypeError
834 # XXX set_connect_state -> TypeError
835 # XXX set_accept_state -> TypeError
836 # XXX renegotiate_pending
837 # XXX do_handshake -> TypeError
838 # XXX bio_read -> TypeError
839 # XXX recv -> TypeError
840 # XXX send -> TypeError
841 # XXX bio_write -> TypeError
842
Rick Deane15b1472009-07-09 15:53:42 -0500843 def test_type(self):
844 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400845 L{Connection} and L{ConnectionType} refer to the same type object and
846 can be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -0500847 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400848 self.assertIdentical(Connection, ConnectionType)
Rick Deane15b1472009-07-09 15:53:42 -0500849 ctx = Context(TLSv1_METHOD)
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400850 self.assertConsistentType(Connection, 'Connection', ctx, None)
Rick Deane15b1472009-07-09 15:53:42 -0500851
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400852
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -0500853 def test_get_context(self):
854 """
855 L{Connection.get_context} returns the L{Context} instance used to
856 construct the L{Connection} instance.
857 """
858 context = Context(TLSv1_METHOD)
859 connection = Connection(context, None)
860 self.assertIdentical(connection.get_context(), context)
861
862
863 def test_get_context_wrong_args(self):
864 """
865 L{Connection.get_context} raises L{TypeError} if called with any
866 arguments.
867 """
868 connection = Connection(Context(TLSv1_METHOD), None)
869 self.assertRaises(TypeError, connection.get_context, None)
870
871
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -0400872 def test_pending(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -0400873 """
874 L{Connection.pending} returns the number of bytes available for
875 immediate read.
876 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -0400877 connection = Connection(Context(TLSv1_METHOD), None)
878 self.assertEquals(connection.pending(), 0)
879
880
881 def test_pending_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -0400882 """
883 L{Connection.pending} raises L{TypeError} if called with any arguments.
884 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -0400885 connection = Connection(Context(TLSv1_METHOD), None)
886 self.assertRaises(TypeError, connection.pending, None)
887
888
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -0400889 def test_connect_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -0400890 """
891 L{Connection.connect} raises L{TypeError} if called with a non-address
892 argument or with the wrong number of arguments.
893 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -0400894 connection = Connection(Context(TLSv1_METHOD), socket())
895 self.assertRaises(TypeError, connection.connect, None)
Jean-Paul Calderone93dba222010-09-08 22:59:37 -0400896 self.assertRaises(TypeError, connection.connect)
897 self.assertRaises(TypeError, connection.connect, ("127.0.0.1", 1), None)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -0400898
899
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -0400900 def test_connect_refused(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -0400901 """
902 L{Connection.connect} raises L{socket.error} if the underlying socket
903 connect method raises it.
904 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -0400905 client = socket()
906 context = Context(TLSv1_METHOD)
907 clientSSL = Connection(context, client)
908 exc = self.assertRaises(error, clientSSL.connect, ("127.0.0.1", 1))
Jean-Paul Calderone35adf9d2010-07-29 18:40:44 -0400909 self.assertEquals(exc.args[0], ECONNREFUSED)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -0400910
911
912 def test_connect(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -0400913 """
914 L{Connection.connect} establishes a connection to the specified address.
915 """
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -0400916 port = socket()
917 port.bind(('', 0))
918 port.listen(3)
919
920 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -0400921 clientSSL.connect(('127.0.0.1', port.getsockname()[1]))
922 # XXX An assertion? Or something?
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -0400923
924
Jean-Paul Calderone7b614872010-09-24 17:43:44 -0400925 if platform == "darwin":
926 "connect_ex sometimes causes a kernel panic on OS X 10.6.4"
927 else:
928 def test_connect_ex(self):
929 """
930 If there is a connection error, L{Connection.connect_ex} returns the
931 errno instead of raising an exception.
932 """
933 port = socket()
934 port.bind(('', 0))
935 port.listen(3)
Jean-Paul Calderone55d91f42010-07-29 19:22:17 -0400936
Jean-Paul Calderone7b614872010-09-24 17:43:44 -0400937 clientSSL = Connection(Context(TLSv1_METHOD), socket())
938 clientSSL.setblocking(False)
939 result = clientSSL.connect_ex(port.getsockname())
940 expected = (EINPROGRESS, EWOULDBLOCK)
941 self.assertTrue(
942 result in expected, "%r not in %r" % (result, expected))
Jean-Paul Calderone55d91f42010-07-29 19:22:17 -0400943
944
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -0400945 def test_accept_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -0400946 """
947 L{Connection.accept} raises L{TypeError} if called with any arguments.
948 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -0400949 connection = Connection(Context(TLSv1_METHOD), socket())
950 self.assertRaises(TypeError, connection.accept, None)
951
952
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -0400953 def test_accept(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -0400954 """
955 L{Connection.accept} accepts a pending connection attempt and returns a
956 tuple of a new L{Connection} (the accepted client) and the address the
957 connection originated from.
958 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -0400959 ctx = Context(TLSv1_METHOD)
960 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
961 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -0400962 port = socket()
963 portSSL = Connection(ctx, port)
964 portSSL.bind(('', 0))
965 portSSL.listen(3)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -0400966
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -0400967 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -0400968
969 # Calling portSSL.getsockname() here to get the server IP address sounds
970 # great, but frequently fails on Windows.
971 clientSSL.connect(('127.0.0.1', portSSL.getsockname()[1]))
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -0400972
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -0400973 serverSSL, address = portSSL.accept()
974
975 self.assertTrue(isinstance(serverSSL, Connection))
976 self.assertIdentical(serverSSL.get_context(), ctx)
977 self.assertEquals(address, clientSSL.getsockname())
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -0400978
979
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -0400980 def test_shutdown_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -0400981 """
982 L{Connection.shutdown} raises L{TypeError} if called with the wrong
983 number of arguments or with arguments other than integers.
984 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -0400985 connection = Connection(Context(TLSv1_METHOD), None)
986 self.assertRaises(TypeError, connection.shutdown, None)
Jean-Paul Calderone1d3e0222010-07-29 22:52:45 -0400987 self.assertRaises(TypeError, connection.get_shutdown, None)
988 self.assertRaises(TypeError, connection.set_shutdown)
989 self.assertRaises(TypeError, connection.set_shutdown, None)
990 self.assertRaises(TypeError, connection.set_shutdown, 0, 1)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -0400991
992
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -0400993 def test_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -0400994 """
995 L{Connection.shutdown} performs an SSL-level connection shutdown.
996 """
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -0400997 server, client = self._loopback()
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -0400998 self.assertFalse(server.shutdown())
999 self.assertEquals(server.get_shutdown(), SENT_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001000 self.assertRaises(ZeroReturnError, client.recv, 1024)
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04001001 self.assertEquals(client.get_shutdown(), RECEIVED_SHUTDOWN)
1002 client.shutdown()
1003 self.assertEquals(client.get_shutdown(), SENT_SHUTDOWN|RECEIVED_SHUTDOWN)
1004 self.assertRaises(ZeroReturnError, server.recv, 1024)
1005 self.assertEquals(server.get_shutdown(), SENT_SHUTDOWN|RECEIVED_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001006
1007
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04001008 def test_set_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001009 """
1010 L{Connection.set_shutdown} sets the state of the SSL connection shutdown
1011 process.
1012 """
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04001013 connection = Connection(Context(TLSv1_METHOD), socket())
1014 connection.set_shutdown(RECEIVED_SHUTDOWN)
1015 self.assertEquals(connection.get_shutdown(), RECEIVED_SHUTDOWN)
1016
1017
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001018 def test_app_data_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001019 """
1020 L{Connection.set_app_data} raises L{TypeError} if called with other than
1021 one argument. L{Connection.get_app_data} raises L{TypeError} if called
1022 with any arguments.
1023 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001024 conn = Connection(Context(TLSv1_METHOD), None)
1025 self.assertRaises(TypeError, conn.get_app_data, None)
1026 self.assertRaises(TypeError, conn.set_app_data)
1027 self.assertRaises(TypeError, conn.set_app_data, None, None)
1028
1029
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04001030 def test_app_data(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001031 """
1032 Any object can be set as app data by passing it to
1033 L{Connection.set_app_data} and later retrieved with
1034 L{Connection.get_app_data}.
1035 """
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04001036 conn = Connection(Context(TLSv1_METHOD), None)
1037 app_data = object()
1038 conn.set_app_data(app_data)
1039 self.assertIdentical(conn.get_app_data(), app_data)
1040
1041
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001042 def test_makefile(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001043 """
1044 L{Connection.makefile} is not implemented and calling that method raises
1045 L{NotImplementedError}.
1046 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001047 conn = Connection(Context(TLSv1_METHOD), None)
1048 self.assertRaises(NotImplementedError, conn.makefile)
1049
1050
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001051
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04001052class ConnectionGetCipherListTests(TestCase):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001053 """
1054 Tests for L{Connection.get_cipher_list}.
1055 """
Jean-Paul Calderone54a2bc02010-09-09 17:52:38 -04001056 def test_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001057 """
1058 L{Connection.get_cipher_list} raises L{TypeError} if called with any
1059 arguments.
1060 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04001061 connection = Connection(Context(TLSv1_METHOD), None)
1062 self.assertRaises(TypeError, connection.get_cipher_list, None)
1063
1064
1065 def test_result(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001066 """
1067 L{Connection.get_cipher_list} returns a C{list} of C{str} giving the
1068 names of the ciphers which might be used.
1069 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04001070 connection = Connection(Context(TLSv1_METHOD), None)
1071 ciphers = connection.get_cipher_list()
1072 self.assertTrue(isinstance(ciphers, list))
1073 for cipher in ciphers:
1074 self.assertTrue(isinstance(cipher, str))
1075
1076
1077
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04001078class ConnectionSendallTests(TestCase, _LoopbackMixin):
1079 """
1080 Tests for L{Connection.sendall}.
1081 """
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001082 def test_wrong_args(self):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04001083 """
1084 When called with arguments other than a single string,
1085 L{Connection.sendall} raises L{TypeError}.
1086 """
1087 connection = Connection(Context(TLSv1_METHOD), None)
1088 self.assertRaises(TypeError, connection.sendall)
1089 self.assertRaises(TypeError, connection.sendall, object())
1090 self.assertRaises(TypeError, connection.sendall, "foo", "bar")
1091
1092
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001093 def test_short(self):
1094 """
1095 L{Connection.sendall} transmits all of the bytes in the string passed to
1096 it.
1097 """
1098 server, client = self._loopback()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04001099 server.sendall(b('x'))
1100 self.assertEquals(client.recv(1), b('x'))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001101
1102
1103 def test_long(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001104 """
1105 L{Connection.sendall} transmits all of the bytes in the string passed to
1106 it even if this requires multiple calls of an underlying write function.
1107 """
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001108 server, client = self._loopback()
Jean-Paul Calderone6241c702010-09-16 19:59:24 -04001109 # Should be enough, underlying SSL_write should only do 16k at a time.
1110 # On Windows, after 32k of bytes the write will block (forever - because
1111 # no one is yet reading).
Jean-Paul Calderone9e4c1352010-09-19 09:34:43 -04001112 message = b('x') * (1024 * 32 - 1) + b('y')
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001113 server.sendall(message)
1114 accum = []
1115 received = 0
1116 while received < len(message):
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04001117 data = client.recv(1024)
1118 accum.append(data)
1119 received += len(data)
Jean-Paul Calderonef4047852010-09-19 09:45:57 -04001120 self.assertEquals(message, b('').join(accum))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001121
1122
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04001123 def test_closed(self):
1124 """
1125 If the underlying socket is closed, L{Connection.sendall} propagates the
1126 write error from the low level write call.
1127 """
1128 server, client = self._loopback()
Jean-Paul Calderone05d43e82010-09-24 18:01:36 -04001129 server.sock_shutdown(2)
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04001130 self.assertRaises(SysCallError, server.sendall, "hello, world")
1131
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001132
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04001133
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04001134class ConnectionRenegotiateTests(TestCase, _LoopbackMixin):
1135 """
1136 Tests for SSL renegotiation APIs.
1137 """
1138 def test_renegotiate_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001139 """
1140 L{Connection.renegotiate} raises L{TypeError} if called with any
1141 arguments.
1142 """
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04001143 connection = Connection(Context(TLSv1_METHOD), None)
1144 self.assertRaises(TypeError, connection.renegotiate, None)
1145
1146
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001147 def test_total_renegotiations_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001148 """
1149 L{Connection.total_renegotiations} raises L{TypeError} if called with
1150 any arguments.
1151 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001152 connection = Connection(Context(TLSv1_METHOD), None)
1153 self.assertRaises(TypeError, connection.total_renegotiations, None)
1154
1155
1156 def test_total_renegotiations(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001157 """
1158 L{Connection.total_renegotiations} returns C{0} before any
1159 renegotiations have happened.
1160 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001161 connection = Connection(Context(TLSv1_METHOD), None)
1162 self.assertEquals(connection.total_renegotiations(), 0)
1163
1164
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04001165# def test_renegotiate(self):
1166# """
1167# """
1168# server, client = self._loopback()
1169
1170# server.send("hello world")
1171# self.assertEquals(client.recv(len("hello world")), "hello world")
1172
1173# self.assertEquals(server.total_renegotiations(), 0)
1174# self.assertTrue(server.renegotiate())
1175
1176# server.setblocking(False)
1177# client.setblocking(False)
1178# while server.renegotiate_pending():
1179# client.do_handshake()
1180# server.do_handshake()
1181
1182# self.assertEquals(server.total_renegotiations(), 1)
1183
1184
1185
1186
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001187class ErrorTests(TestCase):
1188 """
1189 Unit tests for L{OpenSSL.SSL.Error}.
1190 """
1191 def test_type(self):
1192 """
1193 L{Error} is an exception type.
1194 """
1195 self.assertTrue(issubclass(Error, Exception))
Rick Deane15b1472009-07-09 15:53:42 -05001196 self.assertEqual(Error.__name__, 'Error')
Rick Deane15b1472009-07-09 15:53:42 -05001197
1198
1199
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05001200class ConstantsTests(TestCase):
1201 """
1202 Tests for the values of constants exposed in L{OpenSSL.SSL}.
1203
1204 These are values defined by OpenSSL intended only to be used as flags to
1205 OpenSSL APIs. The only assertions it seems can be made about them is
1206 their values.
1207 """
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05001208 # unittest.TestCase has no skip mechanism
1209 if OP_NO_QUERY_MTU is not None:
1210 def test_op_no_query_mtu(self):
1211 """
1212 The value of L{OpenSSL.SSL.OP_NO_QUERY_MTU} is 0x1000, the value of
1213 I{SSL_OP_NO_QUERY_MTU} defined by I{openssl/ssl.h}.
1214 """
1215 self.assertEqual(OP_NO_QUERY_MTU, 0x1000)
1216 else:
1217 "OP_NO_QUERY_MTU unavailable - OpenSSL version may be too old"
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05001218
1219
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05001220 if OP_COOKIE_EXCHANGE is not None:
1221 def test_op_cookie_exchange(self):
1222 """
1223 The value of L{OpenSSL.SSL.OP_COOKIE_EXCHANGE} is 0x2000, the value
1224 of I{SSL_OP_COOKIE_EXCHANGE} defined by I{openssl/ssl.h}.
1225 """
1226 self.assertEqual(OP_COOKIE_EXCHANGE, 0x2000)
1227 else:
1228 "OP_COOKIE_EXCHANGE unavailable - OpenSSL version may be too old"
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05001229
1230
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05001231 if OP_NO_TICKET is not None:
1232 def test_op_no_ticket(self):
1233 """
1234 The value of L{OpenSSL.SSL.OP_NO_TICKET} is 0x4000, the value of
1235 I{SSL_OP_NO_TICKET} defined by I{openssl/ssl.h}.
1236 """
1237 self.assertEqual(OP_NO_TICKET, 0x4000)
1238 else:
1239 "OP_NO_TICKET unavailable - OpenSSL version may be too old"
Rick Dean5b7b6372009-04-01 11:34:06 -05001240
1241
Jean-Paul Calderoneeeee26a2009-04-27 11:24:30 -04001242
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001243class MemoryBIOTests(TestCase, _LoopbackMixin):
Rick Deanb71c0d22009-04-01 14:09:23 -05001244 """
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04001245 Tests for L{OpenSSL.SSL.Connection} using a memory BIO.
Rick Deanb71c0d22009-04-01 14:09:23 -05001246 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04001247 def _server(self, sock):
1248 """
1249 Create a new server-side SSL L{Connection} object wrapped around
1250 C{sock}.
1251 """
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04001252 # Create the server side Connection. This is mostly setup boilerplate
1253 # - use TLSv1, use a particular certificate, etc.
1254 server_ctx = Context(TLSv1_METHOD)
1255 server_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE )
1256 server_ctx.set_verify(VERIFY_PEER|VERIFY_FAIL_IF_NO_PEER_CERT|VERIFY_CLIENT_ONCE, verify_cb)
1257 server_store = server_ctx.get_cert_store()
1258 server_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1259 server_ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
1260 server_ctx.check_privatekey()
1261 server_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05001262 # Here the Connection is actually created. If None is passed as the 2nd
1263 # parameter, it indicates a memory BIO should be created.
1264 server_conn = Connection(server_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04001265 server_conn.set_accept_state()
1266 return server_conn
1267
1268
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04001269 def _client(self, sock):
1270 """
1271 Create a new client-side SSL L{Connection} object wrapped around
1272 C{sock}.
1273 """
1274 # Now create the client side Connection. Similar boilerplate to the
1275 # above.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04001276 client_ctx = Context(TLSv1_METHOD)
1277 client_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE )
1278 client_ctx.set_verify(VERIFY_PEER|VERIFY_FAIL_IF_NO_PEER_CERT|VERIFY_CLIENT_ONCE, verify_cb)
1279 client_store = client_ctx.get_cert_store()
1280 client_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, client_key_pem))
1281 client_ctx.use_certificate(load_certificate(FILETYPE_PEM, client_cert_pem))
1282 client_ctx.check_privatekey()
1283 client_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05001284 client_conn = Connection(client_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04001285 client_conn.set_connect_state()
1286 return client_conn
1287
1288
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04001289 def test_memoryConnect(self):
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04001290 """
1291 Two L{Connection}s which use memory BIOs can be manually connected by
1292 reading from the output of each and writing those bytes to the input of
1293 the other and in this way establish a connection and exchange
1294 application-level bytes with each other.
1295 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04001296 server_conn = self._server(None)
1297 client_conn = self._client(None)
Rick Deanb71c0d22009-04-01 14:09:23 -05001298
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04001299 # There should be no key or nonces yet.
1300 self.assertIdentical(server_conn.master_key(), None)
1301 self.assertIdentical(server_conn.client_random(), None)
1302 self.assertIdentical(server_conn.server_random(), None)
Rick Deanb71c0d22009-04-01 14:09:23 -05001303
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04001304 # First, the handshake needs to happen. We'll deliver bytes back and
1305 # forth between the client and server until neither of them feels like
1306 # speaking any more.
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001307 self.assertIdentical(
1308 self._interactInMemory(client_conn, server_conn), None)
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04001309
1310 # Now that the handshake is done, there should be a key and nonces.
1311 self.assertNotIdentical(server_conn.master_key(), None)
1312 self.assertNotIdentical(server_conn.client_random(), None)
1313 self.assertNotIdentical(server_conn.server_random(), None)
Jean-Paul Calderone6c051e62009-07-05 13:50:34 -04001314 self.assertEquals(server_conn.client_random(), client_conn.client_random())
1315 self.assertEquals(server_conn.server_random(), client_conn.server_random())
1316 self.assertNotEquals(server_conn.client_random(), server_conn.server_random())
1317 self.assertNotEquals(client_conn.client_random(), client_conn.server_random())
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04001318
1319 # Here are the bytes we'll try to send.
Jean-Paul Calderonea441fdc2010-08-22 21:33:57 -04001320 important_message = b('One if by land, two if by sea.')
Rick Deanb71c0d22009-04-01 14:09:23 -05001321
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04001322 server_conn.write(important_message)
1323 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001324 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04001325 (client_conn, important_message))
1326
1327 client_conn.write(important_message[::-1])
1328 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001329 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04001330 (server_conn, important_message[::-1]))
Rick Deanb71c0d22009-04-01 14:09:23 -05001331
1332
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04001333 def test_socketConnect(self):
Rick Deanb1ccd562009-07-09 23:52:39 -05001334 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04001335 Just like L{test_memoryConnect} but with an actual socket.
1336
1337 This is primarily to rule out the memory BIO code as the source of
1338 any problems encountered while passing data over a L{Connection} (if
1339 this test fails, there must be a problem outside the memory BIO
1340 code, as no memory BIO is involved here). Even though this isn't a
1341 memory BIO test, it's convenient to have it here.
Rick Deanb1ccd562009-07-09 23:52:39 -05001342 """
1343 (server, client) = socket_pair()
1344
1345 # Let the encryption begin...
1346 client_conn = self._client(client)
Rick Deanb1ccd562009-07-09 23:52:39 -05001347 server_conn = self._server(server)
Jean-Paul Calderone7903cbd2009-07-16 12:23:34 -04001348
Rick Deanb1ccd562009-07-09 23:52:39 -05001349 # Establish the connection
1350 established = False
1351 while not established:
1352 established = True # assume the best
1353 for ssl in client_conn, server_conn:
1354 try:
Ziga Seilnacht44611bf2009-08-31 20:49:30 +02001355 # Generally a recv() or send() could also work instead
1356 # of do_handshake(), and we would stop on the first
Rick Deanb1ccd562009-07-09 23:52:39 -05001357 # non-exception.
1358 ssl.do_handshake()
1359 except WantReadError:
1360 established = False
1361
Jean-Paul Calderonea441fdc2010-08-22 21:33:57 -04001362 important_message = b("Help me Obi Wan Kenobi, you're my only hope.")
Rick Deanb1ccd562009-07-09 23:52:39 -05001363 client_conn.send(important_message)
1364 msg = server_conn.recv(1024)
1365 self.assertEqual(msg, important_message)
1366
1367 # Again in the other direction, just for fun.
1368 important_message = important_message[::-1]
1369 server_conn.send(important_message)
1370 msg = client_conn.recv(1024)
1371 self.assertEqual(msg, important_message)
1372
1373
Jean-Paul Calderonefc4ed0f2009-04-27 11:51:27 -04001374 def test_socketOverridesMemory(self):
Rick Deanb71c0d22009-04-01 14:09:23 -05001375 """
1376 Test that L{OpenSSL.SSL.bio_read} and L{OpenSSL.SSL.bio_write} don't
1377 work on L{OpenSSL.SSL.Connection}() that use sockets.
1378 """
1379 context = Context(SSLv3_METHOD)
1380 client = socket()
1381 clientSSL = Connection(context, client)
1382 self.assertRaises( TypeError, clientSSL.bio_read, 100)
1383 self.assertRaises( TypeError, clientSSL.bio_write, "foo")
Jean-Paul Calderone07acf3f2009-05-05 13:23:28 -04001384 self.assertRaises( TypeError, clientSSL.bio_shutdown )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04001385
1386
1387 def test_outgoingOverflow(self):
1388 """
1389 If more bytes than can be written to the memory BIO are passed to
1390 L{Connection.send} at once, the number of bytes which were written is
1391 returned and that many bytes from the beginning of the input can be
1392 read from the other end of the connection.
1393 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04001394 server = self._server(None)
1395 client = self._client(None)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04001396
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001397 self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04001398
1399 size = 2 ** 15
1400 sent = client.send("x" * size)
1401 # Sanity check. We're trying to test what happens when the entire
1402 # input can't be sent. If the entire input was sent, this test is
1403 # meaningless.
1404 self.assertTrue(sent < size)
1405
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001406 receiver, received = self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04001407 self.assertIdentical(receiver, server)
1408
1409 # We can rely on all of these bytes being received at once because
1410 # _loopback passes 2 ** 16 to recv - more than 2 ** 15.
1411 self.assertEquals(len(received), sent)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04001412
1413
1414 def test_shutdown(self):
1415 """
1416 L{Connection.bio_shutdown} signals the end of the data stream from
1417 which the L{Connection} reads.
1418 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04001419 server = self._server(None)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04001420 server.bio_shutdown()
1421 e = self.assertRaises(Error, server.recv, 1024)
1422 # We don't want WantReadError or ZeroReturnError or anything - it's a
1423 # handshake failure.
1424 self.assertEquals(e.__class__, Error)
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04001425
1426
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001427 def _check_client_ca_list(self, func):
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001428 """
1429 Verify the return value of the C{get_client_ca_list} method for server and client connections.
1430
1431 @param func: A function which will be called with the server context
1432 before the client and server are connected to each other. This
1433 function should specify a list of CAs for the server to send to the
1434 client and return that same list. The list will be used to verify
1435 that C{get_client_ca_list} returns the proper value at various
1436 times.
1437 """
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001438 server = self._server(None)
1439 client = self._client(None)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001440 self.assertEqual(client.get_client_ca_list(), [])
1441 self.assertEqual(server.get_client_ca_list(), [])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001442 ctx = server.get_context()
1443 expected = func(ctx)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001444 self.assertEqual(client.get_client_ca_list(), [])
1445 self.assertEqual(server.get_client_ca_list(), expected)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001446 self._interactInMemory(client, server)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001447 self.assertEqual(client.get_client_ca_list(), expected)
1448 self.assertEqual(server.get_client_ca_list(), expected)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001449
1450
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001451 def test_set_client_ca_list_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001452 """
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001453 L{Context.set_client_ca_list} raises a L{TypeError} if called with a
1454 non-list or a list that contains objects other than X509Names.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001455 """
1456 ctx = Context(TLSv1_METHOD)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001457 self.assertRaises(TypeError, ctx.set_client_ca_list, "spam")
1458 self.assertRaises(TypeError, ctx.set_client_ca_list, ["spam"])
1459 self.assertIdentical(ctx.set_client_ca_list([]), None)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001460
1461
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001462 def test_set_empty_ca_list(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001463 """
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001464 If passed an empty list, L{Context.set_client_ca_list} configures the
1465 context to send no CA names to the client and, on both the server and
1466 client sides, L{Connection.get_client_ca_list} returns an empty list
1467 after the connection is set up.
1468 """
1469 def no_ca(ctx):
1470 ctx.set_client_ca_list([])
1471 return []
1472 self._check_client_ca_list(no_ca)
1473
1474
1475 def test_set_one_ca_list(self):
1476 """
1477 If passed a list containing a single X509Name,
1478 L{Context.set_client_ca_list} configures the context to send that CA
1479 name to the client and, on both the server and client sides,
1480 L{Connection.get_client_ca_list} returns a list containing that
1481 X509Name after the connection is set up.
1482 """
1483 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
1484 cadesc = cacert.get_subject()
1485 def single_ca(ctx):
1486 ctx.set_client_ca_list([cadesc])
1487 return [cadesc]
1488 self._check_client_ca_list(single_ca)
1489
1490
1491 def test_set_multiple_ca_list(self):
1492 """
1493 If passed a list containing multiple X509Name objects,
1494 L{Context.set_client_ca_list} configures the context to send those CA
1495 names to the client and, on both the server and client sides,
1496 L{Connection.get_client_ca_list} returns a list containing those
1497 X509Names after the connection is set up.
1498 """
1499 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
1500 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
1501
1502 sedesc = secert.get_subject()
1503 cldesc = clcert.get_subject()
1504
1505 def multiple_ca(ctx):
1506 L = [sedesc, cldesc]
1507 ctx.set_client_ca_list(L)
1508 return L
1509 self._check_client_ca_list(multiple_ca)
1510
1511
1512 def test_reset_ca_list(self):
1513 """
1514 If called multiple times, only the X509Names passed to the final call
1515 of L{Context.set_client_ca_list} are used to configure the CA names
1516 sent to the client.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001517 """
1518 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
1519 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
1520 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
1521
1522 cadesc = cacert.get_subject()
1523 sedesc = secert.get_subject()
1524 cldesc = clcert.get_subject()
1525
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001526 def changed_ca(ctx):
1527 ctx.set_client_ca_list([sedesc, cldesc])
1528 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001529 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001530 self._check_client_ca_list(changed_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001531
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001532
1533 def test_mutated_ca_list(self):
1534 """
1535 If the list passed to L{Context.set_client_ca_list} is mutated
1536 afterwards, this does not affect the list of CA names sent to the
1537 client.
1538 """
1539 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
1540 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
1541
1542 cadesc = cacert.get_subject()
1543 sedesc = secert.get_subject()
1544
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001545 def mutated_ca(ctx):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001546 L = [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001547 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001548 L.append(sedesc)
1549 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001550 self._check_client_ca_list(mutated_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001551
1552
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001553 def test_add_client_ca_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001554 """
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001555 L{Context.add_client_ca} raises L{TypeError} if called with a non-X509
1556 object or with a number of arguments other than one.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001557 """
1558 ctx = Context(TLSv1_METHOD)
1559 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001560 self.assertRaises(TypeError, ctx.add_client_ca)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001561 self.assertRaises(TypeError, ctx.add_client_ca, "spam")
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001562 self.assertRaises(TypeError, ctx.add_client_ca, cacert, cacert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001563
1564
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04001565 def test_one_add_client_ca(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001566 """
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04001567 A certificate's subject can be added as a CA to be sent to the client
1568 with L{Context.add_client_ca}.
1569 """
1570 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
1571 cadesc = cacert.get_subject()
1572 def single_ca(ctx):
1573 ctx.add_client_ca(cacert)
1574 return [cadesc]
1575 self._check_client_ca_list(single_ca)
1576
1577
1578 def test_multiple_add_client_ca(self):
1579 """
1580 Multiple CA names can be sent to the client by calling
1581 L{Context.add_client_ca} with multiple X509 objects.
1582 """
1583 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
1584 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
1585
1586 cadesc = cacert.get_subject()
1587 sedesc = secert.get_subject()
1588
1589 def multiple_ca(ctx):
1590 ctx.add_client_ca(cacert)
1591 ctx.add_client_ca(secert)
1592 return [cadesc, sedesc]
1593 self._check_client_ca_list(multiple_ca)
1594
1595
1596 def test_set_and_add_client_ca(self):
1597 """
1598 A call to L{Context.set_client_ca_list} followed by a call to
1599 L{Context.add_client_ca} results in using the CA names from the first
1600 call and the CA name from the second call.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001601 """
1602 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
1603 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
1604 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
1605
1606 cadesc = cacert.get_subject()
1607 sedesc = secert.get_subject()
1608 cldesc = clcert.get_subject()
1609
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001610 def mixed_set_add_ca(ctx):
1611 ctx.set_client_ca_list([cadesc, sedesc])
1612 ctx.add_client_ca(clcert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001613 return [cadesc, sedesc, cldesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001614 self._check_client_ca_list(mixed_set_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001615
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04001616
1617 def test_set_after_add_client_ca(self):
1618 """
1619 A call to L{Context.set_client_ca_list} after a call to
1620 L{Context.add_client_ca} replaces the CA name specified by the former
1621 call with the names specified by the latter cal.
1622 """
1623 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
1624 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
1625 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
1626
1627 cadesc = cacert.get_subject()
1628 sedesc = secert.get_subject()
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04001629
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001630 def set_replaces_add_ca(ctx):
1631 ctx.add_client_ca(clcert)
1632 ctx.set_client_ca_list([cadesc])
1633 ctx.add_client_ca(secert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001634 return [cadesc, sedesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001635 self._check_client_ca_list(set_replaces_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001636
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04001637
Ziga Seilnacht44611bf2009-08-31 20:49:30 +02001638
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04001639if __name__ == '__main__':
1640 main()