blob: ff2e725200f5d85e78248472155d32fb7871d266 [file] [log] [blame]
Jean-Paul Calderone8671c852011-03-02 19:26:20 -05001# Copyright (C) Jean-Paul Calderone
2# See LICENSE for details.
Jean-Paul Calderone8b63d452008-03-21 18:31:12 -04003
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -04004"""
5Unit tests for L{OpenSSL.SSL}.
6"""
7
Jean-Paul Calderone8322d782010-09-17 19:22:31 -04008from errno import ECONNREFUSED, EINPROGRESS, EWOULDBLOCK
Jean-Paul Calderone52f0d8b2009-03-07 09:10:19 -05009from sys import platform
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -040010from socket import error, socket
Jean-Paul Calderonea65cf6c2009-07-19 10:26:52 -040011from os import makedirs
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -040012from os.path import join
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -040013from unittest import main
Jean-Paul Calderone460cc1f2009-03-07 11:31:12 -050014
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040015from OpenSSL.crypto import TYPE_RSA, FILETYPE_PEM, FILETYPE_ASN1
16from OpenSSL.crypto import PKey, X509, X509Extension
17from OpenSSL.crypto import dump_privatekey, load_privatekey
18from OpenSSL.crypto import dump_certificate, load_certificate
19
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -040020from OpenSSL.SSL import OPENSSL_VERSION_NUMBER, SSLEAY_VERSION, SSLEAY_CFLAGS
21from OpenSSL.SSL import SSLEAY_PLATFORM, SSLEAY_DIR, SSLEAY_BUILT_ON
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -040022from OpenSSL.SSL import SENT_SHUTDOWN, RECEIVED_SHUTDOWN
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -040023from OpenSSL.SSL import SSLv2_METHOD, SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD
Jean-Paul Calderone68649052009-07-17 21:14:27 -040024from OpenSSL.SSL import OP_NO_SSLv2, OP_NO_SSLv3, OP_SINGLE_DH_USE
Rick Deanb71c0d22009-04-01 14:09:23 -050025from OpenSSL.SSL import VERIFY_PEER, VERIFY_FAIL_IF_NO_PEER_CERT, VERIFY_CLIENT_ONCE
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -040026from OpenSSL.SSL import Error, SysCallError, WantReadError, ZeroReturnError, SSLeay_version
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040027from OpenSSL.SSL import Context, ContextType, Connection, ConnectionType
28
Jean-Paul Calderone9e4eeae2010-08-22 21:32:52 -040029from OpenSSL.test.util import TestCase, bytes, b
Jean-Paul Calderone18808652009-07-05 12:54:05 -040030from OpenSSL.test.test_crypto import cleartextCertificatePEM, cleartextPrivateKeyPEM
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040031from OpenSSL.test.test_crypto import client_cert_pem, client_key_pem
32from OpenSSL.test.test_crypto import server_cert_pem, server_key_pem, root_cert_pem
Jean-Paul Calderone4bccf5e2008-12-28 22:50:42 -050033try:
34 from OpenSSL.SSL import OP_NO_QUERY_MTU
35except ImportError:
36 OP_NO_QUERY_MTU = None
37try:
38 from OpenSSL.SSL import OP_COOKIE_EXCHANGE
39except ImportError:
40 OP_COOKIE_EXCHANGE = None
41try:
42 from OpenSSL.SSL import OP_NO_TICKET
43except ImportError:
44 OP_NO_TICKET = None
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -040045
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -040046from OpenSSL.SSL import (
47 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK, SSL_ST_INIT, SSL_ST_BEFORE,
48 SSL_ST_OK, SSL_ST_RENEGOTIATE,
49 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
50 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
51 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
52 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE)
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -040053
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -040054# openssl dhparam 128 -out dh-128.pem (note that 128 is a small number of bits
55# to use)
56dhparam = """\
57-----BEGIN DH PARAMETERS-----
58MBYCEQCobsg29c9WZP/54oAPcwiDAgEC
59-----END DH PARAMETERS-----
60"""
61
62
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -040063def verify_cb(conn, cert, errnum, depth, ok):
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -040064 return ok
65
Rick Deanb1ccd562009-07-09 23:52:39 -050066def socket_pair():
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -040067 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -040068 Establish and return a pair of network sockets connected to each other.
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -040069 """
70 # Connect a pair of sockets
Rick Deanb1ccd562009-07-09 23:52:39 -050071 port = socket()
72 port.bind(('', 0))
73 port.listen(1)
74 client = socket()
75 client.setblocking(False)
Jean-Paul Calderonef23c5d92009-07-23 17:58:15 -040076 client.connect_ex(("127.0.0.1", port.getsockname()[1]))
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -040077 client.setblocking(True)
Rick Deanb1ccd562009-07-09 23:52:39 -050078 server = port.accept()[0]
Rick Deanb1ccd562009-07-09 23:52:39 -050079
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -040080 # Let's pass some unencrypted data to make sure our socket connection is
81 # fine. Just one byte, so we don't have to worry about buffers getting
82 # filled up or fragmentation.
Jean-Paul Calderone9e4eeae2010-08-22 21:32:52 -040083 server.send(b("x"))
84 assert client.recv(1024) == b("x")
85 client.send(b("y"))
86 assert server.recv(1024) == b("y")
Rick Deanb1ccd562009-07-09 23:52:39 -050087
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -040088 # Most of our callers want non-blocking sockets, make it easy for them.
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -040089 server.setblocking(False)
90 client.setblocking(False)
91
Rick Deanb1ccd562009-07-09 23:52:39 -050092 return (server, client)
93
94
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -040095
Jean-Paul Calderonef8742032010-09-25 00:00:32 -040096def handshake(client, server):
97 conns = [client, server]
98 while conns:
99 for conn in conns:
100 try:
101 conn.do_handshake()
102 except WantReadError:
103 pass
104 else:
105 conns.remove(conn)
106
107
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400108class _LoopbackMixin:
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400109 """
110 Helper mixin which defines methods for creating a connected socket pair and
111 for forcing two connected SSL sockets to talk to each other via memory BIOs.
112 """
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400113 def _loopback(self):
114 (server, client) = socket_pair()
115
116 ctx = Context(TLSv1_METHOD)
117 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
118 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
119 server = Connection(ctx, server)
120 server.set_accept_state()
121 client = Connection(Context(TLSv1_METHOD), client)
122 client.set_connect_state()
123
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400124 handshake(client, server)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400125
126 server.setblocking(True)
127 client.setblocking(True)
128 return server, client
129
130
131 def _interactInMemory(self, client_conn, server_conn):
132 """
133 Try to read application bytes from each of the two L{Connection}
134 objects. Copy bytes back and forth between their send/receive buffers
135 for as long as there is anything to copy. When there is nothing more
136 to copy, return C{None}. If one of them actually manages to deliver
137 some application bytes, return a two-tuple of the connection from which
138 the bytes were read and the bytes themselves.
139 """
140 wrote = True
141 while wrote:
142 # Loop until neither side has anything to say
143 wrote = False
144
145 # Copy stuff from each side's send buffer to the other side's
146 # receive buffer.
147 for (read, write) in [(client_conn, server_conn),
148 (server_conn, client_conn)]:
149
150 # Give the side a chance to generate some more bytes, or
151 # succeed.
152 try:
153 bytes = read.recv(2 ** 16)
154 except WantReadError:
155 # It didn't succeed, so we'll hope it generated some
156 # output.
157 pass
158 else:
159 # It did succeed, so we'll stop now and let the caller deal
160 # with it.
161 return (read, bytes)
162
163 while True:
164 # Keep copying as long as there's more stuff there.
165 try:
166 dirty = read.bio_read(4096)
167 except WantReadError:
168 # Okay, nothing more waiting to be sent. Stop
169 # processing this send buffer.
170 break
171 else:
172 # Keep track of the fact that someone generated some
173 # output.
174 wrote = True
175 write.bio_write(dirty)
176
177
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400178class VersionTests(TestCase):
179 """
180 Tests for version information exposed by
181 L{OpenSSL.SSL.SSLeay_version} and
182 L{OpenSSL.SSL.OPENSSL_VERSION_NUMBER}.
183 """
184 def test_OPENSSL_VERSION_NUMBER(self):
185 """
186 L{OPENSSL_VERSION_NUMBER} is an integer with status in the low
187 byte and the patch, fix, minor, and major versions in the
188 nibbles above that.
189 """
190 self.assertTrue(isinstance(OPENSSL_VERSION_NUMBER, int))
191
192
193 def test_SSLeay_version(self):
194 """
195 L{SSLeay_version} takes a version type indicator and returns
196 one of a number of version strings based on that indicator.
197 """
198 versions = {}
199 for t in [SSLEAY_VERSION, SSLEAY_CFLAGS, SSLEAY_BUILT_ON,
200 SSLEAY_PLATFORM, SSLEAY_DIR]:
201 version = SSLeay_version(t)
202 versions[version] = t
203 self.assertTrue(isinstance(version, bytes))
204 self.assertEqual(len(versions), 5)
205
206
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400207
208class ContextTests(TestCase, _LoopbackMixin):
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400209 """
210 Unit tests for L{OpenSSL.SSL.Context}.
211 """
212 def test_method(self):
213 """
214 L{Context} can be instantiated with one of L{SSLv2_METHOD},
215 L{SSLv3_METHOD}, L{SSLv23_METHOD}, or L{TLSv1_METHOD}.
216 """
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400217 for meth in [SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD]:
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400218 Context(meth)
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400219
220 try:
221 Context(SSLv2_METHOD)
222 except ValueError:
223 # Some versions of OpenSSL have SSLv2, some don't.
224 # Difficult to say in advance.
225 pass
226
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400227 self.assertRaises(TypeError, Context, "")
228 self.assertRaises(ValueError, Context, 10)
229
230
Rick Deane15b1472009-07-09 15:53:42 -0500231 def test_type(self):
232 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400233 L{Context} and L{ContextType} refer to the same type object and can be
234 used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -0500235 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400236 self.assertIdentical(Context, ContextType)
237 self.assertConsistentType(Context, 'Context', TLSv1_METHOD)
Rick Deane15b1472009-07-09 15:53:42 -0500238
239
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400240 def test_use_privatekey(self):
241 """
242 L{Context.use_privatekey} takes an L{OpenSSL.crypto.PKey} instance.
243 """
244 key = PKey()
245 key.generate_key(TYPE_RSA, 128)
246 ctx = Context(TLSv1_METHOD)
247 ctx.use_privatekey(key)
248 self.assertRaises(TypeError, ctx.use_privatekey, "")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400249
250
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400251 def test_set_app_data_wrong_args(self):
252 """
253 L{Context.set_app_data} raises L{TypeError} if called with other than
254 one argument.
255 """
256 context = Context(TLSv1_METHOD)
257 self.assertRaises(TypeError, context.set_app_data)
258 self.assertRaises(TypeError, context.set_app_data, None, None)
259
260
261 def test_get_app_data_wrong_args(self):
262 """
263 L{Context.get_app_data} raises L{TypeError} if called with any
264 arguments.
265 """
266 context = Context(TLSv1_METHOD)
267 self.assertRaises(TypeError, context.get_app_data, None)
268
269
270 def test_app_data(self):
271 """
272 L{Context.set_app_data} stores an object for later retrieval using
273 L{Context.get_app_data}.
274 """
275 app_data = object()
276 context = Context(TLSv1_METHOD)
277 context.set_app_data(app_data)
278 self.assertIdentical(context.get_app_data(), app_data)
279
280
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400281 def test_set_options_wrong_args(self):
282 """
283 L{Context.set_options} raises L{TypeError} if called with the wrong
284 number of arguments or a non-C{int} argument.
285 """
286 context = Context(TLSv1_METHOD)
287 self.assertRaises(TypeError, context.set_options)
288 self.assertRaises(TypeError, context.set_options, None)
289 self.assertRaises(TypeError, context.set_options, 1, None)
290
291
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400292 def test_set_timeout_wrong_args(self):
293 """
294 L{Context.set_timeout} raises L{TypeError} if called with the wrong
295 number of arguments or a non-C{int} argument.
296 """
297 context = Context(TLSv1_METHOD)
298 self.assertRaises(TypeError, context.set_timeout)
299 self.assertRaises(TypeError, context.set_timeout, None)
300 self.assertRaises(TypeError, context.set_timeout, 1, None)
301
302
303 def test_get_timeout_wrong_args(self):
304 """
305 L{Context.get_timeout} raises L{TypeError} if called with any arguments.
306 """
307 context = Context(TLSv1_METHOD)
308 self.assertRaises(TypeError, context.get_timeout, None)
309
310
311 def test_timeout(self):
312 """
313 L{Context.set_timeout} sets the session timeout for all connections
314 created using the context object. L{Context.get_timeout} retrieves this
315 value.
316 """
317 context = Context(TLSv1_METHOD)
318 context.set_timeout(1234)
319 self.assertEquals(context.get_timeout(), 1234)
320
321
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400322 def test_set_verify_depth_wrong_args(self):
323 """
324 L{Context.set_verify_depth} raises L{TypeError} if called with the wrong
325 number of arguments or a non-C{int} argument.
326 """
327 context = Context(TLSv1_METHOD)
328 self.assertRaises(TypeError, context.set_verify_depth)
329 self.assertRaises(TypeError, context.set_verify_depth, None)
330 self.assertRaises(TypeError, context.set_verify_depth, 1, None)
331
332
333 def test_get_verify_depth_wrong_args(self):
334 """
335 L{Context.get_verify_depth} raises L{TypeError} if called with any arguments.
336 """
337 context = Context(TLSv1_METHOD)
338 self.assertRaises(TypeError, context.get_verify_depth, None)
339
340
341 def test_verify_depth(self):
342 """
343 L{Context.set_verify_depth} sets the number of certificates in a chain
344 to follow before giving up. The value can be retrieved with
345 L{Context.get_verify_depth}.
346 """
347 context = Context(TLSv1_METHOD)
348 context.set_verify_depth(11)
349 self.assertEquals(context.get_verify_depth(), 11)
350
351
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400352 def _write_encrypted_pem(self, passphrase):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400353 """
354 Write a new private key out to a new file, encrypted using the given
355 passphrase. Return the path to the new file.
356 """
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400357 key = PKey()
358 key.generate_key(TYPE_RSA, 128)
359 pemFile = self.mktemp()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400360 fObj = open(pemFile, 'w')
361 pem = dump_privatekey(FILETYPE_PEM, key, "blowfish", passphrase)
362 fObj.write(pem.decode('ascii'))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400363 fObj.close()
364 return pemFile
365
366
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400367 def test_set_passwd_cb_wrong_args(self):
368 """
369 L{Context.set_passwd_cb} raises L{TypeError} if called with the
370 wrong arguments or with a non-callable first argument.
371 """
372 context = Context(TLSv1_METHOD)
373 self.assertRaises(TypeError, context.set_passwd_cb)
374 self.assertRaises(TypeError, context.set_passwd_cb, None)
375 self.assertRaises(TypeError, context.set_passwd_cb, lambda: None, None, None)
376
377
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400378 def test_set_passwd_cb(self):
379 """
380 L{Context.set_passwd_cb} accepts a callable which will be invoked when
381 a private key is loaded from an encrypted PEM.
382 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400383 passphrase = b("foobar")
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400384 pemFile = self._write_encrypted_pem(passphrase)
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400385 calledWith = []
386 def passphraseCallback(maxlen, verify, extra):
387 calledWith.append((maxlen, verify, extra))
388 return passphrase
389 context = Context(TLSv1_METHOD)
390 context.set_passwd_cb(passphraseCallback)
391 context.use_privatekey_file(pemFile)
392 self.assertTrue(len(calledWith), 1)
393 self.assertTrue(isinstance(calledWith[0][0], int))
394 self.assertTrue(isinstance(calledWith[0][1], int))
395 self.assertEqual(calledWith[0][2], None)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400396
397
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400398 def test_passwd_callback_exception(self):
399 """
400 L{Context.use_privatekey_file} propagates any exception raised by the
401 passphrase callback.
402 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400403 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400404 def passphraseCallback(maxlen, verify, extra):
405 raise RuntimeError("Sorry, I am a fail.")
406
407 context = Context(TLSv1_METHOD)
408 context.set_passwd_cb(passphraseCallback)
409 self.assertRaises(RuntimeError, context.use_privatekey_file, pemFile)
410
411
412 def test_passwd_callback_false(self):
413 """
414 L{Context.use_privatekey_file} raises L{OpenSSL.SSL.Error} if the
415 passphrase callback returns a false value.
416 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400417 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400418 def passphraseCallback(maxlen, verify, extra):
419 return None
420
421 context = Context(TLSv1_METHOD)
422 context.set_passwd_cb(passphraseCallback)
423 self.assertRaises(Error, context.use_privatekey_file, pemFile)
424
425
426 def test_passwd_callback_non_string(self):
427 """
428 L{Context.use_privatekey_file} raises L{OpenSSL.SSL.Error} if the
429 passphrase callback returns a true non-string value.
430 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400431 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400432 def passphraseCallback(maxlen, verify, extra):
433 return 10
434
435 context = Context(TLSv1_METHOD)
436 context.set_passwd_cb(passphraseCallback)
437 self.assertRaises(Error, context.use_privatekey_file, pemFile)
438
439
440 def test_passwd_callback_too_long(self):
441 """
442 If the passphrase returned by the passphrase callback returns a string
443 longer than the indicated maximum length, it is truncated.
444 """
445 # A priori knowledge!
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400446 passphrase = b("x") * 1024
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400447 pemFile = self._write_encrypted_pem(passphrase)
448 def passphraseCallback(maxlen, verify, extra):
449 assert maxlen == 1024
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400450 return passphrase + b("y")
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400451
452 context = Context(TLSv1_METHOD)
453 context.set_passwd_cb(passphraseCallback)
454 # This shall succeed because the truncated result is the correct
455 # passphrase.
456 context.use_privatekey_file(pemFile)
457
458
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400459 def test_set_info_callback(self):
460 """
461 L{Context.set_info_callback} accepts a callable which will be invoked
462 when certain information about an SSL connection is available.
463 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500464 (server, client) = socket_pair()
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400465
466 clientSSL = Connection(Context(TLSv1_METHOD), client)
467 clientSSL.set_connect_state()
468
469 called = []
470 def info(conn, where, ret):
471 called.append((conn, where, ret))
472 context = Context(TLSv1_METHOD)
473 context.set_info_callback(info)
474 context.use_certificate(
475 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
476 context.use_privatekey(
477 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
478
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400479 serverSSL = Connection(context, server)
480 serverSSL.set_accept_state()
481
482 while not called:
483 for ssl in clientSSL, serverSSL:
484 try:
485 ssl.do_handshake()
486 except WantReadError:
487 pass
488
489 # Kind of lame. Just make sure it got called somehow.
490 self.assertTrue(called)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400491
492
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400493 def _load_verify_locations_test(self, *args):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400494 """
495 Create a client context which will verify the peer certificate and call
496 its C{load_verify_locations} method with C{*args}. Then connect it to a
497 server and ensure that the handshake succeeds.
498 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500499 (server, client) = socket_pair()
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400500
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400501 clientContext = Context(TLSv1_METHOD)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400502 clientContext.load_verify_locations(*args)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400503 # Require that the server certificate verify properly or the
504 # connection will fail.
505 clientContext.set_verify(
506 VERIFY_PEER,
507 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
508
509 clientSSL = Connection(clientContext, client)
510 clientSSL.set_connect_state()
511
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400512 serverContext = Context(TLSv1_METHOD)
513 serverContext.use_certificate(
514 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
515 serverContext.use_privatekey(
516 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
517
518 serverSSL = Connection(serverContext, server)
519 serverSSL.set_accept_state()
520
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400521 # Without load_verify_locations above, the handshake
522 # will fail:
523 # Error: [('SSL routines', 'SSL3_GET_SERVER_CERTIFICATE',
524 # 'certificate verify failed')]
525 handshake(clientSSL, serverSSL)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400526
527 cert = clientSSL.get_peer_certificate()
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400528 self.assertEqual(cert.get_subject().CN, 'Testing Root CA')
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400529
Jean-Paul Calderone12608a82009-11-07 10:35:15 -0500530
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400531 def test_load_verify_file(self):
532 """
533 L{Context.load_verify_locations} accepts a file name and uses the
534 certificates within for verification purposes.
535 """
536 cafile = self.mktemp()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400537 fObj = open(cafile, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400538 fObj.write(cleartextCertificatePEM.decode('ascii'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400539 fObj.close()
540
541 self._load_verify_locations_test(cafile)
542
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400543
544 def test_load_verify_invalid_file(self):
545 """
546 L{Context.load_verify_locations} raises L{Error} when passed a
547 non-existent cafile.
548 """
549 clientContext = Context(TLSv1_METHOD)
550 self.assertRaises(
551 Error, clientContext.load_verify_locations, self.mktemp())
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400552
553
554 def test_load_verify_directory(self):
555 """
556 L{Context.load_verify_locations} accepts a directory name and uses
557 the certificates within for verification purposes.
558 """
559 capath = self.mktemp()
560 makedirs(capath)
Jean-Paul Calderone24dfb332011-05-04 18:10:26 -0400561 # Hash values computed manually with c_rehash to avoid depending on
562 # c_rehash in the test suite. One is from OpenSSL 0.9.8, the other
563 # from OpenSSL 1.0.0.
564 for name in ['c7adac82.0', 'c3705638.0']:
565 cafile = join(capath, name)
566 fObj = open(cafile, 'w')
567 fObj.write(cleartextCertificatePEM.decode('ascii'))
568 fObj.close()
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400569
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400570 self._load_verify_locations_test(None, capath)
571
572
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400573 def test_load_verify_locations_wrong_args(self):
574 """
575 L{Context.load_verify_locations} raises L{TypeError} if called with
576 the wrong number of arguments or with non-C{str} arguments.
577 """
578 context = Context(TLSv1_METHOD)
579 self.assertRaises(TypeError, context.load_verify_locations)
580 self.assertRaises(TypeError, context.load_verify_locations, object())
581 self.assertRaises(TypeError, context.load_verify_locations, object(), object())
582 self.assertRaises(TypeError, context.load_verify_locations, None, None, None)
583
584
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -0400585 if platform == "win32":
586 "set_default_verify_paths appears not to work on Windows. "
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400587 "See LP#404343 and LP#404344."
588 else:
589 def test_set_default_verify_paths(self):
590 """
591 L{Context.set_default_verify_paths} causes the platform-specific CA
592 certificate locations to be used for verification purposes.
593 """
594 # Testing this requires a server with a certificate signed by one of
595 # the CAs in the platform CA location. Getting one of those costs
596 # money. Fortunately (or unfortunately, depending on your
597 # perspective), it's easy to think of a public server on the
598 # internet which has such a certificate. Connecting to the network
599 # in a unit test is bad, but it's the only way I can think of to
600 # really test this. -exarkun
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400601
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400602 # Arg, verisign.com doesn't speak TLSv1
603 context = Context(SSLv3_METHOD)
604 context.set_default_verify_paths()
605 context.set_verify(
Ziga Seilnacht44611bf2009-08-31 20:49:30 +0200606 VERIFY_PEER,
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400607 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400608
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400609 client = socket()
610 client.connect(('verisign.com', 443))
611 clientSSL = Connection(context, client)
612 clientSSL.set_connect_state()
613 clientSSL.do_handshake()
614 clientSSL.send('GET / HTTP/1.0\r\n\r\n')
615 self.assertTrue(clientSSL.recv(1024))
Jean-Paul Calderone9eadb962008-09-07 21:20:44 -0400616
617
618 def test_set_default_verify_paths_signature(self):
619 """
620 L{Context.set_default_verify_paths} takes no arguments and raises
621 L{TypeError} if given any.
622 """
623 context = Context(TLSv1_METHOD)
624 self.assertRaises(TypeError, context.set_default_verify_paths, None)
625 self.assertRaises(TypeError, context.set_default_verify_paths, 1)
626 self.assertRaises(TypeError, context.set_default_verify_paths, "")
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -0500627
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400628
Jean-Paul Calderone12608a82009-11-07 10:35:15 -0500629 def test_add_extra_chain_cert_invalid_cert(self):
630 """
631 L{Context.add_extra_chain_cert} raises L{TypeError} if called with
632 other than one argument or if called with an object which is not an
633 instance of L{X509}.
634 """
635 context = Context(TLSv1_METHOD)
636 self.assertRaises(TypeError, context.add_extra_chain_cert)
637 self.assertRaises(TypeError, context.add_extra_chain_cert, object())
638 self.assertRaises(TypeError, context.add_extra_chain_cert, object(), object())
639
640
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400641 def _create_certificate_chain(self):
Jean-Paul Calderone12608a82009-11-07 10:35:15 -0500642 """
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400643 Construct and return a chain of certificates.
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400644
645 1. A new self-signed certificate authority certificate (cacert)
646 2. A new intermediate certificate signed by cacert (icert)
647 3. A new server certificate signed by icert (scert)
Jean-Paul Calderone12608a82009-11-07 10:35:15 -0500648 """
Jean-Paul Calderone9b0744c2010-09-14 18:11:01 -0400649 caext = X509Extension(b('basicConstraints'), False, b('CA:true'))
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -0500650
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400651 # Step 1
652 cakey = PKey()
653 cakey.generate_key(TYPE_RSA, 512)
654 cacert = X509()
Jean-Paul Calderone16cf03d2010-09-08 18:53:39 -0400655 cacert.get_subject().commonName = "Authority Certificate"
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400656 cacert.set_issuer(cacert.get_subject())
657 cacert.set_pubkey(cakey)
Jean-Paul Calderone4e6aed62010-09-19 10:05:34 -0400658 cacert.set_notBefore(b("20000101000000Z"))
659 cacert.set_notAfter(b("20200101000000Z"))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400660 cacert.add_extensions([caext])
Jean-Paul Calderone16cf03d2010-09-08 18:53:39 -0400661 cacert.set_serial_number(0)
662 cacert.sign(cakey, "sha1")
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -0500663
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400664 # Step 2
665 ikey = PKey()
666 ikey.generate_key(TYPE_RSA, 512)
667 icert = X509()
668 icert.get_subject().commonName = "Intermediate Certificate"
669 icert.set_issuer(cacert.get_subject())
670 icert.set_pubkey(ikey)
Jean-Paul Calderone4e6aed62010-09-19 10:05:34 -0400671 icert.set_notBefore(b("20000101000000Z"))
672 icert.set_notAfter(b("20200101000000Z"))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400673 icert.add_extensions([caext])
Jean-Paul Calderone16cf03d2010-09-08 18:53:39 -0400674 icert.set_serial_number(0)
675 icert.sign(cakey, "sha1")
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -0400676
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400677 # Step 3
678 skey = PKey()
679 skey.generate_key(TYPE_RSA, 512)
680 scert = X509()
681 scert.get_subject().commonName = "Server Certificate"
682 scert.set_issuer(icert.get_subject())
683 scert.set_pubkey(skey)
Jean-Paul Calderone4e6aed62010-09-19 10:05:34 -0400684 scert.set_notBefore(b("20000101000000Z"))
685 scert.set_notAfter(b("20200101000000Z"))
Jean-Paul Calderone2db1de52010-09-19 10:08:13 -0400686 scert.add_extensions([
687 X509Extension(b('basicConstraints'), True, b('CA:false'))])
Jean-Paul Calderone16cf03d2010-09-08 18:53:39 -0400688 scert.set_serial_number(0)
689 scert.sign(ikey, "sha1")
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -0400690
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400691 return [(cakey, cacert), (ikey, icert), (skey, scert)]
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400692
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400693
694 def _handshake_test(self, serverContext, clientContext):
695 """
696 Verify that a client and server created with the given contexts can
697 successfully handshake and communicate.
698 """
699 serverSocket, clientSocket = socket_pair()
700
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400701 server = Connection(serverContext, serverSocket)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -0400702 server.set_accept_state()
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400703
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400704 client = Connection(clientContext, clientSocket)
705 client.set_connect_state()
706
707 # Make them talk to each other.
708 # self._interactInMemory(client, server)
709 for i in range(3):
710 for s in [client, server]:
711 try:
712 s.do_handshake()
713 except WantReadError:
714 pass
715
716
717 def test_add_extra_chain_cert(self):
718 """
719 L{Context.add_extra_chain_cert} accepts an L{X509} instance to add to
720 the certificate chain.
721
722 See L{_create_certificate_chain} for the details of the certificate
723 chain tested.
724
725 The chain is tested by starting a server with scert and connecting
726 to it with a client which trusts cacert and requires verification to
727 succeed.
728 """
729 chain = self._create_certificate_chain()
730 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
731
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400732 # Dump the CA certificate to a file because that's the only way to load
733 # it as a trusted CA in the client context.
734 for cert, name in [(cacert, 'ca.pem'), (icert, 'i.pem'), (scert, 's.pem')]:
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400735 fObj = open(name, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400736 fObj.write(dump_certificate(FILETYPE_PEM, cert).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400737 fObj.close()
738
739 for key, name in [(cakey, 'ca.key'), (ikey, 'i.key'), (skey, 's.key')]:
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400740 fObj = open(name, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400741 fObj.write(dump_privatekey(FILETYPE_PEM, key).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400742 fObj.close()
743
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400744 # Create the server context
745 serverContext = Context(TLSv1_METHOD)
746 serverContext.use_privatekey(skey)
747 serverContext.use_certificate(scert)
Jean-Paul Calderone16cf03d2010-09-08 18:53:39 -0400748 # The client already has cacert, we only need to give them icert.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400749 serverContext.add_extra_chain_cert(icert)
750
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400751 # Create the client
752 clientContext = Context(TLSv1_METHOD)
753 clientContext.set_verify(
754 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
755 clientContext.load_verify_locations('ca.pem')
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -0400756
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400757 # Try it out.
758 self._handshake_test(serverContext, clientContext)
759
760
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400761 def test_use_certificate_chain_file(self):
762 """
763 L{Context.use_certificate_chain_file} reads a certificate chain from
764 the specified file.
765
766 The chain is tested by starting a server with scert and connecting
767 to it with a client which trusts cacert and requires verification to
768 succeed.
769 """
770 chain = self._create_certificate_chain()
771 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
772
773 # Write out the chain file.
774 chainFile = self.mktemp()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400775 fObj = open(chainFile, 'w')
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400776 # Most specific to least general.
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400777 fObj.write(dump_certificate(FILETYPE_PEM, scert).decode('ascii'))
778 fObj.write(dump_certificate(FILETYPE_PEM, icert).decode('ascii'))
779 fObj.write(dump_certificate(FILETYPE_PEM, cacert).decode('ascii'))
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400780 fObj.close()
781
782 serverContext = Context(TLSv1_METHOD)
783 serverContext.use_certificate_chain_file(chainFile)
784 serverContext.use_privatekey(skey)
785
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400786 fObj = open('ca.pem', 'w')
787 fObj.write(dump_certificate(FILETYPE_PEM, cacert).decode('ascii'))
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400788 fObj.close()
789
790 clientContext = Context(TLSv1_METHOD)
791 clientContext.set_verify(
792 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
793 clientContext.load_verify_locations('ca.pem')
794
795 self._handshake_test(serverContext, clientContext)
796
Jean-Paul Calderonee0d79362010-08-03 18:46:46 -0400797 # XXX load_client_ca
798 # XXX set_session_id
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -0400799
800 def test_get_verify_mode_wrong_args(self):
801 """
802 L{Context.get_verify_mode} raises L{TypeError} if called with any
803 arguments.
804 """
805 context = Context(TLSv1_METHOD)
806 self.assertRaises(TypeError, context.get_verify_mode, None)
807
808
809 def test_get_verify_mode(self):
810 """
811 L{Context.get_verify_mode} returns the verify mode flags previously
812 passed to L{Context.set_verify}.
813 """
814 context = Context(TLSv1_METHOD)
815 self.assertEquals(context.get_verify_mode(), 0)
816 context.set_verify(
817 VERIFY_PEER | VERIFY_CLIENT_ONCE, lambda *args: None)
818 self.assertEquals(
819 context.get_verify_mode(), VERIFY_PEER | VERIFY_CLIENT_ONCE)
820
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -0400821
822 def test_load_tmp_dh_wrong_args(self):
823 """
824 L{Context.load_tmp_dh} raises L{TypeError} if called with the wrong
825 number of arguments or with a non-C{str} argument.
826 """
827 context = Context(TLSv1_METHOD)
828 self.assertRaises(TypeError, context.load_tmp_dh)
829 self.assertRaises(TypeError, context.load_tmp_dh, "foo", None)
830 self.assertRaises(TypeError, context.load_tmp_dh, object())
831
832
833 def test_load_tmp_dh_missing_file(self):
834 """
835 L{Context.load_tmp_dh} raises L{OpenSSL.SSL.Error} if the specified file
836 does not exist.
837 """
838 context = Context(TLSv1_METHOD)
839 self.assertRaises(Error, context.load_tmp_dh, "hello")
840
841
842 def test_load_tmp_dh(self):
843 """
844 L{Context.load_tmp_dh} loads Diffie-Hellman parameters from the
845 specified file.
846 """
847 context = Context(TLSv1_METHOD)
848 dhfilename = self.mktemp()
849 dhfile = open(dhfilename, "w")
850 dhfile.write(dhparam)
851 dhfile.close()
852 context.load_tmp_dh(dhfilename)
853 # XXX What should I assert here? -exarkun
854
855
856 def test_set_cipher_list(self):
857 """
858 L{Context.set_cipher_list} accepts a C{str} naming the ciphers which
859 connections created with the context object will be able to choose from.
860 """
861 context = Context(TLSv1_METHOD)
862 context.set_cipher_list("hello world:EXP-RC4-MD5")
863 conn = Connection(context, None)
864 self.assertEquals(conn.get_cipher_list(), ["EXP-RC4-MD5"])
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -0400865
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -0400866
867
868class ConnectionTests(TestCase, _LoopbackMixin):
Rick Deane15b1472009-07-09 15:53:42 -0500869 """
870 Unit tests for L{OpenSSL.SSL.Connection}.
871 """
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -0400872 # XXX want_write
873 # XXX want_read
874 # XXX get_peer_certificate -> None
875 # XXX sock_shutdown
876 # XXX master_key -> TypeError
877 # XXX server_random -> TypeError
878 # XXX state_string
879 # XXX connect -> TypeError
880 # XXX connect_ex -> TypeError
881 # XXX set_connect_state -> TypeError
882 # XXX set_accept_state -> TypeError
883 # XXX renegotiate_pending
884 # XXX do_handshake -> TypeError
885 # XXX bio_read -> TypeError
886 # XXX recv -> TypeError
887 # XXX send -> TypeError
888 # XXX bio_write -> TypeError
889
Rick Deane15b1472009-07-09 15:53:42 -0500890 def test_type(self):
891 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400892 L{Connection} and L{ConnectionType} refer to the same type object and
893 can be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -0500894 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400895 self.assertIdentical(Connection, ConnectionType)
Rick Deane15b1472009-07-09 15:53:42 -0500896 ctx = Context(TLSv1_METHOD)
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400897 self.assertConsistentType(Connection, 'Connection', ctx, None)
Rick Deane15b1472009-07-09 15:53:42 -0500898
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400899
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -0500900 def test_get_context(self):
901 """
902 L{Connection.get_context} returns the L{Context} instance used to
903 construct the L{Connection} instance.
904 """
905 context = Context(TLSv1_METHOD)
906 connection = Connection(context, None)
907 self.assertIdentical(connection.get_context(), context)
908
909
910 def test_get_context_wrong_args(self):
911 """
912 L{Connection.get_context} raises L{TypeError} if called with any
913 arguments.
914 """
915 connection = Connection(Context(TLSv1_METHOD), None)
916 self.assertRaises(TypeError, connection.get_context, None)
917
918
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -0400919 def test_pending(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -0400920 """
921 L{Connection.pending} returns the number of bytes available for
922 immediate read.
923 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -0400924 connection = Connection(Context(TLSv1_METHOD), None)
925 self.assertEquals(connection.pending(), 0)
926
927
928 def test_pending_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -0400929 """
930 L{Connection.pending} raises L{TypeError} if called with any arguments.
931 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -0400932 connection = Connection(Context(TLSv1_METHOD), None)
933 self.assertRaises(TypeError, connection.pending, None)
934
935
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -0400936 def test_connect_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -0400937 """
938 L{Connection.connect} raises L{TypeError} if called with a non-address
939 argument or with the wrong number of arguments.
940 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -0400941 connection = Connection(Context(TLSv1_METHOD), socket())
942 self.assertRaises(TypeError, connection.connect, None)
Jean-Paul Calderone93dba222010-09-08 22:59:37 -0400943 self.assertRaises(TypeError, connection.connect)
944 self.assertRaises(TypeError, connection.connect, ("127.0.0.1", 1), None)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -0400945
946
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -0400947 def test_connect_refused(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -0400948 """
949 L{Connection.connect} raises L{socket.error} if the underlying socket
950 connect method raises it.
951 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -0400952 client = socket()
953 context = Context(TLSv1_METHOD)
954 clientSSL = Connection(context, client)
955 exc = self.assertRaises(error, clientSSL.connect, ("127.0.0.1", 1))
Jean-Paul Calderone35adf9d2010-07-29 18:40:44 -0400956 self.assertEquals(exc.args[0], ECONNREFUSED)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -0400957
958
959 def test_connect(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -0400960 """
961 L{Connection.connect} establishes a connection to the specified address.
962 """
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -0400963 port = socket()
964 port.bind(('', 0))
965 port.listen(3)
966
967 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -0400968 clientSSL.connect(('127.0.0.1', port.getsockname()[1]))
969 # XXX An assertion? Or something?
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -0400970
971
Jean-Paul Calderone7b614872010-09-24 17:43:44 -0400972 if platform == "darwin":
973 "connect_ex sometimes causes a kernel panic on OS X 10.6.4"
974 else:
975 def test_connect_ex(self):
976 """
977 If there is a connection error, L{Connection.connect_ex} returns the
978 errno instead of raising an exception.
979 """
980 port = socket()
981 port.bind(('', 0))
982 port.listen(3)
Jean-Paul Calderone55d91f42010-07-29 19:22:17 -0400983
Jean-Paul Calderone7b614872010-09-24 17:43:44 -0400984 clientSSL = Connection(Context(TLSv1_METHOD), socket())
985 clientSSL.setblocking(False)
986 result = clientSSL.connect_ex(port.getsockname())
987 expected = (EINPROGRESS, EWOULDBLOCK)
988 self.assertTrue(
989 result in expected, "%r not in %r" % (result, expected))
Jean-Paul Calderone55d91f42010-07-29 19:22:17 -0400990
991
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -0400992 def test_accept_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -0400993 """
994 L{Connection.accept} raises L{TypeError} if called with any arguments.
995 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -0400996 connection = Connection(Context(TLSv1_METHOD), socket())
997 self.assertRaises(TypeError, connection.accept, None)
998
999
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001000 def test_accept(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001001 """
1002 L{Connection.accept} accepts a pending connection attempt and returns a
1003 tuple of a new L{Connection} (the accepted client) and the address the
1004 connection originated from.
1005 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001006 ctx = Context(TLSv1_METHOD)
1007 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1008 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001009 port = socket()
1010 portSSL = Connection(ctx, port)
1011 portSSL.bind(('', 0))
1012 portSSL.listen(3)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001013
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001014 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04001015
1016 # Calling portSSL.getsockname() here to get the server IP address sounds
1017 # great, but frequently fails on Windows.
1018 clientSSL.connect(('127.0.0.1', portSSL.getsockname()[1]))
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001019
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001020 serverSSL, address = portSSL.accept()
1021
1022 self.assertTrue(isinstance(serverSSL, Connection))
1023 self.assertIdentical(serverSSL.get_context(), ctx)
1024 self.assertEquals(address, clientSSL.getsockname())
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001025
1026
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001027 def test_shutdown_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001028 """
1029 L{Connection.shutdown} raises L{TypeError} if called with the wrong
1030 number of arguments or with arguments other than integers.
1031 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001032 connection = Connection(Context(TLSv1_METHOD), None)
1033 self.assertRaises(TypeError, connection.shutdown, None)
Jean-Paul Calderone1d3e0222010-07-29 22:52:45 -04001034 self.assertRaises(TypeError, connection.get_shutdown, None)
1035 self.assertRaises(TypeError, connection.set_shutdown)
1036 self.assertRaises(TypeError, connection.set_shutdown, None)
1037 self.assertRaises(TypeError, connection.set_shutdown, 0, 1)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001038
1039
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001040 def test_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001041 """
1042 L{Connection.shutdown} performs an SSL-level connection shutdown.
1043 """
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001044 server, client = self._loopback()
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04001045 self.assertFalse(server.shutdown())
1046 self.assertEquals(server.get_shutdown(), SENT_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001047 self.assertRaises(ZeroReturnError, client.recv, 1024)
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04001048 self.assertEquals(client.get_shutdown(), RECEIVED_SHUTDOWN)
1049 client.shutdown()
1050 self.assertEquals(client.get_shutdown(), SENT_SHUTDOWN|RECEIVED_SHUTDOWN)
1051 self.assertRaises(ZeroReturnError, server.recv, 1024)
1052 self.assertEquals(server.get_shutdown(), SENT_SHUTDOWN|RECEIVED_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001053
1054
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04001055 def test_set_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001056 """
1057 L{Connection.set_shutdown} sets the state of the SSL connection shutdown
1058 process.
1059 """
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04001060 connection = Connection(Context(TLSv1_METHOD), socket())
1061 connection.set_shutdown(RECEIVED_SHUTDOWN)
1062 self.assertEquals(connection.get_shutdown(), RECEIVED_SHUTDOWN)
1063
1064
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001065 def test_app_data_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001066 """
1067 L{Connection.set_app_data} raises L{TypeError} if called with other than
1068 one argument. L{Connection.get_app_data} raises L{TypeError} if called
1069 with any arguments.
1070 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001071 conn = Connection(Context(TLSv1_METHOD), None)
1072 self.assertRaises(TypeError, conn.get_app_data, None)
1073 self.assertRaises(TypeError, conn.set_app_data)
1074 self.assertRaises(TypeError, conn.set_app_data, None, None)
1075
1076
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04001077 def test_app_data(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001078 """
1079 Any object can be set as app data by passing it to
1080 L{Connection.set_app_data} and later retrieved with
1081 L{Connection.get_app_data}.
1082 """
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04001083 conn = Connection(Context(TLSv1_METHOD), None)
1084 app_data = object()
1085 conn.set_app_data(app_data)
1086 self.assertIdentical(conn.get_app_data(), app_data)
1087
1088
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001089 def test_makefile(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001090 """
1091 L{Connection.makefile} is not implemented and calling that method raises
1092 L{NotImplementedError}.
1093 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001094 conn = Connection(Context(TLSv1_METHOD), None)
1095 self.assertRaises(NotImplementedError, conn.makefile)
1096
1097
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001098
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04001099class ConnectionGetCipherListTests(TestCase):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001100 """
1101 Tests for L{Connection.get_cipher_list}.
1102 """
Jean-Paul Calderone54a2bc02010-09-09 17:52:38 -04001103 def test_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001104 """
1105 L{Connection.get_cipher_list} raises L{TypeError} if called with any
1106 arguments.
1107 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04001108 connection = Connection(Context(TLSv1_METHOD), None)
1109 self.assertRaises(TypeError, connection.get_cipher_list, None)
1110
1111
1112 def test_result(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001113 """
1114 L{Connection.get_cipher_list} returns a C{list} of C{str} giving the
1115 names of the ciphers which might be used.
1116 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04001117 connection = Connection(Context(TLSv1_METHOD), None)
1118 ciphers = connection.get_cipher_list()
1119 self.assertTrue(isinstance(ciphers, list))
1120 for cipher in ciphers:
1121 self.assertTrue(isinstance(cipher, str))
1122
1123
1124
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05001125class ConnectionSendTests(TestCase, _LoopbackMixin):
1126 """
1127 Tests for L{Connection.send}
1128 """
1129 def test_wrong_args(self):
1130 """
1131 When called with arguments other than a single string,
Jean-Paul Calderone77fa2602011-01-05 18:23:39 -05001132 L{Connection.send} raises L{TypeError}.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05001133 """
1134 connection = Connection(Context(TLSv1_METHOD), None)
Jean-Paul Calderone77fa2602011-01-05 18:23:39 -05001135 self.assertRaises(TypeError, connection.send)
1136 self.assertRaises(TypeError, connection.send, object())
1137 self.assertRaises(TypeError, connection.send, "foo", "bar")
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05001138
1139
1140 def test_short_bytes(self):
1141 """
1142 When passed a short byte string, L{Connection.send} transmits all of it
1143 and returns the number of bytes sent.
1144 """
1145 server, client = self._loopback()
1146 count = server.send(b('xy'))
1147 self.assertEquals(count, 2)
1148 self.assertEquals(client.recv(2), b('xy'))
1149
1150 try:
1151 memoryview
1152 except NameError:
1153 "cannot test sending memoryview without memoryview"
1154 else:
1155 def test_short_memoryview(self):
1156 """
1157 When passed a memoryview onto a small number of bytes,
1158 L{Connection.send} transmits all of them and returns the number of
1159 bytes sent.
1160 """
1161 server, client = self._loopback()
1162 count = server.send(memoryview(b('xy')))
1163 self.assertEquals(count, 2)
1164 self.assertEquals(client.recv(2), b('xy'))
1165
1166
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05001167
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04001168class ConnectionSendallTests(TestCase, _LoopbackMixin):
1169 """
1170 Tests for L{Connection.sendall}.
1171 """
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001172 def test_wrong_args(self):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04001173 """
1174 When called with arguments other than a single string,
1175 L{Connection.sendall} raises L{TypeError}.
1176 """
1177 connection = Connection(Context(TLSv1_METHOD), None)
1178 self.assertRaises(TypeError, connection.sendall)
1179 self.assertRaises(TypeError, connection.sendall, object())
1180 self.assertRaises(TypeError, connection.sendall, "foo", "bar")
1181
1182
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001183 def test_short(self):
1184 """
1185 L{Connection.sendall} transmits all of the bytes in the string passed to
1186 it.
1187 """
1188 server, client = self._loopback()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04001189 server.sendall(b('x'))
1190 self.assertEquals(client.recv(1), b('x'))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001191
1192
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05001193 try:
1194 memoryview
1195 except NameError:
1196 "cannot test sending memoryview without memoryview"
1197 else:
1198 def test_short_memoryview(self):
1199 """
1200 When passed a memoryview onto a small number of bytes,
1201 L{Connection.sendall} transmits all of them.
1202 """
1203 server, client = self._loopback()
1204 server.sendall(memoryview(b('x')))
1205 self.assertEquals(client.recv(1), b('x'))
1206
1207
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001208 def test_long(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001209 """
1210 L{Connection.sendall} transmits all of the bytes in the string passed to
1211 it even if this requires multiple calls of an underlying write function.
1212 """
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001213 server, client = self._loopback()
Jean-Paul Calderone6241c702010-09-16 19:59:24 -04001214 # Should be enough, underlying SSL_write should only do 16k at a time.
1215 # On Windows, after 32k of bytes the write will block (forever - because
1216 # no one is yet reading).
Jean-Paul Calderone9e4c1352010-09-19 09:34:43 -04001217 message = b('x') * (1024 * 32 - 1) + b('y')
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001218 server.sendall(message)
1219 accum = []
1220 received = 0
1221 while received < len(message):
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04001222 data = client.recv(1024)
1223 accum.append(data)
1224 received += len(data)
Jean-Paul Calderonef4047852010-09-19 09:45:57 -04001225 self.assertEquals(message, b('').join(accum))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001226
1227
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04001228 def test_closed(self):
1229 """
1230 If the underlying socket is closed, L{Connection.sendall} propagates the
1231 write error from the low level write call.
1232 """
1233 server, client = self._loopback()
Jean-Paul Calderone05d43e82010-09-24 18:01:36 -04001234 server.sock_shutdown(2)
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04001235 self.assertRaises(SysCallError, server.sendall, "hello, world")
1236
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001237
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04001238
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04001239class ConnectionRenegotiateTests(TestCase, _LoopbackMixin):
1240 """
1241 Tests for SSL renegotiation APIs.
1242 """
1243 def test_renegotiate_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001244 """
1245 L{Connection.renegotiate} raises L{TypeError} if called with any
1246 arguments.
1247 """
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04001248 connection = Connection(Context(TLSv1_METHOD), None)
1249 self.assertRaises(TypeError, connection.renegotiate, None)
1250
1251
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001252 def test_total_renegotiations_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001253 """
1254 L{Connection.total_renegotiations} raises L{TypeError} if called with
1255 any arguments.
1256 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001257 connection = Connection(Context(TLSv1_METHOD), None)
1258 self.assertRaises(TypeError, connection.total_renegotiations, None)
1259
1260
1261 def test_total_renegotiations(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001262 """
1263 L{Connection.total_renegotiations} returns C{0} before any
1264 renegotiations have happened.
1265 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001266 connection = Connection(Context(TLSv1_METHOD), None)
1267 self.assertEquals(connection.total_renegotiations(), 0)
1268
1269
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04001270# def test_renegotiate(self):
1271# """
1272# """
1273# server, client = self._loopback()
1274
1275# server.send("hello world")
1276# self.assertEquals(client.recv(len("hello world")), "hello world")
1277
1278# self.assertEquals(server.total_renegotiations(), 0)
1279# self.assertTrue(server.renegotiate())
1280
1281# server.setblocking(False)
1282# client.setblocking(False)
1283# while server.renegotiate_pending():
1284# client.do_handshake()
1285# server.do_handshake()
1286
1287# self.assertEquals(server.total_renegotiations(), 1)
1288
1289
1290
1291
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001292class ErrorTests(TestCase):
1293 """
1294 Unit tests for L{OpenSSL.SSL.Error}.
1295 """
1296 def test_type(self):
1297 """
1298 L{Error} is an exception type.
1299 """
1300 self.assertTrue(issubclass(Error, Exception))
Rick Deane15b1472009-07-09 15:53:42 -05001301 self.assertEqual(Error.__name__, 'Error')
Rick Deane15b1472009-07-09 15:53:42 -05001302
1303
1304
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05001305class ConstantsTests(TestCase):
1306 """
1307 Tests for the values of constants exposed in L{OpenSSL.SSL}.
1308
1309 These are values defined by OpenSSL intended only to be used as flags to
1310 OpenSSL APIs. The only assertions it seems can be made about them is
1311 their values.
1312 """
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05001313 # unittest.TestCase has no skip mechanism
1314 if OP_NO_QUERY_MTU is not None:
1315 def test_op_no_query_mtu(self):
1316 """
1317 The value of L{OpenSSL.SSL.OP_NO_QUERY_MTU} is 0x1000, the value of
1318 I{SSL_OP_NO_QUERY_MTU} defined by I{openssl/ssl.h}.
1319 """
1320 self.assertEqual(OP_NO_QUERY_MTU, 0x1000)
1321 else:
1322 "OP_NO_QUERY_MTU unavailable - OpenSSL version may be too old"
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05001323
1324
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05001325 if OP_COOKIE_EXCHANGE is not None:
1326 def test_op_cookie_exchange(self):
1327 """
1328 The value of L{OpenSSL.SSL.OP_COOKIE_EXCHANGE} is 0x2000, the value
1329 of I{SSL_OP_COOKIE_EXCHANGE} defined by I{openssl/ssl.h}.
1330 """
1331 self.assertEqual(OP_COOKIE_EXCHANGE, 0x2000)
1332 else:
1333 "OP_COOKIE_EXCHANGE unavailable - OpenSSL version may be too old"
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05001334
1335
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05001336 if OP_NO_TICKET is not None:
1337 def test_op_no_ticket(self):
1338 """
1339 The value of L{OpenSSL.SSL.OP_NO_TICKET} is 0x4000, the value of
1340 I{SSL_OP_NO_TICKET} defined by I{openssl/ssl.h}.
1341 """
1342 self.assertEqual(OP_NO_TICKET, 0x4000)
1343 else:
1344 "OP_NO_TICKET unavailable - OpenSSL version may be too old"
Rick Dean5b7b6372009-04-01 11:34:06 -05001345
1346
Jean-Paul Calderoneeeee26a2009-04-27 11:24:30 -04001347
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001348class MemoryBIOTests(TestCase, _LoopbackMixin):
Rick Deanb71c0d22009-04-01 14:09:23 -05001349 """
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04001350 Tests for L{OpenSSL.SSL.Connection} using a memory BIO.
Rick Deanb71c0d22009-04-01 14:09:23 -05001351 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04001352 def _server(self, sock):
1353 """
1354 Create a new server-side SSL L{Connection} object wrapped around
1355 C{sock}.
1356 """
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04001357 # Create the server side Connection. This is mostly setup boilerplate
1358 # - use TLSv1, use a particular certificate, etc.
1359 server_ctx = Context(TLSv1_METHOD)
1360 server_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE )
1361 server_ctx.set_verify(VERIFY_PEER|VERIFY_FAIL_IF_NO_PEER_CERT|VERIFY_CLIENT_ONCE, verify_cb)
1362 server_store = server_ctx.get_cert_store()
1363 server_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1364 server_ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
1365 server_ctx.check_privatekey()
1366 server_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05001367 # Here the Connection is actually created. If None is passed as the 2nd
1368 # parameter, it indicates a memory BIO should be created.
1369 server_conn = Connection(server_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04001370 server_conn.set_accept_state()
1371 return server_conn
1372
1373
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04001374 def _client(self, sock):
1375 """
1376 Create a new client-side SSL L{Connection} object wrapped around
1377 C{sock}.
1378 """
1379 # Now create the client side Connection. Similar boilerplate to the
1380 # above.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04001381 client_ctx = Context(TLSv1_METHOD)
1382 client_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE )
1383 client_ctx.set_verify(VERIFY_PEER|VERIFY_FAIL_IF_NO_PEER_CERT|VERIFY_CLIENT_ONCE, verify_cb)
1384 client_store = client_ctx.get_cert_store()
1385 client_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, client_key_pem))
1386 client_ctx.use_certificate(load_certificate(FILETYPE_PEM, client_cert_pem))
1387 client_ctx.check_privatekey()
1388 client_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05001389 client_conn = Connection(client_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04001390 client_conn.set_connect_state()
1391 return client_conn
1392
1393
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04001394 def test_memoryConnect(self):
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04001395 """
1396 Two L{Connection}s which use memory BIOs can be manually connected by
1397 reading from the output of each and writing those bytes to the input of
1398 the other and in this way establish a connection and exchange
1399 application-level bytes with each other.
1400 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04001401 server_conn = self._server(None)
1402 client_conn = self._client(None)
Rick Deanb71c0d22009-04-01 14:09:23 -05001403
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04001404 # There should be no key or nonces yet.
1405 self.assertIdentical(server_conn.master_key(), None)
1406 self.assertIdentical(server_conn.client_random(), None)
1407 self.assertIdentical(server_conn.server_random(), None)
Rick Deanb71c0d22009-04-01 14:09:23 -05001408
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04001409 # First, the handshake needs to happen. We'll deliver bytes back and
1410 # forth between the client and server until neither of them feels like
1411 # speaking any more.
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001412 self.assertIdentical(
1413 self._interactInMemory(client_conn, server_conn), None)
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04001414
1415 # Now that the handshake is done, there should be a key and nonces.
1416 self.assertNotIdentical(server_conn.master_key(), None)
1417 self.assertNotIdentical(server_conn.client_random(), None)
1418 self.assertNotIdentical(server_conn.server_random(), None)
Jean-Paul Calderone6c051e62009-07-05 13:50:34 -04001419 self.assertEquals(server_conn.client_random(), client_conn.client_random())
1420 self.assertEquals(server_conn.server_random(), client_conn.server_random())
1421 self.assertNotEquals(server_conn.client_random(), server_conn.server_random())
1422 self.assertNotEquals(client_conn.client_random(), client_conn.server_random())
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04001423
1424 # Here are the bytes we'll try to send.
Jean-Paul Calderonea441fdc2010-08-22 21:33:57 -04001425 important_message = b('One if by land, two if by sea.')
Rick Deanb71c0d22009-04-01 14:09:23 -05001426
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04001427 server_conn.write(important_message)
1428 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001429 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04001430 (client_conn, important_message))
1431
1432 client_conn.write(important_message[::-1])
1433 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001434 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04001435 (server_conn, important_message[::-1]))
Rick Deanb71c0d22009-04-01 14:09:23 -05001436
1437
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04001438 def test_socketConnect(self):
Rick Deanb1ccd562009-07-09 23:52:39 -05001439 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04001440 Just like L{test_memoryConnect} but with an actual socket.
1441
1442 This is primarily to rule out the memory BIO code as the source of
1443 any problems encountered while passing data over a L{Connection} (if
1444 this test fails, there must be a problem outside the memory BIO
1445 code, as no memory BIO is involved here). Even though this isn't a
1446 memory BIO test, it's convenient to have it here.
Rick Deanb1ccd562009-07-09 23:52:39 -05001447 """
Jean-Paul Calderone06c7cc92010-09-24 23:52:00 -04001448 server_conn, client_conn = self._loopback()
Rick Deanb1ccd562009-07-09 23:52:39 -05001449
Jean-Paul Calderonea441fdc2010-08-22 21:33:57 -04001450 important_message = b("Help me Obi Wan Kenobi, you're my only hope.")
Rick Deanb1ccd562009-07-09 23:52:39 -05001451 client_conn.send(important_message)
1452 msg = server_conn.recv(1024)
1453 self.assertEqual(msg, important_message)
1454
1455 # Again in the other direction, just for fun.
1456 important_message = important_message[::-1]
1457 server_conn.send(important_message)
1458 msg = client_conn.recv(1024)
1459 self.assertEqual(msg, important_message)
1460
1461
Jean-Paul Calderonefc4ed0f2009-04-27 11:51:27 -04001462 def test_socketOverridesMemory(self):
Rick Deanb71c0d22009-04-01 14:09:23 -05001463 """
1464 Test that L{OpenSSL.SSL.bio_read} and L{OpenSSL.SSL.bio_write} don't
1465 work on L{OpenSSL.SSL.Connection}() that use sockets.
1466 """
1467 context = Context(SSLv3_METHOD)
1468 client = socket()
1469 clientSSL = Connection(context, client)
1470 self.assertRaises( TypeError, clientSSL.bio_read, 100)
1471 self.assertRaises( TypeError, clientSSL.bio_write, "foo")
Jean-Paul Calderone07acf3f2009-05-05 13:23:28 -04001472 self.assertRaises( TypeError, clientSSL.bio_shutdown )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04001473
1474
1475 def test_outgoingOverflow(self):
1476 """
1477 If more bytes than can be written to the memory BIO are passed to
1478 L{Connection.send} at once, the number of bytes which were written is
1479 returned and that many bytes from the beginning of the input can be
1480 read from the other end of the connection.
1481 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04001482 server = self._server(None)
1483 client = self._client(None)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04001484
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001485 self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04001486
1487 size = 2 ** 15
1488 sent = client.send("x" * size)
1489 # Sanity check. We're trying to test what happens when the entire
1490 # input can't be sent. If the entire input was sent, this test is
1491 # meaningless.
1492 self.assertTrue(sent < size)
1493
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001494 receiver, received = self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04001495 self.assertIdentical(receiver, server)
1496
1497 # We can rely on all of these bytes being received at once because
1498 # _loopback passes 2 ** 16 to recv - more than 2 ** 15.
1499 self.assertEquals(len(received), sent)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04001500
1501
1502 def test_shutdown(self):
1503 """
1504 L{Connection.bio_shutdown} signals the end of the data stream from
1505 which the L{Connection} reads.
1506 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04001507 server = self._server(None)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04001508 server.bio_shutdown()
1509 e = self.assertRaises(Error, server.recv, 1024)
1510 # We don't want WantReadError or ZeroReturnError or anything - it's a
1511 # handshake failure.
1512 self.assertEquals(e.__class__, Error)
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04001513
1514
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001515 def _check_client_ca_list(self, func):
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001516 """
1517 Verify the return value of the C{get_client_ca_list} method for server and client connections.
1518
1519 @param func: A function which will be called with the server context
1520 before the client and server are connected to each other. This
1521 function should specify a list of CAs for the server to send to the
1522 client and return that same list. The list will be used to verify
1523 that C{get_client_ca_list} returns the proper value at various
1524 times.
1525 """
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001526 server = self._server(None)
1527 client = self._client(None)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001528 self.assertEqual(client.get_client_ca_list(), [])
1529 self.assertEqual(server.get_client_ca_list(), [])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001530 ctx = server.get_context()
1531 expected = func(ctx)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001532 self.assertEqual(client.get_client_ca_list(), [])
1533 self.assertEqual(server.get_client_ca_list(), expected)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001534 self._interactInMemory(client, server)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001535 self.assertEqual(client.get_client_ca_list(), expected)
1536 self.assertEqual(server.get_client_ca_list(), expected)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001537
1538
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001539 def test_set_client_ca_list_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001540 """
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001541 L{Context.set_client_ca_list} raises a L{TypeError} if called with a
1542 non-list or a list that contains objects other than X509Names.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001543 """
1544 ctx = Context(TLSv1_METHOD)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001545 self.assertRaises(TypeError, ctx.set_client_ca_list, "spam")
1546 self.assertRaises(TypeError, ctx.set_client_ca_list, ["spam"])
1547 self.assertIdentical(ctx.set_client_ca_list([]), None)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001548
1549
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001550 def test_set_empty_ca_list(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001551 """
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001552 If passed an empty list, L{Context.set_client_ca_list} configures the
1553 context to send no CA names to the client and, on both the server and
1554 client sides, L{Connection.get_client_ca_list} returns an empty list
1555 after the connection is set up.
1556 """
1557 def no_ca(ctx):
1558 ctx.set_client_ca_list([])
1559 return []
1560 self._check_client_ca_list(no_ca)
1561
1562
1563 def test_set_one_ca_list(self):
1564 """
1565 If passed a list containing a single X509Name,
1566 L{Context.set_client_ca_list} configures the context to send that CA
1567 name to the client and, on both the server and client sides,
1568 L{Connection.get_client_ca_list} returns a list containing that
1569 X509Name after the connection is set up.
1570 """
1571 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
1572 cadesc = cacert.get_subject()
1573 def single_ca(ctx):
1574 ctx.set_client_ca_list([cadesc])
1575 return [cadesc]
1576 self._check_client_ca_list(single_ca)
1577
1578
1579 def test_set_multiple_ca_list(self):
1580 """
1581 If passed a list containing multiple X509Name objects,
1582 L{Context.set_client_ca_list} configures the context to send those CA
1583 names to the client and, on both the server and client sides,
1584 L{Connection.get_client_ca_list} returns a list containing those
1585 X509Names after the connection is set up.
1586 """
1587 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
1588 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
1589
1590 sedesc = secert.get_subject()
1591 cldesc = clcert.get_subject()
1592
1593 def multiple_ca(ctx):
1594 L = [sedesc, cldesc]
1595 ctx.set_client_ca_list(L)
1596 return L
1597 self._check_client_ca_list(multiple_ca)
1598
1599
1600 def test_reset_ca_list(self):
1601 """
1602 If called multiple times, only the X509Names passed to the final call
1603 of L{Context.set_client_ca_list} are used to configure the CA names
1604 sent to the client.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001605 """
1606 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
1607 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
1608 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
1609
1610 cadesc = cacert.get_subject()
1611 sedesc = secert.get_subject()
1612 cldesc = clcert.get_subject()
1613
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001614 def changed_ca(ctx):
1615 ctx.set_client_ca_list([sedesc, cldesc])
1616 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001617 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001618 self._check_client_ca_list(changed_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001619
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001620
1621 def test_mutated_ca_list(self):
1622 """
1623 If the list passed to L{Context.set_client_ca_list} is mutated
1624 afterwards, this does not affect the list of CA names sent to the
1625 client.
1626 """
1627 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
1628 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
1629
1630 cadesc = cacert.get_subject()
1631 sedesc = secert.get_subject()
1632
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001633 def mutated_ca(ctx):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001634 L = [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001635 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001636 L.append(sedesc)
1637 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001638 self._check_client_ca_list(mutated_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001639
1640
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001641 def test_add_client_ca_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001642 """
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001643 L{Context.add_client_ca} raises L{TypeError} if called with a non-X509
1644 object or with a number of arguments other than one.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001645 """
1646 ctx = Context(TLSv1_METHOD)
1647 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001648 self.assertRaises(TypeError, ctx.add_client_ca)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001649 self.assertRaises(TypeError, ctx.add_client_ca, "spam")
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04001650 self.assertRaises(TypeError, ctx.add_client_ca, cacert, cacert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001651
1652
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04001653 def test_one_add_client_ca(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001654 """
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04001655 A certificate's subject can be added as a CA to be sent to the client
1656 with L{Context.add_client_ca}.
1657 """
1658 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
1659 cadesc = cacert.get_subject()
1660 def single_ca(ctx):
1661 ctx.add_client_ca(cacert)
1662 return [cadesc]
1663 self._check_client_ca_list(single_ca)
1664
1665
1666 def test_multiple_add_client_ca(self):
1667 """
1668 Multiple CA names can be sent to the client by calling
1669 L{Context.add_client_ca} with multiple X509 objects.
1670 """
1671 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
1672 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
1673
1674 cadesc = cacert.get_subject()
1675 sedesc = secert.get_subject()
1676
1677 def multiple_ca(ctx):
1678 ctx.add_client_ca(cacert)
1679 ctx.add_client_ca(secert)
1680 return [cadesc, sedesc]
1681 self._check_client_ca_list(multiple_ca)
1682
1683
1684 def test_set_and_add_client_ca(self):
1685 """
1686 A call to L{Context.set_client_ca_list} followed by a call to
1687 L{Context.add_client_ca} results in using the CA names from the first
1688 call and the CA name from the second call.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001689 """
1690 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
1691 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
1692 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
1693
1694 cadesc = cacert.get_subject()
1695 sedesc = secert.get_subject()
1696 cldesc = clcert.get_subject()
1697
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001698 def mixed_set_add_ca(ctx):
1699 ctx.set_client_ca_list([cadesc, sedesc])
1700 ctx.add_client_ca(clcert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001701 return [cadesc, sedesc, cldesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001702 self._check_client_ca_list(mixed_set_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001703
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04001704
1705 def test_set_after_add_client_ca(self):
1706 """
1707 A call to L{Context.set_client_ca_list} after a call to
1708 L{Context.add_client_ca} replaces the CA name specified by the former
1709 call with the names specified by the latter cal.
1710 """
1711 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
1712 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
1713 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
1714
1715 cadesc = cacert.get_subject()
1716 sedesc = secert.get_subject()
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04001717
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001718 def set_replaces_add_ca(ctx):
1719 ctx.add_client_ca(clcert)
1720 ctx.set_client_ca_list([cadesc])
1721 ctx.add_client_ca(secert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001722 return [cadesc, sedesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02001723 self._check_client_ca_list(set_replaces_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02001724
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04001725
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04001726class InfoConstantTests(TestCase):
1727 """
1728 Tests for assorted constants exposed for use in info callbacks.
1729 """
1730 def test_integers(self):
1731 """
1732 All of the info constants are integers.
1733
1734 This is a very weak test. It would be nice to have one that actually
1735 verifies that as certain info events happen, the value passed to the
1736 info callback matches up with the constant exposed by OpenSSL.SSL.
1737 """
1738 for const in [
1739 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK, SSL_ST_INIT,
1740 SSL_ST_BEFORE, SSL_ST_OK, SSL_ST_RENEGOTIATE,
1741 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
1742 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
1743 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
1744 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE]:
1745
1746 self.assertTrue(isinstance(const, int))
1747
Ziga Seilnacht44611bf2009-08-31 20:49:30 +02001748
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04001749if __name__ == '__main__':
1750 main()