blob: e0a720bf5e446cf73fc92a2033368c2e2247a66b [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
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01008import datetime
9import uuid
10
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -050011from gc import collect, get_referrers
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +020012from errno import ECONNREFUSED, EINPROGRESS, EWOULDBLOCK, EPIPE, ESHUTDOWN
Hynek Schlawackf8979a52015-09-05 21:25:25 +020013from sys import platform, getfilesystemencoding, version_info
Maximilian Hils1d95dea2015-08-17 19:27:20 +020014from socket import MSG_PEEK, SHUT_RDWR, error, socket
Jean-Paul Calderonea65cf6c2009-07-19 10:26:52 -040015from os import makedirs
Jean-Paul Calderone1461c492013-10-03 16:05:00 -040016from os.path import join
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -040017from weakref import ref
Abraham Martinef063482015-03-25 14:06:24 +000018from warnings import catch_warnings, simplefilter
Jean-Paul Calderone460cc1f2009-03-07 11:31:12 -050019
Hynek Schlawack734d3022015-09-05 19:19:32 +020020import pytest
21
Hynek Schlawackf90e3682016-03-11 11:21:13 +010022from six import PY3, text_type
Jean-Paul Calderonec76c61c2014-01-18 13:21:52 -050023
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +010024from cryptography import x509
25from cryptography.hazmat.backends import default_backend
26from cryptography.hazmat.primitives import hashes
27from cryptography.hazmat.primitives import serialization
28from cryptography.hazmat.primitives.asymmetric import rsa
29from cryptography.x509.oid import NameOID
30
31
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040032from OpenSSL.crypto import TYPE_RSA, FILETYPE_PEM
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -080033from OpenSSL.crypto import PKey, X509, X509Extension, X509Store
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040034from OpenSSL.crypto import dump_privatekey, load_privatekey
35from OpenSSL.crypto import dump_certificate, load_certificate
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -040036from OpenSSL.crypto import get_elliptic_curves
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040037
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -040038from OpenSSL.SSL import OPENSSL_VERSION_NUMBER, SSLEAY_VERSION, SSLEAY_CFLAGS
39from OpenSSL.SSL import SSLEAY_PLATFORM, SSLEAY_DIR, SSLEAY_BUILT_ON
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -040040from OpenSSL.SSL import SENT_SHUTDOWN, RECEIVED_SHUTDOWN
Jean-Paul Calderone1461c492013-10-03 16:05:00 -040041from OpenSSL.SSL import (
42 SSLv2_METHOD, SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD,
43 TLSv1_1_METHOD, TLSv1_2_METHOD)
44from OpenSSL.SSL import OP_SINGLE_DH_USE, OP_NO_SSLv2, OP_NO_SSLv3
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040045from OpenSSL.SSL import (
46 VERIFY_PEER, VERIFY_FAIL_IF_NO_PEER_CERT, VERIFY_CLIENT_ONCE, VERIFY_NONE)
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040047
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040048from OpenSSL.SSL import (
Jean-Paul Calderone313bf012012-02-08 13:02:49 -050049 SESS_CACHE_OFF, SESS_CACHE_CLIENT, SESS_CACHE_SERVER, SESS_CACHE_BOTH,
50 SESS_CACHE_NO_AUTO_CLEAR, SESS_CACHE_NO_INTERNAL_LOOKUP,
51 SESS_CACHE_NO_INTERNAL_STORE, SESS_CACHE_NO_INTERNAL)
52
53from OpenSSL.SSL import (
Jean-Paul Calderoned899af02013-03-19 22:10:37 -070054 Error, SysCallError, WantReadError, WantWriteError, ZeroReturnError)
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -050055from OpenSSL.SSL import (
Jean-Paul Calderoned899af02013-03-19 22:10:37 -070056 Context, ContextType, Session, Connection, ConnectionType, SSLeay_version)
Cory Benfield0ba57ec2016-03-30 09:35:05 +010057from OpenSSL.SSL import _make_requires
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040058
Cory Benfieldba1820d2015-04-13 17:39:12 -040059from OpenSSL._util import lib as _lib
60
Alex Gaynord3b5d9b2016-07-31 10:54:24 -040061from OpenSSL.SSL import (
62 OP_NO_QUERY_MTU, OP_COOKIE_EXCHANGE, OP_NO_TICKET, OP_NO_COMPRESSION,
63 MODE_RELEASE_BUFFERS)
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040064
Jean-Paul Calderone1461c492013-10-03 16:05:00 -040065try:
66 from OpenSSL.SSL import OP_NO_TLSv1, OP_NO_TLSv1_1, OP_NO_TLSv1_2
67except ImportError:
68 OP_NO_TLSv1 = OP_NO_TLSv1_1 = OP_NO_TLSv1_2 = None
69
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -040070from OpenSSL.SSL import (
Alex Gaynor5af32d02016-09-24 01:52:21 -040071 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK,
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -040072 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
73 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
74 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
75 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE)
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -040076
Alex Gaynor5af32d02016-09-24 01:52:21 -040077try:
78 from OpenSSL.SSL import (
79 SSL_ST_INIT, SSL_ST_BEFORE, SSL_ST_OK, SSL_ST_RENEGOTIATE
80 )
81except ImportError:
82 SSL_ST_INIT = SSL_ST_BEFORE = SSL_ST_OK = SSL_ST_RENEGOTIATE = None
83
Alex Chan532b79e2017-01-24 15:14:52 +000084from .util import (
85 WARNING_TYPE_EXPECTED, NON_ASCII, TestCase, is_consistent_type)
Hynek Schlawackf0e66852015-10-16 20:18:38 +020086from .test_crypto import (
87 cleartextCertificatePEM, cleartextPrivateKeyPEM,
88 client_cert_pem, client_key_pem, server_cert_pem, server_key_pem,
89 root_cert_pem)
90
Hynek Schlawackde00dd52015-09-05 19:09:26 +020091
Alex Gaynord0bdd2d2016-09-10 14:23:46 -040092# openssl dhparam 1024 -out dh-1024.pem (note that 1024 is a small number of
93# bits to use)
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -040094dhparam = """\
95-----BEGIN DH PARAMETERS-----
Alex Gaynord0bdd2d2016-09-10 14:23:46 -040096MIGHAoGBALdUMvn+C9MM+y5BWZs11mSeH6HHoEq0UVbzVq7UojC1hbsZUuGukQ3a
97Qh2/pwqb18BZFykrWB0zv/OkLa0kx4cuUgNrUVq1EFheBiX6YqryJ7t2sO09NQiO
98V7H54LmltOT/hEh6QWsJqb6BQgH65bswvV/XkYGja8/T0GzvbaVzAgEC
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -040099-----END DH PARAMETERS-----
100"""
101
102
Hynek Schlawackb4f02402015-09-05 20:48:34 +0200103skip_if_py3 = pytest.mark.skipif(PY3, reason="Python 2 only")
Hynek Schlawackf8979a52015-09-05 21:25:25 +0200104skip_if_py26 = pytest.mark.skipif(
105 version_info[0:2] == (2, 6),
106 reason="Python 2.7 and later only"
107)
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200108
109
Jean-Paul Calderone05826732015-04-12 11:38:49 -0400110def join_bytes_or_unicode(prefix, suffix):
111 """
112 Join two path components of either ``bytes`` or ``unicode``.
113
114 The return type is the same as the type of ``prefix``.
115 """
116 # If the types are the same, nothing special is necessary.
117 if type(prefix) == type(suffix):
118 return join(prefix, suffix)
119
120 # Otherwise, coerce suffix to the type of prefix.
121 if isinstance(prefix, text_type):
122 return join(prefix, suffix.decode(getfilesystemencoding()))
123 else:
124 return join(prefix, suffix.encode(getfilesystemencoding()))
125
126
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400127def verify_cb(conn, cert, errnum, depth, ok):
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400128 return ok
129
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400130
Rick Deanb1ccd562009-07-09 23:52:39 -0500131def socket_pair():
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400132 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400133 Establish and return a pair of network sockets connected to each other.
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400134 """
135 # Connect a pair of sockets
Rick Deanb1ccd562009-07-09 23:52:39 -0500136 port = socket()
137 port.bind(('', 0))
138 port.listen(1)
139 client = socket()
140 client.setblocking(False)
Jean-Paul Calderonef23c5d92009-07-23 17:58:15 -0400141 client.connect_ex(("127.0.0.1", port.getsockname()[1]))
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400142 client.setblocking(True)
Rick Deanb1ccd562009-07-09 23:52:39 -0500143 server = port.accept()[0]
Rick Deanb1ccd562009-07-09 23:52:39 -0500144
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400145 # Let's pass some unencrypted data to make sure our socket connection is
146 # fine. Just one byte, so we don't have to worry about buffers getting
147 # filled up or fragmentation.
Alex Gaynore7f51982016-09-11 11:48:14 -0400148 server.send(b"x")
149 assert client.recv(1024) == b"x"
150 client.send(b"y")
151 assert server.recv(1024) == b"y"
Rick Deanb1ccd562009-07-09 23:52:39 -0500152
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -0400153 # Most of our callers want non-blocking sockets, make it easy for them.
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400154 server.setblocking(False)
155 client.setblocking(False)
Jim Shaver46f28912015-05-29 19:32:16 -0400156
Rick Deanb1ccd562009-07-09 23:52:39 -0500157 return (server, client)
158
159
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400160def handshake(client, server):
161 conns = [client, server]
162 while conns:
163 for conn in conns:
164 try:
165 conn.do_handshake()
166 except WantReadError:
167 pass
168 else:
169 conns.remove(conn)
170
171
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400172def _create_certificate_chain():
173 """
174 Construct and return a chain of certificates.
175
176 1. A new self-signed certificate authority certificate (cacert)
177 2. A new intermediate certificate signed by cacert (icert)
178 3. A new server certificate signed by icert (scert)
179 """
Alex Gaynore7f51982016-09-11 11:48:14 -0400180 caext = X509Extension(b'basicConstraints', False, b'CA:true')
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400181
182 # Step 1
183 cakey = PKey()
Alex Gaynor0737a5e2016-09-10 14:35:09 -0400184 cakey.generate_key(TYPE_RSA, 1024)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400185 cacert = X509()
186 cacert.get_subject().commonName = "Authority Certificate"
187 cacert.set_issuer(cacert.get_subject())
188 cacert.set_pubkey(cakey)
Alex Gaynore7f51982016-09-11 11:48:14 -0400189 cacert.set_notBefore(b"20000101000000Z")
190 cacert.set_notAfter(b"20200101000000Z")
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400191 cacert.add_extensions([caext])
192 cacert.set_serial_number(0)
193 cacert.sign(cakey, "sha1")
194
195 # Step 2
196 ikey = PKey()
Alex Gaynor0737a5e2016-09-10 14:35:09 -0400197 ikey.generate_key(TYPE_RSA, 1024)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400198 icert = X509()
199 icert.get_subject().commonName = "Intermediate Certificate"
200 icert.set_issuer(cacert.get_subject())
201 icert.set_pubkey(ikey)
Alex Gaynore7f51982016-09-11 11:48:14 -0400202 icert.set_notBefore(b"20000101000000Z")
203 icert.set_notAfter(b"20200101000000Z")
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400204 icert.add_extensions([caext])
205 icert.set_serial_number(0)
206 icert.sign(cakey, "sha1")
207
208 # Step 3
209 skey = PKey()
Alex Gaynor0737a5e2016-09-10 14:35:09 -0400210 skey.generate_key(TYPE_RSA, 1024)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400211 scert = X509()
212 scert.get_subject().commonName = "Server Certificate"
213 scert.set_issuer(icert.get_subject())
214 scert.set_pubkey(skey)
Alex Gaynore7f51982016-09-11 11:48:14 -0400215 scert.set_notBefore(b"20000101000000Z")
216 scert.set_notAfter(b"20200101000000Z")
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400217 scert.add_extensions([
Alex Gaynore7f51982016-09-11 11:48:14 -0400218 X509Extension(b'basicConstraints', True, b'CA:false')])
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400219 scert.set_serial_number(0)
220 scert.sign(ikey, "sha1")
221
222 return [(cakey, cacert), (ikey, icert), (skey, scert)]
223
224
Alex Chan1ca9e3a2016-11-05 13:01:51 +0000225class _LoopbackMixin(object):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400226 """
227 Helper mixin which defines methods for creating a connected socket pair and
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200228 for forcing two connected SSL sockets to talk to each other via memory
229 BIOs.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400230 """
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500231 def _loopbackClientFactory(self, socket):
232 client = Connection(Context(TLSv1_METHOD), socket)
233 client.set_connect_state()
234 return client
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400235
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500236 def _loopbackServerFactory(self, socket):
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400237 ctx = Context(TLSv1_METHOD)
238 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
239 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500240 server = Connection(ctx, socket)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400241 server.set_accept_state()
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500242 return server
243
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500244 def _loopback(self, serverFactory=None, clientFactory=None):
245 if serverFactory is None:
246 serverFactory = self._loopbackServerFactory
247 if clientFactory is None:
248 clientFactory = self._loopbackClientFactory
249
250 (server, client) = socket_pair()
251 server = serverFactory(server)
252 client = clientFactory(client)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400253
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400254 handshake(client, server)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400255
256 server.setblocking(True)
257 client.setblocking(True)
258 return server, client
259
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400260 def _interactInMemory(self, client_conn, server_conn):
Alex Chan1ca9e3a2016-11-05 13:01:51 +0000261 return interact_in_memory(client_conn, server_conn)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400262
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -0400263 def _handshakeInMemory(self, client_conn, server_conn):
Alex Chan532b79e2017-01-24 15:14:52 +0000264 return handshake_in_memory(client_conn, server_conn)
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -0400265
266
Alex Chan1ca9e3a2016-11-05 13:01:51 +0000267def interact_in_memory(client_conn, server_conn):
268 """
269 Try to read application bytes from each of the two `Connection` objects.
270 Copy bytes back and forth between their send/receive buffers for as long
271 as there is anything to copy. When there is nothing more to copy,
272 return `None`. If one of them actually manages to deliver some application
273 bytes, return a two-tuple of the connection from which the bytes were read
274 and the bytes themselves.
275 """
276 wrote = True
277 while wrote:
278 # Loop until neither side has anything to say
279 wrote = False
280
281 # Copy stuff from each side's send buffer to the other side's
282 # receive buffer.
283 for (read, write) in [(client_conn, server_conn),
284 (server_conn, client_conn)]:
285
286 # Give the side a chance to generate some more bytes, or succeed.
287 try:
288 data = read.recv(2 ** 16)
289 except WantReadError:
290 # It didn't succeed, so we'll hope it generated some output.
291 pass
292 else:
293 # It did succeed, so we'll stop now and let the caller deal
294 # with it.
295 return (read, data)
296
297 while True:
298 # Keep copying as long as there's more stuff there.
299 try:
300 dirty = read.bio_read(4096)
301 except WantReadError:
302 # Okay, nothing more waiting to be sent. Stop
303 # processing this send buffer.
304 break
305 else:
306 # Keep track of the fact that someone generated some
307 # output.
308 wrote = True
309 write.bio_write(dirty)
310
311
Alex Chan532b79e2017-01-24 15:14:52 +0000312def handshake_in_memory(client_conn, server_conn):
313 """
314 Perform the TLS handshake between two `Connection` instances connected to
315 each other via memory BIOs.
316 """
317 client_conn.set_connect_state()
318 server_conn.set_accept_state()
319
320 for conn in [client_conn, server_conn]:
321 try:
322 conn.do_handshake()
323 except WantReadError:
324 pass
325
326 interact_in_memory(client_conn, server_conn)
327
328
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400329class VersionTests(TestCase):
330 """
331 Tests for version information exposed by
Jonathan Ballet648875f2011-07-16 14:14:58 +0900332 :py:obj:`OpenSSL.SSL.SSLeay_version` and
333 :py:obj:`OpenSSL.SSL.OPENSSL_VERSION_NUMBER`.
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400334 """
335 def test_OPENSSL_VERSION_NUMBER(self):
336 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900337 :py:obj:`OPENSSL_VERSION_NUMBER` is an integer with status in the low
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400338 byte and the patch, fix, minor, and major versions in the
339 nibbles above that.
340 """
341 self.assertTrue(isinstance(OPENSSL_VERSION_NUMBER, int))
342
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400343 def test_SSLeay_version(self):
344 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900345 :py:obj:`SSLeay_version` takes a version type indicator and returns
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400346 one of a number of version strings based on that indicator.
347 """
348 versions = {}
349 for t in [SSLEAY_VERSION, SSLEAY_CFLAGS, SSLEAY_BUILT_ON,
350 SSLEAY_PLATFORM, SSLEAY_DIR]:
351 version = SSLeay_version(t)
352 versions[version] = t
353 self.assertTrue(isinstance(version, bytes))
354 self.assertEqual(len(versions), 5)
355
356
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100357@pytest.fixture
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100358def ca_file(tmpdir):
359 """
360 Create a valid PEM file with CA certificates and return the path.
361 """
362 key = rsa.generate_private_key(
363 public_exponent=65537,
364 key_size=2048,
365 backend=default_backend()
366 )
367 public_key = key.public_key()
368
369 builder = x509.CertificateBuilder()
370 builder = builder.subject_name(x509.Name([
371 x509.NameAttribute(NameOID.COMMON_NAME, u"pyopenssl.org"),
372 ]))
373 builder = builder.issuer_name(x509.Name([
374 x509.NameAttribute(NameOID.COMMON_NAME, u"pyopenssl.org"),
375 ]))
376 one_day = datetime.timedelta(1, 0, 0)
377 builder = builder.not_valid_before(datetime.datetime.today() - one_day)
378 builder = builder.not_valid_after(datetime.datetime.today() + one_day)
379 builder = builder.serial_number(int(uuid.uuid4()))
380 builder = builder.public_key(public_key)
381 builder = builder.add_extension(
382 x509.BasicConstraints(ca=True, path_length=None), critical=True,
383 )
384
385 certificate = builder.sign(
386 private_key=key, algorithm=hashes.SHA256(),
387 backend=default_backend()
388 )
389
390 ca_file = tmpdir.join("test.pem")
391 ca_file.write_binary(
392 certificate.public_bytes(
393 encoding=serialization.Encoding.PEM,
394 )
395 )
396
397 return str(ca_file).encode("ascii")
398
399
400@pytest.fixture
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100401def context():
402 """
403 A simple TLS 1.0 context.
404 """
405 return Context(TLSv1_METHOD)
406
407
408class TestContext(object):
Hynek Schlawackaa861212016-03-13 13:53:48 +0100409 """
Alex Chan532b79e2017-01-24 15:14:52 +0000410 Unit tests for `OpenSSL.SSL.Context`.
Hynek Schlawackaa861212016-03-13 13:53:48 +0100411 """
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100412 @pytest.mark.parametrize("cipher_string", [
413 b"hello world:AES128-SHA",
414 u"hello world:AES128-SHA",
415 ])
416 def test_set_cipher_list(self, context, cipher_string):
417 """
Alex Chan532b79e2017-01-24 15:14:52 +0000418 `Context.set_cipher_list` accepts both byte and unicode strings
Hynek Schlawacka7a63af2016-03-11 12:05:26 +0100419 for naming the ciphers which connections created with the context
420 object will be able to choose from.
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100421 """
422 context.set_cipher_list(cipher_string)
423 conn = Connection(context, None)
424
425 assert "AES128-SHA" in conn.get_cipher_list()
426
427 @pytest.mark.parametrize("cipher_list,error", [
428 (object(), TypeError),
429 ("imaginary-cipher", Error),
430 ])
431 def test_set_cipher_list_wrong_args(self, context, cipher_list, error):
432 """
Alex Chan532b79e2017-01-24 15:14:52 +0000433 `Context.set_cipher_list` raises `TypeError` when passed a non-string
434 argument and raises `OpenSSL.SSL.Error` when passed an incorrect cipher
435 list string.
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100436 """
437 with pytest.raises(error):
438 context.set_cipher_list(cipher_list)
439
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100440 def test_load_client_ca(self, context, ca_file):
441 """
Alex Chan532b79e2017-01-24 15:14:52 +0000442 `Context.load_client_ca` works as far as we can tell.
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100443 """
444 context.load_client_ca(ca_file)
445
446 def test_load_client_ca_invalid(self, context, tmpdir):
447 """
Alex Chan532b79e2017-01-24 15:14:52 +0000448 `Context.load_client_ca` raises an Error if the ca file is invalid.
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100449 """
450 ca_file = tmpdir.join("test.pem")
451 ca_file.write("")
452
453 with pytest.raises(Error) as e:
454 context.load_client_ca(str(ca_file).encode("ascii"))
455
456 assert "PEM routines" == e.value.args[0][0][0]
457
458 def test_load_client_ca_unicode(self, context, ca_file):
459 """
460 Passing the path as unicode raises a warning but works.
461 """
462 pytest.deprecated_call(
463 context.load_client_ca, ca_file.decode("ascii")
464 )
465
466 def test_set_session_id(self, context):
467 """
Alex Chan532b79e2017-01-24 15:14:52 +0000468 `Context.set_session_id` works as far as we can tell.
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100469 """
470 context.set_session_id(b"abc")
471
472 def test_set_session_id_fail(self, context):
473 """
Alex Chan532b79e2017-01-24 15:14:52 +0000474 `Context.set_session_id` errors are propagated.
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100475 """
476 with pytest.raises(Error) as e:
477 context.set_session_id(b"abc" * 1000)
478
479 assert [
480 ("SSL routines",
481 "SSL_CTX_set_session_id_context",
482 "ssl session id context too long")
483 ] == e.value.args[0]
484
485 def test_set_session_id_unicode(self, context):
486 """
Alex Chan532b79e2017-01-24 15:14:52 +0000487 `Context.set_session_id` raises a warning if a unicode string is
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100488 passed.
489 """
490 pytest.deprecated_call(context.set_session_id, u"abc")
491
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400492 def test_method(self):
493 """
Alex Chan532b79e2017-01-24 15:14:52 +0000494 `Context` can be instantiated with one of `SSLv2_METHOD`,
495 `SSLv3_METHOD`, `SSLv23_METHOD`, `TLSv1_METHOD`, `TLSv1_1_METHOD`,
496 or `TLSv1_2_METHOD`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400497 """
Alex Gaynor5af32d02016-09-24 01:52:21 -0400498 methods = [SSLv23_METHOD, TLSv1_METHOD]
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400499 for meth in methods:
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400500 Context(meth)
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400501
Alex Gaynor5af32d02016-09-24 01:52:21 -0400502 maybe = [SSLv2_METHOD, SSLv3_METHOD, TLSv1_1_METHOD, TLSv1_2_METHOD]
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400503 for meth in maybe:
504 try:
505 Context(meth)
506 except (Error, ValueError):
507 # Some versions of OpenSSL have SSLv2 / TLSv1.1 / TLSv1.2, some
508 # don't. Difficult to say in advance.
509 pass
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400510
Alex Chan532b79e2017-01-24 15:14:52 +0000511 with pytest.raises(TypeError):
512 Context("")
513 with pytest.raises(ValueError):
514 Context(10)
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400515
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200516 @skip_if_py3
517 def test_method_long(self):
518 """
Alex Chan532b79e2017-01-24 15:14:52 +0000519 On Python 2 `Context` accepts values of type `long` as well as `int`.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200520 """
521 Context(long(TLSv1_METHOD))
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500522
Rick Deane15b1472009-07-09 15:53:42 -0500523 def test_type(self):
524 """
Alex Chan532b79e2017-01-24 15:14:52 +0000525 `Context` and `ContextType` refer to the same type object and can
526 be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -0500527 """
Alex Chan532b79e2017-01-24 15:14:52 +0000528 assert Context is ContextType
529 assert is_consistent_type(Context, 'Context', TLSv1_METHOD)
Rick Deane15b1472009-07-09 15:53:42 -0500530
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400531 def test_use_privatekey(self):
532 """
Alex Chan532b79e2017-01-24 15:14:52 +0000533 `Context.use_privatekey` takes an `OpenSSL.crypto.PKey` instance.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400534 """
535 key = PKey()
536 key.generate_key(TYPE_RSA, 128)
537 ctx = Context(TLSv1_METHOD)
538 ctx.use_privatekey(key)
Alex Chan532b79e2017-01-24 15:14:52 +0000539 with pytest.raises(TypeError):
540 ctx.use_privatekey("")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400541
Alex Chan532b79e2017-01-24 15:14:52 +0000542 def test_use_privatekey_file_missing(self, tmpfile):
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800543 """
Alex Chan532b79e2017-01-24 15:14:52 +0000544 `Context.use_privatekey_file` raises `OpenSSL.SSL.Error` when passed
545 the name of a file which does not exist.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800546 """
547 ctx = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000548 with pytest.raises(Error):
549 ctx.use_privatekey_file(tmpfile)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800550
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400551 def _use_privatekey_file_test(self, pemfile, filetype):
552 """
553 Verify that calling ``Context.use_privatekey_file`` with the given
554 arguments does not raise an exception.
555 """
556 key = PKey()
557 key.generate_key(TYPE_RSA, 128)
558
559 with open(pemfile, "wt") as pem:
560 pem.write(
561 dump_privatekey(FILETYPE_PEM, key).decode("ascii")
562 )
563
564 ctx = Context(TLSv1_METHOD)
565 ctx.use_privatekey_file(pemfile, filetype)
566
Alex Chan532b79e2017-01-24 15:14:52 +0000567 def test_use_privatekey_file_bytes(self, tmpfile):
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400568 """
569 A private key can be specified from a file by passing a ``bytes``
570 instance giving the file name to ``Context.use_privatekey_file``.
571 """
572 self._use_privatekey_file_test(
Alex Chan532b79e2017-01-24 15:14:52 +0000573 tmpfile + NON_ASCII.encode(getfilesystemencoding()),
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400574 FILETYPE_PEM,
575 )
576
Alex Chan532b79e2017-01-24 15:14:52 +0000577 def test_use_privatekey_file_unicode(self, tmpfile):
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400578 """
579 A private key can be specified from a file by passing a ``unicode``
580 instance giving the file name to ``Context.use_privatekey_file``.
581 """
582 self._use_privatekey_file_test(
Alex Chan532b79e2017-01-24 15:14:52 +0000583 tmpfile.decode(getfilesystemencoding()) + NON_ASCII,
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400584 FILETYPE_PEM,
585 )
586
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200587 @skip_if_py3
Alex Chan532b79e2017-01-24 15:14:52 +0000588 def test_use_privatekey_file_long(self, tmpfile):
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200589 """
Alex Chan532b79e2017-01-24 15:14:52 +0000590 On Python 2 `Context.use_privatekey_file` accepts a filetype of
591 type `long` as well as `int`.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200592 """
Alex Chan532b79e2017-01-24 15:14:52 +0000593 self._use_privatekey_file_test(tmpfile, long(FILETYPE_PEM))
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500594
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800595 def test_use_certificate_wrong_args(self):
596 """
Alex Chan532b79e2017-01-24 15:14:52 +0000597 `Context.use_certificate_wrong_args` raises `TypeError` when not passed
598 exactly one `OpenSSL.crypto.X509` instance as an argument.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800599 """
600 ctx = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000601 with pytest.raises(TypeError):
602 ctx.use_certificate("hello, world")
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800603
604 def test_use_certificate_uninitialized(self):
605 """
Alex Chan532b79e2017-01-24 15:14:52 +0000606 `Context.use_certificate` raises `OpenSSL.SSL.Error` when passed a
607 `OpenSSL.crypto.X509` instance which has not been initialized
608 (ie, which does not actually have any certificate data).
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800609 """
610 ctx = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000611 with pytest.raises(Error):
612 ctx.use_certificate(X509())
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800613
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800614 def test_use_certificate(self):
615 """
Alex Chan532b79e2017-01-24 15:14:52 +0000616 `Context.use_certificate` sets the certificate which will be
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800617 used to identify connections created using the context.
618 """
619 # TODO
620 # Hard to assert anything. But we could set a privatekey then ask
621 # OpenSSL if the cert and key agree using check_privatekey. Then as
622 # long as check_privatekey works right we're good...
623 ctx = Context(TLSv1_METHOD)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200624 ctx.use_certificate(
625 load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
626 )
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800627
628 def test_use_certificate_file_wrong_args(self):
629 """
Alex Chan532b79e2017-01-24 15:14:52 +0000630 `Context.use_certificate_file` raises `TypeError` if the first
631 argument is not a byte string or the second argument is not an integer.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800632 """
633 ctx = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000634 with pytest.raises(TypeError):
635 ctx.use_certificate_file(object(), FILETYPE_PEM)
636 with pytest.raises(TypeError):
637 ctx.use_certificate_file(b"somefile", object())
638 with pytest.raises(TypeError):
639 ctx.use_certificate_file(object(), FILETYPE_PEM)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800640
Alex Chan532b79e2017-01-24 15:14:52 +0000641 def test_use_certificate_file_missing(self, tmpfile):
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800642 """
Alex Chan532b79e2017-01-24 15:14:52 +0000643 `Context.use_certificate_file` raises `OpenSSL.SSL.Error` if passed
644 the name of a file which does not exist.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800645 """
646 ctx = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000647 with pytest.raises(Error):
648 ctx.use_certificate_file(tmpfile)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800649
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400650 def _use_certificate_file_test(self, certificate_file):
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800651 """
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400652 Verify that calling ``Context.use_certificate_file`` with the given
653 filename doesn't raise an exception.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800654 """
655 # TODO
656 # Hard to assert anything. But we could set a privatekey then ask
657 # OpenSSL if the cert and key agree using check_privatekey. Then as
658 # long as check_privatekey works right we're good...
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400659 with open(certificate_file, "wb") as pem_file:
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800660 pem_file.write(cleartextCertificatePEM)
661
662 ctx = Context(TLSv1_METHOD)
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400663 ctx.use_certificate_file(certificate_file)
664
Alex Chan532b79e2017-01-24 15:14:52 +0000665 def test_use_certificate_file_bytes(self, tmpfile):
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400666 """
Alex Chan532b79e2017-01-24 15:14:52 +0000667 `Context.use_certificate_file` sets the certificate (given as a
668 `bytes` filename) which will be used to identify connections created
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400669 using the context.
670 """
Alex Chan532b79e2017-01-24 15:14:52 +0000671 filename = tmpfile + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400672 self._use_certificate_file_test(filename)
673
Alex Chan532b79e2017-01-24 15:14:52 +0000674 def test_use_certificate_file_unicode(self, tmpfile):
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400675 """
Alex Chan532b79e2017-01-24 15:14:52 +0000676 `Context.use_certificate_file` sets the certificate (given as a
677 `bytes` filename) which will be used to identify connections created
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400678 using the context.
679 """
Alex Chan532b79e2017-01-24 15:14:52 +0000680 filename = tmpfile.decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400681 self._use_certificate_file_test(filename)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800682
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200683 @skip_if_py3
Alex Chan532b79e2017-01-24 15:14:52 +0000684 def test_use_certificate_file_long(self, tmpfile):
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200685 """
Alex Chan532b79e2017-01-24 15:14:52 +0000686 On Python 2 `Context.use_certificate_file` accepts a
687 filetype of type `long` as well as `int`.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200688 """
Alex Chan532b79e2017-01-24 15:14:52 +0000689 pem_filename = tmpfile
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200690 with open(pem_filename, "wb") as pem_file:
691 pem_file.write(cleartextCertificatePEM)
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500692
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200693 ctx = Context(TLSv1_METHOD)
694 ctx.use_certificate_file(pem_filename, long(FILETYPE_PEM))
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500695
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500696 def test_check_privatekey_valid(self):
697 """
Alex Chan532b79e2017-01-24 15:14:52 +0000698 `Context.check_privatekey` returns `None` if the `Context` instance
699 has been configured to use a matched key and certificate pair.
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500700 """
701 key = load_privatekey(FILETYPE_PEM, client_key_pem)
702 cert = load_certificate(FILETYPE_PEM, client_cert_pem)
703 context = Context(TLSv1_METHOD)
704 context.use_privatekey(key)
705 context.use_certificate(cert)
Alex Chan532b79e2017-01-24 15:14:52 +0000706 assert None is context.check_privatekey()
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500707
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500708 def test_check_privatekey_invalid(self):
709 """
Alex Chan532b79e2017-01-24 15:14:52 +0000710 `Context.check_privatekey` raises `Error` if the `Context` instance
711 has been configured to use a key and certificate pair which don't
712 relate to each other.
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500713 """
714 key = load_privatekey(FILETYPE_PEM, client_key_pem)
715 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
716 context = Context(TLSv1_METHOD)
717 context.use_privatekey(key)
718 context.use_certificate(cert)
Alex Chan532b79e2017-01-24 15:14:52 +0000719 with pytest.raises(Error):
720 context.check_privatekey()
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400721
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400722 def test_app_data(self):
723 """
Alex Chan532b79e2017-01-24 15:14:52 +0000724 `Context.set_app_data` stores an object for later retrieval
725 using `Context.get_app_data`.
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400726 """
727 app_data = object()
728 context = Context(TLSv1_METHOD)
729 context.set_app_data(app_data)
Alex Chan532b79e2017-01-24 15:14:52 +0000730 assert context.get_app_data() is app_data
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400731
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400732 def test_set_options_wrong_args(self):
733 """
Alex Chan532b79e2017-01-24 15:14:52 +0000734 `Context.set_options` raises `TypeError` if called with
735 a non-`int` argument.
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400736 """
737 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000738 with pytest.raises(TypeError):
739 context.set_options(None)
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400740
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500741 def test_set_options(self):
742 """
Alex Chan532b79e2017-01-24 15:14:52 +0000743 `Context.set_options` returns the new options value.
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500744 """
745 context = Context(TLSv1_METHOD)
746 options = context.set_options(OP_NO_SSLv2)
Alex Gaynor2310f8b2016-09-10 14:39:32 -0400747 assert options & OP_NO_SSLv2 == OP_NO_SSLv2
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500748
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200749 @skip_if_py3
750 def test_set_options_long(self):
751 """
Alex Chan532b79e2017-01-24 15:14:52 +0000752 On Python 2 `Context.set_options` accepts values of type
753 `long` as well as `int`.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200754 """
755 context = Context(TLSv1_METHOD)
756 options = context.set_options(long(OP_NO_SSLv2))
Alex Gaynor2310f8b2016-09-10 14:39:32 -0400757 assert options & OP_NO_SSLv2 == OP_NO_SSLv2
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500758
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300759 def test_set_mode_wrong_args(self):
760 """
Alex Chan532b79e2017-01-24 15:14:52 +0000761 `Context.set_mode` raises `TypeError` if called with
762 a non-`int` argument.
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300763 """
764 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000765 with pytest.raises(TypeError):
766 context.set_mode(None)
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300767
Alex Gaynord3b5d9b2016-07-31 10:54:24 -0400768 def test_set_mode(self):
769 """
Alex Chan532b79e2017-01-24 15:14:52 +0000770 `Context.set_mode` accepts a mode bitvector and returns the
Alex Gaynord3b5d9b2016-07-31 10:54:24 -0400771 newly set mode.
772 """
773 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000774 assert MODE_RELEASE_BUFFERS & context.set_mode(MODE_RELEASE_BUFFERS)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500775
Alex Gaynord3b5d9b2016-07-31 10:54:24 -0400776 @skip_if_py3
777 def test_set_mode_long(self):
778 """
Alex Chan532b79e2017-01-24 15:14:52 +0000779 On Python 2 `Context.set_mode` accepts values of type `long` as well
780 as `int`.
Alex Gaynord3b5d9b2016-07-31 10:54:24 -0400781 """
782 context = Context(TLSv1_METHOD)
783 mode = context.set_mode(long(MODE_RELEASE_BUFFERS))
Alex Chan532b79e2017-01-24 15:14:52 +0000784 assert MODE_RELEASE_BUFFERS & mode
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400785
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400786 def test_set_timeout_wrong_args(self):
787 """
Alex Chan532b79e2017-01-24 15:14:52 +0000788 `Context.set_timeout` raises `TypeError` if called with
789 a non-`int` argument.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400790 """
791 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000792 with pytest.raises(TypeError):
793 context.set_timeout(None)
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400794
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400795 def test_timeout(self):
796 """
Alex Chan532b79e2017-01-24 15:14:52 +0000797 `Context.set_timeout` sets the session timeout for all connections
798 created using the context object. `Context.get_timeout` retrieves
799 this value.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400800 """
801 context = Context(TLSv1_METHOD)
802 context.set_timeout(1234)
Alex Chan532b79e2017-01-24 15:14:52 +0000803 assert context.get_timeout() == 1234
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400804
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200805 @skip_if_py3
806 def test_timeout_long(self):
807 """
Alex Chan532b79e2017-01-24 15:14:52 +0000808 On Python 2 `Context.set_timeout` accepts values of type `long` as
809 well as int.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200810 """
811 context = Context(TLSv1_METHOD)
812 context.set_timeout(long(1234))
Alex Chan532b79e2017-01-24 15:14:52 +0000813 assert context.get_timeout() == 1234
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500814
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400815 def test_set_verify_depth_wrong_args(self):
816 """
Alex Chan532b79e2017-01-24 15:14:52 +0000817 `Context.set_verify_depth` raises `TypeError` if called with a
818 non-`int` argument.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400819 """
820 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000821 with pytest.raises(TypeError):
822 context.set_verify_depth(None)
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400823
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400824 def test_verify_depth(self):
825 """
Alex Chan532b79e2017-01-24 15:14:52 +0000826 `Context.set_verify_depth` sets the number of certificates in
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200827 a chain to follow before giving up. The value can be retrieved with
Alex Chan532b79e2017-01-24 15:14:52 +0000828 `Context.get_verify_depth`.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400829 """
830 context = Context(TLSv1_METHOD)
831 context.set_verify_depth(11)
Alex Chan532b79e2017-01-24 15:14:52 +0000832 assert context.get_verify_depth() == 11
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400833
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200834 @skip_if_py3
835 def test_verify_depth_long(self):
836 """
Alex Chan532b79e2017-01-24 15:14:52 +0000837 On Python 2 `Context.set_verify_depth` accepts values of type `long`
838 as well as int.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200839 """
840 context = Context(TLSv1_METHOD)
841 context.set_verify_depth(long(11))
Alex Chan532b79e2017-01-24 15:14:52 +0000842 assert context.get_verify_depth() == 11
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500843
Alex Chan532b79e2017-01-24 15:14:52 +0000844 def _write_encrypted_pem(self, passphrase, tmpfile):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400845 """
846 Write a new private key out to a new file, encrypted using the given
847 passphrase. Return the path to the new file.
848 """
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400849 key = PKey()
850 key.generate_key(TYPE_RSA, 128)
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400851 pem = dump_privatekey(FILETYPE_PEM, key, "blowfish", passphrase)
Alex Chan532b79e2017-01-24 15:14:52 +0000852 with open(tmpfile, 'w') as fObj:
853 fObj.write(pem.decode('ascii'))
854 return tmpfile
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400855
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400856 def test_set_passwd_cb_wrong_args(self):
857 """
Alex Chan532b79e2017-01-24 15:14:52 +0000858 `Context.set_passwd_cb` raises `TypeError` if called with a
859 non-callable first argument.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400860 """
861 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000862 with pytest.raises(TypeError):
863 context.set_passwd_cb(None)
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400864
Alex Chan532b79e2017-01-24 15:14:52 +0000865 def test_set_passwd_cb(self, tmpfile):
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400866 """
Alex Chan532b79e2017-01-24 15:14:52 +0000867 `Context.set_passwd_cb` accepts a callable which will be invoked when
868 a private key is loaded from an encrypted PEM.
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400869 """
Alex Gaynore7f51982016-09-11 11:48:14 -0400870 passphrase = b"foobar"
Alex Chan532b79e2017-01-24 15:14:52 +0000871 pemFile = self._write_encrypted_pem(passphrase, tmpfile)
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400872 calledWith = []
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200873
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400874 def passphraseCallback(maxlen, verify, extra):
875 calledWith.append((maxlen, verify, extra))
876 return passphrase
877 context = Context(TLSv1_METHOD)
878 context.set_passwd_cb(passphraseCallback)
879 context.use_privatekey_file(pemFile)
Alex Chan532b79e2017-01-24 15:14:52 +0000880 assert len(calledWith) == 1
881 assert isinstance(calledWith[0][0], int)
882 assert isinstance(calledWith[0][1], int)
883 assert calledWith[0][2] is None
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400884
Alex Chan532b79e2017-01-24 15:14:52 +0000885 def test_passwd_callback_exception(self, tmpfile):
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400886 """
Alex Chan532b79e2017-01-24 15:14:52 +0000887 `Context.use_privatekey_file` propagates any exception raised
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200888 by the passphrase callback.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400889 """
Alex Chan532b79e2017-01-24 15:14:52 +0000890 pemFile = self._write_encrypted_pem(b"monkeys are nice", tmpfile)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200891
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400892 def passphraseCallback(maxlen, verify, extra):
893 raise RuntimeError("Sorry, I am a fail.")
894
895 context = Context(TLSv1_METHOD)
896 context.set_passwd_cb(passphraseCallback)
Alex Chan532b79e2017-01-24 15:14:52 +0000897 with pytest.raises(RuntimeError):
898 context.use_privatekey_file(pemFile)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400899
Alex Chan532b79e2017-01-24 15:14:52 +0000900 def test_passwd_callback_false(self, tmpfile):
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400901 """
Alex Chan532b79e2017-01-24 15:14:52 +0000902 `Context.use_privatekey_file` raises `OpenSSL.SSL.Error` if the
903 passphrase callback returns a false value.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400904 """
Alex Chan532b79e2017-01-24 15:14:52 +0000905 pemFile = self._write_encrypted_pem(b"monkeys are nice", tmpfile)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200906
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400907 def passphraseCallback(maxlen, verify, extra):
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500908 return b""
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400909
910 context = Context(TLSv1_METHOD)
911 context.set_passwd_cb(passphraseCallback)
Alex Chan532b79e2017-01-24 15:14:52 +0000912 with pytest.raises(Error):
913 context.use_privatekey_file(pemFile)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400914
Alex Chan532b79e2017-01-24 15:14:52 +0000915 def test_passwd_callback_non_string(self, tmpfile):
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400916 """
Alex Chan532b79e2017-01-24 15:14:52 +0000917 `Context.use_privatekey_file` raises `OpenSSL.SSL.Error` if the
918 passphrase callback returns a true non-string value.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400919 """
Alex Chan532b79e2017-01-24 15:14:52 +0000920 pemFile = self._write_encrypted_pem(b"monkeys are nice", tmpfile)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200921
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400922 def passphraseCallback(maxlen, verify, extra):
923 return 10
924
925 context = Context(TLSv1_METHOD)
926 context.set_passwd_cb(passphraseCallback)
Alex Chan532b79e2017-01-24 15:14:52 +0000927 # TODO: Surely this is the wrong error?
928 with pytest.raises(ValueError):
929 context.use_privatekey_file(pemFile)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400930
Alex Chan532b79e2017-01-24 15:14:52 +0000931 def test_passwd_callback_too_long(self, tmpfile):
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400932 """
933 If the passphrase returned by the passphrase callback returns a string
934 longer than the indicated maximum length, it is truncated.
935 """
936 # A priori knowledge!
Alex Gaynore7f51982016-09-11 11:48:14 -0400937 passphrase = b"x" * 1024
Alex Chan532b79e2017-01-24 15:14:52 +0000938 pemFile = self._write_encrypted_pem(passphrase, tmpfile)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200939
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400940 def passphraseCallback(maxlen, verify, extra):
941 assert maxlen == 1024
Alex Gaynore7f51982016-09-11 11:48:14 -0400942 return passphrase + b"y"
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400943
944 context = Context(TLSv1_METHOD)
945 context.set_passwd_cb(passphraseCallback)
946 # This shall succeed because the truncated result is the correct
947 # passphrase.
948 context.use_privatekey_file(pemFile)
949
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400950 def test_set_info_callback(self):
951 """
Alex Chan532b79e2017-01-24 15:14:52 +0000952 `Context.set_info_callback` accepts a callable which will be
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200953 invoked when certain information about an SSL connection is available.
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400954 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500955 (server, client) = socket_pair()
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400956
957 clientSSL = Connection(Context(TLSv1_METHOD), client)
958 clientSSL.set_connect_state()
959
960 called = []
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200961
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400962 def info(conn, where, ret):
963 called.append((conn, where, ret))
964 context = Context(TLSv1_METHOD)
965 context.set_info_callback(info)
966 context.use_certificate(
967 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
968 context.use_privatekey(
969 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
970
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400971 serverSSL = Connection(context, server)
972 serverSSL.set_accept_state()
973
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -0500974 handshake(clientSSL, serverSSL)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400975
Jean-Paul Calderone3835e522014-02-02 11:12:30 -0500976 # The callback must always be called with a Connection instance as the
977 # first argument. It would probably be better to split this into
978 # separate tests for client and server side info callbacks so we could
979 # assert it is called with the right Connection instance. It would
980 # also be good to assert *something* about `where` and `ret`.
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -0500981 notConnections = [
982 conn for (conn, where, ret) in called
983 if not isinstance(conn, Connection)]
Alex Chan532b79e2017-01-24 15:14:52 +0000984 assert [] == notConnections, (
985 "Some info callback arguments were not Connection instances.")
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400986
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400987 def _load_verify_locations_test(self, *args):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400988 """
989 Create a client context which will verify the peer certificate and call
Alex Chan532b79e2017-01-24 15:14:52 +0000990 its `load_verify_locations` method with the given arguments.
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -0400991 Then connect it to a server and ensure that the handshake succeeds.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400992 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500993 (server, client) = socket_pair()
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400994
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400995 clientContext = Context(TLSv1_METHOD)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400996 clientContext.load_verify_locations(*args)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400997 # Require that the server certificate verify properly or the
998 # connection will fail.
999 clientContext.set_verify(
1000 VERIFY_PEER,
1001 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
1002
1003 clientSSL = Connection(clientContext, client)
1004 clientSSL.set_connect_state()
1005
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001006 serverContext = Context(TLSv1_METHOD)
1007 serverContext.use_certificate(
1008 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1009 serverContext.use_privatekey(
1010 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1011
1012 serverSSL = Connection(serverContext, server)
1013 serverSSL.set_accept_state()
1014
Jean-Paul Calderonef8742032010-09-25 00:00:32 -04001015 # Without load_verify_locations above, the handshake
1016 # will fail:
1017 # Error: [('SSL routines', 'SSL3_GET_SERVER_CERTIFICATE',
1018 # 'certificate verify failed')]
1019 handshake(clientSSL, serverSSL)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001020
1021 cert = clientSSL.get_peer_certificate()
Alex Chan532b79e2017-01-24 15:14:52 +00001022 assert cert.get_subject().CN == 'Testing Root CA'
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -04001023
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001024 def _load_verify_cafile(self, cafile):
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001025 """
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001026 Verify that if path to a file containing a certificate is passed to
Alex Chan532b79e2017-01-24 15:14:52 +00001027 `Context.load_verify_locations` for the ``cafile`` parameter, that
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001028 certificate is used as a trust root for the purposes of verifying
Alex Chan532b79e2017-01-24 15:14:52 +00001029 connections created using that `Context`.
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001030 """
Alex Chan532b79e2017-01-24 15:14:52 +00001031 with open(cafile, 'w') as fObj:
1032 fObj.write(cleartextCertificatePEM.decode('ascii'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001033
1034 self._load_verify_locations_test(cafile)
1035
Alex Chan532b79e2017-01-24 15:14:52 +00001036 def test_load_verify_bytes_cafile(self, tmpfile):
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001037 """
Alex Chan532b79e2017-01-24 15:14:52 +00001038 `Context.load_verify_locations` accepts a file name as a `bytes`
1039 instance and uses the certificates within for verification purposes.
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001040 """
Alex Chan532b79e2017-01-24 15:14:52 +00001041 cafile = tmpfile + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001042 self._load_verify_cafile(cafile)
1043
Alex Chan532b79e2017-01-24 15:14:52 +00001044 def test_load_verify_unicode_cafile(self, tmpfile):
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001045 """
Alex Chan532b79e2017-01-24 15:14:52 +00001046 `Context.load_verify_locations` accepts a file name as a `unicode`
1047 instance and uses the certificates within for verification purposes.
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001048 """
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001049 self._load_verify_cafile(
Alex Chan532b79e2017-01-24 15:14:52 +00001050 tmpfile.decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001051 )
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001052
Alex Chan532b79e2017-01-24 15:14:52 +00001053 def test_load_verify_invalid_file(self, tmpfile):
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -04001054 """
Alex Chan532b79e2017-01-24 15:14:52 +00001055 `Context.load_verify_locations` raises `Error` when passed a
1056 non-existent cafile.
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -04001057 """
1058 clientContext = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001059 with pytest.raises(Error):
1060 clientContext.load_verify_locations(tmpfile)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001061
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001062 def _load_verify_directory_locations_capath(self, capath):
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001063 """
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001064 Verify that if path to a directory containing certificate files is
1065 passed to ``Context.load_verify_locations`` for the ``capath``
1066 parameter, those certificates are used as trust roots for the purposes
1067 of verifying connections created using that ``Context``.
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001068 """
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001069 makedirs(capath)
Jean-Paul Calderone24dfb332011-05-04 18:10:26 -04001070 # Hash values computed manually with c_rehash to avoid depending on
1071 # c_rehash in the test suite. One is from OpenSSL 0.9.8, the other
1072 # from OpenSSL 1.0.0.
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001073 for name in [b'c7adac82.0', b'c3705638.0']:
Jean-Paul Calderone05826732015-04-12 11:38:49 -04001074 cafile = join_bytes_or_unicode(capath, name)
1075 with open(cafile, 'w') as fObj:
1076 fObj.write(cleartextCertificatePEM.decode('ascii'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001077
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001078 self._load_verify_locations_test(None, capath)
1079
Alex Chan532b79e2017-01-24 15:14:52 +00001080 def test_load_verify_directory_bytes_capath(self, tmpfile):
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001081 """
Alex Chan532b79e2017-01-24 15:14:52 +00001082 `Context.load_verify_locations` accepts a directory name as a `bytes`
1083 instance and uses the certificates within for verification purposes.
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001084 """
1085 self._load_verify_directory_locations_capath(
Alex Chan532b79e2017-01-24 15:14:52 +00001086 tmpfile + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001087 )
1088
Alex Chan532b79e2017-01-24 15:14:52 +00001089 def test_load_verify_directory_unicode_capath(self, tmpfile):
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001090 """
Alex Chan532b79e2017-01-24 15:14:52 +00001091 `Context.load_verify_locations` accepts a directory name as a `unicode`
1092 instance and uses the certificates within for verification purposes.
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001093 """
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001094 self._load_verify_directory_locations_capath(
Alex Chan532b79e2017-01-24 15:14:52 +00001095 tmpfile.decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001096 )
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001097
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001098 def test_load_verify_locations_wrong_args(self):
1099 """
Alex Chan532b79e2017-01-24 15:14:52 +00001100 `Context.load_verify_locations` raises `TypeError` if with non-`str`
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001101 arguments.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001102 """
1103 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001104 with pytest.raises(TypeError):
1105 context.load_verify_locations(object())
1106 with pytest.raises(TypeError):
1107 context.load_verify_locations(object(), object())
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001108
Hynek Schlawack734d3022015-09-05 19:19:32 +02001109 @pytest.mark.skipif(
1110 platform == "win32",
1111 reason="set_default_verify_paths appears not to work on Windows. "
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -04001112 "See LP#404343 and LP#404344."
Hynek Schlawack734d3022015-09-05 19:19:32 +02001113 )
1114 def test_set_default_verify_paths(self):
1115 """
Alex Chan532b79e2017-01-24 15:14:52 +00001116 `Context.set_default_verify_paths` causes the platform-specific CA
1117 certificate locations to be used for verification purposes.
Hynek Schlawack734d3022015-09-05 19:19:32 +02001118 """
1119 # Testing this requires a server with a certificate signed by one
1120 # of the CAs in the platform CA location. Getting one of those
1121 # costs money. Fortunately (or unfortunately, depending on your
1122 # perspective), it's easy to think of a public server on the
1123 # internet which has such a certificate. Connecting to the network
1124 # in a unit test is bad, but it's the only way I can think of to
1125 # really test this. -exarkun
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001126
Hynek Schlawack734d3022015-09-05 19:19:32 +02001127 # Arg, verisign.com doesn't speak anything newer than TLS 1.0
Hynek Schlawackbf887932015-10-21 17:13:47 +02001128 context = Context(SSLv23_METHOD)
Hynek Schlawack734d3022015-09-05 19:19:32 +02001129 context.set_default_verify_paths()
1130 context.set_verify(
1131 VERIFY_PEER,
1132 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001133
Hynek Schlawack734d3022015-09-05 19:19:32 +02001134 client = socket()
Hynek Schlawackbf887932015-10-21 17:13:47 +02001135 client.connect(("encrypted.google.com", 443))
Hynek Schlawack734d3022015-09-05 19:19:32 +02001136 clientSSL = Connection(context, client)
1137 clientSSL.set_connect_state()
1138 clientSSL.do_handshake()
1139 clientSSL.send(b"GET / HTTP/1.0\r\n\r\n")
Alex Chan532b79e2017-01-24 15:14:52 +00001140 assert clientSSL.recv(1024)
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05001141
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001142 def test_add_extra_chain_cert_invalid_cert(self):
1143 """
Alex Chan532b79e2017-01-24 15:14:52 +00001144 `Context.add_extra_chain_cert` raises `TypeError` if called with an
1145 object which is not an instance of `X509`.
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001146 """
1147 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001148 with pytest.raises(TypeError):
1149 context.add_extra_chain_cert(object())
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001150
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001151 def _handshake_test(self, serverContext, clientContext):
1152 """
1153 Verify that a client and server created with the given contexts can
1154 successfully handshake and communicate.
1155 """
1156 serverSocket, clientSocket = socket_pair()
1157
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001158 server = Connection(serverContext, serverSocket)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001159 server.set_accept_state()
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001160
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001161 client = Connection(clientContext, clientSocket)
1162 client.set_connect_state()
1163
1164 # Make them talk to each other.
Alex Chan532b79e2017-01-24 15:14:52 +00001165 # interact_in_memory(client, server)
1166 for _ in range(3):
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001167 for s in [client, server]:
1168 try:
1169 s.do_handshake()
1170 except WantReadError:
1171 pass
1172
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001173 def test_set_verify_callback_connection_argument(self):
1174 """
1175 The first argument passed to the verify callback is the
Alex Chan532b79e2017-01-24 15:14:52 +00001176 `Connection` instance for which verification is taking place.
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001177 """
1178 serverContext = Context(TLSv1_METHOD)
1179 serverContext.use_privatekey(
1180 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1181 serverContext.use_certificate(
1182 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1183 serverConnection = Connection(serverContext, None)
1184
1185 class VerifyCallback(object):
1186 def callback(self, connection, *args):
1187 self.connection = connection
1188 return 1
1189
1190 verify = VerifyCallback()
1191 clientContext = Context(TLSv1_METHOD)
1192 clientContext.set_verify(VERIFY_PEER, verify.callback)
1193 clientConnection = Connection(clientContext, None)
1194 clientConnection.set_connect_state()
1195
Alex Chan532b79e2017-01-24 15:14:52 +00001196 handshake_in_memory(clientConnection, serverConnection)
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001197
Alex Chan532b79e2017-01-24 15:14:52 +00001198 assert verify.connection is clientConnection
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001199
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001200 def test_set_verify_callback_exception(self):
1201 """
Alex Chan532b79e2017-01-24 15:14:52 +00001202 If the verify callback passed to `Context.set_verify` raises an
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001203 exception, verification fails and the exception is propagated to the
Alex Chan532b79e2017-01-24 15:14:52 +00001204 caller of `Connection.do_handshake`.
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001205 """
1206 serverContext = Context(TLSv1_METHOD)
1207 serverContext.use_privatekey(
1208 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1209 serverContext.use_certificate(
1210 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1211
1212 clientContext = Context(TLSv1_METHOD)
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001213
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001214 def verify_callback(*args):
1215 raise Exception("silly verify failure")
1216 clientContext.set_verify(VERIFY_PEER, verify_callback)
1217
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01001218 with pytest.raises(Exception) as exc:
1219 self._handshake_test(serverContext, clientContext)
1220
Alex Chan532b79e2017-01-24 15:14:52 +00001221 assert "silly verify failure" == str(exc.value)
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001222
Alex Chan532b79e2017-01-24 15:14:52 +00001223 def test_add_extra_chain_cert(self, tmpdir):
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001224 """
Alex Chan532b79e2017-01-24 15:14:52 +00001225 `Context.add_extra_chain_cert` accepts an `X509`
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001226 instance to add to the certificate chain.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001227
Alex Chan532b79e2017-01-24 15:14:52 +00001228 See `_create_certificate_chain` for the details of the
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001229 certificate chain tested.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001230
1231 The chain is tested by starting a server with scert and connecting
1232 to it with a client which trusts cacert and requires verification to
1233 succeed.
1234 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001235 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001236 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1237
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001238 # Dump the CA certificate to a file because that's the only way to load
1239 # it as a trusted CA in the client context.
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001240 for cert, name in [(cacert, 'ca.pem'),
1241 (icert, 'i.pem'),
1242 (scert, 's.pem')]:
Alex Chan532b79e2017-01-24 15:14:52 +00001243 with tmpdir.join(name).open('w') as f:
Hynek Schlawacke90680f2015-04-16 15:09:27 -04001244 f.write(dump_certificate(FILETYPE_PEM, cert).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001245
Hynek Schlawack1902c012015-04-16 15:06:41 -04001246 for key, name in [(cakey, 'ca.key'),
1247 (ikey, 'i.key'),
1248 (skey, 's.key')]:
Alex Chan532b79e2017-01-24 15:14:52 +00001249 with tmpdir.join(name).open('w') as f:
Hynek Schlawacke90680f2015-04-16 15:09:27 -04001250 f.write(dump_privatekey(FILETYPE_PEM, key).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001251
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001252 # Create the server context
1253 serverContext = Context(TLSv1_METHOD)
1254 serverContext.use_privatekey(skey)
1255 serverContext.use_certificate(scert)
Jean-Paul Calderone16cf03d2010-09-08 18:53:39 -04001256 # The client already has cacert, we only need to give them icert.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001257 serverContext.add_extra_chain_cert(icert)
1258
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001259 # Create the client
1260 clientContext = Context(TLSv1_METHOD)
1261 clientContext.set_verify(
1262 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Alex Chan532b79e2017-01-24 15:14:52 +00001263 clientContext.load_verify_locations(str(tmpdir.join("ca.pem")))
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001264
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001265 # Try it out.
1266 self._handshake_test(serverContext, clientContext)
1267
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001268 def _use_certificate_chain_file_test(self, certdir):
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001269 """
Alex Chan532b79e2017-01-24 15:14:52 +00001270 Verify that `Context.use_certificate_chain_file` reads a
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001271 certificate chain from a specified file.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001272
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001273 The chain is tested by starting a server with scert and connecting to
1274 it with a client which trusts cacert and requires verification to
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001275 succeed.
1276 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001277 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001278 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1279
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001280 makedirs(certdir)
1281
Jean-Paul Calderone05826732015-04-12 11:38:49 -04001282 chainFile = join_bytes_or_unicode(certdir, "chain.pem")
1283 caFile = join_bytes_or_unicode(certdir, "ca.pem")
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001284
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001285 # Write out the chain file.
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001286 with open(chainFile, 'wb') as fObj:
1287 # Most specific to least general.
1288 fObj.write(dump_certificate(FILETYPE_PEM, scert))
1289 fObj.write(dump_certificate(FILETYPE_PEM, icert))
1290 fObj.write(dump_certificate(FILETYPE_PEM, cacert))
1291
1292 with open(caFile, 'w') as fObj:
1293 fObj.write(dump_certificate(FILETYPE_PEM, cacert).decode('ascii'))
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001294
1295 serverContext = Context(TLSv1_METHOD)
1296 serverContext.use_certificate_chain_file(chainFile)
1297 serverContext.use_privatekey(skey)
1298
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001299 clientContext = Context(TLSv1_METHOD)
1300 clientContext.set_verify(
1301 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001302 clientContext.load_verify_locations(caFile)
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001303
1304 self._handshake_test(serverContext, clientContext)
1305
Alex Chan532b79e2017-01-24 15:14:52 +00001306 def test_use_certificate_chain_file_bytes(self, tmpfile):
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001307 """
1308 ``Context.use_certificate_chain_file`` accepts the name of a file (as
1309 an instance of ``bytes``) to specify additional certificates to use to
1310 construct and verify a trust chain.
1311 """
1312 self._use_certificate_chain_file_test(
Alex Chan532b79e2017-01-24 15:14:52 +00001313 tmpfile + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001314 )
1315
Alex Chan532b79e2017-01-24 15:14:52 +00001316 def test_use_certificate_chain_file_unicode(self, tmpfile):
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001317 """
1318 ``Context.use_certificate_chain_file`` accepts the name of a file (as
1319 an instance of ``unicode``) to specify additional certificates to use
1320 to construct and verify a trust chain.
1321 """
1322 self._use_certificate_chain_file_test(
Alex Chan532b79e2017-01-24 15:14:52 +00001323 tmpfile.decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001324 )
1325
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001326 def test_use_certificate_chain_file_wrong_args(self):
1327 """
Alex Chan532b79e2017-01-24 15:14:52 +00001328 `Context.use_certificate_chain_file` raises `TypeError` if passed a
1329 non-byte string single argument.
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001330 """
1331 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001332 with pytest.raises(TypeError):
1333 context.use_certificate_chain_file(object())
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001334
Alex Chan532b79e2017-01-24 15:14:52 +00001335 def test_use_certificate_chain_file_missing_file(self, tmpfile):
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001336 """
Alex Chan532b79e2017-01-24 15:14:52 +00001337 `Context.use_certificate_chain_file` raises `OpenSSL.SSL.Error` when
1338 passed a bad chain file name (for example, the name of a file which
1339 does not exist).
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001340 """
1341 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001342 with pytest.raises(Error):
1343 context.use_certificate_chain_file(tmpfile)
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001344
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001345 def test_set_verify_mode(self):
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001346 """
Alex Chan532b79e2017-01-24 15:14:52 +00001347 `Context.get_verify_mode` returns the verify mode flags previously
1348 passed to `Context.set_verify`.
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001349 """
1350 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001351 assert context.get_verify_mode() == 0
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001352 context.set_verify(
1353 VERIFY_PEER | VERIFY_CLIENT_ONCE, lambda *args: None)
Alex Chan532b79e2017-01-24 15:14:52 +00001354 assert context.get_verify_mode() == (VERIFY_PEER | VERIFY_CLIENT_ONCE)
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001355
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001356 @skip_if_py3
1357 def test_set_verify_mode_long(self):
1358 """
Alex Chan532b79e2017-01-24 15:14:52 +00001359 On Python 2 `Context.set_verify_mode` accepts values of type `long`
1360 as well as `int`.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001361 """
1362 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001363 assert context.get_verify_mode() == 0
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001364 context.set_verify(
Hynek Schlawackb4ceed32015-09-05 20:55:19 +02001365 long(VERIFY_PEER | VERIFY_CLIENT_ONCE), lambda *args: None
1366 ) # pragma: nocover
Alex Chan532b79e2017-01-24 15:14:52 +00001367 assert context.get_verify_mode() == (VERIFY_PEER | VERIFY_CLIENT_ONCE)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001368
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001369 def test_load_tmp_dh_wrong_args(self):
1370 """
Alex Chan532b79e2017-01-24 15:14:52 +00001371 `Context.load_tmp_dh` raises `TypeError` if called with a
1372 non-`str` argument.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001373 """
1374 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001375 with pytest.raises(TypeError):
1376 context.load_tmp_dh(object())
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001377
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001378 def test_load_tmp_dh_missing_file(self):
1379 """
Alex Chan532b79e2017-01-24 15:14:52 +00001380 `Context.load_tmp_dh` raises `OpenSSL.SSL.Error` if the
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001381 specified file does not exist.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001382 """
1383 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001384 with pytest.raises(Error):
1385 context.load_tmp_dh(b"hello")
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001386
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001387 def _load_tmp_dh_test(self, dhfilename):
Jean-Paul Calderone4e0c43f2015-04-13 10:15:17 -04001388 """
1389 Verify that calling ``Context.load_tmp_dh`` with the given filename
1390 does not raise an exception.
1391 """
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001392 context = Context(TLSv1_METHOD)
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001393 with open(dhfilename, "w") as dhfile:
1394 dhfile.write(dhparam)
1395
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001396 context.load_tmp_dh(dhfilename)
1397 # XXX What should I assert here? -exarkun
1398
Alex Chan532b79e2017-01-24 15:14:52 +00001399 def test_load_tmp_dh_bytes(self, tmpfile):
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001400 """
Alex Chan532b79e2017-01-24 15:14:52 +00001401 `Context.load_tmp_dh` loads Diffie-Hellman parameters from the
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001402 specified file (given as ``bytes``).
1403 """
1404 self._load_tmp_dh_test(
Alex Chan532b79e2017-01-24 15:14:52 +00001405 tmpfile + NON_ASCII.encode(getfilesystemencoding()),
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001406 )
1407
Alex Chan532b79e2017-01-24 15:14:52 +00001408 def test_load_tmp_dh_unicode(self, tmpfile):
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001409 """
Alex Chan532b79e2017-01-24 15:14:52 +00001410 `Context.load_tmp_dh` loads Diffie-Hellman parameters from the
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001411 specified file (given as ``unicode``).
1412 """
1413 self._load_tmp_dh_test(
Alex Chan532b79e2017-01-24 15:14:52 +00001414 tmpfile.decode(getfilesystemencoding()) + NON_ASCII,
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001415 )
1416
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001417 def test_set_tmp_ecdh(self):
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001418 """
Alex Chan532b79e2017-01-24 15:14:52 +00001419 `Context.set_tmp_ecdh` sets the elliptic curve for Diffie-Hellman to
1420 the specified curve.
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001421 """
1422 context = Context(TLSv1_METHOD)
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001423 for curve in get_elliptic_curves():
Hynek Schlawacka07fa8c2015-10-17 10:15:28 +02001424 if curve.name.startswith(u"Oakley-"):
Hynek Schlawack7408aff2015-10-17 09:51:16 +02001425 # Setting Oakley-EC2N-4 and Oakley-EC2N-3 adds
1426 # ('bignum routines', 'BN_mod_inverse', 'no inverse') to the
1427 # error queue on OpenSSL 1.0.2.
1428 continue
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001429 # The only easily "assertable" thing is that it does not raise an
1430 # exception.
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001431 context.set_tmp_ecdh(curve)
Alex Gaynor12dc0842014-01-17 12:51:31 -06001432
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001433 def test_set_session_cache_mode_wrong_args(self):
1434 """
Alex Chan532b79e2017-01-24 15:14:52 +00001435 `Context.set_session_cache_mode` raises `TypeError` if called with
1436 a non-integer argument.
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001437 called with other than one integer argument.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001438 """
1439 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001440 with pytest.raises(TypeError):
1441 context.set_session_cache_mode(object())
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001442
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001443 def test_session_cache_mode(self):
1444 """
Alex Chan532b79e2017-01-24 15:14:52 +00001445 `Context.set_session_cache_mode` specifies how sessions are cached.
1446 The setting can be retrieved via `Context.get_session_cache_mode`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001447 """
1448 context = Context(TLSv1_METHOD)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001449 context.set_session_cache_mode(SESS_CACHE_OFF)
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001450 off = context.set_session_cache_mode(SESS_CACHE_BOTH)
Alex Chan532b79e2017-01-24 15:14:52 +00001451 assert SESS_CACHE_OFF == off
1452 assert SESS_CACHE_BOTH == context.get_session_cache_mode()
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001453
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001454 @skip_if_py3
1455 def test_session_cache_mode_long(self):
1456 """
Alex Chan532b79e2017-01-24 15:14:52 +00001457 On Python 2 `Context.set_session_cache_mode` accepts values
1458 of type `long` as well as `int`.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001459 """
1460 context = Context(TLSv1_METHOD)
1461 context.set_session_cache_mode(long(SESS_CACHE_BOTH))
Alex Chan532b79e2017-01-24 15:14:52 +00001462 assert SESS_CACHE_BOTH == context.get_session_cache_mode()
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001463
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001464 def test_get_cert_store(self):
1465 """
Alex Chan532b79e2017-01-24 15:14:52 +00001466 `Context.get_cert_store` returns a `X509Store` instance.
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001467 """
1468 context = Context(TLSv1_METHOD)
1469 store = context.get_cert_store()
Alex Chan532b79e2017-01-24 15:14:52 +00001470 assert isinstance(store, X509Store)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001471
1472
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001473class TestServerNameCallback(object):
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001474 """
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001475 Tests for `Context.set_tlsext_servername_callback` and its
1476 interaction with `Connection`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001477 """
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001478 def test_old_callback_forgotten(self):
1479 """
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001480 If `Context.set_tlsext_servername_callback` is used to specify
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001481 a new callback, the one it replaces is dereferenced.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001482 """
1483 def callback(connection):
1484 pass
1485
1486 def replacement(connection):
1487 pass
1488
1489 context = Context(TLSv1_METHOD)
1490 context.set_tlsext_servername_callback(callback)
1491
1492 tracker = ref(callback)
1493 del callback
1494
1495 context.set_tlsext_servername_callback(replacement)
Jean-Paul Calderoned4033eb2014-01-11 08:21:46 -05001496
1497 # One run of the garbage collector happens to work on CPython. PyPy
1498 # doesn't collect the underlying object until a second run for whatever
1499 # reason. That's fine, it still demonstrates our code has properly
1500 # dropped the reference.
1501 collect()
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001502 collect()
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001503
1504 callback = tracker()
1505 if callback is not None:
1506 referrers = get_referrers(callback)
Jean-Paul Calderone7de39562014-01-11 08:17:59 -05001507 if len(referrers) > 1:
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001508 self.fail("Some references remain: %r" % (referrers,))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001509
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001510 def test_no_servername(self):
1511 """
1512 When a client specifies no server name, the callback passed to
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001513 `Context.set_tlsext_servername_callback` is invoked and the
1514 result of `Connection.get_servername` is `None`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001515 """
1516 args = []
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001517
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001518 def servername(conn):
1519 args.append((conn, conn.get_servername()))
1520 context = Context(TLSv1_METHOD)
1521 context.set_tlsext_servername_callback(servername)
1522
1523 # Lose our reference to it. The Context is responsible for keeping it
1524 # alive now.
1525 del servername
1526 collect()
1527
1528 # Necessary to actually accept the connection
1529 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001530 context.use_certificate(
1531 load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001532
1533 # Do a little connection to trigger the logic
1534 server = Connection(context, None)
1535 server.set_accept_state()
1536
1537 client = Connection(Context(TLSv1_METHOD), None)
1538 client.set_connect_state()
1539
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001540 interact_in_memory(server, client)
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001541
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001542 assert args == [(server, None)]
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001543
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001544 def test_servername(self):
1545 """
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001546 When a client specifies a server name in its hello message, the
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001547 callback passed to `Contexts.set_tlsext_servername_callback` is
1548 invoked and the result of `Connection.get_servername` is that
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001549 server name.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001550 """
1551 args = []
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001552
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001553 def servername(conn):
1554 args.append((conn, conn.get_servername()))
1555 context = Context(TLSv1_METHOD)
1556 context.set_tlsext_servername_callback(servername)
1557
1558 # Necessary to actually accept the connection
1559 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001560 context.use_certificate(
1561 load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001562
1563 # Do a little connection to trigger the logic
1564 server = Connection(context, None)
1565 server.set_accept_state()
1566
1567 client = Connection(Context(TLSv1_METHOD), None)
1568 client.set_connect_state()
Alex Gaynore7f51982016-09-11 11:48:14 -04001569 client.set_tlsext_host_name(b"foo1.example.com")
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001570
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001571 interact_in_memory(server, client)
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001572
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001573 assert args == [(server, b"foo1.example.com")]
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001574
1575
Alex Chan9e08b3e2016-11-10 12:18:54 +00001576class TestNextProtoNegotiation(object):
Cory Benfield84a121e2014-03-31 20:30:25 +01001577 """
1578 Test for Next Protocol Negotiation in PyOpenSSL.
1579 """
Alex Chan9e08b3e2016-11-10 12:18:54 +00001580 def test_npn_success(self):
1581 """
1582 Tests that clients and servers that agree on the negotiated next
1583 protocol can correct establish a connection, and that the agreed
1584 protocol is reported by the connections.
1585 """
1586 advertise_args = []
1587 select_args = []
1588
1589 def advertise(conn):
1590 advertise_args.append((conn,))
1591 return [b'http/1.1', b'spdy/2']
1592
1593 def select(conn, options):
1594 select_args.append((conn, options))
1595 return b'spdy/2'
1596
1597 server_context = Context(TLSv1_METHOD)
1598 server_context.set_npn_advertise_callback(advertise)
1599
1600 client_context = Context(TLSv1_METHOD)
1601 client_context.set_npn_select_callback(select)
1602
1603 # Necessary to actually accept the connection
1604 server_context.use_privatekey(
1605 load_privatekey(FILETYPE_PEM, server_key_pem))
1606 server_context.use_certificate(
1607 load_certificate(FILETYPE_PEM, server_cert_pem))
1608
1609 # Do a little connection to trigger the logic
1610 server = Connection(server_context, None)
1611 server.set_accept_state()
1612
1613 client = Connection(client_context, None)
1614 client.set_connect_state()
1615
1616 interact_in_memory(server, client)
1617
1618 assert advertise_args == [(server,)]
1619 assert select_args == [(client, [b'http/1.1', b'spdy/2'])]
1620
1621 assert server.get_next_proto_negotiated() == b'spdy/2'
1622 assert client.get_next_proto_negotiated() == b'spdy/2'
1623
1624 def test_npn_client_fail(self):
1625 """
1626 Tests that when clients and servers cannot agree on what protocol
1627 to use next that the TLS connection does not get established.
1628 """
1629 advertise_args = []
1630 select_args = []
1631
1632 def advertise(conn):
1633 advertise_args.append((conn,))
1634 return [b'http/1.1', b'spdy/2']
1635
1636 def select(conn, options):
1637 select_args.append((conn, options))
1638 return b''
1639
1640 server_context = Context(TLSv1_METHOD)
1641 server_context.set_npn_advertise_callback(advertise)
1642
1643 client_context = Context(TLSv1_METHOD)
1644 client_context.set_npn_select_callback(select)
1645
1646 # Necessary to actually accept the connection
1647 server_context.use_privatekey(
1648 load_privatekey(FILETYPE_PEM, server_key_pem))
1649 server_context.use_certificate(
1650 load_certificate(FILETYPE_PEM, server_cert_pem))
1651
1652 # Do a little connection to trigger the logic
1653 server = Connection(server_context, None)
1654 server.set_accept_state()
1655
1656 client = Connection(client_context, None)
1657 client.set_connect_state()
1658
1659 # If the client doesn't return anything, the connection will fail.
1660 with pytest.raises(Error):
1661 interact_in_memory(server, client)
1662
1663 assert advertise_args == [(server,)]
1664 assert select_args == [(client, [b'http/1.1', b'spdy/2'])]
1665
1666 def test_npn_select_error(self):
1667 """
1668 Test that we can handle exceptions in the select callback. If
1669 select fails it should be fatal to the connection.
1670 """
1671 advertise_args = []
1672
1673 def advertise(conn):
1674 advertise_args.append((conn,))
1675 return [b'http/1.1', b'spdy/2']
1676
1677 def select(conn, options):
1678 raise TypeError
1679
1680 server_context = Context(TLSv1_METHOD)
1681 server_context.set_npn_advertise_callback(advertise)
1682
1683 client_context = Context(TLSv1_METHOD)
1684 client_context.set_npn_select_callback(select)
1685
1686 # Necessary to actually accept the connection
1687 server_context.use_privatekey(
1688 load_privatekey(FILETYPE_PEM, server_key_pem))
1689 server_context.use_certificate(
1690 load_certificate(FILETYPE_PEM, server_cert_pem))
1691
1692 # Do a little connection to trigger the logic
1693 server = Connection(server_context, None)
1694 server.set_accept_state()
1695
1696 client = Connection(client_context, None)
1697 client.set_connect_state()
1698
1699 # If the callback throws an exception it should be raised here.
1700 with pytest.raises(TypeError):
1701 interact_in_memory(server, client)
1702 assert advertise_args == [(server,), ]
1703
1704 def test_npn_advertise_error(self):
1705 """
1706 Test that we can handle exceptions in the advertise callback. If
1707 advertise fails no NPN is advertised to the client.
1708 """
1709 select_args = []
1710
1711 def advertise(conn):
1712 raise TypeError
1713
1714 def select(conn, options): # pragma: nocover
Cory Benfieldba1820d2015-04-13 17:39:12 -04001715 """
Alex Chan9e08b3e2016-11-10 12:18:54 +00001716 Assert later that no args are actually appended.
Cory Benfieldba1820d2015-04-13 17:39:12 -04001717 """
Alex Chan9e08b3e2016-11-10 12:18:54 +00001718 select_args.append((conn, options))
1719 return b''
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001720
Alex Chan9e08b3e2016-11-10 12:18:54 +00001721 server_context = Context(TLSv1_METHOD)
1722 server_context.set_npn_advertise_callback(advertise)
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001723
Alex Chan9e08b3e2016-11-10 12:18:54 +00001724 client_context = Context(TLSv1_METHOD)
1725 client_context.set_npn_select_callback(select)
Cory Benfield84a121e2014-03-31 20:30:25 +01001726
Alex Chan9e08b3e2016-11-10 12:18:54 +00001727 # Necessary to actually accept the connection
1728 server_context.use_privatekey(
1729 load_privatekey(FILETYPE_PEM, server_key_pem))
1730 server_context.use_certificate(
1731 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield84a121e2014-03-31 20:30:25 +01001732
Alex Chan9e08b3e2016-11-10 12:18:54 +00001733 # Do a little connection to trigger the logic
1734 server = Connection(server_context, None)
1735 server.set_accept_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001736
Alex Chan9e08b3e2016-11-10 12:18:54 +00001737 client = Connection(client_context, None)
1738 client.set_connect_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001739
Alex Chan9e08b3e2016-11-10 12:18:54 +00001740 # If the client doesn't return anything, the connection will fail.
1741 with pytest.raises(TypeError):
1742 interact_in_memory(server, client)
1743 assert select_args == []
Cory Benfield0ea76e72015-03-22 09:05:28 +00001744
1745
Alex Chanec1e32d2016-11-10 14:11:45 +00001746class TestApplicationLayerProtoNegotiation(object):
Cory Benfield12eae892014-06-07 15:42:56 +01001747 """
1748 Tests for ALPN in PyOpenSSL.
1749 """
Cory Benfielde46fa842015-04-13 16:50:49 -04001750 # Skip tests on versions that don't support ALPN.
1751 if _lib.Cryptography_HAS_ALPN:
Cory Benfield12eae892014-06-07 15:42:56 +01001752
Cory Benfielde46fa842015-04-13 16:50:49 -04001753 def test_alpn_success(self):
1754 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04001755 Clients and servers that agree on the negotiated ALPN protocol can
1756 correct establish a connection, and the agreed protocol is reported
1757 by the connections.
Cory Benfielde46fa842015-04-13 16:50:49 -04001758 """
1759 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001760
Cory Benfielde46fa842015-04-13 16:50:49 -04001761 def select(conn, options):
1762 select_args.append((conn, options))
1763 return b'spdy/2'
Cory Benfield12eae892014-06-07 15:42:56 +01001764
Cory Benfielde46fa842015-04-13 16:50:49 -04001765 client_context = Context(TLSv1_METHOD)
1766 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfield12eae892014-06-07 15:42:56 +01001767
Cory Benfielde46fa842015-04-13 16:50:49 -04001768 server_context = Context(TLSv1_METHOD)
1769 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01001770
Cory Benfielde46fa842015-04-13 16:50:49 -04001771 # Necessary to actually accept the connection
1772 server_context.use_privatekey(
1773 load_privatekey(FILETYPE_PEM, server_key_pem))
1774 server_context.use_certificate(
1775 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield12eae892014-06-07 15:42:56 +01001776
Cory Benfielde46fa842015-04-13 16:50:49 -04001777 # Do a little connection to trigger the logic
1778 server = Connection(server_context, None)
1779 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001780
Cory Benfielde46fa842015-04-13 16:50:49 -04001781 client = Connection(client_context, None)
1782 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001783
Alex Chanec1e32d2016-11-10 14:11:45 +00001784 interact_in_memory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001785
Alex Chanec1e32d2016-11-10 14:11:45 +00001786 assert select_args == [(server, [b'http/1.1', b'spdy/2'])]
Cory Benfielde46fa842015-04-13 16:50:49 -04001787
Alex Chanec1e32d2016-11-10 14:11:45 +00001788 assert server.get_alpn_proto_negotiated() == b'spdy/2'
1789 assert client.get_alpn_proto_negotiated() == b'spdy/2'
Cory Benfield12eae892014-06-07 15:42:56 +01001790
Cory Benfielde46fa842015-04-13 16:50:49 -04001791 def test_alpn_set_on_connection(self):
1792 """
1793 The same as test_alpn_success, but setting the ALPN protocols on
1794 the connection rather than the context.
1795 """
1796 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001797
Cory Benfielde46fa842015-04-13 16:50:49 -04001798 def select(conn, options):
1799 select_args.append((conn, options))
1800 return b'spdy/2'
Cory Benfield12eae892014-06-07 15:42:56 +01001801
Cory Benfielde46fa842015-04-13 16:50:49 -04001802 # Setup the client context but don't set any ALPN protocols.
1803 client_context = Context(TLSv1_METHOD)
Cory Benfield12eae892014-06-07 15:42:56 +01001804
Cory Benfielde46fa842015-04-13 16:50:49 -04001805 server_context = Context(TLSv1_METHOD)
1806 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01001807
Cory Benfielde46fa842015-04-13 16:50:49 -04001808 # Necessary to actually accept the connection
1809 server_context.use_privatekey(
1810 load_privatekey(FILETYPE_PEM, server_key_pem))
1811 server_context.use_certificate(
1812 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield12eae892014-06-07 15:42:56 +01001813
Cory Benfielde46fa842015-04-13 16:50:49 -04001814 # Do a little connection to trigger the logic
1815 server = Connection(server_context, None)
1816 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001817
Cory Benfielde46fa842015-04-13 16:50:49 -04001818 # Set the ALPN protocols on the client connection.
1819 client = Connection(client_context, None)
1820 client.set_alpn_protos([b'http/1.1', b'spdy/2'])
1821 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001822
Alex Chanec1e32d2016-11-10 14:11:45 +00001823 interact_in_memory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001824
Alex Chanec1e32d2016-11-10 14:11:45 +00001825 assert select_args == [(server, [b'http/1.1', b'spdy/2'])]
Cory Benfield12eae892014-06-07 15:42:56 +01001826
Alex Chanec1e32d2016-11-10 14:11:45 +00001827 assert server.get_alpn_proto_negotiated() == b'spdy/2'
1828 assert client.get_alpn_proto_negotiated() == b'spdy/2'
Cory Benfield12eae892014-06-07 15:42:56 +01001829
Cory Benfielde46fa842015-04-13 16:50:49 -04001830 def test_alpn_server_fail(self):
1831 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04001832 When clients and servers cannot agree on what protocol to use next
1833 the TLS connection does not get established.
Cory Benfielde46fa842015-04-13 16:50:49 -04001834 """
1835 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001836
Cory Benfielde46fa842015-04-13 16:50:49 -04001837 def select(conn, options):
1838 select_args.append((conn, options))
1839 return b''
Cory Benfield12eae892014-06-07 15:42:56 +01001840
Cory Benfielde46fa842015-04-13 16:50:49 -04001841 client_context = Context(TLSv1_METHOD)
1842 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfield12eae892014-06-07 15:42:56 +01001843
Cory Benfielde46fa842015-04-13 16:50:49 -04001844 server_context = Context(TLSv1_METHOD)
1845 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01001846
Cory Benfielde46fa842015-04-13 16:50:49 -04001847 # Necessary to actually accept the connection
1848 server_context.use_privatekey(
1849 load_privatekey(FILETYPE_PEM, server_key_pem))
1850 server_context.use_certificate(
1851 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield12eae892014-06-07 15:42:56 +01001852
Cory Benfielde46fa842015-04-13 16:50:49 -04001853 # Do a little connection to trigger the logic
1854 server = Connection(server_context, None)
1855 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001856
Cory Benfielde46fa842015-04-13 16:50:49 -04001857 client = Connection(client_context, None)
1858 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001859
Cory Benfielde46fa842015-04-13 16:50:49 -04001860 # If the client doesn't return anything, the connection will fail.
Alex Chanec1e32d2016-11-10 14:11:45 +00001861 with pytest.raises(Error):
1862 interact_in_memory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001863
Alex Chanec1e32d2016-11-10 14:11:45 +00001864 assert select_args == [(server, [b'http/1.1', b'spdy/2'])]
Cory Benfield12eae892014-06-07 15:42:56 +01001865
Cory Benfielde46fa842015-04-13 16:50:49 -04001866 def test_alpn_no_server(self):
1867 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04001868 When clients and servers cannot agree on what protocol to use next
1869 because the server doesn't offer ALPN, no protocol is negotiated.
Cory Benfielde46fa842015-04-13 16:50:49 -04001870 """
1871 client_context = Context(TLSv1_METHOD)
1872 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfielde3d57152015-04-11 17:57:35 -04001873
Cory Benfielde46fa842015-04-13 16:50:49 -04001874 server_context = Context(TLSv1_METHOD)
Cory Benfielde3d57152015-04-11 17:57:35 -04001875
Cory Benfielde46fa842015-04-13 16:50:49 -04001876 # Necessary to actually accept the connection
1877 server_context.use_privatekey(
1878 load_privatekey(FILETYPE_PEM, server_key_pem))
1879 server_context.use_certificate(
1880 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfielde3d57152015-04-11 17:57:35 -04001881
Cory Benfielde46fa842015-04-13 16:50:49 -04001882 # Do a little connection to trigger the logic
1883 server = Connection(server_context, None)
1884 server.set_accept_state()
Cory Benfielde3d57152015-04-11 17:57:35 -04001885
Cory Benfielde46fa842015-04-13 16:50:49 -04001886 client = Connection(client_context, None)
1887 client.set_connect_state()
Cory Benfielde3d57152015-04-11 17:57:35 -04001888
Cory Benfielde46fa842015-04-13 16:50:49 -04001889 # Do the dance.
Alex Chanec1e32d2016-11-10 14:11:45 +00001890 interact_in_memory(server, client)
Cory Benfielde3d57152015-04-11 17:57:35 -04001891
Alex Chanec1e32d2016-11-10 14:11:45 +00001892 assert client.get_alpn_proto_negotiated() == b''
Cory Benfielde3d57152015-04-11 17:57:35 -04001893
Cory Benfielde46fa842015-04-13 16:50:49 -04001894 def test_alpn_callback_exception(self):
1895 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04001896 We can handle exceptions in the ALPN select callback.
Cory Benfielde46fa842015-04-13 16:50:49 -04001897 """
1898 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001899
Cory Benfielde46fa842015-04-13 16:50:49 -04001900 def select(conn, options):
1901 select_args.append((conn, options))
Cory Benfieldef401452015-04-13 18:17:36 -04001902 raise TypeError()
Cory Benfieldf1177e72015-04-12 09:11:49 -04001903
Cory Benfielde46fa842015-04-13 16:50:49 -04001904 client_context = Context(TLSv1_METHOD)
1905 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfieldf1177e72015-04-12 09:11:49 -04001906
Cory Benfielde46fa842015-04-13 16:50:49 -04001907 server_context = Context(TLSv1_METHOD)
1908 server_context.set_alpn_select_callback(select)
Cory Benfieldf1177e72015-04-12 09:11:49 -04001909
Cory Benfielde46fa842015-04-13 16:50:49 -04001910 # Necessary to actually accept the connection
1911 server_context.use_privatekey(
1912 load_privatekey(FILETYPE_PEM, server_key_pem))
1913 server_context.use_certificate(
1914 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfieldf1177e72015-04-12 09:11:49 -04001915
Cory Benfielde46fa842015-04-13 16:50:49 -04001916 # Do a little connection to trigger the logic
1917 server = Connection(server_context, None)
1918 server.set_accept_state()
Cory Benfieldf1177e72015-04-12 09:11:49 -04001919
Cory Benfielde46fa842015-04-13 16:50:49 -04001920 client = Connection(client_context, None)
1921 client.set_connect_state()
Cory Benfieldf1177e72015-04-12 09:11:49 -04001922
Alex Chanec1e32d2016-11-10 14:11:45 +00001923 with pytest.raises(TypeError):
1924 interact_in_memory(server, client)
1925 assert select_args == [(server, [b'http/1.1', b'spdy/2'])]
Cory Benfieldf1177e72015-04-12 09:11:49 -04001926
Cory Benfield0f7b04c2015-04-13 17:51:12 -04001927 else:
1928 # No ALPN.
1929 def test_alpn_not_implemented(self):
Cory Benfieldef401452015-04-13 18:17:36 -04001930 """
1931 If ALPN is not in OpenSSL, we should raise NotImplementedError.
1932 """
Cory Benfield0f7b04c2015-04-13 17:51:12 -04001933 # Test the context methods first.
1934 context = Context(TLSv1_METHOD)
Alex Chanec1e32d2016-11-10 14:11:45 +00001935 with pytest.raises(NotImplementedError):
1936 context.set_alpn_protos(None)
1937 with pytest.raises(NotImplementedError):
1938 context.set_alpn_select_callback(None)
Cory Benfield0f7b04c2015-04-13 17:51:12 -04001939
1940 # Now test a connection.
1941 conn = Connection(context)
Alex Chanec1e32d2016-11-10 14:11:45 +00001942 with pytest.raises(NotImplementedError):
1943 conn.set_alpn_protos(None)
Cory Benfield0f7b04c2015-04-13 17:51:12 -04001944
Cory Benfieldf1177e72015-04-12 09:11:49 -04001945
Alex Chanec1e32d2016-11-10 14:11:45 +00001946class TestSession(object):
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05001947 """
1948 Unit tests for :py:obj:`OpenSSL.SSL.Session`.
1949 """
1950 def test_construction(self):
1951 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001952 :py:class:`Session` can be constructed with no arguments, creating
1953 a new instance of that type.
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05001954 """
1955 new_session = Session()
Alex Chanec1e32d2016-11-10 14:11:45 +00001956 assert isinstance(new_session, Session)
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05001957
1958
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001959class ConnectionTests(TestCase, _LoopbackMixin):
Rick Deane15b1472009-07-09 15:53:42 -05001960 """
Hynek Schlawackaa861212016-03-13 13:53:48 +01001961 Unit tests for :class:`OpenSSL.SSL.Connection`.
Rick Deane15b1472009-07-09 15:53:42 -05001962 """
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04001963 # XXX get_peer_certificate -> None
1964 # XXX sock_shutdown
1965 # XXX master_key -> TypeError
1966 # XXX server_random -> TypeError
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04001967 # XXX connect -> TypeError
1968 # XXX connect_ex -> TypeError
1969 # XXX set_connect_state -> TypeError
1970 # XXX set_accept_state -> TypeError
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04001971 # XXX do_handshake -> TypeError
1972 # XXX bio_read -> TypeError
1973 # XXX recv -> TypeError
1974 # XXX send -> TypeError
1975 # XXX bio_write -> TypeError
1976
Rick Deane15b1472009-07-09 15:53:42 -05001977 def test_type(self):
1978 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001979 :py:obj:`Connection` and :py:obj:`ConnectionType` refer to the same
1980 type object and can be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -05001981 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001982 self.assertIdentical(Connection, ConnectionType)
Rick Deane15b1472009-07-09 15:53:42 -05001983 ctx = Context(TLSv1_METHOD)
Jean-Paul Calderone68649052009-07-17 21:14:27 -04001984 self.assertConsistentType(Connection, 'Connection', ctx, None)
Rick Deane15b1472009-07-09 15:53:42 -05001985
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05001986 def test_get_context(self):
1987 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001988 :py:obj:`Connection.get_context` returns the :py:obj:`Context` instance
1989 used to construct the :py:obj:`Connection` instance.
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05001990 """
1991 context = Context(TLSv1_METHOD)
1992 connection = Connection(context, None)
1993 self.assertIdentical(connection.get_context(), context)
1994
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05001995 def test_get_context_wrong_args(self):
1996 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001997 :py:obj:`Connection.get_context` raises :py:obj:`TypeError` if called
1998 with any arguments.
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05001999 """
2000 connection = Connection(Context(TLSv1_METHOD), None)
2001 self.assertRaises(TypeError, connection.get_context, None)
2002
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002003 def test_set_context_wrong_args(self):
2004 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002005 :py:obj:`Connection.set_context` raises :py:obj:`TypeError` if called
2006 with a non-:py:obj:`Context` instance argument or with any number of
2007 arguments other than 1.
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002008 """
2009 ctx = Context(TLSv1_METHOD)
2010 connection = Connection(ctx, None)
2011 self.assertRaises(TypeError, connection.set_context)
2012 self.assertRaises(TypeError, connection.set_context, object())
2013 self.assertRaises(TypeError, connection.set_context, "hello")
2014 self.assertRaises(TypeError, connection.set_context, 1)
2015 self.assertRaises(TypeError, connection.set_context, 1, 2)
2016 self.assertRaises(
2017 TypeError, connection.set_context, Context(TLSv1_METHOD), 2)
2018 self.assertIdentical(ctx, connection.get_context())
2019
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002020 def test_set_context(self):
2021 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002022 :py:obj:`Connection.set_context` specifies a new :py:obj:`Context`
2023 instance to be used for the connection.
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002024 """
2025 original = Context(SSLv23_METHOD)
2026 replacement = Context(TLSv1_METHOD)
2027 connection = Connection(original, None)
2028 connection.set_context(replacement)
2029 self.assertIdentical(replacement, connection.get_context())
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002030 # Lose our references to the contexts, just in case the Connection
2031 # isn't properly managing its own contributions to their reference
2032 # counts.
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002033 del original, replacement
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002034 collect()
2035
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002036 def test_set_tlsext_host_name_wrong_args(self):
2037 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002038 If :py:obj:`Connection.set_tlsext_host_name` is called with a non-byte
2039 string argument or a byte string with an embedded NUL or other than one
Jonathan Ballet648875f2011-07-16 14:14:58 +09002040 argument, :py:obj:`TypeError` is raised.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002041 """
2042 conn = Connection(Context(TLSv1_METHOD), None)
2043 self.assertRaises(TypeError, conn.set_tlsext_host_name)
2044 self.assertRaises(TypeError, conn.set_tlsext_host_name, object())
2045 self.assertRaises(TypeError, conn.set_tlsext_host_name, 123, 456)
2046 self.assertRaises(
Alex Gaynore7f51982016-09-11 11:48:14 -04002047 TypeError, conn.set_tlsext_host_name, b"with\0null")
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002048
Abraham Martinc5484ba2015-03-25 15:33:05 +00002049 if PY3:
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002050 # On Python 3.x, don't accidentally implicitly convert from text.
2051 self.assertRaises(
2052 TypeError,
Alex Gaynore7f51982016-09-11 11:48:14 -04002053 conn.set_tlsext_host_name, b"example.com".decode("ascii"))
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002054
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04002055 def test_get_servername_wrong_args(self):
2056 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002057 :py:obj:`Connection.get_servername` raises :py:obj:`TypeError` if
2058 called with any arguments.
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04002059 """
2060 connection = Connection(Context(TLSv1_METHOD), None)
2061 self.assertRaises(TypeError, connection.get_servername, object())
2062 self.assertRaises(TypeError, connection.get_servername, 1)
2063 self.assertRaises(TypeError, connection.get_servername, "hello")
2064
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002065 def test_pending(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002066 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002067 :py:obj:`Connection.pending` returns the number of bytes available for
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002068 immediate read.
2069 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002070 connection = Connection(Context(TLSv1_METHOD), None)
2071 self.assertEquals(connection.pending(), 0)
2072
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002073 def test_pending_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002074 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002075 :py:obj:`Connection.pending` raises :py:obj:`TypeError` if called with
2076 any arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002077 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002078 connection = Connection(Context(TLSv1_METHOD), None)
2079 self.assertRaises(TypeError, connection.pending, None)
2080
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002081 def test_peek(self):
2082 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002083 :py:obj:`Connection.recv` peeks into the connection if
2084 :py:obj:`socket.MSG_PEEK` is passed.
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002085 """
2086 server, client = self._loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002087 server.send(b'xy')
2088 self.assertEqual(client.recv(2, MSG_PEEK), b'xy')
2089 self.assertEqual(client.recv(2, MSG_PEEK), b'xy')
2090 self.assertEqual(client.recv(2), b'xy')
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002091
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002092 def test_connect_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002093 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002094 :py:obj:`Connection.connect` raises :py:obj:`TypeError` if called with
2095 a non-address argument or with the wrong number of arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002096 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002097 connection = Connection(Context(TLSv1_METHOD), socket())
2098 self.assertRaises(TypeError, connection.connect, None)
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002099 self.assertRaises(TypeError, connection.connect)
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002100 self.assertRaises(
2101 TypeError, connection.connect, ("127.0.0.1", 1), None
2102 )
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002103
kjavfe508d62015-09-02 12:20:35 +01002104 def test_connection_undefined_attr(self):
2105 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002106 :py:obj:`Connection.connect` raises :py:obj:`TypeError` if called with
2107 a non-address argument or with the wrong number of arguments.
kjavfe508d62015-09-02 12:20:35 +01002108 """
Alex Gaynor1aabb2e2015-09-05 13:35:18 -04002109
kjavfe508d62015-09-02 12:20:35 +01002110 def attr_access_test(connection):
2111 return connection.an_attribute_which_is_not_defined
Alex Gaynor1aabb2e2015-09-05 13:35:18 -04002112
kjavfe508d62015-09-02 12:20:35 +01002113 connection = Connection(Context(TLSv1_METHOD), None)
2114 self.assertRaises(AttributeError, attr_access_test, connection)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002115
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002116 def test_connect_refused(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002117 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002118 :py:obj:`Connection.connect` raises :py:obj:`socket.error` if the
2119 underlying socket connect method raises it.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002120 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002121 client = socket()
2122 context = Context(TLSv1_METHOD)
2123 clientSSL = Connection(context, client)
Alex Gaynor122717b2015-09-05 14:14:18 -04002124 # pytest.raises here doesn't work because of a bug in py.test on Python
2125 # 2.6: https://github.com/pytest-dev/pytest/issues/988
Alex Gaynore69c2782015-09-05 14:07:48 -04002126 try:
Alex Gaynor1aabb2e2015-09-05 13:35:18 -04002127 clientSSL.connect(("127.0.0.1", 1))
Alex Gaynore69c2782015-09-05 14:07:48 -04002128 except error as e:
Alex Gaynor20a4c082015-09-05 14:24:15 -04002129 exc = e
2130 assert exc.args[0] == ECONNREFUSED
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002131
2132 def test_connect(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002133 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002134 :py:obj:`Connection.connect` establishes a connection to the specified
2135 address.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002136 """
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002137 port = socket()
2138 port.bind(('', 0))
2139 port.listen(3)
2140
2141 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002142 clientSSL.connect(('127.0.0.1', port.getsockname()[1]))
2143 # XXX An assertion? Or something?
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002144
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002145 @pytest.mark.skipif(
2146 platform == "darwin",
2147 reason="connect_ex sometimes causes a kernel panic on OS X 10.6.4"
2148 )
2149 def test_connect_ex(self):
2150 """
2151 If there is a connection error, :py:obj:`Connection.connect_ex`
2152 returns the errno instead of raising an exception.
2153 """
2154 port = socket()
2155 port.bind(('', 0))
2156 port.listen(3)
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002157
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002158 clientSSL = Connection(Context(TLSv1_METHOD), socket())
2159 clientSSL.setblocking(False)
2160 result = clientSSL.connect_ex(port.getsockname())
2161 expected = (EINPROGRESS, EWOULDBLOCK)
2162 self.assertTrue(
2163 result in expected, "%r not in %r" % (result, expected))
Jean-Paul Calderone55d91f42010-07-29 19:22:17 -04002164
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002165 def test_accept_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002166 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002167 :py:obj:`Connection.accept` raises :py:obj:`TypeError` if called with
2168 any arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002169 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002170 connection = Connection(Context(TLSv1_METHOD), socket())
2171 self.assertRaises(TypeError, connection.accept, None)
2172
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002173 def test_accept(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002174 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002175 :py:obj:`Connection.accept` accepts a pending connection attempt and
2176 returns a tuple of a new :py:obj:`Connection` (the accepted client) and
2177 the address the connection originated from.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002178 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002179 ctx = Context(TLSv1_METHOD)
2180 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2181 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002182 port = socket()
2183 portSSL = Connection(ctx, port)
2184 portSSL.bind(('', 0))
2185 portSSL.listen(3)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002186
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002187 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002188
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002189 # Calling portSSL.getsockname() here to get the server IP address
2190 # sounds great, but frequently fails on Windows.
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002191 clientSSL.connect(('127.0.0.1', portSSL.getsockname()[1]))
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002192
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002193 serverSSL, address = portSSL.accept()
2194
2195 self.assertTrue(isinstance(serverSSL, Connection))
2196 self.assertIdentical(serverSSL.get_context(), ctx)
2197 self.assertEquals(address, clientSSL.getsockname())
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002198
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002199 def test_shutdown_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002200 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002201 :py:obj:`Connection.shutdown` raises :py:obj:`TypeError` if called with
2202 the wrong number of arguments or with arguments other than integers.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002203 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002204 connection = Connection(Context(TLSv1_METHOD), None)
2205 self.assertRaises(TypeError, connection.shutdown, None)
Jean-Paul Calderone1d3e0222010-07-29 22:52:45 -04002206 self.assertRaises(TypeError, connection.get_shutdown, None)
2207 self.assertRaises(TypeError, connection.set_shutdown)
2208 self.assertRaises(TypeError, connection.set_shutdown, None)
2209 self.assertRaises(TypeError, connection.set_shutdown, 0, 1)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002210
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002211 def test_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002212 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002213 :py:obj:`Connection.shutdown` performs an SSL-level connection
2214 shutdown.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002215 """
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002216 server, client = self._loopback()
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04002217 self.assertFalse(server.shutdown())
2218 self.assertEquals(server.get_shutdown(), SENT_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002219 self.assertRaises(ZeroReturnError, client.recv, 1024)
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04002220 self.assertEquals(client.get_shutdown(), RECEIVED_SHUTDOWN)
2221 client.shutdown()
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002222 self.assertEquals(
2223 client.get_shutdown(), SENT_SHUTDOWN | RECEIVED_SHUTDOWN
2224 )
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04002225 self.assertRaises(ZeroReturnError, server.recv, 1024)
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002226 self.assertEquals(
2227 server.get_shutdown(), SENT_SHUTDOWN | RECEIVED_SHUTDOWN
2228 )
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002229
Paul Aurichc85e0862015-01-08 08:34:33 -08002230 def test_shutdown_closed(self):
2231 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002232 If the underlying socket is closed, :py:obj:`Connection.shutdown`
2233 propagates the write error from the low level write call.
Paul Aurichc85e0862015-01-08 08:34:33 -08002234 """
2235 server, client = self._loopback()
2236 server.sock_shutdown(2)
2237 exc = self.assertRaises(SysCallError, server.shutdown)
2238 if platform == "win32":
2239 self.assertEqual(exc.args[0], ESHUTDOWN)
2240 else:
2241 self.assertEqual(exc.args[0], EPIPE)
2242
Glyph89389472015-04-14 17:29:26 -04002243 def test_shutdown_truncated(self):
Glyph6064ec32015-04-14 16:38:22 -04002244 """
Glyph89389472015-04-14 17:29:26 -04002245 If the underlying connection is truncated, :obj:`Connection.shutdown`
2246 raises an :obj:`Error`.
Glyph6064ec32015-04-14 16:38:22 -04002247 """
Glyph89389472015-04-14 17:29:26 -04002248 server_ctx = Context(TLSv1_METHOD)
2249 client_ctx = Context(TLSv1_METHOD)
2250 server_ctx.use_privatekey(
2251 load_privatekey(FILETYPE_PEM, server_key_pem))
2252 server_ctx.use_certificate(
2253 load_certificate(FILETYPE_PEM, server_cert_pem))
2254 server = Connection(server_ctx, None)
2255 client = Connection(client_ctx, None)
2256 self._handshakeInMemory(client, server)
2257 self.assertEqual(server.shutdown(), False)
2258 self.assertRaises(WantReadError, server.shutdown)
2259 server.bio_shutdown()
Glyph6064ec32015-04-14 16:38:22 -04002260 self.assertRaises(Error, server.shutdown)
2261
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002262 def test_set_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002263 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002264 :py:obj:`Connection.set_shutdown` sets the state of the SSL connection
2265 shutdown process.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002266 """
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002267 connection = Connection(Context(TLSv1_METHOD), socket())
2268 connection.set_shutdown(RECEIVED_SHUTDOWN)
2269 self.assertEquals(connection.get_shutdown(), RECEIVED_SHUTDOWN)
2270
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002271 @skip_if_py3
2272 def test_set_shutdown_long(self):
2273 """
2274 On Python 2 :py:obj:`Connection.set_shutdown` accepts an argument
2275 of type :py:obj:`long` as well as :py:obj:`int`.
2276 """
2277 connection = Connection(Context(TLSv1_METHOD), socket())
2278 connection.set_shutdown(long(RECEIVED_SHUTDOWN))
2279 self.assertEquals(connection.get_shutdown(), RECEIVED_SHUTDOWN)
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -05002280
kjavaf248592015-09-07 12:14:01 +01002281 def test_state_string(self):
2282 """
Hynek Schlawackb0274ce2015-10-16 19:56:26 +02002283 :meth:`Connection.state_string` verbosely describes the current
2284 state of the :class:`Connection`.
kjavaf248592015-09-07 12:14:01 +01002285 """
Hynek Schlawackb0274ce2015-10-16 19:56:26 +02002286 server, client = socket_pair()
kjavaf248592015-09-07 12:14:01 +01002287 server = self._loopbackServerFactory(server)
2288 client = self._loopbackClientFactory(client)
2289
Alex Gaynor5af32d02016-09-24 01:52:21 -04002290 assert server.get_state_string() in [
2291 b"before/accept initialization", b"before SSL initialization"
2292 ]
2293 assert client.get_state_string() in [
2294 b"before/connect initialization", b"before SSL initialization"
2295 ]
kjavaf248592015-09-07 12:14:01 +01002296
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002297 def test_app_data_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002298 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002299 :py:obj:`Connection.set_app_data` raises :py:obj:`TypeError` if called
2300 with other than one argument. :py:obj:`Connection.get_app_data` raises
2301 :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002302 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002303 conn = Connection(Context(TLSv1_METHOD), None)
2304 self.assertRaises(TypeError, conn.get_app_data, None)
2305 self.assertRaises(TypeError, conn.set_app_data)
2306 self.assertRaises(TypeError, conn.set_app_data, None, None)
2307
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002308 def test_app_data(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002309 """
2310 Any object can be set as app data by passing it to
Jonathan Ballet648875f2011-07-16 14:14:58 +09002311 :py:obj:`Connection.set_app_data` and later retrieved with
2312 :py:obj:`Connection.get_app_data`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002313 """
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002314 conn = Connection(Context(TLSv1_METHOD), None)
Todd Chapman4f73e4f2015-08-27 11:26:43 -04002315 assert None is conn.get_app_data()
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002316 app_data = object()
2317 conn.set_app_data(app_data)
Todd Chapman4f73e4f2015-08-27 11:26:43 -04002318 assert conn.get_app_data() is app_data
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002319
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002320 def test_makefile(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002321 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002322 :py:obj:`Connection.makefile` is not implemented and calling that
2323 method raises :py:obj:`NotImplementedError`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002324 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002325 conn = Connection(Context(TLSv1_METHOD), None)
2326 self.assertRaises(NotImplementedError, conn.makefile)
2327
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002328 def test_get_peer_cert_chain_wrong_args(self):
2329 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002330 :py:obj:`Connection.get_peer_cert_chain` raises :py:obj:`TypeError` if
2331 called with any arguments.
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002332 """
2333 conn = Connection(Context(TLSv1_METHOD), None)
2334 self.assertRaises(TypeError, conn.get_peer_cert_chain, 1)
2335 self.assertRaises(TypeError, conn.get_peer_cert_chain, "foo")
2336 self.assertRaises(TypeError, conn.get_peer_cert_chain, object())
2337 self.assertRaises(TypeError, conn.get_peer_cert_chain, [])
2338
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002339 def test_get_peer_cert_chain(self):
2340 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002341 :py:obj:`Connection.get_peer_cert_chain` returns a list of certificates
2342 which the connected server returned for the certification verification.
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002343 """
2344 chain = _create_certificate_chain()
2345 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
2346
2347 serverContext = Context(TLSv1_METHOD)
2348 serverContext.use_privatekey(skey)
2349 serverContext.use_certificate(scert)
2350 serverContext.add_extra_chain_cert(icert)
2351 serverContext.add_extra_chain_cert(cacert)
2352 server = Connection(serverContext, None)
2353 server.set_accept_state()
2354
2355 # Create the client
2356 clientContext = Context(TLSv1_METHOD)
2357 clientContext.set_verify(VERIFY_NONE, verify_cb)
2358 client = Connection(clientContext, None)
2359 client.set_connect_state()
2360
2361 self._interactInMemory(client, server)
2362
2363 chain = client.get_peer_cert_chain()
2364 self.assertEqual(len(chain), 3)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04002365 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002366 "Server Certificate", chain[0].get_subject().CN)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04002367 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002368 "Intermediate Certificate", chain[1].get_subject().CN)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04002369 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002370 "Authority Certificate", chain[2].get_subject().CN)
2371
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002372 def test_get_peer_cert_chain_none(self):
2373 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002374 :py:obj:`Connection.get_peer_cert_chain` returns :py:obj:`None` if the
2375 peer sends no certificate chain.
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002376 """
2377 ctx = Context(TLSv1_METHOD)
2378 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2379 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
2380 server = Connection(ctx, None)
2381 server.set_accept_state()
2382 client = Connection(Context(TLSv1_METHOD), None)
2383 client.set_connect_state()
2384 self._interactInMemory(client, server)
2385 self.assertIdentical(None, server.get_peer_cert_chain())
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002386
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002387 def test_get_session_wrong_args(self):
2388 """
2389 :py:obj:`Connection.get_session` raises :py:obj:`TypeError` if called
2390 with any arguments.
2391 """
2392 ctx = Context(TLSv1_METHOD)
2393 server = Connection(ctx, None)
2394 self.assertRaises(TypeError, server.get_session, 123)
2395 self.assertRaises(TypeError, server.get_session, "hello")
2396 self.assertRaises(TypeError, server.get_session, object())
2397
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002398 def test_get_session_unconnected(self):
2399 """
2400 :py:obj:`Connection.get_session` returns :py:obj:`None` when used with
2401 an object which has not been connected.
2402 """
2403 ctx = Context(TLSv1_METHOD)
2404 server = Connection(ctx, None)
2405 session = server.get_session()
2406 self.assertIdentical(None, session)
2407
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002408 def test_server_get_session(self):
2409 """
2410 On the server side of a connection, :py:obj:`Connection.get_session`
2411 returns a :py:class:`Session` instance representing the SSL session for
2412 that connection.
2413 """
2414 server, client = self._loopback()
2415 session = server.get_session()
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08002416 self.assertIsInstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002417
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002418 def test_client_get_session(self):
2419 """
2420 On the client side of a connection, :py:obj:`Connection.get_session`
2421 returns a :py:class:`Session` instance representing the SSL session for
2422 that connection.
2423 """
2424 server, client = self._loopback()
2425 session = client.get_session()
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08002426 self.assertIsInstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002427
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002428 def test_set_session_wrong_args(self):
2429 """
Hynek Schlawackdddd1112015-09-05 21:12:30 +02002430 If called with an object that is not an instance of
2431 :py:class:`Session`, or with other than one argument,
2432 :py:obj:`Connection.set_session` raises :py:obj:`TypeError`.
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002433 """
2434 ctx = Context(TLSv1_METHOD)
2435 connection = Connection(ctx, None)
2436 self.assertRaises(TypeError, connection.set_session)
2437 self.assertRaises(TypeError, connection.set_session, 123)
2438 self.assertRaises(TypeError, connection.set_session, "hello")
2439 self.assertRaises(TypeError, connection.set_session, object())
2440 self.assertRaises(
2441 TypeError, connection.set_session, Session(), Session())
2442
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002443 def test_client_set_session(self):
2444 """
2445 :py:obj:`Connection.set_session`, when used prior to a connection being
2446 established, accepts a :py:class:`Session` instance and causes an
2447 attempt to re-use the session it represents when the SSL handshake is
2448 performed.
2449 """
2450 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2451 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
2452 ctx = Context(TLSv1_METHOD)
2453 ctx.use_privatekey(key)
2454 ctx.use_certificate(cert)
2455 ctx.set_session_id("unity-test")
2456
2457 def makeServer(socket):
2458 server = Connection(ctx, socket)
2459 server.set_accept_state()
2460 return server
2461
2462 originalServer, originalClient = self._loopback(
2463 serverFactory=makeServer)
2464 originalSession = originalClient.get_session()
2465
2466 def makeClient(socket):
2467 client = self._loopbackClientFactory(socket)
2468 client.set_session(originalSession)
2469 return client
2470 resumedServer, resumedClient = self._loopback(
2471 serverFactory=makeServer,
2472 clientFactory=makeClient)
2473
2474 # This is a proxy: in general, we have no access to any unique
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002475 # identifier for the session (new enough versions of OpenSSL expose
2476 # a hash which could be usable, but "new enough" is very, very new).
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002477 # Instead, exploit the fact that the master key is re-used if the
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002478 # session is re-used. As long as the master key for the two
2479 # connections is the same, the session was re-used!
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002480 self.assertEqual(
2481 originalServer.master_key(), resumedServer.master_key())
2482
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002483 def test_set_session_wrong_method(self):
2484 """
Jean-Paul Calderone068cb592012-02-14 16:52:43 -05002485 If :py:obj:`Connection.set_session` is passed a :py:class:`Session`
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002486 instance associated with a context using a different SSL method than
2487 the :py:obj:`Connection` is using, a :py:class:`OpenSSL.SSL.Error` is
Jean-Paul Calderone068cb592012-02-14 16:52:43 -05002488 raised.
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002489 """
Alex Gaynor5af32d02016-09-24 01:52:21 -04002490 # Make this work on both OpenSSL 1.0.0, which doesn't support TLSv1.2
2491 # and also on OpenSSL 1.1.0 which doesn't support SSLv3. (SSL_ST_INIT
2492 # is a way to check for 1.1.0)
2493 if SSL_ST_INIT is not None:
2494 v1 = TLSv1_METHOD
2495 v2 = SSLv3_METHOD
2496 else:
2497 v1 = TLSv1_2_METHOD
2498 v2 = TLSv1_METHOD
2499
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002500 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2501 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
Alex Gaynor5af32d02016-09-24 01:52:21 -04002502 ctx = Context(v1)
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002503 ctx.use_privatekey(key)
2504 ctx.use_certificate(cert)
2505 ctx.set_session_id("unity-test")
2506
2507 def makeServer(socket):
2508 server = Connection(ctx, socket)
2509 server.set_accept_state()
2510 return server
2511
Alex Gaynor5af32d02016-09-24 01:52:21 -04002512 def makeOriginalClient(socket):
2513 client = Connection(Context(v1), socket)
2514 client.set_connect_state()
2515 return client
2516
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002517 originalServer, originalClient = self._loopback(
Alex Gaynor5af32d02016-09-24 01:52:21 -04002518 serverFactory=makeServer, clientFactory=makeOriginalClient)
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002519 originalSession = originalClient.get_session()
2520
2521 def makeClient(socket):
2522 # Intentionally use a different, incompatible method here.
Alex Gaynor5af32d02016-09-24 01:52:21 -04002523 client = Connection(Context(v2), socket)
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002524 client.set_connect_state()
2525 client.set_session(originalSession)
2526 return client
2527
2528 self.assertRaises(
2529 Error,
2530 self._loopback, clientFactory=makeClient, serverFactory=makeServer)
2531
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002532 def test_wantWriteError(self):
2533 """
2534 :py:obj:`Connection` methods which generate output raise
2535 :py:obj:`OpenSSL.SSL.WantWriteError` if writing to the connection's BIO
2536 fail indicating a should-write state.
2537 """
2538 client_socket, server_socket = socket_pair()
2539 # Fill up the client's send buffer so Connection won't be able to write
Jean-Paul Calderonebbff8b92014-03-22 14:20:30 -04002540 # anything. Only write a single byte at a time so we can be sure we
2541 # completely fill the buffer. Even though the socket API is allowed to
2542 # signal a short write via its return value it seems this doesn't
2543 # always happen on all platforms (FreeBSD and OS X particular) for the
2544 # very last bit of available buffer space.
2545 msg = b"x"
2546 for i in range(1024 * 1024 * 4):
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002547 try:
2548 client_socket.send(msg)
2549 except error as e:
2550 if e.errno == EWOULDBLOCK:
2551 break
2552 raise
2553 else:
2554 self.fail(
2555 "Failed to fill socket buffer, cannot test BIO want write")
2556
2557 ctx = Context(TLSv1_METHOD)
2558 conn = Connection(ctx, client_socket)
2559 # Client's speak first, so make it an SSL client
2560 conn.set_connect_state()
2561 self.assertRaises(WantWriteError, conn.do_handshake)
2562
2563 # XXX want_read
2564
Fedor Brunner416f4a12014-03-28 13:18:38 +01002565 def test_get_finished_before_connect(self):
Fedor Brunner5747b932014-03-05 14:22:34 +01002566 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002567 :py:obj:`Connection.get_finished` returns :py:obj:`None` before TLS
2568 handshake is completed.
Fedor Brunner5747b932014-03-05 14:22:34 +01002569 """
Fedor Brunner5747b932014-03-05 14:22:34 +01002570 ctx = Context(TLSv1_METHOD)
2571 connection = Connection(ctx, None)
2572 self.assertEqual(connection.get_finished(), None)
Fedor Brunner416f4a12014-03-28 13:18:38 +01002573
2574 def test_get_peer_finished_before_connect(self):
2575 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002576 :py:obj:`Connection.get_peer_finished` returns :py:obj:`None` before
2577 TLS handshake is completed.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002578 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002579 ctx = Context(TLSv1_METHOD)
2580 connection = Connection(ctx, None)
Fedor Brunner5747b932014-03-05 14:22:34 +01002581 self.assertEqual(connection.get_peer_finished(), None)
2582
Fedor Brunner416f4a12014-03-28 13:18:38 +01002583 def test_get_finished(self):
2584 """
2585 :py:obj:`Connection.get_finished` method returns the TLS Finished
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002586 message send from client, or server. Finished messages are send during
2587 TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002588 """
2589
Fedor Brunner5747b932014-03-05 14:22:34 +01002590 server, client = self._loopback()
2591
2592 self.assertNotEqual(server.get_finished(), None)
2593 self.assertTrue(len(server.get_finished()) > 0)
Fedor Brunner416f4a12014-03-28 13:18:38 +01002594
2595 def test_get_peer_finished(self):
2596 """
2597 :py:obj:`Connection.get_peer_finished` method returns the TLS Finished
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002598 message received from client, or server. Finished messages are send
2599 during TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002600 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002601 server, client = self._loopback()
2602
2603 self.assertNotEqual(server.get_peer_finished(), None)
Fedor Brunner5747b932014-03-05 14:22:34 +01002604 self.assertTrue(len(server.get_peer_finished()) > 0)
2605
Fedor Brunner416f4a12014-03-28 13:18:38 +01002606 def test_tls_finished_message_symmetry(self):
2607 """
Hynek Schlawackdddd1112015-09-05 21:12:30 +02002608 The TLS Finished message send by server must be the TLS Finished
2609 message received by client.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002610
Hynek Schlawackdddd1112015-09-05 21:12:30 +02002611 The TLS Finished message send by client must be the TLS Finished
2612 message received by server.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002613 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002614 server, client = self._loopback()
2615
Fedor Brunner5747b932014-03-05 14:22:34 +01002616 self.assertEqual(server.get_finished(), client.get_peer_finished())
2617 self.assertEqual(client.get_finished(), server.get_peer_finished())
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002618
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002619 def test_get_cipher_name_before_connect(self):
2620 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002621 :py:obj:`Connection.get_cipher_name` returns :py:obj:`None` if no
2622 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002623 """
2624 ctx = Context(TLSv1_METHOD)
2625 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002626 self.assertIdentical(conn.get_cipher_name(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002627
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002628 def test_get_cipher_name(self):
2629 """
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002630 :py:obj:`Connection.get_cipher_name` returns a :py:class:`unicode`
2631 string giving the name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002632 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002633 server, client = self._loopback()
2634 server_cipher_name, client_cipher_name = \
2635 server.get_cipher_name(), client.get_cipher_name()
2636
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002637 self.assertIsInstance(server_cipher_name, text_type)
2638 self.assertIsInstance(client_cipher_name, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002639
2640 self.assertEqual(server_cipher_name, client_cipher_name)
2641
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002642 def test_get_cipher_version_before_connect(self):
2643 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002644 :py:obj:`Connection.get_cipher_version` returns :py:obj:`None` if no
2645 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002646 """
2647 ctx = Context(TLSv1_METHOD)
2648 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002649 self.assertIdentical(conn.get_cipher_version(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002650
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002651 def test_get_cipher_version(self):
2652 """
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002653 :py:obj:`Connection.get_cipher_version` returns a :py:class:`unicode`
2654 string giving the protocol name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002655 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002656 server, client = self._loopback()
2657 server_cipher_version, client_cipher_version = \
2658 server.get_cipher_version(), client.get_cipher_version()
2659
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002660 self.assertIsInstance(server_cipher_version, text_type)
2661 self.assertIsInstance(client_cipher_version, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002662
2663 self.assertEqual(server_cipher_version, client_cipher_version)
2664
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002665 def test_get_cipher_bits_before_connect(self):
2666 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002667 :py:obj:`Connection.get_cipher_bits` returns :py:obj:`None` if no
2668 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002669 """
2670 ctx = Context(TLSv1_METHOD)
2671 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002672 self.assertIdentical(conn.get_cipher_bits(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002673
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002674 def test_get_cipher_bits(self):
2675 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002676 :py:obj:`Connection.get_cipher_bits` returns the number of secret bits
2677 of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002678 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002679 server, client = self._loopback()
2680 server_cipher_bits, client_cipher_bits = \
2681 server.get_cipher_bits(), client.get_cipher_bits()
2682
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002683 self.assertIsInstance(server_cipher_bits, int)
2684 self.assertIsInstance(client_cipher_bits, int)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002685
2686 self.assertEqual(server_cipher_bits, client_cipher_bits)
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002687
Jim Shaverabff1882015-05-27 09:15:55 -04002688 def test_get_protocol_version_name(self):
2689 """
2690 :py:obj:`Connection.get_protocol_version_name()` returns a string
2691 giving the protocol version of the current connection.
2692 """
2693 server, client = self._loopback()
2694 client_protocol_version_name = client.get_protocol_version_name()
2695 server_protocol_version_name = server.get_protocol_version_name()
2696
Jim Shaver58d25732015-05-28 11:52:32 -04002697 self.assertIsInstance(server_protocol_version_name, text_type)
2698 self.assertIsInstance(client_protocol_version_name, text_type)
Jim Shaverabff1882015-05-27 09:15:55 -04002699
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002700 self.assertEqual(
2701 server_protocol_version_name, client_protocol_version_name
2702 )
Jim Shaverabff1882015-05-27 09:15:55 -04002703
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002704 def test_get_protocol_version(self):
2705 """
Alex Gaynor43307782015-09-04 09:05:45 -04002706 :py:obj:`Connection.get_protocol_version()` returns an integer
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002707 giving the protocol version of the current connection.
2708 """
2709 server, client = self._loopback()
Jim Shaver85a4dff2015-04-27 17:42:46 -04002710 client_protocol_version = client.get_protocol_version()
2711 server_protocol_version = server.get_protocol_version()
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002712
Jim Shaverabff1882015-05-27 09:15:55 -04002713 self.assertIsInstance(server_protocol_version, int)
2714 self.assertIsInstance(client_protocol_version, int)
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002715
2716 self.assertEqual(server_protocol_version, client_protocol_version)
2717
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002718
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002719class ConnectionGetCipherListTests(TestCase):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002720 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002721 Tests for :py:obj:`Connection.get_cipher_list`.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002722 """
Jean-Paul Calderone54a2bc02010-09-09 17:52:38 -04002723 def test_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002724 """
Hynek Schlawackdddd1112015-09-05 21:12:30 +02002725 :py:obj:`Connection.get_cipher_list` raises :py:obj:`TypeError` if
2726 called with any arguments.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002727 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002728 connection = Connection(Context(TLSv1_METHOD), None)
2729 self.assertRaises(TypeError, connection.get_cipher_list, None)
2730
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002731 def test_result(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002732 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002733 :py:obj:`Connection.get_cipher_list` returns a :py:obj:`list` of
2734 :py:obj:`bytes` giving the names of the ciphers which might be used.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002735 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002736 connection = Connection(Context(TLSv1_METHOD), None)
2737 ciphers = connection.get_cipher_list()
2738 self.assertTrue(isinstance(ciphers, list))
2739 for cipher in ciphers:
2740 self.assertTrue(isinstance(cipher, str))
2741
2742
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002743class ConnectionSendTests(TestCase, _LoopbackMixin):
2744 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002745 Tests for :py:obj:`Connection.send`
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002746 """
2747 def test_wrong_args(self):
2748 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002749 When called with arguments other than string argument for its first
2750 parameter or more than two arguments, :py:obj:`Connection.send` raises
2751 :py:obj:`TypeError`.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002752 """
2753 connection = Connection(Context(TLSv1_METHOD), None)
Jean-Paul Calderone77fa2602011-01-05 18:23:39 -05002754 self.assertRaises(TypeError, connection.send)
2755 self.assertRaises(TypeError, connection.send, object())
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002756 self.assertRaises(TypeError, connection.send, "foo", object(), "bar")
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002757
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002758 def test_short_bytes(self):
2759 """
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002760 When passed a short byte string, :py:obj:`Connection.send` transmits
2761 all of it and returns the number of bytes sent.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002762 """
2763 server, client = self._loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002764 count = server.send(b'xy')
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002765 self.assertEquals(count, 2)
Alex Gaynore7f51982016-09-11 11:48:14 -04002766 self.assertEquals(client.recv(2), b'xy')
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002767
Abraham Martinef063482015-03-25 14:06:24 +00002768 def test_text(self):
2769 """
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002770 When passed a text, :py:obj:`Connection.send` transmits all of it and
2771 returns the number of bytes sent. It also raises a DeprecationWarning.
Abraham Martinef063482015-03-25 14:06:24 +00002772 """
2773 server, client = self._loopback()
2774 with catch_warnings(record=True) as w:
2775 simplefilter("always")
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002776 count = server.send(b"xy".decode("ascii"))
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002777 self.assertEqual(
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002778 "{0} for buf is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002779 WARNING_TYPE_EXPECTED
2780 ),
2781 str(w[-1].message)
2782 )
2783 self.assertIs(w[-1].category, DeprecationWarning)
Abraham Martinef063482015-03-25 14:06:24 +00002784 self.assertEquals(count, 2)
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002785 self.assertEquals(client.recv(2), b"xy")
Abraham Martinef063482015-03-25 14:06:24 +00002786
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002787 @skip_if_py26
2788 def test_short_memoryview(self):
2789 """
2790 When passed a memoryview onto a small number of bytes,
2791 :py:obj:`Connection.send` transmits all of them and returns the number
2792 of bytes sent.
2793 """
2794 server, client = self._loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002795 count = server.send(memoryview(b'xy'))
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002796 self.assertEquals(count, 2)
Alex Gaynore7f51982016-09-11 11:48:14 -04002797 self.assertEquals(client.recv(2), b'xy')
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002798
Hynek Schlawack8e94f1b2015-09-05 21:31:00 +02002799 @skip_if_py3
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002800 def test_short_buffer(self):
2801 """
2802 When passed a buffer containing a small number of bytes,
2803 :py:obj:`Connection.send` transmits all of them and returns the number
2804 of bytes sent.
2805 """
2806 server, client = self._loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002807 count = server.send(buffer(b'xy'))
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002808 self.assertEquals(count, 2)
Alex Gaynore7f51982016-09-11 11:48:14 -04002809 self.assertEquals(client.recv(2), b'xy')
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02002810
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05002811
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002812def _make_memoryview(size):
2813 """
2814 Create a new ``memoryview`` wrapped around a ``bytearray`` of the given
2815 size.
2816 """
2817 return memoryview(bytearray(size))
2818
2819
Cory Benfield62d10332014-06-15 10:03:41 +01002820class ConnectionRecvIntoTests(TestCase, _LoopbackMixin):
2821 """
2822 Tests for :py:obj:`Connection.recv_into`
2823 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002824 def _no_length_test(self, factory):
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04002825 """
2826 Assert that when the given buffer is passed to
2827 ``Connection.recv_into``, whatever bytes are available to be received
2828 that fit into that buffer are written into that buffer.
2829 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002830 output_buffer = factory(5)
2831
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04002832 server, client = self._loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002833 server.send(b'xy')
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04002834
Jean-Paul Calderone320af1e2015-03-15 17:20:13 -04002835 self.assertEqual(client.recv_into(output_buffer), 2)
Alex Gaynore7f51982016-09-11 11:48:14 -04002836 self.assertEqual(output_buffer, bytearray(b'xy\x00\x00\x00'))
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04002837
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002838 def test_bytearray_no_length(self):
Cory Benfield62d10332014-06-15 10:03:41 +01002839 """
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04002840 :py:obj:`Connection.recv_into` can be passed a ``bytearray`` instance
2841 and data in the receive buffer is written to it.
Cory Benfield62d10332014-06-15 10:03:41 +01002842 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002843 self._no_length_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01002844
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002845 def _respects_length_test(self, factory):
Cory Benfield62d10332014-06-15 10:03:41 +01002846 """
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002847 Assert that when the given buffer is passed to ``Connection.recv_into``
2848 along with a value for ``nbytes`` that is less than the size of that
2849 buffer, only ``nbytes`` bytes are written into the buffer.
Cory Benfield62d10332014-06-15 10:03:41 +01002850 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002851 output_buffer = factory(10)
2852
Cory Benfield62d10332014-06-15 10:03:41 +01002853 server, client = self._loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002854 server.send(b'abcdefghij')
Cory Benfield62d10332014-06-15 10:03:41 +01002855
Jean-Paul Calderone320af1e2015-03-15 17:20:13 -04002856 self.assertEqual(client.recv_into(output_buffer, 5), 5)
2857 self.assertEqual(
Alex Gaynore7f51982016-09-11 11:48:14 -04002858 output_buffer, bytearray(b'abcde\x00\x00\x00\x00\x00')
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002859 )
2860
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002861 def test_bytearray_respects_length(self):
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002862 """
2863 When called with a ``bytearray`` instance,
2864 :py:obj:`Connection.recv_into` respects the ``nbytes`` parameter and
2865 doesn't copy in more than that number of bytes.
2866 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002867 self._respects_length_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01002868
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002869 def _doesnt_overfill_test(self, factory):
Cory Benfield62d10332014-06-15 10:03:41 +01002870 """
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002871 Assert that if there are more bytes available to be read from the
2872 receive buffer than would fit into the buffer passed to
2873 :py:obj:`Connection.recv_into`, only as many as fit are written into
2874 it.
Cory Benfield62d10332014-06-15 10:03:41 +01002875 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002876 output_buffer = factory(5)
2877
Cory Benfield62d10332014-06-15 10:03:41 +01002878 server, client = self._loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002879 server.send(b'abcdefghij')
Cory Benfield62d10332014-06-15 10:03:41 +01002880
Jean-Paul Calderone320af1e2015-03-15 17:20:13 -04002881 self.assertEqual(client.recv_into(output_buffer), 5)
Alex Gaynore7f51982016-09-11 11:48:14 -04002882 self.assertEqual(output_buffer, bytearray(b'abcde'))
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002883 rest = client.recv(5)
Alex Gaynore7f51982016-09-11 11:48:14 -04002884 self.assertEqual(b'fghij', rest)
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002885
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002886 def test_bytearray_doesnt_overfill(self):
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002887 """
2888 When called with a ``bytearray`` instance,
2889 :py:obj:`Connection.recv_into` respects the size of the array and
2890 doesn't write more bytes into it than will fit.
2891 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002892 self._doesnt_overfill_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01002893
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002894 def test_bytearray_really_doesnt_overfill(self):
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04002895 """
2896 When called with a ``bytearray`` instance and an ``nbytes`` value that
2897 is too large, :py:obj:`Connection.recv_into` respects the size of the
2898 array and not the ``nbytes`` value and doesn't write more bytes into
2899 the buffer than will fit.
2900 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002901 self._doesnt_overfill_test(bytearray)
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04002902
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002903 def test_peek(self):
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002904 server, client = self._loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002905 server.send(b'xy')
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002906
2907 for _ in range(2):
2908 output_buffer = bytearray(5)
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002909 self.assertEqual(
2910 client.recv_into(output_buffer, flags=MSG_PEEK), 2)
Alex Gaynore7f51982016-09-11 11:48:14 -04002911 self.assertEqual(output_buffer, bytearray(b'xy\x00\x00\x00'))
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002912
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002913 @skip_if_py26
2914 def test_memoryview_no_length(self):
2915 """
2916 :py:obj:`Connection.recv_into` can be passed a ``memoryview``
2917 instance and data in the receive buffer is written to it.
2918 """
2919 self._no_length_test(_make_memoryview)
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002920
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002921 @skip_if_py26
2922 def test_memoryview_respects_length(self):
2923 """
2924 When called with a ``memoryview`` instance,
2925 :py:obj:`Connection.recv_into` respects the ``nbytes`` parameter
2926 and doesn't copy more than that number of bytes in.
2927 """
2928 self._respects_length_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01002929
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002930 @skip_if_py26
2931 def test_memoryview_doesnt_overfill(self):
2932 """
2933 When called with a ``memoryview`` instance,
2934 :py:obj:`Connection.recv_into` respects the size of the array and
2935 doesn't write more bytes into it than will fit.
2936 """
2937 self._doesnt_overfill_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01002938
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002939 @skip_if_py26
2940 def test_memoryview_really_doesnt_overfill(self):
2941 """
2942 When called with a ``memoryview`` instance and an ``nbytes`` value
2943 that is too large, :py:obj:`Connection.recv_into` respects the size
2944 of the array and not the ``nbytes`` value and doesn't write more
2945 bytes into the buffer than will fit.
2946 """
2947 self._doesnt_overfill_test(_make_memoryview)
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04002948
Cory Benfield62d10332014-06-15 10:03:41 +01002949
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002950class ConnectionSendallTests(TestCase, _LoopbackMixin):
2951 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002952 Tests for :py:obj:`Connection.sendall`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002953 """
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002954 def test_wrong_args(self):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002955 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002956 When called with arguments other than a string argument for its first
2957 parameter or with more than two arguments, :py:obj:`Connection.sendall`
2958 raises :py:obj:`TypeError`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002959 """
2960 connection = Connection(Context(TLSv1_METHOD), None)
2961 self.assertRaises(TypeError, connection.sendall)
2962 self.assertRaises(TypeError, connection.sendall, object())
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002963 self.assertRaises(
2964 TypeError, connection.sendall, "foo", object(), "bar")
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002965
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002966 def test_short(self):
2967 """
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02002968 :py:obj:`Connection.sendall` transmits all of the bytes in the string
2969 passed to it.
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002970 """
2971 server, client = self._loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002972 server.sendall(b'x')
2973 self.assertEquals(client.recv(1), b'x')
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002974
Abraham Martinef063482015-03-25 14:06:24 +00002975 def test_text(self):
2976 """
Jean-Paul Calderone93477422015-04-13 20:38:57 -04002977 :py:obj:`Connection.sendall` transmits all the content in the string
2978 passed to it raising a DeprecationWarning in case of this being a text.
Abraham Martinef063482015-03-25 14:06:24 +00002979 """
2980 server, client = self._loopback()
2981 with catch_warnings(record=True) as w:
2982 simplefilter("always")
Jean-Paul Calderone8dc37a12015-03-29 08:16:52 -04002983 server.sendall(b"x".decode("ascii"))
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002984 self.assertEqual(
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002985 "{0} for buf is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002986 WARNING_TYPE_EXPECTED
2987 ),
2988 str(w[-1].message)
2989 )
2990 self.assertIs(w[-1].category, DeprecationWarning)
2991 self.assertEquals(client.recv(1), b"x")
Abraham Martinef063482015-03-25 14:06:24 +00002992
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02002993 @skip_if_py26
2994 def test_short_memoryview(self):
2995 """
2996 When passed a memoryview onto a small number of bytes,
2997 :py:obj:`Connection.sendall` transmits all of them.
2998 """
2999 server, client = self._loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04003000 server.sendall(memoryview(b'x'))
3001 self.assertEquals(client.recv(1), b'x')
Abraham Martinef063482015-03-25 14:06:24 +00003002
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003003 @skip_if_py3
3004 def test_short_buffers(self):
3005 """
3006 When passed a buffer containing a small number of bytes,
3007 :py:obj:`Connection.sendall` transmits all of them.
3008 """
3009 server, client = self._loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04003010 server.sendall(buffer(b'x'))
3011 self.assertEquals(client.recv(1), b'x')
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02003012
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003013 def test_long(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003014 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003015 :py:obj:`Connection.sendall` transmits all of the bytes in the string
3016 passed to it even if this requires multiple calls of an underlying
3017 write function.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003018 """
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003019 server, client = self._loopback()
Jean-Paul Calderone6241c702010-09-16 19:59:24 -04003020 # Should be enough, underlying SSL_write should only do 16k at a time.
Hynek Schlawack35618382015-09-05 21:54:25 +02003021 # On Windows, after 32k of bytes the write will block (forever
3022 # - because no one is yet reading).
Alex Gaynore7f51982016-09-11 11:48:14 -04003023 message = b'x' * (1024 * 32 - 1) + b'y'
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003024 server.sendall(message)
3025 accum = []
3026 received = 0
3027 while received < len(message):
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04003028 data = client.recv(1024)
3029 accum.append(data)
3030 received += len(data)
Alex Gaynore7f51982016-09-11 11:48:14 -04003031 self.assertEquals(message, b''.join(accum))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003032
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003033 def test_closed(self):
3034 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003035 If the underlying socket is closed, :py:obj:`Connection.sendall`
3036 propagates the write error from the low level write call.
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003037 """
3038 server, client = self._loopback()
Jean-Paul Calderone05d43e82010-09-24 18:01:36 -04003039 server.sock_shutdown(2)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003040 exc = self.assertRaises(SysCallError, server.sendall, b"hello, world")
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +02003041 if platform == "win32":
3042 self.assertEqual(exc.args[0], ESHUTDOWN)
3043 else:
3044 self.assertEqual(exc.args[0], EPIPE)
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003045
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003046
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003047class ConnectionRenegotiateTests(TestCase, _LoopbackMixin):
3048 """
3049 Tests for SSL renegotiation APIs.
3050 """
3051 def test_renegotiate_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003052 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003053 :py:obj:`Connection.renegotiate` raises :py:obj:`TypeError` if called
3054 with any arguments.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003055 """
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003056 connection = Connection(Context(TLSv1_METHOD), None)
3057 self.assertRaises(TypeError, connection.renegotiate, None)
3058
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003059 def test_total_renegotiations_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003060 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003061 :py:obj:`Connection.total_renegotiations` raises :py:obj:`TypeError` if
3062 called with any arguments.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003063 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003064 connection = Connection(Context(TLSv1_METHOD), None)
3065 self.assertRaises(TypeError, connection.total_renegotiations, None)
3066
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003067 def test_total_renegotiations(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003068 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003069 :py:obj:`Connection.total_renegotiations` returns :py:obj:`0` before
3070 any renegotiations have happened.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003071 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003072 connection = Connection(Context(TLSv1_METHOD), None)
3073 self.assertEquals(connection.total_renegotiations(), 0)
3074
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003075 def test_renegotiate(self):
3076 """
3077 Go through a complete renegotiation cycle.
3078 """
3079 server, client = self._loopback()
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003080
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003081 server.send(b"hello world")
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003082
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003083 assert b"hello world" == client.recv(len(b"hello world"))
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003084
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003085 assert 0 == server.total_renegotiations()
3086 assert False is server.renegotiate_pending()
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003087
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003088 assert True is server.renegotiate()
3089
3090 assert True is server.renegotiate_pending()
3091
3092 server.setblocking(False)
3093 client.setblocking(False)
3094
3095 client.do_handshake()
3096 server.do_handshake()
3097
3098 assert 1 == server.total_renegotiations()
3099 while False is server.renegotiate_pending():
3100 pass
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003101
3102
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003103class ErrorTests(TestCase):
3104 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003105 Unit tests for :py:obj:`OpenSSL.SSL.Error`.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003106 """
3107 def test_type(self):
3108 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003109 :py:obj:`Error` is an exception type.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003110 """
3111 self.assertTrue(issubclass(Error, Exception))
Rick Deane15b1472009-07-09 15:53:42 -05003112 self.assertEqual(Error.__name__, 'Error')
Rick Deane15b1472009-07-09 15:53:42 -05003113
3114
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003115class ConstantsTests(TestCase):
3116 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003117 Tests for the values of constants exposed in :py:obj:`OpenSSL.SSL`.
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003118
3119 These are values defined by OpenSSL intended only to be used as flags to
3120 OpenSSL APIs. The only assertions it seems can be made about them is
3121 their values.
3122 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003123 @pytest.mark.skipif(
3124 OP_NO_QUERY_MTU is None,
3125 reason="OP_NO_QUERY_MTU unavailable - OpenSSL version may be too old"
3126 )
3127 def test_op_no_query_mtu(self):
3128 """
3129 The value of :py:obj:`OpenSSL.SSL.OP_NO_QUERY_MTU` is 0x1000, the value
3130 of :py:const:`SSL_OP_NO_QUERY_MTU` defined by :file:`openssl/ssl.h`.
3131 """
3132 self.assertEqual(OP_NO_QUERY_MTU, 0x1000)
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003133
Hynek Schlawack35618382015-09-05 21:54:25 +02003134 @pytest.mark.skipif(
3135 OP_COOKIE_EXCHANGE is None,
3136 reason="OP_COOKIE_EXCHANGE unavailable - "
3137 "OpenSSL version may be too old"
3138 )
3139 def test_op_cookie_exchange(self):
3140 """
3141 The value of :py:obj:`OpenSSL.SSL.OP_COOKIE_EXCHANGE` is 0x2000, the
3142 value of :py:const:`SSL_OP_COOKIE_EXCHANGE` defined by
3143 :file:`openssl/ssl.h`.
3144 """
3145 self.assertEqual(OP_COOKIE_EXCHANGE, 0x2000)
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003146
Hynek Schlawack35618382015-09-05 21:54:25 +02003147 @pytest.mark.skipif(
3148 OP_NO_TICKET is None,
3149 reason="OP_NO_TICKET unavailable - OpenSSL version may be too old"
3150 )
3151 def test_op_no_ticket(self):
3152 """
3153 The value of :py:obj:`OpenSSL.SSL.OP_NO_TICKET` is 0x4000, the value of
3154 :py:const:`SSL_OP_NO_TICKET` defined by :file:`openssl/ssl.h`.
3155 """
3156 self.assertEqual(OP_NO_TICKET, 0x4000)
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003157
Hynek Schlawack35618382015-09-05 21:54:25 +02003158 @pytest.mark.skipif(
3159 OP_NO_COMPRESSION is None,
3160 reason="OP_NO_COMPRESSION unavailable - OpenSSL version may be too old"
3161 )
3162 def test_op_no_compression(self):
3163 """
3164 The value of :py:obj:`OpenSSL.SSL.OP_NO_COMPRESSION` is 0x20000, the
3165 value of :py:const:`SSL_OP_NO_COMPRESSION` defined by
3166 :file:`openssl/ssl.h`.
3167 """
3168 self.assertEqual(OP_NO_COMPRESSION, 0x20000)
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04003169
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003170 def test_sess_cache_off(self):
3171 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003172 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_OFF` 0x0, the value of
3173 :py:obj:`SSL_SESS_CACHE_OFF` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003174 """
3175 self.assertEqual(0x0, SESS_CACHE_OFF)
3176
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003177 def test_sess_cache_client(self):
3178 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003179 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_CLIENT` 0x1, the value of
3180 :py:obj:`SSL_SESS_CACHE_CLIENT` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003181 """
3182 self.assertEqual(0x1, SESS_CACHE_CLIENT)
3183
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003184 def test_sess_cache_server(self):
3185 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003186 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_SERVER` 0x2, the value of
3187 :py:obj:`SSL_SESS_CACHE_SERVER` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003188 """
3189 self.assertEqual(0x2, SESS_CACHE_SERVER)
3190
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003191 def test_sess_cache_both(self):
3192 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003193 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_BOTH` 0x3, the value of
3194 :py:obj:`SSL_SESS_CACHE_BOTH` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003195 """
3196 self.assertEqual(0x3, SESS_CACHE_BOTH)
3197
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003198 def test_sess_cache_no_auto_clear(self):
3199 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003200 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_AUTO_CLEAR` 0x80, the
3201 value of :py:obj:`SSL_SESS_CACHE_NO_AUTO_CLEAR` defined by
3202 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003203 """
3204 self.assertEqual(0x80, SESS_CACHE_NO_AUTO_CLEAR)
3205
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003206 def test_sess_cache_no_internal_lookup(self):
3207 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003208 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_LOOKUP` 0x100,
3209 the value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL_LOOKUP` defined by
3210 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003211 """
3212 self.assertEqual(0x100, SESS_CACHE_NO_INTERNAL_LOOKUP)
3213
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003214 def test_sess_cache_no_internal_store(self):
3215 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003216 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_STORE` 0x200,
3217 the value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL_STORE` defined by
3218 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003219 """
3220 self.assertEqual(0x200, SESS_CACHE_NO_INTERNAL_STORE)
3221
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003222 def test_sess_cache_no_internal(self):
3223 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003224 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL` 0x300, the
3225 value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL` defined by
3226 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003227 """
3228 self.assertEqual(0x300, SESS_CACHE_NO_INTERNAL)
3229
3230
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003231class MemoryBIOTests(TestCase, _LoopbackMixin):
Rick Deanb71c0d22009-04-01 14:09:23 -05003232 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003233 Tests for :py:obj:`OpenSSL.SSL.Connection` using a memory BIO.
Rick Deanb71c0d22009-04-01 14:09:23 -05003234 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003235 def _server(self, sock):
3236 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003237 Create a new server-side SSL :py:obj:`Connection` object wrapped around
3238 :py:obj:`sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003239 """
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003240 # Create the server side Connection. This is mostly setup boilerplate
3241 # - use TLSv1, use a particular certificate, etc.
3242 server_ctx = Context(TLSv1_METHOD)
Alex Gaynor43307782015-09-04 09:05:45 -04003243 server_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE)
Hynek Schlawack35618382015-09-05 21:54:25 +02003244 server_ctx.set_verify(
3245 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT | VERIFY_CLIENT_ONCE,
3246 verify_cb
3247 )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003248 server_store = server_ctx.get_cert_store()
Hynek Schlawack35618382015-09-05 21:54:25 +02003249 server_ctx.use_privatekey(
3250 load_privatekey(FILETYPE_PEM, server_key_pem))
3251 server_ctx.use_certificate(
3252 load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003253 server_ctx.check_privatekey()
3254 server_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Hynek Schlawack35618382015-09-05 21:54:25 +02003255 # Here the Connection is actually created. If None is passed as the
3256 # 2nd parameter, it indicates a memory BIO should be created.
Rick Deanb1ccd562009-07-09 23:52:39 -05003257 server_conn = Connection(server_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003258 server_conn.set_accept_state()
3259 return server_conn
3260
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003261 def _client(self, sock):
3262 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003263 Create a new client-side SSL :py:obj:`Connection` object wrapped around
3264 :py:obj:`sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003265 """
3266 # Now create the client side Connection. Similar boilerplate to the
3267 # above.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003268 client_ctx = Context(TLSv1_METHOD)
Alex Gaynor43307782015-09-04 09:05:45 -04003269 client_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE)
Hynek Schlawack35618382015-09-05 21:54:25 +02003270 client_ctx.set_verify(
3271 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT | VERIFY_CLIENT_ONCE,
3272 verify_cb
3273 )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003274 client_store = client_ctx.get_cert_store()
Hynek Schlawack35618382015-09-05 21:54:25 +02003275 client_ctx.use_privatekey(
3276 load_privatekey(FILETYPE_PEM, client_key_pem))
3277 client_ctx.use_certificate(
3278 load_certificate(FILETYPE_PEM, client_cert_pem))
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003279 client_ctx.check_privatekey()
3280 client_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05003281 client_conn = Connection(client_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003282 client_conn.set_connect_state()
3283 return client_conn
3284
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003285 def test_memoryConnect(self):
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003286 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003287 Two :py:obj:`Connection`s which use memory BIOs can be manually
3288 connected by reading from the output of each and writing those bytes to
3289 the input of the other and in this way establish a connection and
3290 exchange application-level bytes with each other.
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003291 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003292 server_conn = self._server(None)
3293 client_conn = self._client(None)
Rick Deanb71c0d22009-04-01 14:09:23 -05003294
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003295 # There should be no key or nonces yet.
3296 self.assertIdentical(server_conn.master_key(), None)
3297 self.assertIdentical(server_conn.client_random(), None)
3298 self.assertIdentical(server_conn.server_random(), None)
Rick Deanb71c0d22009-04-01 14:09:23 -05003299
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003300 # First, the handshake needs to happen. We'll deliver bytes back and
3301 # forth between the client and server until neither of them feels like
3302 # speaking any more.
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003303 self.assertIdentical(
3304 self._interactInMemory(client_conn, server_conn), None)
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003305
3306 # Now that the handshake is done, there should be a key and nonces.
3307 self.assertNotIdentical(server_conn.master_key(), None)
3308 self.assertNotIdentical(server_conn.client_random(), None)
3309 self.assertNotIdentical(server_conn.server_random(), None)
Hynek Schlawack35618382015-09-05 21:54:25 +02003310 self.assertEquals(
3311 server_conn.client_random(), client_conn.client_random())
3312 self.assertEquals(
3313 server_conn.server_random(), client_conn.server_random())
3314 self.assertNotEquals(
3315 server_conn.client_random(), server_conn.server_random())
3316 self.assertNotEquals(
3317 client_conn.client_random(), client_conn.server_random())
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003318
3319 # Here are the bytes we'll try to send.
Alex Gaynore7f51982016-09-11 11:48:14 -04003320 important_message = b'One if by land, two if by sea.'
Rick Deanb71c0d22009-04-01 14:09:23 -05003321
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003322 server_conn.write(important_message)
3323 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003324 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003325 (client_conn, important_message))
3326
3327 client_conn.write(important_message[::-1])
3328 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003329 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003330 (server_conn, important_message[::-1]))
Rick Deanb71c0d22009-04-01 14:09:23 -05003331
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003332 def test_socketConnect(self):
Rick Deanb1ccd562009-07-09 23:52:39 -05003333 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003334 Just like :py:obj:`test_memoryConnect` but with an actual socket.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003335
Hynek Schlawack35618382015-09-05 21:54:25 +02003336 This is primarily to rule out the memory BIO code as the source of any
3337 problems encountered while passing data over a :py:obj:`Connection` (if
3338 this test fails, there must be a problem outside the memory BIO code,
3339 as no memory BIO is involved here). Even though this isn't a memory
3340 BIO test, it's convenient to have it here.
Rick Deanb1ccd562009-07-09 23:52:39 -05003341 """
Jean-Paul Calderone06c7cc92010-09-24 23:52:00 -04003342 server_conn, client_conn = self._loopback()
Rick Deanb1ccd562009-07-09 23:52:39 -05003343
Alex Gaynore7f51982016-09-11 11:48:14 -04003344 important_message = b"Help me Obi Wan Kenobi, you're my only hope."
Rick Deanb1ccd562009-07-09 23:52:39 -05003345 client_conn.send(important_message)
3346 msg = server_conn.recv(1024)
3347 self.assertEqual(msg, important_message)
3348
3349 # Again in the other direction, just for fun.
3350 important_message = important_message[::-1]
3351 server_conn.send(important_message)
3352 msg = client_conn.recv(1024)
3353 self.assertEqual(msg, important_message)
3354
Jean-Paul Calderonefc4ed0f2009-04-27 11:51:27 -04003355 def test_socketOverridesMemory(self):
Rick Deanb71c0d22009-04-01 14:09:23 -05003356 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003357 Test that :py:obj:`OpenSSL.SSL.bio_read` and
3358 :py:obj:`OpenSSL.SSL.bio_write` don't work on
3359 :py:obj:`OpenSSL.SSL.Connection`() that use sockets.
Rick Deanb71c0d22009-04-01 14:09:23 -05003360 """
Alex Gaynor51d424c2016-09-10 14:50:11 -04003361 context = Context(TLSv1_METHOD)
Rick Deanb71c0d22009-04-01 14:09:23 -05003362 client = socket()
3363 clientSSL = Connection(context, client)
Alex Gaynor43307782015-09-04 09:05:45 -04003364 self.assertRaises(TypeError, clientSSL.bio_read, 100)
3365 self.assertRaises(TypeError, clientSSL.bio_write, "foo")
Alex Gaynor7e8b61e2015-09-04 13:13:05 -04003366 self.assertRaises(TypeError, clientSSL.bio_shutdown)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003367
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003368 def test_outgoingOverflow(self):
3369 """
3370 If more bytes than can be written to the memory BIO are passed to
Hynek Schlawack35618382015-09-05 21:54:25 +02003371 :py:obj:`Connection.send` at once, the number of bytes which were
3372 written is returned and that many bytes from the beginning of the input
3373 can be read from the other end of the connection.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003374 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003375 server = self._server(None)
3376 client = self._client(None)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003377
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003378 self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003379
3380 size = 2 ** 15
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003381 sent = client.send(b"x" * size)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003382 # Sanity check. We're trying to test what happens when the entire
3383 # input can't be sent. If the entire input was sent, this test is
3384 # meaningless.
3385 self.assertTrue(sent < size)
3386
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003387 receiver, received = self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003388 self.assertIdentical(receiver, server)
3389
3390 # We can rely on all of these bytes being received at once because
3391 # _loopback passes 2 ** 16 to recv - more than 2 ** 15.
3392 self.assertEquals(len(received), sent)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003393
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003394 def test_shutdown(self):
3395 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003396 :py:obj:`Connection.bio_shutdown` signals the end of the data stream
3397 from which the :py:obj:`Connection` reads.
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003398 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003399 server = self._server(None)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003400 server.bio_shutdown()
3401 e = self.assertRaises(Error, server.recv, 1024)
3402 # We don't want WantReadError or ZeroReturnError or anything - it's a
3403 # handshake failure.
Alex Gaynor5af32d02016-09-24 01:52:21 -04003404 assert type(e) in [Error, SysCallError]
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003405
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003406 def test_unexpectedEndOfFile(self):
3407 """
3408 If the connection is lost before an orderly SSL shutdown occurs,
3409 :py:obj:`OpenSSL.SSL.SysCallError` is raised with a message of
3410 "Unexpected EOF".
3411 """
3412 server_conn, client_conn = self._loopback()
3413 client_conn.sock_shutdown(SHUT_RDWR)
3414 exc = self.assertRaises(SysCallError, server_conn.recv, 1024)
3415 self.assertEqual(exc.args, (-1, "Unexpected EOF"))
3416
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003417 def _check_client_ca_list(self, func):
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003418 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003419 Verify the return value of the :py:obj:`get_client_ca_list` method for
3420 server and client connections.
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003421
Jonathan Ballet78b92a22011-07-16 08:07:26 +09003422 :param func: A function which will be called with the server context
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003423 before the client and server are connected to each other. This
3424 function should specify a list of CAs for the server to send to the
3425 client and return that same list. The list will be used to verify
Hynek Schlawack35618382015-09-05 21:54:25 +02003426 that :py:obj:`get_client_ca_list` returns the proper value at
3427 various times.
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003428 """
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003429 server = self._server(None)
3430 client = self._client(None)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003431 self.assertEqual(client.get_client_ca_list(), [])
3432 self.assertEqual(server.get_client_ca_list(), [])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003433 ctx = server.get_context()
3434 expected = func(ctx)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003435 self.assertEqual(client.get_client_ca_list(), [])
3436 self.assertEqual(server.get_client_ca_list(), expected)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003437 self._interactInMemory(client, server)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003438 self.assertEqual(client.get_client_ca_list(), expected)
3439 self.assertEqual(server.get_client_ca_list(), expected)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003440
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003441 def test_set_client_ca_list_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003442 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003443 :py:obj:`Context.set_client_ca_list` raises a :py:obj:`TypeError` if
3444 called with a non-list or a list that contains objects other than
3445 X509Names.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003446 """
3447 ctx = Context(TLSv1_METHOD)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003448 self.assertRaises(TypeError, ctx.set_client_ca_list, "spam")
3449 self.assertRaises(TypeError, ctx.set_client_ca_list, ["spam"])
3450 self.assertIdentical(ctx.set_client_ca_list([]), None)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003451
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003452 def test_set_empty_ca_list(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003453 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003454 If passed an empty list, :py:obj:`Context.set_client_ca_list`
3455 configures the context to send no CA names to the client and, on both
3456 the server and client sides, :py:obj:`Connection.get_client_ca_list`
3457 returns an empty list after the connection is set up.
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003458 """
3459 def no_ca(ctx):
3460 ctx.set_client_ca_list([])
3461 return []
3462 self._check_client_ca_list(no_ca)
3463
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003464 def test_set_one_ca_list(self):
3465 """
3466 If passed a list containing a single X509Name,
Hynek Schlawack35618382015-09-05 21:54:25 +02003467 :py:obj:`Context.set_client_ca_list` configures the context to send
3468 that CA name to the client and, on both the server and client sides,
Jonathan Ballet648875f2011-07-16 14:14:58 +09003469 :py:obj:`Connection.get_client_ca_list` returns a list containing that
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003470 X509Name after the connection is set up.
3471 """
3472 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3473 cadesc = cacert.get_subject()
Hynek Schlawack35618382015-09-05 21:54:25 +02003474
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003475 def single_ca(ctx):
3476 ctx.set_client_ca_list([cadesc])
3477 return [cadesc]
3478 self._check_client_ca_list(single_ca)
3479
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003480 def test_set_multiple_ca_list(self):
3481 """
3482 If passed a list containing multiple X509Name objects,
Hynek Schlawack35618382015-09-05 21:54:25 +02003483 :py:obj:`Context.set_client_ca_list` configures the context to send
3484 those CA names to the client and, on both the server and client sides,
Jonathan Ballet648875f2011-07-16 14:14:58 +09003485 :py:obj:`Connection.get_client_ca_list` returns a list containing those
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003486 X509Names after the connection is set up.
3487 """
3488 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3489 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3490
3491 sedesc = secert.get_subject()
3492 cldesc = clcert.get_subject()
3493
3494 def multiple_ca(ctx):
3495 L = [sedesc, cldesc]
3496 ctx.set_client_ca_list(L)
3497 return L
3498 self._check_client_ca_list(multiple_ca)
3499
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003500 def test_reset_ca_list(self):
3501 """
3502 If called multiple times, only the X509Names passed to the final call
Hynek Schlawack35618382015-09-05 21:54:25 +02003503 of :py:obj:`Context.set_client_ca_list` are used to configure the CA
3504 names sent to the client.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003505 """
3506 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3507 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3508 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3509
3510 cadesc = cacert.get_subject()
3511 sedesc = secert.get_subject()
3512 cldesc = clcert.get_subject()
3513
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003514 def changed_ca(ctx):
3515 ctx.set_client_ca_list([sedesc, cldesc])
3516 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003517 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003518 self._check_client_ca_list(changed_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003519
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003520 def test_mutated_ca_list(self):
3521 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003522 If the list passed to :py:obj:`Context.set_client_ca_list` is mutated
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003523 afterwards, this does not affect the list of CA names sent to the
3524 client.
3525 """
3526 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3527 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3528
3529 cadesc = cacert.get_subject()
3530 sedesc = secert.get_subject()
3531
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003532 def mutated_ca(ctx):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003533 L = [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003534 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003535 L.append(sedesc)
3536 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003537 self._check_client_ca_list(mutated_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003538
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003539 def test_add_client_ca_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003540 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003541 :py:obj:`Context.add_client_ca` raises :py:obj:`TypeError` if called
3542 with a non-X509 object or with a number of arguments other than one.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003543 """
3544 ctx = Context(TLSv1_METHOD)
3545 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003546 self.assertRaises(TypeError, ctx.add_client_ca)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003547 self.assertRaises(TypeError, ctx.add_client_ca, "spam")
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003548 self.assertRaises(TypeError, ctx.add_client_ca, cacert, cacert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003549
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003550 def test_one_add_client_ca(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003551 """
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003552 A certificate's subject can be added as a CA to be sent to the client
Jonathan Ballet648875f2011-07-16 14:14:58 +09003553 with :py:obj:`Context.add_client_ca`.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003554 """
3555 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3556 cadesc = cacert.get_subject()
Hynek Schlawack35618382015-09-05 21:54:25 +02003557
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003558 def single_ca(ctx):
3559 ctx.add_client_ca(cacert)
3560 return [cadesc]
3561 self._check_client_ca_list(single_ca)
3562
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003563 def test_multiple_add_client_ca(self):
3564 """
3565 Multiple CA names can be sent to the client by calling
Jonathan Ballet648875f2011-07-16 14:14:58 +09003566 :py:obj:`Context.add_client_ca` with multiple X509 objects.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003567 """
3568 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3569 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3570
3571 cadesc = cacert.get_subject()
3572 sedesc = secert.get_subject()
3573
3574 def multiple_ca(ctx):
3575 ctx.add_client_ca(cacert)
3576 ctx.add_client_ca(secert)
3577 return [cadesc, sedesc]
3578 self._check_client_ca_list(multiple_ca)
3579
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003580 def test_set_and_add_client_ca(self):
3581 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003582 A call to :py:obj:`Context.set_client_ca_list` followed by a call to
Hynek Schlawack35618382015-09-05 21:54:25 +02003583 :py:obj:`Context.add_client_ca` results in using the CA names from the
3584 first call and the CA name from the second call.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003585 """
3586 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3587 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3588 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3589
3590 cadesc = cacert.get_subject()
3591 sedesc = secert.get_subject()
3592 cldesc = clcert.get_subject()
3593
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003594 def mixed_set_add_ca(ctx):
3595 ctx.set_client_ca_list([cadesc, sedesc])
3596 ctx.add_client_ca(clcert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003597 return [cadesc, sedesc, cldesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003598 self._check_client_ca_list(mixed_set_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003599
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003600 def test_set_after_add_client_ca(self):
3601 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003602 A call to :py:obj:`Context.set_client_ca_list` after a call to
Hynek Schlawack35618382015-09-05 21:54:25 +02003603 :py:obj:`Context.add_client_ca` replaces the CA name specified by the
3604 former call with the names specified by the latter call.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003605 """
3606 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3607 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3608 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3609
3610 cadesc = cacert.get_subject()
3611 sedesc = secert.get_subject()
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003612
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003613 def set_replaces_add_ca(ctx):
3614 ctx.add_client_ca(clcert)
3615 ctx.set_client_ca_list([cadesc])
3616 ctx.add_client_ca(secert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003617 return [cadesc, sedesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003618 self._check_client_ca_list(set_replaces_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003619
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003620
Alex Chandeec9342016-12-19 22:00:38 +00003621class TestConnection(object):
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003622 """
Alex Chandeec9342016-12-19 22:00:38 +00003623 Tests for `Connection.bio_read` and `Connection.bio_write`.
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003624 """
3625 def test_wantReadError(self):
3626 """
Alex Chandeec9342016-12-19 22:00:38 +00003627 `Connection.bio_read` raises `OpenSSL.SSL.WantReadError` if there are
3628 no bytes available to be read from the BIO.
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003629 """
3630 ctx = Context(TLSv1_METHOD)
3631 conn = Connection(ctx, None)
Alex Chandeec9342016-12-19 22:00:38 +00003632 with pytest.raises(WantReadError):
3633 conn.bio_read(1024)
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003634
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003635 def test_buffer_size(self):
3636 """
Alex Chandeec9342016-12-19 22:00:38 +00003637 `Connection.bio_read` accepts an integer giving the maximum number
3638 of bytes to read and return.
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003639 """
3640 ctx = Context(TLSv1_METHOD)
3641 conn = Connection(ctx, None)
3642 conn.set_connect_state()
3643 try:
3644 conn.do_handshake()
3645 except WantReadError:
3646 pass
3647 data = conn.bio_read(2)
Alex Chandeec9342016-12-19 22:00:38 +00003648 assert 2 == len(data)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003649
Hynek Schlawack35618382015-09-05 21:54:25 +02003650 @skip_if_py3
3651 def test_buffer_size_long(self):
3652 """
Alex Chandeec9342016-12-19 22:00:38 +00003653 On Python 2 `Connection.bio_read` accepts values of type `long` as
3654 well as `int`.
Hynek Schlawack35618382015-09-05 21:54:25 +02003655 """
3656 ctx = Context(TLSv1_METHOD)
3657 conn = Connection(ctx, None)
3658 conn.set_connect_state()
3659 try:
3660 conn.do_handshake()
3661 except WantReadError:
3662 pass
3663 data = conn.bio_read(long(2))
Alex Chandeec9342016-12-19 22:00:38 +00003664 assert 2 == len(data)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003665
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003666
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003667class InfoConstantTests(TestCase):
3668 """
3669 Tests for assorted constants exposed for use in info callbacks.
3670 """
3671 def test_integers(self):
3672 """
3673 All of the info constants are integers.
3674
3675 This is a very weak test. It would be nice to have one that actually
3676 verifies that as certain info events happen, the value passed to the
3677 info callback matches up with the constant exposed by OpenSSL.SSL.
3678 """
3679 for const in [
Alex Gaynor5af32d02016-09-24 01:52:21 -04003680 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK,
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003681 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
3682 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
3683 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
Hynek Schlawack35618382015-09-05 21:54:25 +02003684 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE
3685 ]:
Alex Gaynor5af32d02016-09-24 01:52:21 -04003686 assert isinstance(const, int)
3687
3688 # These constants don't exist on OpenSSL 1.1.0
3689 for const in [
3690 SSL_ST_INIT, SSL_ST_BEFORE, SSL_ST_OK, SSL_ST_RENEGOTIATE
3691 ]:
3692 assert const is None or isinstance(const, int)
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003693
Ziga Seilnacht44611bf2009-08-31 20:49:30 +02003694
Cory Benfield1d142142016-03-30 11:51:45 +01003695class TestRequires(object):
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003696 """
3697 Tests for the decorator factory used to conditionally raise
Cory Benfield1d142142016-03-30 11:51:45 +01003698 NotImplementedError when older OpenSSLs are used.
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003699 """
3700 def test_available(self):
3701 """
3702 When the OpenSSL functionality is available the decorated functions
3703 work appropriately.
3704 """
3705 feature_guard = _make_requires(True, "Error text")
3706 results = []
3707
3708 @feature_guard
3709 def inner():
3710 results.append(True)
3711 return True
3712
Cory Benfield2333e5e2016-03-30 14:24:16 +01003713 assert inner() is True
3714 assert [True] == results
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003715
3716 def test_unavailable(self):
3717 """
3718 When the OpenSSL functionality is not available the decorated function
3719 does not execute and NotImplementedError is raised.
3720 """
3721 feature_guard = _make_requires(False, "Error text")
3722 results = []
3723
3724 @feature_guard
3725 def inner():
3726 results.append(True)
3727 return True
3728
Cory Benfield1d142142016-03-30 11:51:45 +01003729 with pytest.raises(NotImplementedError) as e:
3730 inner()
3731
3732 assert "Error text" in str(e.value)
Cory Benfield2333e5e2016-03-30 14:24:16 +01003733 assert results == []
Cory Benfield496652a2017-01-24 11:42:56 +00003734
3735
3736class TestOCSP(_LoopbackMixin):
3737 """
3738 Tests for PyOpenSSL's OCSP stapling support.
3739 """
3740 sample_ocsp_data = b"this is totally ocsp data"
3741
3742 def _client_connection(self, callback, data, request_ocsp=True):
3743 """
3744 Builds a client connection suitable for using OCSP.
3745
3746 :param callback: The callback to register for OCSP.
3747 :param data: The opaque data object that will be handed to the
3748 OCSP callback.
3749 :param request_ocsp: Whether the client will actually ask for OCSP
3750 stapling. Useful for testing only.
3751 """
3752 ctx = Context(SSLv23_METHOD)
3753 ctx.set_ocsp_client_callback(callback, data)
3754 client = Connection(ctx)
3755
3756 if request_ocsp:
3757 client.request_ocsp()
3758
3759 client.set_connect_state()
3760 return client
3761
3762 def _server_connection(self, callback, data):
3763 """
3764 Builds a server connection suitable for using OCSP.
3765
3766 :param callback: The callback to register for OCSP.
3767 :param data: The opaque data object that will be handed to the
3768 OCSP callback.
3769 """
3770 ctx = Context(SSLv23_METHOD)
3771 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
3772 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
3773 ctx.set_ocsp_server_callback(callback, data)
3774 server = Connection(ctx)
3775 server.set_accept_state()
3776 return server
3777
3778 def test_callbacks_arent_called_by_default(self):
3779 """
3780 If both the client and the server have registered OCSP callbacks, but
3781 the client does not send the OCSP request, neither callback gets
3782 called.
3783 """
3784 called = []
3785
3786 def ocsp_callback(*args, **kwargs):
3787 called.append((args, kwargs))
3788
3789 client = self._client_connection(
3790 callback=ocsp_callback, data=None, request_ocsp=False
3791 )
3792 server = self._server_connection(callback=ocsp_callback, data=None)
3793 self._handshakeInMemory(client, server)
3794
3795 assert not called
3796
3797 def test_client_negotiates_without_server(self):
3798 """
3799 If the client wants to do OCSP but the server does not, the handshake
3800 succeeds, and the client callback fires with an empty byte string.
3801 """
3802 called = []
3803
3804 def ocsp_callback(conn, ocsp_data, ignored):
3805 called.append(ocsp_data)
3806 return True
3807
3808 client = self._client_connection(callback=ocsp_callback, data=None)
3809 server = self._loopbackServerFactory(socket=None)
3810 self._handshakeInMemory(client, server)
3811
3812 assert len(called) == 1
3813 assert called[0] == b''
3814
3815 def test_client_receives_servers_data(self):
3816 """
3817 The data the server sends in its callback is received by the client.
3818 """
3819 calls = []
3820
3821 def server_callback(*args, **kwargs):
3822 return self.sample_ocsp_data
3823
3824 def client_callback(conn, ocsp_data, ignored):
3825 calls.append(ocsp_data)
3826 return True
3827
3828 client = self._client_connection(callback=client_callback, data=None)
3829 server = self._server_connection(callback=server_callback, data=None)
3830 self._handshakeInMemory(client, server)
3831
3832 assert len(calls) == 1
3833 assert calls[0] == self.sample_ocsp_data
3834
3835 def test_callbacks_are_invoked_with_connections(self):
3836 """
3837 The first arguments to both callbacks are their respective connections.
3838 """
3839 client_calls = []
3840 server_calls = []
3841
3842 def client_callback(conn, *args, **kwargs):
3843 client_calls.append(conn)
3844 return True
3845
3846 def server_callback(conn, *args, **kwargs):
3847 server_calls.append(conn)
3848 return self.sample_ocsp_data
3849
3850 client = self._client_connection(callback=client_callback, data=None)
3851 server = self._server_connection(callback=server_callback, data=None)
3852 self._handshakeInMemory(client, server)
3853
3854 assert len(client_calls) == 1
3855 assert len(server_calls) == 1
3856 assert client_calls[0] is client
3857 assert server_calls[0] is server
3858
3859 def test_opaque_data_is_passed_through(self):
3860 """
3861 Both callbacks receive an opaque, user-provided piece of data in their
3862 callbacks as the final argument.
3863 """
3864 calls = []
3865
3866 def server_callback(*args):
3867 calls.append(args)
3868 return self.sample_ocsp_data
3869
3870 def client_callback(*args):
3871 calls.append(args)
3872 return True
3873
3874 sentinel = object()
3875
3876 client = self._client_connection(
3877 callback=client_callback, data=sentinel
3878 )
3879 server = self._server_connection(
3880 callback=server_callback, data=sentinel
3881 )
3882 self._handshakeInMemory(client, server)
3883
3884 assert len(calls) == 2
3885 assert calls[0][-1] is sentinel
3886 assert calls[1][-1] is sentinel
3887
3888 def test_server_returns_empty_string(self):
3889 """
3890 If the server returns an empty bytestring from its callback, the
3891 client callback is called with the empty bytestring.
3892 """
3893 client_calls = []
3894
3895 def server_callback(*args):
3896 return b''
3897
3898 def client_callback(conn, ocsp_data, ignored):
3899 client_calls.append(ocsp_data)
3900 return True
3901
3902 client = self._client_connection(callback=client_callback, data=None)
3903 server = self._server_connection(callback=server_callback, data=None)
3904 self._handshakeInMemory(client, server)
3905
3906 assert len(client_calls) == 1
3907 assert client_calls[0] == b''
3908
3909 def test_client_returns_false_terminates_handshake(self):
3910 """
3911 If the client returns False from its callback, the handshake fails.
3912 """
3913 def server_callback(*args):
3914 return self.sample_ocsp_data
3915
3916 def client_callback(*args):
3917 return False
3918
3919 client = self._client_connection(callback=client_callback, data=None)
3920 server = self._server_connection(callback=server_callback, data=None)
3921
3922 with pytest.raises(Error):
3923 self._handshakeInMemory(client, server)
3924
3925 def test_exceptions_in_client_bubble_up(self):
3926 """
3927 The callbacks thrown in the client callback bubble up to the caller.
3928 """
3929 class SentinelException(Exception):
3930 pass
3931
3932 def server_callback(*args):
3933 return self.sample_ocsp_data
3934
3935 def client_callback(*args):
3936 raise SentinelException()
3937
3938 client = self._client_connection(callback=client_callback, data=None)
3939 server = self._server_connection(callback=server_callback, data=None)
3940
3941 with pytest.raises(SentinelException):
3942 self._handshakeInMemory(client, server)
3943
3944 def test_exceptions_in_server_bubble_up(self):
3945 """
3946 The callbacks thrown in the server callback bubble up to the caller.
3947 """
3948 class SentinelException(Exception):
3949 pass
3950
3951 def server_callback(*args):
3952 raise SentinelException()
3953
3954 def client_callback(*args):
3955 pytest.fail("Should not be called")
3956
3957 client = self._client_connection(callback=client_callback, data=None)
3958 server = self._server_connection(callback=server_callback, data=None)
3959
3960 with pytest.raises(SentinelException):
3961 self._handshakeInMemory(client, server)
3962
3963 def test_server_must_return_bytes(self):
3964 """
3965 The server callback must return a bytestring, or a TypeError is thrown.
3966 """
3967 def server_callback(*args):
3968 return self.sample_ocsp_data.decode('ascii')
3969
3970 def client_callback(*args):
3971 pytest.fail("Should not be called")
3972
3973 client = self._client_connection(callback=client_callback, data=None)
3974 server = self._server_connection(callback=server_callback, data=None)
3975
3976 with pytest.raises(TypeError):
3977 self._handshakeInMemory(client, server)