blob: 433fa2c1025cc1b386e2356b9b3df324671aa984 [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"""
Hynek Schlawackf90e3682016-03-11 11:21:13 +01005Unit tests for :mod:`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
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +02009from errno import ECONNREFUSED, EINPROGRESS, EWOULDBLOCK, EPIPE, ESHUTDOWN
Hynek Schlawackf8979a52015-09-05 21:25:25 +020010from sys import platform, getfilesystemencoding, version_info
Maximilian Hils1d95dea2015-08-17 19:27:20 +020011from socket import MSG_PEEK, 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
Abraham Martinef063482015-03-25 14:06:24 +000016from warnings import catch_warnings, simplefilter
Jean-Paul Calderone460cc1f2009-03-07 11:31:12 -050017
Hynek Schlawack734d3022015-09-05 19:19:32 +020018import pytest
19
Hynek Schlawackf90e3682016-03-11 11:21:13 +010020from six import PY3, text_type
Jean-Paul Calderonec76c61c2014-01-18 13:21:52 -050021
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040022from OpenSSL.crypto import TYPE_RSA, FILETYPE_PEM
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -080023from OpenSSL.crypto import PKey, X509, X509Extension, X509Store
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040024from OpenSSL.crypto import dump_privatekey, load_privatekey
25from OpenSSL.crypto import dump_certificate, load_certificate
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -040026from OpenSSL.crypto import get_elliptic_curves
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040027
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -040028from OpenSSL.SSL import OPENSSL_VERSION_NUMBER, SSLEAY_VERSION, SSLEAY_CFLAGS
29from OpenSSL.SSL import SSLEAY_PLATFORM, SSLEAY_DIR, SSLEAY_BUILT_ON
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -040030from OpenSSL.SSL import SENT_SHUTDOWN, RECEIVED_SHUTDOWN
Jean-Paul Calderone1461c492013-10-03 16:05:00 -040031from OpenSSL.SSL import (
32 SSLv2_METHOD, SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD,
33 TLSv1_1_METHOD, TLSv1_2_METHOD)
34from OpenSSL.SSL import OP_SINGLE_DH_USE, OP_NO_SSLv2, OP_NO_SSLv3
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040035from OpenSSL.SSL import (
36 VERIFY_PEER, VERIFY_FAIL_IF_NO_PEER_CERT, VERIFY_CLIENT_ONCE, VERIFY_NONE)
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040037
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040038from OpenSSL.SSL import (
Jean-Paul Calderone313bf012012-02-08 13:02:49 -050039 SESS_CACHE_OFF, SESS_CACHE_CLIENT, SESS_CACHE_SERVER, SESS_CACHE_BOTH,
40 SESS_CACHE_NO_AUTO_CLEAR, SESS_CACHE_NO_INTERNAL_LOOKUP,
41 SESS_CACHE_NO_INTERNAL_STORE, SESS_CACHE_NO_INTERNAL)
42
43from OpenSSL.SSL import (
Jean-Paul Calderoned899af02013-03-19 22:10:37 -070044 Error, SysCallError, WantReadError, WantWriteError, ZeroReturnError)
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -050045from OpenSSL.SSL import (
Jean-Paul Calderoned899af02013-03-19 22:10:37 -070046 Context, ContextType, Session, Connection, ConnectionType, SSLeay_version)
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040047
Cory Benfieldba1820d2015-04-13 17:39:12 -040048from OpenSSL._util import lib as _lib
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
Hynek Schlawackf0e66852015-10-16 20:18:38 +020086from .util import WARNING_TYPE_EXPECTED, NON_ASCII, TestCase, b
87from .test_crypto import (
88 cleartextCertificatePEM, cleartextPrivateKeyPEM,
89 client_cert_pem, client_key_pem, server_cert_pem, server_key_pem,
90 root_cert_pem)
91
Hynek Schlawackde00dd52015-09-05 19:09:26 +020092
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -040093# openssl dhparam 128 -out dh-128.pem (note that 128 is a small number of bits
94# to use)
95dhparam = """\
96-----BEGIN DH PARAMETERS-----
97MBYCEQCobsg29c9WZP/54oAPcwiDAgEC
98-----END DH PARAMETERS-----
99"""
100
101
Hynek Schlawackb4f02402015-09-05 20:48:34 +0200102skip_if_py3 = pytest.mark.skipif(PY3, reason="Python 2 only")
Hynek Schlawackf8979a52015-09-05 21:25:25 +0200103skip_if_py26 = pytest.mark.skipif(
104 version_info[0:2] == (2, 6),
105 reason="Python 2.7 and later only"
106)
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200107
108
Jean-Paul Calderone05826732015-04-12 11:38:49 -0400109def join_bytes_or_unicode(prefix, suffix):
110 """
111 Join two path components of either ``bytes`` or ``unicode``.
112
113 The return type is the same as the type of ``prefix``.
114 """
115 # If the types are the same, nothing special is necessary.
116 if type(prefix) == type(suffix):
117 return join(prefix, suffix)
118
119 # Otherwise, coerce suffix to the type of prefix.
120 if isinstance(prefix, text_type):
121 return join(prefix, suffix.decode(getfilesystemencoding()))
122 else:
123 return join(prefix, suffix.encode(getfilesystemencoding()))
124
125
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400126def verify_cb(conn, cert, errnum, depth, ok):
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400127 return ok
128
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400129
Rick Deanb1ccd562009-07-09 23:52:39 -0500130def socket_pair():
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400131 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400132 Establish and return a pair of network sockets connected to each other.
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400133 """
134 # Connect a pair of sockets
Rick Deanb1ccd562009-07-09 23:52:39 -0500135 port = socket()
136 port.bind(('', 0))
137 port.listen(1)
138 client = socket()
139 client.setblocking(False)
Jean-Paul Calderonef23c5d92009-07-23 17:58:15 -0400140 client.connect_ex(("127.0.0.1", port.getsockname()[1]))
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400141 client.setblocking(True)
Rick Deanb1ccd562009-07-09 23:52:39 -0500142 server = port.accept()[0]
Rick Deanb1ccd562009-07-09 23:52:39 -0500143
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400144 # Let's pass some unencrypted data to make sure our socket connection is
145 # fine. Just one byte, so we don't have to worry about buffers getting
146 # filled up or fragmentation.
Jean-Paul Calderone9e4eeae2010-08-22 21:32:52 -0400147 server.send(b("x"))
148 assert client.recv(1024) == b("x")
149 client.send(b("y"))
150 assert server.recv(1024) == b("y")
Rick Deanb1ccd562009-07-09 23:52:39 -0500151
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -0400152 # Most of our callers want non-blocking sockets, make it easy for them.
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400153 server.setblocking(False)
154 client.setblocking(False)
Jim Shaver46f28912015-05-29 19:32:16 -0400155
Rick Deanb1ccd562009-07-09 23:52:39 -0500156 return (server, client)
157
158
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400159def handshake(client, server):
160 conns = [client, server]
161 while conns:
162 for conn in conns:
163 try:
164 conn.do_handshake()
165 except WantReadError:
166 pass
167 else:
168 conns.remove(conn)
169
170
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400171def _create_certificate_chain():
172 """
173 Construct and return a chain of certificates.
174
175 1. A new self-signed certificate authority certificate (cacert)
176 2. A new intermediate certificate signed by cacert (icert)
177 3. A new server certificate signed by icert (scert)
178 """
179 caext = X509Extension(b('basicConstraints'), False, b('CA:true'))
180
181 # Step 1
182 cakey = PKey()
183 cakey.generate_key(TYPE_RSA, 512)
184 cacert = X509()
185 cacert.get_subject().commonName = "Authority Certificate"
186 cacert.set_issuer(cacert.get_subject())
187 cacert.set_pubkey(cakey)
188 cacert.set_notBefore(b("20000101000000Z"))
189 cacert.set_notAfter(b("20200101000000Z"))
190 cacert.add_extensions([caext])
191 cacert.set_serial_number(0)
192 cacert.sign(cakey, "sha1")
193
194 # Step 2
195 ikey = PKey()
196 ikey.generate_key(TYPE_RSA, 512)
197 icert = X509()
198 icert.get_subject().commonName = "Intermediate Certificate"
199 icert.set_issuer(cacert.get_subject())
200 icert.set_pubkey(ikey)
201 icert.set_notBefore(b("20000101000000Z"))
202 icert.set_notAfter(b("20200101000000Z"))
203 icert.add_extensions([caext])
204 icert.set_serial_number(0)
205 icert.sign(cakey, "sha1")
206
207 # Step 3
208 skey = PKey()
209 skey.generate_key(TYPE_RSA, 512)
210 scert = X509()
211 scert.get_subject().commonName = "Server Certificate"
212 scert.set_issuer(icert.get_subject())
213 scert.set_pubkey(skey)
214 scert.set_notBefore(b("20000101000000Z"))
215 scert.set_notAfter(b("20200101000000Z"))
216 scert.add_extensions([
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200217 X509Extension(b('basicConstraints'), True, b('CA:false'))])
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400218 scert.set_serial_number(0)
219 scert.sign(ikey, "sha1")
220
221 return [(cakey, cacert), (ikey, icert), (skey, scert)]
222
223
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400224class _LoopbackMixin:
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400225 """
226 Helper mixin which defines methods for creating a connected socket pair and
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200227 for forcing two connected SSL sockets to talk to each other via memory
228 BIOs.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400229 """
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500230 def _loopbackClientFactory(self, socket):
231 client = Connection(Context(TLSv1_METHOD), socket)
232 client.set_connect_state()
233 return client
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400234
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500235 def _loopbackServerFactory(self, socket):
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400236 ctx = Context(TLSv1_METHOD)
237 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
238 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500239 server = Connection(ctx, socket)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400240 server.set_accept_state()
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500241 return server
242
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500243 def _loopback(self, serverFactory=None, clientFactory=None):
244 if serverFactory is None:
245 serverFactory = self._loopbackServerFactory
246 if clientFactory is None:
247 clientFactory = self._loopbackClientFactory
248
249 (server, client) = socket_pair()
250 server = serverFactory(server)
251 client = clientFactory(client)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400252
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400253 handshake(client, server)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400254
255 server.setblocking(True)
256 client.setblocking(True)
257 return server, client
258
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400259 def _interactInMemory(self, client_conn, server_conn):
260 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900261 Try to read application bytes from each of the two :py:obj:`Connection`
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400262 objects. Copy bytes back and forth between their send/receive buffers
263 for as long as there is anything to copy. When there is nothing more
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200264 to copy, return :py:obj:`None`. If one of them actually manages to
265 deliver some application bytes, return a two-tuple of the connection
266 from which the bytes were read and the bytes themselves.
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400267 """
268 wrote = True
269 while wrote:
270 # Loop until neither side has anything to say
271 wrote = False
272
273 # Copy stuff from each side's send buffer to the other side's
274 # receive buffer.
275 for (read, write) in [(client_conn, server_conn),
276 (server_conn, client_conn)]:
277
278 # Give the side a chance to generate some more bytes, or
279 # succeed.
280 try:
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400281 data = read.recv(2 ** 16)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400282 except WantReadError:
283 # It didn't succeed, so we'll hope it generated some
284 # output.
285 pass
286 else:
287 # It did succeed, so we'll stop now and let the caller deal
288 # with it.
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400289 return (read, data)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400290
291 while True:
292 # Keep copying as long as there's more stuff there.
293 try:
294 dirty = read.bio_read(4096)
295 except WantReadError:
296 # Okay, nothing more waiting to be sent. Stop
297 # processing this send buffer.
298 break
299 else:
300 # Keep track of the fact that someone generated some
301 # output.
302 wrote = True
303 write.bio_write(dirty)
304
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -0400305 def _handshakeInMemory(self, client_conn, server_conn):
Jean-Paul Calderoneb2b40782014-05-06 08:47:40 -0400306 """
307 Perform the TLS handshake between two :py:class:`Connection` instances
308 connected to each other via memory BIOs.
309 """
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -0400310 client_conn.set_connect_state()
311 server_conn.set_accept_state()
312
313 for conn in [client_conn, server_conn]:
314 try:
315 conn.do_handshake()
316 except WantReadError:
317 pass
318
319 self._interactInMemory(client_conn, server_conn)
320
321
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400322class VersionTests(TestCase):
323 """
324 Tests for version information exposed by
Jonathan Ballet648875f2011-07-16 14:14:58 +0900325 :py:obj:`OpenSSL.SSL.SSLeay_version` and
326 :py:obj:`OpenSSL.SSL.OPENSSL_VERSION_NUMBER`.
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400327 """
328 def test_OPENSSL_VERSION_NUMBER(self):
329 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900330 :py:obj:`OPENSSL_VERSION_NUMBER` is an integer with status in the low
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400331 byte and the patch, fix, minor, and major versions in the
332 nibbles above that.
333 """
334 self.assertTrue(isinstance(OPENSSL_VERSION_NUMBER, int))
335
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400336 def test_SSLeay_version(self):
337 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900338 :py:obj:`SSLeay_version` takes a version type indicator and returns
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400339 one of a number of version strings based on that indicator.
340 """
341 versions = {}
342 for t in [SSLEAY_VERSION, SSLEAY_CFLAGS, SSLEAY_BUILT_ON,
343 SSLEAY_PLATFORM, SSLEAY_DIR]:
344 version = SSLeay_version(t)
345 versions[version] = t
346 self.assertTrue(isinstance(version, bytes))
347 self.assertEqual(len(versions), 5)
348
349
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100350@pytest.fixture
351def context():
352 """
353 A simple TLS 1.0 context.
354 """
355 return Context(TLSv1_METHOD)
356
357
358class TestContext(object):
359 @pytest.mark.parametrize("cipher_string", [
360 b"hello world:AES128-SHA",
361 u"hello world:AES128-SHA",
362 ])
363 def test_set_cipher_list(self, context, cipher_string):
364 """
Hynek Schlawacka7a63af2016-03-11 12:05:26 +0100365 :meth:`Context.set_cipher_list` accepts both byte and unicode strings
366 for naming the ciphers which connections created with the context
367 object will be able to choose from.
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100368 """
369 context.set_cipher_list(cipher_string)
370 conn = Connection(context, None)
371
372 assert "AES128-SHA" in conn.get_cipher_list()
373
374 @pytest.mark.parametrize("cipher_list,error", [
375 (object(), TypeError),
376 ("imaginary-cipher", Error),
377 ])
378 def test_set_cipher_list_wrong_args(self, context, cipher_list, error):
379 """
380 :meth:`Context.set_cipher_list` raises :exc:`TypeError` when passed a
381 non-string argument and raises :exc:`OpenSSL.SSL.Error` when passed an
382 incorrect cipher list string.
383 """
384 with pytest.raises(error):
385 context.set_cipher_list(cipher_list)
386
387
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400388class ContextTests(TestCase, _LoopbackMixin):
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400389 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900390 Unit tests for :py:obj:`OpenSSL.SSL.Context`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400391 """
392 def test_method(self):
393 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200394 :py:obj:`Context` can be instantiated with one of
395 :py:obj:`SSLv2_METHOD`, :py:obj:`SSLv3_METHOD`,
396 :py:obj:`SSLv23_METHOD`, :py:obj:`TLSv1_METHOD`,
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400397 :py:obj:`TLSv1_1_METHOD`, or :py:obj:`TLSv1_2_METHOD`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400398 """
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400399 methods = [
400 SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD]
401 for meth in methods:
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400402 Context(meth)
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400403
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400404 maybe = [SSLv2_METHOD, TLSv1_1_METHOD, TLSv1_2_METHOD]
405 for meth in maybe:
406 try:
407 Context(meth)
408 except (Error, ValueError):
409 # Some versions of OpenSSL have SSLv2 / TLSv1.1 / TLSv1.2, some
410 # don't. Difficult to say in advance.
411 pass
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400412
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400413 self.assertRaises(TypeError, Context, "")
414 self.assertRaises(ValueError, Context, 10)
415
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200416 @skip_if_py3
417 def test_method_long(self):
418 """
419 On Python 2 :py:class:`Context` accepts values of type
420 :py:obj:`long` as well as :py:obj:`int`.
421 """
422 Context(long(TLSv1_METHOD))
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500423
Rick Deane15b1472009-07-09 15:53:42 -0500424 def test_type(self):
425 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200426 :py:obj:`Context` and :py:obj:`ContextType` refer to the same type
427 object and can be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -0500428 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400429 self.assertIdentical(Context, ContextType)
430 self.assertConsistentType(Context, 'Context', TLSv1_METHOD)
Rick Deane15b1472009-07-09 15:53:42 -0500431
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400432 def test_use_privatekey(self):
433 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200434 :py:obj:`Context.use_privatekey` takes an :py:obj:`OpenSSL.crypto.PKey`
435 instance.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400436 """
437 key = PKey()
438 key.generate_key(TYPE_RSA, 128)
439 ctx = Context(TLSv1_METHOD)
440 ctx.use_privatekey(key)
441 self.assertRaises(TypeError, ctx.use_privatekey, "")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400442
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800443 def test_use_privatekey_file_missing(self):
444 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200445 :py:obj:`Context.use_privatekey_file` raises
446 :py:obj:`OpenSSL.SSL.Error` when passed the name of a file which does
447 not exist.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800448 """
449 ctx = Context(TLSv1_METHOD)
450 self.assertRaises(Error, ctx.use_privatekey_file, self.mktemp())
451
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400452 def _use_privatekey_file_test(self, pemfile, filetype):
453 """
454 Verify that calling ``Context.use_privatekey_file`` with the given
455 arguments does not raise an exception.
456 """
457 key = PKey()
458 key.generate_key(TYPE_RSA, 128)
459
460 with open(pemfile, "wt") as pem:
461 pem.write(
462 dump_privatekey(FILETYPE_PEM, key).decode("ascii")
463 )
464
465 ctx = Context(TLSv1_METHOD)
466 ctx.use_privatekey_file(pemfile, filetype)
467
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400468 def test_use_privatekey_file_bytes(self):
469 """
470 A private key can be specified from a file by passing a ``bytes``
471 instance giving the file name to ``Context.use_privatekey_file``.
472 """
473 self._use_privatekey_file_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -0400474 self.mktemp() + NON_ASCII.encode(getfilesystemencoding()),
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400475 FILETYPE_PEM,
476 )
477
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400478 def test_use_privatekey_file_unicode(self):
479 """
480 A private key can be specified from a file by passing a ``unicode``
481 instance giving the file name to ``Context.use_privatekey_file``.
482 """
483 self._use_privatekey_file_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -0400484 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII,
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400485 FILETYPE_PEM,
486 )
487
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200488 @skip_if_py3
489 def test_use_privatekey_file_long(self):
490 """
491 On Python 2 :py:obj:`Context.use_privatekey_file` accepts a
492 filetype of type :py:obj:`long` as well as :py:obj:`int`.
493 """
494 self._use_privatekey_file_test(self.mktemp(), long(FILETYPE_PEM))
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500495
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800496 def test_use_certificate_wrong_args(self):
497 """
498 :py:obj:`Context.use_certificate_wrong_args` raises :py:obj:`TypeError`
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200499 when not passed exactly one :py:obj:`OpenSSL.crypto.X509` instance as
500 an argument.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800501 """
502 ctx = Context(TLSv1_METHOD)
503 self.assertRaises(TypeError, ctx.use_certificate)
504 self.assertRaises(TypeError, ctx.use_certificate, "hello, world")
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200505 self.assertRaises(
506 TypeError, ctx.use_certificate, X509(), "hello, world"
507 )
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800508
509 def test_use_certificate_uninitialized(self):
510 """
511 :py:obj:`Context.use_certificate` raises :py:obj:`OpenSSL.SSL.Error`
512 when passed a :py:obj:`OpenSSL.crypto.X509` instance which has not been
513 initialized (ie, which does not actually have any certificate data).
514 """
515 ctx = Context(TLSv1_METHOD)
516 self.assertRaises(Error, ctx.use_certificate, X509())
517
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800518 def test_use_certificate(self):
519 """
520 :py:obj:`Context.use_certificate` sets the certificate which will be
521 used to identify connections created using the context.
522 """
523 # TODO
524 # Hard to assert anything. But we could set a privatekey then ask
525 # OpenSSL if the cert and key agree using check_privatekey. Then as
526 # long as check_privatekey works right we're good...
527 ctx = Context(TLSv1_METHOD)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200528 ctx.use_certificate(
529 load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
530 )
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800531
532 def test_use_certificate_file_wrong_args(self):
533 """
534 :py:obj:`Context.use_certificate_file` raises :py:obj:`TypeError` if
535 called with zero arguments or more than two arguments, or if the first
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200536 argument is not a byte string or the second argumnent is not an
537 integer.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800538 """
539 ctx = Context(TLSv1_METHOD)
540 self.assertRaises(TypeError, ctx.use_certificate_file)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200541 self.assertRaises(TypeError, ctx.use_certificate_file, b"somefile",
542 object())
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800543 self.assertRaises(
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200544 TypeError, ctx.use_certificate_file, b"somefile", FILETYPE_PEM,
545 object())
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800546 self.assertRaises(
547 TypeError, ctx.use_certificate_file, object(), FILETYPE_PEM)
548 self.assertRaises(
549 TypeError, ctx.use_certificate_file, b"somefile", object())
550
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800551 def test_use_certificate_file_missing(self):
552 """
553 :py:obj:`Context.use_certificate_file` raises
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200554 `:py:obj:`OpenSSL.SSL.Error` if passed the name of a file which does
555 not exist.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800556 """
557 ctx = Context(TLSv1_METHOD)
558 self.assertRaises(Error, ctx.use_certificate_file, self.mktemp())
559
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400560 def _use_certificate_file_test(self, certificate_file):
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800561 """
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400562 Verify that calling ``Context.use_certificate_file`` with the given
563 filename doesn't raise an exception.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800564 """
565 # TODO
566 # Hard to assert anything. But we could set a privatekey then ask
567 # OpenSSL if the cert and key agree using check_privatekey. Then as
568 # long as check_privatekey works right we're good...
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400569 with open(certificate_file, "wb") as pem_file:
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800570 pem_file.write(cleartextCertificatePEM)
571
572 ctx = Context(TLSv1_METHOD)
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400573 ctx.use_certificate_file(certificate_file)
574
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400575 def test_use_certificate_file_bytes(self):
576 """
577 :py:obj:`Context.use_certificate_file` sets the certificate (given as a
578 ``bytes`` filename) which will be used to identify connections created
579 using the context.
580 """
Hynek Schlawack4813c0e2015-04-16 13:38:01 -0400581 filename = self.mktemp() + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400582 self._use_certificate_file_test(filename)
583
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400584 def test_use_certificate_file_unicode(self):
585 """
586 :py:obj:`Context.use_certificate_file` sets the certificate (given as a
587 ``bytes`` filename) which will be used to identify connections created
588 using the context.
589 """
Hynek Schlawack4813c0e2015-04-16 13:38:01 -0400590 filename = self.mktemp().decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400591 self._use_certificate_file_test(filename)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800592
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200593 @skip_if_py3
594 def test_use_certificate_file_long(self):
595 """
596 On Python 2 :py:obj:`Context.use_certificate_file` accepts a
597 filetype of type :py:obj:`long` as well as :py:obj:`int`.
598 """
599 pem_filename = self.mktemp()
600 with open(pem_filename, "wb") as pem_file:
601 pem_file.write(cleartextCertificatePEM)
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500602
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200603 ctx = Context(TLSv1_METHOD)
604 ctx.use_certificate_file(pem_filename, long(FILETYPE_PEM))
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500605
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500606 def test_check_privatekey_valid(self):
607 """
608 :py:obj:`Context.check_privatekey` returns :py:obj:`None` if the
609 :py:obj:`Context` instance has been configured to use a matched key and
610 certificate pair.
611 """
612 key = load_privatekey(FILETYPE_PEM, client_key_pem)
613 cert = load_certificate(FILETYPE_PEM, client_cert_pem)
614 context = Context(TLSv1_METHOD)
615 context.use_privatekey(key)
616 context.use_certificate(cert)
617 self.assertIs(None, context.check_privatekey())
618
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500619 def test_check_privatekey_invalid(self):
620 """
621 :py:obj:`Context.check_privatekey` raises :py:obj:`Error` if the
622 :py:obj:`Context` instance has been configured to use a key and
623 certificate pair which don't relate to each other.
624 """
625 key = load_privatekey(FILETYPE_PEM, client_key_pem)
626 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
627 context = Context(TLSv1_METHOD)
628 context.use_privatekey(key)
629 context.use_certificate(cert)
630 self.assertRaises(Error, context.check_privatekey)
631
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500632 def test_check_privatekey_wrong_args(self):
633 """
634 :py:obj:`Context.check_privatekey` raises :py:obj:`TypeError` if called
635 with other than no arguments.
636 """
637 context = Context(TLSv1_METHOD)
638 self.assertRaises(TypeError, context.check_privatekey, object())
639
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400640 def test_set_app_data_wrong_args(self):
641 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200642 :py:obj:`Context.set_app_data` raises :py:obj:`TypeError` if called
643 with other than one argument.
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400644 """
645 context = Context(TLSv1_METHOD)
646 self.assertRaises(TypeError, context.set_app_data)
647 self.assertRaises(TypeError, context.set_app_data, None, None)
648
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400649 def test_get_app_data_wrong_args(self):
650 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200651 :py:obj:`Context.get_app_data` raises :py:obj:`TypeError` if called
652 with any arguments.
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400653 """
654 context = Context(TLSv1_METHOD)
655 self.assertRaises(TypeError, context.get_app_data, None)
656
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400657 def test_app_data(self):
658 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200659 :py:obj:`Context.set_app_data` stores an object for later retrieval
660 using :py:obj:`Context.get_app_data`.
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400661 """
662 app_data = object()
663 context = Context(TLSv1_METHOD)
664 context.set_app_data(app_data)
665 self.assertIdentical(context.get_app_data(), app_data)
666
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400667 def test_set_options_wrong_args(self):
668 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200669 :py:obj:`Context.set_options` raises :py:obj:`TypeError` if called with
670 the wrong number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400671 """
672 context = Context(TLSv1_METHOD)
673 self.assertRaises(TypeError, context.set_options)
674 self.assertRaises(TypeError, context.set_options, None)
675 self.assertRaises(TypeError, context.set_options, 1, None)
676
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500677 def test_set_options(self):
678 """
679 :py:obj:`Context.set_options` returns the new options value.
680 """
681 context = Context(TLSv1_METHOD)
682 options = context.set_options(OP_NO_SSLv2)
683 self.assertTrue(OP_NO_SSLv2 & options)
684
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200685 @skip_if_py3
686 def test_set_options_long(self):
687 """
688 On Python 2 :py:obj:`Context.set_options` accepts values of type
689 :py:obj:`long` as well as :py:obj:`int`.
690 """
691 context = Context(TLSv1_METHOD)
692 options = context.set_options(long(OP_NO_SSLv2))
693 self.assertTrue(OP_NO_SSLv2 & options)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500694
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300695 def test_set_mode_wrong_args(self):
696 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200697 :py:obj:`Context.set`mode} raises :py:obj:`TypeError` if called with
698 the wrong number of arguments or a non-:py:obj:`int` argument.
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300699 """
700 context = Context(TLSv1_METHOD)
701 self.assertRaises(TypeError, context.set_mode)
702 self.assertRaises(TypeError, context.set_mode, None)
703 self.assertRaises(TypeError, context.set_mode, 1, None)
704
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400705 if MODE_RELEASE_BUFFERS is not None:
706 def test_set_mode(self):
707 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200708 :py:obj:`Context.set_mode` accepts a mode bitvector and returns the
709 newly set mode.
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400710 """
711 context = Context(TLSv1_METHOD)
712 self.assertTrue(
713 MODE_RELEASE_BUFFERS & context.set_mode(MODE_RELEASE_BUFFERS))
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500714
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200715 @skip_if_py3
716 def test_set_mode_long(self):
717 """
718 On Python 2 :py:obj:`Context.set_mode` accepts values of type
719 :py:obj:`long` as well as :py:obj:`int`.
720 """
721 context = Context(TLSv1_METHOD)
722 mode = context.set_mode(long(MODE_RELEASE_BUFFERS))
723 self.assertTrue(MODE_RELEASE_BUFFERS & mode)
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400724 else:
725 "MODE_RELEASE_BUFFERS unavailable - OpenSSL version may be too old"
726
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400727 def test_set_timeout_wrong_args(self):
728 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200729 :py:obj:`Context.set_timeout` raises :py:obj:`TypeError` if called with
730 the wrong number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400731 """
732 context = Context(TLSv1_METHOD)
733 self.assertRaises(TypeError, context.set_timeout)
734 self.assertRaises(TypeError, context.set_timeout, None)
735 self.assertRaises(TypeError, context.set_timeout, 1, None)
736
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400737 def test_get_timeout_wrong_args(self):
738 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200739 :py:obj:`Context.get_timeout` raises :py:obj:`TypeError` if called with
740 any arguments.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400741 """
742 context = Context(TLSv1_METHOD)
743 self.assertRaises(TypeError, context.get_timeout, None)
744
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400745 def test_timeout(self):
746 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200747 :py:obj:`Context.set_timeout` sets the session timeout for all
748 connections created using the context object.
749 :py:obj:`Context.get_timeout` retrieves this value.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400750 """
751 context = Context(TLSv1_METHOD)
752 context.set_timeout(1234)
753 self.assertEquals(context.get_timeout(), 1234)
754
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200755 @skip_if_py3
756 def test_timeout_long(self):
757 """
758 On Python 2 :py:obj:`Context.set_timeout` accepts values of type
759 `long` as well as int.
760 """
761 context = Context(TLSv1_METHOD)
762 context.set_timeout(long(1234))
763 self.assertEquals(context.get_timeout(), 1234)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500764
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400765 def test_set_verify_depth_wrong_args(self):
766 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200767 :py:obj:`Context.set_verify_depth` raises :py:obj:`TypeError` if called
768 with the wrong number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400769 """
770 context = Context(TLSv1_METHOD)
771 self.assertRaises(TypeError, context.set_verify_depth)
772 self.assertRaises(TypeError, context.set_verify_depth, None)
773 self.assertRaises(TypeError, context.set_verify_depth, 1, None)
774
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400775 def test_get_verify_depth_wrong_args(self):
776 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200777 :py:obj:`Context.get_verify_depth` raises :py:obj:`TypeError` if called
778 with any arguments.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400779 """
780 context = Context(TLSv1_METHOD)
781 self.assertRaises(TypeError, context.get_verify_depth, None)
782
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400783 def test_verify_depth(self):
784 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200785 :py:obj:`Context.set_verify_depth` sets the number of certificates in
786 a chain to follow before giving up. The value can be retrieved with
Jonathan Ballet648875f2011-07-16 14:14:58 +0900787 :py:obj:`Context.get_verify_depth`.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400788 """
789 context = Context(TLSv1_METHOD)
790 context.set_verify_depth(11)
791 self.assertEquals(context.get_verify_depth(), 11)
792
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200793 @skip_if_py3
794 def test_verify_depth_long(self):
795 """
796 On Python 2 :py:obj:`Context.set_verify_depth` accepts values of
797 type `long` as well as int.
798 """
799 context = Context(TLSv1_METHOD)
800 context.set_verify_depth(long(11))
801 self.assertEquals(context.get_verify_depth(), 11)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500802
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400803 def _write_encrypted_pem(self, passphrase):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400804 """
805 Write a new private key out to a new file, encrypted using the given
806 passphrase. Return the path to the new file.
807 """
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400808 key = PKey()
809 key.generate_key(TYPE_RSA, 128)
810 pemFile = self.mktemp()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400811 fObj = open(pemFile, 'w')
812 pem = dump_privatekey(FILETYPE_PEM, key, "blowfish", passphrase)
813 fObj.write(pem.decode('ascii'))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400814 fObj.close()
815 return pemFile
816
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400817 def test_set_passwd_cb_wrong_args(self):
818 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200819 :py:obj:`Context.set_passwd_cb` raises :py:obj:`TypeError` if called
820 with the wrong arguments or with a non-callable first argument.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400821 """
822 context = Context(TLSv1_METHOD)
823 self.assertRaises(TypeError, context.set_passwd_cb)
824 self.assertRaises(TypeError, context.set_passwd_cb, None)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200825 self.assertRaises(
826 TypeError, context.set_passwd_cb, lambda: None, None, None
Hynek Schlawack2c013a92015-09-05 19:33:05 +0200827 ) # pragma: nocover
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400828
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400829 def test_set_passwd_cb(self):
830 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200831 :py:obj:`Context.set_passwd_cb` accepts a callable which will be
832 invoked when a private key is loaded from an encrypted PEM.
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400833 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400834 passphrase = b("foobar")
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400835 pemFile = self._write_encrypted_pem(passphrase)
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400836 calledWith = []
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200837
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400838 def passphraseCallback(maxlen, verify, extra):
839 calledWith.append((maxlen, verify, extra))
840 return passphrase
841 context = Context(TLSv1_METHOD)
842 context.set_passwd_cb(passphraseCallback)
843 context.use_privatekey_file(pemFile)
844 self.assertTrue(len(calledWith), 1)
845 self.assertTrue(isinstance(calledWith[0][0], int))
846 self.assertTrue(isinstance(calledWith[0][1], int))
847 self.assertEqual(calledWith[0][2], None)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400848
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400849 def test_passwd_callback_exception(self):
850 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200851 :py:obj:`Context.use_privatekey_file` propagates any exception raised
852 by the passphrase callback.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400853 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400854 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200855
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400856 def passphraseCallback(maxlen, verify, extra):
857 raise RuntimeError("Sorry, I am a fail.")
858
859 context = Context(TLSv1_METHOD)
860 context.set_passwd_cb(passphraseCallback)
861 self.assertRaises(RuntimeError, context.use_privatekey_file, pemFile)
862
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400863 def test_passwd_callback_false(self):
864 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200865 :py:obj:`Context.use_privatekey_file` raises
866 :py:obj:`OpenSSL.SSL.Error` if the passphrase callback returns a false
867 value.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400868 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400869 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200870
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400871 def passphraseCallback(maxlen, verify, extra):
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500872 return b""
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400873
874 context = Context(TLSv1_METHOD)
875 context.set_passwd_cb(passphraseCallback)
876 self.assertRaises(Error, context.use_privatekey_file, pemFile)
877
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400878 def test_passwd_callback_non_string(self):
879 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200880 :py:obj:`Context.use_privatekey_file` raises
881 :py:obj:`OpenSSL.SSL.Error` if the passphrase callback returns a true
882 non-string value.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400883 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400884 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200885
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400886 def passphraseCallback(maxlen, verify, extra):
887 return 10
888
889 context = Context(TLSv1_METHOD)
890 context.set_passwd_cb(passphraseCallback)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800891 self.assertRaises(ValueError, context.use_privatekey_file, pemFile)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400892
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400893 def test_passwd_callback_too_long(self):
894 """
895 If the passphrase returned by the passphrase callback returns a string
896 longer than the indicated maximum length, it is truncated.
897 """
898 # A priori knowledge!
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400899 passphrase = b("x") * 1024
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400900 pemFile = self._write_encrypted_pem(passphrase)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200901
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400902 def passphraseCallback(maxlen, verify, extra):
903 assert maxlen == 1024
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400904 return passphrase + b("y")
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400905
906 context = Context(TLSv1_METHOD)
907 context.set_passwd_cb(passphraseCallback)
908 # This shall succeed because the truncated result is the correct
909 # passphrase.
910 context.use_privatekey_file(pemFile)
911
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400912 def test_set_info_callback(self):
913 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200914 :py:obj:`Context.set_info_callback` accepts a callable which will be
915 invoked when certain information about an SSL connection is available.
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400916 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500917 (server, client) = socket_pair()
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400918
919 clientSSL = Connection(Context(TLSv1_METHOD), client)
920 clientSSL.set_connect_state()
921
922 called = []
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200923
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400924 def info(conn, where, ret):
925 called.append((conn, where, ret))
926 context = Context(TLSv1_METHOD)
927 context.set_info_callback(info)
928 context.use_certificate(
929 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
930 context.use_privatekey(
931 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
932
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400933 serverSSL = Connection(context, server)
934 serverSSL.set_accept_state()
935
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -0500936 handshake(clientSSL, serverSSL)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400937
Jean-Paul Calderone3835e522014-02-02 11:12:30 -0500938 # The callback must always be called with a Connection instance as the
939 # first argument. It would probably be better to split this into
940 # separate tests for client and server side info callbacks so we could
941 # assert it is called with the right Connection instance. It would
942 # also be good to assert *something* about `where` and `ret`.
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -0500943 notConnections = [
944 conn for (conn, where, ret) in called
945 if not isinstance(conn, Connection)]
946 self.assertEqual(
947 [], notConnections,
948 "Some info callback arguments were not Connection instaces.")
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400949
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400950 def _load_verify_locations_test(self, *args):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400951 """
952 Create a client context which will verify the peer certificate and call
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -0400953 its :py:obj:`load_verify_locations` method with the given arguments.
954 Then connect it to a server and ensure that the handshake succeeds.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400955 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500956 (server, client) = socket_pair()
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400957
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400958 clientContext = Context(TLSv1_METHOD)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400959 clientContext.load_verify_locations(*args)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400960 # Require that the server certificate verify properly or the
961 # connection will fail.
962 clientContext.set_verify(
963 VERIFY_PEER,
964 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
965
966 clientSSL = Connection(clientContext, client)
967 clientSSL.set_connect_state()
968
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400969 serverContext = Context(TLSv1_METHOD)
970 serverContext.use_certificate(
971 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
972 serverContext.use_privatekey(
973 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
974
975 serverSSL = Connection(serverContext, server)
976 serverSSL.set_accept_state()
977
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400978 # Without load_verify_locations above, the handshake
979 # will fail:
980 # Error: [('SSL routines', 'SSL3_GET_SERVER_CERTIFICATE',
981 # 'certificate verify failed')]
982 handshake(clientSSL, serverSSL)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400983
984 cert = clientSSL.get_peer_certificate()
Jean-Paul Calderone20131f52009-04-01 12:05:45 -0400985 self.assertEqual(cert.get_subject().CN, 'Testing Root CA')
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400986
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400987 def _load_verify_cafile(self, cafile):
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400988 """
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400989 Verify that if path to a file containing a certificate is passed to
990 ``Context.load_verify_locations`` for the ``cafile`` parameter, that
991 certificate is used as a trust root for the purposes of verifying
992 connections created using that ``Context``.
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400993 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400994 fObj = open(cafile, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400995 fObj.write(cleartextCertificatePEM.decode('ascii'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400996 fObj.close()
997
998 self._load_verify_locations_test(cafile)
999
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001000 def test_load_verify_bytes_cafile(self):
1001 """
1002 :py:obj:`Context.load_verify_locations` accepts a file name as a
1003 ``bytes`` instance and uses the certificates within for verification
1004 purposes.
1005 """
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001006 cafile = self.mktemp() + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001007 self._load_verify_cafile(cafile)
1008
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001009 def test_load_verify_unicode_cafile(self):
1010 """
1011 :py:obj:`Context.load_verify_locations` accepts a file name as a
1012 ``unicode`` instance and uses the certificates within for verification
1013 purposes.
1014 """
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001015 self._load_verify_cafile(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001016 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001017 )
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001018
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -04001019 def test_load_verify_invalid_file(self):
1020 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001021 :py:obj:`Context.load_verify_locations` raises :py:obj:`Error` when
1022 passed a non-existent cafile.
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -04001023 """
1024 clientContext = Context(TLSv1_METHOD)
1025 self.assertRaises(
1026 Error, clientContext.load_verify_locations, self.mktemp())
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001027
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001028 def _load_verify_directory_locations_capath(self, capath):
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001029 """
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001030 Verify that if path to a directory containing certificate files is
1031 passed to ``Context.load_verify_locations`` for the ``capath``
1032 parameter, those certificates are used as trust roots for the purposes
1033 of verifying connections created using that ``Context``.
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001034 """
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001035 makedirs(capath)
Jean-Paul Calderone24dfb332011-05-04 18:10:26 -04001036 # Hash values computed manually with c_rehash to avoid depending on
1037 # c_rehash in the test suite. One is from OpenSSL 0.9.8, the other
1038 # from OpenSSL 1.0.0.
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001039 for name in [b'c7adac82.0', b'c3705638.0']:
Jean-Paul Calderone05826732015-04-12 11:38:49 -04001040 cafile = join_bytes_or_unicode(capath, name)
1041 with open(cafile, 'w') as fObj:
1042 fObj.write(cleartextCertificatePEM.decode('ascii'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001043
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001044 self._load_verify_locations_test(None, capath)
1045
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001046 def test_load_verify_directory_bytes_capath(self):
1047 """
1048 :py:obj:`Context.load_verify_locations` accepts a directory name as a
1049 ``bytes`` instance and uses the certificates within for verification
1050 purposes.
1051 """
1052 self._load_verify_directory_locations_capath(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001053 self.mktemp() + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001054 )
1055
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001056 def test_load_verify_directory_unicode_capath(self):
1057 """
1058 :py:obj:`Context.load_verify_locations` accepts a directory name as a
1059 ``unicode`` instance and uses the certificates within for verification
1060 purposes.
1061 """
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001062 self._load_verify_directory_locations_capath(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001063 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001064 )
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001065
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001066 def test_load_verify_locations_wrong_args(self):
1067 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001068 :py:obj:`Context.load_verify_locations` raises :py:obj:`TypeError` if
1069 called with the wrong number of arguments or with non-:py:obj:`str`
1070 arguments.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001071 """
1072 context = Context(TLSv1_METHOD)
1073 self.assertRaises(TypeError, context.load_verify_locations)
1074 self.assertRaises(TypeError, context.load_verify_locations, object())
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001075 self.assertRaises(
1076 TypeError, context.load_verify_locations, object(), object()
1077 )
1078 self.assertRaises(
1079 TypeError, context.load_verify_locations, None, None, None
1080 )
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001081
Hynek Schlawack734d3022015-09-05 19:19:32 +02001082 @pytest.mark.skipif(
1083 platform == "win32",
1084 reason="set_default_verify_paths appears not to work on Windows. "
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -04001085 "See LP#404343 and LP#404344."
Hynek Schlawack734d3022015-09-05 19:19:32 +02001086 )
1087 def test_set_default_verify_paths(self):
1088 """
1089 :py:obj:`Context.set_default_verify_paths` causes the
1090 platform-specific CA certificate locations to be used for
1091 verification purposes.
1092 """
1093 # Testing this requires a server with a certificate signed by one
1094 # of the CAs in the platform CA location. Getting one of those
1095 # costs money. Fortunately (or unfortunately, depending on your
1096 # perspective), it's easy to think of a public server on the
1097 # internet which has such a certificate. Connecting to the network
1098 # in a unit test is bad, but it's the only way I can think of to
1099 # really test this. -exarkun
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001100
Hynek Schlawack734d3022015-09-05 19:19:32 +02001101 # Arg, verisign.com doesn't speak anything newer than TLS 1.0
Hynek Schlawackbf887932015-10-21 17:13:47 +02001102 context = Context(SSLv23_METHOD)
Hynek Schlawack734d3022015-09-05 19:19:32 +02001103 context.set_default_verify_paths()
1104 context.set_verify(
1105 VERIFY_PEER,
1106 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001107
Hynek Schlawack734d3022015-09-05 19:19:32 +02001108 client = socket()
Hynek Schlawackbf887932015-10-21 17:13:47 +02001109 client.connect(("encrypted.google.com", 443))
Hynek Schlawack734d3022015-09-05 19:19:32 +02001110 clientSSL = Connection(context, client)
1111 clientSSL.set_connect_state()
1112 clientSSL.do_handshake()
1113 clientSSL.send(b"GET / HTTP/1.0\r\n\r\n")
1114 self.assertTrue(clientSSL.recv(1024))
Jean-Paul Calderone9eadb962008-09-07 21:20:44 -04001115
1116 def test_set_default_verify_paths_signature(self):
1117 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001118 :py:obj:`Context.set_default_verify_paths` takes no arguments and
1119 raises :py:obj:`TypeError` if given any.
Jean-Paul Calderone9eadb962008-09-07 21:20:44 -04001120 """
1121 context = Context(TLSv1_METHOD)
1122 self.assertRaises(TypeError, context.set_default_verify_paths, None)
1123 self.assertRaises(TypeError, context.set_default_verify_paths, 1)
1124 self.assertRaises(TypeError, context.set_default_verify_paths, "")
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05001125
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001126 def test_add_extra_chain_cert_invalid_cert(self):
1127 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001128 :py:obj:`Context.add_extra_chain_cert` raises :py:obj:`TypeError` if
1129 called with other than one argument or if called with an object which
1130 is not an instance of :py:obj:`X509`.
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001131 """
1132 context = Context(TLSv1_METHOD)
1133 self.assertRaises(TypeError, context.add_extra_chain_cert)
1134 self.assertRaises(TypeError, context.add_extra_chain_cert, object())
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001135 self.assertRaises(
1136 TypeError, context.add_extra_chain_cert, object(), object()
1137 )
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001138
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001139 def _handshake_test(self, serverContext, clientContext):
1140 """
1141 Verify that a client and server created with the given contexts can
1142 successfully handshake and communicate.
1143 """
1144 serverSocket, clientSocket = socket_pair()
1145
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001146 server = Connection(serverContext, serverSocket)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001147 server.set_accept_state()
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001148
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001149 client = Connection(clientContext, clientSocket)
1150 client.set_connect_state()
1151
1152 # Make them talk to each other.
1153 # self._interactInMemory(client, server)
1154 for i in range(3):
1155 for s in [client, server]:
1156 try:
1157 s.do_handshake()
1158 except WantReadError:
1159 pass
1160
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001161 def test_set_verify_callback_connection_argument(self):
1162 """
1163 The first argument passed to the verify callback is the
1164 :py:class:`Connection` instance for which verification is taking place.
1165 """
1166 serverContext = Context(TLSv1_METHOD)
1167 serverContext.use_privatekey(
1168 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1169 serverContext.use_certificate(
1170 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1171 serverConnection = Connection(serverContext, None)
1172
1173 class VerifyCallback(object):
1174 def callback(self, connection, *args):
1175 self.connection = connection
1176 return 1
1177
1178 verify = VerifyCallback()
1179 clientContext = Context(TLSv1_METHOD)
1180 clientContext.set_verify(VERIFY_PEER, verify.callback)
1181 clientConnection = Connection(clientContext, None)
1182 clientConnection.set_connect_state()
1183
1184 self._handshakeInMemory(clientConnection, serverConnection)
1185
1186 self.assertIdentical(verify.connection, clientConnection)
1187
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001188 def test_set_verify_callback_exception(self):
1189 """
1190 If the verify callback passed to :py:obj:`Context.set_verify` raises an
1191 exception, verification fails and the exception is propagated to the
1192 caller of :py:obj:`Connection.do_handshake`.
1193 """
1194 serverContext = Context(TLSv1_METHOD)
1195 serverContext.use_privatekey(
1196 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1197 serverContext.use_certificate(
1198 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1199
1200 clientContext = Context(TLSv1_METHOD)
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001201
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001202 def verify_callback(*args):
1203 raise Exception("silly verify failure")
1204 clientContext.set_verify(VERIFY_PEER, verify_callback)
1205
1206 exc = self.assertRaises(
1207 Exception, self._handshake_test, serverContext, clientContext)
1208 self.assertEqual("silly verify failure", str(exc))
1209
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001210 def test_add_extra_chain_cert(self):
1211 """
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001212 :py:obj:`Context.add_extra_chain_cert` accepts an :py:obj:`X509`
1213 instance to add to the certificate chain.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001214
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001215 See :py:obj:`_create_certificate_chain` for the details of the
1216 certificate chain tested.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001217
1218 The chain is tested by starting a server with scert and connecting
1219 to it with a client which trusts cacert and requires verification to
1220 succeed.
1221 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001222 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001223 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1224
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001225 # Dump the CA certificate to a file because that's the only way to load
1226 # it as a trusted CA in the client context.
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001227 for cert, name in [(cacert, 'ca.pem'),
1228 (icert, 'i.pem'),
1229 (scert, 's.pem')]:
Hynek Schlawacke90680f2015-04-16 15:09:27 -04001230 with open(join(self.tmpdir, name), 'w') as f:
1231 f.write(dump_certificate(FILETYPE_PEM, cert).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001232
Hynek Schlawack1902c012015-04-16 15:06:41 -04001233 for key, name in [(cakey, 'ca.key'),
1234 (ikey, 'i.key'),
1235 (skey, 's.key')]:
Hynek Schlawacke90680f2015-04-16 15:09:27 -04001236 with open(join(self.tmpdir, name), 'w') as f:
1237 f.write(dump_privatekey(FILETYPE_PEM, key).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001238
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001239 # Create the server context
1240 serverContext = Context(TLSv1_METHOD)
1241 serverContext.use_privatekey(skey)
1242 serverContext.use_certificate(scert)
Jean-Paul Calderone16cf03d2010-09-08 18:53:39 -04001243 # The client already has cacert, we only need to give them icert.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001244 serverContext.add_extra_chain_cert(icert)
1245
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001246 # Create the client
1247 clientContext = Context(TLSv1_METHOD)
1248 clientContext.set_verify(
1249 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001250 clientContext.load_verify_locations(join(self.tmpdir, "ca.pem"))
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001251
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001252 # Try it out.
1253 self._handshake_test(serverContext, clientContext)
1254
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001255 def _use_certificate_chain_file_test(self, certdir):
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001256 """
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001257 Verify that :py:obj:`Context.use_certificate_chain_file` reads a
1258 certificate chain from a specified file.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001259
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001260 The chain is tested by starting a server with scert and connecting to
1261 it with a client which trusts cacert and requires verification to
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001262 succeed.
1263 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001264 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001265 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1266
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001267 makedirs(certdir)
1268
Jean-Paul Calderone05826732015-04-12 11:38:49 -04001269 chainFile = join_bytes_or_unicode(certdir, "chain.pem")
1270 caFile = join_bytes_or_unicode(certdir, "ca.pem")
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001271
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001272 # Write out the chain file.
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001273 with open(chainFile, 'wb') as fObj:
1274 # Most specific to least general.
1275 fObj.write(dump_certificate(FILETYPE_PEM, scert))
1276 fObj.write(dump_certificate(FILETYPE_PEM, icert))
1277 fObj.write(dump_certificate(FILETYPE_PEM, cacert))
1278
1279 with open(caFile, 'w') as fObj:
1280 fObj.write(dump_certificate(FILETYPE_PEM, cacert).decode('ascii'))
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001281
1282 serverContext = Context(TLSv1_METHOD)
1283 serverContext.use_certificate_chain_file(chainFile)
1284 serverContext.use_privatekey(skey)
1285
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001286 clientContext = Context(TLSv1_METHOD)
1287 clientContext.set_verify(
1288 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001289 clientContext.load_verify_locations(caFile)
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001290
1291 self._handshake_test(serverContext, clientContext)
1292
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001293 def test_use_certificate_chain_file_bytes(self):
1294 """
1295 ``Context.use_certificate_chain_file`` accepts the name of a file (as
1296 an instance of ``bytes``) to specify additional certificates to use to
1297 construct and verify a trust chain.
1298 """
1299 self._use_certificate_chain_file_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001300 self.mktemp() + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001301 )
1302
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001303 def test_use_certificate_chain_file_unicode(self):
1304 """
1305 ``Context.use_certificate_chain_file`` accepts the name of a file (as
1306 an instance of ``unicode``) to specify additional certificates to use
1307 to construct and verify a trust chain.
1308 """
1309 self._use_certificate_chain_file_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001310 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001311 )
1312
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001313 def test_use_certificate_chain_file_wrong_args(self):
1314 """
1315 :py:obj:`Context.use_certificate_chain_file` raises :py:obj:`TypeError`
1316 if passed zero or more than one argument or when passed a non-byte
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001317 string single argument. It also raises :py:obj:`OpenSSL.SSL.Error`
1318 when passed a bad chain file name (for example, the name of a file
1319 which does not exist).
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001320 """
1321 context = Context(TLSv1_METHOD)
1322 self.assertRaises(TypeError, context.use_certificate_chain_file)
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001323 self.assertRaises(
1324 TypeError, context.use_certificate_chain_file, object()
1325 )
1326 self.assertRaises(
1327 TypeError, context.use_certificate_chain_file, b"foo", object()
1328 )
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001329
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001330 self.assertRaises(
1331 Error, context.use_certificate_chain_file, self.mktemp()
1332 )
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001333
Jean-Paul Calderonee0d79362010-08-03 18:46:46 -04001334 # XXX load_client_ca
1335 # XXX set_session_id
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001336
1337 def test_get_verify_mode_wrong_args(self):
1338 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001339 :py:obj:`Context.get_verify_mode` raises :py:obj:`TypeError` if called
1340 with any arguments.
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001341 """
1342 context = Context(TLSv1_METHOD)
1343 self.assertRaises(TypeError, context.get_verify_mode, None)
1344
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001345 def test_set_verify_mode(self):
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001346 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001347 :py:obj:`Context.get_verify_mode` returns the verify mode flags
1348 previously passed to :py:obj:`Context.set_verify`.
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001349 """
1350 context = Context(TLSv1_METHOD)
1351 self.assertEquals(context.get_verify_mode(), 0)
1352 context.set_verify(
1353 VERIFY_PEER | VERIFY_CLIENT_ONCE, lambda *args: None)
1354 self.assertEquals(
1355 context.get_verify_mode(), VERIFY_PEER | VERIFY_CLIENT_ONCE)
1356
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001357 @skip_if_py3
1358 def test_set_verify_mode_long(self):
1359 """
1360 On Python 2 :py:obj:`Context.set_verify_mode` accepts values of
1361 type :py:obj:`long` as well as :py:obj:`int`.
1362 """
1363 context = Context(TLSv1_METHOD)
1364 self.assertEquals(context.get_verify_mode(), 0)
1365 context.set_verify(
Hynek Schlawackb4ceed32015-09-05 20:55:19 +02001366 long(VERIFY_PEER | VERIFY_CLIENT_ONCE), lambda *args: None
1367 ) # pragma: nocover
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001368 self.assertEquals(
1369 context.get_verify_mode(), VERIFY_PEER | VERIFY_CLIENT_ONCE)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001370
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001371 def test_load_tmp_dh_wrong_args(self):
1372 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001373 :py:obj:`Context.load_tmp_dh` raises :py:obj:`TypeError` if called with
1374 the wrong number of arguments or with a non-:py:obj:`str` argument.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001375 """
1376 context = Context(TLSv1_METHOD)
1377 self.assertRaises(TypeError, context.load_tmp_dh)
1378 self.assertRaises(TypeError, context.load_tmp_dh, "foo", None)
1379 self.assertRaises(TypeError, context.load_tmp_dh, object())
1380
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001381 def test_load_tmp_dh_missing_file(self):
1382 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001383 :py:obj:`Context.load_tmp_dh` raises :py:obj:`OpenSSL.SSL.Error` if the
1384 specified file does not exist.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001385 """
1386 context = Context(TLSv1_METHOD)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001387 self.assertRaises(Error, context.load_tmp_dh, b"hello")
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001388
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001389 def _load_tmp_dh_test(self, dhfilename):
Jean-Paul Calderone4e0c43f2015-04-13 10:15:17 -04001390 """
1391 Verify that calling ``Context.load_tmp_dh`` with the given filename
1392 does not raise an exception.
1393 """
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001394 context = Context(TLSv1_METHOD)
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001395 with open(dhfilename, "w") as dhfile:
1396 dhfile.write(dhparam)
1397
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001398 context.load_tmp_dh(dhfilename)
1399 # XXX What should I assert here? -exarkun
1400
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001401 def test_load_tmp_dh_bytes(self):
1402 """
1403 :py:obj:`Context.load_tmp_dh` loads Diffie-Hellman parameters from the
1404 specified file (given as ``bytes``).
1405 """
1406 self._load_tmp_dh_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001407 self.mktemp() + NON_ASCII.encode(getfilesystemencoding()),
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001408 )
1409
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001410 def test_load_tmp_dh_unicode(self):
1411 """
1412 :py:obj:`Context.load_tmp_dh` loads Diffie-Hellman parameters from the
1413 specified file (given as ``unicode``).
1414 """
1415 self._load_tmp_dh_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001416 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII,
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001417 )
1418
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001419 def test_set_tmp_ecdh(self):
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001420 """
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001421 :py:obj:`Context.set_tmp_ecdh` sets the elliptic curve for
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001422 Diffie-Hellman to the specified curve.
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001423 """
1424 context = Context(TLSv1_METHOD)
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001425 for curve in get_elliptic_curves():
Hynek Schlawacka07fa8c2015-10-17 10:15:28 +02001426 if curve.name.startswith(u"Oakley-"):
Hynek Schlawack7408aff2015-10-17 09:51:16 +02001427 # Setting Oakley-EC2N-4 and Oakley-EC2N-3 adds
1428 # ('bignum routines', 'BN_mod_inverse', 'no inverse') to the
1429 # error queue on OpenSSL 1.0.2.
1430 continue
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001431 # The only easily "assertable" thing is that it does not raise an
1432 # exception.
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001433 context.set_tmp_ecdh(curve)
Alex Gaynor12dc0842014-01-17 12:51:31 -06001434
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001435 def test_set_session_cache_mode_wrong_args(self):
1436 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001437 :py:obj:`Context.set_session_cache_mode` raises :py:obj:`TypeError` if
1438 called with other than one integer argument.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001439 """
1440 context = Context(TLSv1_METHOD)
1441 self.assertRaises(TypeError, context.set_session_cache_mode)
1442 self.assertRaises(TypeError, context.set_session_cache_mode, object())
1443
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001444 def test_get_session_cache_mode_wrong_args(self):
1445 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001446 :py:obj:`Context.get_session_cache_mode` raises :py:obj:`TypeError` if
1447 called with any arguments.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001448 """
1449 context = Context(TLSv1_METHOD)
1450 self.assertRaises(TypeError, context.get_session_cache_mode, 1)
1451
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001452 def test_session_cache_mode(self):
1453 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001454 :py:obj:`Context.set_session_cache_mode` specifies how sessions are
1455 cached. The setting can be retrieved via
1456 :py:obj:`Context.get_session_cache_mode`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001457 """
1458 context = Context(TLSv1_METHOD)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001459 context.set_session_cache_mode(SESS_CACHE_OFF)
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001460 off = context.set_session_cache_mode(SESS_CACHE_BOTH)
1461 self.assertEqual(SESS_CACHE_OFF, off)
1462 self.assertEqual(SESS_CACHE_BOTH, context.get_session_cache_mode())
1463
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001464 @skip_if_py3
1465 def test_session_cache_mode_long(self):
1466 """
1467 On Python 2 :py:obj:`Context.set_session_cache_mode` accepts values
1468 of type :py:obj:`long` as well as :py:obj:`int`.
1469 """
1470 context = Context(TLSv1_METHOD)
1471 context.set_session_cache_mode(long(SESS_CACHE_BOTH))
1472 self.assertEqual(
1473 SESS_CACHE_BOTH, context.get_session_cache_mode())
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001474
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001475 def test_get_cert_store(self):
1476 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001477 :py:obj:`Context.get_cert_store` returns a :py:obj:`X509Store`
1478 instance.
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001479 """
1480 context = Context(TLSv1_METHOD)
1481 store = context.get_cert_store()
1482 self.assertIsInstance(store, X509Store)
1483
1484
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001485class ServerNameCallbackTests(TestCase, _LoopbackMixin):
1486 """
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001487 Tests for :py:obj:`Context.set_tlsext_servername_callback` and its
1488 interaction with :py:obj:`Connection`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001489 """
1490 def test_wrong_args(self):
1491 """
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001492 :py:obj:`Context.set_tlsext_servername_callback` raises
1493 :py:obj:`TypeError` if called with other than one argument.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001494 """
1495 context = Context(TLSv1_METHOD)
1496 self.assertRaises(TypeError, context.set_tlsext_servername_callback)
1497 self.assertRaises(
1498 TypeError, context.set_tlsext_servername_callback, 1, 2)
1499
1500 def test_old_callback_forgotten(self):
1501 """
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001502 If :py:obj:`Context.set_tlsext_servername_callback` is used to specify
1503 a new callback, the one it replaces is dereferenced.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001504 """
1505 def callback(connection):
1506 pass
1507
1508 def replacement(connection):
1509 pass
1510
1511 context = Context(TLSv1_METHOD)
1512 context.set_tlsext_servername_callback(callback)
1513
1514 tracker = ref(callback)
1515 del callback
1516
1517 context.set_tlsext_servername_callback(replacement)
Jean-Paul Calderoned4033eb2014-01-11 08:21:46 -05001518
1519 # One run of the garbage collector happens to work on CPython. PyPy
1520 # doesn't collect the underlying object until a second run for whatever
1521 # reason. That's fine, it still demonstrates our code has properly
1522 # dropped the reference.
1523 collect()
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001524 collect()
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001525
1526 callback = tracker()
1527 if callback is not None:
1528 referrers = get_referrers(callback)
Jean-Paul Calderone7de39562014-01-11 08:17:59 -05001529 if len(referrers) > 1:
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001530 self.fail("Some references remain: %r" % (referrers,))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001531
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001532 def test_no_servername(self):
1533 """
1534 When a client specifies no server name, the callback passed to
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001535 :py:obj:`Context.set_tlsext_servername_callback` is invoked and the
1536 result of :py:obj:`Connection.get_servername` is :py:obj:`None`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001537 """
1538 args = []
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001539
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001540 def servername(conn):
1541 args.append((conn, conn.get_servername()))
1542 context = Context(TLSv1_METHOD)
1543 context.set_tlsext_servername_callback(servername)
1544
1545 # Lose our reference to it. The Context is responsible for keeping it
1546 # alive now.
1547 del servername
1548 collect()
1549
1550 # Necessary to actually accept the connection
1551 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001552 context.use_certificate(
1553 load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001554
1555 # Do a little connection to trigger the logic
1556 server = Connection(context, None)
1557 server.set_accept_state()
1558
1559 client = Connection(Context(TLSv1_METHOD), None)
1560 client.set_connect_state()
1561
1562 self._interactInMemory(server, client)
1563
1564 self.assertEqual([(server, None)], args)
1565
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001566 def test_servername(self):
1567 """
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001568 When a client specifies a server name in its hello message, the
1569 callback passed to :py:obj:`Contexts.set_tlsext_servername_callback` is
1570 invoked and the result of :py:obj:`Connection.get_servername` is that
1571 server name.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001572 """
1573 args = []
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001574
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001575 def servername(conn):
1576 args.append((conn, conn.get_servername()))
1577 context = Context(TLSv1_METHOD)
1578 context.set_tlsext_servername_callback(servername)
1579
1580 # Necessary to actually accept the connection
1581 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001582 context.use_certificate(
1583 load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001584
1585 # Do a little connection to trigger the logic
1586 server = Connection(context, None)
1587 server.set_accept_state()
1588
1589 client = Connection(Context(TLSv1_METHOD), None)
1590 client.set_connect_state()
1591 client.set_tlsext_host_name(b("foo1.example.com"))
1592
1593 self._interactInMemory(server, client)
1594
1595 self.assertEqual([(server, b("foo1.example.com"))], args)
1596
1597
Cory Benfield84a121e2014-03-31 20:30:25 +01001598class NextProtoNegotiationTests(TestCase, _LoopbackMixin):
1599 """
1600 Test for Next Protocol Negotiation in PyOpenSSL.
1601 """
Cory Benfieldba1820d2015-04-13 17:39:12 -04001602 if _lib.Cryptography_HAS_NEXTPROTONEG:
1603 def test_npn_success(self):
1604 """
1605 Tests that clients and servers that agree on the negotiated next
1606 protocol can correct establish a connection, and that the agreed
1607 protocol is reported by the connections.
1608 """
1609 advertise_args = []
1610 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001611
Cory Benfieldba1820d2015-04-13 17:39:12 -04001612 def advertise(conn):
1613 advertise_args.append((conn,))
1614 return [b'http/1.1', b'spdy/2']
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001615
Cory Benfieldba1820d2015-04-13 17:39:12 -04001616 def select(conn, options):
1617 select_args.append((conn, options))
1618 return b'spdy/2'
Cory Benfield84a121e2014-03-31 20:30:25 +01001619
Cory Benfieldba1820d2015-04-13 17:39:12 -04001620 server_context = Context(TLSv1_METHOD)
1621 server_context.set_npn_advertise_callback(advertise)
Cory Benfield84a121e2014-03-31 20:30:25 +01001622
Cory Benfieldba1820d2015-04-13 17:39:12 -04001623 client_context = Context(TLSv1_METHOD)
1624 client_context.set_npn_select_callback(select)
Cory Benfield84a121e2014-03-31 20:30:25 +01001625
Cory Benfieldba1820d2015-04-13 17:39:12 -04001626 # Necessary to actually accept the connection
1627 server_context.use_privatekey(
1628 load_privatekey(FILETYPE_PEM, server_key_pem))
1629 server_context.use_certificate(
1630 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield84a121e2014-03-31 20:30:25 +01001631
Cory Benfieldba1820d2015-04-13 17:39:12 -04001632 # Do a little connection to trigger the logic
1633 server = Connection(server_context, None)
1634 server.set_accept_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001635
Cory Benfieldba1820d2015-04-13 17:39:12 -04001636 client = Connection(client_context, None)
1637 client.set_connect_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001638
Cory Benfieldba1820d2015-04-13 17:39:12 -04001639 self._interactInMemory(server, client)
Cory Benfield84a121e2014-03-31 20:30:25 +01001640
Cory Benfieldba1820d2015-04-13 17:39:12 -04001641 self.assertEqual([(server,)], advertise_args)
1642 self.assertEqual([(client, [b'http/1.1', b'spdy/2'])], select_args)
Cory Benfield84a121e2014-03-31 20:30:25 +01001643
Cory Benfieldba1820d2015-04-13 17:39:12 -04001644 self.assertEqual(server.get_next_proto_negotiated(), b'spdy/2')
1645 self.assertEqual(client.get_next_proto_negotiated(), b'spdy/2')
Cory Benfield84a121e2014-03-31 20:30:25 +01001646
Cory Benfieldba1820d2015-04-13 17:39:12 -04001647 def test_npn_client_fail(self):
1648 """
1649 Tests that when clients and servers cannot agree on what protocol
1650 to use next that the TLS connection does not get established.
1651 """
1652 advertise_args = []
1653 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001654
Cory Benfieldba1820d2015-04-13 17:39:12 -04001655 def advertise(conn):
1656 advertise_args.append((conn,))
1657 return [b'http/1.1', b'spdy/2']
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001658
Cory Benfieldba1820d2015-04-13 17:39:12 -04001659 def select(conn, options):
1660 select_args.append((conn, options))
1661 return b''
Cory Benfield84a121e2014-03-31 20:30:25 +01001662
Cory Benfieldba1820d2015-04-13 17:39:12 -04001663 server_context = Context(TLSv1_METHOD)
1664 server_context.set_npn_advertise_callback(advertise)
Cory Benfield84a121e2014-03-31 20:30:25 +01001665
Cory Benfieldba1820d2015-04-13 17:39:12 -04001666 client_context = Context(TLSv1_METHOD)
1667 client_context.set_npn_select_callback(select)
Cory Benfield84a121e2014-03-31 20:30:25 +01001668
Cory Benfieldba1820d2015-04-13 17:39:12 -04001669 # Necessary to actually accept the connection
1670 server_context.use_privatekey(
1671 load_privatekey(FILETYPE_PEM, server_key_pem))
1672 server_context.use_certificate(
1673 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield84a121e2014-03-31 20:30:25 +01001674
Cory Benfieldba1820d2015-04-13 17:39:12 -04001675 # Do a little connection to trigger the logic
1676 server = Connection(server_context, None)
1677 server.set_accept_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001678
Cory Benfieldba1820d2015-04-13 17:39:12 -04001679 client = Connection(client_context, None)
1680 client.set_connect_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001681
Cory Benfieldba1820d2015-04-13 17:39:12 -04001682 # If the client doesn't return anything, the connection will fail.
1683 self.assertRaises(Error, self._interactInMemory, server, client)
Cory Benfield84a121e2014-03-31 20:30:25 +01001684
Cory Benfieldba1820d2015-04-13 17:39:12 -04001685 self.assertEqual([(server,)], advertise_args)
1686 self.assertEqual([(client, [b'http/1.1', b'spdy/2'])], select_args)
Cory Benfield84a121e2014-03-31 20:30:25 +01001687
Cory Benfieldba1820d2015-04-13 17:39:12 -04001688 def test_npn_select_error(self):
1689 """
1690 Test that we can handle exceptions in the select callback. If
1691 select fails it should be fatal to the connection.
1692 """
1693 advertise_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001694
Cory Benfieldba1820d2015-04-13 17:39:12 -04001695 def advertise(conn):
1696 advertise_args.append((conn,))
1697 return [b'http/1.1', b'spdy/2']
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001698
Cory Benfieldba1820d2015-04-13 17:39:12 -04001699 def select(conn, options):
1700 raise TypeError
Cory Benfield0ea76e72015-03-22 09:05:28 +00001701
Cory Benfieldba1820d2015-04-13 17:39:12 -04001702 server_context = Context(TLSv1_METHOD)
1703 server_context.set_npn_advertise_callback(advertise)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001704
Cory Benfieldba1820d2015-04-13 17:39:12 -04001705 client_context = Context(TLSv1_METHOD)
1706 client_context.set_npn_select_callback(select)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001707
Cory Benfieldba1820d2015-04-13 17:39:12 -04001708 # Necessary to actually accept the connection
1709 server_context.use_privatekey(
1710 load_privatekey(FILETYPE_PEM, server_key_pem))
1711 server_context.use_certificate(
1712 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield0ea76e72015-03-22 09:05:28 +00001713
Cory Benfieldba1820d2015-04-13 17:39:12 -04001714 # Do a little connection to trigger the logic
1715 server = Connection(server_context, None)
1716 server.set_accept_state()
Cory Benfield0ea76e72015-03-22 09:05:28 +00001717
Cory Benfieldba1820d2015-04-13 17:39:12 -04001718 client = Connection(client_context, None)
1719 client.set_connect_state()
Cory Benfield0ea76e72015-03-22 09:05:28 +00001720
Cory Benfieldba1820d2015-04-13 17:39:12 -04001721 # If the callback throws an exception it should be raised here.
1722 self.assertRaises(
1723 TypeError, self._interactInMemory, server, client
1724 )
1725 self.assertEqual([(server,)], advertise_args)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001726
Cory Benfieldba1820d2015-04-13 17:39:12 -04001727 def test_npn_advertise_error(self):
1728 """
1729 Test that we can handle exceptions in the advertise callback. If
1730 advertise fails no NPN is advertised to the client.
1731 """
1732 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001733
Cory Benfieldba1820d2015-04-13 17:39:12 -04001734 def advertise(conn):
1735 raise TypeError
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001736
Hynek Schlawackb4ceed32015-09-05 20:55:19 +02001737 def select(conn, options): # pragma: nocover
1738 """
1739 Assert later that no args are actually appended.
1740 """
Cory Benfieldba1820d2015-04-13 17:39:12 -04001741 select_args.append((conn, options))
1742 return b''
Cory Benfield0ea76e72015-03-22 09:05:28 +00001743
Cory Benfieldba1820d2015-04-13 17:39:12 -04001744 server_context = Context(TLSv1_METHOD)
1745 server_context.set_npn_advertise_callback(advertise)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001746
Cory Benfieldba1820d2015-04-13 17:39:12 -04001747 client_context = Context(TLSv1_METHOD)
1748 client_context.set_npn_select_callback(select)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001749
Cory Benfieldba1820d2015-04-13 17:39:12 -04001750 # Necessary to actually accept the connection
1751 server_context.use_privatekey(
1752 load_privatekey(FILETYPE_PEM, server_key_pem))
1753 server_context.use_certificate(
1754 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield0ea76e72015-03-22 09:05:28 +00001755
Cory Benfieldba1820d2015-04-13 17:39:12 -04001756 # Do a little connection to trigger the logic
1757 server = Connection(server_context, None)
1758 server.set_accept_state()
Cory Benfield0ea76e72015-03-22 09:05:28 +00001759
Cory Benfieldba1820d2015-04-13 17:39:12 -04001760 client = Connection(client_context, None)
1761 client.set_connect_state()
Cory Benfield0ea76e72015-03-22 09:05:28 +00001762
Cory Benfieldba1820d2015-04-13 17:39:12 -04001763 # If the client doesn't return anything, the connection will fail.
1764 self.assertRaises(
1765 TypeError, self._interactInMemory, server, client
1766 )
1767 self.assertEqual([], select_args)
1768
1769 else:
1770 # No NPN.
1771 def test_npn_not_implemented(self):
1772 # Test the context methods first.
1773 context = Context(TLSv1_METHOD)
1774 fail_methods = [
1775 context.set_npn_advertise_callback,
1776 context.set_npn_select_callback,
1777 ]
1778 for method in fail_methods:
1779 self.assertRaises(
1780 NotImplementedError, method, None
1781 )
1782
1783 # Now test a connection.
1784 conn = Connection(context)
1785 fail_methods = [
1786 conn.get_next_proto_negotiated,
1787 ]
1788 for method in fail_methods:
1789 self.assertRaises(NotImplementedError, method)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001790
1791
Cory Benfield12eae892014-06-07 15:42:56 +01001792class ApplicationLayerProtoNegotiationTests(TestCase, _LoopbackMixin):
1793 """
1794 Tests for ALPN in PyOpenSSL.
1795 """
Cory Benfielde46fa842015-04-13 16:50:49 -04001796 # Skip tests on versions that don't support ALPN.
1797 if _lib.Cryptography_HAS_ALPN:
Cory Benfield12eae892014-06-07 15:42:56 +01001798
Cory Benfielde46fa842015-04-13 16:50:49 -04001799 def test_alpn_success(self):
1800 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04001801 Clients and servers that agree on the negotiated ALPN protocol can
1802 correct establish a connection, and the agreed protocol is reported
1803 by the connections.
Cory Benfielde46fa842015-04-13 16:50:49 -04001804 """
1805 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001806
Cory Benfielde46fa842015-04-13 16:50:49 -04001807 def select(conn, options):
1808 select_args.append((conn, options))
1809 return b'spdy/2'
Cory Benfield12eae892014-06-07 15:42:56 +01001810
Cory Benfielde46fa842015-04-13 16:50:49 -04001811 client_context = Context(TLSv1_METHOD)
1812 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfield12eae892014-06-07 15:42:56 +01001813
Cory Benfielde46fa842015-04-13 16:50:49 -04001814 server_context = Context(TLSv1_METHOD)
1815 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01001816
Cory Benfielde46fa842015-04-13 16:50:49 -04001817 # Necessary to actually accept the connection
1818 server_context.use_privatekey(
1819 load_privatekey(FILETYPE_PEM, server_key_pem))
1820 server_context.use_certificate(
1821 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield12eae892014-06-07 15:42:56 +01001822
Cory Benfielde46fa842015-04-13 16:50:49 -04001823 # Do a little connection to trigger the logic
1824 server = Connection(server_context, None)
1825 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001826
Cory Benfielde46fa842015-04-13 16:50:49 -04001827 client = Connection(client_context, None)
1828 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001829
Cory Benfielde46fa842015-04-13 16:50:49 -04001830 self._interactInMemory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001831
Cory Benfielde46fa842015-04-13 16:50:49 -04001832 self.assertEqual([(server, [b'http/1.1', b'spdy/2'])], select_args)
1833
1834 self.assertEqual(server.get_alpn_proto_negotiated(), b'spdy/2')
1835 self.assertEqual(client.get_alpn_proto_negotiated(), b'spdy/2')
Cory Benfield12eae892014-06-07 15:42:56 +01001836
Cory Benfielde46fa842015-04-13 16:50:49 -04001837 def test_alpn_set_on_connection(self):
1838 """
1839 The same as test_alpn_success, but setting the ALPN protocols on
1840 the connection rather than the context.
1841 """
1842 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001843
Cory Benfielde46fa842015-04-13 16:50:49 -04001844 def select(conn, options):
1845 select_args.append((conn, options))
1846 return b'spdy/2'
Cory Benfield12eae892014-06-07 15:42:56 +01001847
Cory Benfielde46fa842015-04-13 16:50:49 -04001848 # Setup the client context but don't set any ALPN protocols.
1849 client_context = Context(TLSv1_METHOD)
Cory Benfield12eae892014-06-07 15:42:56 +01001850
Cory Benfielde46fa842015-04-13 16:50:49 -04001851 server_context = Context(TLSv1_METHOD)
1852 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01001853
Cory Benfielde46fa842015-04-13 16:50:49 -04001854 # Necessary to actually accept the connection
1855 server_context.use_privatekey(
1856 load_privatekey(FILETYPE_PEM, server_key_pem))
1857 server_context.use_certificate(
1858 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield12eae892014-06-07 15:42:56 +01001859
Cory Benfielde46fa842015-04-13 16:50:49 -04001860 # Do a little connection to trigger the logic
1861 server = Connection(server_context, None)
1862 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001863
Cory Benfielde46fa842015-04-13 16:50:49 -04001864 # Set the ALPN protocols on the client connection.
1865 client = Connection(client_context, None)
1866 client.set_alpn_protos([b'http/1.1', b'spdy/2'])
1867 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001868
Cory Benfielde46fa842015-04-13 16:50:49 -04001869 self._interactInMemory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001870
Cory Benfielde46fa842015-04-13 16:50:49 -04001871 self.assertEqual([(server, [b'http/1.1', b'spdy/2'])], select_args)
Cory Benfield12eae892014-06-07 15:42:56 +01001872
Cory Benfielde46fa842015-04-13 16:50:49 -04001873 self.assertEqual(server.get_alpn_proto_negotiated(), b'spdy/2')
1874 self.assertEqual(client.get_alpn_proto_negotiated(), b'spdy/2')
Cory Benfield12eae892014-06-07 15:42:56 +01001875
Cory Benfielde46fa842015-04-13 16:50:49 -04001876 def test_alpn_server_fail(self):
1877 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04001878 When clients and servers cannot agree on what protocol to use next
1879 the TLS connection does not get established.
Cory Benfielde46fa842015-04-13 16:50:49 -04001880 """
1881 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001882
Cory Benfielde46fa842015-04-13 16:50:49 -04001883 def select(conn, options):
1884 select_args.append((conn, options))
1885 return b''
Cory Benfield12eae892014-06-07 15:42:56 +01001886
Cory Benfielde46fa842015-04-13 16:50:49 -04001887 client_context = Context(TLSv1_METHOD)
1888 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfield12eae892014-06-07 15:42:56 +01001889
Cory Benfielde46fa842015-04-13 16:50:49 -04001890 server_context = Context(TLSv1_METHOD)
1891 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01001892
Cory Benfielde46fa842015-04-13 16:50:49 -04001893 # Necessary to actually accept the connection
1894 server_context.use_privatekey(
1895 load_privatekey(FILETYPE_PEM, server_key_pem))
1896 server_context.use_certificate(
1897 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield12eae892014-06-07 15:42:56 +01001898
Cory Benfielde46fa842015-04-13 16:50:49 -04001899 # Do a little connection to trigger the logic
1900 server = Connection(server_context, None)
1901 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001902
Cory Benfielde46fa842015-04-13 16:50:49 -04001903 client = Connection(client_context, None)
1904 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001905
Cory Benfielde46fa842015-04-13 16:50:49 -04001906 # If the client doesn't return anything, the connection will fail.
1907 self.assertRaises(Error, self._interactInMemory, server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001908
Cory Benfielde46fa842015-04-13 16:50:49 -04001909 self.assertEqual([(server, [b'http/1.1', b'spdy/2'])], select_args)
Cory Benfield12eae892014-06-07 15:42:56 +01001910
Cory Benfielde46fa842015-04-13 16:50:49 -04001911 def test_alpn_no_server(self):
1912 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04001913 When clients and servers cannot agree on what protocol to use next
1914 because the server doesn't offer ALPN, no protocol is negotiated.
Cory Benfielde46fa842015-04-13 16:50:49 -04001915 """
1916 client_context = Context(TLSv1_METHOD)
1917 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfielde3d57152015-04-11 17:57:35 -04001918
Cory Benfielde46fa842015-04-13 16:50:49 -04001919 server_context = Context(TLSv1_METHOD)
Cory Benfielde3d57152015-04-11 17:57:35 -04001920
Cory Benfielde46fa842015-04-13 16:50:49 -04001921 # Necessary to actually accept the connection
1922 server_context.use_privatekey(
1923 load_privatekey(FILETYPE_PEM, server_key_pem))
1924 server_context.use_certificate(
1925 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfielde3d57152015-04-11 17:57:35 -04001926
Cory Benfielde46fa842015-04-13 16:50:49 -04001927 # Do a little connection to trigger the logic
1928 server = Connection(server_context, None)
1929 server.set_accept_state()
Cory Benfielde3d57152015-04-11 17:57:35 -04001930
Cory Benfielde46fa842015-04-13 16:50:49 -04001931 client = Connection(client_context, None)
1932 client.set_connect_state()
Cory Benfielde3d57152015-04-11 17:57:35 -04001933
Cory Benfielde46fa842015-04-13 16:50:49 -04001934 # Do the dance.
1935 self._interactInMemory(server, client)
Cory Benfielde3d57152015-04-11 17:57:35 -04001936
Cory Benfielde46fa842015-04-13 16:50:49 -04001937 self.assertEqual(client.get_alpn_proto_negotiated(), b'')
Cory Benfielde3d57152015-04-11 17:57:35 -04001938
Cory Benfielde46fa842015-04-13 16:50:49 -04001939 def test_alpn_callback_exception(self):
1940 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04001941 We can handle exceptions in the ALPN select callback.
Cory Benfielde46fa842015-04-13 16:50:49 -04001942 """
1943 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001944
Cory Benfielde46fa842015-04-13 16:50:49 -04001945 def select(conn, options):
1946 select_args.append((conn, options))
Cory Benfieldef401452015-04-13 18:17:36 -04001947 raise TypeError()
Cory Benfieldf1177e72015-04-12 09:11:49 -04001948
Cory Benfielde46fa842015-04-13 16:50:49 -04001949 client_context = Context(TLSv1_METHOD)
1950 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfieldf1177e72015-04-12 09:11:49 -04001951
Cory Benfielde46fa842015-04-13 16:50:49 -04001952 server_context = Context(TLSv1_METHOD)
1953 server_context.set_alpn_select_callback(select)
Cory Benfieldf1177e72015-04-12 09:11:49 -04001954
Cory Benfielde46fa842015-04-13 16:50:49 -04001955 # Necessary to actually accept the connection
1956 server_context.use_privatekey(
1957 load_privatekey(FILETYPE_PEM, server_key_pem))
1958 server_context.use_certificate(
1959 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfieldf1177e72015-04-12 09:11:49 -04001960
Cory Benfielde46fa842015-04-13 16:50:49 -04001961 # Do a little connection to trigger the logic
1962 server = Connection(server_context, None)
1963 server.set_accept_state()
Cory Benfieldf1177e72015-04-12 09:11:49 -04001964
Cory Benfielde46fa842015-04-13 16:50:49 -04001965 client = Connection(client_context, None)
1966 client.set_connect_state()
Cory Benfieldf1177e72015-04-12 09:11:49 -04001967
Cory Benfielde46fa842015-04-13 16:50:49 -04001968 self.assertRaises(
1969 TypeError, self._interactInMemory, server, client
1970 )
1971 self.assertEqual([(server, [b'http/1.1', b'spdy/2'])], select_args)
Cory Benfieldf1177e72015-04-12 09:11:49 -04001972
Cory Benfield0f7b04c2015-04-13 17:51:12 -04001973 else:
1974 # No ALPN.
1975 def test_alpn_not_implemented(self):
Cory Benfieldef401452015-04-13 18:17:36 -04001976 """
1977 If ALPN is not in OpenSSL, we should raise NotImplementedError.
1978 """
Cory Benfield0f7b04c2015-04-13 17:51:12 -04001979 # Test the context methods first.
1980 context = Context(TLSv1_METHOD)
Cory Benfield307e9e62015-04-13 18:21:12 -04001981 self.assertRaises(
1982 NotImplementedError, context.set_alpn_protos, None
1983 )
1984 self.assertRaises(
1985 NotImplementedError, context.set_alpn_select_callback, None
1986 )
Cory Benfield0f7b04c2015-04-13 17:51:12 -04001987
1988 # Now test a connection.
1989 conn = Connection(context)
Cory Benfield307e9e62015-04-13 18:21:12 -04001990 self.assertRaises(
Alex Gaynor68417232015-09-04 07:56:29 -04001991 NotImplementedError, conn.set_alpn_protos, None
Cory Benfield307e9e62015-04-13 18:21:12 -04001992 )
Cory Benfield0f7b04c2015-04-13 17:51:12 -04001993
Cory Benfieldf1177e72015-04-12 09:11:49 -04001994
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05001995class SessionTests(TestCase):
1996 """
1997 Unit tests for :py:obj:`OpenSSL.SSL.Session`.
1998 """
1999 def test_construction(self):
2000 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002001 :py:class:`Session` can be constructed with no arguments, creating
2002 a new instance of that type.
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05002003 """
2004 new_session = Session()
2005 self.assertTrue(isinstance(new_session, Session))
2006
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05002007 def test_construction_wrong_args(self):
2008 """
2009 If any arguments are passed to :py:class:`Session`, :py:obj:`TypeError`
2010 is raised.
2011 """
2012 self.assertRaises(TypeError, Session, 123)
2013 self.assertRaises(TypeError, Session, "hello")
2014 self.assertRaises(TypeError, Session, object())
2015
2016
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002017class ConnectionTests(TestCase, _LoopbackMixin):
Rick Deane15b1472009-07-09 15:53:42 -05002018 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002019 Unit tests for :py:obj:`OpenSSL.SSL.Connection`.
Rick Deane15b1472009-07-09 15:53:42 -05002020 """
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04002021 # XXX get_peer_certificate -> None
2022 # XXX sock_shutdown
2023 # XXX master_key -> TypeError
2024 # XXX server_random -> TypeError
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04002025 # XXX connect -> TypeError
2026 # XXX connect_ex -> TypeError
2027 # XXX set_connect_state -> TypeError
2028 # XXX set_accept_state -> TypeError
2029 # XXX renegotiate_pending
2030 # XXX do_handshake -> TypeError
2031 # XXX bio_read -> TypeError
2032 # XXX recv -> TypeError
2033 # XXX send -> TypeError
2034 # XXX bio_write -> TypeError
2035
Rick Deane15b1472009-07-09 15:53:42 -05002036 def test_type(self):
2037 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002038 :py:obj:`Connection` and :py:obj:`ConnectionType` refer to the same
2039 type object and can be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -05002040 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002041 self.assertIdentical(Connection, ConnectionType)
Rick Deane15b1472009-07-09 15:53:42 -05002042 ctx = Context(TLSv1_METHOD)
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002043 self.assertConsistentType(Connection, 'Connection', ctx, None)
Rick Deane15b1472009-07-09 15:53:42 -05002044
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002045 def test_get_context(self):
2046 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002047 :py:obj:`Connection.get_context` returns the :py:obj:`Context` instance
2048 used to construct the :py:obj:`Connection` instance.
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002049 """
2050 context = Context(TLSv1_METHOD)
2051 connection = Connection(context, None)
2052 self.assertIdentical(connection.get_context(), context)
2053
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002054 def test_get_context_wrong_args(self):
2055 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002056 :py:obj:`Connection.get_context` raises :py:obj:`TypeError` if called
2057 with any arguments.
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002058 """
2059 connection = Connection(Context(TLSv1_METHOD), None)
2060 self.assertRaises(TypeError, connection.get_context, None)
2061
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002062 def test_set_context_wrong_args(self):
2063 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002064 :py:obj:`Connection.set_context` raises :py:obj:`TypeError` if called
2065 with a non-:py:obj:`Context` instance argument or with any number of
2066 arguments other than 1.
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002067 """
2068 ctx = Context(TLSv1_METHOD)
2069 connection = Connection(ctx, None)
2070 self.assertRaises(TypeError, connection.set_context)
2071 self.assertRaises(TypeError, connection.set_context, object())
2072 self.assertRaises(TypeError, connection.set_context, "hello")
2073 self.assertRaises(TypeError, connection.set_context, 1)
2074 self.assertRaises(TypeError, connection.set_context, 1, 2)
2075 self.assertRaises(
2076 TypeError, connection.set_context, Context(TLSv1_METHOD), 2)
2077 self.assertIdentical(ctx, connection.get_context())
2078
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002079 def test_set_context(self):
2080 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002081 :py:obj:`Connection.set_context` specifies a new :py:obj:`Context`
2082 instance to be used for the connection.
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002083 """
2084 original = Context(SSLv23_METHOD)
2085 replacement = Context(TLSv1_METHOD)
2086 connection = Connection(original, None)
2087 connection.set_context(replacement)
2088 self.assertIdentical(replacement, connection.get_context())
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002089 # Lose our references to the contexts, just in case the Connection
2090 # isn't properly managing its own contributions to their reference
2091 # counts.
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002092 del original, replacement
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002093 collect()
2094
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002095 def test_set_tlsext_host_name_wrong_args(self):
2096 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002097 If :py:obj:`Connection.set_tlsext_host_name` is called with a non-byte
2098 string argument or a byte string with an embedded NUL or other than one
Jonathan Ballet648875f2011-07-16 14:14:58 +09002099 argument, :py:obj:`TypeError` is raised.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002100 """
2101 conn = Connection(Context(TLSv1_METHOD), None)
2102 self.assertRaises(TypeError, conn.set_tlsext_host_name)
2103 self.assertRaises(TypeError, conn.set_tlsext_host_name, object())
2104 self.assertRaises(TypeError, conn.set_tlsext_host_name, 123, 456)
2105 self.assertRaises(
2106 TypeError, conn.set_tlsext_host_name, b("with\0null"))
2107
Abraham Martinc5484ba2015-03-25 15:33:05 +00002108 if PY3:
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002109 # On Python 3.x, don't accidentally implicitly convert from text.
2110 self.assertRaises(
2111 TypeError,
2112 conn.set_tlsext_host_name, b("example.com").decode("ascii"))
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002113
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04002114 def test_get_servername_wrong_args(self):
2115 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002116 :py:obj:`Connection.get_servername` raises :py:obj:`TypeError` if
2117 called with any arguments.
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04002118 """
2119 connection = Connection(Context(TLSv1_METHOD), None)
2120 self.assertRaises(TypeError, connection.get_servername, object())
2121 self.assertRaises(TypeError, connection.get_servername, 1)
2122 self.assertRaises(TypeError, connection.get_servername, "hello")
2123
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002124 def test_pending(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002125 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002126 :py:obj:`Connection.pending` returns the number of bytes available for
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002127 immediate read.
2128 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002129 connection = Connection(Context(TLSv1_METHOD), None)
2130 self.assertEquals(connection.pending(), 0)
2131
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002132 def test_pending_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002133 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002134 :py:obj:`Connection.pending` raises :py:obj:`TypeError` if called with
2135 any arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002136 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002137 connection = Connection(Context(TLSv1_METHOD), None)
2138 self.assertRaises(TypeError, connection.pending, None)
2139
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002140 def test_peek(self):
2141 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002142 :py:obj:`Connection.recv` peeks into the connection if
2143 :py:obj:`socket.MSG_PEEK` is passed.
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002144 """
2145 server, client = self._loopback()
2146 server.send(b('xy'))
2147 self.assertEqual(client.recv(2, MSG_PEEK), b('xy'))
2148 self.assertEqual(client.recv(2, MSG_PEEK), b('xy'))
2149 self.assertEqual(client.recv(2), b('xy'))
2150
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002151 def test_connect_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002152 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002153 :py:obj:`Connection.connect` raises :py:obj:`TypeError` if called with
2154 a non-address argument or with the wrong number of arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002155 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002156 connection = Connection(Context(TLSv1_METHOD), socket())
2157 self.assertRaises(TypeError, connection.connect, None)
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002158 self.assertRaises(TypeError, connection.connect)
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002159 self.assertRaises(
2160 TypeError, connection.connect, ("127.0.0.1", 1), None
2161 )
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002162
kjavfe508d62015-09-02 12:20:35 +01002163 def test_connection_undefined_attr(self):
2164 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002165 :py:obj:`Connection.connect` raises :py:obj:`TypeError` if called with
2166 a non-address argument or with the wrong number of arguments.
kjavfe508d62015-09-02 12:20:35 +01002167 """
Alex Gaynor1aabb2e2015-09-05 13:35:18 -04002168
kjavfe508d62015-09-02 12:20:35 +01002169 def attr_access_test(connection):
2170 return connection.an_attribute_which_is_not_defined
Alex Gaynor1aabb2e2015-09-05 13:35:18 -04002171
kjavfe508d62015-09-02 12:20:35 +01002172 connection = Connection(Context(TLSv1_METHOD), None)
2173 self.assertRaises(AttributeError, attr_access_test, connection)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002174
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002175 def test_connect_refused(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002176 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002177 :py:obj:`Connection.connect` raises :py:obj:`socket.error` if the
2178 underlying socket connect method raises it.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002179 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002180 client = socket()
2181 context = Context(TLSv1_METHOD)
2182 clientSSL = Connection(context, client)
Alex Gaynor122717b2015-09-05 14:14:18 -04002183 # pytest.raises here doesn't work because of a bug in py.test on Python
2184 # 2.6: https://github.com/pytest-dev/pytest/issues/988
Alex Gaynore69c2782015-09-05 14:07:48 -04002185 try:
Alex Gaynor1aabb2e2015-09-05 13:35:18 -04002186 clientSSL.connect(("127.0.0.1", 1))
Alex Gaynore69c2782015-09-05 14:07:48 -04002187 except error as e:
Alex Gaynor20a4c082015-09-05 14:24:15 -04002188 exc = e
2189 assert exc.args[0] == ECONNREFUSED
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002190
2191 def test_connect(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002192 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002193 :py:obj:`Connection.connect` establishes a connection to the specified
2194 address.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002195 """
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002196 port = socket()
2197 port.bind(('', 0))
2198 port.listen(3)
2199
2200 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002201 clientSSL.connect(('127.0.0.1', port.getsockname()[1]))
2202 # XXX An assertion? Or something?
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002203
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002204 @pytest.mark.skipif(
2205 platform == "darwin",
2206 reason="connect_ex sometimes causes a kernel panic on OS X 10.6.4"
2207 )
2208 def test_connect_ex(self):
2209 """
2210 If there is a connection error, :py:obj:`Connection.connect_ex`
2211 returns the errno instead of raising an exception.
2212 """
2213 port = socket()
2214 port.bind(('', 0))
2215 port.listen(3)
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002216
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002217 clientSSL = Connection(Context(TLSv1_METHOD), socket())
2218 clientSSL.setblocking(False)
2219 result = clientSSL.connect_ex(port.getsockname())
2220 expected = (EINPROGRESS, EWOULDBLOCK)
2221 self.assertTrue(
2222 result in expected, "%r not in %r" % (result, expected))
Jean-Paul Calderone55d91f42010-07-29 19:22:17 -04002223
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002224 def test_accept_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002225 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002226 :py:obj:`Connection.accept` raises :py:obj:`TypeError` if called with
2227 any arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002228 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002229 connection = Connection(Context(TLSv1_METHOD), socket())
2230 self.assertRaises(TypeError, connection.accept, None)
2231
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002232 def test_accept(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002233 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002234 :py:obj:`Connection.accept` accepts a pending connection attempt and
2235 returns a tuple of a new :py:obj:`Connection` (the accepted client) and
2236 the address the connection originated from.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002237 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002238 ctx = Context(TLSv1_METHOD)
2239 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2240 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002241 port = socket()
2242 portSSL = Connection(ctx, port)
2243 portSSL.bind(('', 0))
2244 portSSL.listen(3)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002245
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002246 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002247
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002248 # Calling portSSL.getsockname() here to get the server IP address
2249 # sounds great, but frequently fails on Windows.
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002250 clientSSL.connect(('127.0.0.1', portSSL.getsockname()[1]))
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002251
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002252 serverSSL, address = portSSL.accept()
2253
2254 self.assertTrue(isinstance(serverSSL, Connection))
2255 self.assertIdentical(serverSSL.get_context(), ctx)
2256 self.assertEquals(address, clientSSL.getsockname())
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002257
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002258 def test_shutdown_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002259 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002260 :py:obj:`Connection.shutdown` raises :py:obj:`TypeError` if called with
2261 the wrong number of arguments or with arguments other than integers.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002262 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002263 connection = Connection(Context(TLSv1_METHOD), None)
2264 self.assertRaises(TypeError, connection.shutdown, None)
Jean-Paul Calderone1d3e0222010-07-29 22:52:45 -04002265 self.assertRaises(TypeError, connection.get_shutdown, None)
2266 self.assertRaises(TypeError, connection.set_shutdown)
2267 self.assertRaises(TypeError, connection.set_shutdown, None)
2268 self.assertRaises(TypeError, connection.set_shutdown, 0, 1)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002269
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002270 def test_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002271 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002272 :py:obj:`Connection.shutdown` performs an SSL-level connection
2273 shutdown.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002274 """
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002275 server, client = self._loopback()
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04002276 self.assertFalse(server.shutdown())
2277 self.assertEquals(server.get_shutdown(), SENT_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002278 self.assertRaises(ZeroReturnError, client.recv, 1024)
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04002279 self.assertEquals(client.get_shutdown(), RECEIVED_SHUTDOWN)
2280 client.shutdown()
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002281 self.assertEquals(
2282 client.get_shutdown(), SENT_SHUTDOWN | RECEIVED_SHUTDOWN
2283 )
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04002284 self.assertRaises(ZeroReturnError, server.recv, 1024)
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002285 self.assertEquals(
2286 server.get_shutdown(), SENT_SHUTDOWN | RECEIVED_SHUTDOWN
2287 )
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002288
Paul Aurichc85e0862015-01-08 08:34:33 -08002289 def test_shutdown_closed(self):
2290 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002291 If the underlying socket is closed, :py:obj:`Connection.shutdown`
2292 propagates the write error from the low level write call.
Paul Aurichc85e0862015-01-08 08:34:33 -08002293 """
2294 server, client = self._loopback()
2295 server.sock_shutdown(2)
2296 exc = self.assertRaises(SysCallError, server.shutdown)
2297 if platform == "win32":
2298 self.assertEqual(exc.args[0], ESHUTDOWN)
2299 else:
2300 self.assertEqual(exc.args[0], EPIPE)
2301
Glyph89389472015-04-14 17:29:26 -04002302 def test_shutdown_truncated(self):
Glyph6064ec32015-04-14 16:38:22 -04002303 """
Glyph89389472015-04-14 17:29:26 -04002304 If the underlying connection is truncated, :obj:`Connection.shutdown`
2305 raises an :obj:`Error`.
Glyph6064ec32015-04-14 16:38:22 -04002306 """
Glyph89389472015-04-14 17:29:26 -04002307 server_ctx = Context(TLSv1_METHOD)
2308 client_ctx = Context(TLSv1_METHOD)
2309 server_ctx.use_privatekey(
2310 load_privatekey(FILETYPE_PEM, server_key_pem))
2311 server_ctx.use_certificate(
2312 load_certificate(FILETYPE_PEM, server_cert_pem))
2313 server = Connection(server_ctx, None)
2314 client = Connection(client_ctx, None)
2315 self._handshakeInMemory(client, server)
2316 self.assertEqual(server.shutdown(), False)
2317 self.assertRaises(WantReadError, server.shutdown)
2318 server.bio_shutdown()
Glyph6064ec32015-04-14 16:38:22 -04002319 self.assertRaises(Error, server.shutdown)
2320
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002321 def test_set_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002322 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002323 :py:obj:`Connection.set_shutdown` sets the state of the SSL connection
2324 shutdown process.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002325 """
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002326 connection = Connection(Context(TLSv1_METHOD), socket())
2327 connection.set_shutdown(RECEIVED_SHUTDOWN)
2328 self.assertEquals(connection.get_shutdown(), RECEIVED_SHUTDOWN)
2329
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002330 @skip_if_py3
2331 def test_set_shutdown_long(self):
2332 """
2333 On Python 2 :py:obj:`Connection.set_shutdown` accepts an argument
2334 of type :py:obj:`long` as well as :py:obj:`int`.
2335 """
2336 connection = Connection(Context(TLSv1_METHOD), socket())
2337 connection.set_shutdown(long(RECEIVED_SHUTDOWN))
2338 self.assertEquals(connection.get_shutdown(), RECEIVED_SHUTDOWN)
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -05002339
kjavaf248592015-09-07 12:14:01 +01002340 def test_state_string(self):
2341 """
Hynek Schlawackb0274ce2015-10-16 19:56:26 +02002342 :meth:`Connection.state_string` verbosely describes the current
2343 state of the :class:`Connection`.
kjavaf248592015-09-07 12:14:01 +01002344 """
Hynek Schlawackb0274ce2015-10-16 19:56:26 +02002345 server, client = socket_pair()
kjavaf248592015-09-07 12:14:01 +01002346 server = self._loopbackServerFactory(server)
2347 client = self._loopbackClientFactory(client)
2348
Hynek Schlawacka5811cc2016-01-31 13:52:42 +01002349 assert b"before/accept initialization" == server.state_string()
2350 assert b"before/connect initialization" == client.state_string()
kjavaf248592015-09-07 12:14:01 +01002351
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002352 def test_app_data_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002353 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002354 :py:obj:`Connection.set_app_data` raises :py:obj:`TypeError` if called
2355 with other than one argument. :py:obj:`Connection.get_app_data` raises
2356 :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002357 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002358 conn = Connection(Context(TLSv1_METHOD), None)
2359 self.assertRaises(TypeError, conn.get_app_data, None)
2360 self.assertRaises(TypeError, conn.set_app_data)
2361 self.assertRaises(TypeError, conn.set_app_data, None, None)
2362
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002363 def test_app_data(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002364 """
2365 Any object can be set as app data by passing it to
Jonathan Ballet648875f2011-07-16 14:14:58 +09002366 :py:obj:`Connection.set_app_data` and later retrieved with
2367 :py:obj:`Connection.get_app_data`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002368 """
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002369 conn = Connection(Context(TLSv1_METHOD), None)
Todd Chapman4f73e4f2015-08-27 11:26:43 -04002370 assert None is conn.get_app_data()
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002371 app_data = object()
2372 conn.set_app_data(app_data)
Todd Chapman4f73e4f2015-08-27 11:26:43 -04002373 assert conn.get_app_data() is app_data
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002374
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002375 def test_makefile(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002376 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002377 :py:obj:`Connection.makefile` is not implemented and calling that
2378 method raises :py:obj:`NotImplementedError`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002379 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002380 conn = Connection(Context(TLSv1_METHOD), None)
2381 self.assertRaises(NotImplementedError, conn.makefile)
2382
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002383 def test_get_peer_cert_chain_wrong_args(self):
2384 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002385 :py:obj:`Connection.get_peer_cert_chain` raises :py:obj:`TypeError` if
2386 called with any arguments.
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002387 """
2388 conn = Connection(Context(TLSv1_METHOD), None)
2389 self.assertRaises(TypeError, conn.get_peer_cert_chain, 1)
2390 self.assertRaises(TypeError, conn.get_peer_cert_chain, "foo")
2391 self.assertRaises(TypeError, conn.get_peer_cert_chain, object())
2392 self.assertRaises(TypeError, conn.get_peer_cert_chain, [])
2393
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002394 def test_get_peer_cert_chain(self):
2395 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002396 :py:obj:`Connection.get_peer_cert_chain` returns a list of certificates
2397 which the connected server returned for the certification verification.
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002398 """
2399 chain = _create_certificate_chain()
2400 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
2401
2402 serverContext = Context(TLSv1_METHOD)
2403 serverContext.use_privatekey(skey)
2404 serverContext.use_certificate(scert)
2405 serverContext.add_extra_chain_cert(icert)
2406 serverContext.add_extra_chain_cert(cacert)
2407 server = Connection(serverContext, None)
2408 server.set_accept_state()
2409
2410 # Create the client
2411 clientContext = Context(TLSv1_METHOD)
2412 clientContext.set_verify(VERIFY_NONE, verify_cb)
2413 client = Connection(clientContext, None)
2414 client.set_connect_state()
2415
2416 self._interactInMemory(client, server)
2417
2418 chain = client.get_peer_cert_chain()
2419 self.assertEqual(len(chain), 3)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04002420 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002421 "Server Certificate", chain[0].get_subject().CN)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04002422 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002423 "Intermediate Certificate", chain[1].get_subject().CN)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04002424 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002425 "Authority Certificate", chain[2].get_subject().CN)
2426
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002427 def test_get_peer_cert_chain_none(self):
2428 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002429 :py:obj:`Connection.get_peer_cert_chain` returns :py:obj:`None` if the
2430 peer sends no certificate chain.
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002431 """
2432 ctx = Context(TLSv1_METHOD)
2433 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2434 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
2435 server = Connection(ctx, None)
2436 server.set_accept_state()
2437 client = Connection(Context(TLSv1_METHOD), None)
2438 client.set_connect_state()
2439 self._interactInMemory(client, server)
2440 self.assertIdentical(None, server.get_peer_cert_chain())
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002441
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002442 def test_get_session_wrong_args(self):
2443 """
2444 :py:obj:`Connection.get_session` raises :py:obj:`TypeError` if called
2445 with any arguments.
2446 """
2447 ctx = Context(TLSv1_METHOD)
2448 server = Connection(ctx, None)
2449 self.assertRaises(TypeError, server.get_session, 123)
2450 self.assertRaises(TypeError, server.get_session, "hello")
2451 self.assertRaises(TypeError, server.get_session, object())
2452
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002453 def test_get_session_unconnected(self):
2454 """
2455 :py:obj:`Connection.get_session` returns :py:obj:`None` when used with
2456 an object which has not been connected.
2457 """
2458 ctx = Context(TLSv1_METHOD)
2459 server = Connection(ctx, None)
2460 session = server.get_session()
2461 self.assertIdentical(None, session)
2462
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002463 def test_server_get_session(self):
2464 """
2465 On the server side of a connection, :py:obj:`Connection.get_session`
2466 returns a :py:class:`Session` instance representing the SSL session for
2467 that connection.
2468 """
2469 server, client = self._loopback()
2470 session = server.get_session()
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08002471 self.assertIsInstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002472
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002473 def test_client_get_session(self):
2474 """
2475 On the client side of a connection, :py:obj:`Connection.get_session`
2476 returns a :py:class:`Session` instance representing the SSL session for
2477 that connection.
2478 """
2479 server, client = self._loopback()
2480 session = client.get_session()
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08002481 self.assertIsInstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002482
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002483 def test_set_session_wrong_args(self):
2484 """
Hynek Schlawackdddd1112015-09-05 21:12:30 +02002485 If called with an object that is not an instance of
2486 :py:class:`Session`, or with other than one argument,
2487 :py:obj:`Connection.set_session` raises :py:obj:`TypeError`.
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002488 """
2489 ctx = Context(TLSv1_METHOD)
2490 connection = Connection(ctx, None)
2491 self.assertRaises(TypeError, connection.set_session)
2492 self.assertRaises(TypeError, connection.set_session, 123)
2493 self.assertRaises(TypeError, connection.set_session, "hello")
2494 self.assertRaises(TypeError, connection.set_session, object())
2495 self.assertRaises(
2496 TypeError, connection.set_session, Session(), Session())
2497
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002498 def test_client_set_session(self):
2499 """
2500 :py:obj:`Connection.set_session`, when used prior to a connection being
2501 established, accepts a :py:class:`Session` instance and causes an
2502 attempt to re-use the session it represents when the SSL handshake is
2503 performed.
2504 """
2505 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2506 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
2507 ctx = Context(TLSv1_METHOD)
2508 ctx.use_privatekey(key)
2509 ctx.use_certificate(cert)
2510 ctx.set_session_id("unity-test")
2511
2512 def makeServer(socket):
2513 server = Connection(ctx, socket)
2514 server.set_accept_state()
2515 return server
2516
2517 originalServer, originalClient = self._loopback(
2518 serverFactory=makeServer)
2519 originalSession = originalClient.get_session()
2520
2521 def makeClient(socket):
2522 client = self._loopbackClientFactory(socket)
2523 client.set_session(originalSession)
2524 return client
2525 resumedServer, resumedClient = self._loopback(
2526 serverFactory=makeServer,
2527 clientFactory=makeClient)
2528
2529 # This is a proxy: in general, we have no access to any unique
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002530 # identifier for the session (new enough versions of OpenSSL expose
2531 # a hash which could be usable, but "new enough" is very, very new).
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002532 # Instead, exploit the fact that the master key is re-used if the
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002533 # session is re-used. As long as the master key for the two
2534 # connections is the same, the session was re-used!
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002535 self.assertEqual(
2536 originalServer.master_key(), resumedServer.master_key())
2537
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002538 def test_set_session_wrong_method(self):
2539 """
Jean-Paul Calderone068cb592012-02-14 16:52:43 -05002540 If :py:obj:`Connection.set_session` is passed a :py:class:`Session`
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002541 instance associated with a context using a different SSL method than
2542 the :py:obj:`Connection` is using, a :py:class:`OpenSSL.SSL.Error` is
Jean-Paul Calderone068cb592012-02-14 16:52:43 -05002543 raised.
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002544 """
2545 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2546 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
2547 ctx = Context(TLSv1_METHOD)
2548 ctx.use_privatekey(key)
2549 ctx.use_certificate(cert)
2550 ctx.set_session_id("unity-test")
2551
2552 def makeServer(socket):
2553 server = Connection(ctx, socket)
2554 server.set_accept_state()
2555 return server
2556
2557 originalServer, originalClient = self._loopback(
2558 serverFactory=makeServer)
2559 originalSession = originalClient.get_session()
2560
2561 def makeClient(socket):
2562 # Intentionally use a different, incompatible method here.
2563 client = Connection(Context(SSLv3_METHOD), socket)
2564 client.set_connect_state()
2565 client.set_session(originalSession)
2566 return client
2567
2568 self.assertRaises(
2569 Error,
2570 self._loopback, clientFactory=makeClient, serverFactory=makeServer)
2571
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002572 def test_wantWriteError(self):
2573 """
2574 :py:obj:`Connection` methods which generate output raise
2575 :py:obj:`OpenSSL.SSL.WantWriteError` if writing to the connection's BIO
2576 fail indicating a should-write state.
2577 """
2578 client_socket, server_socket = socket_pair()
2579 # Fill up the client's send buffer so Connection won't be able to write
Jean-Paul Calderonebbff8b92014-03-22 14:20:30 -04002580 # anything. Only write a single byte at a time so we can be sure we
2581 # completely fill the buffer. Even though the socket API is allowed to
2582 # signal a short write via its return value it seems this doesn't
2583 # always happen on all platforms (FreeBSD and OS X particular) for the
2584 # very last bit of available buffer space.
2585 msg = b"x"
2586 for i in range(1024 * 1024 * 4):
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002587 try:
2588 client_socket.send(msg)
2589 except error as e:
2590 if e.errno == EWOULDBLOCK:
2591 break
2592 raise
2593 else:
2594 self.fail(
2595 "Failed to fill socket buffer, cannot test BIO want write")
2596
2597 ctx = Context(TLSv1_METHOD)
2598 conn = Connection(ctx, client_socket)
2599 # Client's speak first, so make it an SSL client
2600 conn.set_connect_state()
2601 self.assertRaises(WantWriteError, conn.do_handshake)
2602
2603 # XXX want_read
2604
Fedor Brunner416f4a12014-03-28 13:18:38 +01002605 def test_get_finished_before_connect(self):
Fedor Brunner5747b932014-03-05 14:22:34 +01002606 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002607 :py:obj:`Connection.get_finished` returns :py:obj:`None` before TLS
2608 handshake is completed.
Fedor Brunner5747b932014-03-05 14:22:34 +01002609 """
Fedor Brunner5747b932014-03-05 14:22:34 +01002610 ctx = Context(TLSv1_METHOD)
2611 connection = Connection(ctx, None)
2612 self.assertEqual(connection.get_finished(), None)
Fedor Brunner416f4a12014-03-28 13:18:38 +01002613
2614 def test_get_peer_finished_before_connect(self):
2615 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002616 :py:obj:`Connection.get_peer_finished` returns :py:obj:`None` before
2617 TLS handshake is completed.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002618 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002619 ctx = Context(TLSv1_METHOD)
2620 connection = Connection(ctx, None)
Fedor Brunner5747b932014-03-05 14:22:34 +01002621 self.assertEqual(connection.get_peer_finished(), None)
2622
Fedor Brunner416f4a12014-03-28 13:18:38 +01002623 def test_get_finished(self):
2624 """
2625 :py:obj:`Connection.get_finished` method returns the TLS Finished
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002626 message send from client, or server. Finished messages are send during
2627 TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002628 """
2629
Fedor Brunner5747b932014-03-05 14:22:34 +01002630 server, client = self._loopback()
2631
2632 self.assertNotEqual(server.get_finished(), None)
2633 self.assertTrue(len(server.get_finished()) > 0)
Fedor Brunner416f4a12014-03-28 13:18:38 +01002634
2635 def test_get_peer_finished(self):
2636 """
2637 :py:obj:`Connection.get_peer_finished` method returns the TLS Finished
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002638 message received from client, or server. Finished messages are send
2639 during TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002640 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002641 server, client = self._loopback()
2642
2643 self.assertNotEqual(server.get_peer_finished(), None)
Fedor Brunner5747b932014-03-05 14:22:34 +01002644 self.assertTrue(len(server.get_peer_finished()) > 0)
2645
Fedor Brunner416f4a12014-03-28 13:18:38 +01002646 def test_tls_finished_message_symmetry(self):
2647 """
Hynek Schlawackdddd1112015-09-05 21:12:30 +02002648 The TLS Finished message send by server must be the TLS Finished
2649 message received by client.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002650
Hynek Schlawackdddd1112015-09-05 21:12:30 +02002651 The TLS Finished message send by client must be the TLS Finished
2652 message received by server.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002653 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002654 server, client = self._loopback()
2655
Fedor Brunner5747b932014-03-05 14:22:34 +01002656 self.assertEqual(server.get_finished(), client.get_peer_finished())
2657 self.assertEqual(client.get_finished(), server.get_peer_finished())
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002658
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002659 def test_get_cipher_name_before_connect(self):
2660 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002661 :py:obj:`Connection.get_cipher_name` returns :py:obj:`None` if no
2662 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002663 """
2664 ctx = Context(TLSv1_METHOD)
2665 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002666 self.assertIdentical(conn.get_cipher_name(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002667
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002668 def test_get_cipher_name(self):
2669 """
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002670 :py:obj:`Connection.get_cipher_name` returns a :py:class:`unicode`
2671 string giving the name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002672 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002673 server, client = self._loopback()
2674 server_cipher_name, client_cipher_name = \
2675 server.get_cipher_name(), client.get_cipher_name()
2676
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002677 self.assertIsInstance(server_cipher_name, text_type)
2678 self.assertIsInstance(client_cipher_name, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002679
2680 self.assertEqual(server_cipher_name, client_cipher_name)
2681
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002682 def test_get_cipher_version_before_connect(self):
2683 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002684 :py:obj:`Connection.get_cipher_version` returns :py:obj:`None` if no
2685 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002686 """
2687 ctx = Context(TLSv1_METHOD)
2688 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002689 self.assertIdentical(conn.get_cipher_version(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002690
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002691 def test_get_cipher_version(self):
2692 """
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002693 :py:obj:`Connection.get_cipher_version` returns a :py:class:`unicode`
2694 string giving the protocol name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002695 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002696 server, client = self._loopback()
2697 server_cipher_version, client_cipher_version = \
2698 server.get_cipher_version(), client.get_cipher_version()
2699
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002700 self.assertIsInstance(server_cipher_version, text_type)
2701 self.assertIsInstance(client_cipher_version, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002702
2703 self.assertEqual(server_cipher_version, client_cipher_version)
2704
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002705 def test_get_cipher_bits_before_connect(self):
2706 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002707 :py:obj:`Connection.get_cipher_bits` returns :py:obj:`None` if no
2708 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002709 """
2710 ctx = Context(TLSv1_METHOD)
2711 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002712 self.assertIdentical(conn.get_cipher_bits(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002713
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002714 def test_get_cipher_bits(self):
2715 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002716 :py:obj:`Connection.get_cipher_bits` returns the number of secret bits
2717 of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002718 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002719 server, client = self._loopback()
2720 server_cipher_bits, client_cipher_bits = \
2721 server.get_cipher_bits(), client.get_cipher_bits()
2722
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002723 self.assertIsInstance(server_cipher_bits, int)
2724 self.assertIsInstance(client_cipher_bits, int)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002725
2726 self.assertEqual(server_cipher_bits, client_cipher_bits)
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002727
Jim Shaverabff1882015-05-27 09:15:55 -04002728 def test_get_protocol_version_name(self):
2729 """
2730 :py:obj:`Connection.get_protocol_version_name()` returns a string
2731 giving the protocol version of the current connection.
2732 """
2733 server, client = self._loopback()
2734 client_protocol_version_name = client.get_protocol_version_name()
2735 server_protocol_version_name = server.get_protocol_version_name()
2736
Jim Shaver58d25732015-05-28 11:52:32 -04002737 self.assertIsInstance(server_protocol_version_name, text_type)
2738 self.assertIsInstance(client_protocol_version_name, text_type)
Jim Shaverabff1882015-05-27 09:15:55 -04002739
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002740 self.assertEqual(
2741 server_protocol_version_name, client_protocol_version_name
2742 )
Jim Shaverabff1882015-05-27 09:15:55 -04002743
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002744 def test_get_protocol_version(self):
2745 """
Alex Gaynor43307782015-09-04 09:05:45 -04002746 :py:obj:`Connection.get_protocol_version()` returns an integer
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002747 giving the protocol version of the current connection.
2748 """
2749 server, client = self._loopback()
Jim Shaver85a4dff2015-04-27 17:42:46 -04002750 client_protocol_version = client.get_protocol_version()
2751 server_protocol_version = server.get_protocol_version()
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002752
Jim Shaverabff1882015-05-27 09:15:55 -04002753 self.assertIsInstance(server_protocol_version, int)
2754 self.assertIsInstance(client_protocol_version, int)
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002755
2756 self.assertEqual(server_protocol_version, client_protocol_version)
2757
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002758
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002759class ConnectionGetCipherListTests(TestCase):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002760 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002761 Tests for :py:obj:`Connection.get_cipher_list`.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002762 """
Jean-Paul Calderone54a2bc02010-09-09 17:52:38 -04002763 def test_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002764 """
Hynek Schlawackdddd1112015-09-05 21:12:30 +02002765 :py:obj:`Connection.get_cipher_list` raises :py:obj:`TypeError` if
2766 called with any arguments.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002767 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002768 connection = Connection(Context(TLSv1_METHOD), None)
2769 self.assertRaises(TypeError, connection.get_cipher_list, None)
2770
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002771 def test_result(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002772 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002773 :py:obj:`Connection.get_cipher_list` returns a :py:obj:`list` of
2774 :py:obj:`bytes` giving the names of the ciphers which might be used.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002775 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002776 connection = Connection(Context(TLSv1_METHOD), None)
2777 ciphers = connection.get_cipher_list()
2778 self.assertTrue(isinstance(ciphers, list))
2779 for cipher in ciphers:
2780 self.assertTrue(isinstance(cipher, str))
2781
2782
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002783class ConnectionSendTests(TestCase, _LoopbackMixin):
2784 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002785 Tests for :py:obj:`Connection.send`
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002786 """
2787 def test_wrong_args(self):
2788 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002789 When called with arguments other than string argument for its first
2790 parameter or more than two arguments, :py:obj:`Connection.send` raises
2791 :py:obj:`TypeError`.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002792 """
2793 connection = Connection(Context(TLSv1_METHOD), None)
Jean-Paul Calderone77fa2602011-01-05 18:23:39 -05002794 self.assertRaises(TypeError, connection.send)
2795 self.assertRaises(TypeError, connection.send, object())
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002796 self.assertRaises(TypeError, connection.send, "foo", object(), "bar")
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002797
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002798 def test_short_bytes(self):
2799 """
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002800 When passed a short byte string, :py:obj:`Connection.send` transmits
2801 all of it and returns the number of bytes sent.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002802 """
2803 server, client = self._loopback()
2804 count = server.send(b('xy'))
2805 self.assertEquals(count, 2)
2806 self.assertEquals(client.recv(2), b('xy'))
2807
Abraham Martinef063482015-03-25 14:06:24 +00002808 def test_text(self):
2809 """
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002810 When passed a text, :py:obj:`Connection.send` transmits all of it and
2811 returns the number of bytes sent. It also raises a DeprecationWarning.
Abraham Martinef063482015-03-25 14:06:24 +00002812 """
2813 server, client = self._loopback()
2814 with catch_warnings(record=True) as w:
2815 simplefilter("always")
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002816 count = server.send(b"xy".decode("ascii"))
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002817 self.assertEqual(
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002818 "{0} for buf is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002819 WARNING_TYPE_EXPECTED
2820 ),
2821 str(w[-1].message)
2822 )
2823 self.assertIs(w[-1].category, DeprecationWarning)
Abraham Martinef063482015-03-25 14:06:24 +00002824 self.assertEquals(count, 2)
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002825 self.assertEquals(client.recv(2), b"xy")
Abraham Martinef063482015-03-25 14:06:24 +00002826
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002827 @skip_if_py26
2828 def test_short_memoryview(self):
2829 """
2830 When passed a memoryview onto a small number of bytes,
2831 :py:obj:`Connection.send` transmits all of them and returns the number
2832 of bytes sent.
2833 """
2834 server, client = self._loopback()
2835 count = server.send(memoryview(b('xy')))
2836 self.assertEquals(count, 2)
2837 self.assertEquals(client.recv(2), b('xy'))
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002838
Hynek Schlawack8e94f1b2015-09-05 21:31:00 +02002839 @skip_if_py3
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002840 def test_short_buffer(self):
2841 """
2842 When passed a buffer containing a small number of bytes,
2843 :py:obj:`Connection.send` transmits all of them and returns the number
2844 of bytes sent.
2845 """
2846 server, client = self._loopback()
2847 count = server.send(buffer(b('xy')))
2848 self.assertEquals(count, 2)
2849 self.assertEquals(client.recv(2), b('xy'))
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02002850
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05002851
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002852def _make_memoryview(size):
2853 """
2854 Create a new ``memoryview`` wrapped around a ``bytearray`` of the given
2855 size.
2856 """
2857 return memoryview(bytearray(size))
2858
2859
Cory Benfield62d10332014-06-15 10:03:41 +01002860class ConnectionRecvIntoTests(TestCase, _LoopbackMixin):
2861 """
2862 Tests for :py:obj:`Connection.recv_into`
2863 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002864 def _no_length_test(self, factory):
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04002865 """
2866 Assert that when the given buffer is passed to
2867 ``Connection.recv_into``, whatever bytes are available to be received
2868 that fit into that buffer are written into that buffer.
2869 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002870 output_buffer = factory(5)
2871
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04002872 server, client = self._loopback()
2873 server.send(b('xy'))
2874
Jean-Paul Calderone320af1e2015-03-15 17:20:13 -04002875 self.assertEqual(client.recv_into(output_buffer), 2)
2876 self.assertEqual(output_buffer, bytearray(b('xy\x00\x00\x00')))
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04002877
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002878 def test_bytearray_no_length(self):
Cory Benfield62d10332014-06-15 10:03:41 +01002879 """
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04002880 :py:obj:`Connection.recv_into` can be passed a ``bytearray`` instance
2881 and data in the receive buffer is written to it.
Cory Benfield62d10332014-06-15 10:03:41 +01002882 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002883 self._no_length_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01002884
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002885 def _respects_length_test(self, factory):
Cory Benfield62d10332014-06-15 10:03:41 +01002886 """
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002887 Assert that when the given buffer is passed to ``Connection.recv_into``
2888 along with a value for ``nbytes`` that is less than the size of that
2889 buffer, only ``nbytes`` bytes are written into the buffer.
Cory Benfield62d10332014-06-15 10:03:41 +01002890 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002891 output_buffer = factory(10)
2892
Cory Benfield62d10332014-06-15 10:03:41 +01002893 server, client = self._loopback()
2894 server.send(b('abcdefghij'))
Cory Benfield62d10332014-06-15 10:03:41 +01002895
Jean-Paul Calderone320af1e2015-03-15 17:20:13 -04002896 self.assertEqual(client.recv_into(output_buffer, 5), 5)
2897 self.assertEqual(
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002898 output_buffer, bytearray(b('abcde\x00\x00\x00\x00\x00'))
2899 )
2900
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002901 def test_bytearray_respects_length(self):
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002902 """
2903 When called with a ``bytearray`` instance,
2904 :py:obj:`Connection.recv_into` respects the ``nbytes`` parameter and
2905 doesn't copy in more than that number of bytes.
2906 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002907 self._respects_length_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01002908
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002909 def _doesnt_overfill_test(self, factory):
Cory Benfield62d10332014-06-15 10:03:41 +01002910 """
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002911 Assert that if there are more bytes available to be read from the
2912 receive buffer than would fit into the buffer passed to
2913 :py:obj:`Connection.recv_into`, only as many as fit are written into
2914 it.
Cory Benfield62d10332014-06-15 10:03:41 +01002915 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002916 output_buffer = factory(5)
2917
Cory Benfield62d10332014-06-15 10:03:41 +01002918 server, client = self._loopback()
2919 server.send(b('abcdefghij'))
Cory Benfield62d10332014-06-15 10:03:41 +01002920
Jean-Paul Calderone320af1e2015-03-15 17:20:13 -04002921 self.assertEqual(client.recv_into(output_buffer), 5)
2922 self.assertEqual(output_buffer, bytearray(b('abcde')))
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002923 rest = client.recv(5)
2924 self.assertEqual(b('fghij'), rest)
2925
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002926 def test_bytearray_doesnt_overfill(self):
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002927 """
2928 When called with a ``bytearray`` instance,
2929 :py:obj:`Connection.recv_into` respects the size of the array and
2930 doesn't write more bytes into it than will fit.
2931 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002932 self._doesnt_overfill_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01002933
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002934 def _really_doesnt_overfill_test(self, factory):
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04002935 """
2936 Assert that if the value given by ``nbytes`` is greater than the actual
2937 size of the output buffer passed to :py:obj:`Connection.recv_into`, the
2938 behavior is as if no value was given for ``nbytes`` at all.
2939 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002940 output_buffer = factory(5)
2941
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04002942 server, client = self._loopback()
2943 server.send(b('abcdefghij'))
2944
2945 self.assertEqual(client.recv_into(output_buffer, 50), 5)
2946 self.assertEqual(output_buffer, bytearray(b('abcde')))
2947 rest = client.recv(5)
2948 self.assertEqual(b('fghij'), rest)
2949
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002950 def test_bytearray_really_doesnt_overfill(self):
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04002951 """
2952 When called with a ``bytearray`` instance and an ``nbytes`` value that
2953 is too large, :py:obj:`Connection.recv_into` respects the size of the
2954 array and not the ``nbytes`` value and doesn't write more bytes into
2955 the buffer than will fit.
2956 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002957 self._doesnt_overfill_test(bytearray)
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04002958
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002959 def test_peek(self):
2960
2961 server, client = self._loopback()
2962 server.send(b('xy'))
2963
2964 for _ in range(2):
2965 output_buffer = bytearray(5)
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002966 self.assertEqual(
2967 client.recv_into(output_buffer, flags=MSG_PEEK), 2)
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002968 self.assertEqual(output_buffer, bytearray(b('xy\x00\x00\x00')))
2969
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002970 @skip_if_py26
2971 def test_memoryview_no_length(self):
2972 """
2973 :py:obj:`Connection.recv_into` can be passed a ``memoryview``
2974 instance and data in the receive buffer is written to it.
2975 """
2976 self._no_length_test(_make_memoryview)
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002977
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002978 @skip_if_py26
2979 def test_memoryview_respects_length(self):
2980 """
2981 When called with a ``memoryview`` instance,
2982 :py:obj:`Connection.recv_into` respects the ``nbytes`` parameter
2983 and doesn't copy more than that number of bytes in.
2984 """
2985 self._respects_length_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01002986
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002987 @skip_if_py26
2988 def test_memoryview_doesnt_overfill(self):
2989 """
2990 When called with a ``memoryview`` instance,
2991 :py:obj:`Connection.recv_into` respects the size of the array and
2992 doesn't write more bytes into it than will fit.
2993 """
2994 self._doesnt_overfill_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01002995
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002996 @skip_if_py26
2997 def test_memoryview_really_doesnt_overfill(self):
2998 """
2999 When called with a ``memoryview`` instance and an ``nbytes`` value
3000 that is too large, :py:obj:`Connection.recv_into` respects the size
3001 of the array and not the ``nbytes`` value and doesn't write more
3002 bytes into the buffer than will fit.
3003 """
3004 self._doesnt_overfill_test(_make_memoryview)
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003005
Cory Benfield62d10332014-06-15 10:03:41 +01003006
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003007class ConnectionSendallTests(TestCase, _LoopbackMixin):
3008 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003009 Tests for :py:obj:`Connection.sendall`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003010 """
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003011 def test_wrong_args(self):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003012 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003013 When called with arguments other than a string argument for its first
3014 parameter or with more than two arguments, :py:obj:`Connection.sendall`
3015 raises :py:obj:`TypeError`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003016 """
3017 connection = Connection(Context(TLSv1_METHOD), None)
3018 self.assertRaises(TypeError, connection.sendall)
3019 self.assertRaises(TypeError, connection.sendall, object())
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003020 self.assertRaises(
3021 TypeError, connection.sendall, "foo", object(), "bar")
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003022
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003023 def test_short(self):
3024 """
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003025 :py:obj:`Connection.sendall` transmits all of the bytes in the string
3026 passed to it.
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003027 """
3028 server, client = self._loopback()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04003029 server.sendall(b('x'))
3030 self.assertEquals(client.recv(1), b('x'))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003031
Abraham Martinef063482015-03-25 14:06:24 +00003032 def test_text(self):
3033 """
Jean-Paul Calderone93477422015-04-13 20:38:57 -04003034 :py:obj:`Connection.sendall` transmits all the content in the string
3035 passed to it raising a DeprecationWarning in case of this being a text.
Abraham Martinef063482015-03-25 14:06:24 +00003036 """
3037 server, client = self._loopback()
3038 with catch_warnings(record=True) as w:
3039 simplefilter("always")
Jean-Paul Calderone8dc37a12015-03-29 08:16:52 -04003040 server.sendall(b"x".decode("ascii"))
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04003041 self.assertEqual(
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04003042 "{0} for buf is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04003043 WARNING_TYPE_EXPECTED
3044 ),
3045 str(w[-1].message)
3046 )
3047 self.assertIs(w[-1].category, DeprecationWarning)
3048 self.assertEquals(client.recv(1), b"x")
Abraham Martinef063482015-03-25 14:06:24 +00003049
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003050 @skip_if_py26
3051 def test_short_memoryview(self):
3052 """
3053 When passed a memoryview onto a small number of bytes,
3054 :py:obj:`Connection.sendall` transmits all of them.
3055 """
3056 server, client = self._loopback()
3057 server.sendall(memoryview(b('x')))
3058 self.assertEquals(client.recv(1), b('x'))
Abraham Martinef063482015-03-25 14:06:24 +00003059
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003060 @skip_if_py3
3061 def test_short_buffers(self):
3062 """
3063 When passed a buffer containing a small number of bytes,
3064 :py:obj:`Connection.sendall` transmits all of them.
3065 """
3066 server, client = self._loopback()
3067 server.sendall(buffer(b('x')))
3068 self.assertEquals(client.recv(1), b('x'))
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02003069
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003070 def test_long(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003071 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003072 :py:obj:`Connection.sendall` transmits all of the bytes in the string
3073 passed to it even if this requires multiple calls of an underlying
3074 write function.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003075 """
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003076 server, client = self._loopback()
Jean-Paul Calderone6241c702010-09-16 19:59:24 -04003077 # Should be enough, underlying SSL_write should only do 16k at a time.
Hynek Schlawack35618382015-09-05 21:54:25 +02003078 # On Windows, after 32k of bytes the write will block (forever
3079 # - because no one is yet reading).
Jean-Paul Calderone9e4c1352010-09-19 09:34:43 -04003080 message = b('x') * (1024 * 32 - 1) + b('y')
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003081 server.sendall(message)
3082 accum = []
3083 received = 0
3084 while received < len(message):
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04003085 data = client.recv(1024)
3086 accum.append(data)
3087 received += len(data)
Jean-Paul Calderonef4047852010-09-19 09:45:57 -04003088 self.assertEquals(message, b('').join(accum))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003089
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003090 def test_closed(self):
3091 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003092 If the underlying socket is closed, :py:obj:`Connection.sendall`
3093 propagates the write error from the low level write call.
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003094 """
3095 server, client = self._loopback()
Jean-Paul Calderone05d43e82010-09-24 18:01:36 -04003096 server.sock_shutdown(2)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003097 exc = self.assertRaises(SysCallError, server.sendall, b"hello, world")
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +02003098 if platform == "win32":
3099 self.assertEqual(exc.args[0], ESHUTDOWN)
3100 else:
3101 self.assertEqual(exc.args[0], EPIPE)
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003102
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003103
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003104class ConnectionRenegotiateTests(TestCase, _LoopbackMixin):
3105 """
3106 Tests for SSL renegotiation APIs.
3107 """
3108 def test_renegotiate_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003109 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003110 :py:obj:`Connection.renegotiate` raises :py:obj:`TypeError` if called
3111 with any arguments.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003112 """
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003113 connection = Connection(Context(TLSv1_METHOD), None)
3114 self.assertRaises(TypeError, connection.renegotiate, None)
3115
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003116 def test_total_renegotiations_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003117 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003118 :py:obj:`Connection.total_renegotiations` raises :py:obj:`TypeError` if
3119 called with any arguments.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003120 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003121 connection = Connection(Context(TLSv1_METHOD), None)
3122 self.assertRaises(TypeError, connection.total_renegotiations, None)
3123
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003124 def test_total_renegotiations(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003125 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003126 :py:obj:`Connection.total_renegotiations` returns :py:obj:`0` before
3127 any renegotiations have happened.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003128 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003129 connection = Connection(Context(TLSv1_METHOD), None)
3130 self.assertEquals(connection.total_renegotiations(), 0)
3131
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003132# def test_renegotiate(self):
3133# """
3134# """
3135# server, client = self._loopback()
3136
3137# server.send("hello world")
3138# self.assertEquals(client.recv(len("hello world")), "hello world")
3139
3140# self.assertEquals(server.total_renegotiations(), 0)
3141# self.assertTrue(server.renegotiate())
3142
3143# server.setblocking(False)
3144# client.setblocking(False)
3145# while server.renegotiate_pending():
3146# client.do_handshake()
3147# server.do_handshake()
3148
3149# self.assertEquals(server.total_renegotiations(), 1)
3150
3151
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003152class ErrorTests(TestCase):
3153 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003154 Unit tests for :py:obj:`OpenSSL.SSL.Error`.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003155 """
3156 def test_type(self):
3157 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003158 :py:obj:`Error` is an exception type.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003159 """
3160 self.assertTrue(issubclass(Error, Exception))
Rick Deane15b1472009-07-09 15:53:42 -05003161 self.assertEqual(Error.__name__, 'Error')
Rick Deane15b1472009-07-09 15:53:42 -05003162
3163
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003164class ConstantsTests(TestCase):
3165 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003166 Tests for the values of constants exposed in :py:obj:`OpenSSL.SSL`.
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003167
3168 These are values defined by OpenSSL intended only to be used as flags to
3169 OpenSSL APIs. The only assertions it seems can be made about them is
3170 their values.
3171 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003172 @pytest.mark.skipif(
3173 OP_NO_QUERY_MTU is None,
3174 reason="OP_NO_QUERY_MTU unavailable - OpenSSL version may be too old"
3175 )
3176 def test_op_no_query_mtu(self):
3177 """
3178 The value of :py:obj:`OpenSSL.SSL.OP_NO_QUERY_MTU` is 0x1000, the value
3179 of :py:const:`SSL_OP_NO_QUERY_MTU` defined by :file:`openssl/ssl.h`.
3180 """
3181 self.assertEqual(OP_NO_QUERY_MTU, 0x1000)
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003182
Hynek Schlawack35618382015-09-05 21:54:25 +02003183 @pytest.mark.skipif(
3184 OP_COOKIE_EXCHANGE is None,
3185 reason="OP_COOKIE_EXCHANGE unavailable - "
3186 "OpenSSL version may be too old"
3187 )
3188 def test_op_cookie_exchange(self):
3189 """
3190 The value of :py:obj:`OpenSSL.SSL.OP_COOKIE_EXCHANGE` is 0x2000, the
3191 value of :py:const:`SSL_OP_COOKIE_EXCHANGE` defined by
3192 :file:`openssl/ssl.h`.
3193 """
3194 self.assertEqual(OP_COOKIE_EXCHANGE, 0x2000)
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003195
Hynek Schlawack35618382015-09-05 21:54:25 +02003196 @pytest.mark.skipif(
3197 OP_NO_TICKET is None,
3198 reason="OP_NO_TICKET unavailable - OpenSSL version may be too old"
3199 )
3200 def test_op_no_ticket(self):
3201 """
3202 The value of :py:obj:`OpenSSL.SSL.OP_NO_TICKET` is 0x4000, the value of
3203 :py:const:`SSL_OP_NO_TICKET` defined by :file:`openssl/ssl.h`.
3204 """
3205 self.assertEqual(OP_NO_TICKET, 0x4000)
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003206
Hynek Schlawack35618382015-09-05 21:54:25 +02003207 @pytest.mark.skipif(
3208 OP_NO_COMPRESSION is None,
3209 reason="OP_NO_COMPRESSION unavailable - OpenSSL version may be too old"
3210 )
3211 def test_op_no_compression(self):
3212 """
3213 The value of :py:obj:`OpenSSL.SSL.OP_NO_COMPRESSION` is 0x20000, the
3214 value of :py:const:`SSL_OP_NO_COMPRESSION` defined by
3215 :file:`openssl/ssl.h`.
3216 """
3217 self.assertEqual(OP_NO_COMPRESSION, 0x20000)
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04003218
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003219 def test_sess_cache_off(self):
3220 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003221 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_OFF` 0x0, the value of
3222 :py:obj:`SSL_SESS_CACHE_OFF` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003223 """
3224 self.assertEqual(0x0, SESS_CACHE_OFF)
3225
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003226 def test_sess_cache_client(self):
3227 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003228 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_CLIENT` 0x1, the value of
3229 :py:obj:`SSL_SESS_CACHE_CLIENT` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003230 """
3231 self.assertEqual(0x1, SESS_CACHE_CLIENT)
3232
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003233 def test_sess_cache_server(self):
3234 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003235 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_SERVER` 0x2, the value of
3236 :py:obj:`SSL_SESS_CACHE_SERVER` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003237 """
3238 self.assertEqual(0x2, SESS_CACHE_SERVER)
3239
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003240 def test_sess_cache_both(self):
3241 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003242 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_BOTH` 0x3, the value of
3243 :py:obj:`SSL_SESS_CACHE_BOTH` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003244 """
3245 self.assertEqual(0x3, SESS_CACHE_BOTH)
3246
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003247 def test_sess_cache_no_auto_clear(self):
3248 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003249 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_AUTO_CLEAR` 0x80, the
3250 value of :py:obj:`SSL_SESS_CACHE_NO_AUTO_CLEAR` defined by
3251 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003252 """
3253 self.assertEqual(0x80, SESS_CACHE_NO_AUTO_CLEAR)
3254
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003255 def test_sess_cache_no_internal_lookup(self):
3256 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003257 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_LOOKUP` 0x100,
3258 the value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL_LOOKUP` defined by
3259 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003260 """
3261 self.assertEqual(0x100, SESS_CACHE_NO_INTERNAL_LOOKUP)
3262
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003263 def test_sess_cache_no_internal_store(self):
3264 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003265 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_STORE` 0x200,
3266 the value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL_STORE` defined by
3267 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003268 """
3269 self.assertEqual(0x200, SESS_CACHE_NO_INTERNAL_STORE)
3270
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003271 def test_sess_cache_no_internal(self):
3272 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003273 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL` 0x300, the
3274 value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL` defined by
3275 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003276 """
3277 self.assertEqual(0x300, SESS_CACHE_NO_INTERNAL)
3278
3279
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003280class MemoryBIOTests(TestCase, _LoopbackMixin):
Rick Deanb71c0d22009-04-01 14:09:23 -05003281 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003282 Tests for :py:obj:`OpenSSL.SSL.Connection` using a memory BIO.
Rick Deanb71c0d22009-04-01 14:09:23 -05003283 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003284 def _server(self, sock):
3285 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003286 Create a new server-side SSL :py:obj:`Connection` object wrapped around
3287 :py:obj:`sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003288 """
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003289 # Create the server side Connection. This is mostly setup boilerplate
3290 # - use TLSv1, use a particular certificate, etc.
3291 server_ctx = Context(TLSv1_METHOD)
Alex Gaynor43307782015-09-04 09:05:45 -04003292 server_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE)
Hynek Schlawack35618382015-09-05 21:54:25 +02003293 server_ctx.set_verify(
3294 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT | VERIFY_CLIENT_ONCE,
3295 verify_cb
3296 )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003297 server_store = server_ctx.get_cert_store()
Hynek Schlawack35618382015-09-05 21:54:25 +02003298 server_ctx.use_privatekey(
3299 load_privatekey(FILETYPE_PEM, server_key_pem))
3300 server_ctx.use_certificate(
3301 load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003302 server_ctx.check_privatekey()
3303 server_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Hynek Schlawack35618382015-09-05 21:54:25 +02003304 # Here the Connection is actually created. If None is passed as the
3305 # 2nd parameter, it indicates a memory BIO should be created.
Rick Deanb1ccd562009-07-09 23:52:39 -05003306 server_conn = Connection(server_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003307 server_conn.set_accept_state()
3308 return server_conn
3309
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003310 def _client(self, sock):
3311 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003312 Create a new client-side SSL :py:obj:`Connection` object wrapped around
3313 :py:obj:`sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003314 """
3315 # Now create the client side Connection. Similar boilerplate to the
3316 # above.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003317 client_ctx = Context(TLSv1_METHOD)
Alex Gaynor43307782015-09-04 09:05:45 -04003318 client_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE)
Hynek Schlawack35618382015-09-05 21:54:25 +02003319 client_ctx.set_verify(
3320 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT | VERIFY_CLIENT_ONCE,
3321 verify_cb
3322 )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003323 client_store = client_ctx.get_cert_store()
Hynek Schlawack35618382015-09-05 21:54:25 +02003324 client_ctx.use_privatekey(
3325 load_privatekey(FILETYPE_PEM, client_key_pem))
3326 client_ctx.use_certificate(
3327 load_certificate(FILETYPE_PEM, client_cert_pem))
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003328 client_ctx.check_privatekey()
3329 client_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05003330 client_conn = Connection(client_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003331 client_conn.set_connect_state()
3332 return client_conn
3333
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003334 def test_memoryConnect(self):
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003335 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003336 Two :py:obj:`Connection`s which use memory BIOs can be manually
3337 connected by reading from the output of each and writing those bytes to
3338 the input of the other and in this way establish a connection and
3339 exchange application-level bytes with each other.
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003340 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003341 server_conn = self._server(None)
3342 client_conn = self._client(None)
Rick Deanb71c0d22009-04-01 14:09:23 -05003343
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003344 # There should be no key or nonces yet.
3345 self.assertIdentical(server_conn.master_key(), None)
3346 self.assertIdentical(server_conn.client_random(), None)
3347 self.assertIdentical(server_conn.server_random(), None)
Rick Deanb71c0d22009-04-01 14:09:23 -05003348
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003349 # First, the handshake needs to happen. We'll deliver bytes back and
3350 # forth between the client and server until neither of them feels like
3351 # speaking any more.
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003352 self.assertIdentical(
3353 self._interactInMemory(client_conn, server_conn), None)
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003354
3355 # Now that the handshake is done, there should be a key and nonces.
3356 self.assertNotIdentical(server_conn.master_key(), None)
3357 self.assertNotIdentical(server_conn.client_random(), None)
3358 self.assertNotIdentical(server_conn.server_random(), None)
Hynek Schlawack35618382015-09-05 21:54:25 +02003359 self.assertEquals(
3360 server_conn.client_random(), client_conn.client_random())
3361 self.assertEquals(
3362 server_conn.server_random(), client_conn.server_random())
3363 self.assertNotEquals(
3364 server_conn.client_random(), server_conn.server_random())
3365 self.assertNotEquals(
3366 client_conn.client_random(), client_conn.server_random())
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003367
3368 # Here are the bytes we'll try to send.
Jean-Paul Calderonea441fdc2010-08-22 21:33:57 -04003369 important_message = b('One if by land, two if by sea.')
Rick Deanb71c0d22009-04-01 14:09:23 -05003370
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003371 server_conn.write(important_message)
3372 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003373 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003374 (client_conn, important_message))
3375
3376 client_conn.write(important_message[::-1])
3377 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003378 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003379 (server_conn, important_message[::-1]))
Rick Deanb71c0d22009-04-01 14:09:23 -05003380
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003381 def test_socketConnect(self):
Rick Deanb1ccd562009-07-09 23:52:39 -05003382 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003383 Just like :py:obj:`test_memoryConnect` but with an actual socket.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003384
Hynek Schlawack35618382015-09-05 21:54:25 +02003385 This is primarily to rule out the memory BIO code as the source of any
3386 problems encountered while passing data over a :py:obj:`Connection` (if
3387 this test fails, there must be a problem outside the memory BIO code,
3388 as no memory BIO is involved here). Even though this isn't a memory
3389 BIO test, it's convenient to have it here.
Rick Deanb1ccd562009-07-09 23:52:39 -05003390 """
Jean-Paul Calderone06c7cc92010-09-24 23:52:00 -04003391 server_conn, client_conn = self._loopback()
Rick Deanb1ccd562009-07-09 23:52:39 -05003392
Jean-Paul Calderonea441fdc2010-08-22 21:33:57 -04003393 important_message = b("Help me Obi Wan Kenobi, you're my only hope.")
Rick Deanb1ccd562009-07-09 23:52:39 -05003394 client_conn.send(important_message)
3395 msg = server_conn.recv(1024)
3396 self.assertEqual(msg, important_message)
3397
3398 # Again in the other direction, just for fun.
3399 important_message = important_message[::-1]
3400 server_conn.send(important_message)
3401 msg = client_conn.recv(1024)
3402 self.assertEqual(msg, important_message)
3403
Jean-Paul Calderonefc4ed0f2009-04-27 11:51:27 -04003404 def test_socketOverridesMemory(self):
Rick Deanb71c0d22009-04-01 14:09:23 -05003405 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003406 Test that :py:obj:`OpenSSL.SSL.bio_read` and
3407 :py:obj:`OpenSSL.SSL.bio_write` don't work on
3408 :py:obj:`OpenSSL.SSL.Connection`() that use sockets.
Rick Deanb71c0d22009-04-01 14:09:23 -05003409 """
3410 context = Context(SSLv3_METHOD)
3411 client = socket()
3412 clientSSL = Connection(context, client)
Alex Gaynor43307782015-09-04 09:05:45 -04003413 self.assertRaises(TypeError, clientSSL.bio_read, 100)
3414 self.assertRaises(TypeError, clientSSL.bio_write, "foo")
Alex Gaynor7e8b61e2015-09-04 13:13:05 -04003415 self.assertRaises(TypeError, clientSSL.bio_shutdown)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003416
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003417 def test_outgoingOverflow(self):
3418 """
3419 If more bytes than can be written to the memory BIO are passed to
Hynek Schlawack35618382015-09-05 21:54:25 +02003420 :py:obj:`Connection.send` at once, the number of bytes which were
3421 written is returned and that many bytes from the beginning of the input
3422 can be read from the other end of the connection.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003423 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003424 server = self._server(None)
3425 client = self._client(None)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003426
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003427 self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003428
3429 size = 2 ** 15
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003430 sent = client.send(b"x" * size)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003431 # Sanity check. We're trying to test what happens when the entire
3432 # input can't be sent. If the entire input was sent, this test is
3433 # meaningless.
3434 self.assertTrue(sent < size)
3435
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003436 receiver, received = self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003437 self.assertIdentical(receiver, server)
3438
3439 # We can rely on all of these bytes being received at once because
3440 # _loopback passes 2 ** 16 to recv - more than 2 ** 15.
3441 self.assertEquals(len(received), sent)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003442
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003443 def test_shutdown(self):
3444 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003445 :py:obj:`Connection.bio_shutdown` signals the end of the data stream
3446 from which the :py:obj:`Connection` reads.
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003447 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003448 server = self._server(None)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003449 server.bio_shutdown()
3450 e = self.assertRaises(Error, server.recv, 1024)
3451 # We don't want WantReadError or ZeroReturnError or anything - it's a
3452 # handshake failure.
3453 self.assertEquals(e.__class__, Error)
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003454
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003455 def test_unexpectedEndOfFile(self):
3456 """
3457 If the connection is lost before an orderly SSL shutdown occurs,
3458 :py:obj:`OpenSSL.SSL.SysCallError` is raised with a message of
3459 "Unexpected EOF".
3460 """
3461 server_conn, client_conn = self._loopback()
3462 client_conn.sock_shutdown(SHUT_RDWR)
3463 exc = self.assertRaises(SysCallError, server_conn.recv, 1024)
3464 self.assertEqual(exc.args, (-1, "Unexpected EOF"))
3465
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003466 def _check_client_ca_list(self, func):
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003467 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003468 Verify the return value of the :py:obj:`get_client_ca_list` method for
3469 server and client connections.
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003470
Jonathan Ballet78b92a22011-07-16 08:07:26 +09003471 :param func: A function which will be called with the server context
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003472 before the client and server are connected to each other. This
3473 function should specify a list of CAs for the server to send to the
3474 client and return that same list. The list will be used to verify
Hynek Schlawack35618382015-09-05 21:54:25 +02003475 that :py:obj:`get_client_ca_list` returns the proper value at
3476 various times.
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003477 """
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003478 server = self._server(None)
3479 client = self._client(None)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003480 self.assertEqual(client.get_client_ca_list(), [])
3481 self.assertEqual(server.get_client_ca_list(), [])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003482 ctx = server.get_context()
3483 expected = func(ctx)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003484 self.assertEqual(client.get_client_ca_list(), [])
3485 self.assertEqual(server.get_client_ca_list(), expected)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003486 self._interactInMemory(client, server)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003487 self.assertEqual(client.get_client_ca_list(), expected)
3488 self.assertEqual(server.get_client_ca_list(), expected)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003489
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003490 def test_set_client_ca_list_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003491 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003492 :py:obj:`Context.set_client_ca_list` raises a :py:obj:`TypeError` if
3493 called with a non-list or a list that contains objects other than
3494 X509Names.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003495 """
3496 ctx = Context(TLSv1_METHOD)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003497 self.assertRaises(TypeError, ctx.set_client_ca_list, "spam")
3498 self.assertRaises(TypeError, ctx.set_client_ca_list, ["spam"])
3499 self.assertIdentical(ctx.set_client_ca_list([]), None)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003500
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003501 def test_set_empty_ca_list(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003502 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003503 If passed an empty list, :py:obj:`Context.set_client_ca_list`
3504 configures the context to send no CA names to the client and, on both
3505 the server and client sides, :py:obj:`Connection.get_client_ca_list`
3506 returns an empty list after the connection is set up.
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003507 """
3508 def no_ca(ctx):
3509 ctx.set_client_ca_list([])
3510 return []
3511 self._check_client_ca_list(no_ca)
3512
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003513 def test_set_one_ca_list(self):
3514 """
3515 If passed a list containing a single X509Name,
Hynek Schlawack35618382015-09-05 21:54:25 +02003516 :py:obj:`Context.set_client_ca_list` configures the context to send
3517 that CA name to the client and, on both the server and client sides,
Jonathan Ballet648875f2011-07-16 14:14:58 +09003518 :py:obj:`Connection.get_client_ca_list` returns a list containing that
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003519 X509Name after the connection is set up.
3520 """
3521 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3522 cadesc = cacert.get_subject()
Hynek Schlawack35618382015-09-05 21:54:25 +02003523
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003524 def single_ca(ctx):
3525 ctx.set_client_ca_list([cadesc])
3526 return [cadesc]
3527 self._check_client_ca_list(single_ca)
3528
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003529 def test_set_multiple_ca_list(self):
3530 """
3531 If passed a list containing multiple X509Name objects,
Hynek Schlawack35618382015-09-05 21:54:25 +02003532 :py:obj:`Context.set_client_ca_list` configures the context to send
3533 those CA names to the client and, on both the server and client sides,
Jonathan Ballet648875f2011-07-16 14:14:58 +09003534 :py:obj:`Connection.get_client_ca_list` returns a list containing those
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003535 X509Names after the connection is set up.
3536 """
3537 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3538 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3539
3540 sedesc = secert.get_subject()
3541 cldesc = clcert.get_subject()
3542
3543 def multiple_ca(ctx):
3544 L = [sedesc, cldesc]
3545 ctx.set_client_ca_list(L)
3546 return L
3547 self._check_client_ca_list(multiple_ca)
3548
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003549 def test_reset_ca_list(self):
3550 """
3551 If called multiple times, only the X509Names passed to the final call
Hynek Schlawack35618382015-09-05 21:54:25 +02003552 of :py:obj:`Context.set_client_ca_list` are used to configure the CA
3553 names sent to the client.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003554 """
3555 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3556 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3557 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3558
3559 cadesc = cacert.get_subject()
3560 sedesc = secert.get_subject()
3561 cldesc = clcert.get_subject()
3562
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003563 def changed_ca(ctx):
3564 ctx.set_client_ca_list([sedesc, cldesc])
3565 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003566 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003567 self._check_client_ca_list(changed_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003568
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003569 def test_mutated_ca_list(self):
3570 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003571 If the list passed to :py:obj:`Context.set_client_ca_list` is mutated
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003572 afterwards, this does not affect the list of CA names sent to the
3573 client.
3574 """
3575 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3576 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3577
3578 cadesc = cacert.get_subject()
3579 sedesc = secert.get_subject()
3580
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003581 def mutated_ca(ctx):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003582 L = [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003583 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003584 L.append(sedesc)
3585 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003586 self._check_client_ca_list(mutated_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003587
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003588 def test_add_client_ca_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003589 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003590 :py:obj:`Context.add_client_ca` raises :py:obj:`TypeError` if called
3591 with a non-X509 object or with a number of arguments other than one.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003592 """
3593 ctx = Context(TLSv1_METHOD)
3594 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003595 self.assertRaises(TypeError, ctx.add_client_ca)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003596 self.assertRaises(TypeError, ctx.add_client_ca, "spam")
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003597 self.assertRaises(TypeError, ctx.add_client_ca, cacert, cacert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003598
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003599 def test_one_add_client_ca(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003600 """
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003601 A certificate's subject can be added as a CA to be sent to the client
Jonathan Ballet648875f2011-07-16 14:14:58 +09003602 with :py:obj:`Context.add_client_ca`.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003603 """
3604 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3605 cadesc = cacert.get_subject()
Hynek Schlawack35618382015-09-05 21:54:25 +02003606
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003607 def single_ca(ctx):
3608 ctx.add_client_ca(cacert)
3609 return [cadesc]
3610 self._check_client_ca_list(single_ca)
3611
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003612 def test_multiple_add_client_ca(self):
3613 """
3614 Multiple CA names can be sent to the client by calling
Jonathan Ballet648875f2011-07-16 14:14:58 +09003615 :py:obj:`Context.add_client_ca` with multiple X509 objects.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003616 """
3617 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3618 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3619
3620 cadesc = cacert.get_subject()
3621 sedesc = secert.get_subject()
3622
3623 def multiple_ca(ctx):
3624 ctx.add_client_ca(cacert)
3625 ctx.add_client_ca(secert)
3626 return [cadesc, sedesc]
3627 self._check_client_ca_list(multiple_ca)
3628
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003629 def test_set_and_add_client_ca(self):
3630 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003631 A call to :py:obj:`Context.set_client_ca_list` followed by a call to
Hynek Schlawack35618382015-09-05 21:54:25 +02003632 :py:obj:`Context.add_client_ca` results in using the CA names from the
3633 first call and the CA name from the second call.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003634 """
3635 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3636 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3637 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3638
3639 cadesc = cacert.get_subject()
3640 sedesc = secert.get_subject()
3641 cldesc = clcert.get_subject()
3642
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003643 def mixed_set_add_ca(ctx):
3644 ctx.set_client_ca_list([cadesc, sedesc])
3645 ctx.add_client_ca(clcert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003646 return [cadesc, sedesc, cldesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003647 self._check_client_ca_list(mixed_set_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003648
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003649 def test_set_after_add_client_ca(self):
3650 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003651 A call to :py:obj:`Context.set_client_ca_list` after a call to
Hynek Schlawack35618382015-09-05 21:54:25 +02003652 :py:obj:`Context.add_client_ca` replaces the CA name specified by the
3653 former call with the names specified by the latter call.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003654 """
3655 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3656 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3657 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3658
3659 cadesc = cacert.get_subject()
3660 sedesc = secert.get_subject()
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003661
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003662 def set_replaces_add_ca(ctx):
3663 ctx.add_client_ca(clcert)
3664 ctx.set_client_ca_list([cadesc])
3665 ctx.add_client_ca(secert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003666 return [cadesc, sedesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003667 self._check_client_ca_list(set_replaces_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003668
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003669
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003670class ConnectionBIOTests(TestCase):
3671 """
3672 Tests for :py:obj:`Connection.bio_read` and :py:obj:`Connection.bio_write`.
3673 """
3674 def test_wantReadError(self):
3675 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003676 :py:obj:`Connection.bio_read` raises
3677 :py:obj:`OpenSSL.SSL.WantReadError` if there are no bytes available to
3678 be read from the BIO.
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003679 """
3680 ctx = Context(TLSv1_METHOD)
3681 conn = Connection(ctx, None)
3682 self.assertRaises(WantReadError, conn.bio_read, 1024)
3683
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003684 def test_buffer_size(self):
3685 """
3686 :py:obj:`Connection.bio_read` accepts an integer giving the maximum
3687 number of bytes to read and return.
3688 """
3689 ctx = Context(TLSv1_METHOD)
3690 conn = Connection(ctx, None)
3691 conn.set_connect_state()
3692 try:
3693 conn.do_handshake()
3694 except WantReadError:
3695 pass
3696 data = conn.bio_read(2)
3697 self.assertEqual(2, len(data))
3698
Hynek Schlawack35618382015-09-05 21:54:25 +02003699 @skip_if_py3
3700 def test_buffer_size_long(self):
3701 """
3702 On Python 2 :py:obj:`Connection.bio_read` accepts values of type
3703 :py:obj:`long` as well as :py:obj:`int`.
3704 """
3705 ctx = Context(TLSv1_METHOD)
3706 conn = Connection(ctx, None)
3707 conn.set_connect_state()
3708 try:
3709 conn.do_handshake()
3710 except WantReadError:
3711 pass
3712 data = conn.bio_read(long(2))
3713 self.assertEqual(2, len(data))
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003714
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003715
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003716class InfoConstantTests(TestCase):
3717 """
3718 Tests for assorted constants exposed for use in info callbacks.
3719 """
3720 def test_integers(self):
3721 """
3722 All of the info constants are integers.
3723
3724 This is a very weak test. It would be nice to have one that actually
3725 verifies that as certain info events happen, the value passed to the
3726 info callback matches up with the constant exposed by OpenSSL.SSL.
3727 """
3728 for const in [
3729 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK, SSL_ST_INIT,
3730 SSL_ST_BEFORE, SSL_ST_OK, SSL_ST_RENEGOTIATE,
3731 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
3732 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
3733 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
Hynek Schlawack35618382015-09-05 21:54:25 +02003734 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE
3735 ]:
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003736 self.assertTrue(isinstance(const, int))
3737
Ziga Seilnacht44611bf2009-08-31 20:49:30 +02003738
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003739if __name__ == '__main__':
3740 main()