blob: c884148e7f88cf68a702d70c97b470bbceda9f55 [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"""
Jonathan Ballet648875f2011-07-16 14:14:58 +09005Unit tests for :py:obj:`OpenSSL.SSL`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -04006"""
7
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05008from gc import collect, get_referrers
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08009from errno import ECONNREFUSED, EINPROGRESS, EWOULDBLOCK, EPIPE
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -040010from sys import platform, version_info
Jean-Paul Calderoned899af02013-03-19 22:10:37 -070011from socket import SHUT_RDWR, error, socket
Jean-Paul Calderonea65cf6c2009-07-19 10:26:52 -040012from os import makedirs
Jean-Paul Calderone1461c492013-10-03 16:05:00 -040013from os.path import join
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -040014from unittest import main
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -040015from weakref import ref
Jean-Paul Calderone460cc1f2009-03-07 11:31:12 -050016
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040017from OpenSSL.crypto import TYPE_RSA, FILETYPE_PEM
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -080018from OpenSSL.crypto import PKey, X509, X509Extension, X509Store
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040019from OpenSSL.crypto import dump_privatekey, load_privatekey
20from OpenSSL.crypto import dump_certificate, load_certificate
21
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -040022from OpenSSL.SSL import OPENSSL_VERSION_NUMBER, SSLEAY_VERSION, SSLEAY_CFLAGS
23from OpenSSL.SSL import SSLEAY_PLATFORM, SSLEAY_DIR, SSLEAY_BUILT_ON
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -040024from OpenSSL.SSL import SENT_SHUTDOWN, RECEIVED_SHUTDOWN
Jean-Paul Calderone1461c492013-10-03 16:05:00 -040025from OpenSSL.SSL import (
26 SSLv2_METHOD, SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD,
27 TLSv1_1_METHOD, TLSv1_2_METHOD)
28from OpenSSL.SSL import OP_SINGLE_DH_USE, OP_NO_SSLv2, OP_NO_SSLv3
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040029from OpenSSL.SSL import (
30 VERIFY_PEER, VERIFY_FAIL_IF_NO_PEER_CERT, VERIFY_CLIENT_ONCE, VERIFY_NONE)
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040031
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040032from OpenSSL.SSL import (
Jean-Paul Calderone313bf012012-02-08 13:02:49 -050033 SESS_CACHE_OFF, SESS_CACHE_CLIENT, SESS_CACHE_SERVER, SESS_CACHE_BOTH,
34 SESS_CACHE_NO_AUTO_CLEAR, SESS_CACHE_NO_INTERNAL_LOOKUP,
35 SESS_CACHE_NO_INTERNAL_STORE, SESS_CACHE_NO_INTERNAL)
Alex Gaynor12dc0842014-01-17 12:51:31 -060036from OpenSSL.SSL import NID_X9_62_prime256v1, OPENSSL_NO_EC
Jean-Paul Calderone313bf012012-02-08 13:02:49 -050037
38from OpenSSL.SSL import (
Jean-Paul Calderoned899af02013-03-19 22:10:37 -070039 Error, SysCallError, WantReadError, WantWriteError, ZeroReturnError)
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -050040from OpenSSL.SSL import (
Jean-Paul Calderoned899af02013-03-19 22:10:37 -070041 Context, ContextType, Session, Connection, ConnectionType, SSLeay_version)
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040042
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -050043from OpenSSL.test.util import TestCase, b
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040044from OpenSSL.test.test_crypto import (
45 cleartextCertificatePEM, cleartextPrivateKeyPEM)
46from OpenSSL.test.test_crypto import (
47 client_cert_pem, client_key_pem, server_cert_pem, server_key_pem,
48 root_cert_pem)
49
Jean-Paul Calderone4bccf5e2008-12-28 22:50:42 -050050try:
51 from OpenSSL.SSL import OP_NO_QUERY_MTU
52except ImportError:
53 OP_NO_QUERY_MTU = None
54try:
55 from OpenSSL.SSL import OP_COOKIE_EXCHANGE
56except ImportError:
57 OP_COOKIE_EXCHANGE = None
58try:
59 from OpenSSL.SSL import OP_NO_TICKET
60except ImportError:
61 OP_NO_TICKET = None
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -040062
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040063try:
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -040064 from OpenSSL.SSL import OP_NO_COMPRESSION
65except ImportError:
66 OP_NO_COMPRESSION = None
67
68try:
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040069 from OpenSSL.SSL import MODE_RELEASE_BUFFERS
70except ImportError:
71 MODE_RELEASE_BUFFERS = None
72
Jean-Paul Calderone1461c492013-10-03 16:05:00 -040073try:
74 from OpenSSL.SSL import OP_NO_TLSv1, OP_NO_TLSv1_1, OP_NO_TLSv1_2
75except ImportError:
76 OP_NO_TLSv1 = OP_NO_TLSv1_1 = OP_NO_TLSv1_2 = None
77
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -040078from OpenSSL.SSL import (
79 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK, SSL_ST_INIT, SSL_ST_BEFORE,
80 SSL_ST_OK, SSL_ST_RENEGOTIATE,
81 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
82 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
83 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
84 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE)
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -040085
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -040086# openssl dhparam 128 -out dh-128.pem (note that 128 is a small number of bits
87# to use)
88dhparam = """\
89-----BEGIN DH PARAMETERS-----
90MBYCEQCobsg29c9WZP/54oAPcwiDAgEC
91-----END DH PARAMETERS-----
92"""
93
94
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -040095def verify_cb(conn, cert, errnum, depth, ok):
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -040096 return ok
97
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040098
Rick Deanb1ccd562009-07-09 23:52:39 -050099def socket_pair():
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400100 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400101 Establish and return a pair of network sockets connected to each other.
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400102 """
103 # Connect a pair of sockets
Rick Deanb1ccd562009-07-09 23:52:39 -0500104 port = socket()
105 port.bind(('', 0))
106 port.listen(1)
107 client = socket()
108 client.setblocking(False)
Jean-Paul Calderonef23c5d92009-07-23 17:58:15 -0400109 client.connect_ex(("127.0.0.1", port.getsockname()[1]))
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400110 client.setblocking(True)
Rick Deanb1ccd562009-07-09 23:52:39 -0500111 server = port.accept()[0]
Rick Deanb1ccd562009-07-09 23:52:39 -0500112
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400113 # Let's pass some unencrypted data to make sure our socket connection is
114 # fine. Just one byte, so we don't have to worry about buffers getting
115 # filled up or fragmentation.
Jean-Paul Calderone9e4eeae2010-08-22 21:32:52 -0400116 server.send(b("x"))
117 assert client.recv(1024) == b("x")
118 client.send(b("y"))
119 assert server.recv(1024) == b("y")
Rick Deanb1ccd562009-07-09 23:52:39 -0500120
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -0400121 # Most of our callers want non-blocking sockets, make it easy for them.
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400122 server.setblocking(False)
123 client.setblocking(False)
124
Rick Deanb1ccd562009-07-09 23:52:39 -0500125 return (server, client)
126
127
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400128
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400129def handshake(client, server):
130 conns = [client, server]
131 while conns:
132 for conn in conns:
133 try:
134 conn.do_handshake()
135 except WantReadError:
136 pass
137 else:
138 conns.remove(conn)
139
140
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400141def _create_certificate_chain():
142 """
143 Construct and return a chain of certificates.
144
145 1. A new self-signed certificate authority certificate (cacert)
146 2. A new intermediate certificate signed by cacert (icert)
147 3. A new server certificate signed by icert (scert)
148 """
149 caext = X509Extension(b('basicConstraints'), False, b('CA:true'))
150
151 # Step 1
152 cakey = PKey()
153 cakey.generate_key(TYPE_RSA, 512)
154 cacert = X509()
155 cacert.get_subject().commonName = "Authority Certificate"
156 cacert.set_issuer(cacert.get_subject())
157 cacert.set_pubkey(cakey)
158 cacert.set_notBefore(b("20000101000000Z"))
159 cacert.set_notAfter(b("20200101000000Z"))
160 cacert.add_extensions([caext])
161 cacert.set_serial_number(0)
162 cacert.sign(cakey, "sha1")
163
164 # Step 2
165 ikey = PKey()
166 ikey.generate_key(TYPE_RSA, 512)
167 icert = X509()
168 icert.get_subject().commonName = "Intermediate Certificate"
169 icert.set_issuer(cacert.get_subject())
170 icert.set_pubkey(ikey)
171 icert.set_notBefore(b("20000101000000Z"))
172 icert.set_notAfter(b("20200101000000Z"))
173 icert.add_extensions([caext])
174 icert.set_serial_number(0)
175 icert.sign(cakey, "sha1")
176
177 # Step 3
178 skey = PKey()
179 skey.generate_key(TYPE_RSA, 512)
180 scert = X509()
181 scert.get_subject().commonName = "Server Certificate"
182 scert.set_issuer(icert.get_subject())
183 scert.set_pubkey(skey)
184 scert.set_notBefore(b("20000101000000Z"))
185 scert.set_notAfter(b("20200101000000Z"))
186 scert.add_extensions([
187 X509Extension(b('basicConstraints'), True, b('CA:false'))])
188 scert.set_serial_number(0)
189 scert.sign(ikey, "sha1")
190
191 return [(cakey, cacert), (ikey, icert), (skey, scert)]
192
193
194
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400195class _LoopbackMixin:
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400196 """
197 Helper mixin which defines methods for creating a connected socket pair and
198 for forcing two connected SSL sockets to talk to each other via memory BIOs.
199 """
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500200 def _loopbackClientFactory(self, socket):
201 client = Connection(Context(TLSv1_METHOD), socket)
202 client.set_connect_state()
203 return client
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400204
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500205
206 def _loopbackServerFactory(self, socket):
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400207 ctx = Context(TLSv1_METHOD)
208 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
209 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500210 server = Connection(ctx, socket)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400211 server.set_accept_state()
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500212 return server
213
214
215 def _loopback(self, serverFactory=None, clientFactory=None):
216 if serverFactory is None:
217 serverFactory = self._loopbackServerFactory
218 if clientFactory is None:
219 clientFactory = self._loopbackClientFactory
220
221 (server, client) = socket_pair()
222 server = serverFactory(server)
223 client = clientFactory(client)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400224
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400225 handshake(client, server)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400226
227 server.setblocking(True)
228 client.setblocking(True)
229 return server, client
230
231
232 def _interactInMemory(self, client_conn, server_conn):
233 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900234 Try to read application bytes from each of the two :py:obj:`Connection`
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400235 objects. Copy bytes back and forth between their send/receive buffers
236 for as long as there is anything to copy. When there is nothing more
Jonathan Ballet648875f2011-07-16 14:14:58 +0900237 to copy, return :py:obj:`None`. If one of them actually manages to deliver
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400238 some application bytes, return a two-tuple of the connection from which
239 the bytes were read and the bytes themselves.
240 """
241 wrote = True
242 while wrote:
243 # Loop until neither side has anything to say
244 wrote = False
245
246 # Copy stuff from each side's send buffer to the other side's
247 # receive buffer.
248 for (read, write) in [(client_conn, server_conn),
249 (server_conn, client_conn)]:
250
251 # Give the side a chance to generate some more bytes, or
252 # succeed.
253 try:
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400254 data = read.recv(2 ** 16)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400255 except WantReadError:
256 # It didn't succeed, so we'll hope it generated some
257 # output.
258 pass
259 else:
260 # It did succeed, so we'll stop now and let the caller deal
261 # with it.
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400262 return (read, data)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400263
264 while True:
265 # Keep copying as long as there's more stuff there.
266 try:
267 dirty = read.bio_read(4096)
268 except WantReadError:
269 # Okay, nothing more waiting to be sent. Stop
270 # processing this send buffer.
271 break
272 else:
273 # Keep track of the fact that someone generated some
274 # output.
275 wrote = True
276 write.bio_write(dirty)
277
278
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400279
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400280class VersionTests(TestCase):
281 """
282 Tests for version information exposed by
Jonathan Ballet648875f2011-07-16 14:14:58 +0900283 :py:obj:`OpenSSL.SSL.SSLeay_version` and
284 :py:obj:`OpenSSL.SSL.OPENSSL_VERSION_NUMBER`.
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400285 """
286 def test_OPENSSL_VERSION_NUMBER(self):
287 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900288 :py:obj:`OPENSSL_VERSION_NUMBER` is an integer with status in the low
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400289 byte and the patch, fix, minor, and major versions in the
290 nibbles above that.
291 """
292 self.assertTrue(isinstance(OPENSSL_VERSION_NUMBER, int))
293
294
295 def test_SSLeay_version(self):
296 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900297 :py:obj:`SSLeay_version` takes a version type indicator and returns
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400298 one of a number of version strings based on that indicator.
299 """
300 versions = {}
301 for t in [SSLEAY_VERSION, SSLEAY_CFLAGS, SSLEAY_BUILT_ON,
302 SSLEAY_PLATFORM, SSLEAY_DIR]:
303 version = SSLeay_version(t)
304 versions[version] = t
305 self.assertTrue(isinstance(version, bytes))
306 self.assertEqual(len(versions), 5)
307
308
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400309
310class ContextTests(TestCase, _LoopbackMixin):
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400311 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900312 Unit tests for :py:obj:`OpenSSL.SSL.Context`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400313 """
314 def test_method(self):
315 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900316 :py:obj:`Context` can be instantiated with one of :py:obj:`SSLv2_METHOD`,
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400317 :py:obj:`SSLv3_METHOD`, :py:obj:`SSLv23_METHOD`, :py:obj:`TLSv1_METHOD`,
318 :py:obj:`TLSv1_1_METHOD`, or :py:obj:`TLSv1_2_METHOD`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400319 """
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400320 methods = [
321 SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD]
322 for meth in methods:
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400323 Context(meth)
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400324
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400325
326 maybe = [SSLv2_METHOD, TLSv1_1_METHOD, TLSv1_2_METHOD]
327 for meth in maybe:
328 try:
329 Context(meth)
330 except (Error, ValueError):
331 # Some versions of OpenSSL have SSLv2 / TLSv1.1 / TLSv1.2, some
332 # don't. Difficult to say in advance.
333 pass
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400334
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400335 self.assertRaises(TypeError, Context, "")
336 self.assertRaises(ValueError, Context, 10)
337
338
Rick Deane15b1472009-07-09 15:53:42 -0500339 def test_type(self):
340 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900341 :py:obj:`Context` and :py:obj:`ContextType` refer to the same type object and can be
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400342 used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -0500343 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400344 self.assertIdentical(Context, ContextType)
345 self.assertConsistentType(Context, 'Context', TLSv1_METHOD)
Rick Deane15b1472009-07-09 15:53:42 -0500346
347
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400348 def test_use_privatekey(self):
349 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900350 :py:obj:`Context.use_privatekey` takes an :py:obj:`OpenSSL.crypto.PKey` instance.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400351 """
352 key = PKey()
353 key.generate_key(TYPE_RSA, 128)
354 ctx = Context(TLSv1_METHOD)
355 ctx.use_privatekey(key)
356 self.assertRaises(TypeError, ctx.use_privatekey, "")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400357
358
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800359 def test_use_privatekey_file_missing(self):
360 """
361 :py:obj:`Context.use_privatekey_file` raises :py:obj:`OpenSSL.SSL.Error`
362 when passed the name of a file which does not exist.
363 """
364 ctx = Context(TLSv1_METHOD)
365 self.assertRaises(Error, ctx.use_privatekey_file, self.mktemp())
366
367
368 def test_use_certificate_wrong_args(self):
369 """
370 :py:obj:`Context.use_certificate_wrong_args` raises :py:obj:`TypeError`
371 when not passed exactly one :py:obj:`OpenSSL.crypto.X509` instance as an
372 argument.
373 """
374 ctx = Context(TLSv1_METHOD)
375 self.assertRaises(TypeError, ctx.use_certificate)
376 self.assertRaises(TypeError, ctx.use_certificate, "hello, world")
377 self.assertRaises(TypeError, ctx.use_certificate, X509(), "hello, world")
378
379
380 def test_use_certificate_uninitialized(self):
381 """
382 :py:obj:`Context.use_certificate` raises :py:obj:`OpenSSL.SSL.Error`
383 when passed a :py:obj:`OpenSSL.crypto.X509` instance which has not been
384 initialized (ie, which does not actually have any certificate data).
385 """
386 ctx = Context(TLSv1_METHOD)
387 self.assertRaises(Error, ctx.use_certificate, X509())
388
389
390 def test_use_certificate(self):
391 """
392 :py:obj:`Context.use_certificate` sets the certificate which will be
393 used to identify connections created using the context.
394 """
395 # TODO
396 # Hard to assert anything. But we could set a privatekey then ask
397 # OpenSSL if the cert and key agree using check_privatekey. Then as
398 # long as check_privatekey works right we're good...
399 ctx = Context(TLSv1_METHOD)
400 ctx.use_certificate(load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
401
402
403 def test_use_certificate_file_wrong_args(self):
404 """
405 :py:obj:`Context.use_certificate_file` raises :py:obj:`TypeError` if
406 called with zero arguments or more than two arguments, or if the first
407 argument is not a byte string or the second argumnent is not an integer.
408 """
409 ctx = Context(TLSv1_METHOD)
410 self.assertRaises(TypeError, ctx.use_certificate_file)
411 self.assertRaises(TypeError, ctx.use_certificate_file, b"somefile", object())
412 self.assertRaises(
413 TypeError, ctx.use_certificate_file, b"somefile", FILETYPE_PEM, object())
414 self.assertRaises(
415 TypeError, ctx.use_certificate_file, object(), FILETYPE_PEM)
416 self.assertRaises(
417 TypeError, ctx.use_certificate_file, b"somefile", object())
418
419
420 def test_use_certificate_file_missing(self):
421 """
422 :py:obj:`Context.use_certificate_file` raises
423 `:py:obj:`OpenSSL.SSL.Error` if passed the name of a file which does not
424 exist.
425 """
426 ctx = Context(TLSv1_METHOD)
427 self.assertRaises(Error, ctx.use_certificate_file, self.mktemp())
428
429
430 def test_use_certificate_file(self):
431 """
432 :py:obj:`Context.use_certificate` sets the certificate which will be
433 used to identify connections created using the context.
434 """
435 # TODO
436 # Hard to assert anything. But we could set a privatekey then ask
437 # OpenSSL if the cert and key agree using check_privatekey. Then as
438 # long as check_privatekey works right we're good...
439 pem_filename = self.mktemp()
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500440 with open(pem_filename, "wb") as pem_file:
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800441 pem_file.write(cleartextCertificatePEM)
442
443 ctx = Context(TLSv1_METHOD)
444 ctx.use_certificate_file(pem_filename)
445
446
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400447 def test_set_app_data_wrong_args(self):
448 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900449 :py:obj:`Context.set_app_data` raises :py:obj:`TypeError` if called with other than
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400450 one argument.
451 """
452 context = Context(TLSv1_METHOD)
453 self.assertRaises(TypeError, context.set_app_data)
454 self.assertRaises(TypeError, context.set_app_data, None, None)
455
456
457 def test_get_app_data_wrong_args(self):
458 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900459 :py:obj:`Context.get_app_data` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400460 arguments.
461 """
462 context = Context(TLSv1_METHOD)
463 self.assertRaises(TypeError, context.get_app_data, None)
464
465
466 def test_app_data(self):
467 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900468 :py:obj:`Context.set_app_data` stores an object for later retrieval using
469 :py:obj:`Context.get_app_data`.
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400470 """
471 app_data = object()
472 context = Context(TLSv1_METHOD)
473 context.set_app_data(app_data)
474 self.assertIdentical(context.get_app_data(), app_data)
475
476
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400477 def test_set_options_wrong_args(self):
478 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900479 :py:obj:`Context.set_options` raises :py:obj:`TypeError` if called with the wrong
480 number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400481 """
482 context = Context(TLSv1_METHOD)
483 self.assertRaises(TypeError, context.set_options)
484 self.assertRaises(TypeError, context.set_options, None)
485 self.assertRaises(TypeError, context.set_options, 1, None)
486
487
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300488 def test_set_mode_wrong_args(self):
489 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -0400490 :py:obj:`Context.set`mode} raises :py:obj:`TypeError` if called with the wrong
491 number of arguments or a non-:py:obj:`int` argument.
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300492 """
493 context = Context(TLSv1_METHOD)
494 self.assertRaises(TypeError, context.set_mode)
495 self.assertRaises(TypeError, context.set_mode, None)
496 self.assertRaises(TypeError, context.set_mode, 1, None)
497
498
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400499 if MODE_RELEASE_BUFFERS is not None:
500 def test_set_mode(self):
501 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -0400502 :py:obj:`Context.set_mode` accepts a mode bitvector and returns the newly
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400503 set mode.
504 """
505 context = Context(TLSv1_METHOD)
506 self.assertTrue(
507 MODE_RELEASE_BUFFERS & context.set_mode(MODE_RELEASE_BUFFERS))
508 else:
509 "MODE_RELEASE_BUFFERS unavailable - OpenSSL version may be too old"
510
511
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400512 def test_set_timeout_wrong_args(self):
513 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900514 :py:obj:`Context.set_timeout` raises :py:obj:`TypeError` if called with the wrong
515 number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400516 """
517 context = Context(TLSv1_METHOD)
518 self.assertRaises(TypeError, context.set_timeout)
519 self.assertRaises(TypeError, context.set_timeout, None)
520 self.assertRaises(TypeError, context.set_timeout, 1, None)
521
522
523 def test_get_timeout_wrong_args(self):
524 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900525 :py:obj:`Context.get_timeout` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400526 """
527 context = Context(TLSv1_METHOD)
528 self.assertRaises(TypeError, context.get_timeout, None)
529
530
531 def test_timeout(self):
532 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900533 :py:obj:`Context.set_timeout` sets the session timeout for all connections
534 created using the context object. :py:obj:`Context.get_timeout` retrieves this
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400535 value.
536 """
537 context = Context(TLSv1_METHOD)
538 context.set_timeout(1234)
539 self.assertEquals(context.get_timeout(), 1234)
540
541
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400542 def test_set_verify_depth_wrong_args(self):
543 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900544 :py:obj:`Context.set_verify_depth` raises :py:obj:`TypeError` if called with the wrong
545 number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400546 """
547 context = Context(TLSv1_METHOD)
548 self.assertRaises(TypeError, context.set_verify_depth)
549 self.assertRaises(TypeError, context.set_verify_depth, None)
550 self.assertRaises(TypeError, context.set_verify_depth, 1, None)
551
552
553 def test_get_verify_depth_wrong_args(self):
554 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900555 :py:obj:`Context.get_verify_depth` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400556 """
557 context = Context(TLSv1_METHOD)
558 self.assertRaises(TypeError, context.get_verify_depth, None)
559
560
561 def test_verify_depth(self):
562 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900563 :py:obj:`Context.set_verify_depth` sets the number of certificates in a chain
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400564 to follow before giving up. The value can be retrieved with
Jonathan Ballet648875f2011-07-16 14:14:58 +0900565 :py:obj:`Context.get_verify_depth`.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400566 """
567 context = Context(TLSv1_METHOD)
568 context.set_verify_depth(11)
569 self.assertEquals(context.get_verify_depth(), 11)
570
571
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400572 def _write_encrypted_pem(self, passphrase):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400573 """
574 Write a new private key out to a new file, encrypted using the given
575 passphrase. Return the path to the new file.
576 """
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400577 key = PKey()
578 key.generate_key(TYPE_RSA, 128)
579 pemFile = self.mktemp()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400580 fObj = open(pemFile, 'w')
581 pem = dump_privatekey(FILETYPE_PEM, key, "blowfish", passphrase)
582 fObj.write(pem.decode('ascii'))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400583 fObj.close()
584 return pemFile
585
586
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400587 def test_set_passwd_cb_wrong_args(self):
588 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900589 :py:obj:`Context.set_passwd_cb` raises :py:obj:`TypeError` if called with the
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400590 wrong arguments or with a non-callable first argument.
591 """
592 context = Context(TLSv1_METHOD)
593 self.assertRaises(TypeError, context.set_passwd_cb)
594 self.assertRaises(TypeError, context.set_passwd_cb, None)
595 self.assertRaises(TypeError, context.set_passwd_cb, lambda: None, None, None)
596
597
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400598 def test_set_passwd_cb(self):
599 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900600 :py:obj:`Context.set_passwd_cb` accepts a callable which will be invoked when
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400601 a private key is loaded from an encrypted PEM.
602 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400603 passphrase = b("foobar")
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400604 pemFile = self._write_encrypted_pem(passphrase)
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400605 calledWith = []
606 def passphraseCallback(maxlen, verify, extra):
607 calledWith.append((maxlen, verify, extra))
608 return passphrase
609 context = Context(TLSv1_METHOD)
610 context.set_passwd_cb(passphraseCallback)
611 context.use_privatekey_file(pemFile)
612 self.assertTrue(len(calledWith), 1)
613 self.assertTrue(isinstance(calledWith[0][0], int))
614 self.assertTrue(isinstance(calledWith[0][1], int))
615 self.assertEqual(calledWith[0][2], None)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400616
617
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400618 def test_passwd_callback_exception(self):
619 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900620 :py:obj:`Context.use_privatekey_file` propagates any exception raised by the
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400621 passphrase callback.
622 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400623 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400624 def passphraseCallback(maxlen, verify, extra):
625 raise RuntimeError("Sorry, I am a fail.")
626
627 context = Context(TLSv1_METHOD)
628 context.set_passwd_cb(passphraseCallback)
629 self.assertRaises(RuntimeError, context.use_privatekey_file, pemFile)
630
631
632 def test_passwd_callback_false(self):
633 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900634 :py:obj:`Context.use_privatekey_file` raises :py:obj:`OpenSSL.SSL.Error` if the
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400635 passphrase callback returns a false value.
636 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400637 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400638 def passphraseCallback(maxlen, verify, extra):
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500639 return b""
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400640
641 context = Context(TLSv1_METHOD)
642 context.set_passwd_cb(passphraseCallback)
643 self.assertRaises(Error, context.use_privatekey_file, pemFile)
644
645
646 def test_passwd_callback_non_string(self):
647 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900648 :py:obj:`Context.use_privatekey_file` raises :py:obj:`OpenSSL.SSL.Error` if the
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400649 passphrase callback returns a true non-string value.
650 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400651 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400652 def passphraseCallback(maxlen, verify, extra):
653 return 10
654
655 context = Context(TLSv1_METHOD)
656 context.set_passwd_cb(passphraseCallback)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800657 self.assertRaises(ValueError, context.use_privatekey_file, pemFile)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400658
659
660 def test_passwd_callback_too_long(self):
661 """
662 If the passphrase returned by the passphrase callback returns a string
663 longer than the indicated maximum length, it is truncated.
664 """
665 # A priori knowledge!
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400666 passphrase = b("x") * 1024
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400667 pemFile = self._write_encrypted_pem(passphrase)
668 def passphraseCallback(maxlen, verify, extra):
669 assert maxlen == 1024
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400670 return passphrase + b("y")
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400671
672 context = Context(TLSv1_METHOD)
673 context.set_passwd_cb(passphraseCallback)
674 # This shall succeed because the truncated result is the correct
675 # passphrase.
676 context.use_privatekey_file(pemFile)
677
678
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400679 def test_set_info_callback(self):
680 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900681 :py:obj:`Context.set_info_callback` accepts a callable which will be invoked
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400682 when certain information about an SSL connection is available.
683 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500684 (server, client) = socket_pair()
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400685
686 clientSSL = Connection(Context(TLSv1_METHOD), client)
687 clientSSL.set_connect_state()
688
689 called = []
690 def info(conn, where, ret):
691 called.append((conn, where, ret))
692 context = Context(TLSv1_METHOD)
693 context.set_info_callback(info)
694 context.use_certificate(
695 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
696 context.use_privatekey(
697 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
698
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400699 serverSSL = Connection(context, server)
700 serverSSL.set_accept_state()
701
702 while not called:
703 for ssl in clientSSL, serverSSL:
704 try:
705 ssl.do_handshake()
706 except WantReadError:
707 pass
708
709 # Kind of lame. Just make sure it got called somehow.
710 self.assertTrue(called)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400711
712
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400713 def _load_verify_locations_test(self, *args):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400714 """
715 Create a client context which will verify the peer certificate and call
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -0400716 its :py:obj:`load_verify_locations` method with the given arguments.
717 Then connect it to a server and ensure that the handshake succeeds.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400718 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500719 (server, client) = socket_pair()
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400720
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400721 clientContext = Context(TLSv1_METHOD)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400722 clientContext.load_verify_locations(*args)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400723 # Require that the server certificate verify properly or the
724 # connection will fail.
725 clientContext.set_verify(
726 VERIFY_PEER,
727 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
728
729 clientSSL = Connection(clientContext, client)
730 clientSSL.set_connect_state()
731
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400732 serverContext = Context(TLSv1_METHOD)
733 serverContext.use_certificate(
734 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
735 serverContext.use_privatekey(
736 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
737
738 serverSSL = Connection(serverContext, server)
739 serverSSL.set_accept_state()
740
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400741 # Without load_verify_locations above, the handshake
742 # will fail:
743 # Error: [('SSL routines', 'SSL3_GET_SERVER_CERTIFICATE',
744 # 'certificate verify failed')]
745 handshake(clientSSL, serverSSL)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400746
747 cert = clientSSL.get_peer_certificate()
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400748 self.assertEqual(cert.get_subject().CN, 'Testing Root CA')
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400749
Jean-Paul Calderone12608a82009-11-07 10:35:15 -0500750
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400751 def test_load_verify_file(self):
752 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900753 :py:obj:`Context.load_verify_locations` accepts a file name and uses the
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400754 certificates within for verification purposes.
755 """
756 cafile = self.mktemp()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400757 fObj = open(cafile, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400758 fObj.write(cleartextCertificatePEM.decode('ascii'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400759 fObj.close()
760
761 self._load_verify_locations_test(cafile)
762
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400763
764 def test_load_verify_invalid_file(self):
765 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900766 :py:obj:`Context.load_verify_locations` raises :py:obj:`Error` when passed a
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400767 non-existent cafile.
768 """
769 clientContext = Context(TLSv1_METHOD)
770 self.assertRaises(
771 Error, clientContext.load_verify_locations, self.mktemp())
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400772
773
774 def test_load_verify_directory(self):
775 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900776 :py:obj:`Context.load_verify_locations` accepts a directory name and uses
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400777 the certificates within for verification purposes.
778 """
779 capath = self.mktemp()
780 makedirs(capath)
Jean-Paul Calderone24dfb332011-05-04 18:10:26 -0400781 # Hash values computed manually with c_rehash to avoid depending on
782 # c_rehash in the test suite. One is from OpenSSL 0.9.8, the other
783 # from OpenSSL 1.0.0.
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500784 for name in [b'c7adac82.0', b'c3705638.0']:
Jean-Paul Calderone24dfb332011-05-04 18:10:26 -0400785 cafile = join(capath, name)
786 fObj = open(cafile, 'w')
787 fObj.write(cleartextCertificatePEM.decode('ascii'))
788 fObj.close()
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400789
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400790 self._load_verify_locations_test(None, capath)
791
792
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400793 def test_load_verify_locations_wrong_args(self):
794 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900795 :py:obj:`Context.load_verify_locations` raises :py:obj:`TypeError` if called with
796 the wrong number of arguments or with non-:py:obj:`str` arguments.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400797 """
798 context = Context(TLSv1_METHOD)
799 self.assertRaises(TypeError, context.load_verify_locations)
800 self.assertRaises(TypeError, context.load_verify_locations, object())
801 self.assertRaises(TypeError, context.load_verify_locations, object(), object())
802 self.assertRaises(TypeError, context.load_verify_locations, None, None, None)
803
804
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -0400805 if platform == "win32":
806 "set_default_verify_paths appears not to work on Windows. "
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400807 "See LP#404343 and LP#404344."
808 else:
809 def test_set_default_verify_paths(self):
810 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900811 :py:obj:`Context.set_default_verify_paths` causes the platform-specific CA
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400812 certificate locations to be used for verification purposes.
813 """
814 # Testing this requires a server with a certificate signed by one of
815 # the CAs in the platform CA location. Getting one of those costs
816 # money. Fortunately (or unfortunately, depending on your
817 # perspective), it's easy to think of a public server on the
818 # internet which has such a certificate. Connecting to the network
819 # in a unit test is bad, but it's the only way I can think of to
820 # really test this. -exarkun
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400821
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400822 # Arg, verisign.com doesn't speak TLSv1
823 context = Context(SSLv3_METHOD)
824 context.set_default_verify_paths()
825 context.set_verify(
Ziga Seilnacht44611bf2009-08-31 20:49:30 +0200826 VERIFY_PEER,
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400827 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400828
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400829 client = socket()
830 client.connect(('verisign.com', 443))
831 clientSSL = Connection(context, client)
832 clientSSL.set_connect_state()
833 clientSSL.do_handshake()
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500834 clientSSL.send(b"GET / HTTP/1.0\r\n\r\n")
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -0400835 self.assertTrue(clientSSL.recv(1024))
Jean-Paul Calderone9eadb962008-09-07 21:20:44 -0400836
837
838 def test_set_default_verify_paths_signature(self):
839 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900840 :py:obj:`Context.set_default_verify_paths` takes no arguments and raises
841 :py:obj:`TypeError` if given any.
Jean-Paul Calderone9eadb962008-09-07 21:20:44 -0400842 """
843 context = Context(TLSv1_METHOD)
844 self.assertRaises(TypeError, context.set_default_verify_paths, None)
845 self.assertRaises(TypeError, context.set_default_verify_paths, 1)
846 self.assertRaises(TypeError, context.set_default_verify_paths, "")
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -0500847
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400848
Jean-Paul Calderone12608a82009-11-07 10:35:15 -0500849 def test_add_extra_chain_cert_invalid_cert(self):
850 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900851 :py:obj:`Context.add_extra_chain_cert` raises :py:obj:`TypeError` if called with
Jean-Paul Calderone12608a82009-11-07 10:35:15 -0500852 other than one argument or if called with an object which is not an
Jonathan Ballet648875f2011-07-16 14:14:58 +0900853 instance of :py:obj:`X509`.
Jean-Paul Calderone12608a82009-11-07 10:35:15 -0500854 """
855 context = Context(TLSv1_METHOD)
856 self.assertRaises(TypeError, context.add_extra_chain_cert)
857 self.assertRaises(TypeError, context.add_extra_chain_cert, object())
858 self.assertRaises(TypeError, context.add_extra_chain_cert, object(), object())
859
860
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400861 def _handshake_test(self, serverContext, clientContext):
862 """
863 Verify that a client and server created with the given contexts can
864 successfully handshake and communicate.
865 """
866 serverSocket, clientSocket = socket_pair()
867
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400868 server = Connection(serverContext, serverSocket)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -0400869 server.set_accept_state()
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400870
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400871 client = Connection(clientContext, clientSocket)
872 client.set_connect_state()
873
874 # Make them talk to each other.
875 # self._interactInMemory(client, server)
876 for i in range(3):
877 for s in [client, server]:
878 try:
879 s.do_handshake()
880 except WantReadError:
881 pass
882
883
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -0800884 def test_set_verify_callback_exception(self):
885 """
886 If the verify callback passed to :py:obj:`Context.set_verify` raises an
887 exception, verification fails and the exception is propagated to the
888 caller of :py:obj:`Connection.do_handshake`.
889 """
890 serverContext = Context(TLSv1_METHOD)
891 serverContext.use_privatekey(
892 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
893 serverContext.use_certificate(
894 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
895
896 clientContext = Context(TLSv1_METHOD)
897 def verify_callback(*args):
898 raise Exception("silly verify failure")
899 clientContext.set_verify(VERIFY_PEER, verify_callback)
900
901 exc = self.assertRaises(
902 Exception, self._handshake_test, serverContext, clientContext)
903 self.assertEqual("silly verify failure", str(exc))
904
905
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400906 def test_add_extra_chain_cert(self):
907 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900908 :py:obj:`Context.add_extra_chain_cert` accepts an :py:obj:`X509` instance to add to
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400909 the certificate chain.
910
Jonathan Ballet648875f2011-07-16 14:14:58 +0900911 See :py:obj:`_create_certificate_chain` for the details of the certificate
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400912 chain tested.
913
914 The chain is tested by starting a server with scert and connecting
915 to it with a client which trusts cacert and requires verification to
916 succeed.
917 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400918 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400919 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
920
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400921 # Dump the CA certificate to a file because that's the only way to load
922 # it as a trusted CA in the client context.
923 for cert, name in [(cacert, 'ca.pem'), (icert, 'i.pem'), (scert, 's.pem')]:
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400924 fObj = open(name, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400925 fObj.write(dump_certificate(FILETYPE_PEM, cert).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400926 fObj.close()
927
928 for key, name in [(cakey, 'ca.key'), (ikey, 'i.key'), (skey, 's.key')]:
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400929 fObj = open(name, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400930 fObj.write(dump_privatekey(FILETYPE_PEM, key).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400931 fObj.close()
932
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400933 # Create the server context
934 serverContext = Context(TLSv1_METHOD)
935 serverContext.use_privatekey(skey)
936 serverContext.use_certificate(scert)
Jean-Paul Calderone16cf03d2010-09-08 18:53:39 -0400937 # The client already has cacert, we only need to give them icert.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400938 serverContext.add_extra_chain_cert(icert)
939
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400940 # Create the client
941 clientContext = Context(TLSv1_METHOD)
942 clientContext.set_verify(
943 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500944 clientContext.load_verify_locations(b"ca.pem")
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -0400945
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400946 # Try it out.
947 self._handshake_test(serverContext, clientContext)
948
949
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400950 def test_use_certificate_chain_file(self):
951 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900952 :py:obj:`Context.use_certificate_chain_file` reads a certificate chain from
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400953 the specified file.
954
955 The chain is tested by starting a server with scert and connecting
956 to it with a client which trusts cacert and requires verification to
957 succeed.
958 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400959 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400960 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
961
962 # Write out the chain file.
963 chainFile = self.mktemp()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400964 fObj = open(chainFile, 'w')
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400965 # Most specific to least general.
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400966 fObj.write(dump_certificate(FILETYPE_PEM, scert).decode('ascii'))
967 fObj.write(dump_certificate(FILETYPE_PEM, icert).decode('ascii'))
968 fObj.write(dump_certificate(FILETYPE_PEM, cacert).decode('ascii'))
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400969 fObj.close()
970
971 serverContext = Context(TLSv1_METHOD)
972 serverContext.use_certificate_chain_file(chainFile)
973 serverContext.use_privatekey(skey)
974
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400975 fObj = open('ca.pem', 'w')
976 fObj.write(dump_certificate(FILETYPE_PEM, cacert).decode('ascii'))
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400977 fObj.close()
978
979 clientContext = Context(TLSv1_METHOD)
980 clientContext.set_verify(
981 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500982 clientContext.load_verify_locations(b"ca.pem")
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400983
984 self._handshake_test(serverContext, clientContext)
985
Jean-Paul Calderone131052e2013-03-05 11:56:19 -0800986
987 def test_use_certificate_chain_file_wrong_args(self):
988 """
989 :py:obj:`Context.use_certificate_chain_file` raises :py:obj:`TypeError`
990 if passed zero or more than one argument or when passed a non-byte
991 string single argument. It also raises :py:obj:`OpenSSL.SSL.Error` when
992 passed a bad chain file name (for example, the name of a file which does
993 not exist).
994 """
995 context = Context(TLSv1_METHOD)
996 self.assertRaises(TypeError, context.use_certificate_chain_file)
997 self.assertRaises(TypeError, context.use_certificate_chain_file, object())
998 self.assertRaises(TypeError, context.use_certificate_chain_file, b"foo", object())
999
1000 self.assertRaises(Error, context.use_certificate_chain_file, self.mktemp())
1001
Jean-Paul Calderonee0d79362010-08-03 18:46:46 -04001002 # XXX load_client_ca
1003 # XXX set_session_id
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001004
1005 def test_get_verify_mode_wrong_args(self):
1006 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001007 :py:obj:`Context.get_verify_mode` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001008 arguments.
1009 """
1010 context = Context(TLSv1_METHOD)
1011 self.assertRaises(TypeError, context.get_verify_mode, None)
1012
1013
1014 def test_get_verify_mode(self):
1015 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001016 :py:obj:`Context.get_verify_mode` returns the verify mode flags previously
1017 passed to :py:obj:`Context.set_verify`.
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001018 """
1019 context = Context(TLSv1_METHOD)
1020 self.assertEquals(context.get_verify_mode(), 0)
1021 context.set_verify(
1022 VERIFY_PEER | VERIFY_CLIENT_ONCE, lambda *args: None)
1023 self.assertEquals(
1024 context.get_verify_mode(), VERIFY_PEER | VERIFY_CLIENT_ONCE)
1025
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001026
1027 def test_load_tmp_dh_wrong_args(self):
1028 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001029 :py:obj:`Context.load_tmp_dh` raises :py:obj:`TypeError` if called with the wrong
1030 number of arguments or with a non-:py:obj:`str` argument.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001031 """
1032 context = Context(TLSv1_METHOD)
1033 self.assertRaises(TypeError, context.load_tmp_dh)
1034 self.assertRaises(TypeError, context.load_tmp_dh, "foo", None)
1035 self.assertRaises(TypeError, context.load_tmp_dh, object())
1036
1037
1038 def test_load_tmp_dh_missing_file(self):
1039 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001040 :py:obj:`Context.load_tmp_dh` raises :py:obj:`OpenSSL.SSL.Error` if the specified file
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001041 does not exist.
1042 """
1043 context = Context(TLSv1_METHOD)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001044 self.assertRaises(Error, context.load_tmp_dh, b"hello")
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001045
1046
1047 def test_load_tmp_dh(self):
1048 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001049 :py:obj:`Context.load_tmp_dh` loads Diffie-Hellman parameters from the
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001050 specified file.
1051 """
1052 context = Context(TLSv1_METHOD)
1053 dhfilename = self.mktemp()
1054 dhfile = open(dhfilename, "w")
1055 dhfile.write(dhparam)
1056 dhfile.close()
1057 context.load_tmp_dh(dhfilename)
1058 # XXX What should I assert here? -exarkun
1059
1060
Alex Gaynor12dc0842014-01-17 12:51:31 -06001061 if not OPENSSL_NO_EC:
1062 def test_set_tmp_ecdh_by_curve_name(self):
1063 """
1064 :py:obj:`Context.set_tmp_ecdh_by_curve_name` sets the Eliptical
1065 Curve for Diffie-Hellman by the named curve.
1066 """
1067 context = Context(TLSv1_METHOD)
1068 context.set_tmp_ecdh_by_curve_name(NID_X9_62_prime256v1)
1069 # XXX What should I assert here? -alex
1070
1071
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001072 def test_set_cipher_list(self):
1073 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001074 :py:obj:`Context.set_cipher_list` accepts a :py:obj:`str` naming the ciphers which
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001075 connections created with the context object will be able to choose from.
1076 """
1077 context = Context(TLSv1_METHOD)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001078 context.set_cipher_list(b"hello world:EXP-RC4-MD5")
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001079 conn = Connection(context, None)
1080 self.assertEquals(conn.get_cipher_list(), ["EXP-RC4-MD5"])
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001081
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001082
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001083 def test_set_cipher_list_wrong_args(self):
1084 """
1085 :py:obj:`Context.set_cipher_list` raises :py:obj:`TypeError` when passed
1086 zero arguments or more than one argument or when passed a non-byte
1087 string single argument and raises :py:obj:`OpenSSL.SSL.Error` when
1088 passed an incorrect cipher list string.
1089 """
1090 context = Context(TLSv1_METHOD)
1091 self.assertRaises(TypeError, context.set_cipher_list)
1092 self.assertRaises(TypeError, context.set_cipher_list, object())
1093 self.assertRaises(TypeError, context.set_cipher_list, b"EXP-RC4-MD5", object())
1094
1095 self.assertRaises(Error, context.set_cipher_list, b"imaginary-cipher")
1096
1097
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001098 def test_set_session_cache_mode_wrong_args(self):
1099 """
1100 L{Context.set_session_cache_mode} raises L{TypeError} if called with
1101 other than one integer argument.
1102 """
1103 context = Context(TLSv1_METHOD)
1104 self.assertRaises(TypeError, context.set_session_cache_mode)
1105 self.assertRaises(TypeError, context.set_session_cache_mode, object())
1106
1107
1108 def test_get_session_cache_mode_wrong_args(self):
1109 """
1110 L{Context.get_session_cache_mode} raises L{TypeError} if called with any
1111 arguments.
1112 """
1113 context = Context(TLSv1_METHOD)
1114 self.assertRaises(TypeError, context.get_session_cache_mode, 1)
1115
1116
1117 def test_session_cache_mode(self):
1118 """
1119 L{Context.set_session_cache_mode} specifies how sessions are cached.
1120 The setting can be retrieved via L{Context.get_session_cache_mode}.
1121 """
1122 context = Context(TLSv1_METHOD)
1123 old = context.set_session_cache_mode(SESS_CACHE_OFF)
1124 off = context.set_session_cache_mode(SESS_CACHE_BOTH)
1125 self.assertEqual(SESS_CACHE_OFF, off)
1126 self.assertEqual(SESS_CACHE_BOTH, context.get_session_cache_mode())
1127
1128
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001129 def test_get_cert_store(self):
1130 """
1131 :py:obj:`Context.get_cert_store` returns a :py:obj:`X509Store` instance.
1132 """
1133 context = Context(TLSv1_METHOD)
1134 store = context.get_cert_store()
1135 self.assertIsInstance(store, X509Store)
1136
1137
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001138
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001139class ServerNameCallbackTests(TestCase, _LoopbackMixin):
1140 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001141 Tests for :py:obj:`Context.set_tlsext_servername_callback` and its interaction with
1142 :py:obj:`Connection`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001143 """
1144 def test_wrong_args(self):
1145 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001146 :py:obj:`Context.set_tlsext_servername_callback` raises :py:obj:`TypeError` if called
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001147 with other than one argument.
1148 """
1149 context = Context(TLSv1_METHOD)
1150 self.assertRaises(TypeError, context.set_tlsext_servername_callback)
1151 self.assertRaises(
1152 TypeError, context.set_tlsext_servername_callback, 1, 2)
1153
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001154
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001155 def test_old_callback_forgotten(self):
1156 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001157 If :py:obj:`Context.set_tlsext_servername_callback` is used to specify a new
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001158 callback, the one it replaces is dereferenced.
1159 """
1160 def callback(connection):
1161 pass
1162
1163 def replacement(connection):
1164 pass
1165
1166 context = Context(TLSv1_METHOD)
1167 context.set_tlsext_servername_callback(callback)
1168
1169 tracker = ref(callback)
1170 del callback
1171
1172 context.set_tlsext_servername_callback(replacement)
Jean-Paul Calderoned4033eb2014-01-11 08:21:46 -05001173
1174 # One run of the garbage collector happens to work on CPython. PyPy
1175 # doesn't collect the underlying object until a second run for whatever
1176 # reason. That's fine, it still demonstrates our code has properly
1177 # dropped the reference.
1178 collect()
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001179 collect()
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001180
1181 callback = tracker()
1182 if callback is not None:
1183 referrers = get_referrers(callback)
Jean-Paul Calderone7de39562014-01-11 08:17:59 -05001184 if len(referrers) > 1:
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001185 self.fail("Some references remain: %r" % (referrers,))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001186
1187
1188 def test_no_servername(self):
1189 """
1190 When a client specifies no server name, the callback passed to
Jonathan Ballet648875f2011-07-16 14:14:58 +09001191 :py:obj:`Context.set_tlsext_servername_callback` is invoked and the result of
1192 :py:obj:`Connection.get_servername` is :py:obj:`None`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001193 """
1194 args = []
1195 def servername(conn):
1196 args.append((conn, conn.get_servername()))
1197 context = Context(TLSv1_METHOD)
1198 context.set_tlsext_servername_callback(servername)
1199
1200 # Lose our reference to it. The Context is responsible for keeping it
1201 # alive now.
1202 del servername
1203 collect()
1204
1205 # Necessary to actually accept the connection
1206 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1207 context.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
1208
1209 # Do a little connection to trigger the logic
1210 server = Connection(context, None)
1211 server.set_accept_state()
1212
1213 client = Connection(Context(TLSv1_METHOD), None)
1214 client.set_connect_state()
1215
1216 self._interactInMemory(server, client)
1217
1218 self.assertEqual([(server, None)], args)
1219
1220
1221 def test_servername(self):
1222 """
1223 When a client specifies a server name in its hello message, the callback
Jonathan Ballet648875f2011-07-16 14:14:58 +09001224 passed to :py:obj:`Contexts.set_tlsext_servername_callback` is invoked and the
1225 result of :py:obj:`Connection.get_servername` is that server name.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001226 """
1227 args = []
1228 def servername(conn):
1229 args.append((conn, conn.get_servername()))
1230 context = Context(TLSv1_METHOD)
1231 context.set_tlsext_servername_callback(servername)
1232
1233 # Necessary to actually accept the connection
1234 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1235 context.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
1236
1237 # Do a little connection to trigger the logic
1238 server = Connection(context, None)
1239 server.set_accept_state()
1240
1241 client = Connection(Context(TLSv1_METHOD), None)
1242 client.set_connect_state()
1243 client.set_tlsext_host_name(b("foo1.example.com"))
1244
1245 self._interactInMemory(server, client)
1246
1247 self.assertEqual([(server, b("foo1.example.com"))], args)
1248
1249
1250
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05001251class SessionTests(TestCase):
1252 """
1253 Unit tests for :py:obj:`OpenSSL.SSL.Session`.
1254 """
1255 def test_construction(self):
1256 """
1257 :py:class:`Session` can be constructed with no arguments, creating a new
1258 instance of that type.
1259 """
1260 new_session = Session()
1261 self.assertTrue(isinstance(new_session, Session))
1262
1263
1264 def test_construction_wrong_args(self):
1265 """
1266 If any arguments are passed to :py:class:`Session`, :py:obj:`TypeError`
1267 is raised.
1268 """
1269 self.assertRaises(TypeError, Session, 123)
1270 self.assertRaises(TypeError, Session, "hello")
1271 self.assertRaises(TypeError, Session, object())
1272
1273
1274
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001275class ConnectionTests(TestCase, _LoopbackMixin):
Rick Deane15b1472009-07-09 15:53:42 -05001276 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001277 Unit tests for :py:obj:`OpenSSL.SSL.Connection`.
Rick Deane15b1472009-07-09 15:53:42 -05001278 """
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04001279 # XXX get_peer_certificate -> None
1280 # XXX sock_shutdown
1281 # XXX master_key -> TypeError
1282 # XXX server_random -> TypeError
1283 # XXX state_string
1284 # XXX connect -> TypeError
1285 # XXX connect_ex -> TypeError
1286 # XXX set_connect_state -> TypeError
1287 # XXX set_accept_state -> TypeError
1288 # XXX renegotiate_pending
1289 # XXX do_handshake -> TypeError
1290 # XXX bio_read -> TypeError
1291 # XXX recv -> TypeError
1292 # XXX send -> TypeError
1293 # XXX bio_write -> TypeError
1294
Rick Deane15b1472009-07-09 15:53:42 -05001295 def test_type(self):
1296 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001297 :py:obj:`Connection` and :py:obj:`ConnectionType` refer to the same type object and
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001298 can be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -05001299 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001300 self.assertIdentical(Connection, ConnectionType)
Rick Deane15b1472009-07-09 15:53:42 -05001301 ctx = Context(TLSv1_METHOD)
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001302 self.assertConsistentType(Connection, 'Connection', ctx, None)
Rick Deane15b1472009-07-09 15:53:42 -05001303
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001304
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05001305 def test_get_context(self):
1306 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001307 :py:obj:`Connection.get_context` returns the :py:obj:`Context` instance used to
1308 construct the :py:obj:`Connection` instance.
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05001309 """
1310 context = Context(TLSv1_METHOD)
1311 connection = Connection(context, None)
1312 self.assertIdentical(connection.get_context(), context)
1313
1314
1315 def test_get_context_wrong_args(self):
1316 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001317 :py:obj:`Connection.get_context` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05001318 arguments.
1319 """
1320 connection = Connection(Context(TLSv1_METHOD), None)
1321 self.assertRaises(TypeError, connection.get_context, None)
1322
1323
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04001324 def test_set_context_wrong_args(self):
1325 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001326 :py:obj:`Connection.set_context` raises :py:obj:`TypeError` if called with a
1327 non-:py:obj:`Context` instance argument or with any number of arguments other
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04001328 than 1.
1329 """
1330 ctx = Context(TLSv1_METHOD)
1331 connection = Connection(ctx, None)
1332 self.assertRaises(TypeError, connection.set_context)
1333 self.assertRaises(TypeError, connection.set_context, object())
1334 self.assertRaises(TypeError, connection.set_context, "hello")
1335 self.assertRaises(TypeError, connection.set_context, 1)
1336 self.assertRaises(TypeError, connection.set_context, 1, 2)
1337 self.assertRaises(
1338 TypeError, connection.set_context, Context(TLSv1_METHOD), 2)
1339 self.assertIdentical(ctx, connection.get_context())
1340
1341
1342 def test_set_context(self):
1343 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001344 :py:obj:`Connection.set_context` specifies a new :py:obj:`Context` instance to be used
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04001345 for the connection.
1346 """
1347 original = Context(SSLv23_METHOD)
1348 replacement = Context(TLSv1_METHOD)
1349 connection = Connection(original, None)
1350 connection.set_context(replacement)
1351 self.assertIdentical(replacement, connection.get_context())
1352 # Lose our references to the contexts, just in case the Connection isn't
1353 # properly managing its own contributions to their reference counts.
1354 del original, replacement
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001355 collect()
1356
1357
1358 def test_set_tlsext_host_name_wrong_args(self):
1359 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001360 If :py:obj:`Connection.set_tlsext_host_name` is called with a non-byte string
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001361 argument or a byte string with an embedded NUL or other than one
Jonathan Ballet648875f2011-07-16 14:14:58 +09001362 argument, :py:obj:`TypeError` is raised.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001363 """
1364 conn = Connection(Context(TLSv1_METHOD), None)
1365 self.assertRaises(TypeError, conn.set_tlsext_host_name)
1366 self.assertRaises(TypeError, conn.set_tlsext_host_name, object())
1367 self.assertRaises(TypeError, conn.set_tlsext_host_name, 123, 456)
1368 self.assertRaises(
1369 TypeError, conn.set_tlsext_host_name, b("with\0null"))
1370
1371 if version_info >= (3,):
1372 # On Python 3.x, don't accidentally implicitly convert from text.
1373 self.assertRaises(
1374 TypeError,
1375 conn.set_tlsext_host_name, b("example.com").decode("ascii"))
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04001376
1377
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04001378 def test_get_servername_wrong_args(self):
1379 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001380 :py:obj:`Connection.get_servername` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04001381 arguments.
1382 """
1383 connection = Connection(Context(TLSv1_METHOD), None)
1384 self.assertRaises(TypeError, connection.get_servername, object())
1385 self.assertRaises(TypeError, connection.get_servername, 1)
1386 self.assertRaises(TypeError, connection.get_servername, "hello")
1387
1388
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04001389 def test_pending(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001390 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001391 :py:obj:`Connection.pending` returns the number of bytes available for
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001392 immediate read.
1393 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04001394 connection = Connection(Context(TLSv1_METHOD), None)
1395 self.assertEquals(connection.pending(), 0)
1396
1397
1398 def test_pending_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001399 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001400 :py:obj:`Connection.pending` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001401 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04001402 connection = Connection(Context(TLSv1_METHOD), None)
1403 self.assertRaises(TypeError, connection.pending, None)
1404
1405
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001406 def test_connect_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001407 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001408 :py:obj:`Connection.connect` raises :py:obj:`TypeError` if called with a non-address
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001409 argument or with the wrong number of arguments.
1410 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001411 connection = Connection(Context(TLSv1_METHOD), socket())
1412 self.assertRaises(TypeError, connection.connect, None)
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001413 self.assertRaises(TypeError, connection.connect)
1414 self.assertRaises(TypeError, connection.connect, ("127.0.0.1", 1), None)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001415
1416
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001417 def test_connect_refused(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001418 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001419 :py:obj:`Connection.connect` raises :py:obj:`socket.error` if the underlying socket
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001420 connect method raises it.
1421 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001422 client = socket()
1423 context = Context(TLSv1_METHOD)
1424 clientSSL = Connection(context, client)
1425 exc = self.assertRaises(error, clientSSL.connect, ("127.0.0.1", 1))
Jean-Paul Calderone35adf9d2010-07-29 18:40:44 -04001426 self.assertEquals(exc.args[0], ECONNREFUSED)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001427
1428
1429 def test_connect(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001430 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001431 :py:obj:`Connection.connect` establishes a connection to the specified address.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001432 """
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001433 port = socket()
1434 port.bind(('', 0))
1435 port.listen(3)
1436
1437 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04001438 clientSSL.connect(('127.0.0.1', port.getsockname()[1]))
1439 # XXX An assertion? Or something?
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001440
1441
Jean-Paul Calderone7b614872010-09-24 17:43:44 -04001442 if platform == "darwin":
1443 "connect_ex sometimes causes a kernel panic on OS X 10.6.4"
1444 else:
1445 def test_connect_ex(self):
1446 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001447 If there is a connection error, :py:obj:`Connection.connect_ex` returns the
Jean-Paul Calderone7b614872010-09-24 17:43:44 -04001448 errno instead of raising an exception.
1449 """
1450 port = socket()
1451 port.bind(('', 0))
1452 port.listen(3)
Jean-Paul Calderone55d91f42010-07-29 19:22:17 -04001453
Jean-Paul Calderone7b614872010-09-24 17:43:44 -04001454 clientSSL = Connection(Context(TLSv1_METHOD), socket())
1455 clientSSL.setblocking(False)
1456 result = clientSSL.connect_ex(port.getsockname())
1457 expected = (EINPROGRESS, EWOULDBLOCK)
1458 self.assertTrue(
1459 result in expected, "%r not in %r" % (result, expected))
Jean-Paul Calderone55d91f42010-07-29 19:22:17 -04001460
1461
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001462 def test_accept_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001463 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001464 :py:obj:`Connection.accept` raises :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001465 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001466 connection = Connection(Context(TLSv1_METHOD), socket())
1467 self.assertRaises(TypeError, connection.accept, None)
1468
1469
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001470 def test_accept(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001471 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001472 :py:obj:`Connection.accept` accepts a pending connection attempt and returns a
1473 tuple of a new :py:obj:`Connection` (the accepted client) and the address the
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001474 connection originated from.
1475 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001476 ctx = Context(TLSv1_METHOD)
1477 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1478 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001479 port = socket()
1480 portSSL = Connection(ctx, port)
1481 portSSL.bind(('', 0))
1482 portSSL.listen(3)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001483
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001484 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04001485
1486 # Calling portSSL.getsockname() here to get the server IP address sounds
1487 # great, but frequently fails on Windows.
1488 clientSSL.connect(('127.0.0.1', portSSL.getsockname()[1]))
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001489
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04001490 serverSSL, address = portSSL.accept()
1491
1492 self.assertTrue(isinstance(serverSSL, Connection))
1493 self.assertIdentical(serverSSL.get_context(), ctx)
1494 self.assertEquals(address, clientSSL.getsockname())
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04001495
1496
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001497 def test_shutdown_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001498 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001499 :py:obj:`Connection.shutdown` raises :py:obj:`TypeError` if called with the wrong
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001500 number of arguments or with arguments other than integers.
1501 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001502 connection = Connection(Context(TLSv1_METHOD), None)
1503 self.assertRaises(TypeError, connection.shutdown, None)
Jean-Paul Calderone1d3e0222010-07-29 22:52:45 -04001504 self.assertRaises(TypeError, connection.get_shutdown, None)
1505 self.assertRaises(TypeError, connection.set_shutdown)
1506 self.assertRaises(TypeError, connection.set_shutdown, None)
1507 self.assertRaises(TypeError, connection.set_shutdown, 0, 1)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001508
1509
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001510 def test_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001511 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001512 :py:obj:`Connection.shutdown` performs an SSL-level connection shutdown.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001513 """
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001514 server, client = self._loopback()
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04001515 self.assertFalse(server.shutdown())
1516 self.assertEquals(server.get_shutdown(), SENT_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001517 self.assertRaises(ZeroReturnError, client.recv, 1024)
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04001518 self.assertEquals(client.get_shutdown(), RECEIVED_SHUTDOWN)
1519 client.shutdown()
1520 self.assertEquals(client.get_shutdown(), SENT_SHUTDOWN|RECEIVED_SHUTDOWN)
1521 self.assertRaises(ZeroReturnError, server.recv, 1024)
1522 self.assertEquals(server.get_shutdown(), SENT_SHUTDOWN|RECEIVED_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001523
1524
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04001525 def test_set_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001526 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001527 :py:obj:`Connection.set_shutdown` sets the state of the SSL connection shutdown
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001528 process.
1529 """
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04001530 connection = Connection(Context(TLSv1_METHOD), socket())
1531 connection.set_shutdown(RECEIVED_SHUTDOWN)
1532 self.assertEquals(connection.get_shutdown(), RECEIVED_SHUTDOWN)
1533
1534
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001535 def test_app_data_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001536 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001537 :py:obj:`Connection.set_app_data` raises :py:obj:`TypeError` if called with other than
1538 one argument. :py:obj:`Connection.get_app_data` raises :py:obj:`TypeError` if called
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001539 with any arguments.
1540 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001541 conn = Connection(Context(TLSv1_METHOD), None)
1542 self.assertRaises(TypeError, conn.get_app_data, None)
1543 self.assertRaises(TypeError, conn.set_app_data)
1544 self.assertRaises(TypeError, conn.set_app_data, None, None)
1545
1546
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04001547 def test_app_data(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001548 """
1549 Any object can be set as app data by passing it to
Jonathan Ballet648875f2011-07-16 14:14:58 +09001550 :py:obj:`Connection.set_app_data` and later retrieved with
1551 :py:obj:`Connection.get_app_data`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001552 """
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04001553 conn = Connection(Context(TLSv1_METHOD), None)
1554 app_data = object()
1555 conn.set_app_data(app_data)
1556 self.assertIdentical(conn.get_app_data(), app_data)
1557
1558
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001559 def test_makefile(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001560 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001561 :py:obj:`Connection.makefile` is not implemented and calling that method raises
1562 :py:obj:`NotImplementedError`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04001563 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001564 conn = Connection(Context(TLSv1_METHOD), None)
1565 self.assertRaises(NotImplementedError, conn.makefile)
1566
1567
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001568 def test_get_peer_cert_chain_wrong_args(self):
1569 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001570 :py:obj:`Connection.get_peer_cert_chain` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001571 arguments.
1572 """
1573 conn = Connection(Context(TLSv1_METHOD), None)
1574 self.assertRaises(TypeError, conn.get_peer_cert_chain, 1)
1575 self.assertRaises(TypeError, conn.get_peer_cert_chain, "foo")
1576 self.assertRaises(TypeError, conn.get_peer_cert_chain, object())
1577 self.assertRaises(TypeError, conn.get_peer_cert_chain, [])
1578
1579
1580 def test_get_peer_cert_chain(self):
1581 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001582 :py:obj:`Connection.get_peer_cert_chain` returns a list of certificates which
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001583 the connected server returned for the certification verification.
1584 """
1585 chain = _create_certificate_chain()
1586 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1587
1588 serverContext = Context(TLSv1_METHOD)
1589 serverContext.use_privatekey(skey)
1590 serverContext.use_certificate(scert)
1591 serverContext.add_extra_chain_cert(icert)
1592 serverContext.add_extra_chain_cert(cacert)
1593 server = Connection(serverContext, None)
1594 server.set_accept_state()
1595
1596 # Create the client
1597 clientContext = Context(TLSv1_METHOD)
1598 clientContext.set_verify(VERIFY_NONE, verify_cb)
1599 client = Connection(clientContext, None)
1600 client.set_connect_state()
1601
1602 self._interactInMemory(client, server)
1603
1604 chain = client.get_peer_cert_chain()
1605 self.assertEqual(len(chain), 3)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04001606 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04001607 "Server Certificate", chain[0].get_subject().CN)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04001608 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04001609 "Intermediate Certificate", chain[1].get_subject().CN)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04001610 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04001611 "Authority Certificate", chain[2].get_subject().CN)
1612
1613
1614 def test_get_peer_cert_chain_none(self):
1615 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001616 :py:obj:`Connection.get_peer_cert_chain` returns :py:obj:`None` if the peer sends no
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04001617 certificate chain.
1618 """
1619 ctx = Context(TLSv1_METHOD)
1620 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
1621 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
1622 server = Connection(ctx, None)
1623 server.set_accept_state()
1624 client = Connection(Context(TLSv1_METHOD), None)
1625 client.set_connect_state()
1626 self._interactInMemory(client, server)
1627 self.assertIdentical(None, server.get_peer_cert_chain())
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001628
1629
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05001630 def test_get_session_wrong_args(self):
1631 """
1632 :py:obj:`Connection.get_session` raises :py:obj:`TypeError` if called
1633 with any arguments.
1634 """
1635 ctx = Context(TLSv1_METHOD)
1636 server = Connection(ctx, None)
1637 self.assertRaises(TypeError, server.get_session, 123)
1638 self.assertRaises(TypeError, server.get_session, "hello")
1639 self.assertRaises(TypeError, server.get_session, object())
1640
1641
1642 def test_get_session_unconnected(self):
1643 """
1644 :py:obj:`Connection.get_session` returns :py:obj:`None` when used with
1645 an object which has not been connected.
1646 """
1647 ctx = Context(TLSv1_METHOD)
1648 server = Connection(ctx, None)
1649 session = server.get_session()
1650 self.assertIdentical(None, session)
1651
1652
1653 def test_server_get_session(self):
1654 """
1655 On the server side of a connection, :py:obj:`Connection.get_session`
1656 returns a :py:class:`Session` instance representing the SSL session for
1657 that connection.
1658 """
1659 server, client = self._loopback()
1660 session = server.get_session()
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001661 self.assertIsInstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05001662
1663
1664 def test_client_get_session(self):
1665 """
1666 On the client side of a connection, :py:obj:`Connection.get_session`
1667 returns a :py:class:`Session` instance representing the SSL session for
1668 that connection.
1669 """
1670 server, client = self._loopback()
1671 session = client.get_session()
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001672 self.assertIsInstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05001673
1674
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05001675 def test_set_session_wrong_args(self):
1676 """
1677 If called with an object that is not an instance of :py:class:`Session`,
1678 or with other than one argument, :py:obj:`Connection.set_session` raises
1679 :py:obj:`TypeError`.
1680 """
1681 ctx = Context(TLSv1_METHOD)
1682 connection = Connection(ctx, None)
1683 self.assertRaises(TypeError, connection.set_session)
1684 self.assertRaises(TypeError, connection.set_session, 123)
1685 self.assertRaises(TypeError, connection.set_session, "hello")
1686 self.assertRaises(TypeError, connection.set_session, object())
1687 self.assertRaises(
1688 TypeError, connection.set_session, Session(), Session())
1689
1690
1691 def test_client_set_session(self):
1692 """
1693 :py:obj:`Connection.set_session`, when used prior to a connection being
1694 established, accepts a :py:class:`Session` instance and causes an
1695 attempt to re-use the session it represents when the SSL handshake is
1696 performed.
1697 """
1698 key = load_privatekey(FILETYPE_PEM, server_key_pem)
1699 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
1700 ctx = Context(TLSv1_METHOD)
1701 ctx.use_privatekey(key)
1702 ctx.use_certificate(cert)
1703 ctx.set_session_id("unity-test")
1704
1705 def makeServer(socket):
1706 server = Connection(ctx, socket)
1707 server.set_accept_state()
1708 return server
1709
1710 originalServer, originalClient = self._loopback(
1711 serverFactory=makeServer)
1712 originalSession = originalClient.get_session()
1713
1714 def makeClient(socket):
1715 client = self._loopbackClientFactory(socket)
1716 client.set_session(originalSession)
1717 return client
1718 resumedServer, resumedClient = self._loopback(
1719 serverFactory=makeServer,
1720 clientFactory=makeClient)
1721
1722 # This is a proxy: in general, we have no access to any unique
1723 # identifier for the session (new enough versions of OpenSSL expose a
1724 # hash which could be usable, but "new enough" is very, very new).
1725 # Instead, exploit the fact that the master key is re-used if the
1726 # session is re-used. As long as the master key for the two connections
1727 # is the same, the session was re-used!
1728 self.assertEqual(
1729 originalServer.master_key(), resumedServer.master_key())
1730
1731
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05001732 def test_set_session_wrong_method(self):
1733 """
Jean-Paul Calderone068cb592012-02-14 16:52:43 -05001734 If :py:obj:`Connection.set_session` is passed a :py:class:`Session`
1735 instance associated with a context using a different SSL method than the
1736 :py:obj:`Connection` is using, a :py:class:`OpenSSL.SSL.Error` is
1737 raised.
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05001738 """
1739 key = load_privatekey(FILETYPE_PEM, server_key_pem)
1740 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
1741 ctx = Context(TLSv1_METHOD)
1742 ctx.use_privatekey(key)
1743 ctx.use_certificate(cert)
1744 ctx.set_session_id("unity-test")
1745
1746 def makeServer(socket):
1747 server = Connection(ctx, socket)
1748 server.set_accept_state()
1749 return server
1750
1751 originalServer, originalClient = self._loopback(
1752 serverFactory=makeServer)
1753 originalSession = originalClient.get_session()
1754
1755 def makeClient(socket):
1756 # Intentionally use a different, incompatible method here.
1757 client = Connection(Context(SSLv3_METHOD), socket)
1758 client.set_connect_state()
1759 client.set_session(originalSession)
1760 return client
1761
1762 self.assertRaises(
1763 Error,
1764 self._loopback, clientFactory=makeClient, serverFactory=makeServer)
1765
1766
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07001767 def test_wantWriteError(self):
1768 """
1769 :py:obj:`Connection` methods which generate output raise
1770 :py:obj:`OpenSSL.SSL.WantWriteError` if writing to the connection's BIO
1771 fail indicating a should-write state.
1772 """
1773 client_socket, server_socket = socket_pair()
1774 # Fill up the client's send buffer so Connection won't be able to write
1775 # anything.
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001776 msg = b"x" * 1024
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07001777 for i in range(1024):
1778 try:
1779 client_socket.send(msg)
1780 except error as e:
1781 if e.errno == EWOULDBLOCK:
1782 break
1783 raise
1784 else:
1785 self.fail(
1786 "Failed to fill socket buffer, cannot test BIO want write")
1787
1788 ctx = Context(TLSv1_METHOD)
1789 conn = Connection(ctx, client_socket)
1790 # Client's speak first, so make it an SSL client
1791 conn.set_connect_state()
1792 self.assertRaises(WantWriteError, conn.do_handshake)
1793
1794 # XXX want_read
1795
1796
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001797
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04001798class ConnectionGetCipherListTests(TestCase):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001799 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001800 Tests for :py:obj:`Connection.get_cipher_list`.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001801 """
Jean-Paul Calderone54a2bc02010-09-09 17:52:38 -04001802 def test_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001803 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001804 :py:obj:`Connection.get_cipher_list` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001805 arguments.
1806 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04001807 connection = Connection(Context(TLSv1_METHOD), None)
1808 self.assertRaises(TypeError, connection.get_cipher_list, None)
1809
1810
1811 def test_result(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001812 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001813 :py:obj:`Connection.get_cipher_list` returns a :py:obj:`list` of
1814 :py:obj:`bytes` giving the names of the ciphers which might be used.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001815 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04001816 connection = Connection(Context(TLSv1_METHOD), None)
1817 ciphers = connection.get_cipher_list()
1818 self.assertTrue(isinstance(ciphers, list))
1819 for cipher in ciphers:
1820 self.assertTrue(isinstance(cipher, str))
1821
1822
1823
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05001824class ConnectionSendTests(TestCase, _LoopbackMixin):
1825 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001826 Tests for :py:obj:`Connection.send`
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05001827 """
1828 def test_wrong_args(self):
1829 """
1830 When called with arguments other than a single string,
Jonathan Ballet648875f2011-07-16 14:14:58 +09001831 :py:obj:`Connection.send` raises :py:obj:`TypeError`.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05001832 """
1833 connection = Connection(Context(TLSv1_METHOD), None)
Jean-Paul Calderone77fa2602011-01-05 18:23:39 -05001834 self.assertRaises(TypeError, connection.send)
1835 self.assertRaises(TypeError, connection.send, object())
1836 self.assertRaises(TypeError, connection.send, "foo", "bar")
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05001837
1838
1839 def test_short_bytes(self):
1840 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001841 When passed a short byte string, :py:obj:`Connection.send` transmits all of it
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05001842 and returns the number of bytes sent.
1843 """
1844 server, client = self._loopback()
1845 count = server.send(b('xy'))
1846 self.assertEquals(count, 2)
1847 self.assertEquals(client.recv(2), b('xy'))
1848
1849 try:
1850 memoryview
1851 except NameError:
1852 "cannot test sending memoryview without memoryview"
1853 else:
1854 def test_short_memoryview(self):
1855 """
1856 When passed a memoryview onto a small number of bytes,
Jonathan Ballet648875f2011-07-16 14:14:58 +09001857 :py:obj:`Connection.send` transmits all of them and returns the number of
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05001858 bytes sent.
1859 """
1860 server, client = self._loopback()
1861 count = server.send(memoryview(b('xy')))
1862 self.assertEquals(count, 2)
1863 self.assertEquals(client.recv(2), b('xy'))
1864
1865
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05001866
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04001867class ConnectionSendallTests(TestCase, _LoopbackMixin):
1868 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001869 Tests for :py:obj:`Connection.sendall`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04001870 """
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001871 def test_wrong_args(self):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04001872 """
1873 When called with arguments other than a single string,
Jonathan Ballet648875f2011-07-16 14:14:58 +09001874 :py:obj:`Connection.sendall` raises :py:obj:`TypeError`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04001875 """
1876 connection = Connection(Context(TLSv1_METHOD), None)
1877 self.assertRaises(TypeError, connection.sendall)
1878 self.assertRaises(TypeError, connection.sendall, object())
1879 self.assertRaises(TypeError, connection.sendall, "foo", "bar")
1880
1881
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001882 def test_short(self):
1883 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001884 :py:obj:`Connection.sendall` transmits all of the bytes in the string passed to
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001885 it.
1886 """
1887 server, client = self._loopback()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04001888 server.sendall(b('x'))
1889 self.assertEquals(client.recv(1), b('x'))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001890
1891
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05001892 try:
1893 memoryview
1894 except NameError:
1895 "cannot test sending memoryview without memoryview"
1896 else:
1897 def test_short_memoryview(self):
1898 """
1899 When passed a memoryview onto a small number of bytes,
Jonathan Ballet648875f2011-07-16 14:14:58 +09001900 :py:obj:`Connection.sendall` transmits all of them.
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05001901 """
1902 server, client = self._loopback()
1903 server.sendall(memoryview(b('x')))
1904 self.assertEquals(client.recv(1), b('x'))
1905
1906
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001907 def test_long(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001908 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001909 :py:obj:`Connection.sendall` transmits all of the bytes in the string passed to
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001910 it even if this requires multiple calls of an underlying write function.
1911 """
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001912 server, client = self._loopback()
Jean-Paul Calderone6241c702010-09-16 19:59:24 -04001913 # Should be enough, underlying SSL_write should only do 16k at a time.
1914 # On Windows, after 32k of bytes the write will block (forever - because
1915 # no one is yet reading).
Jean-Paul Calderone9e4c1352010-09-19 09:34:43 -04001916 message = b('x') * (1024 * 32 - 1) + b('y')
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001917 server.sendall(message)
1918 accum = []
1919 received = 0
1920 while received < len(message):
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04001921 data = client.recv(1024)
1922 accum.append(data)
1923 received += len(data)
Jean-Paul Calderonef4047852010-09-19 09:45:57 -04001924 self.assertEquals(message, b('').join(accum))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001925
1926
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04001927 def test_closed(self):
1928 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001929 If the underlying socket is closed, :py:obj:`Connection.sendall` propagates the
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04001930 write error from the low level write call.
1931 """
1932 server, client = self._loopback()
Jean-Paul Calderone05d43e82010-09-24 18:01:36 -04001933 server.sock_shutdown(2)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001934 exc = self.assertRaises(SysCallError, server.sendall, b"hello, world")
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001935 self.assertEqual(exc.args[0], EPIPE)
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04001936
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04001937
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04001938
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04001939class ConnectionRenegotiateTests(TestCase, _LoopbackMixin):
1940 """
1941 Tests for SSL renegotiation APIs.
1942 """
1943 def test_renegotiate_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001944 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001945 :py:obj:`Connection.renegotiate` raises :py:obj:`TypeError` if called with any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001946 arguments.
1947 """
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04001948 connection = Connection(Context(TLSv1_METHOD), None)
1949 self.assertRaises(TypeError, connection.renegotiate, None)
1950
1951
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001952 def test_total_renegotiations_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001953 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001954 :py:obj:`Connection.total_renegotiations` raises :py:obj:`TypeError` if called with
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001955 any arguments.
1956 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001957 connection = Connection(Context(TLSv1_METHOD), None)
1958 self.assertRaises(TypeError, connection.total_renegotiations, None)
1959
1960
1961 def test_total_renegotiations(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001962 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001963 :py:obj:`Connection.total_renegotiations` returns :py:obj:`0` before any
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001964 renegotiations have happened.
1965 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04001966 connection = Connection(Context(TLSv1_METHOD), None)
1967 self.assertEquals(connection.total_renegotiations(), 0)
1968
1969
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04001970# def test_renegotiate(self):
1971# """
1972# """
1973# server, client = self._loopback()
1974
1975# server.send("hello world")
1976# self.assertEquals(client.recv(len("hello world")), "hello world")
1977
1978# self.assertEquals(server.total_renegotiations(), 0)
1979# self.assertTrue(server.renegotiate())
1980
1981# server.setblocking(False)
1982# client.setblocking(False)
1983# while server.renegotiate_pending():
1984# client.do_handshake()
1985# server.do_handshake()
1986
1987# self.assertEquals(server.total_renegotiations(), 1)
1988
1989
1990
1991
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001992class ErrorTests(TestCase):
1993 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001994 Unit tests for :py:obj:`OpenSSL.SSL.Error`.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001995 """
1996 def test_type(self):
1997 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09001998 :py:obj:`Error` is an exception type.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001999 """
2000 self.assertTrue(issubclass(Error, Exception))
Rick Deane15b1472009-07-09 15:53:42 -05002001 self.assertEqual(Error.__name__, 'Error')
Rick Deane15b1472009-07-09 15:53:42 -05002002
2003
2004
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05002005class ConstantsTests(TestCase):
2006 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002007 Tests for the values of constants exposed in :py:obj:`OpenSSL.SSL`.
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05002008
2009 These are values defined by OpenSSL intended only to be used as flags to
2010 OpenSSL APIs. The only assertions it seems can be made about them is
2011 their values.
2012 """
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002013 # unittest.TestCase has no skip mechanism
2014 if OP_NO_QUERY_MTU is not None:
2015 def test_op_no_query_mtu(self):
2016 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002017 The value of :py:obj:`OpenSSL.SSL.OP_NO_QUERY_MTU` is 0x1000, the value of
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002018 :py:const:`SSL_OP_NO_QUERY_MTU` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002019 """
2020 self.assertEqual(OP_NO_QUERY_MTU, 0x1000)
2021 else:
2022 "OP_NO_QUERY_MTU unavailable - OpenSSL version may be too old"
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05002023
2024
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002025 if OP_COOKIE_EXCHANGE is not None:
2026 def test_op_cookie_exchange(self):
2027 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002028 The value of :py:obj:`OpenSSL.SSL.OP_COOKIE_EXCHANGE` is 0x2000, the value
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002029 of :py:const:`SSL_OP_COOKIE_EXCHANGE` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002030 """
2031 self.assertEqual(OP_COOKIE_EXCHANGE, 0x2000)
2032 else:
2033 "OP_COOKIE_EXCHANGE unavailable - OpenSSL version may be too old"
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05002034
2035
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002036 if OP_NO_TICKET is not None:
2037 def test_op_no_ticket(self):
2038 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002039 The value of :py:obj:`OpenSSL.SSL.OP_NO_TICKET` is 0x4000, the value of
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002040 :py:const:`SSL_OP_NO_TICKET` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002041 """
2042 self.assertEqual(OP_NO_TICKET, 0x4000)
Jean-Paul Calderonecebd1782011-09-11 10:01:31 -04002043 else:
Jean-Paul Calderoned811b682008-12-28 22:59:15 -05002044 "OP_NO_TICKET unavailable - OpenSSL version may be too old"
Rick Dean5b7b6372009-04-01 11:34:06 -05002045
2046
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04002047 if OP_NO_COMPRESSION is not None:
2048 def test_op_no_compression(self):
2049 """
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04002050 The value of :py:obj:`OpenSSL.SSL.OP_NO_COMPRESSION` is 0x20000, the value
2051 of :py:const:`SSL_OP_NO_COMPRESSION` defined by :file:`openssl/ssl.h`.
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04002052 """
2053 self.assertEqual(OP_NO_COMPRESSION, 0x20000)
2054 else:
2055 "OP_NO_COMPRESSION unavailable - OpenSSL version may be too old"
2056
2057
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05002058 def test_sess_cache_off(self):
2059 """
2060 The value of L{OpenSSL.SSL.SESS_CACHE_OFF} 0x0, the value of
2061 L{SSL_SESS_CACHE_OFF} defined by I{openssl/ssl.h}.
2062 """
2063 self.assertEqual(0x0, SESS_CACHE_OFF)
2064
2065
2066 def test_sess_cache_client(self):
2067 """
2068 The value of L{OpenSSL.SSL.SESS_CACHE_CLIENT} 0x1, the value of
2069 L{SSL_SESS_CACHE_CLIENT} defined by I{openssl/ssl.h}.
2070 """
2071 self.assertEqual(0x1, SESS_CACHE_CLIENT)
2072
2073
2074 def test_sess_cache_server(self):
2075 """
2076 The value of L{OpenSSL.SSL.SESS_CACHE_SERVER} 0x2, the value of
2077 L{SSL_SESS_CACHE_SERVER} defined by I{openssl/ssl.h}.
2078 """
2079 self.assertEqual(0x2, SESS_CACHE_SERVER)
2080
2081
2082 def test_sess_cache_both(self):
2083 """
2084 The value of L{OpenSSL.SSL.SESS_CACHE_BOTH} 0x3, the value of
2085 L{SSL_SESS_CACHE_BOTH} defined by I{openssl/ssl.h}.
2086 """
2087 self.assertEqual(0x3, SESS_CACHE_BOTH)
2088
2089
2090 def test_sess_cache_no_auto_clear(self):
2091 """
2092 The value of L{OpenSSL.SSL.SESS_CACHE_NO_AUTO_CLEAR} 0x80, the value of
2093 L{SSL_SESS_CACHE_NO_AUTO_CLEAR} defined by I{openssl/ssl.h}.
2094 """
2095 self.assertEqual(0x80, SESS_CACHE_NO_AUTO_CLEAR)
2096
2097
2098 def test_sess_cache_no_internal_lookup(self):
2099 """
2100 The value of L{OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_LOOKUP} 0x100, the
2101 value of L{SSL_SESS_CACHE_NO_INTERNAL_LOOKUP} defined by
2102 I{openssl/ssl.h}.
2103 """
2104 self.assertEqual(0x100, SESS_CACHE_NO_INTERNAL_LOOKUP)
2105
2106
2107 def test_sess_cache_no_internal_store(self):
2108 """
2109 The value of L{OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_STORE} 0x200, the
2110 value of L{SSL_SESS_CACHE_NO_INTERNAL_STORE} defined by
2111 I{openssl/ssl.h}.
2112 """
2113 self.assertEqual(0x200, SESS_CACHE_NO_INTERNAL_STORE)
2114
2115
2116 def test_sess_cache_no_internal(self):
2117 """
2118 The value of L{OpenSSL.SSL.SESS_CACHE_NO_INTERNAL} 0x300, the value of
2119 L{SSL_SESS_CACHE_NO_INTERNAL} defined by I{openssl/ssl.h}.
2120 """
2121 self.assertEqual(0x300, SESS_CACHE_NO_INTERNAL)
2122
2123
Jean-Paul Calderoneeeee26a2009-04-27 11:24:30 -04002124
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002125class MemoryBIOTests(TestCase, _LoopbackMixin):
Rick Deanb71c0d22009-04-01 14:09:23 -05002126 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002127 Tests for :py:obj:`OpenSSL.SSL.Connection` using a memory BIO.
Rick Deanb71c0d22009-04-01 14:09:23 -05002128 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002129 def _server(self, sock):
2130 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002131 Create a new server-side SSL :py:obj:`Connection` object wrapped around
2132 :py:obj:`sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002133 """
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002134 # Create the server side Connection. This is mostly setup boilerplate
2135 # - use TLSv1, use a particular certificate, etc.
2136 server_ctx = Context(TLSv1_METHOD)
2137 server_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE )
2138 server_ctx.set_verify(VERIFY_PEER|VERIFY_FAIL_IF_NO_PEER_CERT|VERIFY_CLIENT_ONCE, verify_cb)
2139 server_store = server_ctx.get_cert_store()
2140 server_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2141 server_ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
2142 server_ctx.check_privatekey()
2143 server_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05002144 # Here the Connection is actually created. If None is passed as the 2nd
2145 # parameter, it indicates a memory BIO should be created.
2146 server_conn = Connection(server_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002147 server_conn.set_accept_state()
2148 return server_conn
2149
2150
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002151 def _client(self, sock):
2152 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002153 Create a new client-side SSL :py:obj:`Connection` object wrapped around
2154 :py:obj:`sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002155 """
2156 # Now create the client side Connection. Similar boilerplate to the
2157 # above.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002158 client_ctx = Context(TLSv1_METHOD)
2159 client_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE )
2160 client_ctx.set_verify(VERIFY_PEER|VERIFY_FAIL_IF_NO_PEER_CERT|VERIFY_CLIENT_ONCE, verify_cb)
2161 client_store = client_ctx.get_cert_store()
2162 client_ctx.use_privatekey(load_privatekey(FILETYPE_PEM, client_key_pem))
2163 client_ctx.use_certificate(load_certificate(FILETYPE_PEM, client_cert_pem))
2164 client_ctx.check_privatekey()
2165 client_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05002166 client_conn = Connection(client_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002167 client_conn.set_connect_state()
2168 return client_conn
2169
2170
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002171 def test_memoryConnect(self):
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002172 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002173 Two :py:obj:`Connection`s which use memory BIOs can be manually connected by
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002174 reading from the output of each and writing those bytes to the input of
2175 the other and in this way establish a connection and exchange
2176 application-level bytes with each other.
2177 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002178 server_conn = self._server(None)
2179 client_conn = self._client(None)
Rick Deanb71c0d22009-04-01 14:09:23 -05002180
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002181 # There should be no key or nonces yet.
2182 self.assertIdentical(server_conn.master_key(), None)
2183 self.assertIdentical(server_conn.client_random(), None)
2184 self.assertIdentical(server_conn.server_random(), None)
Rick Deanb71c0d22009-04-01 14:09:23 -05002185
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002186 # First, the handshake needs to happen. We'll deliver bytes back and
2187 # forth between the client and server until neither of them feels like
2188 # speaking any more.
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002189 self.assertIdentical(
2190 self._interactInMemory(client_conn, server_conn), None)
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002191
2192 # Now that the handshake is done, there should be a key and nonces.
2193 self.assertNotIdentical(server_conn.master_key(), None)
2194 self.assertNotIdentical(server_conn.client_random(), None)
2195 self.assertNotIdentical(server_conn.server_random(), None)
Jean-Paul Calderone6c051e62009-07-05 13:50:34 -04002196 self.assertEquals(server_conn.client_random(), client_conn.client_random())
2197 self.assertEquals(server_conn.server_random(), client_conn.server_random())
2198 self.assertNotEquals(server_conn.client_random(), server_conn.server_random())
2199 self.assertNotEquals(client_conn.client_random(), client_conn.server_random())
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002200
2201 # Here are the bytes we'll try to send.
Jean-Paul Calderonea441fdc2010-08-22 21:33:57 -04002202 important_message = b('One if by land, two if by sea.')
Rick Deanb71c0d22009-04-01 14:09:23 -05002203
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002204 server_conn.write(important_message)
2205 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002206 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002207 (client_conn, important_message))
2208
2209 client_conn.write(important_message[::-1])
2210 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002211 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04002212 (server_conn, important_message[::-1]))
Rick Deanb71c0d22009-04-01 14:09:23 -05002213
2214
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002215 def test_socketConnect(self):
Rick Deanb1ccd562009-07-09 23:52:39 -05002216 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002217 Just like :py:obj:`test_memoryConnect` but with an actual socket.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002218
2219 This is primarily to rule out the memory BIO code as the source of
Jonathan Ballet648875f2011-07-16 14:14:58 +09002220 any problems encountered while passing data over a :py:obj:`Connection` (if
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002221 this test fails, there must be a problem outside the memory BIO
2222 code, as no memory BIO is involved here). Even though this isn't a
2223 memory BIO test, it's convenient to have it here.
Rick Deanb1ccd562009-07-09 23:52:39 -05002224 """
Jean-Paul Calderone06c7cc92010-09-24 23:52:00 -04002225 server_conn, client_conn = self._loopback()
Rick Deanb1ccd562009-07-09 23:52:39 -05002226
Jean-Paul Calderonea441fdc2010-08-22 21:33:57 -04002227 important_message = b("Help me Obi Wan Kenobi, you're my only hope.")
Rick Deanb1ccd562009-07-09 23:52:39 -05002228 client_conn.send(important_message)
2229 msg = server_conn.recv(1024)
2230 self.assertEqual(msg, important_message)
2231
2232 # Again in the other direction, just for fun.
2233 important_message = important_message[::-1]
2234 server_conn.send(important_message)
2235 msg = client_conn.recv(1024)
2236 self.assertEqual(msg, important_message)
2237
2238
Jean-Paul Calderonefc4ed0f2009-04-27 11:51:27 -04002239 def test_socketOverridesMemory(self):
Rick Deanb71c0d22009-04-01 14:09:23 -05002240 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002241 Test that :py:obj:`OpenSSL.SSL.bio_read` and :py:obj:`OpenSSL.SSL.bio_write` don't
2242 work on :py:obj:`OpenSSL.SSL.Connection`() that use sockets.
Rick Deanb71c0d22009-04-01 14:09:23 -05002243 """
2244 context = Context(SSLv3_METHOD)
2245 client = socket()
2246 clientSSL = Connection(context, client)
2247 self.assertRaises( TypeError, clientSSL.bio_read, 100)
2248 self.assertRaises( TypeError, clientSSL.bio_write, "foo")
Jean-Paul Calderone07acf3f2009-05-05 13:23:28 -04002249 self.assertRaises( TypeError, clientSSL.bio_shutdown )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002250
2251
2252 def test_outgoingOverflow(self):
2253 """
2254 If more bytes than can be written to the memory BIO are passed to
Jonathan Ballet648875f2011-07-16 14:14:58 +09002255 :py:obj:`Connection.send` at once, the number of bytes which were written is
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002256 returned and that many bytes from the beginning of the input can be
2257 read from the other end of the connection.
2258 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002259 server = self._server(None)
2260 client = self._client(None)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002261
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002262 self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002263
2264 size = 2 ** 15
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002265 sent = client.send(b"x" * size)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002266 # Sanity check. We're trying to test what happens when the entire
2267 # input can't be sent. If the entire input was sent, this test is
2268 # meaningless.
2269 self.assertTrue(sent < size)
2270
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002271 receiver, received = self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04002272 self.assertIdentical(receiver, server)
2273
2274 # We can rely on all of these bytes being received at once because
2275 # _loopback passes 2 ** 16 to recv - more than 2 ** 15.
2276 self.assertEquals(len(received), sent)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04002277
2278
2279 def test_shutdown(self):
2280 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002281 :py:obj:`Connection.bio_shutdown` signals the end of the data stream from
2282 which the :py:obj:`Connection` reads.
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04002283 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04002284 server = self._server(None)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04002285 server.bio_shutdown()
2286 e = self.assertRaises(Error, server.recv, 1024)
2287 # We don't want WantReadError or ZeroReturnError or anything - it's a
2288 # handshake failure.
2289 self.assertEquals(e.__class__, Error)
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04002290
2291
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002292 def test_unexpectedEndOfFile(self):
2293 """
2294 If the connection is lost before an orderly SSL shutdown occurs,
2295 :py:obj:`OpenSSL.SSL.SysCallError` is raised with a message of
2296 "Unexpected EOF".
2297 """
2298 server_conn, client_conn = self._loopback()
2299 client_conn.sock_shutdown(SHUT_RDWR)
2300 exc = self.assertRaises(SysCallError, server_conn.recv, 1024)
2301 self.assertEqual(exc.args, (-1, "Unexpected EOF"))
2302
2303
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002304 def _check_client_ca_list(self, func):
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002305 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002306 Verify the return value of the :py:obj:`get_client_ca_list` method for server and client connections.
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002307
Jonathan Ballet78b92a22011-07-16 08:07:26 +09002308 :param func: A function which will be called with the server context
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002309 before the client and server are connected to each other. This
2310 function should specify a list of CAs for the server to send to the
2311 client and return that same list. The list will be used to verify
Jonathan Ballet648875f2011-07-16 14:14:58 +09002312 that :py:obj:`get_client_ca_list` returns the proper value at various
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002313 times.
2314 """
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002315 server = self._server(None)
2316 client = self._client(None)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002317 self.assertEqual(client.get_client_ca_list(), [])
2318 self.assertEqual(server.get_client_ca_list(), [])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002319 ctx = server.get_context()
2320 expected = func(ctx)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002321 self.assertEqual(client.get_client_ca_list(), [])
2322 self.assertEqual(server.get_client_ca_list(), expected)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04002323 self._interactInMemory(client, server)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002324 self.assertEqual(client.get_client_ca_list(), expected)
2325 self.assertEqual(server.get_client_ca_list(), expected)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002326
2327
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002328 def test_set_client_ca_list_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002329 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002330 :py:obj:`Context.set_client_ca_list` raises a :py:obj:`TypeError` if called with a
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002331 non-list or a list that contains objects other than X509Names.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002332 """
2333 ctx = Context(TLSv1_METHOD)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002334 self.assertRaises(TypeError, ctx.set_client_ca_list, "spam")
2335 self.assertRaises(TypeError, ctx.set_client_ca_list, ["spam"])
2336 self.assertIdentical(ctx.set_client_ca_list([]), None)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002337
2338
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002339 def test_set_empty_ca_list(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002340 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002341 If passed an empty list, :py:obj:`Context.set_client_ca_list` configures the
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002342 context to send no CA names to the client and, on both the server and
Jonathan Ballet648875f2011-07-16 14:14:58 +09002343 client sides, :py:obj:`Connection.get_client_ca_list` returns an empty list
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002344 after the connection is set up.
2345 """
2346 def no_ca(ctx):
2347 ctx.set_client_ca_list([])
2348 return []
2349 self._check_client_ca_list(no_ca)
2350
2351
2352 def test_set_one_ca_list(self):
2353 """
2354 If passed a list containing a single X509Name,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002355 :py:obj:`Context.set_client_ca_list` configures the context to send that CA
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002356 name to the client and, on both the server and client sides,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002357 :py:obj:`Connection.get_client_ca_list` returns a list containing that
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002358 X509Name after the connection is set up.
2359 """
2360 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2361 cadesc = cacert.get_subject()
2362 def single_ca(ctx):
2363 ctx.set_client_ca_list([cadesc])
2364 return [cadesc]
2365 self._check_client_ca_list(single_ca)
2366
2367
2368 def test_set_multiple_ca_list(self):
2369 """
2370 If passed a list containing multiple X509Name objects,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002371 :py:obj:`Context.set_client_ca_list` configures the context to send those CA
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002372 names to the client and, on both the server and client sides,
Jonathan Ballet648875f2011-07-16 14:14:58 +09002373 :py:obj:`Connection.get_client_ca_list` returns a list containing those
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002374 X509Names after the connection is set up.
2375 """
2376 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2377 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
2378
2379 sedesc = secert.get_subject()
2380 cldesc = clcert.get_subject()
2381
2382 def multiple_ca(ctx):
2383 L = [sedesc, cldesc]
2384 ctx.set_client_ca_list(L)
2385 return L
2386 self._check_client_ca_list(multiple_ca)
2387
2388
2389 def test_reset_ca_list(self):
2390 """
2391 If called multiple times, only the X509Names passed to the final call
Jonathan Ballet648875f2011-07-16 14:14:58 +09002392 of :py:obj:`Context.set_client_ca_list` are used to configure the CA names
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002393 sent to the client.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002394 """
2395 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2396 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2397 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
2398
2399 cadesc = cacert.get_subject()
2400 sedesc = secert.get_subject()
2401 cldesc = clcert.get_subject()
2402
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002403 def changed_ca(ctx):
2404 ctx.set_client_ca_list([sedesc, cldesc])
2405 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002406 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002407 self._check_client_ca_list(changed_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002408
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002409
2410 def test_mutated_ca_list(self):
2411 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002412 If the list passed to :py:obj:`Context.set_client_ca_list` is mutated
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002413 afterwards, this does not affect the list of CA names sent to the
2414 client.
2415 """
2416 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2417 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2418
2419 cadesc = cacert.get_subject()
2420 sedesc = secert.get_subject()
2421
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002422 def mutated_ca(ctx):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002423 L = [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002424 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002425 L.append(sedesc)
2426 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002427 self._check_client_ca_list(mutated_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002428
2429
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002430 def test_add_client_ca_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002431 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002432 :py:obj:`Context.add_client_ca` raises :py:obj:`TypeError` if called with a non-X509
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002433 object or with a number of arguments other than one.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002434 """
2435 ctx = Context(TLSv1_METHOD)
2436 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002437 self.assertRaises(TypeError, ctx.add_client_ca)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002438 self.assertRaises(TypeError, ctx.add_client_ca, "spam")
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04002439 self.assertRaises(TypeError, ctx.add_client_ca, cacert, cacert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002440
2441
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002442 def test_one_add_client_ca(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002443 """
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002444 A certificate's subject can be added as a CA to be sent to the client
Jonathan Ballet648875f2011-07-16 14:14:58 +09002445 with :py:obj:`Context.add_client_ca`.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002446 """
2447 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2448 cadesc = cacert.get_subject()
2449 def single_ca(ctx):
2450 ctx.add_client_ca(cacert)
2451 return [cadesc]
2452 self._check_client_ca_list(single_ca)
2453
2454
2455 def test_multiple_add_client_ca(self):
2456 """
2457 Multiple CA names can be sent to the client by calling
Jonathan Ballet648875f2011-07-16 14:14:58 +09002458 :py:obj:`Context.add_client_ca` with multiple X509 objects.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002459 """
2460 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2461 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2462
2463 cadesc = cacert.get_subject()
2464 sedesc = secert.get_subject()
2465
2466 def multiple_ca(ctx):
2467 ctx.add_client_ca(cacert)
2468 ctx.add_client_ca(secert)
2469 return [cadesc, sedesc]
2470 self._check_client_ca_list(multiple_ca)
2471
2472
2473 def test_set_and_add_client_ca(self):
2474 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002475 A call to :py:obj:`Context.set_client_ca_list` followed by a call to
2476 :py:obj:`Context.add_client_ca` results in using the CA names from the first
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002477 call and the CA name from the second call.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002478 """
2479 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2480 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2481 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
2482
2483 cadesc = cacert.get_subject()
2484 sedesc = secert.get_subject()
2485 cldesc = clcert.get_subject()
2486
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002487 def mixed_set_add_ca(ctx):
2488 ctx.set_client_ca_list([cadesc, sedesc])
2489 ctx.add_client_ca(clcert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002490 return [cadesc, sedesc, cldesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002491 self._check_client_ca_list(mixed_set_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002492
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002493
2494 def test_set_after_add_client_ca(self):
2495 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002496 A call to :py:obj:`Context.set_client_ca_list` after a call to
2497 :py:obj:`Context.add_client_ca` replaces the CA name specified by the former
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002498 call with the names specified by the latter cal.
2499 """
2500 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
2501 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
2502 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
2503
2504 cadesc = cacert.get_subject()
2505 sedesc = secert.get_subject()
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04002506
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002507 def set_replaces_add_ca(ctx):
2508 ctx.add_client_ca(clcert)
2509 ctx.set_client_ca_list([cadesc])
2510 ctx.add_client_ca(secert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002511 return [cadesc, sedesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02002512 self._check_client_ca_list(set_replaces_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02002513
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04002514
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002515
2516class ConnectionBIOTests(TestCase):
2517 """
2518 Tests for :py:obj:`Connection.bio_read` and :py:obj:`Connection.bio_write`.
2519 """
2520 def test_wantReadError(self):
2521 """
2522 :py:obj:`Connection.bio_read` raises :py:obj:`OpenSSL.SSL.WantReadError`
2523 if there are no bytes available to be read from the BIO.
2524 """
2525 ctx = Context(TLSv1_METHOD)
2526 conn = Connection(ctx, None)
2527 self.assertRaises(WantReadError, conn.bio_read, 1024)
2528
2529
2530
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04002531class InfoConstantTests(TestCase):
2532 """
2533 Tests for assorted constants exposed for use in info callbacks.
2534 """
2535 def test_integers(self):
2536 """
2537 All of the info constants are integers.
2538
2539 This is a very weak test. It would be nice to have one that actually
2540 verifies that as certain info events happen, the value passed to the
2541 info callback matches up with the constant exposed by OpenSSL.SSL.
2542 """
2543 for const in [
2544 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK, SSL_ST_INIT,
2545 SSL_ST_BEFORE, SSL_ST_OK, SSL_ST_RENEGOTIATE,
2546 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
2547 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
2548 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
2549 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE]:
2550
2551 self.assertTrue(isinstance(const, int))
2552
Ziga Seilnacht44611bf2009-08-31 20:49:30 +02002553
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04002554if __name__ == '__main__':
2555 main()