blob: e2681e3182d0b81f0d7ad3dc62bb288dfda909e2 [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
Maximilian Hils868dc3c2017-02-10 14:56:55 +01009import sys
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +010010import uuid
11
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -050012from gc import collect, get_referrers
David Benjamin1fbe0642019-04-15 17:05:13 -050013from errno import (
14 EAFNOSUPPORT, ECONNREFUSED, EINPROGRESS, EWOULDBLOCK, EPIPE, ESHUTDOWN)
Jeremy Lainé1ae7cb62018-03-21 14:49:42 +010015from sys import platform, getfilesystemencoding
David Benjamin1fbe0642019-04-15 17:05:13 -050016from socket import AF_INET, AF_INET6, MSG_PEEK, SHUT_RDWR, error, socket
Jean-Paul Calderonea65cf6c2009-07-19 10:26:52 -040017from os import makedirs
Jean-Paul Calderone1461c492013-10-03 16:05:00 -040018from os.path import join
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -040019from weakref import ref
Alex Chanb7480992017-01-30 14:04:47 +000020from warnings import simplefilter
Jean-Paul Calderone460cc1f2009-03-07 11:31:12 -050021
Alex Gaynor963ae032019-07-06 17:38:32 -040022import flaky
23
Hynek Schlawack734d3022015-09-05 19:19:32 +020024import pytest
25
Paul Kehrer55fb3412017-06-29 18:44:08 -050026from pretend import raiser
27
Hugo van Kemenade60827f82019-08-30 00:39:35 +030028from six import PY2, text_type
Jean-Paul Calderonec76c61c2014-01-18 13:21:52 -050029
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +010030from cryptography import x509
31from cryptography.hazmat.backends import default_backend
32from cryptography.hazmat.primitives import hashes
33from cryptography.hazmat.primitives import serialization
34from cryptography.hazmat.primitives.asymmetric import rsa
35from cryptography.x509.oid import NameOID
36
37
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040038from OpenSSL.crypto import TYPE_RSA, FILETYPE_PEM
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -080039from OpenSSL.crypto import PKey, X509, X509Extension, X509Store
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040040from OpenSSL.crypto import dump_privatekey, load_privatekey
41from OpenSSL.crypto import dump_certificate, load_certificate
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -040042from OpenSSL.crypto import get_elliptic_curves
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040043
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -040044from OpenSSL.SSL import OPENSSL_VERSION_NUMBER, SSLEAY_VERSION, SSLEAY_CFLAGS
45from OpenSSL.SSL import SSLEAY_PLATFORM, SSLEAY_DIR, SSLEAY_BUILT_ON
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -040046from OpenSSL.SSL import SENT_SHUTDOWN, RECEIVED_SHUTDOWN
Jean-Paul Calderone1461c492013-10-03 16:05:00 -040047from OpenSSL.SSL import (
48 SSLv2_METHOD, SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD,
49 TLSv1_1_METHOD, TLSv1_2_METHOD)
50from OpenSSL.SSL import OP_SINGLE_DH_USE, OP_NO_SSLv2, OP_NO_SSLv3
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040051from OpenSSL.SSL import (
52 VERIFY_PEER, VERIFY_FAIL_IF_NO_PEER_CERT, VERIFY_CLIENT_ONCE, VERIFY_NONE)
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040053
Paul Kehrer55fb3412017-06-29 18:44:08 -050054from OpenSSL import SSL
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040055from OpenSSL.SSL import (
Jean-Paul Calderone313bf012012-02-08 13:02:49 -050056 SESS_CACHE_OFF, SESS_CACHE_CLIENT, SESS_CACHE_SERVER, SESS_CACHE_BOTH,
57 SESS_CACHE_NO_AUTO_CLEAR, SESS_CACHE_NO_INTERNAL_LOOKUP,
58 SESS_CACHE_NO_INTERNAL_STORE, SESS_CACHE_NO_INTERNAL)
59
60from OpenSSL.SSL import (
Jean-Paul Calderoned899af02013-03-19 22:10:37 -070061 Error, SysCallError, WantReadError, WantWriteError, ZeroReturnError)
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -050062from OpenSSL.SSL import (
Alex Gaynor01f90a12019-02-07 09:14:48 -050063 Context, Session, Connection, SSLeay_version)
Cory Benfield0ba57ec2016-03-30 09:35:05 +010064from OpenSSL.SSL import _make_requires
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040065
Paul Kehrer55fb3412017-06-29 18:44:08 -050066from OpenSSL._util import ffi as _ffi, lib as _lib
Cory Benfieldba1820d2015-04-13 17:39:12 -040067
Alex Gaynord3b5d9b2016-07-31 10:54:24 -040068from OpenSSL.SSL import (
69 OP_NO_QUERY_MTU, OP_COOKIE_EXCHANGE, OP_NO_TICKET, OP_NO_COMPRESSION,
Mark Williams5d890a02019-11-17 19:56:26 -080070 MODE_RELEASE_BUFFERS, NO_OVERLAPPING_PROTOCOLS)
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040071
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -040072from OpenSSL.SSL import (
Alex Gaynor5af32d02016-09-24 01:52:21 -040073 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK,
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -040074 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
75 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
76 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
77 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE)
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -040078
Alex Gaynor5af32d02016-09-24 01:52:21 -040079try:
80 from OpenSSL.SSL import (
81 SSL_ST_INIT, SSL_ST_BEFORE, SSL_ST_OK, SSL_ST_RENEGOTIATE
82 )
83except ImportError:
84 SSL_ST_INIT = SSL_ST_BEFORE = SSL_ST_OK = SSL_ST_RENEGOTIATE = None
85
Alex Chanb7480992017-01-30 14:04:47 +000086from .util import WARNING_TYPE_EXPECTED, NON_ASCII, is_consistent_type
Hynek Schlawackf0e66852015-10-16 20:18:38 +020087from .test_crypto import (
88 cleartextCertificatePEM, cleartextPrivateKeyPEM,
89 client_cert_pem, client_key_pem, server_cert_pem, server_key_pem,
90 root_cert_pem)
91
Hynek Schlawackde00dd52015-09-05 19:09:26 +020092
Alex Gaynord0bdd2d2016-09-10 14:23:46 -040093# openssl dhparam 1024 -out dh-1024.pem (note that 1024 is a small number of
94# bits to use)
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -040095dhparam = """\
96-----BEGIN DH PARAMETERS-----
Alex Gaynord0bdd2d2016-09-10 14:23:46 -040097MIGHAoGBALdUMvn+C9MM+y5BWZs11mSeH6HHoEq0UVbzVq7UojC1hbsZUuGukQ3a
98Qh2/pwqb18BZFykrWB0zv/OkLa0kx4cuUgNrUVq1EFheBiX6YqryJ7t2sO09NQiO
99V7H54LmltOT/hEh6QWsJqb6BQgH65bswvV/XkYGja8/T0GzvbaVzAgEC
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -0400100-----END DH PARAMETERS-----
101"""
102
103
Hugo van Kemenade60827f82019-08-30 00:39:35 +0300104skip_if_py3 = pytest.mark.skipif(not PY2, reason="Python 2 only")
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200105
106
David Benjamin1fbe0642019-04-15 17:05:13 -0500107def socket_any_family():
108 try:
109 return socket(AF_INET)
110 except error as e:
111 if e.errno == EAFNOSUPPORT:
112 return socket(AF_INET6)
113 raise
114
115
116def loopback_address(socket):
117 if socket.family == AF_INET:
118 return "127.0.0.1"
119 else:
120 assert socket.family == AF_INET6
121 return "::1"
122
123
Jean-Paul Calderone05826732015-04-12 11:38:49 -0400124def join_bytes_or_unicode(prefix, suffix):
125 """
126 Join two path components of either ``bytes`` or ``unicode``.
127
128 The return type is the same as the type of ``prefix``.
129 """
130 # If the types are the same, nothing special is necessary.
131 if type(prefix) == type(suffix):
132 return join(prefix, suffix)
133
134 # Otherwise, coerce suffix to the type of prefix.
135 if isinstance(prefix, text_type):
136 return join(prefix, suffix.decode(getfilesystemencoding()))
137 else:
138 return join(prefix, suffix.encode(getfilesystemencoding()))
139
140
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400141def verify_cb(conn, cert, errnum, depth, ok):
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400142 return ok
143
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400144
Rick Deanb1ccd562009-07-09 23:52:39 -0500145def socket_pair():
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400146 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400147 Establish and return a pair of network sockets connected to each other.
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400148 """
149 # Connect a pair of sockets
David Benjamin1fbe0642019-04-15 17:05:13 -0500150 port = socket_any_family()
Rick Deanb1ccd562009-07-09 23:52:39 -0500151 port.bind(('', 0))
152 port.listen(1)
David Benjamin1fbe0642019-04-15 17:05:13 -0500153 client = socket(port.family)
Rick Deanb1ccd562009-07-09 23:52:39 -0500154 client.setblocking(False)
David Benjamin1fbe0642019-04-15 17:05:13 -0500155 client.connect_ex((loopback_address(port), port.getsockname()[1]))
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400156 client.setblocking(True)
Rick Deanb1ccd562009-07-09 23:52:39 -0500157 server = port.accept()[0]
Rick Deanb1ccd562009-07-09 23:52:39 -0500158
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400159 # Let's pass some unencrypted data to make sure our socket connection is
160 # fine. Just one byte, so we don't have to worry about buffers getting
161 # filled up or fragmentation.
Alex Gaynore7f51982016-09-11 11:48:14 -0400162 server.send(b"x")
163 assert client.recv(1024) == b"x"
164 client.send(b"y")
165 assert server.recv(1024) == b"y"
Rick Deanb1ccd562009-07-09 23:52:39 -0500166
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -0400167 # Most of our callers want non-blocking sockets, make it easy for them.
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400168 server.setblocking(False)
169 client.setblocking(False)
Jim Shaver46f28912015-05-29 19:32:16 -0400170
Rick Deanb1ccd562009-07-09 23:52:39 -0500171 return (server, client)
172
173
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400174def handshake(client, server):
175 conns = [client, server]
176 while conns:
177 for conn in conns:
178 try:
179 conn.do_handshake()
180 except WantReadError:
181 pass
182 else:
183 conns.remove(conn)
184
185
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400186def _create_certificate_chain():
187 """
188 Construct and return a chain of certificates.
189
190 1. A new self-signed certificate authority certificate (cacert)
191 2. A new intermediate certificate signed by cacert (icert)
192 3. A new server certificate signed by icert (scert)
193 """
Alex Gaynore7f51982016-09-11 11:48:14 -0400194 caext = X509Extension(b'basicConstraints', False, b'CA:true')
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400195
196 # Step 1
197 cakey = PKey()
Alex Gaynor0737a5e2016-09-10 14:35:09 -0400198 cakey.generate_key(TYPE_RSA, 1024)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400199 cacert = X509()
200 cacert.get_subject().commonName = "Authority Certificate"
201 cacert.set_issuer(cacert.get_subject())
202 cacert.set_pubkey(cakey)
Alex Gaynore7f51982016-09-11 11:48:14 -0400203 cacert.set_notBefore(b"20000101000000Z")
204 cacert.set_notAfter(b"20200101000000Z")
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400205 cacert.add_extensions([caext])
206 cacert.set_serial_number(0)
207 cacert.sign(cakey, "sha1")
208
209 # Step 2
210 ikey = PKey()
Alex Gaynor0737a5e2016-09-10 14:35:09 -0400211 ikey.generate_key(TYPE_RSA, 1024)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400212 icert = X509()
213 icert.get_subject().commonName = "Intermediate Certificate"
214 icert.set_issuer(cacert.get_subject())
215 icert.set_pubkey(ikey)
Alex Gaynore7f51982016-09-11 11:48:14 -0400216 icert.set_notBefore(b"20000101000000Z")
217 icert.set_notAfter(b"20200101000000Z")
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400218 icert.add_extensions([caext])
219 icert.set_serial_number(0)
220 icert.sign(cakey, "sha1")
221
222 # Step 3
223 skey = PKey()
Alex Gaynor0737a5e2016-09-10 14:35:09 -0400224 skey.generate_key(TYPE_RSA, 1024)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400225 scert = X509()
226 scert.get_subject().commonName = "Server Certificate"
227 scert.set_issuer(icert.get_subject())
228 scert.set_pubkey(skey)
Alex Gaynore7f51982016-09-11 11:48:14 -0400229 scert.set_notBefore(b"20000101000000Z")
230 scert.set_notAfter(b"20200101000000Z")
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400231 scert.add_extensions([
Alex Gaynore7f51982016-09-11 11:48:14 -0400232 X509Extension(b'basicConstraints', True, b'CA:false')])
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400233 scert.set_serial_number(0)
234 scert.sign(ikey, "sha1")
235
236 return [(cakey, cacert), (ikey, icert), (skey, scert)]
237
238
Paul Kehrer7d5a3bf2019-01-21 12:24:02 -0600239def loopback_client_factory(socket, version=SSLv23_METHOD):
240 client = Connection(Context(version), socket)
Alex Chan1c0cb662017-01-30 07:13:30 +0000241 client.set_connect_state()
242 return client
243
244
Paul Kehrer7d5a3bf2019-01-21 12:24:02 -0600245def loopback_server_factory(socket, version=SSLv23_METHOD):
246 ctx = Context(version)
Alex Chan1c0cb662017-01-30 07:13:30 +0000247 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
248 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
249 server = Connection(ctx, socket)
250 server.set_accept_state()
251 return server
252
253
254def loopback(server_factory=None, client_factory=None):
255 """
256 Create a connected socket pair and force two connected SSL sockets
257 to talk to each other via memory BIOs.
258 """
259 if server_factory is None:
260 server_factory = loopback_server_factory
261 if client_factory is None:
262 client_factory = loopback_client_factory
263
264 (server, client) = socket_pair()
265 server = server_factory(server)
266 client = client_factory(client)
267
268 handshake(client, server)
269
270 server.setblocking(True)
271 client.setblocking(True)
272 return server, client
273
274
Alex Chan1ca9e3a2016-11-05 13:01:51 +0000275def interact_in_memory(client_conn, server_conn):
276 """
277 Try to read application bytes from each of the two `Connection` objects.
278 Copy bytes back and forth between their send/receive buffers for as long
279 as there is anything to copy. When there is nothing more to copy,
280 return `None`. If one of them actually manages to deliver some application
281 bytes, return a two-tuple of the connection from which the bytes were read
282 and the bytes themselves.
283 """
284 wrote = True
285 while wrote:
286 # Loop until neither side has anything to say
287 wrote = False
288
289 # Copy stuff from each side's send buffer to the other side's
290 # receive buffer.
291 for (read, write) in [(client_conn, server_conn),
292 (server_conn, client_conn)]:
293
294 # Give the side a chance to generate some more bytes, or succeed.
295 try:
296 data = read.recv(2 ** 16)
297 except WantReadError:
298 # It didn't succeed, so we'll hope it generated some output.
299 pass
300 else:
301 # It did succeed, so we'll stop now and let the caller deal
302 # with it.
303 return (read, data)
304
305 while True:
306 # Keep copying as long as there's more stuff there.
307 try:
308 dirty = read.bio_read(4096)
309 except WantReadError:
310 # Okay, nothing more waiting to be sent. Stop
311 # processing this send buffer.
312 break
313 else:
314 # Keep track of the fact that someone generated some
315 # output.
316 wrote = True
317 write.bio_write(dirty)
318
319
Alex Chan532b79e2017-01-24 15:14:52 +0000320def handshake_in_memory(client_conn, server_conn):
321 """
322 Perform the TLS handshake between two `Connection` instances connected to
323 each other via memory BIOs.
324 """
325 client_conn.set_connect_state()
326 server_conn.set_accept_state()
327
328 for conn in [client_conn, server_conn]:
329 try:
330 conn.do_handshake()
331 except WantReadError:
332 pass
333
334 interact_in_memory(client_conn, server_conn)
335
336
Alex Chanb7480992017-01-30 14:04:47 +0000337class TestVersion(object):
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400338 """
Alex Chanb7480992017-01-30 14:04:47 +0000339 Tests for version information exposed by `OpenSSL.SSL.SSLeay_version` and
340 `OpenSSL.SSL.OPENSSL_VERSION_NUMBER`.
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400341 """
342 def test_OPENSSL_VERSION_NUMBER(self):
343 """
Alex Chanb7480992017-01-30 14:04:47 +0000344 `OPENSSL_VERSION_NUMBER` is an integer with status in the low byte and
345 the patch, fix, minor, and major versions in the nibbles above that.
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400346 """
Alex Chanb7480992017-01-30 14:04:47 +0000347 assert isinstance(OPENSSL_VERSION_NUMBER, int)
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400348
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400349 def test_SSLeay_version(self):
350 """
Alex Chanb7480992017-01-30 14:04:47 +0000351 `SSLeay_version` takes a version type indicator and returns one of a
352 number of version strings based on that indicator.
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400353 """
354 versions = {}
355 for t in [SSLEAY_VERSION, SSLEAY_CFLAGS, SSLEAY_BUILT_ON,
356 SSLEAY_PLATFORM, SSLEAY_DIR]:
357 version = SSLeay_version(t)
358 versions[version] = t
Alex Chanb7480992017-01-30 14:04:47 +0000359 assert isinstance(version, bytes)
360 assert len(versions) == 5
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400361
362
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100363@pytest.fixture
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100364def ca_file(tmpdir):
365 """
366 Create a valid PEM file with CA certificates and return the path.
367 """
368 key = rsa.generate_private_key(
369 public_exponent=65537,
370 key_size=2048,
371 backend=default_backend()
372 )
373 public_key = key.public_key()
374
375 builder = x509.CertificateBuilder()
376 builder = builder.subject_name(x509.Name([
377 x509.NameAttribute(NameOID.COMMON_NAME, u"pyopenssl.org"),
378 ]))
379 builder = builder.issuer_name(x509.Name([
380 x509.NameAttribute(NameOID.COMMON_NAME, u"pyopenssl.org"),
381 ]))
382 one_day = datetime.timedelta(1, 0, 0)
383 builder = builder.not_valid_before(datetime.datetime.today() - one_day)
384 builder = builder.not_valid_after(datetime.datetime.today() + one_day)
385 builder = builder.serial_number(int(uuid.uuid4()))
386 builder = builder.public_key(public_key)
387 builder = builder.add_extension(
388 x509.BasicConstraints(ca=True, path_length=None), critical=True,
389 )
390
391 certificate = builder.sign(
392 private_key=key, algorithm=hashes.SHA256(),
393 backend=default_backend()
394 )
395
396 ca_file = tmpdir.join("test.pem")
397 ca_file.write_binary(
398 certificate.public_bytes(
399 encoding=serialization.Encoding.PEM,
400 )
401 )
402
403 return str(ca_file).encode("ascii")
404
405
406@pytest.fixture
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100407def context():
408 """
409 A simple TLS 1.0 context.
410 """
411 return Context(TLSv1_METHOD)
412
413
414class TestContext(object):
Hynek Schlawackaa861212016-03-13 13:53:48 +0100415 """
Alex Chan532b79e2017-01-24 15:14:52 +0000416 Unit tests for `OpenSSL.SSL.Context`.
Hynek Schlawackaa861212016-03-13 13:53:48 +0100417 """
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100418 @pytest.mark.parametrize("cipher_string", [
419 b"hello world:AES128-SHA",
420 u"hello world:AES128-SHA",
421 ])
422 def test_set_cipher_list(self, context, cipher_string):
423 """
Alex Chan532b79e2017-01-24 15:14:52 +0000424 `Context.set_cipher_list` accepts both byte and unicode strings
Hynek Schlawacka7a63af2016-03-11 12:05:26 +0100425 for naming the ciphers which connections created with the context
426 object will be able to choose from.
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100427 """
428 context.set_cipher_list(cipher_string)
429 conn = Connection(context, None)
430
431 assert "AES128-SHA" in conn.get_cipher_list()
432
Mark Williamsdf2480d2019-02-14 19:30:07 -0800433 def test_set_cipher_list_wrong_type(self, context):
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100434 """
Alex Chan532b79e2017-01-24 15:14:52 +0000435 `Context.set_cipher_list` raises `TypeError` when passed a non-string
Mark Williamsdf2480d2019-02-14 19:30:07 -0800436 argument.
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100437 """
Mark Williamsdf2480d2019-02-14 19:30:07 -0800438 with pytest.raises(TypeError):
439 context.set_cipher_list(object())
440
Alex Gaynor963ae032019-07-06 17:38:32 -0400441 @flaky.flaky
Mark Williamsdf2480d2019-02-14 19:30:07 -0800442 def test_set_cipher_list_no_cipher_match(self, context):
443 """
444 `Context.set_cipher_list` raises `OpenSSL.SSL.Error` with a
445 `"no cipher match"` reason string regardless of the TLS
446 version.
447 """
448 with pytest.raises(Error) as excinfo:
449 context.set_cipher_list(b"imaginary-cipher")
450 assert excinfo.value.args == (
451 [
452 (
453 'SSL routines',
454 'SSL_CTX_set_cipher_list',
455 'no cipher match',
456 ),
457 ],
458 )
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100459
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100460 def test_load_client_ca(self, context, ca_file):
461 """
Alex Chan532b79e2017-01-24 15:14:52 +0000462 `Context.load_client_ca` works as far as we can tell.
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100463 """
464 context.load_client_ca(ca_file)
465
466 def test_load_client_ca_invalid(self, context, tmpdir):
467 """
Alex Chan532b79e2017-01-24 15:14:52 +0000468 `Context.load_client_ca` raises an Error if the ca file is invalid.
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100469 """
470 ca_file = tmpdir.join("test.pem")
471 ca_file.write("")
472
473 with pytest.raises(Error) as e:
474 context.load_client_ca(str(ca_file).encode("ascii"))
475
476 assert "PEM routines" == e.value.args[0][0][0]
477
478 def test_load_client_ca_unicode(self, context, ca_file):
479 """
480 Passing the path as unicode raises a warning but works.
481 """
482 pytest.deprecated_call(
483 context.load_client_ca, ca_file.decode("ascii")
484 )
485
486 def test_set_session_id(self, context):
487 """
Alex Chan532b79e2017-01-24 15:14:52 +0000488 `Context.set_session_id` works as far as we can tell.
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100489 """
490 context.set_session_id(b"abc")
491
492 def test_set_session_id_fail(self, context):
493 """
Alex Chan532b79e2017-01-24 15:14:52 +0000494 `Context.set_session_id` errors are propagated.
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100495 """
496 with pytest.raises(Error) as e:
497 context.set_session_id(b"abc" * 1000)
498
499 assert [
500 ("SSL routines",
501 "SSL_CTX_set_session_id_context",
502 "ssl session id context too long")
503 ] == e.value.args[0]
504
505 def test_set_session_id_unicode(self, context):
506 """
Alex Chan532b79e2017-01-24 15:14:52 +0000507 `Context.set_session_id` raises a warning if a unicode string is
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100508 passed.
509 """
510 pytest.deprecated_call(context.set_session_id, u"abc")
511
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400512 def test_method(self):
513 """
Alex Chan532b79e2017-01-24 15:14:52 +0000514 `Context` can be instantiated with one of `SSLv2_METHOD`,
515 `SSLv3_METHOD`, `SSLv23_METHOD`, `TLSv1_METHOD`, `TLSv1_1_METHOD`,
516 or `TLSv1_2_METHOD`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400517 """
Alex Gaynor5af32d02016-09-24 01:52:21 -0400518 methods = [SSLv23_METHOD, TLSv1_METHOD]
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400519 for meth in methods:
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400520 Context(meth)
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400521
Alex Gaynor5af32d02016-09-24 01:52:21 -0400522 maybe = [SSLv2_METHOD, SSLv3_METHOD, TLSv1_1_METHOD, TLSv1_2_METHOD]
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400523 for meth in maybe:
524 try:
525 Context(meth)
526 except (Error, ValueError):
527 # Some versions of OpenSSL have SSLv2 / TLSv1.1 / TLSv1.2, some
528 # don't. Difficult to say in advance.
529 pass
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400530
Alex Chan532b79e2017-01-24 15:14:52 +0000531 with pytest.raises(TypeError):
532 Context("")
533 with pytest.raises(ValueError):
534 Context(10)
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400535
Rick Deane15b1472009-07-09 15:53:42 -0500536 def test_type(self):
537 """
Alex Gaynor01f90a12019-02-07 09:14:48 -0500538 `Context` can be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -0500539 """
Alex Chan532b79e2017-01-24 15:14:52 +0000540 assert is_consistent_type(Context, 'Context', TLSv1_METHOD)
Rick Deane15b1472009-07-09 15:53:42 -0500541
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400542 def test_use_privatekey(self):
543 """
Alex Chan532b79e2017-01-24 15:14:52 +0000544 `Context.use_privatekey` takes an `OpenSSL.crypto.PKey` instance.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400545 """
546 key = PKey()
Alex Gaynor6e9f9762018-05-12 07:44:37 -0400547 key.generate_key(TYPE_RSA, 512)
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400548 ctx = Context(TLSv1_METHOD)
549 ctx.use_privatekey(key)
Alex Chan532b79e2017-01-24 15:14:52 +0000550 with pytest.raises(TypeError):
551 ctx.use_privatekey("")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400552
Alex Chan532b79e2017-01-24 15:14:52 +0000553 def test_use_privatekey_file_missing(self, tmpfile):
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800554 """
Alex Chan532b79e2017-01-24 15:14:52 +0000555 `Context.use_privatekey_file` raises `OpenSSL.SSL.Error` when passed
556 the name of a file which does not exist.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800557 """
558 ctx = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000559 with pytest.raises(Error):
560 ctx.use_privatekey_file(tmpfile)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800561
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400562 def _use_privatekey_file_test(self, pemfile, filetype):
563 """
564 Verify that calling ``Context.use_privatekey_file`` with the given
565 arguments does not raise an exception.
566 """
567 key = PKey()
Alex Gaynor6e9f9762018-05-12 07:44:37 -0400568 key.generate_key(TYPE_RSA, 512)
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400569
570 with open(pemfile, "wt") as pem:
571 pem.write(
572 dump_privatekey(FILETYPE_PEM, key).decode("ascii")
573 )
574
575 ctx = Context(TLSv1_METHOD)
576 ctx.use_privatekey_file(pemfile, filetype)
577
Alex Chanfb078d82017-04-20 11:16:15 +0100578 @pytest.mark.parametrize('filetype', [object(), "", None, 1.0])
579 def test_wrong_privatekey_file_wrong_args(self, tmpfile, filetype):
580 """
581 `Context.use_privatekey_file` raises `TypeError` when called with
582 a `filetype` which is not a valid file encoding.
583 """
584 ctx = Context(TLSv1_METHOD)
585 with pytest.raises(TypeError):
586 ctx.use_privatekey_file(tmpfile, filetype)
587
Alex Chan532b79e2017-01-24 15:14:52 +0000588 def test_use_privatekey_file_bytes(self, tmpfile):
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400589 """
590 A private key can be specified from a file by passing a ``bytes``
591 instance giving the file name to ``Context.use_privatekey_file``.
592 """
593 self._use_privatekey_file_test(
Alex Chan532b79e2017-01-24 15:14:52 +0000594 tmpfile + NON_ASCII.encode(getfilesystemencoding()),
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400595 FILETYPE_PEM,
596 )
597
Alex Chan532b79e2017-01-24 15:14:52 +0000598 def test_use_privatekey_file_unicode(self, tmpfile):
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400599 """
600 A private key can be specified from a file by passing a ``unicode``
601 instance giving the file name to ``Context.use_privatekey_file``.
602 """
603 self._use_privatekey_file_test(
Alex Chan532b79e2017-01-24 15:14:52 +0000604 tmpfile.decode(getfilesystemencoding()) + NON_ASCII,
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400605 FILETYPE_PEM,
606 )
607
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800608 def test_use_certificate_wrong_args(self):
609 """
Alex Chan532b79e2017-01-24 15:14:52 +0000610 `Context.use_certificate_wrong_args` raises `TypeError` when not passed
611 exactly one `OpenSSL.crypto.X509` instance as an argument.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800612 """
613 ctx = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000614 with pytest.raises(TypeError):
615 ctx.use_certificate("hello, world")
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800616
617 def test_use_certificate_uninitialized(self):
618 """
Alex Chan532b79e2017-01-24 15:14:52 +0000619 `Context.use_certificate` raises `OpenSSL.SSL.Error` when passed a
620 `OpenSSL.crypto.X509` instance which has not been initialized
621 (ie, which does not actually have any certificate data).
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800622 """
623 ctx = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000624 with pytest.raises(Error):
625 ctx.use_certificate(X509())
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800626
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800627 def test_use_certificate(self):
628 """
Alex Chan532b79e2017-01-24 15:14:52 +0000629 `Context.use_certificate` sets the certificate which will be
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800630 used to identify connections created using the context.
631 """
632 # TODO
633 # Hard to assert anything. But we could set a privatekey then ask
634 # OpenSSL if the cert and key agree using check_privatekey. Then as
635 # long as check_privatekey works right we're good...
636 ctx = Context(TLSv1_METHOD)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200637 ctx.use_certificate(
638 load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
639 )
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800640
641 def test_use_certificate_file_wrong_args(self):
642 """
Alex Chan532b79e2017-01-24 15:14:52 +0000643 `Context.use_certificate_file` raises `TypeError` if the first
644 argument is not a byte string or the second argument is not an integer.
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(TypeError):
648 ctx.use_certificate_file(object(), FILETYPE_PEM)
649 with pytest.raises(TypeError):
650 ctx.use_certificate_file(b"somefile", object())
651 with pytest.raises(TypeError):
652 ctx.use_certificate_file(object(), FILETYPE_PEM)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800653
Alex Chan532b79e2017-01-24 15:14:52 +0000654 def test_use_certificate_file_missing(self, tmpfile):
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800655 """
Alex Chan532b79e2017-01-24 15:14:52 +0000656 `Context.use_certificate_file` raises `OpenSSL.SSL.Error` if passed
657 the name of a file which does not exist.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800658 """
659 ctx = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000660 with pytest.raises(Error):
661 ctx.use_certificate_file(tmpfile)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800662
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400663 def _use_certificate_file_test(self, certificate_file):
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800664 """
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400665 Verify that calling ``Context.use_certificate_file`` with the given
666 filename doesn't raise an exception.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800667 """
668 # TODO
669 # Hard to assert anything. But we could set a privatekey then ask
670 # OpenSSL if the cert and key agree using check_privatekey. Then as
671 # long as check_privatekey works right we're good...
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400672 with open(certificate_file, "wb") as pem_file:
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800673 pem_file.write(cleartextCertificatePEM)
674
675 ctx = Context(TLSv1_METHOD)
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400676 ctx.use_certificate_file(certificate_file)
677
Alex Chan532b79e2017-01-24 15:14:52 +0000678 def test_use_certificate_file_bytes(self, tmpfile):
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400679 """
Alex Chan532b79e2017-01-24 15:14:52 +0000680 `Context.use_certificate_file` sets the certificate (given as a
681 `bytes` filename) which will be used to identify connections created
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400682 using the context.
683 """
Alex Chan532b79e2017-01-24 15:14:52 +0000684 filename = tmpfile + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400685 self._use_certificate_file_test(filename)
686
Alex Chan532b79e2017-01-24 15:14:52 +0000687 def test_use_certificate_file_unicode(self, tmpfile):
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400688 """
Alex Chan532b79e2017-01-24 15:14:52 +0000689 `Context.use_certificate_file` sets the certificate (given as a
690 `bytes` filename) which will be used to identify connections created
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400691 using the context.
692 """
Alex Chan532b79e2017-01-24 15:14:52 +0000693 filename = tmpfile.decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400694 self._use_certificate_file_test(filename)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800695
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
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300749 def test_set_mode_wrong_args(self):
750 """
Alex Chan532b79e2017-01-24 15:14:52 +0000751 `Context.set_mode` raises `TypeError` if called with
752 a non-`int` argument.
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300753 """
754 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000755 with pytest.raises(TypeError):
756 context.set_mode(None)
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300757
Alex Gaynord3b5d9b2016-07-31 10:54:24 -0400758 def test_set_mode(self):
759 """
Alex Chan532b79e2017-01-24 15:14:52 +0000760 `Context.set_mode` accepts a mode bitvector and returns the
Alex Gaynord3b5d9b2016-07-31 10:54:24 -0400761 newly set mode.
762 """
763 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000764 assert MODE_RELEASE_BUFFERS & context.set_mode(MODE_RELEASE_BUFFERS)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500765
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400766 def test_set_timeout_wrong_args(self):
767 """
Alex Chan532b79e2017-01-24 15:14:52 +0000768 `Context.set_timeout` raises `TypeError` if called with
769 a non-`int` argument.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400770 """
771 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000772 with pytest.raises(TypeError):
773 context.set_timeout(None)
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400774
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400775 def test_timeout(self):
776 """
Alex Chan532b79e2017-01-24 15:14:52 +0000777 `Context.set_timeout` sets the session timeout for all connections
778 created using the context object. `Context.get_timeout` retrieves
779 this value.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400780 """
781 context = Context(TLSv1_METHOD)
782 context.set_timeout(1234)
Alex Chan532b79e2017-01-24 15:14:52 +0000783 assert context.get_timeout() == 1234
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400784
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400785 def test_set_verify_depth_wrong_args(self):
786 """
Alex Chan532b79e2017-01-24 15:14:52 +0000787 `Context.set_verify_depth` raises `TypeError` if called with a
788 non-`int` argument.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400789 """
790 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000791 with pytest.raises(TypeError):
792 context.set_verify_depth(None)
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400793
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400794 def test_verify_depth(self):
795 """
Alex Chan532b79e2017-01-24 15:14:52 +0000796 `Context.set_verify_depth` sets the number of certificates in
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200797 a chain to follow before giving up. The value can be retrieved with
Alex Chan532b79e2017-01-24 15:14:52 +0000798 `Context.get_verify_depth`.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400799 """
800 context = Context(TLSv1_METHOD)
801 context.set_verify_depth(11)
Alex Chan532b79e2017-01-24 15:14:52 +0000802 assert context.get_verify_depth() == 11
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400803
Alex Chan532b79e2017-01-24 15:14:52 +0000804 def _write_encrypted_pem(self, passphrase, tmpfile):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400805 """
806 Write a new private key out to a new file, encrypted using the given
807 passphrase. Return the path to the new file.
808 """
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400809 key = PKey()
Alex Gaynor6e9f9762018-05-12 07:44:37 -0400810 key.generate_key(TYPE_RSA, 512)
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400811 pem = dump_privatekey(FILETYPE_PEM, key, "blowfish", passphrase)
Alex Chan532b79e2017-01-24 15:14:52 +0000812 with open(tmpfile, 'w') as fObj:
813 fObj.write(pem.decode('ascii'))
814 return tmpfile
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400815
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400816 def test_set_passwd_cb_wrong_args(self):
817 """
Alex Chan532b79e2017-01-24 15:14:52 +0000818 `Context.set_passwd_cb` raises `TypeError` if called with a
819 non-callable first argument.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400820 """
821 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000822 with pytest.raises(TypeError):
823 context.set_passwd_cb(None)
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400824
Alex Chan532b79e2017-01-24 15:14:52 +0000825 def test_set_passwd_cb(self, tmpfile):
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400826 """
Alex Chan532b79e2017-01-24 15:14:52 +0000827 `Context.set_passwd_cb` accepts a callable which will be invoked when
828 a private key is loaded from an encrypted PEM.
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400829 """
Alex Gaynore7f51982016-09-11 11:48:14 -0400830 passphrase = b"foobar"
Alex Chan532b79e2017-01-24 15:14:52 +0000831 pemFile = self._write_encrypted_pem(passphrase, tmpfile)
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400832 calledWith = []
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200833
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400834 def passphraseCallback(maxlen, verify, extra):
835 calledWith.append((maxlen, verify, extra))
836 return passphrase
837 context = Context(TLSv1_METHOD)
838 context.set_passwd_cb(passphraseCallback)
839 context.use_privatekey_file(pemFile)
Alex Chan532b79e2017-01-24 15:14:52 +0000840 assert len(calledWith) == 1
841 assert isinstance(calledWith[0][0], int)
842 assert isinstance(calledWith[0][1], int)
843 assert calledWith[0][2] is None
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400844
Alex Chan532b79e2017-01-24 15:14:52 +0000845 def test_passwd_callback_exception(self, tmpfile):
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400846 """
Alex Chan532b79e2017-01-24 15:14:52 +0000847 `Context.use_privatekey_file` propagates any exception raised
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200848 by the passphrase callback.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400849 """
Alex Chan532b79e2017-01-24 15:14:52 +0000850 pemFile = self._write_encrypted_pem(b"monkeys are nice", tmpfile)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200851
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400852 def passphraseCallback(maxlen, verify, extra):
853 raise RuntimeError("Sorry, I am a fail.")
854
855 context = Context(TLSv1_METHOD)
856 context.set_passwd_cb(passphraseCallback)
Alex Chan532b79e2017-01-24 15:14:52 +0000857 with pytest.raises(RuntimeError):
858 context.use_privatekey_file(pemFile)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400859
Alex Chan532b79e2017-01-24 15:14:52 +0000860 def test_passwd_callback_false(self, tmpfile):
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400861 """
Alex Chan532b79e2017-01-24 15:14:52 +0000862 `Context.use_privatekey_file` raises `OpenSSL.SSL.Error` if the
863 passphrase callback returns a false value.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400864 """
Alex Chan532b79e2017-01-24 15:14:52 +0000865 pemFile = self._write_encrypted_pem(b"monkeys are nice", tmpfile)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200866
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400867 def passphraseCallback(maxlen, verify, extra):
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500868 return b""
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400869
870 context = Context(TLSv1_METHOD)
871 context.set_passwd_cb(passphraseCallback)
Alex Chan532b79e2017-01-24 15:14:52 +0000872 with pytest.raises(Error):
873 context.use_privatekey_file(pemFile)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400874
Alex Chan532b79e2017-01-24 15:14:52 +0000875 def test_passwd_callback_non_string(self, tmpfile):
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400876 """
Alex Chan532b79e2017-01-24 15:14:52 +0000877 `Context.use_privatekey_file` raises `OpenSSL.SSL.Error` if the
878 passphrase callback returns a true non-string value.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400879 """
Alex Chan532b79e2017-01-24 15:14:52 +0000880 pemFile = self._write_encrypted_pem(b"monkeys are nice", tmpfile)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200881
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400882 def passphraseCallback(maxlen, verify, extra):
883 return 10
884
885 context = Context(TLSv1_METHOD)
886 context.set_passwd_cb(passphraseCallback)
Alex Chan532b79e2017-01-24 15:14:52 +0000887 # TODO: Surely this is the wrong error?
888 with pytest.raises(ValueError):
889 context.use_privatekey_file(pemFile)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400890
Alex Chan532b79e2017-01-24 15:14:52 +0000891 def test_passwd_callback_too_long(self, tmpfile):
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400892 """
893 If the passphrase returned by the passphrase callback returns a string
894 longer than the indicated maximum length, it is truncated.
895 """
896 # A priori knowledge!
Alex Gaynore7f51982016-09-11 11:48:14 -0400897 passphrase = b"x" * 1024
Alex Chan532b79e2017-01-24 15:14:52 +0000898 pemFile = self._write_encrypted_pem(passphrase, tmpfile)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200899
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400900 def passphraseCallback(maxlen, verify, extra):
901 assert maxlen == 1024
Alex Gaynore7f51982016-09-11 11:48:14 -0400902 return passphrase + b"y"
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400903
904 context = Context(TLSv1_METHOD)
905 context.set_passwd_cb(passphraseCallback)
906 # This shall succeed because the truncated result is the correct
907 # passphrase.
908 context.use_privatekey_file(pemFile)
909
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400910 def test_set_info_callback(self):
911 """
Alex Chan532b79e2017-01-24 15:14:52 +0000912 `Context.set_info_callback` accepts a callable which will be
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200913 invoked when certain information about an SSL connection is available.
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400914 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500915 (server, client) = socket_pair()
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400916
917 clientSSL = Connection(Context(TLSv1_METHOD), client)
918 clientSSL.set_connect_state()
919
920 called = []
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200921
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400922 def info(conn, where, ret):
923 called.append((conn, where, ret))
924 context = Context(TLSv1_METHOD)
925 context.set_info_callback(info)
926 context.use_certificate(
927 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
928 context.use_privatekey(
929 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
930
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400931 serverSSL = Connection(context, server)
932 serverSSL.set_accept_state()
933
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -0500934 handshake(clientSSL, serverSSL)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400935
Jean-Paul Calderone3835e522014-02-02 11:12:30 -0500936 # The callback must always be called with a Connection instance as the
937 # first argument. It would probably be better to split this into
938 # separate tests for client and server side info callbacks so we could
939 # assert it is called with the right Connection instance. It would
940 # also be good to assert *something* about `where` and `ret`.
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -0500941 notConnections = [
942 conn for (conn, where, ret) in called
943 if not isinstance(conn, Connection)]
Alex Chan532b79e2017-01-24 15:14:52 +0000944 assert [] == notConnections, (
945 "Some info callback arguments were not Connection instances.")
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400946
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400947 def _load_verify_locations_test(self, *args):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400948 """
949 Create a client context which will verify the peer certificate and call
Alex Chan532b79e2017-01-24 15:14:52 +0000950 its `load_verify_locations` method with the given arguments.
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -0400951 Then connect it to a server and ensure that the handshake succeeds.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400952 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500953 (server, client) = socket_pair()
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400954
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400955 clientContext = Context(TLSv1_METHOD)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400956 clientContext.load_verify_locations(*args)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400957 # Require that the server certificate verify properly or the
958 # connection will fail.
959 clientContext.set_verify(
960 VERIFY_PEER,
961 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
962
963 clientSSL = Connection(clientContext, client)
964 clientSSL.set_connect_state()
965
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400966 serverContext = Context(TLSv1_METHOD)
967 serverContext.use_certificate(
968 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
969 serverContext.use_privatekey(
970 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
971
972 serverSSL = Connection(serverContext, server)
973 serverSSL.set_accept_state()
974
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400975 # Without load_verify_locations above, the handshake
976 # will fail:
977 # Error: [('SSL routines', 'SSL3_GET_SERVER_CERTIFICATE',
978 # 'certificate verify failed')]
979 handshake(clientSSL, serverSSL)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400980
981 cert = clientSSL.get_peer_certificate()
Alex Chan532b79e2017-01-24 15:14:52 +0000982 assert cert.get_subject().CN == 'Testing Root CA'
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400983
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400984 def _load_verify_cafile(self, cafile):
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400985 """
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400986 Verify that if path to a file containing a certificate is passed to
Alex Chan532b79e2017-01-24 15:14:52 +0000987 `Context.load_verify_locations` for the ``cafile`` parameter, that
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400988 certificate is used as a trust root for the purposes of verifying
Alex Chan532b79e2017-01-24 15:14:52 +0000989 connections created using that `Context`.
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400990 """
Alex Chan532b79e2017-01-24 15:14:52 +0000991 with open(cafile, 'w') as fObj:
992 fObj.write(cleartextCertificatePEM.decode('ascii'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400993
994 self._load_verify_locations_test(cafile)
995
Alex Chan532b79e2017-01-24 15:14:52 +0000996 def test_load_verify_bytes_cafile(self, tmpfile):
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400997 """
Alex Chan532b79e2017-01-24 15:14:52 +0000998 `Context.load_verify_locations` accepts a file name as a `bytes`
999 instance and uses the certificates within for verification purposes.
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001000 """
Alex Chan532b79e2017-01-24 15:14:52 +00001001 cafile = tmpfile + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001002 self._load_verify_cafile(cafile)
1003
Alex Chan532b79e2017-01-24 15:14:52 +00001004 def test_load_verify_unicode_cafile(self, tmpfile):
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001005 """
Alex Chan532b79e2017-01-24 15:14:52 +00001006 `Context.load_verify_locations` accepts a file name as a `unicode`
1007 instance and uses the certificates within for verification purposes.
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001008 """
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001009 self._load_verify_cafile(
Alex Chan532b79e2017-01-24 15:14:52 +00001010 tmpfile.decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001011 )
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001012
Alex Chan532b79e2017-01-24 15:14:52 +00001013 def test_load_verify_invalid_file(self, tmpfile):
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -04001014 """
Alex Chan532b79e2017-01-24 15:14:52 +00001015 `Context.load_verify_locations` raises `Error` when passed a
1016 non-existent cafile.
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -04001017 """
1018 clientContext = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001019 with pytest.raises(Error):
1020 clientContext.load_verify_locations(tmpfile)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001021
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001022 def _load_verify_directory_locations_capath(self, capath):
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001023 """
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001024 Verify that if path to a directory containing certificate files is
1025 passed to ``Context.load_verify_locations`` for the ``capath``
1026 parameter, those certificates are used as trust roots for the purposes
1027 of verifying connections created using that ``Context``.
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001028 """
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001029 makedirs(capath)
Jean-Paul Calderone24dfb332011-05-04 18:10:26 -04001030 # Hash values computed manually with c_rehash to avoid depending on
1031 # c_rehash in the test suite. One is from OpenSSL 0.9.8, the other
1032 # from OpenSSL 1.0.0.
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001033 for name in [b'c7adac82.0', b'c3705638.0']:
Jean-Paul Calderone05826732015-04-12 11:38:49 -04001034 cafile = join_bytes_or_unicode(capath, name)
1035 with open(cafile, 'w') as fObj:
1036 fObj.write(cleartextCertificatePEM.decode('ascii'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001037
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001038 self._load_verify_locations_test(None, capath)
1039
Alex Chan532b79e2017-01-24 15:14:52 +00001040 def test_load_verify_directory_bytes_capath(self, tmpfile):
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001041 """
Alex Chan532b79e2017-01-24 15:14:52 +00001042 `Context.load_verify_locations` accepts a directory name as a `bytes`
1043 instance and uses the certificates within for verification purposes.
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001044 """
1045 self._load_verify_directory_locations_capath(
Alex Chan532b79e2017-01-24 15:14:52 +00001046 tmpfile + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001047 )
1048
Alex Chan532b79e2017-01-24 15:14:52 +00001049 def test_load_verify_directory_unicode_capath(self, tmpfile):
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001050 """
Alex Chan532b79e2017-01-24 15:14:52 +00001051 `Context.load_verify_locations` accepts a directory name as a `unicode`
1052 instance and uses the certificates within for verification purposes.
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001053 """
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001054 self._load_verify_directory_locations_capath(
Alex Chan532b79e2017-01-24 15:14:52 +00001055 tmpfile.decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001056 )
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001057
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001058 def test_load_verify_locations_wrong_args(self):
1059 """
Alex Chan532b79e2017-01-24 15:14:52 +00001060 `Context.load_verify_locations` raises `TypeError` if with non-`str`
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001061 arguments.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001062 """
1063 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001064 with pytest.raises(TypeError):
1065 context.load_verify_locations(object())
1066 with pytest.raises(TypeError):
1067 context.load_verify_locations(object(), object())
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001068
Hynek Schlawack734d3022015-09-05 19:19:32 +02001069 @pytest.mark.skipif(
Paul Kehrer55fb3412017-06-29 18:44:08 -05001070 not platform.startswith("linux"),
1071 reason="Loading fallback paths is a linux-specific behavior to "
1072 "accommodate pyca/cryptography manylinux1 wheels"
1073 )
1074 def test_fallback_default_verify_paths(self, monkeypatch):
1075 """
1076 Test that we load certificates successfully on linux from the fallback
1077 path. To do this we set the _CRYPTOGRAPHY_MANYLINUX1_CA_FILE and
1078 _CRYPTOGRAPHY_MANYLINUX1_CA_DIR vars to be equal to whatever the
1079 current OpenSSL default is and we disable
1080 SSL_CTX_SET_default_verify_paths so that it can't find certs unless
1081 it loads via fallback.
1082 """
1083 context = Context(TLSv1_METHOD)
1084 monkeypatch.setattr(
1085 _lib, "SSL_CTX_set_default_verify_paths", lambda x: 1
1086 )
1087 monkeypatch.setattr(
1088 SSL,
1089 "_CRYPTOGRAPHY_MANYLINUX1_CA_FILE",
1090 _ffi.string(_lib.X509_get_default_cert_file())
1091 )
1092 monkeypatch.setattr(
1093 SSL,
1094 "_CRYPTOGRAPHY_MANYLINUX1_CA_DIR",
1095 _ffi.string(_lib.X509_get_default_cert_dir())
1096 )
1097 context.set_default_verify_paths()
1098 store = context.get_cert_store()
1099 sk_obj = _lib.X509_STORE_get0_objects(store._store)
1100 assert sk_obj != _ffi.NULL
1101 num = _lib.sk_X509_OBJECT_num(sk_obj)
1102 assert num != 0
1103
1104 def test_check_env_vars(self, monkeypatch):
1105 """
1106 Test that we return True/False appropriately if the env vars are set.
1107 """
1108 context = Context(TLSv1_METHOD)
1109 dir_var = "CUSTOM_DIR_VAR"
1110 file_var = "CUSTOM_FILE_VAR"
1111 assert context._check_env_vars_set(dir_var, file_var) is False
1112 monkeypatch.setenv(dir_var, "value")
1113 monkeypatch.setenv(file_var, "value")
1114 assert context._check_env_vars_set(dir_var, file_var) is True
1115 assert context._check_env_vars_set(dir_var, file_var) is True
1116
1117 def test_verify_no_fallback_if_env_vars_set(self, monkeypatch):
1118 """
1119 Test that we don't use the fallback path if env vars are set.
1120 """
1121 context = Context(TLSv1_METHOD)
1122 monkeypatch.setattr(
1123 _lib, "SSL_CTX_set_default_verify_paths", lambda x: 1
1124 )
1125 dir_env_var = _ffi.string(
1126 _lib.X509_get_default_cert_dir_env()
1127 ).decode("ascii")
1128 file_env_var = _ffi.string(
1129 _lib.X509_get_default_cert_file_env()
1130 ).decode("ascii")
1131 monkeypatch.setenv(dir_env_var, "value")
1132 monkeypatch.setenv(file_env_var, "value")
1133 context.set_default_verify_paths()
1134
1135 monkeypatch.setattr(
1136 context,
1137 "_fallback_default_verify_paths",
1138 raiser(SystemError)
1139 )
1140 context.set_default_verify_paths()
1141
1142 @pytest.mark.skipif(
Hynek Schlawack734d3022015-09-05 19:19:32 +02001143 platform == "win32",
1144 reason="set_default_verify_paths appears not to work on Windows. "
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -04001145 "See LP#404343 and LP#404344."
Hynek Schlawack734d3022015-09-05 19:19:32 +02001146 )
1147 def test_set_default_verify_paths(self):
1148 """
Alex Chan532b79e2017-01-24 15:14:52 +00001149 `Context.set_default_verify_paths` causes the platform-specific CA
1150 certificate locations to be used for verification purposes.
Hynek Schlawack734d3022015-09-05 19:19:32 +02001151 """
1152 # Testing this requires a server with a certificate signed by one
1153 # of the CAs in the platform CA location. Getting one of those
1154 # costs money. Fortunately (or unfortunately, depending on your
1155 # perspective), it's easy to think of a public server on the
1156 # internet which has such a certificate. Connecting to the network
1157 # in a unit test is bad, but it's the only way I can think of to
1158 # really test this. -exarkun
Hynek Schlawackbf887932015-10-21 17:13:47 +02001159 context = Context(SSLv23_METHOD)
Hynek Schlawack734d3022015-09-05 19:19:32 +02001160 context.set_default_verify_paths()
1161 context.set_verify(
1162 VERIFY_PEER,
1163 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001164
David Benjamin1fbe0642019-04-15 17:05:13 -05001165 client = socket_any_family()
Hynek Schlawackbf887932015-10-21 17:13:47 +02001166 client.connect(("encrypted.google.com", 443))
Hynek Schlawack734d3022015-09-05 19:19:32 +02001167 clientSSL = Connection(context, client)
1168 clientSSL.set_connect_state()
Alex Gaynor373926c2018-05-12 07:43:07 -04001169 clientSSL.set_tlsext_host_name(b"encrypted.google.com")
Hynek Schlawack734d3022015-09-05 19:19:32 +02001170 clientSSL.do_handshake()
1171 clientSSL.send(b"GET / HTTP/1.0\r\n\r\n")
Alex Chan532b79e2017-01-24 15:14:52 +00001172 assert clientSSL.recv(1024)
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05001173
Paul Kehrer55fb3412017-06-29 18:44:08 -05001174 def test_fallback_path_is_not_file_or_dir(self):
1175 """
1176 Test that when passed empty arrays or paths that do not exist no
1177 errors are raised.
1178 """
1179 context = Context(TLSv1_METHOD)
1180 context._fallback_default_verify_paths([], [])
1181 context._fallback_default_verify_paths(
1182 ["/not/a/file"], ["/not/a/dir"]
1183 )
1184
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001185 def test_add_extra_chain_cert_invalid_cert(self):
1186 """
Alex Chan532b79e2017-01-24 15:14:52 +00001187 `Context.add_extra_chain_cert` raises `TypeError` if called with an
1188 object which is not an instance of `X509`.
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001189 """
1190 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001191 with pytest.raises(TypeError):
1192 context.add_extra_chain_cert(object())
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001193
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001194 def _handshake_test(self, serverContext, clientContext):
1195 """
1196 Verify that a client and server created with the given contexts can
1197 successfully handshake and communicate.
1198 """
1199 serverSocket, clientSocket = socket_pair()
1200
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001201 server = Connection(serverContext, serverSocket)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001202 server.set_accept_state()
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001203
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001204 client = Connection(clientContext, clientSocket)
1205 client.set_connect_state()
1206
1207 # Make them talk to each other.
Alex Chan532b79e2017-01-24 15:14:52 +00001208 # interact_in_memory(client, server)
1209 for _ in range(3):
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001210 for s in [client, server]:
1211 try:
1212 s.do_handshake()
1213 except WantReadError:
1214 pass
1215
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001216 def test_set_verify_callback_connection_argument(self):
1217 """
1218 The first argument passed to the verify callback is the
Alex Chan532b79e2017-01-24 15:14:52 +00001219 `Connection` instance for which verification is taking place.
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001220 """
1221 serverContext = Context(TLSv1_METHOD)
1222 serverContext.use_privatekey(
1223 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1224 serverContext.use_certificate(
1225 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1226 serverConnection = Connection(serverContext, None)
1227
1228 class VerifyCallback(object):
1229 def callback(self, connection, *args):
1230 self.connection = connection
1231 return 1
1232
1233 verify = VerifyCallback()
1234 clientContext = Context(TLSv1_METHOD)
1235 clientContext.set_verify(VERIFY_PEER, verify.callback)
1236 clientConnection = Connection(clientContext, None)
1237 clientConnection.set_connect_state()
1238
Alex Chan532b79e2017-01-24 15:14:52 +00001239 handshake_in_memory(clientConnection, serverConnection)
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001240
Alex Chan532b79e2017-01-24 15:14:52 +00001241 assert verify.connection is clientConnection
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001242
Paul Kehrere7381862017-11-30 20:55:25 +08001243 def test_x509_in_verify_works(self):
1244 """
1245 We had a bug where the X509 cert instantiated in the callback wrapper
1246 didn't __init__ so it was missing objects needed when calling
1247 get_subject. This test sets up a handshake where we call get_subject
1248 on the cert provided to the verify callback.
1249 """
1250 serverContext = Context(TLSv1_METHOD)
1251 serverContext.use_privatekey(
1252 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1253 serverContext.use_certificate(
1254 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1255 serverConnection = Connection(serverContext, None)
1256
1257 def verify_cb_get_subject(conn, cert, errnum, depth, ok):
1258 assert cert.get_subject()
1259 return 1
1260
1261 clientContext = Context(TLSv1_METHOD)
1262 clientContext.set_verify(VERIFY_PEER, verify_cb_get_subject)
1263 clientConnection = Connection(clientContext, None)
1264 clientConnection.set_connect_state()
1265
1266 handshake_in_memory(clientConnection, serverConnection)
1267
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001268 def test_set_verify_callback_exception(self):
1269 """
Alex Chan532b79e2017-01-24 15:14:52 +00001270 If the verify callback passed to `Context.set_verify` raises an
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001271 exception, verification fails and the exception is propagated to the
Alex Chan532b79e2017-01-24 15:14:52 +00001272 caller of `Connection.do_handshake`.
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001273 """
Paul Kehrer7d5a3bf2019-01-21 12:24:02 -06001274 serverContext = Context(TLSv1_2_METHOD)
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001275 serverContext.use_privatekey(
1276 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1277 serverContext.use_certificate(
1278 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1279
Paul Kehrer7d5a3bf2019-01-21 12:24:02 -06001280 clientContext = Context(TLSv1_2_METHOD)
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001281
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001282 def verify_callback(*args):
1283 raise Exception("silly verify failure")
1284 clientContext.set_verify(VERIFY_PEER, verify_callback)
1285
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01001286 with pytest.raises(Exception) as exc:
1287 self._handshake_test(serverContext, clientContext)
1288
Alex Chan532b79e2017-01-24 15:14:52 +00001289 assert "silly verify failure" == str(exc.value)
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001290
Alex Chan532b79e2017-01-24 15:14:52 +00001291 def test_add_extra_chain_cert(self, tmpdir):
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001292 """
Alex Chan532b79e2017-01-24 15:14:52 +00001293 `Context.add_extra_chain_cert` accepts an `X509`
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001294 instance to add to the certificate chain.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001295
Alex Chan532b79e2017-01-24 15:14:52 +00001296 See `_create_certificate_chain` for the details of the
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001297 certificate chain tested.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001298
1299 The chain is tested by starting a server with scert and connecting
1300 to it with a client which trusts cacert and requires verification to
1301 succeed.
1302 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001303 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001304 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1305
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001306 # Dump the CA certificate to a file because that's the only way to load
1307 # it as a trusted CA in the client context.
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001308 for cert, name in [(cacert, 'ca.pem'),
1309 (icert, 'i.pem'),
1310 (scert, 's.pem')]:
Alex Chan532b79e2017-01-24 15:14:52 +00001311 with tmpdir.join(name).open('w') as f:
Hynek Schlawacke90680f2015-04-16 15:09:27 -04001312 f.write(dump_certificate(FILETYPE_PEM, cert).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001313
Hynek Schlawack1902c012015-04-16 15:06:41 -04001314 for key, name in [(cakey, 'ca.key'),
1315 (ikey, 'i.key'),
1316 (skey, 's.key')]:
Alex Chan532b79e2017-01-24 15:14:52 +00001317 with tmpdir.join(name).open('w') as f:
Hynek Schlawacke90680f2015-04-16 15:09:27 -04001318 f.write(dump_privatekey(FILETYPE_PEM, key).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001319
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001320 # Create the server context
1321 serverContext = Context(TLSv1_METHOD)
1322 serverContext.use_privatekey(skey)
1323 serverContext.use_certificate(scert)
Jean-Paul Calderone16cf03d2010-09-08 18:53:39 -04001324 # The client already has cacert, we only need to give them icert.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001325 serverContext.add_extra_chain_cert(icert)
1326
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001327 # Create the client
1328 clientContext = Context(TLSv1_METHOD)
1329 clientContext.set_verify(
1330 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Alex Chan532b79e2017-01-24 15:14:52 +00001331 clientContext.load_verify_locations(str(tmpdir.join("ca.pem")))
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001332
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001333 # Try it out.
1334 self._handshake_test(serverContext, clientContext)
1335
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001336 def _use_certificate_chain_file_test(self, certdir):
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001337 """
Alex Chan532b79e2017-01-24 15:14:52 +00001338 Verify that `Context.use_certificate_chain_file` reads a
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001339 certificate chain from a specified file.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001340
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001341 The chain is tested by starting a server with scert and connecting to
1342 it with a client which trusts cacert and requires verification to
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001343 succeed.
1344 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001345 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001346 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1347
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001348 makedirs(certdir)
1349
Jean-Paul Calderone05826732015-04-12 11:38:49 -04001350 chainFile = join_bytes_or_unicode(certdir, "chain.pem")
1351 caFile = join_bytes_or_unicode(certdir, "ca.pem")
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001352
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001353 # Write out the chain file.
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001354 with open(chainFile, 'wb') as fObj:
1355 # Most specific to least general.
1356 fObj.write(dump_certificate(FILETYPE_PEM, scert))
1357 fObj.write(dump_certificate(FILETYPE_PEM, icert))
1358 fObj.write(dump_certificate(FILETYPE_PEM, cacert))
1359
1360 with open(caFile, 'w') as fObj:
1361 fObj.write(dump_certificate(FILETYPE_PEM, cacert).decode('ascii'))
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001362
1363 serverContext = Context(TLSv1_METHOD)
1364 serverContext.use_certificate_chain_file(chainFile)
1365 serverContext.use_privatekey(skey)
1366
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001367 clientContext = Context(TLSv1_METHOD)
1368 clientContext.set_verify(
1369 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001370 clientContext.load_verify_locations(caFile)
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001371
1372 self._handshake_test(serverContext, clientContext)
1373
Alex Chan532b79e2017-01-24 15:14:52 +00001374 def test_use_certificate_chain_file_bytes(self, tmpfile):
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001375 """
1376 ``Context.use_certificate_chain_file`` accepts the name of a file (as
1377 an instance of ``bytes``) to specify additional certificates to use to
1378 construct and verify a trust chain.
1379 """
1380 self._use_certificate_chain_file_test(
Alex Chan532b79e2017-01-24 15:14:52 +00001381 tmpfile + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001382 )
1383
Alex Chan532b79e2017-01-24 15:14:52 +00001384 def test_use_certificate_chain_file_unicode(self, tmpfile):
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001385 """
1386 ``Context.use_certificate_chain_file`` accepts the name of a file (as
1387 an instance of ``unicode``) to specify additional certificates to use
1388 to construct and verify a trust chain.
1389 """
1390 self._use_certificate_chain_file_test(
Alex Chan532b79e2017-01-24 15:14:52 +00001391 tmpfile.decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001392 )
1393
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001394 def test_use_certificate_chain_file_wrong_args(self):
1395 """
Alex Chan532b79e2017-01-24 15:14:52 +00001396 `Context.use_certificate_chain_file` raises `TypeError` if passed a
1397 non-byte string single argument.
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001398 """
1399 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001400 with pytest.raises(TypeError):
1401 context.use_certificate_chain_file(object())
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001402
Alex Chan532b79e2017-01-24 15:14:52 +00001403 def test_use_certificate_chain_file_missing_file(self, tmpfile):
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001404 """
Alex Chan532b79e2017-01-24 15:14:52 +00001405 `Context.use_certificate_chain_file` raises `OpenSSL.SSL.Error` when
1406 passed a bad chain file name (for example, the name of a file which
1407 does not exist).
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001408 """
1409 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001410 with pytest.raises(Error):
1411 context.use_certificate_chain_file(tmpfile)
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001412
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001413 def test_set_verify_mode(self):
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001414 """
Alex Chan532b79e2017-01-24 15:14:52 +00001415 `Context.get_verify_mode` returns the verify mode flags previously
1416 passed to `Context.set_verify`.
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001417 """
1418 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001419 assert context.get_verify_mode() == 0
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001420 context.set_verify(
1421 VERIFY_PEER | VERIFY_CLIENT_ONCE, lambda *args: None)
Alex Chan532b79e2017-01-24 15:14:52 +00001422 assert context.get_verify_mode() == (VERIFY_PEER | VERIFY_CLIENT_ONCE)
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001423
Alex Chanfb078d82017-04-20 11:16:15 +01001424 @pytest.mark.parametrize('mode', [None, 1.0, object(), 'mode'])
1425 def test_set_verify_wrong_mode_arg(self, mode):
1426 """
1427 `Context.set_verify` raises `TypeError` if the first argument is
1428 not an integer.
1429 """
1430 context = Context(TLSv1_METHOD)
1431 with pytest.raises(TypeError):
1432 context.set_verify(mode=mode, callback=lambda *args: None)
1433
1434 @pytest.mark.parametrize('callback', [None, 1.0, 'mode', ('foo', 'bar')])
1435 def test_set_verify_wrong_callable_arg(self, callback):
1436 """
Alex Gaynor40bc0f12018-05-14 14:06:16 -04001437 `Context.set_verify` raises `TypeError` if the second argument
Alex Chanfb078d82017-04-20 11:16:15 +01001438 is not callable.
1439 """
1440 context = Context(TLSv1_METHOD)
1441 with pytest.raises(TypeError):
1442 context.set_verify(mode=VERIFY_PEER, callback=callback)
1443
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001444 def test_load_tmp_dh_wrong_args(self):
1445 """
Alex Chan532b79e2017-01-24 15:14:52 +00001446 `Context.load_tmp_dh` raises `TypeError` if called with a
1447 non-`str` argument.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001448 """
1449 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001450 with pytest.raises(TypeError):
1451 context.load_tmp_dh(object())
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001452
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001453 def test_load_tmp_dh_missing_file(self):
1454 """
Alex Chan532b79e2017-01-24 15:14:52 +00001455 `Context.load_tmp_dh` raises `OpenSSL.SSL.Error` if the
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001456 specified file does not exist.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001457 """
1458 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001459 with pytest.raises(Error):
1460 context.load_tmp_dh(b"hello")
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001461
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001462 def _load_tmp_dh_test(self, dhfilename):
Jean-Paul Calderone4e0c43f2015-04-13 10:15:17 -04001463 """
1464 Verify that calling ``Context.load_tmp_dh`` with the given filename
1465 does not raise an exception.
1466 """
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001467 context = Context(TLSv1_METHOD)
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001468 with open(dhfilename, "w") as dhfile:
1469 dhfile.write(dhparam)
1470
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001471 context.load_tmp_dh(dhfilename)
1472 # XXX What should I assert here? -exarkun
1473
Alex Chan532b79e2017-01-24 15:14:52 +00001474 def test_load_tmp_dh_bytes(self, tmpfile):
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001475 """
Alex Chan532b79e2017-01-24 15:14:52 +00001476 `Context.load_tmp_dh` loads Diffie-Hellman parameters from the
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001477 specified file (given as ``bytes``).
1478 """
1479 self._load_tmp_dh_test(
Alex Chan532b79e2017-01-24 15:14:52 +00001480 tmpfile + NON_ASCII.encode(getfilesystemencoding()),
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001481 )
1482
Alex Chan532b79e2017-01-24 15:14:52 +00001483 def test_load_tmp_dh_unicode(self, tmpfile):
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001484 """
Alex Chan532b79e2017-01-24 15:14:52 +00001485 `Context.load_tmp_dh` loads Diffie-Hellman parameters from the
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001486 specified file (given as ``unicode``).
1487 """
1488 self._load_tmp_dh_test(
Alex Chan532b79e2017-01-24 15:14:52 +00001489 tmpfile.decode(getfilesystemencoding()) + NON_ASCII,
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001490 )
1491
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001492 def test_set_tmp_ecdh(self):
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001493 """
Alex Chan532b79e2017-01-24 15:14:52 +00001494 `Context.set_tmp_ecdh` sets the elliptic curve for Diffie-Hellman to
1495 the specified curve.
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001496 """
1497 context = Context(TLSv1_METHOD)
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001498 for curve in get_elliptic_curves():
Hynek Schlawacka07fa8c2015-10-17 10:15:28 +02001499 if curve.name.startswith(u"Oakley-"):
Hynek Schlawack7408aff2015-10-17 09:51:16 +02001500 # Setting Oakley-EC2N-4 and Oakley-EC2N-3 adds
1501 # ('bignum routines', 'BN_mod_inverse', 'no inverse') to the
1502 # error queue on OpenSSL 1.0.2.
1503 continue
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001504 # The only easily "assertable" thing is that it does not raise an
1505 # exception.
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001506 context.set_tmp_ecdh(curve)
Alex Gaynor12dc0842014-01-17 12:51:31 -06001507
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001508 def test_set_session_cache_mode_wrong_args(self):
1509 """
Alex Chan532b79e2017-01-24 15:14:52 +00001510 `Context.set_session_cache_mode` raises `TypeError` if called with
1511 a non-integer argument.
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001512 called with other than one integer argument.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001513 """
1514 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001515 with pytest.raises(TypeError):
1516 context.set_session_cache_mode(object())
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001517
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001518 def test_session_cache_mode(self):
1519 """
Alex Chan532b79e2017-01-24 15:14:52 +00001520 `Context.set_session_cache_mode` specifies how sessions are cached.
1521 The setting can be retrieved via `Context.get_session_cache_mode`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001522 """
1523 context = Context(TLSv1_METHOD)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001524 context.set_session_cache_mode(SESS_CACHE_OFF)
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001525 off = context.set_session_cache_mode(SESS_CACHE_BOTH)
Alex Chan532b79e2017-01-24 15:14:52 +00001526 assert SESS_CACHE_OFF == off
1527 assert SESS_CACHE_BOTH == context.get_session_cache_mode()
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001528
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001529 def test_get_cert_store(self):
1530 """
Alex Chan532b79e2017-01-24 15:14:52 +00001531 `Context.get_cert_store` returns a `X509Store` instance.
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001532 """
1533 context = Context(TLSv1_METHOD)
1534 store = context.get_cert_store()
Alex Chan532b79e2017-01-24 15:14:52 +00001535 assert isinstance(store, X509Store)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001536
Jeremy Lainé02261ad2018-05-16 18:33:25 +02001537 def test_set_tlsext_use_srtp_not_bytes(self):
1538 """
1539 `Context.set_tlsext_use_srtp' enables negotiating SRTP keying material.
1540
1541 It raises a TypeError if the list of profiles is not a byte string.
1542 """
1543 context = Context(TLSv1_METHOD)
1544 with pytest.raises(TypeError):
1545 context.set_tlsext_use_srtp(text_type('SRTP_AES128_CM_SHA1_80'))
1546
1547 def test_set_tlsext_use_srtp_invalid_profile(self):
1548 """
1549 `Context.set_tlsext_use_srtp' enables negotiating SRTP keying material.
1550
1551 It raises an Error if the call to OpenSSL fails.
1552 """
1553 context = Context(TLSv1_METHOD)
1554 with pytest.raises(Error):
1555 context.set_tlsext_use_srtp(b'SRTP_BOGUS')
1556
1557 def test_set_tlsext_use_srtp_valid(self):
1558 """
1559 `Context.set_tlsext_use_srtp' enables negotiating SRTP keying material.
1560
1561 It does not return anything.
1562 """
1563 context = Context(TLSv1_METHOD)
1564 assert context.set_tlsext_use_srtp(b'SRTP_AES128_CM_SHA1_80') is None
1565
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001566
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001567class TestServerNameCallback(object):
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001568 """
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001569 Tests for `Context.set_tlsext_servername_callback` and its
1570 interaction with `Connection`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001571 """
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001572 def test_old_callback_forgotten(self):
1573 """
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001574 If `Context.set_tlsext_servername_callback` is used to specify
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001575 a new callback, the one it replaces is dereferenced.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001576 """
Alex Chanfb078d82017-04-20 11:16:15 +01001577 def callback(connection): # pragma: no cover
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001578 pass
1579
Alex Chanfb078d82017-04-20 11:16:15 +01001580 def replacement(connection): # pragma: no cover
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001581 pass
1582
1583 context = Context(TLSv1_METHOD)
1584 context.set_tlsext_servername_callback(callback)
1585
1586 tracker = ref(callback)
1587 del callback
1588
1589 context.set_tlsext_servername_callback(replacement)
Jean-Paul Calderoned4033eb2014-01-11 08:21:46 -05001590
1591 # One run of the garbage collector happens to work on CPython. PyPy
1592 # doesn't collect the underlying object until a second run for whatever
1593 # reason. That's fine, it still demonstrates our code has properly
1594 # dropped the reference.
1595 collect()
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001596 collect()
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001597
1598 callback = tracker()
1599 if callback is not None:
1600 referrers = get_referrers(callback)
Alex Chanfb078d82017-04-20 11:16:15 +01001601 if len(referrers) > 1: # pragma: nocover
1602 pytest.fail("Some references remain: %r" % (referrers,))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001603
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001604 def test_no_servername(self):
1605 """
1606 When a client specifies no server name, the callback passed to
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001607 `Context.set_tlsext_servername_callback` is invoked and the
1608 result of `Connection.get_servername` is `None`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001609 """
1610 args = []
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001611
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001612 def servername(conn):
1613 args.append((conn, conn.get_servername()))
1614 context = Context(TLSv1_METHOD)
1615 context.set_tlsext_servername_callback(servername)
1616
1617 # Lose our reference to it. The Context is responsible for keeping it
1618 # alive now.
1619 del servername
1620 collect()
1621
1622 # Necessary to actually accept the connection
1623 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001624 context.use_certificate(
1625 load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001626
1627 # Do a little connection to trigger the logic
1628 server = Connection(context, None)
1629 server.set_accept_state()
1630
1631 client = Connection(Context(TLSv1_METHOD), None)
1632 client.set_connect_state()
1633
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001634 interact_in_memory(server, client)
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001635
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001636 assert args == [(server, None)]
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001637
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001638 def test_servername(self):
1639 """
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001640 When a client specifies a server name in its hello message, the
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001641 callback passed to `Contexts.set_tlsext_servername_callback` is
1642 invoked and the result of `Connection.get_servername` is that
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001643 server name.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001644 """
1645 args = []
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001646
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001647 def servername(conn):
1648 args.append((conn, conn.get_servername()))
1649 context = Context(TLSv1_METHOD)
1650 context.set_tlsext_servername_callback(servername)
1651
1652 # Necessary to actually accept the connection
1653 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001654 context.use_certificate(
1655 load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001656
1657 # Do a little connection to trigger the logic
1658 server = Connection(context, None)
1659 server.set_accept_state()
1660
1661 client = Connection(Context(TLSv1_METHOD), None)
1662 client.set_connect_state()
Alex Gaynore7f51982016-09-11 11:48:14 -04001663 client.set_tlsext_host_name(b"foo1.example.com")
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001664
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001665 interact_in_memory(server, client)
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001666
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001667 assert args == [(server, b"foo1.example.com")]
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001668
1669
Paul Kehrer4d575902019-02-26 21:42:12 +08001670@pytest.mark.skipif(
1671 not _lib.Cryptography_HAS_NEXTPROTONEG, reason="NPN is not available"
1672)
Alex Chan9e08b3e2016-11-10 12:18:54 +00001673class TestNextProtoNegotiation(object):
Cory Benfield84a121e2014-03-31 20:30:25 +01001674 """
1675 Test for Next Protocol Negotiation in PyOpenSSL.
1676 """
Alex Chan9e08b3e2016-11-10 12:18:54 +00001677 def test_npn_success(self):
1678 """
1679 Tests that clients and servers that agree on the negotiated next
1680 protocol can correct establish a connection, and that the agreed
1681 protocol is reported by the connections.
1682 """
1683 advertise_args = []
1684 select_args = []
1685
1686 def advertise(conn):
1687 advertise_args.append((conn,))
1688 return [b'http/1.1', b'spdy/2']
1689
1690 def select(conn, options):
1691 select_args.append((conn, options))
1692 return b'spdy/2'
1693
1694 server_context = Context(TLSv1_METHOD)
1695 server_context.set_npn_advertise_callback(advertise)
1696
1697 client_context = Context(TLSv1_METHOD)
1698 client_context.set_npn_select_callback(select)
1699
1700 # Necessary to actually accept the connection
1701 server_context.use_privatekey(
1702 load_privatekey(FILETYPE_PEM, server_key_pem))
1703 server_context.use_certificate(
1704 load_certificate(FILETYPE_PEM, server_cert_pem))
1705
1706 # Do a little connection to trigger the logic
1707 server = Connection(server_context, None)
1708 server.set_accept_state()
1709
1710 client = Connection(client_context, None)
1711 client.set_connect_state()
1712
1713 interact_in_memory(server, client)
1714
1715 assert advertise_args == [(server,)]
1716 assert select_args == [(client, [b'http/1.1', b'spdy/2'])]
1717
1718 assert server.get_next_proto_negotiated() == b'spdy/2'
1719 assert client.get_next_proto_negotiated() == b'spdy/2'
1720
1721 def test_npn_client_fail(self):
1722 """
1723 Tests that when clients and servers cannot agree on what protocol
1724 to use next that the TLS connection does not get established.
1725 """
1726 advertise_args = []
1727 select_args = []
1728
1729 def advertise(conn):
1730 advertise_args.append((conn,))
1731 return [b'http/1.1', b'spdy/2']
1732
1733 def select(conn, options):
1734 select_args.append((conn, options))
1735 return b''
1736
1737 server_context = Context(TLSv1_METHOD)
1738 server_context.set_npn_advertise_callback(advertise)
1739
1740 client_context = Context(TLSv1_METHOD)
1741 client_context.set_npn_select_callback(select)
1742
1743 # Necessary to actually accept the connection
1744 server_context.use_privatekey(
1745 load_privatekey(FILETYPE_PEM, server_key_pem))
1746 server_context.use_certificate(
1747 load_certificate(FILETYPE_PEM, server_cert_pem))
1748
1749 # Do a little connection to trigger the logic
1750 server = Connection(server_context, None)
1751 server.set_accept_state()
1752
1753 client = Connection(client_context, None)
1754 client.set_connect_state()
1755
1756 # If the client doesn't return anything, the connection will fail.
1757 with pytest.raises(Error):
1758 interact_in_memory(server, client)
1759
1760 assert advertise_args == [(server,)]
1761 assert select_args == [(client, [b'http/1.1', b'spdy/2'])]
1762
1763 def test_npn_select_error(self):
1764 """
1765 Test that we can handle exceptions in the select callback. If
1766 select fails it should be fatal to the connection.
1767 """
1768 advertise_args = []
1769
1770 def advertise(conn):
1771 advertise_args.append((conn,))
1772 return [b'http/1.1', b'spdy/2']
1773
1774 def select(conn, options):
1775 raise TypeError
1776
1777 server_context = Context(TLSv1_METHOD)
1778 server_context.set_npn_advertise_callback(advertise)
1779
1780 client_context = Context(TLSv1_METHOD)
1781 client_context.set_npn_select_callback(select)
1782
1783 # Necessary to actually accept the connection
1784 server_context.use_privatekey(
1785 load_privatekey(FILETYPE_PEM, server_key_pem))
1786 server_context.use_certificate(
1787 load_certificate(FILETYPE_PEM, server_cert_pem))
1788
1789 # Do a little connection to trigger the logic
1790 server = Connection(server_context, None)
1791 server.set_accept_state()
1792
1793 client = Connection(client_context, None)
1794 client.set_connect_state()
1795
1796 # If the callback throws an exception it should be raised here.
1797 with pytest.raises(TypeError):
1798 interact_in_memory(server, client)
1799 assert advertise_args == [(server,), ]
1800
1801 def test_npn_advertise_error(self):
1802 """
1803 Test that we can handle exceptions in the advertise callback. If
1804 advertise fails no NPN is advertised to the client.
1805 """
1806 select_args = []
1807
1808 def advertise(conn):
1809 raise TypeError
1810
1811 def select(conn, options): # pragma: nocover
Cory Benfieldba1820d2015-04-13 17:39:12 -04001812 """
Alex Chan9e08b3e2016-11-10 12:18:54 +00001813 Assert later that no args are actually appended.
Cory Benfieldba1820d2015-04-13 17:39:12 -04001814 """
Alex Chan9e08b3e2016-11-10 12:18:54 +00001815 select_args.append((conn, options))
1816 return b''
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001817
Alex Chan9e08b3e2016-11-10 12:18:54 +00001818 server_context = Context(TLSv1_METHOD)
1819 server_context.set_npn_advertise_callback(advertise)
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001820
Alex Chan9e08b3e2016-11-10 12:18:54 +00001821 client_context = Context(TLSv1_METHOD)
1822 client_context.set_npn_select_callback(select)
Cory Benfield84a121e2014-03-31 20:30:25 +01001823
Alex Chan9e08b3e2016-11-10 12:18:54 +00001824 # Necessary to actually accept the connection
1825 server_context.use_privatekey(
1826 load_privatekey(FILETYPE_PEM, server_key_pem))
1827 server_context.use_certificate(
1828 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield84a121e2014-03-31 20:30:25 +01001829
Alex Chan9e08b3e2016-11-10 12:18:54 +00001830 # Do a little connection to trigger the logic
1831 server = Connection(server_context, None)
1832 server.set_accept_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001833
Alex Chan9e08b3e2016-11-10 12:18:54 +00001834 client = Connection(client_context, None)
1835 client.set_connect_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001836
Alex Chan9e08b3e2016-11-10 12:18:54 +00001837 # If the client doesn't return anything, the connection will fail.
1838 with pytest.raises(TypeError):
1839 interact_in_memory(server, client)
1840 assert select_args == []
Cory Benfield0ea76e72015-03-22 09:05:28 +00001841
1842
Alex Chanec1e32d2016-11-10 14:11:45 +00001843class TestApplicationLayerProtoNegotiation(object):
Cory Benfield12eae892014-06-07 15:42:56 +01001844 """
1845 Tests for ALPN in PyOpenSSL.
1846 """
Cory Benfielde46fa842015-04-13 16:50:49 -04001847 # Skip tests on versions that don't support ALPN.
1848 if _lib.Cryptography_HAS_ALPN:
Cory Benfield12eae892014-06-07 15:42:56 +01001849
Cory Benfielde46fa842015-04-13 16:50:49 -04001850 def test_alpn_success(self):
1851 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04001852 Clients and servers that agree on the negotiated ALPN protocol can
1853 correct establish a connection, and the agreed protocol is reported
1854 by the connections.
Cory Benfielde46fa842015-04-13 16:50:49 -04001855 """
1856 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001857
Cory Benfielde46fa842015-04-13 16:50:49 -04001858 def select(conn, options):
1859 select_args.append((conn, options))
1860 return b'spdy/2'
Cory Benfield12eae892014-06-07 15:42:56 +01001861
Cory Benfielde46fa842015-04-13 16:50:49 -04001862 client_context = Context(TLSv1_METHOD)
1863 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfield12eae892014-06-07 15:42:56 +01001864
Cory Benfielde46fa842015-04-13 16:50:49 -04001865 server_context = Context(TLSv1_METHOD)
1866 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01001867
Cory Benfielde46fa842015-04-13 16:50:49 -04001868 # Necessary to actually accept the connection
1869 server_context.use_privatekey(
1870 load_privatekey(FILETYPE_PEM, server_key_pem))
1871 server_context.use_certificate(
1872 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield12eae892014-06-07 15:42:56 +01001873
Cory Benfielde46fa842015-04-13 16:50:49 -04001874 # Do a little connection to trigger the logic
1875 server = Connection(server_context, None)
1876 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001877
Cory Benfielde46fa842015-04-13 16:50:49 -04001878 client = Connection(client_context, None)
1879 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001880
Alex Chanec1e32d2016-11-10 14:11:45 +00001881 interact_in_memory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001882
Alex Chanec1e32d2016-11-10 14:11:45 +00001883 assert select_args == [(server, [b'http/1.1', b'spdy/2'])]
Cory Benfielde46fa842015-04-13 16:50:49 -04001884
Alex Chanec1e32d2016-11-10 14:11:45 +00001885 assert server.get_alpn_proto_negotiated() == b'spdy/2'
1886 assert client.get_alpn_proto_negotiated() == b'spdy/2'
Cory Benfield12eae892014-06-07 15:42:56 +01001887
Cory Benfielde46fa842015-04-13 16:50:49 -04001888 def test_alpn_set_on_connection(self):
1889 """
1890 The same as test_alpn_success, but setting the ALPN protocols on
1891 the connection rather than the context.
1892 """
1893 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001894
Cory Benfielde46fa842015-04-13 16:50:49 -04001895 def select(conn, options):
1896 select_args.append((conn, options))
1897 return b'spdy/2'
Cory Benfield12eae892014-06-07 15:42:56 +01001898
Cory Benfielde46fa842015-04-13 16:50:49 -04001899 # Setup the client context but don't set any ALPN protocols.
1900 client_context = Context(TLSv1_METHOD)
Cory Benfield12eae892014-06-07 15:42:56 +01001901
Cory Benfielde46fa842015-04-13 16:50:49 -04001902 server_context = Context(TLSv1_METHOD)
1903 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01001904
Cory Benfielde46fa842015-04-13 16:50:49 -04001905 # Necessary to actually accept the connection
1906 server_context.use_privatekey(
1907 load_privatekey(FILETYPE_PEM, server_key_pem))
1908 server_context.use_certificate(
1909 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield12eae892014-06-07 15:42:56 +01001910
Cory Benfielde46fa842015-04-13 16:50:49 -04001911 # Do a little connection to trigger the logic
1912 server = Connection(server_context, None)
1913 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001914
Cory Benfielde46fa842015-04-13 16:50:49 -04001915 # Set the ALPN protocols on the client connection.
1916 client = Connection(client_context, None)
1917 client.set_alpn_protos([b'http/1.1', b'spdy/2'])
1918 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001919
Alex Chanec1e32d2016-11-10 14:11:45 +00001920 interact_in_memory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001921
Alex Chanec1e32d2016-11-10 14:11:45 +00001922 assert select_args == [(server, [b'http/1.1', b'spdy/2'])]
Cory Benfield12eae892014-06-07 15:42:56 +01001923
Alex Chanec1e32d2016-11-10 14:11:45 +00001924 assert server.get_alpn_proto_negotiated() == b'spdy/2'
1925 assert client.get_alpn_proto_negotiated() == b'spdy/2'
Cory Benfield12eae892014-06-07 15:42:56 +01001926
Cory Benfielde46fa842015-04-13 16:50:49 -04001927 def test_alpn_server_fail(self):
1928 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04001929 When clients and servers cannot agree on what protocol to use next
1930 the TLS connection does not get established.
Cory Benfielde46fa842015-04-13 16:50:49 -04001931 """
1932 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001933
Cory Benfielde46fa842015-04-13 16:50:49 -04001934 def select(conn, options):
1935 select_args.append((conn, options))
1936 return b''
Cory Benfield12eae892014-06-07 15:42:56 +01001937
Cory Benfielde46fa842015-04-13 16:50:49 -04001938 client_context = Context(TLSv1_METHOD)
1939 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfield12eae892014-06-07 15:42:56 +01001940
Cory Benfielde46fa842015-04-13 16:50:49 -04001941 server_context = Context(TLSv1_METHOD)
1942 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01001943
Cory Benfielde46fa842015-04-13 16:50:49 -04001944 # Necessary to actually accept the connection
1945 server_context.use_privatekey(
1946 load_privatekey(FILETYPE_PEM, server_key_pem))
1947 server_context.use_certificate(
1948 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield12eae892014-06-07 15:42:56 +01001949
Cory Benfielde46fa842015-04-13 16:50:49 -04001950 # Do a little connection to trigger the logic
1951 server = Connection(server_context, None)
1952 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001953
Cory Benfielde46fa842015-04-13 16:50:49 -04001954 client = Connection(client_context, None)
1955 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001956
Cory Benfielde46fa842015-04-13 16:50:49 -04001957 # If the client doesn't return anything, the connection will fail.
Alex Chanec1e32d2016-11-10 14:11:45 +00001958 with pytest.raises(Error):
1959 interact_in_memory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001960
Alex Chanec1e32d2016-11-10 14:11:45 +00001961 assert select_args == [(server, [b'http/1.1', b'spdy/2'])]
Cory Benfield12eae892014-06-07 15:42:56 +01001962
Mark Williams5d890a02019-11-17 19:56:26 -08001963 def test_alpn_no_server_overlap(self):
1964 """
1965 A server can allow a TLS handshake to complete without
1966 agreeing to an application protocol by returning
1967 ``NO_OVERLAPPING_PROTOCOLS``.
1968 """
1969 refusal_args = []
1970
1971 def refusal(conn, options):
1972 refusal_args.append((conn, options))
1973 return NO_OVERLAPPING_PROTOCOLS
1974
1975 client_context = Context(SSLv23_METHOD)
1976 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
1977
1978 server_context = Context(SSLv23_METHOD)
1979 server_context.set_alpn_select_callback(refusal)
1980
1981 # Necessary to actually accept the connection
1982 server_context.use_privatekey(
1983 load_privatekey(FILETYPE_PEM, server_key_pem))
1984 server_context.use_certificate(
1985 load_certificate(FILETYPE_PEM, server_cert_pem))
1986
1987 # Do a little connection to trigger the logic
1988 server = Connection(server_context, None)
1989 server.set_accept_state()
1990
1991 client = Connection(client_context, None)
1992 client.set_connect_state()
1993
1994 # Do the dance.
1995 interact_in_memory(server, client)
1996
1997 assert refusal_args == [(server, [b'http/1.1', b'spdy/2'])]
1998
1999 assert client.get_alpn_proto_negotiated() == b''
2000
2001 def test_alpn_select_cb_returns_invalid_value(self):
2002 """
2003 If the ALPN selection callback returns anything other than
2004 a bytestring or ``NO_OVERLAPPING_PROTOCOLS``, a
2005 :py:exc:`TypeError` is raised.
2006 """
2007 invalid_cb_args = []
2008
2009 def invalid_cb(conn, options):
2010 invalid_cb_args.append((conn, options))
2011 return u"can't return unicode"
2012
2013 client_context = Context(SSLv23_METHOD)
2014 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
2015
2016 server_context = Context(SSLv23_METHOD)
2017 server_context.set_alpn_select_callback(invalid_cb)
2018
2019 # Necessary to actually accept the connection
2020 server_context.use_privatekey(
2021 load_privatekey(FILETYPE_PEM, server_key_pem))
2022 server_context.use_certificate(
2023 load_certificate(FILETYPE_PEM, server_cert_pem))
2024
2025 # Do a little connection to trigger the logic
2026 server = Connection(server_context, None)
2027 server.set_accept_state()
2028
2029 client = Connection(client_context, None)
2030 client.set_connect_state()
2031
2032 # Do the dance.
2033 with pytest.raises(TypeError):
2034 interact_in_memory(server, client)
2035
2036 assert invalid_cb_args == [(server, [b'http/1.1', b'spdy/2'])]
2037
2038 assert client.get_alpn_proto_negotiated() == b''
2039
Cory Benfielde46fa842015-04-13 16:50:49 -04002040 def test_alpn_no_server(self):
2041 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04002042 When clients and servers cannot agree on what protocol to use next
2043 because the server doesn't offer ALPN, no protocol is negotiated.
Cory Benfielde46fa842015-04-13 16:50:49 -04002044 """
2045 client_context = Context(TLSv1_METHOD)
2046 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfielde3d57152015-04-11 17:57:35 -04002047
Cory Benfielde46fa842015-04-13 16:50:49 -04002048 server_context = Context(TLSv1_METHOD)
Cory Benfielde3d57152015-04-11 17:57:35 -04002049
Cory Benfielde46fa842015-04-13 16:50:49 -04002050 # Necessary to actually accept the connection
2051 server_context.use_privatekey(
2052 load_privatekey(FILETYPE_PEM, server_key_pem))
2053 server_context.use_certificate(
2054 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfielde3d57152015-04-11 17:57:35 -04002055
Cory Benfielde46fa842015-04-13 16:50:49 -04002056 # Do a little connection to trigger the logic
2057 server = Connection(server_context, None)
2058 server.set_accept_state()
Cory Benfielde3d57152015-04-11 17:57:35 -04002059
Cory Benfielde46fa842015-04-13 16:50:49 -04002060 client = Connection(client_context, None)
2061 client.set_connect_state()
Cory Benfielde3d57152015-04-11 17:57:35 -04002062
Cory Benfielde46fa842015-04-13 16:50:49 -04002063 # Do the dance.
Alex Chanec1e32d2016-11-10 14:11:45 +00002064 interact_in_memory(server, client)
Cory Benfielde3d57152015-04-11 17:57:35 -04002065
Alex Chanec1e32d2016-11-10 14:11:45 +00002066 assert client.get_alpn_proto_negotiated() == b''
Cory Benfielde3d57152015-04-11 17:57:35 -04002067
Cory Benfielde46fa842015-04-13 16:50:49 -04002068 def test_alpn_callback_exception(self):
2069 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04002070 We can handle exceptions in the ALPN select callback.
Cory Benfielde46fa842015-04-13 16:50:49 -04002071 """
2072 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002073
Cory Benfielde46fa842015-04-13 16:50:49 -04002074 def select(conn, options):
2075 select_args.append((conn, options))
Cory Benfieldef401452015-04-13 18:17:36 -04002076 raise TypeError()
Cory Benfieldf1177e72015-04-12 09:11:49 -04002077
Cory Benfielde46fa842015-04-13 16:50:49 -04002078 client_context = Context(TLSv1_METHOD)
2079 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfieldf1177e72015-04-12 09:11:49 -04002080
Cory Benfielde46fa842015-04-13 16:50:49 -04002081 server_context = Context(TLSv1_METHOD)
2082 server_context.set_alpn_select_callback(select)
Cory Benfieldf1177e72015-04-12 09:11:49 -04002083
Cory Benfielde46fa842015-04-13 16:50:49 -04002084 # Necessary to actually accept the connection
2085 server_context.use_privatekey(
2086 load_privatekey(FILETYPE_PEM, server_key_pem))
2087 server_context.use_certificate(
2088 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfieldf1177e72015-04-12 09:11:49 -04002089
Cory Benfielde46fa842015-04-13 16:50:49 -04002090 # Do a little connection to trigger the logic
2091 server = Connection(server_context, None)
2092 server.set_accept_state()
Cory Benfieldf1177e72015-04-12 09:11:49 -04002093
Cory Benfielde46fa842015-04-13 16:50:49 -04002094 client = Connection(client_context, None)
2095 client.set_connect_state()
Cory Benfieldf1177e72015-04-12 09:11:49 -04002096
Alex Chanec1e32d2016-11-10 14:11:45 +00002097 with pytest.raises(TypeError):
2098 interact_in_memory(server, client)
2099 assert select_args == [(server, [b'http/1.1', b'spdy/2'])]
Cory Benfieldf1177e72015-04-12 09:11:49 -04002100
Cory Benfield0f7b04c2015-04-13 17:51:12 -04002101 else:
2102 # No ALPN.
2103 def test_alpn_not_implemented(self):
Cory Benfieldef401452015-04-13 18:17:36 -04002104 """
2105 If ALPN is not in OpenSSL, we should raise NotImplementedError.
2106 """
Cory Benfield0f7b04c2015-04-13 17:51:12 -04002107 # Test the context methods first.
2108 context = Context(TLSv1_METHOD)
Alex Chanec1e32d2016-11-10 14:11:45 +00002109 with pytest.raises(NotImplementedError):
2110 context.set_alpn_protos(None)
2111 with pytest.raises(NotImplementedError):
2112 context.set_alpn_select_callback(None)
Cory Benfield0f7b04c2015-04-13 17:51:12 -04002113
2114 # Now test a connection.
2115 conn = Connection(context)
Alex Chanec1e32d2016-11-10 14:11:45 +00002116 with pytest.raises(NotImplementedError):
2117 conn.set_alpn_protos(None)
Cory Benfield0f7b04c2015-04-13 17:51:12 -04002118
Cory Benfieldf1177e72015-04-12 09:11:49 -04002119
Alex Chanec1e32d2016-11-10 14:11:45 +00002120class TestSession(object):
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05002121 """
2122 Unit tests for :py:obj:`OpenSSL.SSL.Session`.
2123 """
2124 def test_construction(self):
2125 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002126 :py:class:`Session` can be constructed with no arguments, creating
2127 a new instance of that type.
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05002128 """
2129 new_session = Session()
Alex Chanec1e32d2016-11-10 14:11:45 +00002130 assert isinstance(new_session, Session)
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05002131
2132
Alex Chan1c0cb662017-01-30 07:13:30 +00002133class TestConnection(object):
Rick Deane15b1472009-07-09 15:53:42 -05002134 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002135 Unit tests for `OpenSSL.SSL.Connection`.
Rick Deane15b1472009-07-09 15:53:42 -05002136 """
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04002137 # XXX get_peer_certificate -> None
2138 # XXX sock_shutdown
2139 # XXX master_key -> TypeError
2140 # XXX server_random -> TypeError
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04002141 # XXX connect -> TypeError
2142 # XXX connect_ex -> TypeError
2143 # XXX set_connect_state -> TypeError
2144 # XXX set_accept_state -> TypeError
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04002145 # XXX do_handshake -> TypeError
2146 # XXX bio_read -> TypeError
2147 # XXX recv -> TypeError
2148 # XXX send -> TypeError
2149 # XXX bio_write -> TypeError
2150
Rick Deane15b1472009-07-09 15:53:42 -05002151 def test_type(self):
2152 """
Alex Gaynor01f90a12019-02-07 09:14:48 -05002153 `Connection` can be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -05002154 """
2155 ctx = Context(TLSv1_METHOD)
Alex Chan1c0cb662017-01-30 07:13:30 +00002156 assert is_consistent_type(Connection, 'Connection', ctx, None)
Rick Deane15b1472009-07-09 15:53:42 -05002157
Alex Chanfb078d82017-04-20 11:16:15 +01002158 @pytest.mark.parametrize('bad_context', [object(), 'context', None, 1])
2159 def test_wrong_args(self, bad_context):
2160 """
2161 `Connection.__init__` raises `TypeError` if called with a non-`Context`
2162 instance argument.
2163 """
2164 with pytest.raises(TypeError):
2165 Connection(bad_context)
2166
Daniel Holth079c9632019-11-17 22:45:52 -05002167 @pytest.mark.parametrize('bad_bio', [object(), None, 1, [1, 2, 3]])
2168 def test_bio_write_wrong_args(self, bad_bio):
2169 """
2170 `Connection.bio_write` raises `TypeError` if called with a non-bytes
2171 (or text) argument.
2172 """
2173 context = Context(TLSv1_METHOD)
2174 connection = Connection(context, None)
2175 with pytest.raises(TypeError):
2176 connection.bio_write(bad_bio)
2177
2178 def test_bio_write(self):
2179 """
2180 `Connection.bio_write` does not raise if called with bytes or
2181 bytearray, warns if called with text.
2182 """
2183 context = Context(TLSv1_METHOD)
2184 connection = Connection(context, None)
2185 connection.bio_write(b'xy')
2186 connection.bio_write(bytearray(b'za'))
2187 with pytest.warns(DeprecationWarning):
2188 connection.bio_write(u'deprecated')
2189
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002190 def test_get_context(self):
2191 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002192 `Connection.get_context` returns the `Context` instance used to
2193 construct the `Connection` instance.
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002194 """
2195 context = Context(TLSv1_METHOD)
2196 connection = Connection(context, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002197 assert connection.get_context() is context
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002198
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002199 def test_set_context_wrong_args(self):
2200 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002201 `Connection.set_context` raises `TypeError` if called with a
Alex Chanfb078d82017-04-20 11:16:15 +01002202 non-`Context` instance argument.
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002203 """
2204 ctx = Context(TLSv1_METHOD)
2205 connection = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002206 with pytest.raises(TypeError):
2207 connection.set_context(object())
2208 with pytest.raises(TypeError):
2209 connection.set_context("hello")
2210 with pytest.raises(TypeError):
2211 connection.set_context(1)
2212 assert ctx is connection.get_context()
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002213
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002214 def test_set_context(self):
2215 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002216 `Connection.set_context` specifies a new `Context` instance to be
2217 used for the connection.
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002218 """
2219 original = Context(SSLv23_METHOD)
2220 replacement = Context(TLSv1_METHOD)
2221 connection = Connection(original, None)
2222 connection.set_context(replacement)
Alex Chan1c0cb662017-01-30 07:13:30 +00002223 assert replacement is connection.get_context()
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002224 # Lose our references to the contexts, just in case the Connection
2225 # isn't properly managing its own contributions to their reference
2226 # counts.
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002227 del original, replacement
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002228 collect()
2229
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002230 def test_set_tlsext_host_name_wrong_args(self):
2231 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002232 If `Connection.set_tlsext_host_name` is called with a non-byte string
2233 argument or a byte string with an embedded NUL, `TypeError` is raised.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002234 """
2235 conn = Connection(Context(TLSv1_METHOD), None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002236 with pytest.raises(TypeError):
2237 conn.set_tlsext_host_name(object())
2238 with pytest.raises(TypeError):
2239 conn.set_tlsext_host_name(b"with\0null")
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002240
Hugo van Kemenade60827f82019-08-30 00:39:35 +03002241 if not PY2:
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002242 # On Python 3.x, don't accidentally implicitly convert from text.
Alex Chan1c0cb662017-01-30 07:13:30 +00002243 with pytest.raises(TypeError):
2244 conn.set_tlsext_host_name(b"example.com".decode("ascii"))
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04002245
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002246 def test_pending(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002247 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002248 `Connection.pending` returns the number of bytes available for
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002249 immediate read.
2250 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002251 connection = Connection(Context(TLSv1_METHOD), None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002252 assert connection.pending() == 0
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002253
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002254 def test_peek(self):
2255 """
Hynek Schlawack3bcf3152017-02-18 08:25:34 +01002256 `Connection.recv` peeks into the connection if `socket.MSG_PEEK` is
2257 passed.
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002258 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002259 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002260 server.send(b'xy')
Alex Chan1c0cb662017-01-30 07:13:30 +00002261 assert client.recv(2, MSG_PEEK) == b'xy'
2262 assert client.recv(2, MSG_PEEK) == b'xy'
2263 assert client.recv(2) == b'xy'
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002264
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002265 def test_connect_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002266 """
Hynek Schlawack3bcf3152017-02-18 08:25:34 +01002267 `Connection.connect` raises `TypeError` if called with a non-address
2268 argument.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002269 """
David Benjamin1fbe0642019-04-15 17:05:13 -05002270 connection = Connection(Context(TLSv1_METHOD), socket_any_family())
Alex Chan1c0cb662017-01-30 07:13:30 +00002271 with pytest.raises(TypeError):
2272 connection.connect(None)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002273
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002274 def test_connect_refused(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002275 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002276 `Connection.connect` raises `socket.error` if the underlying socket
2277 connect method raises it.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002278 """
David Benjamin1fbe0642019-04-15 17:05:13 -05002279 client = socket_any_family()
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002280 context = Context(TLSv1_METHOD)
2281 clientSSL = Connection(context, client)
Alex Gaynor122717b2015-09-05 14:14:18 -04002282 # pytest.raises here doesn't work because of a bug in py.test on Python
2283 # 2.6: https://github.com/pytest-dev/pytest/issues/988
Alex Gaynore69c2782015-09-05 14:07:48 -04002284 try:
David Benjamin1fbe0642019-04-15 17:05:13 -05002285 clientSSL.connect((loopback_address(client), 1))
Alex Gaynore69c2782015-09-05 14:07:48 -04002286 except error as e:
Alex Gaynor20a4c082015-09-05 14:24:15 -04002287 exc = e
2288 assert exc.args[0] == ECONNREFUSED
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002289
2290 def test_connect(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002291 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002292 `Connection.connect` establishes a connection to the specified address.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002293 """
David Benjamin1fbe0642019-04-15 17:05:13 -05002294 port = socket_any_family()
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002295 port.bind(('', 0))
2296 port.listen(3)
2297
David Benjamin1fbe0642019-04-15 17:05:13 -05002298 clientSSL = Connection(Context(TLSv1_METHOD), socket(port.family))
2299 clientSSL.connect((loopback_address(port), port.getsockname()[1]))
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002300 # XXX An assertion? Or something?
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002301
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002302 @pytest.mark.skipif(
2303 platform == "darwin",
2304 reason="connect_ex sometimes causes a kernel panic on OS X 10.6.4"
2305 )
2306 def test_connect_ex(self):
2307 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002308 If there is a connection error, `Connection.connect_ex` returns the
2309 errno instead of raising an exception.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002310 """
David Benjamin1fbe0642019-04-15 17:05:13 -05002311 port = socket_any_family()
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002312 port.bind(('', 0))
2313 port.listen(3)
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002314
David Benjamin1fbe0642019-04-15 17:05:13 -05002315 clientSSL = Connection(Context(TLSv1_METHOD), socket(port.family))
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002316 clientSSL.setblocking(False)
2317 result = clientSSL.connect_ex(port.getsockname())
2318 expected = (EINPROGRESS, EWOULDBLOCK)
Alex Chan1c0cb662017-01-30 07:13:30 +00002319 assert result in expected
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002320
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002321 def test_accept(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002322 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002323 `Connection.accept` accepts a pending connection attempt and returns a
2324 tuple of a new `Connection` (the accepted client) and the address the
2325 connection originated from.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002326 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002327 ctx = Context(TLSv1_METHOD)
2328 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2329 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
David Benjamin1fbe0642019-04-15 17:05:13 -05002330 port = socket_any_family()
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002331 portSSL = Connection(ctx, port)
2332 portSSL.bind(('', 0))
2333 portSSL.listen(3)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002334
David Benjamin1fbe0642019-04-15 17:05:13 -05002335 clientSSL = Connection(Context(TLSv1_METHOD), socket(port.family))
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002336
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002337 # Calling portSSL.getsockname() here to get the server IP address
2338 # sounds great, but frequently fails on Windows.
David Benjamin1fbe0642019-04-15 17:05:13 -05002339 clientSSL.connect((loopback_address(port), portSSL.getsockname()[1]))
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002340
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002341 serverSSL, address = portSSL.accept()
2342
Alex Chan1c0cb662017-01-30 07:13:30 +00002343 assert isinstance(serverSSL, Connection)
2344 assert serverSSL.get_context() is ctx
2345 assert address == clientSSL.getsockname()
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002346
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002347 def test_shutdown_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002348 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002349 `Connection.set_shutdown` raises `TypeError` if called with arguments
2350 other than integers.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002351 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002352 connection = Connection(Context(TLSv1_METHOD), None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002353 with pytest.raises(TypeError):
2354 connection.set_shutdown(None)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002355
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002356 def test_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002357 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002358 `Connection.shutdown` performs an SSL-level connection shutdown.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002359 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002360 server, client = loopback()
2361 assert not server.shutdown()
2362 assert server.get_shutdown() == SENT_SHUTDOWN
2363 with pytest.raises(ZeroReturnError):
2364 client.recv(1024)
2365 assert client.get_shutdown() == RECEIVED_SHUTDOWN
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04002366 client.shutdown()
Alex Chan1c0cb662017-01-30 07:13:30 +00002367 assert client.get_shutdown() == (SENT_SHUTDOWN | RECEIVED_SHUTDOWN)
2368 with pytest.raises(ZeroReturnError):
2369 server.recv(1024)
2370 assert server.get_shutdown() == (SENT_SHUTDOWN | RECEIVED_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002371
Paul Aurichc85e0862015-01-08 08:34:33 -08002372 def test_shutdown_closed(self):
2373 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002374 If the underlying socket is closed, `Connection.shutdown` propagates
2375 the write error from the low level write call.
Paul Aurichc85e0862015-01-08 08:34:33 -08002376 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002377 server, client = loopback()
Paul Aurichc85e0862015-01-08 08:34:33 -08002378 server.sock_shutdown(2)
Alex Chan1c0cb662017-01-30 07:13:30 +00002379 with pytest.raises(SysCallError) as exc:
2380 server.shutdown()
Alex Chanfb078d82017-04-20 11:16:15 +01002381 if platform == "win32":
2382 assert exc.value.args[0] == ESHUTDOWN
2383 else:
2384 assert exc.value.args[0] == EPIPE
Paul Aurichc85e0862015-01-08 08:34:33 -08002385
Glyph89389472015-04-14 17:29:26 -04002386 def test_shutdown_truncated(self):
Glyph6064ec32015-04-14 16:38:22 -04002387 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002388 If the underlying connection is truncated, `Connection.shutdown`
2389 raises an `Error`.
Glyph6064ec32015-04-14 16:38:22 -04002390 """
Glyph89389472015-04-14 17:29:26 -04002391 server_ctx = Context(TLSv1_METHOD)
2392 client_ctx = Context(TLSv1_METHOD)
2393 server_ctx.use_privatekey(
2394 load_privatekey(FILETYPE_PEM, server_key_pem))
2395 server_ctx.use_certificate(
2396 load_certificate(FILETYPE_PEM, server_cert_pem))
2397 server = Connection(server_ctx, None)
2398 client = Connection(client_ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002399 handshake_in_memory(client, server)
2400 assert not server.shutdown()
2401 with pytest.raises(WantReadError):
2402 server.shutdown()
Glyph89389472015-04-14 17:29:26 -04002403 server.bio_shutdown()
Alex Chan1c0cb662017-01-30 07:13:30 +00002404 with pytest.raises(Error):
2405 server.shutdown()
Glyph6064ec32015-04-14 16:38:22 -04002406
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002407 def test_set_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002408 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002409 `Connection.set_shutdown` sets the state of the SSL connection
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002410 shutdown process.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002411 """
David Benjamin1fbe0642019-04-15 17:05:13 -05002412 connection = Connection(Context(TLSv1_METHOD), socket_any_family())
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002413 connection.set_shutdown(RECEIVED_SHUTDOWN)
Alex Chan1c0cb662017-01-30 07:13:30 +00002414 assert connection.get_shutdown() == RECEIVED_SHUTDOWN
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002415
kjavaf248592015-09-07 12:14:01 +01002416 def test_state_string(self):
2417 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002418 `Connection.state_string` verbosely describes the current state of
2419 the `Connection`.
kjavaf248592015-09-07 12:14:01 +01002420 """
Hynek Schlawackb0274ce2015-10-16 19:56:26 +02002421 server, client = socket_pair()
Alex Chan1c0cb662017-01-30 07:13:30 +00002422 server = loopback_server_factory(server)
2423 client = loopback_client_factory(client)
kjavaf248592015-09-07 12:14:01 +01002424
Alex Gaynor5af32d02016-09-24 01:52:21 -04002425 assert server.get_state_string() in [
2426 b"before/accept initialization", b"before SSL initialization"
2427 ]
2428 assert client.get_state_string() in [
2429 b"before/connect initialization", b"before SSL initialization"
2430 ]
kjavaf248592015-09-07 12:14:01 +01002431
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002432 def test_app_data(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002433 """
2434 Any object can be set as app data by passing it to
Alex Chan1c0cb662017-01-30 07:13:30 +00002435 `Connection.set_app_data` and later retrieved with
2436 `Connection.get_app_data`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002437 """
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002438 conn = Connection(Context(TLSv1_METHOD), None)
Todd Chapman4f73e4f2015-08-27 11:26:43 -04002439 assert None is conn.get_app_data()
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002440 app_data = object()
2441 conn.set_app_data(app_data)
Todd Chapman4f73e4f2015-08-27 11:26:43 -04002442 assert conn.get_app_data() is app_data
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002443
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002444 def test_makefile(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002445 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002446 `Connection.makefile` is not implemented and calling that
2447 method raises `NotImplementedError`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002448 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002449 conn = Connection(Context(TLSv1_METHOD), None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002450 with pytest.raises(NotImplementedError):
2451 conn.makefile()
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002452
Jeremy Lainé460a19d2018-05-16 19:44:19 +02002453 def test_get_certificate(self):
2454 """
2455 `Connection.get_certificate` returns the local certificate.
2456 """
2457 chain = _create_certificate_chain()
2458 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
2459
2460 context = Context(TLSv1_METHOD)
2461 context.use_certificate(scert)
2462 client = Connection(context, None)
2463 cert = client.get_certificate()
2464 assert cert is not None
2465 assert "Server Certificate" == cert.get_subject().CN
2466
2467 def test_get_certificate_none(self):
2468 """
2469 `Connection.get_certificate` returns the local certificate.
2470
2471 If there is no certificate, it returns None.
2472 """
2473 context = Context(TLSv1_METHOD)
2474 client = Connection(context, None)
2475 cert = client.get_certificate()
2476 assert cert is None
2477
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002478 def test_get_peer_cert_chain(self):
2479 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002480 `Connection.get_peer_cert_chain` returns a list of certificates
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002481 which the connected server returned for the certification verification.
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002482 """
2483 chain = _create_certificate_chain()
2484 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
2485
2486 serverContext = Context(TLSv1_METHOD)
2487 serverContext.use_privatekey(skey)
2488 serverContext.use_certificate(scert)
2489 serverContext.add_extra_chain_cert(icert)
2490 serverContext.add_extra_chain_cert(cacert)
2491 server = Connection(serverContext, None)
2492 server.set_accept_state()
2493
2494 # Create the client
2495 clientContext = Context(TLSv1_METHOD)
2496 clientContext.set_verify(VERIFY_NONE, verify_cb)
2497 client = Connection(clientContext, None)
2498 client.set_connect_state()
2499
Alex Chan1c0cb662017-01-30 07:13:30 +00002500 interact_in_memory(client, server)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002501
2502 chain = client.get_peer_cert_chain()
Alex Chan1c0cb662017-01-30 07:13:30 +00002503 assert len(chain) == 3
2504 assert "Server Certificate" == chain[0].get_subject().CN
2505 assert "Intermediate Certificate" == chain[1].get_subject().CN
2506 assert "Authority Certificate" == chain[2].get_subject().CN
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002507
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002508 def test_get_peer_cert_chain_none(self):
2509 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002510 `Connection.get_peer_cert_chain` returns `None` if the peer sends
2511 no certificate chain.
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002512 """
2513 ctx = Context(TLSv1_METHOD)
2514 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2515 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
2516 server = Connection(ctx, None)
2517 server.set_accept_state()
2518 client = Connection(Context(TLSv1_METHOD), None)
2519 client.set_connect_state()
Alex Chan1c0cb662017-01-30 07:13:30 +00002520 interact_in_memory(client, server)
2521 assert None is server.get_peer_cert_chain()
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002522
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002523 def test_get_session_unconnected(self):
2524 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002525 `Connection.get_session` returns `None` when used with an object
2526 which has not been connected.
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002527 """
2528 ctx = Context(TLSv1_METHOD)
2529 server = Connection(ctx, None)
2530 session = server.get_session()
Alex Chan1c0cb662017-01-30 07:13:30 +00002531 assert None is session
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002532
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002533 def test_server_get_session(self):
2534 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002535 On the server side of a connection, `Connection.get_session` returns a
2536 `Session` instance representing the SSL session for that connection.
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002537 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002538 server, client = loopback()
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002539 session = server.get_session()
Alex Chan1c0cb662017-01-30 07:13:30 +00002540 assert isinstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002541
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002542 def test_client_get_session(self):
2543 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002544 On the client side of a connection, `Connection.get_session`
2545 returns a `Session` instance representing the SSL session for
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002546 that connection.
2547 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002548 server, client = loopback()
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002549 session = client.get_session()
Alex Chan1c0cb662017-01-30 07:13:30 +00002550 assert isinstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002551
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002552 def test_set_session_wrong_args(self):
2553 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002554 `Connection.set_session` raises `TypeError` if called with an object
2555 that is not an instance of `Session`.
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002556 """
2557 ctx = Context(TLSv1_METHOD)
2558 connection = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002559 with pytest.raises(TypeError):
2560 connection.set_session(123)
2561 with pytest.raises(TypeError):
2562 connection.set_session("hello")
2563 with pytest.raises(TypeError):
2564 connection.set_session(object())
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002565
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002566 def test_client_set_session(self):
2567 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002568 `Connection.set_session`, when used prior to a connection being
2569 established, accepts a `Session` instance and causes an attempt to
2570 re-use the session it represents when the SSL handshake is performed.
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002571 """
2572 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2573 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
Paul Kehrer7d5a3bf2019-01-21 12:24:02 -06002574 ctx = Context(TLSv1_2_METHOD)
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002575 ctx.use_privatekey(key)
2576 ctx.use_certificate(cert)
2577 ctx.set_session_id("unity-test")
2578
2579 def makeServer(socket):
2580 server = Connection(ctx, socket)
2581 server.set_accept_state()
2582 return server
2583
Alex Chan1c0cb662017-01-30 07:13:30 +00002584 originalServer, originalClient = loopback(
2585 server_factory=makeServer)
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002586 originalSession = originalClient.get_session()
2587
2588 def makeClient(socket):
Alex Chan1c0cb662017-01-30 07:13:30 +00002589 client = loopback_client_factory(socket)
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002590 client.set_session(originalSession)
2591 return client
Alex Chan1c0cb662017-01-30 07:13:30 +00002592 resumedServer, resumedClient = loopback(
2593 server_factory=makeServer,
2594 client_factory=makeClient)
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002595
2596 # This is a proxy: in general, we have no access to any unique
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002597 # identifier for the session (new enough versions of OpenSSL expose
2598 # a hash which could be usable, but "new enough" is very, very new).
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002599 # Instead, exploit the fact that the master key is re-used if the
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002600 # session is re-used. As long as the master key for the two
2601 # connections is the same, the session was re-used!
Alex Chan1c0cb662017-01-30 07:13:30 +00002602 assert originalServer.master_key() == resumedServer.master_key()
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002603
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002604 def test_set_session_wrong_method(self):
2605 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002606 If `Connection.set_session` is passed a `Session` instance associated
2607 with a context using a different SSL method than the `Connection`
2608 is using, a `OpenSSL.SSL.Error` is raised.
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002609 """
Alex Gaynor5af32d02016-09-24 01:52:21 -04002610 # Make this work on both OpenSSL 1.0.0, which doesn't support TLSv1.2
2611 # and also on OpenSSL 1.1.0 which doesn't support SSLv3. (SSL_ST_INIT
2612 # is a way to check for 1.1.0)
Alex Gaynoraa32e712017-06-29 20:56:12 -07002613 if SSL_ST_INIT is None:
2614 v1 = TLSv1_2_METHOD
2615 v2 = TLSv1_METHOD
2616 elif hasattr(_lib, "SSLv3_method"):
Alex Gaynor5af32d02016-09-24 01:52:21 -04002617 v1 = TLSv1_METHOD
2618 v2 = SSLv3_METHOD
2619 else:
Alex Gaynoraa32e712017-06-29 20:56:12 -07002620 pytest.skip("Test requires either OpenSSL 1.1.0 or SSLv3")
Alex Gaynor5af32d02016-09-24 01:52:21 -04002621
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002622 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2623 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
Alex Gaynor5af32d02016-09-24 01:52:21 -04002624 ctx = Context(v1)
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002625 ctx.use_privatekey(key)
2626 ctx.use_certificate(cert)
2627 ctx.set_session_id("unity-test")
2628
2629 def makeServer(socket):
2630 server = Connection(ctx, socket)
2631 server.set_accept_state()
2632 return server
2633
Alex Gaynor5af32d02016-09-24 01:52:21 -04002634 def makeOriginalClient(socket):
2635 client = Connection(Context(v1), socket)
2636 client.set_connect_state()
2637 return client
2638
Alex Chan1c0cb662017-01-30 07:13:30 +00002639 originalServer, originalClient = loopback(
2640 server_factory=makeServer, client_factory=makeOriginalClient)
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002641 originalSession = originalClient.get_session()
2642
2643 def makeClient(socket):
2644 # Intentionally use a different, incompatible method here.
Alex Gaynor5af32d02016-09-24 01:52:21 -04002645 client = Connection(Context(v2), socket)
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002646 client.set_connect_state()
2647 client.set_session(originalSession)
2648 return client
2649
Alex Chan1c0cb662017-01-30 07:13:30 +00002650 with pytest.raises(Error):
2651 loopback(client_factory=makeClient, server_factory=makeServer)
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002652
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002653 def test_wantWriteError(self):
2654 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002655 `Connection` methods which generate output raise
2656 `OpenSSL.SSL.WantWriteError` if writing to the connection's BIO
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002657 fail indicating a should-write state.
2658 """
2659 client_socket, server_socket = socket_pair()
2660 # Fill up the client's send buffer so Connection won't be able to write
Jean-Paul Calderonebbff8b92014-03-22 14:20:30 -04002661 # anything. Only write a single byte at a time so we can be sure we
2662 # completely fill the buffer. Even though the socket API is allowed to
2663 # signal a short write via its return value it seems this doesn't
2664 # always happen on all platforms (FreeBSD and OS X particular) for the
2665 # very last bit of available buffer space.
2666 msg = b"x"
caternb2777a42018-08-09 15:38:13 -04002667 for i in range(1024 * 1024 * 64):
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002668 try:
2669 client_socket.send(msg)
2670 except error as e:
2671 if e.errno == EWOULDBLOCK:
2672 break
2673 raise
2674 else:
Alex Chan1c0cb662017-01-30 07:13:30 +00002675 pytest.fail(
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002676 "Failed to fill socket buffer, cannot test BIO want write")
2677
2678 ctx = Context(TLSv1_METHOD)
2679 conn = Connection(ctx, client_socket)
2680 # Client's speak first, so make it an SSL client
2681 conn.set_connect_state()
Alex Chan1c0cb662017-01-30 07:13:30 +00002682 with pytest.raises(WantWriteError):
2683 conn.do_handshake()
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002684
2685 # XXX want_read
2686
Fedor Brunner416f4a12014-03-28 13:18:38 +01002687 def test_get_finished_before_connect(self):
Fedor Brunner5747b932014-03-05 14:22:34 +01002688 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002689 `Connection.get_finished` returns `None` before TLS handshake
2690 is completed.
Fedor Brunner5747b932014-03-05 14:22:34 +01002691 """
Fedor Brunner5747b932014-03-05 14:22:34 +01002692 ctx = Context(TLSv1_METHOD)
2693 connection = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002694 assert connection.get_finished() is None
Fedor Brunner416f4a12014-03-28 13:18:38 +01002695
2696 def test_get_peer_finished_before_connect(self):
2697 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002698 `Connection.get_peer_finished` returns `None` before TLS handshake
2699 is completed.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002700 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002701 ctx = Context(TLSv1_METHOD)
2702 connection = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002703 assert connection.get_peer_finished() is None
Fedor Brunner5747b932014-03-05 14:22:34 +01002704
Fedor Brunner416f4a12014-03-28 13:18:38 +01002705 def test_get_finished(self):
2706 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002707 `Connection.get_finished` method returns the TLS Finished message send
2708 from client, or server. Finished messages are send during
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002709 TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002710 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002711 server, client = loopback()
Fedor Brunner416f4a12014-03-28 13:18:38 +01002712
Alex Chan1c0cb662017-01-30 07:13:30 +00002713 assert server.get_finished() is not None
2714 assert len(server.get_finished()) > 0
Fedor Brunner416f4a12014-03-28 13:18:38 +01002715
2716 def test_get_peer_finished(self):
2717 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002718 `Connection.get_peer_finished` method returns the TLS Finished
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002719 message received from client, or server. Finished messages are send
2720 during TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002721 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002722 server, client = loopback()
Fedor Brunner416f4a12014-03-28 13:18:38 +01002723
Alex Chan1c0cb662017-01-30 07:13:30 +00002724 assert server.get_peer_finished() is not None
2725 assert len(server.get_peer_finished()) > 0
Fedor Brunner5747b932014-03-05 14:22:34 +01002726
Fedor Brunner416f4a12014-03-28 13:18:38 +01002727 def test_tls_finished_message_symmetry(self):
2728 """
Hynek Schlawackdddd1112015-09-05 21:12:30 +02002729 The TLS Finished message send by server must be the TLS Finished
2730 message received by client.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002731
Hynek Schlawackdddd1112015-09-05 21:12:30 +02002732 The TLS Finished message send by client must be the TLS Finished
2733 message received by server.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002734 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002735 server, client = loopback()
Fedor Brunner416f4a12014-03-28 13:18:38 +01002736
Alex Chan1c0cb662017-01-30 07:13:30 +00002737 assert server.get_finished() == client.get_peer_finished()
2738 assert client.get_finished() == server.get_peer_finished()
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002739
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002740 def test_get_cipher_name_before_connect(self):
2741 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002742 `Connection.get_cipher_name` returns `None` if no connection
2743 has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002744 """
2745 ctx = Context(TLSv1_METHOD)
2746 conn = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002747 assert conn.get_cipher_name() is None
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002748
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002749 def test_get_cipher_name(self):
2750 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002751 `Connection.get_cipher_name` returns a `unicode` string giving the
2752 name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002753 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002754 server, client = loopback()
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002755 server_cipher_name, client_cipher_name = \
2756 server.get_cipher_name(), client.get_cipher_name()
2757
Alex Chan1c0cb662017-01-30 07:13:30 +00002758 assert isinstance(server_cipher_name, text_type)
2759 assert isinstance(client_cipher_name, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002760
Alex Chan1c0cb662017-01-30 07:13:30 +00002761 assert server_cipher_name == client_cipher_name
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002762
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002763 def test_get_cipher_version_before_connect(self):
2764 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002765 `Connection.get_cipher_version` returns `None` if no connection
2766 has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002767 """
2768 ctx = Context(TLSv1_METHOD)
2769 conn = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002770 assert conn.get_cipher_version() is None
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002771
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002772 def test_get_cipher_version(self):
2773 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002774 `Connection.get_cipher_version` returns a `unicode` string giving
2775 the protocol name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002776 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002777 server, client = loopback()
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002778 server_cipher_version, client_cipher_version = \
2779 server.get_cipher_version(), client.get_cipher_version()
2780
Alex Chan1c0cb662017-01-30 07:13:30 +00002781 assert isinstance(server_cipher_version, text_type)
2782 assert isinstance(client_cipher_version, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002783
Alex Chan1c0cb662017-01-30 07:13:30 +00002784 assert server_cipher_version == client_cipher_version
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002785
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002786 def test_get_cipher_bits_before_connect(self):
2787 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002788 `Connection.get_cipher_bits` returns `None` if no connection has
2789 been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002790 """
2791 ctx = Context(TLSv1_METHOD)
2792 conn = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002793 assert conn.get_cipher_bits() is None
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002794
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002795 def test_get_cipher_bits(self):
2796 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002797 `Connection.get_cipher_bits` returns the number of secret bits
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002798 of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002799 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002800 server, client = loopback()
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002801 server_cipher_bits, client_cipher_bits = \
2802 server.get_cipher_bits(), client.get_cipher_bits()
2803
Alex Chan1c0cb662017-01-30 07:13:30 +00002804 assert isinstance(server_cipher_bits, int)
2805 assert isinstance(client_cipher_bits, int)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002806
Alex Chan1c0cb662017-01-30 07:13:30 +00002807 assert server_cipher_bits == client_cipher_bits
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002808
Jim Shaverabff1882015-05-27 09:15:55 -04002809 def test_get_protocol_version_name(self):
2810 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002811 `Connection.get_protocol_version_name()` returns a string giving the
2812 protocol version of the current connection.
Jim Shaverabff1882015-05-27 09:15:55 -04002813 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002814 server, client = loopback()
Jim Shaverabff1882015-05-27 09:15:55 -04002815 client_protocol_version_name = client.get_protocol_version_name()
2816 server_protocol_version_name = server.get_protocol_version_name()
2817
Alex Chan1c0cb662017-01-30 07:13:30 +00002818 assert isinstance(server_protocol_version_name, text_type)
2819 assert isinstance(client_protocol_version_name, text_type)
Jim Shaverabff1882015-05-27 09:15:55 -04002820
Alex Chan1c0cb662017-01-30 07:13:30 +00002821 assert server_protocol_version_name == client_protocol_version_name
Jim Shaverabff1882015-05-27 09:15:55 -04002822
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002823 def test_get_protocol_version(self):
2824 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002825 `Connection.get_protocol_version()` returns an integer
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002826 giving the protocol version of the current connection.
2827 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002828 server, client = loopback()
Jim Shaver85a4dff2015-04-27 17:42:46 -04002829 client_protocol_version = client.get_protocol_version()
2830 server_protocol_version = server.get_protocol_version()
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002831
Alex Chan1c0cb662017-01-30 07:13:30 +00002832 assert isinstance(server_protocol_version, int)
2833 assert isinstance(client_protocol_version, int)
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002834
Alex Chan1c0cb662017-01-30 07:13:30 +00002835 assert server_protocol_version == client_protocol_version
2836
2837 def test_wantReadError(self):
2838 """
2839 `Connection.bio_read` raises `OpenSSL.SSL.WantReadError` if there are
2840 no bytes available to be read from the BIO.
2841 """
2842 ctx = Context(TLSv1_METHOD)
2843 conn = Connection(ctx, None)
2844 with pytest.raises(WantReadError):
2845 conn.bio_read(1024)
2846
Alex Chanfb078d82017-04-20 11:16:15 +01002847 @pytest.mark.parametrize('bufsize', [1.0, None, object(), 'bufsize'])
2848 def test_bio_read_wrong_args(self, bufsize):
2849 """
2850 `Connection.bio_read` raises `TypeError` if passed a non-integer
2851 argument.
2852 """
2853 ctx = Context(TLSv1_METHOD)
2854 conn = Connection(ctx, None)
2855 with pytest.raises(TypeError):
2856 conn.bio_read(bufsize)
2857
Alex Chan1c0cb662017-01-30 07:13:30 +00002858 def test_buffer_size(self):
2859 """
2860 `Connection.bio_read` accepts an integer giving the maximum number
2861 of bytes to read and return.
2862 """
2863 ctx = Context(TLSv1_METHOD)
2864 conn = Connection(ctx, None)
2865 conn.set_connect_state()
2866 try:
2867 conn.do_handshake()
2868 except WantReadError:
2869 pass
2870 data = conn.bio_read(2)
2871 assert 2 == len(data)
2872
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002873
Alex Chanb7480992017-01-30 14:04:47 +00002874class TestConnectionGetCipherList(object):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002875 """
Alex Chanb7480992017-01-30 14:04:47 +00002876 Tests for `Connection.get_cipher_list`.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002877 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002878 def test_result(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002879 """
Alex Chanb7480992017-01-30 14:04:47 +00002880 `Connection.get_cipher_list` returns a list of `bytes` giving the
2881 names of the ciphers which might be used.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002882 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002883 connection = Connection(Context(TLSv1_METHOD), None)
2884 ciphers = connection.get_cipher_list()
Alex Chanb7480992017-01-30 14:04:47 +00002885 assert isinstance(ciphers, list)
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002886 for cipher in ciphers:
Alex Chanb7480992017-01-30 14:04:47 +00002887 assert isinstance(cipher, str)
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002888
2889
Maximilian Hils868dc3c2017-02-10 14:56:55 +01002890class VeryLarge(bytes):
2891 """
2892 Mock object so that we don't have to allocate 2**31 bytes
2893 """
2894 def __len__(self):
2895 return 2**31
2896
2897
Alex Chanb7480992017-01-30 14:04:47 +00002898class TestConnectionSend(object):
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002899 """
Alex Chanb7480992017-01-30 14:04:47 +00002900 Tests for `Connection.send`.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002901 """
2902 def test_wrong_args(self):
2903 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002904 When called with arguments other than string argument for its first
Alex Chanb7480992017-01-30 14:04:47 +00002905 parameter, `Connection.send` raises `TypeError`.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002906 """
2907 connection = Connection(Context(TLSv1_METHOD), None)
Alex Chanb7480992017-01-30 14:04:47 +00002908 with pytest.raises(TypeError):
2909 connection.send(object())
Daniel Holth079c9632019-11-17 22:45:52 -05002910 with pytest.raises(TypeError):
2911 connection.send([1, 2, 3])
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002912
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002913 def test_short_bytes(self):
2914 """
Alex Chanb7480992017-01-30 14:04:47 +00002915 When passed a short byte string, `Connection.send` transmits all of it
2916 and returns the number of bytes sent.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002917 """
Alex Chanb7480992017-01-30 14:04:47 +00002918 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002919 count = server.send(b'xy')
Alex Chanb7480992017-01-30 14:04:47 +00002920 assert count == 2
2921 assert client.recv(2) == b'xy'
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002922
Abraham Martinef063482015-03-25 14:06:24 +00002923 def test_text(self):
2924 """
Alex Chanb7480992017-01-30 14:04:47 +00002925 When passed a text, `Connection.send` transmits all of it and
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002926 returns the number of bytes sent. It also raises a DeprecationWarning.
Abraham Martinef063482015-03-25 14:06:24 +00002927 """
Alex Chanb7480992017-01-30 14:04:47 +00002928 server, client = loopback()
2929 with pytest.warns(DeprecationWarning) as w:
Abraham Martinef063482015-03-25 14:06:24 +00002930 simplefilter("always")
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002931 count = server.send(b"xy".decode("ascii"))
Alex Chanb7480992017-01-30 14:04:47 +00002932 assert (
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002933 "{0} for buf is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002934 WARNING_TYPE_EXPECTED
Alex Chanb7480992017-01-30 14:04:47 +00002935 ) == str(w[-1].message))
2936 assert count == 2
2937 assert client.recv(2) == b'xy'
Abraham Martinef063482015-03-25 14:06:24 +00002938
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002939 def test_short_memoryview(self):
2940 """
2941 When passed a memoryview onto a small number of bytes,
Alex Chanb7480992017-01-30 14:04:47 +00002942 `Connection.send` transmits all of them and returns the number
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002943 of bytes sent.
2944 """
Alex Chanb7480992017-01-30 14:04:47 +00002945 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002946 count = server.send(memoryview(b'xy'))
Alex Chanb7480992017-01-30 14:04:47 +00002947 assert count == 2
2948 assert client.recv(2) == b'xy'
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002949
Daniel Holth079c9632019-11-17 22:45:52 -05002950 def test_short_bytearray(self):
2951 """
2952 When passed a short bytearray, `Connection.send` transmits all of
2953 it and returns the number of bytes sent.
2954 """
2955 server, client = loopback()
2956 count = server.send(bytearray(b'xy'))
2957 assert count == 2
2958 assert client.recv(2) == b'xy'
2959
Hynek Schlawack8e94f1b2015-09-05 21:31:00 +02002960 @skip_if_py3
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002961 def test_short_buffer(self):
2962 """
2963 When passed a buffer containing a small number of bytes,
Alex Chanb7480992017-01-30 14:04:47 +00002964 `Connection.send` transmits all of them and returns the number
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002965 of bytes sent.
2966 """
Alex Chanb7480992017-01-30 14:04:47 +00002967 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002968 count = server.send(buffer(b'xy'))
Alex Chanb7480992017-01-30 14:04:47 +00002969 assert count == 2
2970 assert client.recv(2) == b'xy'
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02002971
Maximilian Hils868dc3c2017-02-10 14:56:55 +01002972 @pytest.mark.skipif(
2973 sys.maxsize < 2**31,
2974 reason="sys.maxsize < 2**31 - test requires 64 bit"
2975 )
2976 def test_buf_too_large(self):
2977 """
2978 When passed a buffer containing >= 2**31 bytes,
2979 `Connection.send` bails out as SSL_write only
2980 accepts an int for the buffer length.
2981 """
2982 connection = Connection(Context(TLSv1_METHOD), None)
2983 with pytest.raises(ValueError) as exc_info:
2984 connection.send(VeryLarge())
2985 exc_info.match(r"Cannot send more than .+ bytes at once")
2986
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05002987
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002988def _make_memoryview(size):
2989 """
2990 Create a new ``memoryview`` wrapped around a ``bytearray`` of the given
2991 size.
2992 """
2993 return memoryview(bytearray(size))
2994
2995
Alex Chanb7480992017-01-30 14:04:47 +00002996class TestConnectionRecvInto(object):
Cory Benfield62d10332014-06-15 10:03:41 +01002997 """
Alex Chanb7480992017-01-30 14:04:47 +00002998 Tests for `Connection.recv_into`.
Cory Benfield62d10332014-06-15 10:03:41 +01002999 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003000 def _no_length_test(self, factory):
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04003001 """
Alex Chanb7480992017-01-30 14:04:47 +00003002 Assert that when the given buffer is passed to `Connection.recv_into`,
3003 whatever bytes are available to be received that fit into that buffer
3004 are written into that buffer.
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04003005 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003006 output_buffer = factory(5)
3007
Alex Chanb7480992017-01-30 14:04:47 +00003008 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04003009 server.send(b'xy')
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04003010
Alex Chanb7480992017-01-30 14:04:47 +00003011 assert client.recv_into(output_buffer) == 2
3012 assert output_buffer == bytearray(b'xy\x00\x00\x00')
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04003013
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04003014 def test_bytearray_no_length(self):
Cory Benfield62d10332014-06-15 10:03:41 +01003015 """
Alex Chanb7480992017-01-30 14:04:47 +00003016 `Connection.recv_into` can be passed a `bytearray` instance and data
3017 in the receive buffer is written to it.
Cory Benfield62d10332014-06-15 10:03:41 +01003018 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003019 self._no_length_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01003020
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003021 def _respects_length_test(self, factory):
Cory Benfield62d10332014-06-15 10:03:41 +01003022 """
Alex Chanb7480992017-01-30 14:04:47 +00003023 Assert that when the given buffer is passed to `Connection.recv_into`
3024 along with a value for `nbytes` that is less than the size of that
3025 buffer, only `nbytes` bytes are written into the buffer.
Cory Benfield62d10332014-06-15 10:03:41 +01003026 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003027 output_buffer = factory(10)
3028
Alex Chanb7480992017-01-30 14:04:47 +00003029 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04003030 server.send(b'abcdefghij')
Cory Benfield62d10332014-06-15 10:03:41 +01003031
Alex Chanb7480992017-01-30 14:04:47 +00003032 assert client.recv_into(output_buffer, 5) == 5
3033 assert output_buffer == bytearray(b'abcde\x00\x00\x00\x00\x00')
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04003034
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04003035 def test_bytearray_respects_length(self):
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04003036 """
Alex Chanb7480992017-01-30 14:04:47 +00003037 When called with a `bytearray` instance, `Connection.recv_into`
3038 respects the `nbytes` parameter and doesn't copy in more than that
3039 number of bytes.
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04003040 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003041 self._respects_length_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01003042
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003043 def _doesnt_overfill_test(self, factory):
Cory Benfield62d10332014-06-15 10:03:41 +01003044 """
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04003045 Assert that if there are more bytes available to be read from the
3046 receive buffer than would fit into the buffer passed to
Alex Chanb7480992017-01-30 14:04:47 +00003047 `Connection.recv_into`, only as many as fit are written into it.
Cory Benfield62d10332014-06-15 10:03:41 +01003048 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003049 output_buffer = factory(5)
3050
Alex Chanb7480992017-01-30 14:04:47 +00003051 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04003052 server.send(b'abcdefghij')
Cory Benfield62d10332014-06-15 10:03:41 +01003053
Alex Chanb7480992017-01-30 14:04:47 +00003054 assert client.recv_into(output_buffer) == 5
3055 assert output_buffer == bytearray(b'abcde')
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04003056 rest = client.recv(5)
Alex Chanb7480992017-01-30 14:04:47 +00003057 assert b'fghij' == rest
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04003058
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04003059 def test_bytearray_doesnt_overfill(self):
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04003060 """
Alex Chanb7480992017-01-30 14:04:47 +00003061 When called with a `bytearray` instance, `Connection.recv_into`
3062 respects the size of the array and doesn't write more bytes into it
3063 than will fit.
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04003064 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003065 self._doesnt_overfill_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01003066
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04003067 def test_bytearray_really_doesnt_overfill(self):
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003068 """
Alex Chanb7480992017-01-30 14:04:47 +00003069 When called with a `bytearray` instance and an `nbytes` value that is
3070 too large, `Connection.recv_into` respects the size of the array and
3071 not the `nbytes` value and doesn't write more bytes into the buffer
3072 than will fit.
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003073 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003074 self._doesnt_overfill_test(bytearray)
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003075
Maximilian Hils1d95dea2015-08-17 19:27:20 +02003076 def test_peek(self):
Alex Chanb7480992017-01-30 14:04:47 +00003077 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04003078 server.send(b'xy')
Maximilian Hils1d95dea2015-08-17 19:27:20 +02003079
3080 for _ in range(2):
3081 output_buffer = bytearray(5)
Alex Chanb7480992017-01-30 14:04:47 +00003082 assert client.recv_into(output_buffer, flags=MSG_PEEK) == 2
3083 assert output_buffer == bytearray(b'xy\x00\x00\x00')
Maximilian Hils1d95dea2015-08-17 19:27:20 +02003084
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003085 def test_memoryview_no_length(self):
3086 """
Alex Chanb7480992017-01-30 14:04:47 +00003087 `Connection.recv_into` can be passed a `memoryview` instance and data
3088 in the receive buffer is written to it.
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003089 """
3090 self._no_length_test(_make_memoryview)
Maximilian Hils1d95dea2015-08-17 19:27:20 +02003091
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003092 def test_memoryview_respects_length(self):
3093 """
Alex Chanb7480992017-01-30 14:04:47 +00003094 When called with a `memoryview` instance, `Connection.recv_into`
3095 respects the ``nbytes`` parameter and doesn't copy more than that
3096 number of bytes in.
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003097 """
3098 self._respects_length_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01003099
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003100 def test_memoryview_doesnt_overfill(self):
3101 """
Alex Chanb7480992017-01-30 14:04:47 +00003102 When called with a `memoryview` instance, `Connection.recv_into`
3103 respects the size of the array and doesn't write more bytes into it
3104 than will fit.
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003105 """
3106 self._doesnt_overfill_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01003107
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003108 def test_memoryview_really_doesnt_overfill(self):
3109 """
Alex Chanb7480992017-01-30 14:04:47 +00003110 When called with a `memoryview` instance and an `nbytes` value that is
3111 too large, `Connection.recv_into` respects the size of the array and
3112 not the `nbytes` value and doesn't write more bytes into the buffer
3113 than will fit.
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003114 """
3115 self._doesnt_overfill_test(_make_memoryview)
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003116
Cory Benfield62d10332014-06-15 10:03:41 +01003117
Alex Chanb7480992017-01-30 14:04:47 +00003118class TestConnectionSendall(object):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003119 """
Alex Chanb7480992017-01-30 14:04:47 +00003120 Tests for `Connection.sendall`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003121 """
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003122 def test_wrong_args(self):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003123 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003124 When called with arguments other than a string argument for its first
Alex Chanb7480992017-01-30 14:04:47 +00003125 parameter, `Connection.sendall` raises `TypeError`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003126 """
3127 connection = Connection(Context(TLSv1_METHOD), None)
Alex Chanb7480992017-01-30 14:04:47 +00003128 with pytest.raises(TypeError):
3129 connection.sendall(object())
Daniel Holth079c9632019-11-17 22:45:52 -05003130 with pytest.raises(TypeError):
3131 connection.sendall([1, 2, 3])
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003132
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003133 def test_short(self):
3134 """
Alex Chanb7480992017-01-30 14:04:47 +00003135 `Connection.sendall` transmits all of the bytes in the string
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003136 passed to it.
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003137 """
Alex Chanb7480992017-01-30 14:04:47 +00003138 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04003139 server.sendall(b'x')
Alex Chanb7480992017-01-30 14:04:47 +00003140 assert client.recv(1) == b'x'
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003141
Abraham Martinef063482015-03-25 14:06:24 +00003142 def test_text(self):
3143 """
Alex Chanb7480992017-01-30 14:04:47 +00003144 `Connection.sendall` transmits all the content in the string passed
3145 to it, raising a DeprecationWarning in case of this being a text.
Abraham Martinef063482015-03-25 14:06:24 +00003146 """
Alex Chanb7480992017-01-30 14:04:47 +00003147 server, client = loopback()
3148 with pytest.warns(DeprecationWarning) as w:
Abraham Martinef063482015-03-25 14:06:24 +00003149 simplefilter("always")
Jean-Paul Calderone8dc37a12015-03-29 08:16:52 -04003150 server.sendall(b"x".decode("ascii"))
Alex Chanb7480992017-01-30 14:04:47 +00003151 assert (
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04003152 "{0} for buf is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04003153 WARNING_TYPE_EXPECTED
Alex Chanb7480992017-01-30 14:04:47 +00003154 ) == str(w[-1].message))
3155 assert client.recv(1) == b"x"
Abraham Martinef063482015-03-25 14:06:24 +00003156
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003157 def test_short_memoryview(self):
3158 """
3159 When passed a memoryview onto a small number of bytes,
Alex Chanb7480992017-01-30 14:04:47 +00003160 `Connection.sendall` transmits all of them.
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003161 """
Alex Chanb7480992017-01-30 14:04:47 +00003162 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04003163 server.sendall(memoryview(b'x'))
Alex Chanb7480992017-01-30 14:04:47 +00003164 assert client.recv(1) == b'x'
Abraham Martinef063482015-03-25 14:06:24 +00003165
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003166 @skip_if_py3
3167 def test_short_buffers(self):
3168 """
3169 When passed a buffer containing a small number of bytes,
Alex Chanb7480992017-01-30 14:04:47 +00003170 `Connection.sendall` transmits all of them.
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003171 """
Alex Chanb7480992017-01-30 14:04:47 +00003172 server, client = loopback()
Daniel Holth079c9632019-11-17 22:45:52 -05003173 count = server.sendall(buffer(b'xy'))
3174 assert count == 2
3175 assert client.recv(2) == b'xy'
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02003176
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003177 def test_long(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003178 """
Alex Chanb7480992017-01-30 14:04:47 +00003179 `Connection.sendall` transmits all the bytes in the string passed to it
3180 even if this requires multiple calls of an underlying write function.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003181 """
Alex Chanb7480992017-01-30 14:04:47 +00003182 server, client = loopback()
Jean-Paul Calderone6241c702010-09-16 19:59:24 -04003183 # Should be enough, underlying SSL_write should only do 16k at a time.
Hynek Schlawack35618382015-09-05 21:54:25 +02003184 # On Windows, after 32k of bytes the write will block (forever
3185 # - because no one is yet reading).
Alex Gaynore7f51982016-09-11 11:48:14 -04003186 message = b'x' * (1024 * 32 - 1) + b'y'
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003187 server.sendall(message)
3188 accum = []
3189 received = 0
3190 while received < len(message):
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04003191 data = client.recv(1024)
3192 accum.append(data)
3193 received += len(data)
Alex Chanb7480992017-01-30 14:04:47 +00003194 assert message == b''.join(accum)
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003195
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003196 def test_closed(self):
3197 """
Alex Chanb7480992017-01-30 14:04:47 +00003198 If the underlying socket is closed, `Connection.sendall` propagates the
3199 write error from the low level write call.
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003200 """
Alex Chanb7480992017-01-30 14:04:47 +00003201 server, client = loopback()
Jean-Paul Calderone05d43e82010-09-24 18:01:36 -04003202 server.sock_shutdown(2)
Alex Chanb7480992017-01-30 14:04:47 +00003203 with pytest.raises(SysCallError) as err:
3204 server.sendall(b"hello, world")
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +02003205 if platform == "win32":
Alex Chanb7480992017-01-30 14:04:47 +00003206 assert err.value.args[0] == ESHUTDOWN
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +02003207 else:
Alex Chanb7480992017-01-30 14:04:47 +00003208 assert err.value.args[0] == EPIPE
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003209
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003210
Alex Chanb7480992017-01-30 14:04:47 +00003211class TestConnectionRenegotiate(object):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003212 """
3213 Tests for SSL renegotiation APIs.
3214 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003215 def test_total_renegotiations(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003216 """
Alex Chanb7480992017-01-30 14:04:47 +00003217 `Connection.total_renegotiations` returns `0` before any renegotiations
3218 have happened.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003219 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003220 connection = Connection(Context(TLSv1_METHOD), None)
Alex Chanb7480992017-01-30 14:04:47 +00003221 assert connection.total_renegotiations() == 0
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003222
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003223 def test_renegotiate(self):
3224 """
3225 Go through a complete renegotiation cycle.
3226 """
Paul Kehrer7d5a3bf2019-01-21 12:24:02 -06003227 server, client = loopback(
3228 lambda s: loopback_server_factory(s, TLSv1_2_METHOD),
3229 lambda s: loopback_client_factory(s, TLSv1_2_METHOD),
3230 )
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003231
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003232 server.send(b"hello world")
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003233
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003234 assert b"hello world" == client.recv(len(b"hello world"))
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003235
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003236 assert 0 == server.total_renegotiations()
3237 assert False is server.renegotiate_pending()
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003238
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003239 assert True is server.renegotiate()
3240
3241 assert True is server.renegotiate_pending()
3242
3243 server.setblocking(False)
3244 client.setblocking(False)
3245
3246 client.do_handshake()
3247 server.do_handshake()
3248
3249 assert 1 == server.total_renegotiations()
3250 while False is server.renegotiate_pending():
3251 pass
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003252
3253
Alex Chanb7480992017-01-30 14:04:47 +00003254class TestError(object):
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003255 """
Alex Chanb7480992017-01-30 14:04:47 +00003256 Unit tests for `OpenSSL.SSL.Error`.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003257 """
3258 def test_type(self):
3259 """
Alex Chanb7480992017-01-30 14:04:47 +00003260 `Error` is an exception type.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003261 """
Alex Chanb7480992017-01-30 14:04:47 +00003262 assert issubclass(Error, Exception)
3263 assert Error.__name__ == 'Error'
Rick Deane15b1472009-07-09 15:53:42 -05003264
3265
Alex Chanb7480992017-01-30 14:04:47 +00003266class TestConstants(object):
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003267 """
Alex Chanb7480992017-01-30 14:04:47 +00003268 Tests for the values of constants exposed in `OpenSSL.SSL`.
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003269
3270 These are values defined by OpenSSL intended only to be used as flags to
3271 OpenSSL APIs. The only assertions it seems can be made about them is
3272 their values.
3273 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003274 @pytest.mark.skipif(
3275 OP_NO_QUERY_MTU is None,
3276 reason="OP_NO_QUERY_MTU unavailable - OpenSSL version may be too old"
3277 )
3278 def test_op_no_query_mtu(self):
3279 """
Alex Chanb7480992017-01-30 14:04:47 +00003280 The value of `OpenSSL.SSL.OP_NO_QUERY_MTU` is 0x1000, the value
3281 of `SSL_OP_NO_QUERY_MTU` defined by `openssl/ssl.h`.
Hynek Schlawack35618382015-09-05 21:54:25 +02003282 """
Alex Chanb7480992017-01-30 14:04:47 +00003283 assert OP_NO_QUERY_MTU == 0x1000
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003284
Hynek Schlawack35618382015-09-05 21:54:25 +02003285 @pytest.mark.skipif(
3286 OP_COOKIE_EXCHANGE is None,
3287 reason="OP_COOKIE_EXCHANGE unavailable - "
3288 "OpenSSL version may be too old"
3289 )
3290 def test_op_cookie_exchange(self):
3291 """
Alex Chanb7480992017-01-30 14:04:47 +00003292 The value of `OpenSSL.SSL.OP_COOKIE_EXCHANGE` is 0x2000, the
3293 value of `SSL_OP_COOKIE_EXCHANGE` defined by `openssl/ssl.h`.
Hynek Schlawack35618382015-09-05 21:54:25 +02003294 """
Alex Chanb7480992017-01-30 14:04:47 +00003295 assert OP_COOKIE_EXCHANGE == 0x2000
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003296
Hynek Schlawack35618382015-09-05 21:54:25 +02003297 @pytest.mark.skipif(
3298 OP_NO_TICKET is None,
3299 reason="OP_NO_TICKET unavailable - OpenSSL version may be too old"
3300 )
3301 def test_op_no_ticket(self):
3302 """
Alex Chanb7480992017-01-30 14:04:47 +00003303 The value of `OpenSSL.SSL.OP_NO_TICKET` is 0x4000, the value of
3304 `SSL_OP_NO_TICKET` defined by `openssl/ssl.h`.
Hynek Schlawack35618382015-09-05 21:54:25 +02003305 """
Alex Chanb7480992017-01-30 14:04:47 +00003306 assert OP_NO_TICKET == 0x4000
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003307
Hynek Schlawack35618382015-09-05 21:54:25 +02003308 @pytest.mark.skipif(
3309 OP_NO_COMPRESSION is None,
3310 reason="OP_NO_COMPRESSION unavailable - OpenSSL version may be too old"
3311 )
3312 def test_op_no_compression(self):
3313 """
Alex Chanb7480992017-01-30 14:04:47 +00003314 The value of `OpenSSL.SSL.OP_NO_COMPRESSION` is 0x20000, the
3315 value of `SSL_OP_NO_COMPRESSION` defined by `openssl/ssl.h`.
Hynek Schlawack35618382015-09-05 21:54:25 +02003316 """
Alex Chanb7480992017-01-30 14:04:47 +00003317 assert OP_NO_COMPRESSION == 0x20000
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04003318
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003319 def test_sess_cache_off(self):
3320 """
Alex Chanb7480992017-01-30 14:04:47 +00003321 The value of `OpenSSL.SSL.SESS_CACHE_OFF` 0x0, the value of
3322 `SSL_SESS_CACHE_OFF` defined by `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003323 """
Alex Chanb7480992017-01-30 14:04:47 +00003324 assert 0x0 == SESS_CACHE_OFF
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003325
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003326 def test_sess_cache_client(self):
3327 """
Alex Chanb7480992017-01-30 14:04:47 +00003328 The value of `OpenSSL.SSL.SESS_CACHE_CLIENT` 0x1, the value of
3329 `SSL_SESS_CACHE_CLIENT` defined by `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003330 """
Alex Chanb7480992017-01-30 14:04:47 +00003331 assert 0x1 == SESS_CACHE_CLIENT
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003332
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003333 def test_sess_cache_server(self):
3334 """
Alex Chanb7480992017-01-30 14:04:47 +00003335 The value of `OpenSSL.SSL.SESS_CACHE_SERVER` 0x2, the value of
3336 `SSL_SESS_CACHE_SERVER` defined by `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003337 """
Alex Chanb7480992017-01-30 14:04:47 +00003338 assert 0x2 == SESS_CACHE_SERVER
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003339
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003340 def test_sess_cache_both(self):
3341 """
Alex Chanb7480992017-01-30 14:04:47 +00003342 The value of `OpenSSL.SSL.SESS_CACHE_BOTH` 0x3, the value of
3343 `SSL_SESS_CACHE_BOTH` defined by `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003344 """
Alex Chanb7480992017-01-30 14:04:47 +00003345 assert 0x3 == SESS_CACHE_BOTH
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003346
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003347 def test_sess_cache_no_auto_clear(self):
3348 """
Alex Chanb7480992017-01-30 14:04:47 +00003349 The value of `OpenSSL.SSL.SESS_CACHE_NO_AUTO_CLEAR` 0x80, the
3350 value of `SSL_SESS_CACHE_NO_AUTO_CLEAR` defined by
3351 `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003352 """
Alex Chanb7480992017-01-30 14:04:47 +00003353 assert 0x80 == SESS_CACHE_NO_AUTO_CLEAR
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003354
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003355 def test_sess_cache_no_internal_lookup(self):
3356 """
Alex Chanb7480992017-01-30 14:04:47 +00003357 The value of `OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_LOOKUP` 0x100,
3358 the value of `SSL_SESS_CACHE_NO_INTERNAL_LOOKUP` defined by
3359 `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003360 """
Alex Chanb7480992017-01-30 14:04:47 +00003361 assert 0x100 == SESS_CACHE_NO_INTERNAL_LOOKUP
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003362
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003363 def test_sess_cache_no_internal_store(self):
3364 """
Alex Chanb7480992017-01-30 14:04:47 +00003365 The value of `OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_STORE` 0x200,
3366 the value of `SSL_SESS_CACHE_NO_INTERNAL_STORE` defined by
3367 `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003368 """
Alex Chanb7480992017-01-30 14:04:47 +00003369 assert 0x200 == SESS_CACHE_NO_INTERNAL_STORE
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003370
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003371 def test_sess_cache_no_internal(self):
3372 """
Alex Chanb7480992017-01-30 14:04:47 +00003373 The value of `OpenSSL.SSL.SESS_CACHE_NO_INTERNAL` 0x300, the
3374 value of `SSL_SESS_CACHE_NO_INTERNAL` defined by
3375 `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003376 """
Alex Chanb7480992017-01-30 14:04:47 +00003377 assert 0x300 == SESS_CACHE_NO_INTERNAL
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003378
3379
Alex Chanb7480992017-01-30 14:04:47 +00003380class TestMemoryBIO(object):
Rick Deanb71c0d22009-04-01 14:09:23 -05003381 """
Alex Chanb7480992017-01-30 14:04:47 +00003382 Tests for `OpenSSL.SSL.Connection` using a memory BIO.
Rick Deanb71c0d22009-04-01 14:09:23 -05003383 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003384 def _server(self, sock):
3385 """
Alex Chanb7480992017-01-30 14:04:47 +00003386 Create a new server-side SSL `Connection` object wrapped around `sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003387 """
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003388 # Create the server side Connection. This is mostly setup boilerplate
3389 # - use TLSv1, use a particular certificate, etc.
3390 server_ctx = Context(TLSv1_METHOD)
Alex Gaynor43307782015-09-04 09:05:45 -04003391 server_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE)
Hynek Schlawack35618382015-09-05 21:54:25 +02003392 server_ctx.set_verify(
3393 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT | VERIFY_CLIENT_ONCE,
3394 verify_cb
3395 )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003396 server_store = server_ctx.get_cert_store()
Hynek Schlawack35618382015-09-05 21:54:25 +02003397 server_ctx.use_privatekey(
3398 load_privatekey(FILETYPE_PEM, server_key_pem))
3399 server_ctx.use_certificate(
3400 load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003401 server_ctx.check_privatekey()
3402 server_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Hynek Schlawack35618382015-09-05 21:54:25 +02003403 # Here the Connection is actually created. If None is passed as the
3404 # 2nd parameter, it indicates a memory BIO should be created.
Rick Deanb1ccd562009-07-09 23:52:39 -05003405 server_conn = Connection(server_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003406 server_conn.set_accept_state()
3407 return server_conn
3408
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003409 def _client(self, sock):
3410 """
Alex Chanb7480992017-01-30 14:04:47 +00003411 Create a new client-side SSL `Connection` object wrapped around `sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003412 """
3413 # Now create the client side Connection. Similar boilerplate to the
3414 # above.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003415 client_ctx = Context(TLSv1_METHOD)
Alex Gaynor43307782015-09-04 09:05:45 -04003416 client_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE)
Hynek Schlawack35618382015-09-05 21:54:25 +02003417 client_ctx.set_verify(
3418 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT | VERIFY_CLIENT_ONCE,
3419 verify_cb
3420 )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003421 client_store = client_ctx.get_cert_store()
Hynek Schlawack35618382015-09-05 21:54:25 +02003422 client_ctx.use_privatekey(
3423 load_privatekey(FILETYPE_PEM, client_key_pem))
3424 client_ctx.use_certificate(
3425 load_certificate(FILETYPE_PEM, client_cert_pem))
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003426 client_ctx.check_privatekey()
3427 client_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05003428 client_conn = Connection(client_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003429 client_conn.set_connect_state()
3430 return client_conn
3431
Alex Chanb7480992017-01-30 14:04:47 +00003432 def test_memory_connect(self):
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003433 """
Alex Chanb7480992017-01-30 14:04:47 +00003434 Two `Connection`s which use memory BIOs can be manually connected by
3435 reading from the output of each and writing those bytes to the input of
3436 the other and in this way establish a connection and exchange
3437 application-level bytes with each other.
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003438 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003439 server_conn = self._server(None)
3440 client_conn = self._client(None)
Rick Deanb71c0d22009-04-01 14:09:23 -05003441
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003442 # There should be no key or nonces yet.
Alex Chanb7480992017-01-30 14:04:47 +00003443 assert server_conn.master_key() is None
3444 assert server_conn.client_random() is None
3445 assert server_conn.server_random() is None
Rick Deanb71c0d22009-04-01 14:09:23 -05003446
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003447 # First, the handshake needs to happen. We'll deliver bytes back and
3448 # forth between the client and server until neither of them feels like
3449 # speaking any more.
Alex Chanb7480992017-01-30 14:04:47 +00003450 assert interact_in_memory(client_conn, server_conn) is None
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003451
3452 # Now that the handshake is done, there should be a key and nonces.
Alex Chanb7480992017-01-30 14:04:47 +00003453 assert server_conn.master_key() is not None
3454 assert server_conn.client_random() is not None
3455 assert server_conn.server_random() is not None
3456 assert server_conn.client_random() == client_conn.client_random()
3457 assert server_conn.server_random() == client_conn.server_random()
3458 assert server_conn.client_random() != server_conn.server_random()
3459 assert client_conn.client_random() != client_conn.server_random()
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003460
Paul Kehrerbdb76392017-12-01 04:54:32 +08003461 # Export key material for other uses.
3462 cekm = client_conn.export_keying_material(b'LABEL', 32)
3463 sekm = server_conn.export_keying_material(b'LABEL', 32)
3464 assert cekm is not None
3465 assert sekm is not None
3466 assert cekm == sekm
3467 assert len(sekm) == 32
3468
3469 # Export key material for other uses with additional context.
3470 cekmc = client_conn.export_keying_material(b'LABEL', 32, b'CONTEXT')
3471 sekmc = server_conn.export_keying_material(b'LABEL', 32, b'CONTEXT')
3472 assert cekmc is not None
3473 assert sekmc is not None
3474 assert cekmc == sekmc
3475 assert cekmc != cekm
3476 assert sekmc != sekm
3477 # Export with alternate label
3478 cekmt = client_conn.export_keying_material(b'test', 32, b'CONTEXT')
3479 sekmt = server_conn.export_keying_material(b'test', 32, b'CONTEXT')
3480 assert cekmc != cekmt
3481 assert sekmc != sekmt
3482
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003483 # Here are the bytes we'll try to send.
Alex Gaynore7f51982016-09-11 11:48:14 -04003484 important_message = b'One if by land, two if by sea.'
Rick Deanb71c0d22009-04-01 14:09:23 -05003485
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003486 server_conn.write(important_message)
Alex Chanb7480992017-01-30 14:04:47 +00003487 assert (
3488 interact_in_memory(client_conn, server_conn) ==
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003489 (client_conn, important_message))
3490
3491 client_conn.write(important_message[::-1])
Alex Chanb7480992017-01-30 14:04:47 +00003492 assert (
3493 interact_in_memory(client_conn, server_conn) ==
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003494 (server_conn, important_message[::-1]))
Rick Deanb71c0d22009-04-01 14:09:23 -05003495
Alex Chanb7480992017-01-30 14:04:47 +00003496 def test_socket_connect(self):
Rick Deanb1ccd562009-07-09 23:52:39 -05003497 """
Alex Chanb7480992017-01-30 14:04:47 +00003498 Just like `test_memory_connect` but with an actual socket.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003499
Hynek Schlawack35618382015-09-05 21:54:25 +02003500 This is primarily to rule out the memory BIO code as the source of any
Alex Chanb7480992017-01-30 14:04:47 +00003501 problems encountered while passing data over a `Connection` (if
Hynek Schlawack35618382015-09-05 21:54:25 +02003502 this test fails, there must be a problem outside the memory BIO code,
3503 as no memory BIO is involved here). Even though this isn't a memory
3504 BIO test, it's convenient to have it here.
Rick Deanb1ccd562009-07-09 23:52:39 -05003505 """
Alex Chanb7480992017-01-30 14:04:47 +00003506 server_conn, client_conn = loopback()
Rick Deanb1ccd562009-07-09 23:52:39 -05003507
Alex Gaynore7f51982016-09-11 11:48:14 -04003508 important_message = b"Help me Obi Wan Kenobi, you're my only hope."
Rick Deanb1ccd562009-07-09 23:52:39 -05003509 client_conn.send(important_message)
3510 msg = server_conn.recv(1024)
Alex Chanb7480992017-01-30 14:04:47 +00003511 assert msg == important_message
Rick Deanb1ccd562009-07-09 23:52:39 -05003512
3513 # Again in the other direction, just for fun.
3514 important_message = important_message[::-1]
3515 server_conn.send(important_message)
3516 msg = client_conn.recv(1024)
Alex Chanb7480992017-01-30 14:04:47 +00003517 assert msg == important_message
Rick Deanb1ccd562009-07-09 23:52:39 -05003518
Alex Chanb7480992017-01-30 14:04:47 +00003519 def test_socket_overrides_memory(self):
Rick Deanb71c0d22009-04-01 14:09:23 -05003520 """
Alex Chanb7480992017-01-30 14:04:47 +00003521 Test that `OpenSSL.SSL.bio_read` and `OpenSSL.SSL.bio_write` don't
3522 work on `OpenSSL.SSL.Connection`() that use sockets.
Rick Deanb71c0d22009-04-01 14:09:23 -05003523 """
Alex Gaynor51d424c2016-09-10 14:50:11 -04003524 context = Context(TLSv1_METHOD)
David Benjamin1fbe0642019-04-15 17:05:13 -05003525 client = socket_any_family()
Rick Deanb71c0d22009-04-01 14:09:23 -05003526 clientSSL = Connection(context, client)
Alex Chanb7480992017-01-30 14:04:47 +00003527 with pytest.raises(TypeError):
3528 clientSSL.bio_read(100)
3529 with pytest.raises(TypeError):
3530 clientSSL.bio_write("foo")
3531 with pytest.raises(TypeError):
3532 clientSSL.bio_shutdown()
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003533
Alex Chanb7480992017-01-30 14:04:47 +00003534 def test_outgoing_overflow(self):
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003535 """
3536 If more bytes than can be written to the memory BIO are passed to
Alex Chanb7480992017-01-30 14:04:47 +00003537 `Connection.send` at once, the number of bytes which were written is
3538 returned and that many bytes from the beginning of the input can be
3539 read from the other end of the connection.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003540 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003541 server = self._server(None)
3542 client = self._client(None)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003543
Alex Chanb7480992017-01-30 14:04:47 +00003544 interact_in_memory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003545
3546 size = 2 ** 15
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003547 sent = client.send(b"x" * size)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003548 # Sanity check. We're trying to test what happens when the entire
3549 # input can't be sent. If the entire input was sent, this test is
3550 # meaningless.
Alex Chanb7480992017-01-30 14:04:47 +00003551 assert sent < size
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003552
Alex Chanb7480992017-01-30 14:04:47 +00003553 receiver, received = interact_in_memory(client, server)
3554 assert receiver is server
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003555
3556 # We can rely on all of these bytes being received at once because
Alex Chanb7480992017-01-30 14:04:47 +00003557 # loopback passes 2 ** 16 to recv - more than 2 ** 15.
3558 assert len(received) == sent
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003559
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003560 def test_shutdown(self):
3561 """
Alex Chanb7480992017-01-30 14:04:47 +00003562 `Connection.bio_shutdown` signals the end of the data stream
3563 from which the `Connection` reads.
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003564 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003565 server = self._server(None)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003566 server.bio_shutdown()
Alex Chanb7480992017-01-30 14:04:47 +00003567 with pytest.raises(Error) as err:
3568 server.recv(1024)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003569 # We don't want WantReadError or ZeroReturnError or anything - it's a
3570 # handshake failure.
Alex Chanb7480992017-01-30 14:04:47 +00003571 assert type(err.value) in [Error, SysCallError]
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003572
Alex Chanb7480992017-01-30 14:04:47 +00003573 def test_unexpected_EOF(self):
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003574 """
3575 If the connection is lost before an orderly SSL shutdown occurs,
Alex Chanb7480992017-01-30 14:04:47 +00003576 `OpenSSL.SSL.SysCallError` is raised with a message of
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003577 "Unexpected EOF".
3578 """
Alex Chanb7480992017-01-30 14:04:47 +00003579 server_conn, client_conn = loopback()
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003580 client_conn.sock_shutdown(SHUT_RDWR)
Alex Chanb7480992017-01-30 14:04:47 +00003581 with pytest.raises(SysCallError) as err:
3582 server_conn.recv(1024)
3583 assert err.value.args == (-1, "Unexpected EOF")
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003584
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003585 def _check_client_ca_list(self, func):
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003586 """
Alex Chanb7480992017-01-30 14:04:47 +00003587 Verify the return value of the `get_client_ca_list` method for
Hynek Schlawack35618382015-09-05 21:54:25 +02003588 server and client connections.
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003589
Jonathan Ballet78b92a22011-07-16 08:07:26 +09003590 :param func: A function which will be called with the server context
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003591 before the client and server are connected to each other. This
3592 function should specify a list of CAs for the server to send to the
3593 client and return that same list. The list will be used to verify
Alex Chanb7480992017-01-30 14:04:47 +00003594 that `get_client_ca_list` returns the proper value at
Hynek Schlawack35618382015-09-05 21:54:25 +02003595 various times.
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003596 """
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003597 server = self._server(None)
3598 client = self._client(None)
Alex Chanb7480992017-01-30 14:04:47 +00003599 assert client.get_client_ca_list() == []
3600 assert server.get_client_ca_list() == []
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003601 ctx = server.get_context()
3602 expected = func(ctx)
Alex Chanb7480992017-01-30 14:04:47 +00003603 assert client.get_client_ca_list() == []
3604 assert server.get_client_ca_list() == expected
3605 interact_in_memory(client, server)
3606 assert client.get_client_ca_list() == expected
3607 assert server.get_client_ca_list() == expected
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003608
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003609 def test_set_client_ca_list_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003610 """
Alex Chanb7480992017-01-30 14:04:47 +00003611 `Context.set_client_ca_list` raises a `TypeError` if called with a
3612 non-list or a list that contains objects other than X509Names.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003613 """
3614 ctx = Context(TLSv1_METHOD)
Alex Chanb7480992017-01-30 14:04:47 +00003615 with pytest.raises(TypeError):
3616 ctx.set_client_ca_list("spam")
3617 with pytest.raises(TypeError):
3618 ctx.set_client_ca_list(["spam"])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003619
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003620 def test_set_empty_ca_list(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003621 """
Alex Chanb7480992017-01-30 14:04:47 +00003622 If passed an empty list, `Context.set_client_ca_list` configures the
3623 context to send no CA names to the client and, on both the server and
3624 client sides, `Connection.get_client_ca_list` returns an empty list
3625 after the connection is set up.
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003626 """
3627 def no_ca(ctx):
3628 ctx.set_client_ca_list([])
3629 return []
3630 self._check_client_ca_list(no_ca)
3631
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003632 def test_set_one_ca_list(self):
3633 """
3634 If passed a list containing a single X509Name,
Alex Chanb7480992017-01-30 14:04:47 +00003635 `Context.set_client_ca_list` configures the context to send
Hynek Schlawack35618382015-09-05 21:54:25 +02003636 that CA name to the client and, on both the server and client sides,
Alex Chanb7480992017-01-30 14:04:47 +00003637 `Connection.get_client_ca_list` returns a list containing that
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003638 X509Name after the connection is set up.
3639 """
3640 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3641 cadesc = cacert.get_subject()
Hynek Schlawack35618382015-09-05 21:54:25 +02003642
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003643 def single_ca(ctx):
3644 ctx.set_client_ca_list([cadesc])
3645 return [cadesc]
3646 self._check_client_ca_list(single_ca)
3647
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003648 def test_set_multiple_ca_list(self):
3649 """
3650 If passed a list containing multiple X509Name objects,
Alex Chanb7480992017-01-30 14:04:47 +00003651 `Context.set_client_ca_list` configures the context to send
Hynek Schlawack35618382015-09-05 21:54:25 +02003652 those CA names to the client and, on both the server and client sides,
Alex Chanb7480992017-01-30 14:04:47 +00003653 `Connection.get_client_ca_list` returns a list containing those
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003654 X509Names after the connection is set up.
3655 """
3656 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3657 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3658
3659 sedesc = secert.get_subject()
3660 cldesc = clcert.get_subject()
3661
3662 def multiple_ca(ctx):
3663 L = [sedesc, cldesc]
3664 ctx.set_client_ca_list(L)
3665 return L
3666 self._check_client_ca_list(multiple_ca)
3667
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003668 def test_reset_ca_list(self):
3669 """
3670 If called multiple times, only the X509Names passed to the final call
Alex Chanb7480992017-01-30 14:04:47 +00003671 of `Context.set_client_ca_list` are used to configure the CA
Hynek Schlawack35618382015-09-05 21:54:25 +02003672 names sent to the client.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003673 """
3674 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3675 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3676 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3677
3678 cadesc = cacert.get_subject()
3679 sedesc = secert.get_subject()
3680 cldesc = clcert.get_subject()
3681
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003682 def changed_ca(ctx):
3683 ctx.set_client_ca_list([sedesc, cldesc])
3684 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003685 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003686 self._check_client_ca_list(changed_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003687
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003688 def test_mutated_ca_list(self):
3689 """
Alex Chanb7480992017-01-30 14:04:47 +00003690 If the list passed to `Context.set_client_ca_list` is mutated
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003691 afterwards, this does not affect the list of CA names sent to the
3692 client.
3693 """
3694 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3695 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3696
3697 cadesc = cacert.get_subject()
3698 sedesc = secert.get_subject()
3699
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003700 def mutated_ca(ctx):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003701 L = [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003702 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003703 L.append(sedesc)
3704 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003705 self._check_client_ca_list(mutated_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003706
Alex Chanb7480992017-01-30 14:04:47 +00003707 def test_add_client_ca_wrong_args(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003708 """
Alex Chanb7480992017-01-30 14:04:47 +00003709 `Context.add_client_ca` raises `TypeError` if called with
3710 a non-X509 object.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003711 """
3712 ctx = Context(TLSv1_METHOD)
Alex Chanb7480992017-01-30 14:04:47 +00003713 with pytest.raises(TypeError):
3714 ctx.add_client_ca("spam")
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003715
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003716 def test_one_add_client_ca(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003717 """
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003718 A certificate's subject can be added as a CA to be sent to the client
Alex Chanb7480992017-01-30 14:04:47 +00003719 with `Context.add_client_ca`.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003720 """
3721 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3722 cadesc = cacert.get_subject()
Hynek Schlawack35618382015-09-05 21:54:25 +02003723
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003724 def single_ca(ctx):
3725 ctx.add_client_ca(cacert)
3726 return [cadesc]
3727 self._check_client_ca_list(single_ca)
3728
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003729 def test_multiple_add_client_ca(self):
3730 """
3731 Multiple CA names can be sent to the client by calling
Alex Chanb7480992017-01-30 14:04:47 +00003732 `Context.add_client_ca` with multiple X509 objects.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003733 """
3734 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3735 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3736
3737 cadesc = cacert.get_subject()
3738 sedesc = secert.get_subject()
3739
3740 def multiple_ca(ctx):
3741 ctx.add_client_ca(cacert)
3742 ctx.add_client_ca(secert)
3743 return [cadesc, sedesc]
3744 self._check_client_ca_list(multiple_ca)
3745
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003746 def test_set_and_add_client_ca(self):
3747 """
Alex Chanb7480992017-01-30 14:04:47 +00003748 A call to `Context.set_client_ca_list` followed by a call to
3749 `Context.add_client_ca` results in using the CA names from the
Hynek Schlawack35618382015-09-05 21:54:25 +02003750 first call and the CA name from the second call.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003751 """
3752 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3753 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3754 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3755
3756 cadesc = cacert.get_subject()
3757 sedesc = secert.get_subject()
3758 cldesc = clcert.get_subject()
3759
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003760 def mixed_set_add_ca(ctx):
3761 ctx.set_client_ca_list([cadesc, sedesc])
3762 ctx.add_client_ca(clcert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003763 return [cadesc, sedesc, cldesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003764 self._check_client_ca_list(mixed_set_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003765
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003766 def test_set_after_add_client_ca(self):
3767 """
Alex Chanb7480992017-01-30 14:04:47 +00003768 A call to `Context.set_client_ca_list` after a call to
3769 `Context.add_client_ca` replaces the CA name specified by the
Hynek Schlawack35618382015-09-05 21:54:25 +02003770 former call with the names specified by the latter call.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003771 """
3772 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3773 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3774 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3775
3776 cadesc = cacert.get_subject()
3777 sedesc = secert.get_subject()
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003778
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003779 def set_replaces_add_ca(ctx):
3780 ctx.add_client_ca(clcert)
3781 ctx.set_client_ca_list([cadesc])
3782 ctx.add_client_ca(secert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003783 return [cadesc, sedesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003784 self._check_client_ca_list(set_replaces_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003785
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003786
Alex Chanb7480992017-01-30 14:04:47 +00003787class TestInfoConstants(object):
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003788 """
3789 Tests for assorted constants exposed for use in info callbacks.
3790 """
3791 def test_integers(self):
3792 """
3793 All of the info constants are integers.
3794
3795 This is a very weak test. It would be nice to have one that actually
3796 verifies that as certain info events happen, the value passed to the
3797 info callback matches up with the constant exposed by OpenSSL.SSL.
3798 """
3799 for const in [
Alex Gaynor5af32d02016-09-24 01:52:21 -04003800 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK,
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003801 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
3802 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
3803 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
Hynek Schlawack35618382015-09-05 21:54:25 +02003804 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE
3805 ]:
Alex Gaynor5af32d02016-09-24 01:52:21 -04003806 assert isinstance(const, int)
3807
3808 # These constants don't exist on OpenSSL 1.1.0
3809 for const in [
3810 SSL_ST_INIT, SSL_ST_BEFORE, SSL_ST_OK, SSL_ST_RENEGOTIATE
3811 ]:
3812 assert const is None or isinstance(const, int)
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003813
Ziga Seilnacht44611bf2009-08-31 20:49:30 +02003814
Cory Benfield1d142142016-03-30 11:51:45 +01003815class TestRequires(object):
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003816 """
3817 Tests for the decorator factory used to conditionally raise
Cory Benfield1d142142016-03-30 11:51:45 +01003818 NotImplementedError when older OpenSSLs are used.
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003819 """
3820 def test_available(self):
3821 """
3822 When the OpenSSL functionality is available the decorated functions
3823 work appropriately.
3824 """
3825 feature_guard = _make_requires(True, "Error text")
3826 results = []
3827
3828 @feature_guard
3829 def inner():
3830 results.append(True)
3831 return True
3832
Cory Benfield2333e5e2016-03-30 14:24:16 +01003833 assert inner() is True
3834 assert [True] == results
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003835
3836 def test_unavailable(self):
3837 """
3838 When the OpenSSL functionality is not available the decorated function
3839 does not execute and NotImplementedError is raised.
3840 """
3841 feature_guard = _make_requires(False, "Error text")
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003842
3843 @feature_guard
Alex Chanfb078d82017-04-20 11:16:15 +01003844 def inner(): # pragma: nocover
3845 pytest.fail("Should not be called")
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003846
Cory Benfield1d142142016-03-30 11:51:45 +01003847 with pytest.raises(NotImplementedError) as e:
3848 inner()
3849
3850 assert "Error text" in str(e.value)
Cory Benfield496652a2017-01-24 11:42:56 +00003851
3852
Alex Chanb7480992017-01-30 14:04:47 +00003853class TestOCSP(object):
Cory Benfield496652a2017-01-24 11:42:56 +00003854 """
3855 Tests for PyOpenSSL's OCSP stapling support.
3856 """
3857 sample_ocsp_data = b"this is totally ocsp data"
3858
3859 def _client_connection(self, callback, data, request_ocsp=True):
3860 """
3861 Builds a client connection suitable for using OCSP.
3862
3863 :param callback: The callback to register for OCSP.
3864 :param data: The opaque data object that will be handed to the
3865 OCSP callback.
3866 :param request_ocsp: Whether the client will actually ask for OCSP
3867 stapling. Useful for testing only.
3868 """
3869 ctx = Context(SSLv23_METHOD)
3870 ctx.set_ocsp_client_callback(callback, data)
3871 client = Connection(ctx)
3872
3873 if request_ocsp:
3874 client.request_ocsp()
3875
3876 client.set_connect_state()
3877 return client
3878
3879 def _server_connection(self, callback, data):
3880 """
3881 Builds a server connection suitable for using OCSP.
3882
3883 :param callback: The callback to register for OCSP.
3884 :param data: The opaque data object that will be handed to the
3885 OCSP callback.
3886 """
3887 ctx = Context(SSLv23_METHOD)
3888 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
3889 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
3890 ctx.set_ocsp_server_callback(callback, data)
3891 server = Connection(ctx)
3892 server.set_accept_state()
3893 return server
3894
3895 def test_callbacks_arent_called_by_default(self):
3896 """
3897 If both the client and the server have registered OCSP callbacks, but
3898 the client does not send the OCSP request, neither callback gets
3899 called.
3900 """
Alex Chanfb078d82017-04-20 11:16:15 +01003901 def ocsp_callback(*args, **kwargs): # pragma: nocover
3902 pytest.fail("Should not be called")
Cory Benfield496652a2017-01-24 11:42:56 +00003903
3904 client = self._client_connection(
3905 callback=ocsp_callback, data=None, request_ocsp=False
3906 )
3907 server = self._server_connection(callback=ocsp_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00003908 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003909
Cory Benfield496652a2017-01-24 11:42:56 +00003910 def test_client_negotiates_without_server(self):
3911 """
3912 If the client wants to do OCSP but the server does not, the handshake
3913 succeeds, and the client callback fires with an empty byte string.
3914 """
3915 called = []
3916
3917 def ocsp_callback(conn, ocsp_data, ignored):
3918 called.append(ocsp_data)
3919 return True
3920
3921 client = self._client_connection(callback=ocsp_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00003922 server = loopback_server_factory(socket=None)
3923 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003924
3925 assert len(called) == 1
3926 assert called[0] == b''
3927
3928 def test_client_receives_servers_data(self):
3929 """
3930 The data the server sends in its callback is received by the client.
3931 """
3932 calls = []
3933
3934 def server_callback(*args, **kwargs):
3935 return self.sample_ocsp_data
3936
3937 def client_callback(conn, ocsp_data, ignored):
3938 calls.append(ocsp_data)
3939 return True
3940
3941 client = self._client_connection(callback=client_callback, data=None)
3942 server = self._server_connection(callback=server_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00003943 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003944
3945 assert len(calls) == 1
3946 assert calls[0] == self.sample_ocsp_data
3947
3948 def test_callbacks_are_invoked_with_connections(self):
3949 """
3950 The first arguments to both callbacks are their respective connections.
3951 """
3952 client_calls = []
3953 server_calls = []
3954
3955 def client_callback(conn, *args, **kwargs):
3956 client_calls.append(conn)
3957 return True
3958
3959 def server_callback(conn, *args, **kwargs):
3960 server_calls.append(conn)
3961 return self.sample_ocsp_data
3962
3963 client = self._client_connection(callback=client_callback, data=None)
3964 server = self._server_connection(callback=server_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00003965 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003966
3967 assert len(client_calls) == 1
3968 assert len(server_calls) == 1
3969 assert client_calls[0] is client
3970 assert server_calls[0] is server
3971
3972 def test_opaque_data_is_passed_through(self):
3973 """
3974 Both callbacks receive an opaque, user-provided piece of data in their
3975 callbacks as the final argument.
3976 """
3977 calls = []
3978
3979 def server_callback(*args):
3980 calls.append(args)
3981 return self.sample_ocsp_data
3982
3983 def client_callback(*args):
3984 calls.append(args)
3985 return True
3986
3987 sentinel = object()
3988
3989 client = self._client_connection(
3990 callback=client_callback, data=sentinel
3991 )
3992 server = self._server_connection(
3993 callback=server_callback, data=sentinel
3994 )
Alex Chanb7480992017-01-30 14:04:47 +00003995 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003996
3997 assert len(calls) == 2
3998 assert calls[0][-1] is sentinel
3999 assert calls[1][-1] is sentinel
4000
4001 def test_server_returns_empty_string(self):
4002 """
4003 If the server returns an empty bytestring from its callback, the
4004 client callback is called with the empty bytestring.
4005 """
4006 client_calls = []
4007
4008 def server_callback(*args):
4009 return b''
4010
4011 def client_callback(conn, ocsp_data, ignored):
4012 client_calls.append(ocsp_data)
4013 return True
4014
4015 client = self._client_connection(callback=client_callback, data=None)
4016 server = self._server_connection(callback=server_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00004017 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00004018
4019 assert len(client_calls) == 1
4020 assert client_calls[0] == b''
4021
4022 def test_client_returns_false_terminates_handshake(self):
4023 """
4024 If the client returns False from its callback, the handshake fails.
4025 """
4026 def server_callback(*args):
4027 return self.sample_ocsp_data
4028
4029 def client_callback(*args):
4030 return False
4031
4032 client = self._client_connection(callback=client_callback, data=None)
4033 server = self._server_connection(callback=server_callback, data=None)
4034
4035 with pytest.raises(Error):
Alex Chanb7480992017-01-30 14:04:47 +00004036 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00004037
4038 def test_exceptions_in_client_bubble_up(self):
4039 """
4040 The callbacks thrown in the client callback bubble up to the caller.
4041 """
4042 class SentinelException(Exception):
4043 pass
4044
4045 def server_callback(*args):
4046 return self.sample_ocsp_data
4047
4048 def client_callback(*args):
4049 raise SentinelException()
4050
4051 client = self._client_connection(callback=client_callback, data=None)
4052 server = self._server_connection(callback=server_callback, data=None)
4053
4054 with pytest.raises(SentinelException):
Alex Chanb7480992017-01-30 14:04:47 +00004055 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00004056
4057 def test_exceptions_in_server_bubble_up(self):
4058 """
4059 The callbacks thrown in the server callback bubble up to the caller.
4060 """
4061 class SentinelException(Exception):
4062 pass
4063
4064 def server_callback(*args):
4065 raise SentinelException()
4066
Alex Chanfb078d82017-04-20 11:16:15 +01004067 def client_callback(*args): # pragma: nocover
Cory Benfield496652a2017-01-24 11:42:56 +00004068 pytest.fail("Should not be called")
4069
4070 client = self._client_connection(callback=client_callback, data=None)
4071 server = self._server_connection(callback=server_callback, data=None)
4072
4073 with pytest.raises(SentinelException):
Alex Chanb7480992017-01-30 14:04:47 +00004074 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00004075
4076 def test_server_must_return_bytes(self):
4077 """
4078 The server callback must return a bytestring, or a TypeError is thrown.
4079 """
4080 def server_callback(*args):
4081 return self.sample_ocsp_data.decode('ascii')
4082
Alex Chanfb078d82017-04-20 11:16:15 +01004083 def client_callback(*args): # pragma: nocover
Cory Benfield496652a2017-01-24 11:42:56 +00004084 pytest.fail("Should not be called")
4085
4086 client = self._client_connection(callback=client_callback, data=None)
4087 server = self._server_connection(callback=server_callback, data=None)
4088
4089 with pytest.raises(TypeError):
Alex Chanb7480992017-01-30 14:04:47 +00004090 handshake_in_memory(client, server)