blob: 66faa017f144d5f8cd958a92204ca8606fa3d8a0 [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
103 for i in range(3):
104 for conn in [client, server]:
105 try:
106 conn.do_handshake()
107 except WantReadError:
108 pass
109
110 server.setblocking(True)
111 client.setblocking(True)
112 return server, client
113
114
115 def _interactInMemory(self, client_conn, server_conn):
116 """
117 Try to read application bytes from each of the two L{Connection}
118 objects. Copy bytes back and forth between their send/receive buffers
119 for as long as there is anything to copy. When there is nothing more
120 to copy, return C{None}. If one of them actually manages to deliver
121 some application bytes, return a two-tuple of the connection from which
122 the bytes were read and the bytes themselves.
123 """
124 wrote = True
125 while wrote:
126 # Loop until neither side has anything to say
127 wrote = False
128
129 # Copy stuff from each side's send buffer to the other side's
130 # receive buffer.
131 for (read, write) in [(client_conn, server_conn),
132 (server_conn, client_conn)]:
133
134 # Give the side a chance to generate some more bytes, or
135 # succeed.
136 try:
137 bytes = read.recv(2 ** 16)
138 except WantReadError:
139 # It didn't succeed, so we'll hope it generated some
140 # output.
141 pass
142 else:
143 # It did succeed, so we'll stop now and let the caller deal
144 # with it.
145 return (read, bytes)
146
147 while True:
148 # Keep copying as long as there's more stuff there.
149 try:
150 dirty = read.bio_read(4096)
151 except WantReadError:
152 # Okay, nothing more waiting to be sent. Stop
153 # processing this send buffer.
154 break
155 else:
156 # Keep track of the fact that someone generated some
157 # output.
158 wrote = True
159 write.bio_write(dirty)
160
161
162
163class ContextTests(TestCase, _LoopbackMixin):
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400164 """
165 Unit tests for L{OpenSSL.SSL.Context}.
166 """
167 def test_method(self):
168 """
169 L{Context} can be instantiated with one of L{SSLv2_METHOD},
170 L{SSLv3_METHOD}, L{SSLv23_METHOD}, or L{TLSv1_METHOD}.
171 """
172 for meth in [SSLv2_METHOD, SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD]:
173 Context(meth)
174 self.assertRaises(TypeError, Context, "")
175 self.assertRaises(ValueError, Context, 10)
176
177
Rick Deane15b1472009-07-09 15:53:42 -0500178 def test_type(self):
179 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400180 L{Context} and L{ContextType} refer to the same type object and can be
181 used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -0500182 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400183 self.assertIdentical(Context, ContextType)
184 self.assertConsistentType(Context, 'Context', TLSv1_METHOD)
Rick Deane15b1472009-07-09 15:53:42 -0500185
186
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400187 def test_use_privatekey(self):
188 """
189 L{Context.use_privatekey} takes an L{OpenSSL.crypto.PKey} instance.
190 """
191 key = PKey()
192 key.generate_key(TYPE_RSA, 128)
193 ctx = Context(TLSv1_METHOD)
194 ctx.use_privatekey(key)
195 self.assertRaises(TypeError, ctx.use_privatekey, "")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400196
197
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400198 def test_set_app_data_wrong_args(self):
199 """
200 L{Context.set_app_data} raises L{TypeError} if called with other than
201 one argument.
202 """
203 context = Context(TLSv1_METHOD)
204 self.assertRaises(TypeError, context.set_app_data)
205 self.assertRaises(TypeError, context.set_app_data, None, None)
206
207
208 def test_get_app_data_wrong_args(self):
209 """
210 L{Context.get_app_data} raises L{TypeError} if called with any
211 arguments.
212 """
213 context = Context(TLSv1_METHOD)
214 self.assertRaises(TypeError, context.get_app_data, None)
215
216
217 def test_app_data(self):
218 """
219 L{Context.set_app_data} stores an object for later retrieval using
220 L{Context.get_app_data}.
221 """
222 app_data = object()
223 context = Context(TLSv1_METHOD)
224 context.set_app_data(app_data)
225 self.assertIdentical(context.get_app_data(), app_data)
226
227
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400228 def test_set_options_wrong_args(self):
229 """
230 L{Context.set_options} raises L{TypeError} if called with the wrong
231 number of arguments or a non-C{int} argument.
232 """
233 context = Context(TLSv1_METHOD)
234 self.assertRaises(TypeError, context.set_options)
235 self.assertRaises(TypeError, context.set_options, None)
236 self.assertRaises(TypeError, context.set_options, 1, None)
237
238
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400239 def test_set_timeout_wrong_args(self):
240 """
241 L{Context.set_timeout} raises L{TypeError} if called with the wrong
242 number of arguments or a non-C{int} argument.
243 """
244 context = Context(TLSv1_METHOD)
245 self.assertRaises(TypeError, context.set_timeout)
246 self.assertRaises(TypeError, context.set_timeout, None)
247 self.assertRaises(TypeError, context.set_timeout, 1, None)
248
249
250 def test_get_timeout_wrong_args(self):
251 """
252 L{Context.get_timeout} raises L{TypeError} if called with any arguments.
253 """
254 context = Context(TLSv1_METHOD)
255 self.assertRaises(TypeError, context.get_timeout, None)
256
257
258 def test_timeout(self):
259 """
260 L{Context.set_timeout} sets the session timeout for all connections
261 created using the context object. L{Context.get_timeout} retrieves this
262 value.
263 """
264 context = Context(TLSv1_METHOD)
265 context.set_timeout(1234)
266 self.assertEquals(context.get_timeout(), 1234)
267
268
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400269 def test_set_verify_depth_wrong_args(self):
270 """
271 L{Context.set_verify_depth} raises L{TypeError} if called with the wrong
272 number of arguments or a non-C{int} argument.
273 """
274 context = Context(TLSv1_METHOD)
275 self.assertRaises(TypeError, context.set_verify_depth)
276 self.assertRaises(TypeError, context.set_verify_depth, None)
277 self.assertRaises(TypeError, context.set_verify_depth, 1, None)
278
279
280 def test_get_verify_depth_wrong_args(self):
281 """
282 L{Context.get_verify_depth} raises L{TypeError} if called with any arguments.
283 """
284 context = Context(TLSv1_METHOD)
285 self.assertRaises(TypeError, context.get_verify_depth, None)
286
287
288 def test_verify_depth(self):
289 """
290 L{Context.set_verify_depth} sets the number of certificates in a chain
291 to follow before giving up. The value can be retrieved with
292 L{Context.get_verify_depth}.
293 """
294 context = Context(TLSv1_METHOD)
295 context.set_verify_depth(11)
296 self.assertEquals(context.get_verify_depth(), 11)
297
298
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400299 def _write_encrypted_pem(self, passphrase):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400300 """
301 Write a new private key out to a new file, encrypted using the given
302 passphrase. Return the path to the new file.
303 """
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400304 key = PKey()
305 key.generate_key(TYPE_RSA, 128)
306 pemFile = self.mktemp()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400307 fObj = open(pemFile, 'w')
308 pem = dump_privatekey(FILETYPE_PEM, key, "blowfish", passphrase)
309 fObj.write(pem.decode('ascii'))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400310 fObj.close()
311 return pemFile
312
313
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400314 def test_set_passwd_cb_wrong_args(self):
315 """
316 L{Context.set_passwd_cb} raises L{TypeError} if called with the
317 wrong arguments or with a non-callable first argument.
318 """
319 context = Context(TLSv1_METHOD)
320 self.assertRaises(TypeError, context.set_passwd_cb)
321 self.assertRaises(TypeError, context.set_passwd_cb, None)
322 self.assertRaises(TypeError, context.set_passwd_cb, lambda: None, None, None)
323
324
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400325 def test_set_passwd_cb(self):
326 """
327 L{Context.set_passwd_cb} accepts a callable which will be invoked when
328 a private key is loaded from an encrypted PEM.
329 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400330 passphrase = b("foobar")
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400331 pemFile = self._write_encrypted_pem(passphrase)
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400332 calledWith = []
333 def passphraseCallback(maxlen, verify, extra):
334 calledWith.append((maxlen, verify, extra))
335 return passphrase
336 context = Context(TLSv1_METHOD)
337 context.set_passwd_cb(passphraseCallback)
338 context.use_privatekey_file(pemFile)
339 self.assertTrue(len(calledWith), 1)
340 self.assertTrue(isinstance(calledWith[0][0], int))
341 self.assertTrue(isinstance(calledWith[0][1], int))
342 self.assertEqual(calledWith[0][2], None)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400343
344
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400345 def test_passwd_callback_exception(self):
346 """
347 L{Context.use_privatekey_file} propagates any exception raised by the
348 passphrase callback.
349 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400350 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400351 def passphraseCallback(maxlen, verify, extra):
352 raise RuntimeError("Sorry, I am a fail.")
353
354 context = Context(TLSv1_METHOD)
355 context.set_passwd_cb(passphraseCallback)
356 self.assertRaises(RuntimeError, context.use_privatekey_file, pemFile)
357
358
359 def test_passwd_callback_false(self):
360 """
361 L{Context.use_privatekey_file} raises L{OpenSSL.SSL.Error} if the
362 passphrase callback returns a false value.
363 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400364 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400365 def passphraseCallback(maxlen, verify, extra):
366 return None
367
368 context = Context(TLSv1_METHOD)
369 context.set_passwd_cb(passphraseCallback)
370 self.assertRaises(Error, context.use_privatekey_file, pemFile)
371
372
373 def test_passwd_callback_non_string(self):
374 """
375 L{Context.use_privatekey_file} raises L{OpenSSL.SSL.Error} if the
376 passphrase callback returns a true non-string value.
377 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400378 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400379 def passphraseCallback(maxlen, verify, extra):
380 return 10
381
382 context = Context(TLSv1_METHOD)
383 context.set_passwd_cb(passphraseCallback)
384 self.assertRaises(Error, context.use_privatekey_file, pemFile)
385
386
387 def test_passwd_callback_too_long(self):
388 """
389 If the passphrase returned by the passphrase callback returns a string
390 longer than the indicated maximum length, it is truncated.
391 """
392 # A priori knowledge!
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400393 passphrase = b("x") * 1024
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400394 pemFile = self._write_encrypted_pem(passphrase)
395 def passphraseCallback(maxlen, verify, extra):
396 assert maxlen == 1024
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400397 return passphrase + b("y")
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400398
399 context = Context(TLSv1_METHOD)
400 context.set_passwd_cb(passphraseCallback)
401 # This shall succeed because the truncated result is the correct
402 # passphrase.
403 context.use_privatekey_file(pemFile)
404
405
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400406 def test_set_info_callback(self):
407 """
408 L{Context.set_info_callback} accepts a callable which will be invoked
409 when certain information about an SSL connection is available.
410 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500411 (server, client) = socket_pair()
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400412
413 clientSSL = Connection(Context(TLSv1_METHOD), client)
414 clientSSL.set_connect_state()
415
416 called = []
417 def info(conn, where, ret):
418 called.append((conn, where, ret))
419 context = Context(TLSv1_METHOD)
420 context.set_info_callback(info)
421 context.use_certificate(
422 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
423 context.use_privatekey(
424 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
425
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400426 serverSSL = Connection(context, server)
427 serverSSL.set_accept_state()
428
429 while not called:
430 for ssl in clientSSL, serverSSL:
431 try:
432 ssl.do_handshake()
433 except WantReadError:
434 pass
435
436 # Kind of lame. Just make sure it got called somehow.
437 self.assertTrue(called)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400438
439
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400440 def _load_verify_locations_test(self, *args):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400441 """
442 Create a client context which will verify the peer certificate and call
443 its C{load_verify_locations} method with C{*args}. Then connect it to a
444 server and ensure that the handshake succeeds.
445 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500446 (server, client) = socket_pair()
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400447
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400448 clientContext = Context(TLSv1_METHOD)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400449 clientContext.load_verify_locations(*args)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400450 # Require that the server certificate verify properly or the
451 # connection will fail.
452 clientContext.set_verify(
453 VERIFY_PEER,
454 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
455
456 clientSSL = Connection(clientContext, client)
457 clientSSL.set_connect_state()
458
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400459 serverContext = Context(TLSv1_METHOD)
460 serverContext.use_certificate(
461 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
462 serverContext.use_privatekey(
463 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
464
465 serverSSL = Connection(serverContext, server)
466 serverSSL.set_accept_state()
467
468 for i in range(3):
469 for ssl in clientSSL, serverSSL:
470 try:
471 # Without load_verify_locations above, the handshake
472 # will fail:
473 # Error: [('SSL routines', 'SSL3_GET_SERVER_CERTIFICATE',
474 # 'certificate verify failed')]
475 ssl.do_handshake()
476 except WantReadError:
477 pass
478
479 cert = clientSSL.get_peer_certificate()
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400480 self.assertEqual(cert.get_subject().CN, 'Testing Root CA')
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400481
Jean-Paul Calderone12608a82009-11-07 10:35:15 -0500482
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400483 def test_load_verify_file(self):
484 """
485 L{Context.load_verify_locations} accepts a file name and uses the
486 certificates within for verification purposes.
487 """
488 cafile = self.mktemp()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400489 fObj = open(cafile, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400490 fObj.write(cleartextCertificatePEM.decode('ascii'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400491 fObj.close()
492
493 self._load_verify_locations_test(cafile)
494
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400495
496 def test_load_verify_invalid_file(self):
497 """
498 L{Context.load_verify_locations} raises L{Error} when passed a
499 non-existent cafile.
500 """
501 clientContext = Context(TLSv1_METHOD)
502 self.assertRaises(
503 Error, clientContext.load_verify_locations, self.mktemp())
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400504
505
506 def test_load_verify_directory(self):
507 """
508 L{Context.load_verify_locations} accepts a directory name and uses
509 the certificates within for verification purposes.
510 """
511 capath = self.mktemp()
512 makedirs(capath)
Jean-Paul Calderonea65cf6c2009-07-19 10:26:52 -0400513 # Hash value computed manually with c_rehash to avoid depending on
514 # c_rehash in the test suite.
515 cafile = join(capath, 'c7adac82.0')
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400516 fObj = open(cafile, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400517 fObj.write(cleartextCertificatePEM.decode('ascii'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400518 fObj.close()
519
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400520 self._load_verify_locations_test(None, capath)
521
522
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400523 def test_load_verify_locations_wrong_args(self):
524 """
525 L{Context.load_verify_locations} raises L{TypeError} if called with
526 the wrong number of arguments or with non-C{str} arguments.
527 """
528 context = Context(TLSv1_METHOD)
529 self.assertRaises(TypeError, context.load_verify_locations)
530 self.assertRaises(TypeError, context.load_verify_locations, object())
531 self.assertRaises(TypeError, context.load_verify_locations, object(), object())
532 self.assertRaises(TypeError, context.load_verify_locations, None, None, None)
533
534
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -0400535 if platform == "win32":
536 "set_default_verify_paths appears not to work on Windows. "
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400537 "See LP#404343 and LP#404344."
538 else:
539 def test_set_default_verify_paths(self):
540 """
541 L{Context.set_default_verify_paths} causes the platform-specific CA
542 certificate locations to be used for verification purposes.
543 """
544 # Testing this requires a server with a certificate signed by one of
545 # the CAs in the platform CA location. Getting one of those costs
546 # money. Fortunately (or unfortunately, depending on your
547 # perspective), it's easy to think of a public server on the
548 # internet which has such a certificate. Connecting to the network
549 # in a unit test is bad, but it's the only way I can think of to
550 # really test this. -exarkun
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400551
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400552 # Arg, verisign.com doesn't speak TLSv1
553 context = Context(SSLv3_METHOD)
554 context.set_default_verify_paths()
555 context.set_verify(
Ziga Seilnacht44611bf2009-08-31 20:49:30 +0200556 VERIFY_PEER,
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400557 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400558
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400559 client = socket()
560 client.connect(('verisign.com', 443))
561 clientSSL = Connection(context, client)
562 clientSSL.set_connect_state()
563 clientSSL.do_handshake()
564 clientSSL.send('GET / HTTP/1.0\r\n\r\n')
565 self.assertTrue(clientSSL.recv(1024))
Jean-Paul Calderone9eadb962008-09-07 21:20:44 -0400566
567
568 def test_set_default_verify_paths_signature(self):
569 """
570 L{Context.set_default_verify_paths} takes no arguments and raises
571 L{TypeError} if given any.
572 """
573 context = Context(TLSv1_METHOD)
574 self.assertRaises(TypeError, context.set_default_verify_paths, None)
575 self.assertRaises(TypeError, context.set_default_verify_paths, 1)
576 self.assertRaises(TypeError, context.set_default_verify_paths, "")
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -0500577
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400578
Jean-Paul Calderone12608a82009-11-07 10:35:15 -0500579 def test_add_extra_chain_cert_invalid_cert(self):
580 """
581 L{Context.add_extra_chain_cert} raises L{TypeError} if called with
582 other than one argument or if called with an object which is not an
583 instance of L{X509}.
584 """
585 context = Context(TLSv1_METHOD)
586 self.assertRaises(TypeError, context.add_extra_chain_cert)
587 self.assertRaises(TypeError, context.add_extra_chain_cert, object())
588 self.assertRaises(TypeError, context.add_extra_chain_cert, object(), object())
589
590
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400591 def _create_certificate_chain(self):
Jean-Paul Calderone12608a82009-11-07 10:35:15 -0500592 """
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400593 Construct and return a chain of certificates.
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400594
595 1. A new self-signed certificate authority certificate (cacert)
596 2. A new intermediate certificate signed by cacert (icert)
597 3. A new server certificate signed by icert (scert)
Jean-Paul Calderone12608a82009-11-07 10:35:15 -0500598 """
Jean-Paul Calderone9b0744c2010-09-14 18:11:01 -0400599 caext = X509Extension(b('basicConstraints'), False, b('CA:true'))
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -0500600
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400601 # Step 1
602 cakey = PKey()
603 cakey.generate_key(TYPE_RSA, 512)
604 cacert = X509()
Jean-Paul Calderone16cf03d2010-09-08 18:53:39 -0400605 cacert.get_subject().commonName = "Authority Certificate"
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400606 cacert.set_issuer(cacert.get_subject())
607 cacert.set_pubkey(cakey)
Jean-Paul Calderone4e6aed62010-09-19 10:05:34 -0400608 cacert.set_notBefore(b("20000101000000Z"))
609 cacert.set_notAfter(b("20200101000000Z"))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400610 cacert.add_extensions([caext])
Jean-Paul Calderone16cf03d2010-09-08 18:53:39 -0400611 cacert.set_serial_number(0)
612 cacert.sign(cakey, "sha1")
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -0500613
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400614 # Step 2
615 ikey = PKey()
616 ikey.generate_key(TYPE_RSA, 512)
617 icert = X509()
618 icert.get_subject().commonName = "Intermediate Certificate"
619 icert.set_issuer(cacert.get_subject())
620 icert.set_pubkey(ikey)
Jean-Paul Calderone4e6aed62010-09-19 10:05:34 -0400621 icert.set_notBefore(b("20000101000000Z"))
622 icert.set_notAfter(b("20200101000000Z"))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400623 icert.add_extensions([caext])
Jean-Paul Calderone16cf03d2010-09-08 18:53:39 -0400624 icert.set_serial_number(0)
625 icert.sign(cakey, "sha1")
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -0400626
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400627 # Step 3
628 skey = PKey()
629 skey.generate_key(TYPE_RSA, 512)
630 scert = X509()
631 scert.get_subject().commonName = "Server Certificate"
632 scert.set_issuer(icert.get_subject())
633 scert.set_pubkey(skey)
Jean-Paul Calderone4e6aed62010-09-19 10:05:34 -0400634 scert.set_notBefore(b("20000101000000Z"))
635 scert.set_notAfter(b("20200101000000Z"))
Jean-Paul Calderone2db1de52010-09-19 10:08:13 -0400636 scert.add_extensions([
637 X509Extension(b('basicConstraints'), True, b('CA:false'))])
Jean-Paul Calderone16cf03d2010-09-08 18:53:39 -0400638 scert.set_serial_number(0)
639 scert.sign(ikey, "sha1")
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -0400640
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400641 return [(cakey, cacert), (ikey, icert), (skey, scert)]
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400642
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400643
644 def _handshake_test(self, serverContext, clientContext):
645 """
646 Verify that a client and server created with the given contexts can
647 successfully handshake and communicate.
648 """
649 serverSocket, clientSocket = socket_pair()
650
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400651 server = Connection(serverContext, serverSocket)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -0400652 server.set_accept_state()
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400653
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400654 client = Connection(clientContext, clientSocket)
655 client.set_connect_state()
656
657 # Make them talk to each other.
658 # self._interactInMemory(client, server)
659 for i in range(3):
660 for s in [client, server]:
661 try:
662 s.do_handshake()
663 except WantReadError:
664 pass
665
666
667 def test_add_extra_chain_cert(self):
668 """
669 L{Context.add_extra_chain_cert} accepts an L{X509} instance to add to
670 the certificate chain.
671
672 See L{_create_certificate_chain} for the details of the certificate
673 chain tested.
674
675 The chain is tested by starting a server with scert and connecting
676 to it with a client which trusts cacert and requires verification to
677 succeed.
678 """
679 chain = self._create_certificate_chain()
680 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
681
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400682 # Dump the CA certificate to a file because that's the only way to load
683 # it as a trusted CA in the client context.
684 for cert, name in [(cacert, 'ca.pem'), (icert, 'i.pem'), (scert, 's.pem')]:
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400685 fObj = open(name, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400686 fObj.write(dump_certificate(FILETYPE_PEM, cert).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400687 fObj.close()
Jean-Paul Calderone16cf03d2010-09-08 18:53:39 -0400688 fObj = file(name.replace('pem', 'asn1'), 'w')
689 fObj.write(dump_certificate(FILETYPE_ASN1, cert))
690 fObj.close()
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400691
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 Calderone55d91f42010-07-29 19:22:17 -0400925 def test_connect_ex(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -0400926 """
927 If there is a connection error, L{Connection.connect_ex} returns the
928 errno instead of raising an exception.
929 """
Jean-Paul Calderone55d91f42010-07-29 19:22:17 -0400930 port = socket()
931 port.bind(('', 0))
932 port.listen(3)
933
934 clientSSL = Connection(Context(TLSv1_METHOD), socket())
935 clientSSL.setblocking(False)
Jean-Paul Calderone8322d782010-09-17 19:22:31 -0400936 result = clientSSL.connect_ex(port.getsockname())
937 expected = (EINPROGRESS, EWOULDBLOCK)
938 self.assertTrue(
939 result in expected, "%r not in %r" % (result, expected))
Jean-Paul Calderone55d91f42010-07-29 19:22:17 -0400940
941
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -0400942 def test_accept_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -0400943 """
944 L{Connection.accept} raises L{TypeError} if called with any arguments.
945 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -0400946 connection = Connection(Context(TLSv1_METHOD), socket())
947 self.assertRaises(TypeError, connection.accept, None)
948
949
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -0400950 def test_accept(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -0400951 """
952 L{Connection.accept} accepts a pending connection attempt and returns a
953 tuple of a new L{Connection} (the accepted client) and the address the
954 connection originated from.
955 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -0400956 ctx = Context(TLSv1_METHOD)
957 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
958 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -0400959 port = socket()
960 portSSL = Connection(ctx, port)
961 portSSL.bind(('', 0))
962 portSSL.listen(3)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -0400963
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -0400964 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -0400965
966 # Calling portSSL.getsockname() here to get the server IP address sounds
967 # great, but frequently fails on Windows.
968 clientSSL.connect(('127.0.0.1', portSSL.getsockname()[1]))
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -0400969
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -0400970 serverSSL, address = portSSL.accept()
971
972 self.assertTrue(isinstance(serverSSL, Connection))
973 self.assertIdentical(serverSSL.get_context(), ctx)
974 self.assertEquals(address, clientSSL.getsockname())
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -0400975
976
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -0400977 def test_shutdown_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -0400978 """
979 L{Connection.shutdown} raises L{TypeError} if called with the wrong
980 number of arguments or with arguments other than integers.
981 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -0400982 connection = Connection(Context(TLSv1_METHOD), None)
983 self.assertRaises(TypeError, connection.shutdown, None)
Jean-Paul Calderone1d3e0222010-07-29 22:52:45 -0400984 self.assertRaises(TypeError, connection.get_shutdown, None)
985 self.assertRaises(TypeError, connection.set_shutdown)
986 self.assertRaises(TypeError, connection.set_shutdown, None)
987 self.assertRaises(TypeError, connection.set_shutdown, 0, 1)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -0400988
989
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -0400990 def test_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -0400991 """
992 L{Connection.shutdown} performs an SSL-level connection shutdown.
993 """
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -0400994 server, client = self._loopback()
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -0400995 self.assertFalse(server.shutdown())
996 self.assertEquals(server.get_shutdown(), SENT_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -0400997 self.assertRaises(ZeroReturnError, client.recv, 1024)
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -0400998 self.assertEquals(client.get_shutdown(), RECEIVED_SHUTDOWN)
999 client.shutdown()
1000 self.assertEquals(client.get_shutdown(), SENT_SHUTDOWN|RECEIVED_SHUTDOWN)
1001 self.assertRaises(ZeroReturnError, server.recv, 1024)
1002 self.assertEquals(server.get_shutdown(), SENT_SHUTDOWN|RECEIVED_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001003
1004
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04001005 def test_set_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001006 """
1007 L{Connection.set_shutdown} sets the state of the SSL connection shutdown
1008 process.
1009 """
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04001010 connection = Connection(Context(TLSv1_METHOD), socket())
1011 connection.set_shutdown(RECEIVED_SHUTDOWN)
1012 self.assertEquals(connection.get_shutdown(), RECEIVED_SHUTDOWN)
1013
1014
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001015 def test_app_data_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001016 """
1017 L{Connection.set_app_data} raises L{TypeError} if called with other than
1018 one argument. L{Connection.get_app_data} raises L{TypeError} if called
1019 with any arguments.
1020 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001021 conn = Connection(Context(TLSv1_METHOD), None)
1022 self.assertRaises(TypeError, conn.get_app_data, None)
1023 self.assertRaises(TypeError, conn.set_app_data)
1024 self.assertRaises(TypeError, conn.set_app_data, None, None)
1025
1026
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04001027 def test_app_data(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001028 """
1029 Any object can be set as app data by passing it to
1030 L{Connection.set_app_data} and later retrieved with
1031 L{Connection.get_app_data}.
1032 """
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04001033 conn = Connection(Context(TLSv1_METHOD), None)
1034 app_data = object()
1035 conn.set_app_data(app_data)
1036 self.assertIdentical(conn.get_app_data(), app_data)
1037
1038
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001039 def test_makefile(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001040 """
1041 L{Connection.makefile} is not implemented and calling that method raises
1042 L{NotImplementedError}.
1043 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001044 conn = Connection(Context(TLSv1_METHOD), None)
1045 self.assertRaises(NotImplementedError, conn.makefile)
1046
1047
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001048
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04001049class ConnectionGetCipherListTests(TestCase):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001050 """
1051 Tests for L{Connection.get_cipher_list}.
1052 """
Jean-Paul Calderone54a2bc02010-09-09 17:52:38 -04001053 def test_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001054 """
1055 L{Connection.get_cipher_list} raises L{TypeError} if called with any
1056 arguments.
1057 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04001058 connection = Connection(Context(TLSv1_METHOD), None)
1059 self.assertRaises(TypeError, connection.get_cipher_list, None)
1060
1061
1062 def test_result(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001063 """
1064 L{Connection.get_cipher_list} returns a C{list} of C{str} giving the
1065 names of the ciphers which might be used.
1066 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04001067 connection = Connection(Context(TLSv1_METHOD), None)
1068 ciphers = connection.get_cipher_list()
1069 self.assertTrue(isinstance(ciphers, list))
1070 for cipher in ciphers:
1071 self.assertTrue(isinstance(cipher, str))
1072
1073
1074
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04001075class ConnectionSendallTests(TestCase, _LoopbackMixin):
1076 """
1077 Tests for L{Connection.sendall}.
1078 """
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001079 def test_wrong_args(self):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04001080 """
1081 When called with arguments other than a single string,
1082 L{Connection.sendall} raises L{TypeError}.
1083 """
1084 connection = Connection(Context(TLSv1_METHOD), None)
1085 self.assertRaises(TypeError, connection.sendall)
1086 self.assertRaises(TypeError, connection.sendall, object())
1087 self.assertRaises(TypeError, connection.sendall, "foo", "bar")
1088
1089
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001090 def test_short(self):
1091 """
1092 L{Connection.sendall} transmits all of the bytes in the string passed to
1093 it.
1094 """
1095 server, client = self._loopback()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04001096 server.sendall(b('x'))
1097 self.assertEquals(client.recv(1), b('x'))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001098
1099
1100 def test_long(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001101 """
1102 L{Connection.sendall} transmits all of the bytes in the string passed to
1103 it even if this requires multiple calls of an underlying write function.
1104 """
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001105 server, client = self._loopback()
Jean-Paul Calderone6241c702010-09-16 19:59:24 -04001106 # Should be enough, underlying SSL_write should only do 16k at a time.
1107 # On Windows, after 32k of bytes the write will block (forever - because
1108 # no one is yet reading).
Jean-Paul Calderone9e4c1352010-09-19 09:34:43 -04001109 message = b('x') * (1024 * 32 - 1) + b('y')
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001110 server.sendall(message)
1111 accum = []
1112 received = 0
1113 while received < len(message):
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04001114 data = client.recv(1024)
1115 accum.append(data)
1116 received += len(data)
Jean-Paul Calderonef4047852010-09-19 09:45:57 -04001117 self.assertEquals(message, b('').join(accum))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001118
1119
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04001120 def test_closed(self):
1121 """
1122 If the underlying socket is closed, L{Connection.sendall} propagates the
1123 write error from the low level write call.
1124 """
1125 server, client = self._loopback()
1126 client.close()
1127 server.sendall("hello, world")
1128 self.assertRaises(SysCallError, server.sendall, "hello, world")
1129
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001130
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04001131
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04001132class ConnectionRenegotiateTests(TestCase, _LoopbackMixin):
1133 """
1134 Tests for SSL renegotiation APIs.
1135 """
1136 def test_renegotiate_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001137 """
1138 L{Connection.renegotiate} raises L{TypeError} if called with any
1139 arguments.
1140 """
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04001141 connection = Connection(Context(TLSv1_METHOD), None)
1142 self.assertRaises(TypeError, connection.renegotiate, None)
1143
1144
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001145 def test_total_renegotiations_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001146 """
1147 L{Connection.total_renegotiations} raises L{TypeError} if called with
1148 any arguments.
1149 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001150 connection = Connection(Context(TLSv1_METHOD), None)
1151 self.assertRaises(TypeError, connection.total_renegotiations, None)
1152
1153
1154 def test_total_renegotiations(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001155 """
1156 L{Connection.total_renegotiations} returns C{0} before any
1157 renegotiations have happened.
1158 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001159 connection = Connection(Context(TLSv1_METHOD), None)
1160 self.assertEquals(connection.total_renegotiations(), 0)
1161
1162
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04001163# def test_renegotiate(self):
1164# """
1165# """
1166# server, client = self._loopback()
1167
1168# server.send("hello world")
1169# self.assertEquals(client.recv(len("hello world")), "hello world")
1170
1171# self.assertEquals(server.total_renegotiations(), 0)
1172# self.assertTrue(server.renegotiate())
1173
1174# server.setblocking(False)
1175# client.setblocking(False)
1176# while server.renegotiate_pending():
1177# client.do_handshake()
1178# server.do_handshake()
1179
1180# self.assertEquals(server.total_renegotiations(), 1)
1181
1182
1183
1184
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001185class ErrorTests(TestCase):
1186 """
1187 Unit tests for L{OpenSSL.SSL.Error}.
1188 """
1189 def test_type(self):
1190 """
1191 L{Error} is an exception type.
1192 """
1193 self.assertTrue(issubclass(Error, Exception))
Rick Deane15b1472009-07-09 15:53:42 -05001194 self.assertEqual(Error.__name__, 'Error')
Rick Deane15b1472009-07-09 15:53:42 -05001195
1196
1197
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05001198class ConstantsTests(TestCase):
1199 """
1200 Tests for the values of constants exposed in L{OpenSSL.SSL}.
1201
1202 These are values defined by OpenSSL intended only to be used as flags to
1203 OpenSSL APIs. The only assertions it seems can be made about them is
1204 their values.
1205 """
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05001206 # unittest.TestCase has no skip mechanism
1207 if OP_NO_QUERY_MTU is not None:
1208 def test_op_no_query_mtu(self):
1209 """
1210 The value of L{OpenSSL.SSL.OP_NO_QUERY_MTU} is 0x1000, the value of
1211 I{SSL_OP_NO_QUERY_MTU} defined by I{openssl/ssl.h}.
1212 """
1213 self.assertEqual(OP_NO_QUERY_MTU, 0x1000)
1214 else:
1215 "OP_NO_QUERY_MTU unavailable - OpenSSL version may be too old"
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05001216
1217
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05001218 if OP_COOKIE_EXCHANGE is not None:
1219 def test_op_cookie_exchange(self):
1220 """
1221 The value of L{OpenSSL.SSL.OP_COOKIE_EXCHANGE} is 0x2000, the value
1222 of I{SSL_OP_COOKIE_EXCHANGE} defined by I{openssl/ssl.h}.
1223 """
1224 self.assertEqual(OP_COOKIE_EXCHANGE, 0x2000)
1225 else:
1226 "OP_COOKIE_EXCHANGE unavailable - OpenSSL version may be too old"
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05001227
1228
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05001229 if OP_NO_TICKET is not None:
1230 def test_op_no_ticket(self):
1231 """
1232 The value of L{OpenSSL.SSL.OP_NO_TICKET} is 0x4000, the value of
1233 I{SSL_OP_NO_TICKET} defined by I{openssl/ssl.h}.
1234 """
1235 self.assertEqual(OP_NO_TICKET, 0x4000)
1236 else:
1237 "OP_NO_TICKET unavailable - OpenSSL version may be too old"
Rick Dean5b7b6372009-04-01 11:34:06 -05001238
1239
Jean-Paul Calderoneeeee26a2009-04-27 11:24:30 -04001240
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001241class MemoryBIOTests(TestCase, _LoopbackMixin):
Rick Deanb71c0d22009-04-01 14:09:23 -05001242 """
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04001243 Tests for L{OpenSSL.SSL.Connection} using a memory BIO.
Rick Deanb71c0d22009-04-01 14:09:23 -05001244 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04001245 def _server(self, sock):
1246 """
1247 Create a new server-side SSL L{Connection} object wrapped around
1248 C{sock}.
1249 """
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04001250 # Create the server side Connection. This is mostly setup boilerplate
1251 # - use TLSv1, use a particular certificate, etc.
1252 server_ctx = Context(TLSv1_METHOD)
1253 server_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE )
1254 server_ctx.set_verify(VERIFY_PEER|VERIFY_FAIL_IF_NO_PEER_CERT|VERIFY_CLIENT_ONCE, verify_cb)
1255 server_store = server_ctx.get_cert_store()
1256 server_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1257 server_ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
1258 server_ctx.check_privatekey()
1259 server_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05001260 # Here the Connection is actually created. If None is passed as the 2nd
1261 # parameter, it indicates a memory BIO should be created.
1262 server_conn = Connection(server_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04001263 server_conn.set_accept_state()
1264 return server_conn
1265
1266
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04001267 def _client(self, sock):
1268 """
1269 Create a new client-side SSL L{Connection} object wrapped around
1270 C{sock}.
1271 """
1272 # Now create the client side Connection. Similar boilerplate to the
1273 # above.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04001274 client_ctx = Context(TLSv1_METHOD)
1275 client_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE )
1276 client_ctx.set_verify(VERIFY_PEER|VERIFY_FAIL_IF_NO_PEER_CERT|VERIFY_CLIENT_ONCE, verify_cb)
1277 client_store = client_ctx.get_cert_store()
1278 client_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, client_key_pem))
1279 client_ctx.use_certificate(load_certificate(FILETYPE_PEM, client_cert_pem))
1280 client_ctx.check_privatekey()
1281 client_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05001282 client_conn = Connection(client_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04001283 client_conn.set_connect_state()
1284 return client_conn
1285
1286
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04001287 def test_memoryConnect(self):
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04001288 """
1289 Two L{Connection}s which use memory BIOs can be manually connected by
1290 reading from the output of each and writing those bytes to the input of
1291 the other and in this way establish a connection and exchange
1292 application-level bytes with each other.
1293 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04001294 server_conn = self._server(None)
1295 client_conn = self._client(None)
Rick Deanb71c0d22009-04-01 14:09:23 -05001296
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04001297 # There should be no key or nonces yet.
1298 self.assertIdentical(server_conn.master_key(), None)
1299 self.assertIdentical(server_conn.client_random(), None)
1300 self.assertIdentical(server_conn.server_random(), None)
Rick Deanb71c0d22009-04-01 14:09:23 -05001301
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04001302 # First, the handshake needs to happen. We'll deliver bytes back and
1303 # forth between the client and server until neither of them feels like
1304 # speaking any more.
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001305 self.assertIdentical(
1306 self._interactInMemory(client_conn, server_conn), None)
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04001307
1308 # Now that the handshake is done, there should be a key and nonces.
1309 self.assertNotIdentical(server_conn.master_key(), None)
1310 self.assertNotIdentical(server_conn.client_random(), None)
1311 self.assertNotIdentical(server_conn.server_random(), None)
Jean-Paul Calderone6c051e62009-07-05 13:50:34 -04001312 self.assertEquals(server_conn.client_random(), client_conn.client_random())
1313 self.assertEquals(server_conn.server_random(), client_conn.server_random())
1314 self.assertNotEquals(server_conn.client_random(), server_conn.server_random())
1315 self.assertNotEquals(client_conn.client_random(), client_conn.server_random())
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04001316
1317 # Here are the bytes we'll try to send.
Jean-Paul Calderonea441fdc2010-08-22 21:33:57 -04001318 important_message = b('One if by land, two if by sea.')
Rick Deanb71c0d22009-04-01 14:09:23 -05001319
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04001320 server_conn.write(important_message)
1321 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001322 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04001323 (client_conn, important_message))
1324
1325 client_conn.write(important_message[::-1])
1326 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001327 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04001328 (server_conn, important_message[::-1]))
Rick Deanb71c0d22009-04-01 14:09:23 -05001329
1330
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04001331 def test_socketConnect(self):
Rick Deanb1ccd562009-07-09 23:52:39 -05001332 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04001333 Just like L{test_memoryConnect} but with an actual socket.
1334
1335 This is primarily to rule out the memory BIO code as the source of
1336 any problems encountered while passing data over a L{Connection} (if
1337 this test fails, there must be a problem outside the memory BIO
1338 code, as no memory BIO is involved here). Even though this isn't a
1339 memory BIO test, it's convenient to have it here.
Rick Deanb1ccd562009-07-09 23:52:39 -05001340 """
1341 (server, client) = socket_pair()
1342
1343 # Let the encryption begin...
1344 client_conn = self._client(client)
Rick Deanb1ccd562009-07-09 23:52:39 -05001345 server_conn = self._server(server)
Jean-Paul Calderone7903cbd2009-07-16 12:23:34 -04001346
Rick Deanb1ccd562009-07-09 23:52:39 -05001347 # Establish the connection
1348 established = False
1349 while not established:
1350 established = True # assume the best
1351 for ssl in client_conn, server_conn:
1352 try:
Ziga Seilnacht44611bf2009-08-31 20:49:30 +02001353 # Generally a recv() or send() could also work instead
1354 # of do_handshake(), and we would stop on the first
Rick Deanb1ccd562009-07-09 23:52:39 -05001355 # non-exception.
1356 ssl.do_handshake()
1357 except WantReadError:
1358 established = False
1359
Jean-Paul Calderonea441fdc2010-08-22 21:33:57 -04001360 important_message = b("Help me Obi Wan Kenobi, you're my only hope.")
Rick Deanb1ccd562009-07-09 23:52:39 -05001361 client_conn.send(important_message)
1362 msg = server_conn.recv(1024)
1363 self.assertEqual(msg, important_message)
1364
1365 # Again in the other direction, just for fun.
1366 important_message = important_message[::-1]
1367 server_conn.send(important_message)
1368 msg = client_conn.recv(1024)
1369 self.assertEqual(msg, important_message)
1370
1371
Jean-Paul Calderonefc4ed0f2009-04-27 11:51:27 -04001372 def test_socketOverridesMemory(self):
Rick Deanb71c0d22009-04-01 14:09:23 -05001373 """
1374 Test that L{OpenSSL.SSL.bio_read} and L{OpenSSL.SSL.bio_write} don't
1375 work on L{OpenSSL.SSL.Connection}() that use sockets.
1376 """
1377 context = Context(SSLv3_METHOD)
1378 client = socket()
1379 clientSSL = Connection(context, client)
1380 self.assertRaises( TypeError, clientSSL.bio_read, 100)
1381 self.assertRaises( TypeError, clientSSL.bio_write, "foo")
Jean-Paul Calderone07acf3f2009-05-05 13:23:28 -04001382 self.assertRaises( TypeError, clientSSL.bio_shutdown )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04001383
1384
1385 def test_outgoingOverflow(self):
1386 """
1387 If more bytes than can be written to the memory BIO are passed to
1388 L{Connection.send} at once, the number of bytes which were written is
1389 returned and that many bytes from the beginning of the input can be
1390 read from the other end of the connection.
1391 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04001392 server = self._server(None)
1393 client = self._client(None)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04001394
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001395 self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04001396
1397 size = 2 ** 15
1398 sent = client.send("x" * size)
1399 # Sanity check. We're trying to test what happens when the entire
1400 # input can't be sent. If the entire input was sent, this test is
1401 # meaningless.
1402 self.assertTrue(sent < size)
1403
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001404 receiver, received = self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04001405 self.assertIdentical(receiver, server)
1406
1407 # We can rely on all of these bytes being received at once because
1408 # _loopback passes 2 ** 16 to recv - more than 2 ** 15.
1409 self.assertEquals(len(received), sent)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04001410
1411
1412 def test_shutdown(self):
1413 """
1414 L{Connection.bio_shutdown} signals the end of the data stream from
1415 which the L{Connection} reads.
1416 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04001417 server = self._server(None)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04001418 server.bio_shutdown()
1419 e = self.assertRaises(Error, server.recv, 1024)
1420 # We don't want WantReadError or ZeroReturnError or anything - it's a
1421 # handshake failure.
1422 self.assertEquals(e.__class__, Error)
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04001423
1424
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001425 def _check_client_ca_list(self, func):
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001426 """
1427 Verify the return value of the C{get_client_ca_list} method for server and client connections.
1428
1429 @param func: A function which will be called with the server context
1430 before the client and server are connected to each other. This
1431 function should specify a list of CAs for the server to send to the
1432 client and return that same list. The list will be used to verify
1433 that C{get_client_ca_list} returns the proper value at various
1434 times.
1435 """
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001436 server = self._server(None)
1437 client = self._client(None)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001438 self.assertEqual(client.get_client_ca_list(), [])
1439 self.assertEqual(server.get_client_ca_list(), [])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001440 ctx = server.get_context()
1441 expected = func(ctx)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001442 self.assertEqual(client.get_client_ca_list(), [])
1443 self.assertEqual(server.get_client_ca_list(), expected)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001444 self._interactInMemory(client, server)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001445 self.assertEqual(client.get_client_ca_list(), expected)
1446 self.assertEqual(server.get_client_ca_list(), expected)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001447
1448
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001449 def test_set_client_ca_list_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001450 """
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001451 L{Context.set_client_ca_list} raises a L{TypeError} if called with a
1452 non-list or a list that contains objects other than X509Names.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001453 """
1454 ctx = Context(TLSv1_METHOD)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001455 self.assertRaises(TypeError, ctx.set_client_ca_list, "spam")
1456 self.assertRaises(TypeError, ctx.set_client_ca_list, ["spam"])
1457 self.assertIdentical(ctx.set_client_ca_list([]), None)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001458
1459
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001460 def test_set_empty_ca_list(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001461 """
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001462 If passed an empty list, L{Context.set_client_ca_list} configures the
1463 context to send no CA names to the client and, on both the server and
1464 client sides, L{Connection.get_client_ca_list} returns an empty list
1465 after the connection is set up.
1466 """
1467 def no_ca(ctx):
1468 ctx.set_client_ca_list([])
1469 return []
1470 self._check_client_ca_list(no_ca)
1471
1472
1473 def test_set_one_ca_list(self):
1474 """
1475 If passed a list containing a single X509Name,
1476 L{Context.set_client_ca_list} configures the context to send that CA
1477 name to the client and, on both the server and client sides,
1478 L{Connection.get_client_ca_list} returns a list containing that
1479 X509Name after the connection is set up.
1480 """
1481 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
1482 cadesc = cacert.get_subject()
1483 def single_ca(ctx):
1484 ctx.set_client_ca_list([cadesc])
1485 return [cadesc]
1486 self._check_client_ca_list(single_ca)
1487
1488
1489 def test_set_multiple_ca_list(self):
1490 """
1491 If passed a list containing multiple X509Name objects,
1492 L{Context.set_client_ca_list} configures the context to send those CA
1493 names to the client and, on both the server and client sides,
1494 L{Connection.get_client_ca_list} returns a list containing those
1495 X509Names after the connection is set up.
1496 """
1497 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
1498 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
1499
1500 sedesc = secert.get_subject()
1501 cldesc = clcert.get_subject()
1502
1503 def multiple_ca(ctx):
1504 L = [sedesc, cldesc]
1505 ctx.set_client_ca_list(L)
1506 return L
1507 self._check_client_ca_list(multiple_ca)
1508
1509
1510 def test_reset_ca_list(self):
1511 """
1512 If called multiple times, only the X509Names passed to the final call
1513 of L{Context.set_client_ca_list} are used to configure the CA names
1514 sent to the client.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001515 """
1516 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
1517 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
1518 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
1519
1520 cadesc = cacert.get_subject()
1521 sedesc = secert.get_subject()
1522 cldesc = clcert.get_subject()
1523
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001524 def changed_ca(ctx):
1525 ctx.set_client_ca_list([sedesc, cldesc])
1526 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001527 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001528 self._check_client_ca_list(changed_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001529
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001530
1531 def test_mutated_ca_list(self):
1532 """
1533 If the list passed to L{Context.set_client_ca_list} is mutated
1534 afterwards, this does not affect the list of CA names sent to the
1535 client.
1536 """
1537 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
1538 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
1539
1540 cadesc = cacert.get_subject()
1541 sedesc = secert.get_subject()
1542
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001543 def mutated_ca(ctx):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001544 L = [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001545 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001546 L.append(sedesc)
1547 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001548 self._check_client_ca_list(mutated_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001549
1550
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001551 def test_add_client_ca_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001552 """
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001553 L{Context.add_client_ca} raises L{TypeError} if called with a non-X509
1554 object or with a number of arguments other than one.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001555 """
1556 ctx = Context(TLSv1_METHOD)
1557 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001558 self.assertRaises(TypeError, ctx.add_client_ca)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001559 self.assertRaises(TypeError, ctx.add_client_ca, "spam")
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001560 self.assertRaises(TypeError, ctx.add_client_ca, cacert, cacert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001561
1562
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04001563 def test_one_add_client_ca(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001564 """
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04001565 A certificate's subject can be added as a CA to be sent to the client
1566 with L{Context.add_client_ca}.
1567 """
1568 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
1569 cadesc = cacert.get_subject()
1570 def single_ca(ctx):
1571 ctx.add_client_ca(cacert)
1572 return [cadesc]
1573 self._check_client_ca_list(single_ca)
1574
1575
1576 def test_multiple_add_client_ca(self):
1577 """
1578 Multiple CA names can be sent to the client by calling
1579 L{Context.add_client_ca} with multiple X509 objects.
1580 """
1581 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
1582 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
1583
1584 cadesc = cacert.get_subject()
1585 sedesc = secert.get_subject()
1586
1587 def multiple_ca(ctx):
1588 ctx.add_client_ca(cacert)
1589 ctx.add_client_ca(secert)
1590 return [cadesc, sedesc]
1591 self._check_client_ca_list(multiple_ca)
1592
1593
1594 def test_set_and_add_client_ca(self):
1595 """
1596 A call to L{Context.set_client_ca_list} followed by a call to
1597 L{Context.add_client_ca} results in using the CA names from the first
1598 call and the CA name from the second call.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001599 """
1600 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
1601 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
1602 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
1603
1604 cadesc = cacert.get_subject()
1605 sedesc = secert.get_subject()
1606 cldesc = clcert.get_subject()
1607
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001608 def mixed_set_add_ca(ctx):
1609 ctx.set_client_ca_list([cadesc, sedesc])
1610 ctx.add_client_ca(clcert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001611 return [cadesc, sedesc, cldesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001612 self._check_client_ca_list(mixed_set_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001613
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04001614
1615 def test_set_after_add_client_ca(self):
1616 """
1617 A call to L{Context.set_client_ca_list} after a call to
1618 L{Context.add_client_ca} replaces the CA name specified by the former
1619 call with the names specified by the latter cal.
1620 """
1621 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
1622 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
1623 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
1624
1625 cadesc = cacert.get_subject()
1626 sedesc = secert.get_subject()
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04001627
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001628 def set_replaces_add_ca(ctx):
1629 ctx.add_client_ca(clcert)
1630 ctx.set_client_ca_list([cadesc])
1631 ctx.add_client_ca(secert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001632 return [cadesc, sedesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001633 self._check_client_ca_list(set_replaces_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001634
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04001635
Ziga Seilnacht44611bf2009-08-31 20:49:30 +02001636
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04001637if __name__ == '__main__':
1638 main()