blob: 2cee928dda6729311409e3a7b7a4b441f45b5c45 [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')
Alex Gaynor675534c2020-01-12 11:59:49 -0600195 not_after_date = (datetime.date.today() + datetime.timedelta(days=365))
196 not_after = not_after_date.strftime("%Y%m%d%H%M%SZ").encode("ascii")
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400197
198 # Step 1
199 cakey = PKey()
Alex Gaynor0737a5e2016-09-10 14:35:09 -0400200 cakey.generate_key(TYPE_RSA, 1024)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400201 cacert = X509()
David Benjamin6b799472020-06-24 17:14:16 -0400202 cacert.set_version(2)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400203 cacert.get_subject().commonName = "Authority Certificate"
204 cacert.set_issuer(cacert.get_subject())
205 cacert.set_pubkey(cakey)
Alex Gaynore7f51982016-09-11 11:48:14 -0400206 cacert.set_notBefore(b"20000101000000Z")
Alex Gaynor675534c2020-01-12 11:59:49 -0600207 cacert.set_notAfter(not_after)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400208 cacert.add_extensions([caext])
209 cacert.set_serial_number(0)
210 cacert.sign(cakey, "sha1")
211
212 # Step 2
213 ikey = PKey()
Alex Gaynor0737a5e2016-09-10 14:35:09 -0400214 ikey.generate_key(TYPE_RSA, 1024)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400215 icert = X509()
David Benjamin6b799472020-06-24 17:14:16 -0400216 icert.set_version(2)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400217 icert.get_subject().commonName = "Intermediate Certificate"
218 icert.set_issuer(cacert.get_subject())
219 icert.set_pubkey(ikey)
Alex Gaynore7f51982016-09-11 11:48:14 -0400220 icert.set_notBefore(b"20000101000000Z")
Alex Gaynor675534c2020-01-12 11:59:49 -0600221 icert.set_notAfter(not_after)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400222 icert.add_extensions([caext])
223 icert.set_serial_number(0)
224 icert.sign(cakey, "sha1")
225
226 # Step 3
227 skey = PKey()
Alex Gaynor0737a5e2016-09-10 14:35:09 -0400228 skey.generate_key(TYPE_RSA, 1024)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400229 scert = X509()
David Benjamin6b799472020-06-24 17:14:16 -0400230 scert.set_version(2)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400231 scert.get_subject().commonName = "Server Certificate"
232 scert.set_issuer(icert.get_subject())
233 scert.set_pubkey(skey)
Alex Gaynore7f51982016-09-11 11:48:14 -0400234 scert.set_notBefore(b"20000101000000Z")
Alex Gaynor675534c2020-01-12 11:59:49 -0600235 scert.set_notAfter(not_after)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400236 scert.add_extensions([
Alex Gaynore7f51982016-09-11 11:48:14 -0400237 X509Extension(b'basicConstraints', True, b'CA:false')])
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400238 scert.set_serial_number(0)
239 scert.sign(ikey, "sha1")
240
241 return [(cakey, cacert), (ikey, icert), (skey, scert)]
242
243
Paul Kehrer7d5a3bf2019-01-21 12:24:02 -0600244def loopback_client_factory(socket, version=SSLv23_METHOD):
245 client = Connection(Context(version), socket)
Alex Chan1c0cb662017-01-30 07:13:30 +0000246 client.set_connect_state()
247 return client
248
249
Paul Kehrer7d5a3bf2019-01-21 12:24:02 -0600250def loopback_server_factory(socket, version=SSLv23_METHOD):
251 ctx = Context(version)
Alex Chan1c0cb662017-01-30 07:13:30 +0000252 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
253 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
254 server = Connection(ctx, socket)
255 server.set_accept_state()
256 return server
257
258
259def loopback(server_factory=None, client_factory=None):
260 """
261 Create a connected socket pair and force two connected SSL sockets
262 to talk to each other via memory BIOs.
263 """
264 if server_factory is None:
265 server_factory = loopback_server_factory
266 if client_factory is None:
267 client_factory = loopback_client_factory
268
269 (server, client) = socket_pair()
270 server = server_factory(server)
271 client = client_factory(client)
272
273 handshake(client, server)
274
275 server.setblocking(True)
276 client.setblocking(True)
277 return server, client
278
279
Alex Chan1ca9e3a2016-11-05 13:01:51 +0000280def interact_in_memory(client_conn, server_conn):
281 """
282 Try to read application bytes from each of the two `Connection` objects.
283 Copy bytes back and forth between their send/receive buffers for as long
284 as there is anything to copy. When there is nothing more to copy,
285 return `None`. If one of them actually manages to deliver some application
286 bytes, return a two-tuple of the connection from which the bytes were read
287 and the bytes themselves.
288 """
289 wrote = True
290 while wrote:
291 # Loop until neither side has anything to say
292 wrote = False
293
294 # Copy stuff from each side's send buffer to the other side's
295 # receive buffer.
296 for (read, write) in [(client_conn, server_conn),
297 (server_conn, client_conn)]:
298
299 # Give the side a chance to generate some more bytes, or succeed.
300 try:
301 data = read.recv(2 ** 16)
302 except WantReadError:
303 # It didn't succeed, so we'll hope it generated some output.
304 pass
305 else:
306 # It did succeed, so we'll stop now and let the caller deal
307 # with it.
308 return (read, data)
309
310 while True:
311 # Keep copying as long as there's more stuff there.
312 try:
313 dirty = read.bio_read(4096)
314 except WantReadError:
315 # Okay, nothing more waiting to be sent. Stop
316 # processing this send buffer.
317 break
318 else:
319 # Keep track of the fact that someone generated some
320 # output.
321 wrote = True
322 write.bio_write(dirty)
323
324
Alex Chan532b79e2017-01-24 15:14:52 +0000325def handshake_in_memory(client_conn, server_conn):
326 """
327 Perform the TLS handshake between two `Connection` instances connected to
328 each other via memory BIOs.
329 """
330 client_conn.set_connect_state()
331 server_conn.set_accept_state()
332
333 for conn in [client_conn, server_conn]:
334 try:
335 conn.do_handshake()
336 except WantReadError:
337 pass
338
339 interact_in_memory(client_conn, server_conn)
340
341
Alex Chanb7480992017-01-30 14:04:47 +0000342class TestVersion(object):
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400343 """
Alex Chanb7480992017-01-30 14:04:47 +0000344 Tests for version information exposed by `OpenSSL.SSL.SSLeay_version` and
345 `OpenSSL.SSL.OPENSSL_VERSION_NUMBER`.
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400346 """
347 def test_OPENSSL_VERSION_NUMBER(self):
348 """
Alex Chanb7480992017-01-30 14:04:47 +0000349 `OPENSSL_VERSION_NUMBER` is an integer with status in the low byte and
350 the patch, fix, minor, and major versions in the nibbles above that.
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400351 """
Alex Chanb7480992017-01-30 14:04:47 +0000352 assert isinstance(OPENSSL_VERSION_NUMBER, int)
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400353
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400354 def test_SSLeay_version(self):
355 """
Alex Chanb7480992017-01-30 14:04:47 +0000356 `SSLeay_version` takes a version type indicator and returns one of a
357 number of version strings based on that indicator.
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400358 """
359 versions = {}
360 for t in [SSLEAY_VERSION, SSLEAY_CFLAGS, SSLEAY_BUILT_ON,
361 SSLEAY_PLATFORM, SSLEAY_DIR]:
362 version = SSLeay_version(t)
363 versions[version] = t
Alex Chanb7480992017-01-30 14:04:47 +0000364 assert isinstance(version, bytes)
365 assert len(versions) == 5
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400366
367
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100368@pytest.fixture
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100369def ca_file(tmpdir):
370 """
371 Create a valid PEM file with CA certificates and return the path.
372 """
373 key = rsa.generate_private_key(
374 public_exponent=65537,
375 key_size=2048,
376 backend=default_backend()
377 )
378 public_key = key.public_key()
379
380 builder = x509.CertificateBuilder()
381 builder = builder.subject_name(x509.Name([
382 x509.NameAttribute(NameOID.COMMON_NAME, u"pyopenssl.org"),
383 ]))
384 builder = builder.issuer_name(x509.Name([
385 x509.NameAttribute(NameOID.COMMON_NAME, u"pyopenssl.org"),
386 ]))
387 one_day = datetime.timedelta(1, 0, 0)
388 builder = builder.not_valid_before(datetime.datetime.today() - one_day)
389 builder = builder.not_valid_after(datetime.datetime.today() + one_day)
390 builder = builder.serial_number(int(uuid.uuid4()))
391 builder = builder.public_key(public_key)
392 builder = builder.add_extension(
393 x509.BasicConstraints(ca=True, path_length=None), critical=True,
394 )
395
396 certificate = builder.sign(
397 private_key=key, algorithm=hashes.SHA256(),
398 backend=default_backend()
399 )
400
401 ca_file = tmpdir.join("test.pem")
402 ca_file.write_binary(
403 certificate.public_bytes(
404 encoding=serialization.Encoding.PEM,
405 )
406 )
407
408 return str(ca_file).encode("ascii")
409
410
411@pytest.fixture
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100412def context():
413 """
414 A simple TLS 1.0 context.
415 """
416 return Context(TLSv1_METHOD)
417
418
419class TestContext(object):
Hynek Schlawackaa861212016-03-13 13:53:48 +0100420 """
Alex Chan532b79e2017-01-24 15:14:52 +0000421 Unit tests for `OpenSSL.SSL.Context`.
Hynek Schlawackaa861212016-03-13 13:53:48 +0100422 """
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100423 @pytest.mark.parametrize("cipher_string", [
424 b"hello world:AES128-SHA",
425 u"hello world:AES128-SHA",
426 ])
427 def test_set_cipher_list(self, context, cipher_string):
428 """
Alex Chan532b79e2017-01-24 15:14:52 +0000429 `Context.set_cipher_list` accepts both byte and unicode strings
Hynek Schlawacka7a63af2016-03-11 12:05:26 +0100430 for naming the ciphers which connections created with the context
431 object will be able to choose from.
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100432 """
433 context.set_cipher_list(cipher_string)
434 conn = Connection(context, None)
435
436 assert "AES128-SHA" in conn.get_cipher_list()
437
Mark Williamsdf2480d2019-02-14 19:30:07 -0800438 def test_set_cipher_list_wrong_type(self, context):
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100439 """
Alex Chan532b79e2017-01-24 15:14:52 +0000440 `Context.set_cipher_list` raises `TypeError` when passed a non-string
Mark Williamsdf2480d2019-02-14 19:30:07 -0800441 argument.
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100442 """
Mark Williamsdf2480d2019-02-14 19:30:07 -0800443 with pytest.raises(TypeError):
444 context.set_cipher_list(object())
445
Alex Gaynor963ae032019-07-06 17:38:32 -0400446 @flaky.flaky
Mark Williamsdf2480d2019-02-14 19:30:07 -0800447 def test_set_cipher_list_no_cipher_match(self, context):
448 """
449 `Context.set_cipher_list` raises `OpenSSL.SSL.Error` with a
450 `"no cipher match"` reason string regardless of the TLS
451 version.
452 """
453 with pytest.raises(Error) as excinfo:
454 context.set_cipher_list(b"imaginary-cipher")
455 assert excinfo.value.args == (
456 [
457 (
458 'SSL routines',
459 'SSL_CTX_set_cipher_list',
460 'no cipher match',
461 ),
462 ],
463 )
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100464
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100465 def test_load_client_ca(self, context, ca_file):
466 """
Alex Chan532b79e2017-01-24 15:14:52 +0000467 `Context.load_client_ca` works as far as we can tell.
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100468 """
469 context.load_client_ca(ca_file)
470
471 def test_load_client_ca_invalid(self, context, tmpdir):
472 """
Alex Chan532b79e2017-01-24 15:14:52 +0000473 `Context.load_client_ca` raises an Error if the ca file is invalid.
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100474 """
475 ca_file = tmpdir.join("test.pem")
476 ca_file.write("")
477
478 with pytest.raises(Error) as e:
479 context.load_client_ca(str(ca_file).encode("ascii"))
480
481 assert "PEM routines" == e.value.args[0][0][0]
482
483 def test_load_client_ca_unicode(self, context, ca_file):
484 """
485 Passing the path as unicode raises a warning but works.
486 """
487 pytest.deprecated_call(
488 context.load_client_ca, ca_file.decode("ascii")
489 )
490
491 def test_set_session_id(self, context):
492 """
Alex Chan532b79e2017-01-24 15:14:52 +0000493 `Context.set_session_id` works as far as we can tell.
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100494 """
495 context.set_session_id(b"abc")
496
497 def test_set_session_id_fail(self, context):
498 """
Alex Chan532b79e2017-01-24 15:14:52 +0000499 `Context.set_session_id` errors are propagated.
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100500 """
501 with pytest.raises(Error) as e:
502 context.set_session_id(b"abc" * 1000)
503
504 assert [
505 ("SSL routines",
506 "SSL_CTX_set_session_id_context",
507 "ssl session id context too long")
508 ] == e.value.args[0]
509
510 def test_set_session_id_unicode(self, context):
511 """
Alex Chan532b79e2017-01-24 15:14:52 +0000512 `Context.set_session_id` raises a warning if a unicode string is
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100513 passed.
514 """
515 pytest.deprecated_call(context.set_session_id, u"abc")
516
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400517 def test_method(self):
518 """
Alex Chan532b79e2017-01-24 15:14:52 +0000519 `Context` can be instantiated with one of `SSLv2_METHOD`,
520 `SSLv3_METHOD`, `SSLv23_METHOD`, `TLSv1_METHOD`, `TLSv1_1_METHOD`,
521 or `TLSv1_2_METHOD`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400522 """
Alex Gaynor5af32d02016-09-24 01:52:21 -0400523 methods = [SSLv23_METHOD, TLSv1_METHOD]
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400524 for meth in methods:
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400525 Context(meth)
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400526
Alex Gaynor5af32d02016-09-24 01:52:21 -0400527 maybe = [SSLv2_METHOD, SSLv3_METHOD, TLSv1_1_METHOD, TLSv1_2_METHOD]
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400528 for meth in maybe:
529 try:
530 Context(meth)
531 except (Error, ValueError):
532 # Some versions of OpenSSL have SSLv2 / TLSv1.1 / TLSv1.2, some
533 # don't. Difficult to say in advance.
534 pass
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400535
Alex Chan532b79e2017-01-24 15:14:52 +0000536 with pytest.raises(TypeError):
537 Context("")
538 with pytest.raises(ValueError):
539 Context(10)
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400540
Rick Deane15b1472009-07-09 15:53:42 -0500541 def test_type(self):
542 """
Alex Gaynor01f90a12019-02-07 09:14:48 -0500543 `Context` can be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -0500544 """
Alex Chan532b79e2017-01-24 15:14:52 +0000545 assert is_consistent_type(Context, 'Context', TLSv1_METHOD)
Rick Deane15b1472009-07-09 15:53:42 -0500546
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400547 def test_use_privatekey(self):
548 """
Alex Chan532b79e2017-01-24 15:14:52 +0000549 `Context.use_privatekey` takes an `OpenSSL.crypto.PKey` instance.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400550 """
551 key = PKey()
Alex Gaynor6e9f9762018-05-12 07:44:37 -0400552 key.generate_key(TYPE_RSA, 512)
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400553 ctx = Context(TLSv1_METHOD)
554 ctx.use_privatekey(key)
Alex Chan532b79e2017-01-24 15:14:52 +0000555 with pytest.raises(TypeError):
556 ctx.use_privatekey("")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400557
Alex Chan532b79e2017-01-24 15:14:52 +0000558 def test_use_privatekey_file_missing(self, tmpfile):
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800559 """
Alex Chan532b79e2017-01-24 15:14:52 +0000560 `Context.use_privatekey_file` raises `OpenSSL.SSL.Error` when passed
561 the name of a file which does not exist.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800562 """
563 ctx = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000564 with pytest.raises(Error):
565 ctx.use_privatekey_file(tmpfile)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800566
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400567 def _use_privatekey_file_test(self, pemfile, filetype):
568 """
569 Verify that calling ``Context.use_privatekey_file`` with the given
570 arguments does not raise an exception.
571 """
572 key = PKey()
Alex Gaynor6e9f9762018-05-12 07:44:37 -0400573 key.generate_key(TYPE_RSA, 512)
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400574
575 with open(pemfile, "wt") as pem:
576 pem.write(
577 dump_privatekey(FILETYPE_PEM, key).decode("ascii")
578 )
579
580 ctx = Context(TLSv1_METHOD)
581 ctx.use_privatekey_file(pemfile, filetype)
582
Alex Chanfb078d82017-04-20 11:16:15 +0100583 @pytest.mark.parametrize('filetype', [object(), "", None, 1.0])
584 def test_wrong_privatekey_file_wrong_args(self, tmpfile, filetype):
585 """
586 `Context.use_privatekey_file` raises `TypeError` when called with
587 a `filetype` which is not a valid file encoding.
588 """
589 ctx = Context(TLSv1_METHOD)
590 with pytest.raises(TypeError):
591 ctx.use_privatekey_file(tmpfile, filetype)
592
Alex Chan532b79e2017-01-24 15:14:52 +0000593 def test_use_privatekey_file_bytes(self, tmpfile):
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400594 """
595 A private key can be specified from a file by passing a ``bytes``
596 instance giving the file name to ``Context.use_privatekey_file``.
597 """
598 self._use_privatekey_file_test(
Alex Chan532b79e2017-01-24 15:14:52 +0000599 tmpfile + NON_ASCII.encode(getfilesystemencoding()),
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400600 FILETYPE_PEM,
601 )
602
Alex Chan532b79e2017-01-24 15:14:52 +0000603 def test_use_privatekey_file_unicode(self, tmpfile):
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400604 """
605 A private key can be specified from a file by passing a ``unicode``
606 instance giving the file name to ``Context.use_privatekey_file``.
607 """
608 self._use_privatekey_file_test(
Alex Chan532b79e2017-01-24 15:14:52 +0000609 tmpfile.decode(getfilesystemencoding()) + NON_ASCII,
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400610 FILETYPE_PEM,
611 )
612
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800613 def test_use_certificate_wrong_args(self):
614 """
Alex Chan532b79e2017-01-24 15:14:52 +0000615 `Context.use_certificate_wrong_args` raises `TypeError` when not passed
616 exactly one `OpenSSL.crypto.X509` instance as an argument.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800617 """
618 ctx = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000619 with pytest.raises(TypeError):
620 ctx.use_certificate("hello, world")
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800621
622 def test_use_certificate_uninitialized(self):
623 """
Alex Chan532b79e2017-01-24 15:14:52 +0000624 `Context.use_certificate` raises `OpenSSL.SSL.Error` when passed a
625 `OpenSSL.crypto.X509` instance which has not been initialized
626 (ie, which does not actually have any certificate data).
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800627 """
628 ctx = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000629 with pytest.raises(Error):
630 ctx.use_certificate(X509())
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800631
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800632 def test_use_certificate(self):
633 """
Alex Chan532b79e2017-01-24 15:14:52 +0000634 `Context.use_certificate` sets the certificate which will be
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800635 used to identify connections created using the context.
636 """
637 # TODO
638 # Hard to assert anything. But we could set a privatekey then ask
639 # OpenSSL if the cert and key agree using check_privatekey. Then as
640 # long as check_privatekey works right we're good...
641 ctx = Context(TLSv1_METHOD)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200642 ctx.use_certificate(
643 load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
644 )
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800645
646 def test_use_certificate_file_wrong_args(self):
647 """
Alex Chan532b79e2017-01-24 15:14:52 +0000648 `Context.use_certificate_file` raises `TypeError` if the first
649 argument is not a byte string or the second argument is not an integer.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800650 """
651 ctx = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000652 with pytest.raises(TypeError):
653 ctx.use_certificate_file(object(), FILETYPE_PEM)
654 with pytest.raises(TypeError):
655 ctx.use_certificate_file(b"somefile", object())
656 with pytest.raises(TypeError):
657 ctx.use_certificate_file(object(), FILETYPE_PEM)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800658
Alex Chan532b79e2017-01-24 15:14:52 +0000659 def test_use_certificate_file_missing(self, tmpfile):
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800660 """
Alex Chan532b79e2017-01-24 15:14:52 +0000661 `Context.use_certificate_file` raises `OpenSSL.SSL.Error` if passed
662 the name of a file which does not exist.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800663 """
664 ctx = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000665 with pytest.raises(Error):
666 ctx.use_certificate_file(tmpfile)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800667
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400668 def _use_certificate_file_test(self, certificate_file):
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800669 """
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400670 Verify that calling ``Context.use_certificate_file`` with the given
671 filename doesn't raise an exception.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800672 """
673 # TODO
674 # Hard to assert anything. But we could set a privatekey then ask
675 # OpenSSL if the cert and key agree using check_privatekey. Then as
676 # long as check_privatekey works right we're good...
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400677 with open(certificate_file, "wb") as pem_file:
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800678 pem_file.write(cleartextCertificatePEM)
679
680 ctx = Context(TLSv1_METHOD)
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400681 ctx.use_certificate_file(certificate_file)
682
Alex Chan532b79e2017-01-24 15:14:52 +0000683 def test_use_certificate_file_bytes(self, tmpfile):
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400684 """
Alex Chan532b79e2017-01-24 15:14:52 +0000685 `Context.use_certificate_file` sets the certificate (given as a
686 `bytes` filename) which will be used to identify connections created
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400687 using the context.
688 """
Alex Chan532b79e2017-01-24 15:14:52 +0000689 filename = tmpfile + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400690 self._use_certificate_file_test(filename)
691
Alex Chan532b79e2017-01-24 15:14:52 +0000692 def test_use_certificate_file_unicode(self, tmpfile):
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400693 """
Alex Chan532b79e2017-01-24 15:14:52 +0000694 `Context.use_certificate_file` sets the certificate (given as a
695 `bytes` filename) which will be used to identify connections created
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400696 using the context.
697 """
Alex Chan532b79e2017-01-24 15:14:52 +0000698 filename = tmpfile.decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400699 self._use_certificate_file_test(filename)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800700
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500701 def test_check_privatekey_valid(self):
702 """
Alex Chan532b79e2017-01-24 15:14:52 +0000703 `Context.check_privatekey` returns `None` if the `Context` instance
704 has been configured to use a matched key and certificate pair.
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500705 """
706 key = load_privatekey(FILETYPE_PEM, client_key_pem)
707 cert = load_certificate(FILETYPE_PEM, client_cert_pem)
708 context = Context(TLSv1_METHOD)
709 context.use_privatekey(key)
710 context.use_certificate(cert)
Alex Chan532b79e2017-01-24 15:14:52 +0000711 assert None is context.check_privatekey()
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500712
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500713 def test_check_privatekey_invalid(self):
714 """
Alex Chan532b79e2017-01-24 15:14:52 +0000715 `Context.check_privatekey` raises `Error` if the `Context` instance
716 has been configured to use a key and certificate pair which don't
717 relate to each other.
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500718 """
719 key = load_privatekey(FILETYPE_PEM, client_key_pem)
720 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
721 context = Context(TLSv1_METHOD)
722 context.use_privatekey(key)
723 context.use_certificate(cert)
Alex Chan532b79e2017-01-24 15:14:52 +0000724 with pytest.raises(Error):
725 context.check_privatekey()
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400726
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400727 def test_app_data(self):
728 """
Alex Chan532b79e2017-01-24 15:14:52 +0000729 `Context.set_app_data` stores an object for later retrieval
730 using `Context.get_app_data`.
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400731 """
732 app_data = object()
733 context = Context(TLSv1_METHOD)
734 context.set_app_data(app_data)
Alex Chan532b79e2017-01-24 15:14:52 +0000735 assert context.get_app_data() is app_data
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400736
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400737 def test_set_options_wrong_args(self):
738 """
Alex Chan532b79e2017-01-24 15:14:52 +0000739 `Context.set_options` raises `TypeError` if called with
740 a non-`int` argument.
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400741 """
742 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000743 with pytest.raises(TypeError):
744 context.set_options(None)
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400745
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500746 def test_set_options(self):
747 """
Alex Chan532b79e2017-01-24 15:14:52 +0000748 `Context.set_options` returns the new options value.
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500749 """
750 context = Context(TLSv1_METHOD)
751 options = context.set_options(OP_NO_SSLv2)
Alex Gaynor2310f8b2016-09-10 14:39:32 -0400752 assert options & OP_NO_SSLv2 == OP_NO_SSLv2
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500753
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300754 def test_set_mode_wrong_args(self):
755 """
Alex Chan532b79e2017-01-24 15:14:52 +0000756 `Context.set_mode` raises `TypeError` if called with
757 a non-`int` argument.
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300758 """
759 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000760 with pytest.raises(TypeError):
761 context.set_mode(None)
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300762
Alex Gaynord3b5d9b2016-07-31 10:54:24 -0400763 def test_set_mode(self):
764 """
Alex Chan532b79e2017-01-24 15:14:52 +0000765 `Context.set_mode` accepts a mode bitvector and returns the
Alex Gaynord3b5d9b2016-07-31 10:54:24 -0400766 newly set mode.
767 """
768 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000769 assert MODE_RELEASE_BUFFERS & context.set_mode(MODE_RELEASE_BUFFERS)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500770
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400771 def test_set_timeout_wrong_args(self):
772 """
Alex Chan532b79e2017-01-24 15:14:52 +0000773 `Context.set_timeout` raises `TypeError` if called with
774 a non-`int` argument.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400775 """
776 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000777 with pytest.raises(TypeError):
778 context.set_timeout(None)
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400779
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400780 def test_timeout(self):
781 """
Alex Chan532b79e2017-01-24 15:14:52 +0000782 `Context.set_timeout` sets the session timeout for all connections
783 created using the context object. `Context.get_timeout` retrieves
784 this value.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400785 """
786 context = Context(TLSv1_METHOD)
787 context.set_timeout(1234)
Alex Chan532b79e2017-01-24 15:14:52 +0000788 assert context.get_timeout() == 1234
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400789
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400790 def test_set_verify_depth_wrong_args(self):
791 """
Alex Chan532b79e2017-01-24 15:14:52 +0000792 `Context.set_verify_depth` raises `TypeError` if called with a
793 non-`int` argument.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400794 """
795 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000796 with pytest.raises(TypeError):
797 context.set_verify_depth(None)
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400798
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400799 def test_verify_depth(self):
800 """
Alex Chan532b79e2017-01-24 15:14:52 +0000801 `Context.set_verify_depth` sets the number of certificates in
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200802 a chain to follow before giving up. The value can be retrieved with
Alex Chan532b79e2017-01-24 15:14:52 +0000803 `Context.get_verify_depth`.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400804 """
805 context = Context(TLSv1_METHOD)
806 context.set_verify_depth(11)
Alex Chan532b79e2017-01-24 15:14:52 +0000807 assert context.get_verify_depth() == 11
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400808
Alex Chan532b79e2017-01-24 15:14:52 +0000809 def _write_encrypted_pem(self, passphrase, tmpfile):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400810 """
811 Write a new private key out to a new file, encrypted using the given
812 passphrase. Return the path to the new file.
813 """
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400814 key = PKey()
Alex Gaynor6e9f9762018-05-12 07:44:37 -0400815 key.generate_key(TYPE_RSA, 512)
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400816 pem = dump_privatekey(FILETYPE_PEM, key, "blowfish", passphrase)
Alex Chan532b79e2017-01-24 15:14:52 +0000817 with open(tmpfile, 'w') as fObj:
818 fObj.write(pem.decode('ascii'))
819 return tmpfile
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400820
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400821 def test_set_passwd_cb_wrong_args(self):
822 """
Alex Chan532b79e2017-01-24 15:14:52 +0000823 `Context.set_passwd_cb` raises `TypeError` if called with a
824 non-callable first argument.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400825 """
826 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000827 with pytest.raises(TypeError):
828 context.set_passwd_cb(None)
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400829
Alex Chan532b79e2017-01-24 15:14:52 +0000830 def test_set_passwd_cb(self, tmpfile):
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400831 """
Alex Chan532b79e2017-01-24 15:14:52 +0000832 `Context.set_passwd_cb` accepts a callable which will be invoked when
833 a private key is loaded from an encrypted PEM.
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400834 """
Alex Gaynore7f51982016-09-11 11:48:14 -0400835 passphrase = b"foobar"
Alex Chan532b79e2017-01-24 15:14:52 +0000836 pemFile = self._write_encrypted_pem(passphrase, tmpfile)
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400837 calledWith = []
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200838
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400839 def passphraseCallback(maxlen, verify, extra):
840 calledWith.append((maxlen, verify, extra))
841 return passphrase
842 context = Context(TLSv1_METHOD)
843 context.set_passwd_cb(passphraseCallback)
844 context.use_privatekey_file(pemFile)
Alex Chan532b79e2017-01-24 15:14:52 +0000845 assert len(calledWith) == 1
846 assert isinstance(calledWith[0][0], int)
847 assert isinstance(calledWith[0][1], int)
848 assert calledWith[0][2] is None
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400849
Alex Chan532b79e2017-01-24 15:14:52 +0000850 def test_passwd_callback_exception(self, tmpfile):
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400851 """
Alex Chan532b79e2017-01-24 15:14:52 +0000852 `Context.use_privatekey_file` propagates any exception raised
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200853 by the passphrase callback.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400854 """
Alex Chan532b79e2017-01-24 15:14:52 +0000855 pemFile = self._write_encrypted_pem(b"monkeys are nice", tmpfile)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200856
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400857 def passphraseCallback(maxlen, verify, extra):
858 raise RuntimeError("Sorry, I am a fail.")
859
860 context = Context(TLSv1_METHOD)
861 context.set_passwd_cb(passphraseCallback)
Alex Chan532b79e2017-01-24 15:14:52 +0000862 with pytest.raises(RuntimeError):
863 context.use_privatekey_file(pemFile)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400864
Alex Chan532b79e2017-01-24 15:14:52 +0000865 def test_passwd_callback_false(self, tmpfile):
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400866 """
Alex Chan532b79e2017-01-24 15:14:52 +0000867 `Context.use_privatekey_file` raises `OpenSSL.SSL.Error` if the
868 passphrase callback returns a false value.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400869 """
Alex Chan532b79e2017-01-24 15:14:52 +0000870 pemFile = self._write_encrypted_pem(b"monkeys are nice", tmpfile)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200871
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400872 def passphraseCallback(maxlen, verify, extra):
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500873 return b""
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400874
875 context = Context(TLSv1_METHOD)
876 context.set_passwd_cb(passphraseCallback)
Alex Chan532b79e2017-01-24 15:14:52 +0000877 with pytest.raises(Error):
878 context.use_privatekey_file(pemFile)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400879
Alex Chan532b79e2017-01-24 15:14:52 +0000880 def test_passwd_callback_non_string(self, tmpfile):
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400881 """
Alex Chan532b79e2017-01-24 15:14:52 +0000882 `Context.use_privatekey_file` raises `OpenSSL.SSL.Error` if the
883 passphrase callback returns a true non-string value.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400884 """
Alex Chan532b79e2017-01-24 15:14:52 +0000885 pemFile = self._write_encrypted_pem(b"monkeys are nice", tmpfile)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200886
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400887 def passphraseCallback(maxlen, verify, extra):
888 return 10
889
890 context = Context(TLSv1_METHOD)
891 context.set_passwd_cb(passphraseCallback)
Alex Chan532b79e2017-01-24 15:14:52 +0000892 # TODO: Surely this is the wrong error?
893 with pytest.raises(ValueError):
894 context.use_privatekey_file(pemFile)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400895
Alex Chan532b79e2017-01-24 15:14:52 +0000896 def test_passwd_callback_too_long(self, tmpfile):
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400897 """
898 If the passphrase returned by the passphrase callback returns a string
899 longer than the indicated maximum length, it is truncated.
900 """
901 # A priori knowledge!
Alex Gaynore7f51982016-09-11 11:48:14 -0400902 passphrase = b"x" * 1024
Alex Chan532b79e2017-01-24 15:14:52 +0000903 pemFile = self._write_encrypted_pem(passphrase, tmpfile)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200904
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400905 def passphraseCallback(maxlen, verify, extra):
906 assert maxlen == 1024
Alex Gaynore7f51982016-09-11 11:48:14 -0400907 return passphrase + b"y"
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400908
909 context = Context(TLSv1_METHOD)
910 context.set_passwd_cb(passphraseCallback)
911 # This shall succeed because the truncated result is the correct
912 # passphrase.
913 context.use_privatekey_file(pemFile)
914
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400915 def test_set_info_callback(self):
916 """
Alex Chan532b79e2017-01-24 15:14:52 +0000917 `Context.set_info_callback` accepts a callable which will be
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200918 invoked when certain information about an SSL connection is available.
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400919 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500920 (server, client) = socket_pair()
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400921
922 clientSSL = Connection(Context(TLSv1_METHOD), client)
923 clientSSL.set_connect_state()
924
925 called = []
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200926
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400927 def info(conn, where, ret):
928 called.append((conn, where, ret))
929 context = Context(TLSv1_METHOD)
930 context.set_info_callback(info)
931 context.use_certificate(
932 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
933 context.use_privatekey(
934 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
935
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400936 serverSSL = Connection(context, server)
937 serverSSL.set_accept_state()
938
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -0500939 handshake(clientSSL, serverSSL)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400940
Jean-Paul Calderone3835e522014-02-02 11:12:30 -0500941 # The callback must always be called with a Connection instance as the
942 # first argument. It would probably be better to split this into
943 # separate tests for client and server side info callbacks so we could
944 # assert it is called with the right Connection instance. It would
945 # also be good to assert *something* about `where` and `ret`.
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -0500946 notConnections = [
947 conn for (conn, where, ret) in called
948 if not isinstance(conn, Connection)]
Alex Chan532b79e2017-01-24 15:14:52 +0000949 assert [] == notConnections, (
950 "Some info callback arguments were not Connection instances.")
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400951
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400952 def _load_verify_locations_test(self, *args):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400953 """
954 Create a client context which will verify the peer certificate and call
Alex Chan532b79e2017-01-24 15:14:52 +0000955 its `load_verify_locations` method with the given arguments.
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -0400956 Then connect it to a server and ensure that the handshake succeeds.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400957 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500958 (server, client) = socket_pair()
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400959
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400960 clientContext = Context(TLSv1_METHOD)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400961 clientContext.load_verify_locations(*args)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400962 # Require that the server certificate verify properly or the
963 # connection will fail.
964 clientContext.set_verify(
965 VERIFY_PEER,
966 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
967
968 clientSSL = Connection(clientContext, client)
969 clientSSL.set_connect_state()
970
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400971 serverContext = Context(TLSv1_METHOD)
972 serverContext.use_certificate(
973 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
974 serverContext.use_privatekey(
975 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
976
977 serverSSL = Connection(serverContext, server)
978 serverSSL.set_accept_state()
979
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400980 # Without load_verify_locations above, the handshake
981 # will fail:
982 # Error: [('SSL routines', 'SSL3_GET_SERVER_CERTIFICATE',
983 # 'certificate verify failed')]
984 handshake(clientSSL, serverSSL)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400985
986 cert = clientSSL.get_peer_certificate()
Alex Chan532b79e2017-01-24 15:14:52 +0000987 assert cert.get_subject().CN == 'Testing Root CA'
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400988
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400989 def _load_verify_cafile(self, cafile):
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400990 """
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400991 Verify that if path to a file containing a certificate is passed to
Alex Chan532b79e2017-01-24 15:14:52 +0000992 `Context.load_verify_locations` for the ``cafile`` parameter, that
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400993 certificate is used as a trust root for the purposes of verifying
Alex Chan532b79e2017-01-24 15:14:52 +0000994 connections created using that `Context`.
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400995 """
Alex Chan532b79e2017-01-24 15:14:52 +0000996 with open(cafile, 'w') as fObj:
997 fObj.write(cleartextCertificatePEM.decode('ascii'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400998
999 self._load_verify_locations_test(cafile)
1000
Alex Chan532b79e2017-01-24 15:14:52 +00001001 def test_load_verify_bytes_cafile(self, tmpfile):
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001002 """
Alex Chan532b79e2017-01-24 15:14:52 +00001003 `Context.load_verify_locations` accepts a file name as a `bytes`
1004 instance and uses the certificates within for verification purposes.
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001005 """
Alex Chan532b79e2017-01-24 15:14:52 +00001006 cafile = tmpfile + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001007 self._load_verify_cafile(cafile)
1008
Alex Chan532b79e2017-01-24 15:14:52 +00001009 def test_load_verify_unicode_cafile(self, tmpfile):
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001010 """
Alex Chan532b79e2017-01-24 15:14:52 +00001011 `Context.load_verify_locations` accepts a file name as a `unicode`
1012 instance and uses the certificates within for verification purposes.
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001013 """
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001014 self._load_verify_cafile(
Alex Chan532b79e2017-01-24 15:14:52 +00001015 tmpfile.decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001016 )
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001017
Alex Chan532b79e2017-01-24 15:14:52 +00001018 def test_load_verify_invalid_file(self, tmpfile):
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -04001019 """
Alex Chan532b79e2017-01-24 15:14:52 +00001020 `Context.load_verify_locations` raises `Error` when passed a
1021 non-existent cafile.
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -04001022 """
1023 clientContext = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001024 with pytest.raises(Error):
1025 clientContext.load_verify_locations(tmpfile)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001026
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001027 def _load_verify_directory_locations_capath(self, capath):
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001028 """
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001029 Verify that if path to a directory containing certificate files is
1030 passed to ``Context.load_verify_locations`` for the ``capath``
1031 parameter, those certificates are used as trust roots for the purposes
1032 of verifying connections created using that ``Context``.
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001033 """
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001034 makedirs(capath)
Jean-Paul Calderone24dfb332011-05-04 18:10:26 -04001035 # Hash values computed manually with c_rehash to avoid depending on
1036 # c_rehash in the test suite. One is from OpenSSL 0.9.8, the other
1037 # from OpenSSL 1.0.0.
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001038 for name in [b'c7adac82.0', b'c3705638.0']:
Jean-Paul Calderone05826732015-04-12 11:38:49 -04001039 cafile = join_bytes_or_unicode(capath, name)
1040 with open(cafile, 'w') as fObj:
1041 fObj.write(cleartextCertificatePEM.decode('ascii'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001042
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001043 self._load_verify_locations_test(None, capath)
1044
Alex Chan532b79e2017-01-24 15:14:52 +00001045 def test_load_verify_directory_bytes_capath(self, tmpfile):
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001046 """
Alex Chan532b79e2017-01-24 15:14:52 +00001047 `Context.load_verify_locations` accepts a directory name as a `bytes`
1048 instance and uses the certificates within for verification purposes.
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001049 """
1050 self._load_verify_directory_locations_capath(
Alex Chan532b79e2017-01-24 15:14:52 +00001051 tmpfile + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001052 )
1053
Alex Chan532b79e2017-01-24 15:14:52 +00001054 def test_load_verify_directory_unicode_capath(self, tmpfile):
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001055 """
Alex Chan532b79e2017-01-24 15:14:52 +00001056 `Context.load_verify_locations` accepts a directory name as a `unicode`
1057 instance and uses the certificates within for verification purposes.
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001058 """
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001059 self._load_verify_directory_locations_capath(
Alex Chan532b79e2017-01-24 15:14:52 +00001060 tmpfile.decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001061 )
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001062
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001063 def test_load_verify_locations_wrong_args(self):
1064 """
Alex Chan532b79e2017-01-24 15:14:52 +00001065 `Context.load_verify_locations` raises `TypeError` if with non-`str`
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001066 arguments.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001067 """
1068 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001069 with pytest.raises(TypeError):
1070 context.load_verify_locations(object())
1071 with pytest.raises(TypeError):
1072 context.load_verify_locations(object(), object())
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001073
Hynek Schlawack734d3022015-09-05 19:19:32 +02001074 @pytest.mark.skipif(
Paul Kehrer55fb3412017-06-29 18:44:08 -05001075 not platform.startswith("linux"),
1076 reason="Loading fallback paths is a linux-specific behavior to "
1077 "accommodate pyca/cryptography manylinux1 wheels"
1078 )
1079 def test_fallback_default_verify_paths(self, monkeypatch):
1080 """
1081 Test that we load certificates successfully on linux from the fallback
1082 path. To do this we set the _CRYPTOGRAPHY_MANYLINUX1_CA_FILE and
1083 _CRYPTOGRAPHY_MANYLINUX1_CA_DIR vars to be equal to whatever the
1084 current OpenSSL default is and we disable
1085 SSL_CTX_SET_default_verify_paths so that it can't find certs unless
1086 it loads via fallback.
1087 """
1088 context = Context(TLSv1_METHOD)
1089 monkeypatch.setattr(
1090 _lib, "SSL_CTX_set_default_verify_paths", lambda x: 1
1091 )
1092 monkeypatch.setattr(
1093 SSL,
1094 "_CRYPTOGRAPHY_MANYLINUX1_CA_FILE",
1095 _ffi.string(_lib.X509_get_default_cert_file())
1096 )
1097 monkeypatch.setattr(
1098 SSL,
1099 "_CRYPTOGRAPHY_MANYLINUX1_CA_DIR",
1100 _ffi.string(_lib.X509_get_default_cert_dir())
1101 )
1102 context.set_default_verify_paths()
1103 store = context.get_cert_store()
1104 sk_obj = _lib.X509_STORE_get0_objects(store._store)
1105 assert sk_obj != _ffi.NULL
1106 num = _lib.sk_X509_OBJECT_num(sk_obj)
1107 assert num != 0
1108
1109 def test_check_env_vars(self, monkeypatch):
1110 """
1111 Test that we return True/False appropriately if the env vars are set.
1112 """
1113 context = Context(TLSv1_METHOD)
1114 dir_var = "CUSTOM_DIR_VAR"
1115 file_var = "CUSTOM_FILE_VAR"
1116 assert context._check_env_vars_set(dir_var, file_var) is False
1117 monkeypatch.setenv(dir_var, "value")
1118 monkeypatch.setenv(file_var, "value")
1119 assert context._check_env_vars_set(dir_var, file_var) is True
1120 assert context._check_env_vars_set(dir_var, file_var) is True
1121
1122 def test_verify_no_fallback_if_env_vars_set(self, monkeypatch):
1123 """
1124 Test that we don't use the fallback path if env vars are set.
1125 """
1126 context = Context(TLSv1_METHOD)
1127 monkeypatch.setattr(
1128 _lib, "SSL_CTX_set_default_verify_paths", lambda x: 1
1129 )
1130 dir_env_var = _ffi.string(
1131 _lib.X509_get_default_cert_dir_env()
1132 ).decode("ascii")
1133 file_env_var = _ffi.string(
1134 _lib.X509_get_default_cert_file_env()
1135 ).decode("ascii")
1136 monkeypatch.setenv(dir_env_var, "value")
1137 monkeypatch.setenv(file_env_var, "value")
1138 context.set_default_verify_paths()
1139
1140 monkeypatch.setattr(
1141 context,
1142 "_fallback_default_verify_paths",
1143 raiser(SystemError)
1144 )
1145 context.set_default_verify_paths()
1146
1147 @pytest.mark.skipif(
Hynek Schlawack734d3022015-09-05 19:19:32 +02001148 platform == "win32",
1149 reason="set_default_verify_paths appears not to work on Windows. "
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -04001150 "See LP#404343 and LP#404344."
Hynek Schlawack734d3022015-09-05 19:19:32 +02001151 )
1152 def test_set_default_verify_paths(self):
1153 """
Alex Chan532b79e2017-01-24 15:14:52 +00001154 `Context.set_default_verify_paths` causes the platform-specific CA
1155 certificate locations to be used for verification purposes.
Hynek Schlawack734d3022015-09-05 19:19:32 +02001156 """
1157 # Testing this requires a server with a certificate signed by one
1158 # of the CAs in the platform CA location. Getting one of those
1159 # costs money. Fortunately (or unfortunately, depending on your
1160 # perspective), it's easy to think of a public server on the
1161 # internet which has such a certificate. Connecting to the network
1162 # in a unit test is bad, but it's the only way I can think of to
1163 # really test this. -exarkun
Hynek Schlawackbf887932015-10-21 17:13:47 +02001164 context = Context(SSLv23_METHOD)
Hynek Schlawack734d3022015-09-05 19:19:32 +02001165 context.set_default_verify_paths()
1166 context.set_verify(
1167 VERIFY_PEER,
1168 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001169
David Benjamin1fbe0642019-04-15 17:05:13 -05001170 client = socket_any_family()
Hynek Schlawackbf887932015-10-21 17:13:47 +02001171 client.connect(("encrypted.google.com", 443))
Hynek Schlawack734d3022015-09-05 19:19:32 +02001172 clientSSL = Connection(context, client)
1173 clientSSL.set_connect_state()
Alex Gaynor373926c2018-05-12 07:43:07 -04001174 clientSSL.set_tlsext_host_name(b"encrypted.google.com")
Hynek Schlawack734d3022015-09-05 19:19:32 +02001175 clientSSL.do_handshake()
1176 clientSSL.send(b"GET / HTTP/1.0\r\n\r\n")
Alex Chan532b79e2017-01-24 15:14:52 +00001177 assert clientSSL.recv(1024)
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05001178
Paul Kehrer55fb3412017-06-29 18:44:08 -05001179 def test_fallback_path_is_not_file_or_dir(self):
1180 """
1181 Test that when passed empty arrays or paths that do not exist no
1182 errors are raised.
1183 """
1184 context = Context(TLSv1_METHOD)
1185 context._fallback_default_verify_paths([], [])
1186 context._fallback_default_verify_paths(
1187 ["/not/a/file"], ["/not/a/dir"]
1188 )
1189
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001190 def test_add_extra_chain_cert_invalid_cert(self):
1191 """
Alex Chan532b79e2017-01-24 15:14:52 +00001192 `Context.add_extra_chain_cert` raises `TypeError` if called with an
1193 object which is not an instance of `X509`.
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001194 """
1195 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001196 with pytest.raises(TypeError):
1197 context.add_extra_chain_cert(object())
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001198
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001199 def _handshake_test(self, serverContext, clientContext):
1200 """
1201 Verify that a client and server created with the given contexts can
1202 successfully handshake and communicate.
1203 """
1204 serverSocket, clientSocket = socket_pair()
1205
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001206 server = Connection(serverContext, serverSocket)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001207 server.set_accept_state()
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001208
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001209 client = Connection(clientContext, clientSocket)
1210 client.set_connect_state()
1211
1212 # Make them talk to each other.
Alex Chan532b79e2017-01-24 15:14:52 +00001213 # interact_in_memory(client, server)
1214 for _ in range(3):
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001215 for s in [client, server]:
1216 try:
1217 s.do_handshake()
1218 except WantReadError:
1219 pass
1220
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001221 def test_set_verify_callback_connection_argument(self):
1222 """
1223 The first argument passed to the verify callback is the
Alex Chan532b79e2017-01-24 15:14:52 +00001224 `Connection` instance for which verification is taking place.
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001225 """
1226 serverContext = Context(TLSv1_METHOD)
1227 serverContext.use_privatekey(
1228 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1229 serverContext.use_certificate(
1230 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1231 serverConnection = Connection(serverContext, None)
1232
1233 class VerifyCallback(object):
1234 def callback(self, connection, *args):
1235 self.connection = connection
1236 return 1
1237
1238 verify = VerifyCallback()
1239 clientContext = Context(TLSv1_METHOD)
1240 clientContext.set_verify(VERIFY_PEER, verify.callback)
1241 clientConnection = Connection(clientContext, None)
1242 clientConnection.set_connect_state()
1243
Alex Chan532b79e2017-01-24 15:14:52 +00001244 handshake_in_memory(clientConnection, serverConnection)
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001245
Alex Chan532b79e2017-01-24 15:14:52 +00001246 assert verify.connection is clientConnection
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001247
Paul Kehrere7381862017-11-30 20:55:25 +08001248 def test_x509_in_verify_works(self):
1249 """
1250 We had a bug where the X509 cert instantiated in the callback wrapper
1251 didn't __init__ so it was missing objects needed when calling
1252 get_subject. This test sets up a handshake where we call get_subject
1253 on the cert provided to the verify callback.
1254 """
1255 serverContext = Context(TLSv1_METHOD)
1256 serverContext.use_privatekey(
1257 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1258 serverContext.use_certificate(
1259 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1260 serverConnection = Connection(serverContext, None)
1261
1262 def verify_cb_get_subject(conn, cert, errnum, depth, ok):
1263 assert cert.get_subject()
1264 return 1
1265
1266 clientContext = Context(TLSv1_METHOD)
1267 clientContext.set_verify(VERIFY_PEER, verify_cb_get_subject)
1268 clientConnection = Connection(clientContext, None)
1269 clientConnection.set_connect_state()
1270
1271 handshake_in_memory(clientConnection, serverConnection)
1272
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001273 def test_set_verify_callback_exception(self):
1274 """
Alex Chan532b79e2017-01-24 15:14:52 +00001275 If the verify callback passed to `Context.set_verify` raises an
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001276 exception, verification fails and the exception is propagated to the
Alex Chan532b79e2017-01-24 15:14:52 +00001277 caller of `Connection.do_handshake`.
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001278 """
Paul Kehrer7d5a3bf2019-01-21 12:24:02 -06001279 serverContext = Context(TLSv1_2_METHOD)
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001280 serverContext.use_privatekey(
1281 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1282 serverContext.use_certificate(
1283 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1284
Paul Kehrer7d5a3bf2019-01-21 12:24:02 -06001285 clientContext = Context(TLSv1_2_METHOD)
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001286
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001287 def verify_callback(*args):
1288 raise Exception("silly verify failure")
1289 clientContext.set_verify(VERIFY_PEER, verify_callback)
1290
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01001291 with pytest.raises(Exception) as exc:
1292 self._handshake_test(serverContext, clientContext)
1293
Alex Chan532b79e2017-01-24 15:14:52 +00001294 assert "silly verify failure" == str(exc.value)
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001295
Alex Chan532b79e2017-01-24 15:14:52 +00001296 def test_add_extra_chain_cert(self, tmpdir):
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001297 """
Alex Chan532b79e2017-01-24 15:14:52 +00001298 `Context.add_extra_chain_cert` accepts an `X509`
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001299 instance to add to the certificate chain.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001300
Alex Chan532b79e2017-01-24 15:14:52 +00001301 See `_create_certificate_chain` for the details of the
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001302 certificate chain tested.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001303
1304 The chain is tested by starting a server with scert and connecting
1305 to it with a client which trusts cacert and requires verification to
1306 succeed.
1307 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001308 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001309 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1310
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001311 # Dump the CA certificate to a file because that's the only way to load
1312 # it as a trusted CA in the client context.
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001313 for cert, name in [(cacert, 'ca.pem'),
1314 (icert, 'i.pem'),
1315 (scert, 's.pem')]:
Alex Chan532b79e2017-01-24 15:14:52 +00001316 with tmpdir.join(name).open('w') as f:
Hynek Schlawacke90680f2015-04-16 15:09:27 -04001317 f.write(dump_certificate(FILETYPE_PEM, cert).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001318
Hynek Schlawack1902c012015-04-16 15:06:41 -04001319 for key, name in [(cakey, 'ca.key'),
1320 (ikey, 'i.key'),
1321 (skey, 's.key')]:
Alex Chan532b79e2017-01-24 15:14:52 +00001322 with tmpdir.join(name).open('w') as f:
Hynek Schlawacke90680f2015-04-16 15:09:27 -04001323 f.write(dump_privatekey(FILETYPE_PEM, key).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001324
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001325 # Create the server context
1326 serverContext = Context(TLSv1_METHOD)
1327 serverContext.use_privatekey(skey)
1328 serverContext.use_certificate(scert)
Jean-Paul Calderone16cf03d2010-09-08 18:53:39 -04001329 # The client already has cacert, we only need to give them icert.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001330 serverContext.add_extra_chain_cert(icert)
1331
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001332 # Create the client
1333 clientContext = Context(TLSv1_METHOD)
1334 clientContext.set_verify(
1335 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Alex Chan532b79e2017-01-24 15:14:52 +00001336 clientContext.load_verify_locations(str(tmpdir.join("ca.pem")))
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001337
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001338 # Try it out.
1339 self._handshake_test(serverContext, clientContext)
1340
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001341 def _use_certificate_chain_file_test(self, certdir):
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001342 """
Alex Chan532b79e2017-01-24 15:14:52 +00001343 Verify that `Context.use_certificate_chain_file` reads a
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001344 certificate chain from a specified file.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001345
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001346 The chain is tested by starting a server with scert and connecting to
1347 it with a client which trusts cacert and requires verification to
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001348 succeed.
1349 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001350 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001351 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1352
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001353 makedirs(certdir)
1354
Jean-Paul Calderone05826732015-04-12 11:38:49 -04001355 chainFile = join_bytes_or_unicode(certdir, "chain.pem")
1356 caFile = join_bytes_or_unicode(certdir, "ca.pem")
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001357
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001358 # Write out the chain file.
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001359 with open(chainFile, 'wb') as fObj:
1360 # Most specific to least general.
1361 fObj.write(dump_certificate(FILETYPE_PEM, scert))
1362 fObj.write(dump_certificate(FILETYPE_PEM, icert))
1363 fObj.write(dump_certificate(FILETYPE_PEM, cacert))
1364
1365 with open(caFile, 'w') as fObj:
1366 fObj.write(dump_certificate(FILETYPE_PEM, cacert).decode('ascii'))
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001367
1368 serverContext = Context(TLSv1_METHOD)
1369 serverContext.use_certificate_chain_file(chainFile)
1370 serverContext.use_privatekey(skey)
1371
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001372 clientContext = Context(TLSv1_METHOD)
1373 clientContext.set_verify(
1374 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001375 clientContext.load_verify_locations(caFile)
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001376
1377 self._handshake_test(serverContext, clientContext)
1378
Alex Chan532b79e2017-01-24 15:14:52 +00001379 def test_use_certificate_chain_file_bytes(self, tmpfile):
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001380 """
1381 ``Context.use_certificate_chain_file`` accepts the name of a file (as
1382 an instance of ``bytes``) to specify additional certificates to use to
1383 construct and verify a trust chain.
1384 """
1385 self._use_certificate_chain_file_test(
Alex Chan532b79e2017-01-24 15:14:52 +00001386 tmpfile + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001387 )
1388
Alex Chan532b79e2017-01-24 15:14:52 +00001389 def test_use_certificate_chain_file_unicode(self, tmpfile):
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001390 """
1391 ``Context.use_certificate_chain_file`` accepts the name of a file (as
1392 an instance of ``unicode``) to specify additional certificates to use
1393 to construct and verify a trust chain.
1394 """
1395 self._use_certificate_chain_file_test(
Alex Chan532b79e2017-01-24 15:14:52 +00001396 tmpfile.decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001397 )
1398
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001399 def test_use_certificate_chain_file_wrong_args(self):
1400 """
Alex Chan532b79e2017-01-24 15:14:52 +00001401 `Context.use_certificate_chain_file` raises `TypeError` if passed a
1402 non-byte string single argument.
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001403 """
1404 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001405 with pytest.raises(TypeError):
1406 context.use_certificate_chain_file(object())
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001407
Alex Chan532b79e2017-01-24 15:14:52 +00001408 def test_use_certificate_chain_file_missing_file(self, tmpfile):
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001409 """
Alex Chan532b79e2017-01-24 15:14:52 +00001410 `Context.use_certificate_chain_file` raises `OpenSSL.SSL.Error` when
1411 passed a bad chain file name (for example, the name of a file which
1412 does not exist).
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001413 """
1414 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001415 with pytest.raises(Error):
1416 context.use_certificate_chain_file(tmpfile)
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001417
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001418 def test_set_verify_mode(self):
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001419 """
Alex Chan532b79e2017-01-24 15:14:52 +00001420 `Context.get_verify_mode` returns the verify mode flags previously
1421 passed to `Context.set_verify`.
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001422 """
1423 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001424 assert context.get_verify_mode() == 0
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001425 context.set_verify(
1426 VERIFY_PEER | VERIFY_CLIENT_ONCE, lambda *args: None)
Alex Chan532b79e2017-01-24 15:14:52 +00001427 assert context.get_verify_mode() == (VERIFY_PEER | VERIFY_CLIENT_ONCE)
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001428
Alex Chanfb078d82017-04-20 11:16:15 +01001429 @pytest.mark.parametrize('mode', [None, 1.0, object(), 'mode'])
1430 def test_set_verify_wrong_mode_arg(self, mode):
1431 """
1432 `Context.set_verify` raises `TypeError` if the first argument is
1433 not an integer.
1434 """
1435 context = Context(TLSv1_METHOD)
1436 with pytest.raises(TypeError):
1437 context.set_verify(mode=mode, callback=lambda *args: None)
1438
1439 @pytest.mark.parametrize('callback', [None, 1.0, 'mode', ('foo', 'bar')])
1440 def test_set_verify_wrong_callable_arg(self, callback):
1441 """
Alex Gaynor40bc0f12018-05-14 14:06:16 -04001442 `Context.set_verify` raises `TypeError` if the second argument
Alex Chanfb078d82017-04-20 11:16:15 +01001443 is not callable.
1444 """
1445 context = Context(TLSv1_METHOD)
1446 with pytest.raises(TypeError):
1447 context.set_verify(mode=VERIFY_PEER, callback=callback)
1448
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001449 def test_load_tmp_dh_wrong_args(self):
1450 """
Alex Chan532b79e2017-01-24 15:14:52 +00001451 `Context.load_tmp_dh` raises `TypeError` if called with a
1452 non-`str` argument.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001453 """
1454 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001455 with pytest.raises(TypeError):
1456 context.load_tmp_dh(object())
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001457
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001458 def test_load_tmp_dh_missing_file(self):
1459 """
Alex Chan532b79e2017-01-24 15:14:52 +00001460 `Context.load_tmp_dh` raises `OpenSSL.SSL.Error` if the
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001461 specified file does not exist.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001462 """
1463 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001464 with pytest.raises(Error):
1465 context.load_tmp_dh(b"hello")
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001466
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001467 def _load_tmp_dh_test(self, dhfilename):
Jean-Paul Calderone4e0c43f2015-04-13 10:15:17 -04001468 """
1469 Verify that calling ``Context.load_tmp_dh`` with the given filename
1470 does not raise an exception.
1471 """
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001472 context = Context(TLSv1_METHOD)
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001473 with open(dhfilename, "w") as dhfile:
1474 dhfile.write(dhparam)
1475
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001476 context.load_tmp_dh(dhfilename)
1477 # XXX What should I assert here? -exarkun
1478
Alex Chan532b79e2017-01-24 15:14:52 +00001479 def test_load_tmp_dh_bytes(self, tmpfile):
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001480 """
Alex Chan532b79e2017-01-24 15:14:52 +00001481 `Context.load_tmp_dh` loads Diffie-Hellman parameters from the
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001482 specified file (given as ``bytes``).
1483 """
1484 self._load_tmp_dh_test(
Alex Chan532b79e2017-01-24 15:14:52 +00001485 tmpfile + NON_ASCII.encode(getfilesystemencoding()),
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001486 )
1487
Alex Chan532b79e2017-01-24 15:14:52 +00001488 def test_load_tmp_dh_unicode(self, tmpfile):
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001489 """
Alex Chan532b79e2017-01-24 15:14:52 +00001490 `Context.load_tmp_dh` loads Diffie-Hellman parameters from the
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001491 specified file (given as ``unicode``).
1492 """
1493 self._load_tmp_dh_test(
Alex Chan532b79e2017-01-24 15:14:52 +00001494 tmpfile.decode(getfilesystemencoding()) + NON_ASCII,
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001495 )
1496
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001497 def test_set_tmp_ecdh(self):
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001498 """
Alex Chan532b79e2017-01-24 15:14:52 +00001499 `Context.set_tmp_ecdh` sets the elliptic curve for Diffie-Hellman to
1500 the specified curve.
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001501 """
1502 context = Context(TLSv1_METHOD)
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001503 for curve in get_elliptic_curves():
Hynek Schlawacka07fa8c2015-10-17 10:15:28 +02001504 if curve.name.startswith(u"Oakley-"):
Hynek Schlawack7408aff2015-10-17 09:51:16 +02001505 # Setting Oakley-EC2N-4 and Oakley-EC2N-3 adds
1506 # ('bignum routines', 'BN_mod_inverse', 'no inverse') to the
1507 # error queue on OpenSSL 1.0.2.
1508 continue
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001509 # The only easily "assertable" thing is that it does not raise an
1510 # exception.
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001511 context.set_tmp_ecdh(curve)
Alex Gaynor12dc0842014-01-17 12:51:31 -06001512
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001513 def test_set_session_cache_mode_wrong_args(self):
1514 """
Alex Chan532b79e2017-01-24 15:14:52 +00001515 `Context.set_session_cache_mode` raises `TypeError` if called with
1516 a non-integer argument.
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001517 called with other than one integer argument.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001518 """
1519 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001520 with pytest.raises(TypeError):
1521 context.set_session_cache_mode(object())
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001522
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001523 def test_session_cache_mode(self):
1524 """
Alex Chan532b79e2017-01-24 15:14:52 +00001525 `Context.set_session_cache_mode` specifies how sessions are cached.
1526 The setting can be retrieved via `Context.get_session_cache_mode`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001527 """
1528 context = Context(TLSv1_METHOD)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001529 context.set_session_cache_mode(SESS_CACHE_OFF)
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001530 off = context.set_session_cache_mode(SESS_CACHE_BOTH)
Alex Chan532b79e2017-01-24 15:14:52 +00001531 assert SESS_CACHE_OFF == off
1532 assert SESS_CACHE_BOTH == context.get_session_cache_mode()
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001533
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001534 def test_get_cert_store(self):
1535 """
Alex Chan532b79e2017-01-24 15:14:52 +00001536 `Context.get_cert_store` returns a `X509Store` instance.
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001537 """
1538 context = Context(TLSv1_METHOD)
1539 store = context.get_cert_store()
Alex Chan532b79e2017-01-24 15:14:52 +00001540 assert isinstance(store, X509Store)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001541
Jeremy Lainé02261ad2018-05-16 18:33:25 +02001542 def test_set_tlsext_use_srtp_not_bytes(self):
1543 """
1544 `Context.set_tlsext_use_srtp' enables negotiating SRTP keying material.
1545
1546 It raises a TypeError if the list of profiles is not a byte string.
1547 """
1548 context = Context(TLSv1_METHOD)
1549 with pytest.raises(TypeError):
1550 context.set_tlsext_use_srtp(text_type('SRTP_AES128_CM_SHA1_80'))
1551
1552 def test_set_tlsext_use_srtp_invalid_profile(self):
1553 """
1554 `Context.set_tlsext_use_srtp' enables negotiating SRTP keying material.
1555
1556 It raises an Error if the call to OpenSSL fails.
1557 """
1558 context = Context(TLSv1_METHOD)
1559 with pytest.raises(Error):
1560 context.set_tlsext_use_srtp(b'SRTP_BOGUS')
1561
1562 def test_set_tlsext_use_srtp_valid(self):
1563 """
1564 `Context.set_tlsext_use_srtp' enables negotiating SRTP keying material.
1565
1566 It does not return anything.
1567 """
1568 context = Context(TLSv1_METHOD)
1569 assert context.set_tlsext_use_srtp(b'SRTP_AES128_CM_SHA1_80') is None
1570
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001571
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001572class TestServerNameCallback(object):
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001573 """
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001574 Tests for `Context.set_tlsext_servername_callback` and its
1575 interaction with `Connection`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001576 """
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001577 def test_old_callback_forgotten(self):
1578 """
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001579 If `Context.set_tlsext_servername_callback` is used to specify
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001580 a new callback, the one it replaces is dereferenced.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001581 """
Alex Chanfb078d82017-04-20 11:16:15 +01001582 def callback(connection): # pragma: no cover
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001583 pass
1584
Alex Chanfb078d82017-04-20 11:16:15 +01001585 def replacement(connection): # pragma: no cover
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001586 pass
1587
1588 context = Context(TLSv1_METHOD)
1589 context.set_tlsext_servername_callback(callback)
1590
1591 tracker = ref(callback)
1592 del callback
1593
1594 context.set_tlsext_servername_callback(replacement)
Jean-Paul Calderoned4033eb2014-01-11 08:21:46 -05001595
1596 # One run of the garbage collector happens to work on CPython. PyPy
1597 # doesn't collect the underlying object until a second run for whatever
1598 # reason. That's fine, it still demonstrates our code has properly
1599 # dropped the reference.
1600 collect()
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001601 collect()
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001602
1603 callback = tracker()
1604 if callback is not None:
1605 referrers = get_referrers(callback)
Alex Chanfb078d82017-04-20 11:16:15 +01001606 if len(referrers) > 1: # pragma: nocover
1607 pytest.fail("Some references remain: %r" % (referrers,))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001608
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001609 def test_no_servername(self):
1610 """
1611 When a client specifies no server name, the callback passed to
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001612 `Context.set_tlsext_servername_callback` is invoked and the
1613 result of `Connection.get_servername` is `None`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001614 """
1615 args = []
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001616
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001617 def servername(conn):
1618 args.append((conn, conn.get_servername()))
1619 context = Context(TLSv1_METHOD)
1620 context.set_tlsext_servername_callback(servername)
1621
1622 # Lose our reference to it. The Context is responsible for keeping it
1623 # alive now.
1624 del servername
1625 collect()
1626
1627 # Necessary to actually accept the connection
1628 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001629 context.use_certificate(
1630 load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001631
1632 # Do a little connection to trigger the logic
1633 server = Connection(context, None)
1634 server.set_accept_state()
1635
1636 client = Connection(Context(TLSv1_METHOD), None)
1637 client.set_connect_state()
1638
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001639 interact_in_memory(server, client)
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001640
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001641 assert args == [(server, None)]
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001642
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001643 def test_servername(self):
1644 """
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001645 When a client specifies a server name in its hello message, the
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001646 callback passed to `Contexts.set_tlsext_servername_callback` is
1647 invoked and the result of `Connection.get_servername` is that
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001648 server name.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001649 """
1650 args = []
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001651
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001652 def servername(conn):
1653 args.append((conn, conn.get_servername()))
1654 context = Context(TLSv1_METHOD)
1655 context.set_tlsext_servername_callback(servername)
1656
1657 # Necessary to actually accept the connection
1658 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001659 context.use_certificate(
1660 load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001661
1662 # Do a little connection to trigger the logic
1663 server = Connection(context, None)
1664 server.set_accept_state()
1665
1666 client = Connection(Context(TLSv1_METHOD), None)
1667 client.set_connect_state()
Alex Gaynore7f51982016-09-11 11:48:14 -04001668 client.set_tlsext_host_name(b"foo1.example.com")
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001669
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001670 interact_in_memory(server, client)
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001671
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001672 assert args == [(server, b"foo1.example.com")]
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001673
1674
Paul Kehrer4d575902019-02-26 21:42:12 +08001675@pytest.mark.skipif(
1676 not _lib.Cryptography_HAS_NEXTPROTONEG, reason="NPN is not available"
1677)
Alex Chan9e08b3e2016-11-10 12:18:54 +00001678class TestNextProtoNegotiation(object):
Cory Benfield84a121e2014-03-31 20:30:25 +01001679 """
1680 Test for Next Protocol Negotiation in PyOpenSSL.
1681 """
Alex Chan9e08b3e2016-11-10 12:18:54 +00001682 def test_npn_success(self):
1683 """
1684 Tests that clients and servers that agree on the negotiated next
1685 protocol can correct establish a connection, and that the agreed
1686 protocol is reported by the connections.
1687 """
1688 advertise_args = []
1689 select_args = []
1690
1691 def advertise(conn):
1692 advertise_args.append((conn,))
1693 return [b'http/1.1', b'spdy/2']
1694
1695 def select(conn, options):
1696 select_args.append((conn, options))
1697 return b'spdy/2'
1698
1699 server_context = Context(TLSv1_METHOD)
1700 server_context.set_npn_advertise_callback(advertise)
1701
1702 client_context = Context(TLSv1_METHOD)
1703 client_context.set_npn_select_callback(select)
1704
1705 # Necessary to actually accept the connection
1706 server_context.use_privatekey(
1707 load_privatekey(FILETYPE_PEM, server_key_pem))
1708 server_context.use_certificate(
1709 load_certificate(FILETYPE_PEM, server_cert_pem))
1710
1711 # Do a little connection to trigger the logic
1712 server = Connection(server_context, None)
1713 server.set_accept_state()
1714
1715 client = Connection(client_context, None)
1716 client.set_connect_state()
1717
1718 interact_in_memory(server, client)
1719
1720 assert advertise_args == [(server,)]
1721 assert select_args == [(client, [b'http/1.1', b'spdy/2'])]
1722
1723 assert server.get_next_proto_negotiated() == b'spdy/2'
1724 assert client.get_next_proto_negotiated() == b'spdy/2'
1725
1726 def test_npn_client_fail(self):
1727 """
1728 Tests that when clients and servers cannot agree on what protocol
1729 to use next that the TLS connection does not get established.
1730 """
1731 advertise_args = []
1732 select_args = []
1733
1734 def advertise(conn):
1735 advertise_args.append((conn,))
1736 return [b'http/1.1', b'spdy/2']
1737
1738 def select(conn, options):
1739 select_args.append((conn, options))
1740 return b''
1741
1742 server_context = Context(TLSv1_METHOD)
1743 server_context.set_npn_advertise_callback(advertise)
1744
1745 client_context = Context(TLSv1_METHOD)
1746 client_context.set_npn_select_callback(select)
1747
1748 # Necessary to actually accept the connection
1749 server_context.use_privatekey(
1750 load_privatekey(FILETYPE_PEM, server_key_pem))
1751 server_context.use_certificate(
1752 load_certificate(FILETYPE_PEM, server_cert_pem))
1753
1754 # Do a little connection to trigger the logic
1755 server = Connection(server_context, None)
1756 server.set_accept_state()
1757
1758 client = Connection(client_context, None)
1759 client.set_connect_state()
1760
1761 # If the client doesn't return anything, the connection will fail.
1762 with pytest.raises(Error):
1763 interact_in_memory(server, client)
1764
1765 assert advertise_args == [(server,)]
1766 assert select_args == [(client, [b'http/1.1', b'spdy/2'])]
1767
1768 def test_npn_select_error(self):
1769 """
1770 Test that we can handle exceptions in the select callback. If
1771 select fails it should be fatal to the connection.
1772 """
1773 advertise_args = []
1774
1775 def advertise(conn):
1776 advertise_args.append((conn,))
1777 return [b'http/1.1', b'spdy/2']
1778
1779 def select(conn, options):
1780 raise TypeError
1781
1782 server_context = Context(TLSv1_METHOD)
1783 server_context.set_npn_advertise_callback(advertise)
1784
1785 client_context = Context(TLSv1_METHOD)
1786 client_context.set_npn_select_callback(select)
1787
1788 # Necessary to actually accept the connection
1789 server_context.use_privatekey(
1790 load_privatekey(FILETYPE_PEM, server_key_pem))
1791 server_context.use_certificate(
1792 load_certificate(FILETYPE_PEM, server_cert_pem))
1793
1794 # Do a little connection to trigger the logic
1795 server = Connection(server_context, None)
1796 server.set_accept_state()
1797
1798 client = Connection(client_context, None)
1799 client.set_connect_state()
1800
1801 # If the callback throws an exception it should be raised here.
1802 with pytest.raises(TypeError):
1803 interact_in_memory(server, client)
1804 assert advertise_args == [(server,), ]
1805
1806 def test_npn_advertise_error(self):
1807 """
1808 Test that we can handle exceptions in the advertise callback. If
1809 advertise fails no NPN is advertised to the client.
1810 """
1811 select_args = []
1812
1813 def advertise(conn):
1814 raise TypeError
1815
1816 def select(conn, options): # pragma: nocover
Cory Benfieldba1820d2015-04-13 17:39:12 -04001817 """
Alex Chan9e08b3e2016-11-10 12:18:54 +00001818 Assert later that no args are actually appended.
Cory Benfieldba1820d2015-04-13 17:39:12 -04001819 """
Alex Chan9e08b3e2016-11-10 12:18:54 +00001820 select_args.append((conn, options))
1821 return b''
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001822
Alex Chan9e08b3e2016-11-10 12:18:54 +00001823 server_context = Context(TLSv1_METHOD)
1824 server_context.set_npn_advertise_callback(advertise)
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001825
Alex Chan9e08b3e2016-11-10 12:18:54 +00001826 client_context = Context(TLSv1_METHOD)
1827 client_context.set_npn_select_callback(select)
Cory Benfield84a121e2014-03-31 20:30:25 +01001828
Alex Chan9e08b3e2016-11-10 12:18:54 +00001829 # Necessary to actually accept the connection
1830 server_context.use_privatekey(
1831 load_privatekey(FILETYPE_PEM, server_key_pem))
1832 server_context.use_certificate(
1833 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield84a121e2014-03-31 20:30:25 +01001834
Alex Chan9e08b3e2016-11-10 12:18:54 +00001835 # Do a little connection to trigger the logic
1836 server = Connection(server_context, None)
1837 server.set_accept_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001838
Alex Chan9e08b3e2016-11-10 12:18:54 +00001839 client = Connection(client_context, None)
1840 client.set_connect_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001841
Alex Chan9e08b3e2016-11-10 12:18:54 +00001842 # If the client doesn't return anything, the connection will fail.
1843 with pytest.raises(TypeError):
1844 interact_in_memory(server, client)
1845 assert select_args == []
Cory Benfield0ea76e72015-03-22 09:05:28 +00001846
1847
Alex Chanec1e32d2016-11-10 14:11:45 +00001848class TestApplicationLayerProtoNegotiation(object):
Cory Benfield12eae892014-06-07 15:42:56 +01001849 """
1850 Tests for ALPN in PyOpenSSL.
1851 """
Alex Gaynor77debda2020-04-07 13:40:59 -04001852 def test_alpn_success(self):
1853 """
1854 Clients and servers that agree on the negotiated ALPN protocol can
1855 correct establish a connection, and the agreed protocol is reported
1856 by the connections.
1857 """
1858 select_args = []
Cory Benfield12eae892014-06-07 15:42:56 +01001859
Alex Gaynor77debda2020-04-07 13:40:59 -04001860 def select(conn, options):
1861 select_args.append((conn, options))
1862 return b'spdy/2'
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001863
Alex Gaynor77debda2020-04-07 13:40:59 -04001864 client_context = Context(TLSv1_METHOD)
1865 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfield12eae892014-06-07 15:42:56 +01001866
Alex Gaynor77debda2020-04-07 13:40:59 -04001867 server_context = Context(TLSv1_METHOD)
1868 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01001869
Alex Gaynor77debda2020-04-07 13:40:59 -04001870 # Necessary to actually accept the connection
1871 server_context.use_privatekey(
1872 load_privatekey(FILETYPE_PEM, server_key_pem))
1873 server_context.use_certificate(
1874 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield12eae892014-06-07 15:42:56 +01001875
Alex Gaynor77debda2020-04-07 13:40:59 -04001876 # Do a little connection to trigger the logic
1877 server = Connection(server_context, None)
1878 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001879
Alex Gaynor77debda2020-04-07 13:40:59 -04001880 client = Connection(client_context, None)
1881 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001882
Alex Gaynor77debda2020-04-07 13:40:59 -04001883 interact_in_memory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001884
Alex Gaynor77debda2020-04-07 13:40:59 -04001885 assert select_args == [(server, [b'http/1.1', b'spdy/2'])]
1886
1887 assert server.get_alpn_proto_negotiated() == b'spdy/2'
1888 assert client.get_alpn_proto_negotiated() == b'spdy/2'
1889
1890 def test_alpn_set_on_connection(self):
1891 """
1892 The same as test_alpn_success, but setting the ALPN protocols on
1893 the connection rather than the context.
1894 """
1895 select_args = []
1896
1897 def select(conn, options):
1898 select_args.append((conn, options))
1899 return b'spdy/2'
1900
1901 # Setup the client context but don't set any ALPN protocols.
1902 client_context = Context(TLSv1_METHOD)
1903
1904 server_context = Context(TLSv1_METHOD)
1905 server_context.set_alpn_select_callback(select)
1906
1907 # Necessary to actually accept the connection
1908 server_context.use_privatekey(
1909 load_privatekey(FILETYPE_PEM, server_key_pem))
1910 server_context.use_certificate(
1911 load_certificate(FILETYPE_PEM, server_cert_pem))
1912
1913 # Do a little connection to trigger the logic
1914 server = Connection(server_context, None)
1915 server.set_accept_state()
1916
1917 # Set the ALPN protocols on the client connection.
1918 client = Connection(client_context, None)
1919 client.set_alpn_protos([b'http/1.1', b'spdy/2'])
1920 client.set_connect_state()
1921
1922 interact_in_memory(server, client)
1923
1924 assert select_args == [(server, [b'http/1.1', b'spdy/2'])]
1925
1926 assert server.get_alpn_proto_negotiated() == b'spdy/2'
1927 assert client.get_alpn_proto_negotiated() == b'spdy/2'
1928
1929 def test_alpn_server_fail(self):
1930 """
1931 When clients and servers cannot agree on what protocol to use next
1932 the TLS connection does not get established.
1933 """
1934 select_args = []
1935
1936 def select(conn, options):
1937 select_args.append((conn, options))
1938 return b''
1939
1940 client_context = Context(TLSv1_METHOD)
1941 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
1942
1943 server_context = Context(TLSv1_METHOD)
1944 server_context.set_alpn_select_callback(select)
1945
1946 # Necessary to actually accept the connection
1947 server_context.use_privatekey(
1948 load_privatekey(FILETYPE_PEM, server_key_pem))
1949 server_context.use_certificate(
1950 load_certificate(FILETYPE_PEM, server_cert_pem))
1951
1952 # Do a little connection to trigger the logic
1953 server = Connection(server_context, None)
1954 server.set_accept_state()
1955
1956 client = Connection(client_context, None)
1957 client.set_connect_state()
1958
1959 # If the client doesn't return anything, the connection will fail.
1960 with pytest.raises(Error):
Alex Chanec1e32d2016-11-10 14:11:45 +00001961 interact_in_memory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001962
Alex Gaynor77debda2020-04-07 13:40:59 -04001963 assert select_args == [(server, [b'http/1.1', b'spdy/2'])]
Cory Benfielde46fa842015-04-13 16:50:49 -04001964
Alex Gaynor77debda2020-04-07 13:40:59 -04001965 def test_alpn_no_server_overlap(self):
1966 """
1967 A server can allow a TLS handshake to complete without
1968 agreeing to an application protocol by returning
1969 ``NO_OVERLAPPING_PROTOCOLS``.
1970 """
1971 refusal_args = []
Cory Benfield12eae892014-06-07 15:42:56 +01001972
Alex Gaynor77debda2020-04-07 13:40:59 -04001973 def refusal(conn, options):
1974 refusal_args.append((conn, options))
1975 return NO_OVERLAPPING_PROTOCOLS
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001976
Alex Gaynor77debda2020-04-07 13:40:59 -04001977 client_context = Context(SSLv23_METHOD)
1978 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfield12eae892014-06-07 15:42:56 +01001979
Alex Gaynor77debda2020-04-07 13:40:59 -04001980 server_context = Context(SSLv23_METHOD)
1981 server_context.set_alpn_select_callback(refusal)
Cory Benfield12eae892014-06-07 15:42:56 +01001982
Alex Gaynor77debda2020-04-07 13:40:59 -04001983 # Necessary to actually accept the connection
1984 server_context.use_privatekey(
1985 load_privatekey(FILETYPE_PEM, server_key_pem))
1986 server_context.use_certificate(
1987 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield12eae892014-06-07 15:42:56 +01001988
Alex Gaynor77debda2020-04-07 13:40:59 -04001989 # Do a little connection to trigger the logic
1990 server = Connection(server_context, None)
1991 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001992
Alex Gaynor77debda2020-04-07 13:40:59 -04001993 client = Connection(client_context, None)
1994 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001995
Alex Gaynor77debda2020-04-07 13:40:59 -04001996 # Do the dance.
1997 interact_in_memory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001998
Alex Gaynor77debda2020-04-07 13:40:59 -04001999 assert refusal_args == [(server, [b'http/1.1', b'spdy/2'])]
2000
2001 assert client.get_alpn_proto_negotiated() == b''
2002
2003 def test_alpn_select_cb_returns_invalid_value(self):
2004 """
2005 If the ALPN selection callback returns anything other than
2006 a bytestring or ``NO_OVERLAPPING_PROTOCOLS``, a
2007 :py:exc:`TypeError` is raised.
2008 """
2009 invalid_cb_args = []
2010
2011 def invalid_cb(conn, options):
2012 invalid_cb_args.append((conn, options))
2013 return u"can't return unicode"
2014
2015 client_context = Context(SSLv23_METHOD)
2016 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
2017
2018 server_context = Context(SSLv23_METHOD)
2019 server_context.set_alpn_select_callback(invalid_cb)
2020
2021 # Necessary to actually accept the connection
2022 server_context.use_privatekey(
2023 load_privatekey(FILETYPE_PEM, server_key_pem))
2024 server_context.use_certificate(
2025 load_certificate(FILETYPE_PEM, server_cert_pem))
2026
2027 # Do a little connection to trigger the logic
2028 server = Connection(server_context, None)
2029 server.set_accept_state()
2030
2031 client = Connection(client_context, None)
2032 client.set_connect_state()
2033
2034 # Do the dance.
2035 with pytest.raises(TypeError):
Alex Chanec1e32d2016-11-10 14:11:45 +00002036 interact_in_memory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01002037
Alex Gaynor77debda2020-04-07 13:40:59 -04002038 assert invalid_cb_args == [(server, [b'http/1.1', b'spdy/2'])]
Cory Benfield12eae892014-06-07 15:42:56 +01002039
Alex Gaynor77debda2020-04-07 13:40:59 -04002040 assert client.get_alpn_proto_negotiated() == b''
Cory Benfield12eae892014-06-07 15:42:56 +01002041
Alex Gaynor77debda2020-04-07 13:40:59 -04002042 def test_alpn_no_server(self):
2043 """
2044 When clients and servers cannot agree on what protocol to use next
2045 because the server doesn't offer ALPN, no protocol is negotiated.
2046 """
2047 client_context = Context(TLSv1_METHOD)
2048 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002049
Alex Gaynor77debda2020-04-07 13:40:59 -04002050 server_context = Context(TLSv1_METHOD)
Cory Benfield12eae892014-06-07 15:42:56 +01002051
Alex Gaynor77debda2020-04-07 13:40:59 -04002052 # Necessary to actually accept the connection
2053 server_context.use_privatekey(
2054 load_privatekey(FILETYPE_PEM, server_key_pem))
2055 server_context.use_certificate(
2056 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield12eae892014-06-07 15:42:56 +01002057
Alex Gaynor77debda2020-04-07 13:40:59 -04002058 # Do a little connection to trigger the logic
2059 server = Connection(server_context, None)
2060 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01002061
Alex Gaynor77debda2020-04-07 13:40:59 -04002062 client = Connection(client_context, None)
2063 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01002064
Alex Gaynor77debda2020-04-07 13:40:59 -04002065 # Do the dance.
2066 interact_in_memory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01002067
Alex Gaynor77debda2020-04-07 13:40:59 -04002068 assert client.get_alpn_proto_negotiated() == b''
Cory Benfield12eae892014-06-07 15:42:56 +01002069
Alex Gaynor77debda2020-04-07 13:40:59 -04002070 def test_alpn_callback_exception(self):
2071 """
2072 We can handle exceptions in the ALPN select callback.
2073 """
2074 select_args = []
Cory Benfield12eae892014-06-07 15:42:56 +01002075
Alex Gaynor77debda2020-04-07 13:40:59 -04002076 def select(conn, options):
2077 select_args.append((conn, options))
2078 raise TypeError()
Cory Benfield12eae892014-06-07 15:42:56 +01002079
Alex Gaynor77debda2020-04-07 13:40:59 -04002080 client_context = Context(TLSv1_METHOD)
2081 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Mark Williams5d890a02019-11-17 19:56:26 -08002082
Alex Gaynor77debda2020-04-07 13:40:59 -04002083 server_context = Context(TLSv1_METHOD)
2084 server_context.set_alpn_select_callback(select)
Mark Williams5d890a02019-11-17 19:56:26 -08002085
Alex Gaynor77debda2020-04-07 13:40:59 -04002086 # Necessary to actually accept the connection
2087 server_context.use_privatekey(
2088 load_privatekey(FILETYPE_PEM, server_key_pem))
2089 server_context.use_certificate(
2090 load_certificate(FILETYPE_PEM, server_cert_pem))
Mark Williams5d890a02019-11-17 19:56:26 -08002091
Alex Gaynor77debda2020-04-07 13:40:59 -04002092 # Do a little connection to trigger the logic
2093 server = Connection(server_context, None)
2094 server.set_accept_state()
Mark Williams5d890a02019-11-17 19:56:26 -08002095
Alex Gaynor77debda2020-04-07 13:40:59 -04002096 client = Connection(client_context, None)
2097 client.set_connect_state()
Mark Williams5d890a02019-11-17 19:56:26 -08002098
Alex Gaynor77debda2020-04-07 13:40:59 -04002099 with pytest.raises(TypeError):
Mark Williams5d890a02019-11-17 19:56:26 -08002100 interact_in_memory(server, client)
Alex Gaynor77debda2020-04-07 13:40:59 -04002101 assert select_args == [(server, [b'http/1.1', b'spdy/2'])]
Cory Benfield0f7b04c2015-04-13 17:51:12 -04002102
Cory Benfieldf1177e72015-04-12 09:11:49 -04002103
Alex Chanec1e32d2016-11-10 14:11:45 +00002104class TestSession(object):
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05002105 """
2106 Unit tests for :py:obj:`OpenSSL.SSL.Session`.
2107 """
2108 def test_construction(self):
2109 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002110 :py:class:`Session` can be constructed with no arguments, creating
2111 a new instance of that type.
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05002112 """
2113 new_session = Session()
Alex Chanec1e32d2016-11-10 14:11:45 +00002114 assert isinstance(new_session, Session)
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05002115
2116
Alex Chan1c0cb662017-01-30 07:13:30 +00002117class TestConnection(object):
Rick Deane15b1472009-07-09 15:53:42 -05002118 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002119 Unit tests for `OpenSSL.SSL.Connection`.
Rick Deane15b1472009-07-09 15:53:42 -05002120 """
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04002121 # XXX get_peer_certificate -> None
2122 # XXX sock_shutdown
2123 # XXX master_key -> TypeError
2124 # XXX server_random -> TypeError
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04002125 # XXX connect -> TypeError
2126 # XXX connect_ex -> TypeError
2127 # XXX set_connect_state -> TypeError
2128 # XXX set_accept_state -> TypeError
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04002129 # XXX do_handshake -> TypeError
2130 # XXX bio_read -> TypeError
2131 # XXX recv -> TypeError
2132 # XXX send -> TypeError
2133 # XXX bio_write -> TypeError
2134
Rick Deane15b1472009-07-09 15:53:42 -05002135 def test_type(self):
2136 """
Alex Gaynor01f90a12019-02-07 09:14:48 -05002137 `Connection` can be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -05002138 """
2139 ctx = Context(TLSv1_METHOD)
Alex Chan1c0cb662017-01-30 07:13:30 +00002140 assert is_consistent_type(Connection, 'Connection', ctx, None)
Rick Deane15b1472009-07-09 15:53:42 -05002141
Alex Chanfb078d82017-04-20 11:16:15 +01002142 @pytest.mark.parametrize('bad_context', [object(), 'context', None, 1])
2143 def test_wrong_args(self, bad_context):
2144 """
2145 `Connection.__init__` raises `TypeError` if called with a non-`Context`
2146 instance argument.
2147 """
2148 with pytest.raises(TypeError):
2149 Connection(bad_context)
2150
Daniel Holth079c9632019-11-17 22:45:52 -05002151 @pytest.mark.parametrize('bad_bio', [object(), None, 1, [1, 2, 3]])
2152 def test_bio_write_wrong_args(self, bad_bio):
2153 """
2154 `Connection.bio_write` raises `TypeError` if called with a non-bytes
2155 (or text) argument.
2156 """
2157 context = Context(TLSv1_METHOD)
2158 connection = Connection(context, None)
2159 with pytest.raises(TypeError):
2160 connection.bio_write(bad_bio)
2161
2162 def test_bio_write(self):
2163 """
2164 `Connection.bio_write` does not raise if called with bytes or
2165 bytearray, warns if called with text.
2166 """
2167 context = Context(TLSv1_METHOD)
2168 connection = Connection(context, None)
2169 connection.bio_write(b'xy')
2170 connection.bio_write(bytearray(b'za'))
2171 with pytest.warns(DeprecationWarning):
2172 connection.bio_write(u'deprecated')
2173
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002174 def test_get_context(self):
2175 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002176 `Connection.get_context` returns the `Context` instance used to
2177 construct the `Connection` instance.
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002178 """
2179 context = Context(TLSv1_METHOD)
2180 connection = Connection(context, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002181 assert connection.get_context() is context
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002182
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002183 def test_set_context_wrong_args(self):
2184 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002185 `Connection.set_context` raises `TypeError` if called with a
Alex Chanfb078d82017-04-20 11:16:15 +01002186 non-`Context` instance argument.
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002187 """
2188 ctx = Context(TLSv1_METHOD)
2189 connection = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002190 with pytest.raises(TypeError):
2191 connection.set_context(object())
2192 with pytest.raises(TypeError):
2193 connection.set_context("hello")
2194 with pytest.raises(TypeError):
2195 connection.set_context(1)
2196 assert ctx is connection.get_context()
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002197
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002198 def test_set_context(self):
2199 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002200 `Connection.set_context` specifies a new `Context` instance to be
2201 used for the connection.
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002202 """
2203 original = Context(SSLv23_METHOD)
2204 replacement = Context(TLSv1_METHOD)
2205 connection = Connection(original, None)
2206 connection.set_context(replacement)
Alex Chan1c0cb662017-01-30 07:13:30 +00002207 assert replacement is connection.get_context()
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002208 # Lose our references to the contexts, just in case the Connection
2209 # isn't properly managing its own contributions to their reference
2210 # counts.
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002211 del original, replacement
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002212 collect()
2213
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002214 def test_set_tlsext_host_name_wrong_args(self):
2215 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002216 If `Connection.set_tlsext_host_name` is called with a non-byte string
2217 argument or a byte string with an embedded NUL, `TypeError` is raised.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002218 """
2219 conn = Connection(Context(TLSv1_METHOD), None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002220 with pytest.raises(TypeError):
2221 conn.set_tlsext_host_name(object())
2222 with pytest.raises(TypeError):
2223 conn.set_tlsext_host_name(b"with\0null")
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002224
Hugo van Kemenade60827f82019-08-30 00:39:35 +03002225 if not PY2:
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002226 # On Python 3.x, don't accidentally implicitly convert from text.
Alex Chan1c0cb662017-01-30 07:13:30 +00002227 with pytest.raises(TypeError):
2228 conn.set_tlsext_host_name(b"example.com".decode("ascii"))
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04002229
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002230 def test_pending(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002231 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002232 `Connection.pending` returns the number of bytes available for
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002233 immediate read.
2234 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002235 connection = Connection(Context(TLSv1_METHOD), None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002236 assert connection.pending() == 0
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002237
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002238 def test_peek(self):
2239 """
Hynek Schlawack3bcf3152017-02-18 08:25:34 +01002240 `Connection.recv` peeks into the connection if `socket.MSG_PEEK` is
2241 passed.
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002242 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002243 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002244 server.send(b'xy')
Alex Chan1c0cb662017-01-30 07:13:30 +00002245 assert client.recv(2, MSG_PEEK) == b'xy'
2246 assert client.recv(2, MSG_PEEK) == b'xy'
2247 assert client.recv(2) == b'xy'
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002248
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002249 def test_connect_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002250 """
Hynek Schlawack3bcf3152017-02-18 08:25:34 +01002251 `Connection.connect` raises `TypeError` if called with a non-address
2252 argument.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002253 """
David Benjamin1fbe0642019-04-15 17:05:13 -05002254 connection = Connection(Context(TLSv1_METHOD), socket_any_family())
Alex Chan1c0cb662017-01-30 07:13:30 +00002255 with pytest.raises(TypeError):
2256 connection.connect(None)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002257
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002258 def test_connect_refused(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002259 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002260 `Connection.connect` raises `socket.error` if the underlying socket
2261 connect method raises it.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002262 """
David Benjamin1fbe0642019-04-15 17:05:13 -05002263 client = socket_any_family()
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002264 context = Context(TLSv1_METHOD)
2265 clientSSL = Connection(context, client)
Alex Gaynor122717b2015-09-05 14:14:18 -04002266 # pytest.raises here doesn't work because of a bug in py.test on Python
2267 # 2.6: https://github.com/pytest-dev/pytest/issues/988
Alex Gaynore69c2782015-09-05 14:07:48 -04002268 try:
David Benjamin1fbe0642019-04-15 17:05:13 -05002269 clientSSL.connect((loopback_address(client), 1))
Alex Gaynore69c2782015-09-05 14:07:48 -04002270 except error as e:
Alex Gaynor20a4c082015-09-05 14:24:15 -04002271 exc = e
2272 assert exc.args[0] == ECONNREFUSED
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002273
2274 def test_connect(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002275 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002276 `Connection.connect` establishes a connection to the specified address.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002277 """
David Benjamin1fbe0642019-04-15 17:05:13 -05002278 port = socket_any_family()
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002279 port.bind(('', 0))
2280 port.listen(3)
2281
David Benjamin1fbe0642019-04-15 17:05:13 -05002282 clientSSL = Connection(Context(TLSv1_METHOD), socket(port.family))
2283 clientSSL.connect((loopback_address(port), port.getsockname()[1]))
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002284 # XXX An assertion? Or something?
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002285
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002286 @pytest.mark.skipif(
2287 platform == "darwin",
2288 reason="connect_ex sometimes causes a kernel panic on OS X 10.6.4"
2289 )
2290 def test_connect_ex(self):
2291 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002292 If there is a connection error, `Connection.connect_ex` returns the
2293 errno instead of raising an exception.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002294 """
David Benjamin1fbe0642019-04-15 17:05:13 -05002295 port = socket_any_family()
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002296 port.bind(('', 0))
2297 port.listen(3)
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002298
David Benjamin1fbe0642019-04-15 17:05:13 -05002299 clientSSL = Connection(Context(TLSv1_METHOD), socket(port.family))
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002300 clientSSL.setblocking(False)
2301 result = clientSSL.connect_ex(port.getsockname())
2302 expected = (EINPROGRESS, EWOULDBLOCK)
Alex Chan1c0cb662017-01-30 07:13:30 +00002303 assert result in expected
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002304
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002305 def test_accept(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002306 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002307 `Connection.accept` accepts a pending connection attempt and returns a
2308 tuple of a new `Connection` (the accepted client) and the address the
2309 connection originated from.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002310 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002311 ctx = Context(TLSv1_METHOD)
2312 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2313 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
David Benjamin1fbe0642019-04-15 17:05:13 -05002314 port = socket_any_family()
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002315 portSSL = Connection(ctx, port)
2316 portSSL.bind(('', 0))
2317 portSSL.listen(3)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002318
David Benjamin1fbe0642019-04-15 17:05:13 -05002319 clientSSL = Connection(Context(TLSv1_METHOD), socket(port.family))
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002320
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002321 # Calling portSSL.getsockname() here to get the server IP address
2322 # sounds great, but frequently fails on Windows.
David Benjamin1fbe0642019-04-15 17:05:13 -05002323 clientSSL.connect((loopback_address(port), portSSL.getsockname()[1]))
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002324
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002325 serverSSL, address = portSSL.accept()
2326
Alex Chan1c0cb662017-01-30 07:13:30 +00002327 assert isinstance(serverSSL, Connection)
2328 assert serverSSL.get_context() is ctx
2329 assert address == clientSSL.getsockname()
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002330
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002331 def test_shutdown_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002332 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002333 `Connection.set_shutdown` raises `TypeError` if called with arguments
2334 other than integers.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002335 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002336 connection = Connection(Context(TLSv1_METHOD), None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002337 with pytest.raises(TypeError):
2338 connection.set_shutdown(None)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002339
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002340 def test_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002341 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002342 `Connection.shutdown` performs an SSL-level connection shutdown.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002343 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002344 server, client = loopback()
2345 assert not server.shutdown()
2346 assert server.get_shutdown() == SENT_SHUTDOWN
2347 with pytest.raises(ZeroReturnError):
2348 client.recv(1024)
2349 assert client.get_shutdown() == RECEIVED_SHUTDOWN
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04002350 client.shutdown()
Alex Chan1c0cb662017-01-30 07:13:30 +00002351 assert client.get_shutdown() == (SENT_SHUTDOWN | RECEIVED_SHUTDOWN)
2352 with pytest.raises(ZeroReturnError):
2353 server.recv(1024)
2354 assert server.get_shutdown() == (SENT_SHUTDOWN | RECEIVED_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002355
Paul Aurichc85e0862015-01-08 08:34:33 -08002356 def test_shutdown_closed(self):
2357 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002358 If the underlying socket is closed, `Connection.shutdown` propagates
2359 the write error from the low level write call.
Paul Aurichc85e0862015-01-08 08:34:33 -08002360 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002361 server, client = loopback()
Paul Aurichc85e0862015-01-08 08:34:33 -08002362 server.sock_shutdown(2)
Alex Chan1c0cb662017-01-30 07:13:30 +00002363 with pytest.raises(SysCallError) as exc:
2364 server.shutdown()
Alex Chanfb078d82017-04-20 11:16:15 +01002365 if platform == "win32":
2366 assert exc.value.args[0] == ESHUTDOWN
2367 else:
2368 assert exc.value.args[0] == EPIPE
Paul Aurichc85e0862015-01-08 08:34:33 -08002369
Glyph89389472015-04-14 17:29:26 -04002370 def test_shutdown_truncated(self):
Glyph6064ec32015-04-14 16:38:22 -04002371 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002372 If the underlying connection is truncated, `Connection.shutdown`
2373 raises an `Error`.
Glyph6064ec32015-04-14 16:38:22 -04002374 """
Glyph89389472015-04-14 17:29:26 -04002375 server_ctx = Context(TLSv1_METHOD)
2376 client_ctx = Context(TLSv1_METHOD)
2377 server_ctx.use_privatekey(
2378 load_privatekey(FILETYPE_PEM, server_key_pem))
2379 server_ctx.use_certificate(
2380 load_certificate(FILETYPE_PEM, server_cert_pem))
2381 server = Connection(server_ctx, None)
2382 client = Connection(client_ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002383 handshake_in_memory(client, server)
2384 assert not server.shutdown()
2385 with pytest.raises(WantReadError):
2386 server.shutdown()
Glyph89389472015-04-14 17:29:26 -04002387 server.bio_shutdown()
Alex Chan1c0cb662017-01-30 07:13:30 +00002388 with pytest.raises(Error):
2389 server.shutdown()
Glyph6064ec32015-04-14 16:38:22 -04002390
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002391 def test_set_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002392 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002393 `Connection.set_shutdown` sets the state of the SSL connection
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002394 shutdown process.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002395 """
David Benjamin1fbe0642019-04-15 17:05:13 -05002396 connection = Connection(Context(TLSv1_METHOD), socket_any_family())
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002397 connection.set_shutdown(RECEIVED_SHUTDOWN)
Alex Chan1c0cb662017-01-30 07:13:30 +00002398 assert connection.get_shutdown() == RECEIVED_SHUTDOWN
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002399
kjavaf248592015-09-07 12:14:01 +01002400 def test_state_string(self):
2401 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002402 `Connection.state_string` verbosely describes the current state of
2403 the `Connection`.
kjavaf248592015-09-07 12:14:01 +01002404 """
Hynek Schlawackb0274ce2015-10-16 19:56:26 +02002405 server, client = socket_pair()
Alex Chan1c0cb662017-01-30 07:13:30 +00002406 server = loopback_server_factory(server)
2407 client = loopback_client_factory(client)
kjavaf248592015-09-07 12:14:01 +01002408
Alex Gaynor5af32d02016-09-24 01:52:21 -04002409 assert server.get_state_string() in [
2410 b"before/accept initialization", b"before SSL initialization"
2411 ]
2412 assert client.get_state_string() in [
2413 b"before/connect initialization", b"before SSL initialization"
2414 ]
kjavaf248592015-09-07 12:14:01 +01002415
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002416 def test_app_data(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002417 """
2418 Any object can be set as app data by passing it to
Alex Chan1c0cb662017-01-30 07:13:30 +00002419 `Connection.set_app_data` and later retrieved with
2420 `Connection.get_app_data`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002421 """
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002422 conn = Connection(Context(TLSv1_METHOD), None)
Todd Chapman4f73e4f2015-08-27 11:26:43 -04002423 assert None is conn.get_app_data()
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002424 app_data = object()
2425 conn.set_app_data(app_data)
Todd Chapman4f73e4f2015-08-27 11:26:43 -04002426 assert conn.get_app_data() is app_data
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002427
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002428 def test_makefile(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002429 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002430 `Connection.makefile` is not implemented and calling that
2431 method raises `NotImplementedError`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002432 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002433 conn = Connection(Context(TLSv1_METHOD), None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002434 with pytest.raises(NotImplementedError):
2435 conn.makefile()
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002436
Jeremy Lainé460a19d2018-05-16 19:44:19 +02002437 def test_get_certificate(self):
2438 """
2439 `Connection.get_certificate` returns the local certificate.
2440 """
2441 chain = _create_certificate_chain()
2442 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
2443
2444 context = Context(TLSv1_METHOD)
2445 context.use_certificate(scert)
2446 client = Connection(context, None)
2447 cert = client.get_certificate()
2448 assert cert is not None
2449 assert "Server Certificate" == cert.get_subject().CN
2450
2451 def test_get_certificate_none(self):
2452 """
2453 `Connection.get_certificate` returns the local certificate.
2454
2455 If there is no certificate, it returns None.
2456 """
2457 context = Context(TLSv1_METHOD)
2458 client = Connection(context, None)
2459 cert = client.get_certificate()
2460 assert cert is None
2461
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002462 def test_get_peer_cert_chain(self):
2463 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002464 `Connection.get_peer_cert_chain` returns a list of certificates
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002465 which the connected server returned for the certification verification.
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002466 """
2467 chain = _create_certificate_chain()
2468 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
2469
2470 serverContext = Context(TLSv1_METHOD)
2471 serverContext.use_privatekey(skey)
2472 serverContext.use_certificate(scert)
2473 serverContext.add_extra_chain_cert(icert)
2474 serverContext.add_extra_chain_cert(cacert)
2475 server = Connection(serverContext, None)
2476 server.set_accept_state()
2477
2478 # Create the client
2479 clientContext = Context(TLSv1_METHOD)
2480 clientContext.set_verify(VERIFY_NONE, verify_cb)
2481 client = Connection(clientContext, None)
2482 client.set_connect_state()
2483
Alex Chan1c0cb662017-01-30 07:13:30 +00002484 interact_in_memory(client, server)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002485
2486 chain = client.get_peer_cert_chain()
Alex Chan1c0cb662017-01-30 07:13:30 +00002487 assert len(chain) == 3
2488 assert "Server Certificate" == chain[0].get_subject().CN
2489 assert "Intermediate Certificate" == chain[1].get_subject().CN
2490 assert "Authority Certificate" == chain[2].get_subject().CN
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002491
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002492 def test_get_peer_cert_chain_none(self):
2493 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002494 `Connection.get_peer_cert_chain` returns `None` if the peer sends
2495 no certificate chain.
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002496 """
2497 ctx = Context(TLSv1_METHOD)
2498 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2499 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
2500 server = Connection(ctx, None)
2501 server.set_accept_state()
2502 client = Connection(Context(TLSv1_METHOD), None)
2503 client.set_connect_state()
Alex Chan1c0cb662017-01-30 07:13:30 +00002504 interact_in_memory(client, server)
2505 assert None is server.get_peer_cert_chain()
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002506
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002507 def test_get_session_unconnected(self):
2508 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002509 `Connection.get_session` returns `None` when used with an object
2510 which has not been connected.
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002511 """
2512 ctx = Context(TLSv1_METHOD)
2513 server = Connection(ctx, None)
2514 session = server.get_session()
Alex Chan1c0cb662017-01-30 07:13:30 +00002515 assert None is session
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002516
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002517 def test_server_get_session(self):
2518 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002519 On the server side of a connection, `Connection.get_session` returns a
2520 `Session` instance representing the SSL session for that connection.
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002521 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002522 server, client = loopback()
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002523 session = server.get_session()
Alex Chan1c0cb662017-01-30 07:13:30 +00002524 assert isinstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002525
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002526 def test_client_get_session(self):
2527 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002528 On the client side of a connection, `Connection.get_session`
2529 returns a `Session` instance representing the SSL session for
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002530 that connection.
2531 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002532 server, client = loopback()
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002533 session = client.get_session()
Alex Chan1c0cb662017-01-30 07:13:30 +00002534 assert isinstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002535
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002536 def test_set_session_wrong_args(self):
2537 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002538 `Connection.set_session` raises `TypeError` if called with an object
2539 that is not an instance of `Session`.
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002540 """
2541 ctx = Context(TLSv1_METHOD)
2542 connection = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002543 with pytest.raises(TypeError):
2544 connection.set_session(123)
2545 with pytest.raises(TypeError):
2546 connection.set_session("hello")
2547 with pytest.raises(TypeError):
2548 connection.set_session(object())
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002549
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002550 def test_client_set_session(self):
2551 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002552 `Connection.set_session`, when used prior to a connection being
2553 established, accepts a `Session` instance and causes an attempt to
2554 re-use the session it represents when the SSL handshake is performed.
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002555 """
2556 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2557 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
Paul Kehrer7d5a3bf2019-01-21 12:24:02 -06002558 ctx = Context(TLSv1_2_METHOD)
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002559 ctx.use_privatekey(key)
2560 ctx.use_certificate(cert)
2561 ctx.set_session_id("unity-test")
2562
2563 def makeServer(socket):
2564 server = Connection(ctx, socket)
2565 server.set_accept_state()
2566 return server
2567
Alex Chan1c0cb662017-01-30 07:13:30 +00002568 originalServer, originalClient = loopback(
2569 server_factory=makeServer)
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002570 originalSession = originalClient.get_session()
2571
2572 def makeClient(socket):
Alex Chan1c0cb662017-01-30 07:13:30 +00002573 client = loopback_client_factory(socket)
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002574 client.set_session(originalSession)
2575 return client
Alex Chan1c0cb662017-01-30 07:13:30 +00002576 resumedServer, resumedClient = loopback(
2577 server_factory=makeServer,
2578 client_factory=makeClient)
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002579
2580 # This is a proxy: in general, we have no access to any unique
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002581 # identifier for the session (new enough versions of OpenSSL expose
2582 # a hash which could be usable, but "new enough" is very, very new).
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002583 # Instead, exploit the fact that the master key is re-used if the
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002584 # session is re-used. As long as the master key for the two
2585 # connections is the same, the session was re-used!
Alex Chan1c0cb662017-01-30 07:13:30 +00002586 assert originalServer.master_key() == resumedServer.master_key()
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002587
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002588 def test_set_session_wrong_method(self):
2589 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002590 If `Connection.set_session` is passed a `Session` instance associated
2591 with a context using a different SSL method than the `Connection`
2592 is using, a `OpenSSL.SSL.Error` is raised.
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002593 """
Alex Gaynor5af32d02016-09-24 01:52:21 -04002594 # Make this work on both OpenSSL 1.0.0, which doesn't support TLSv1.2
2595 # and also on OpenSSL 1.1.0 which doesn't support SSLv3. (SSL_ST_INIT
2596 # is a way to check for 1.1.0)
Alex Gaynoraa32e712017-06-29 20:56:12 -07002597 if SSL_ST_INIT is None:
2598 v1 = TLSv1_2_METHOD
2599 v2 = TLSv1_METHOD
2600 elif hasattr(_lib, "SSLv3_method"):
Alex Gaynor5af32d02016-09-24 01:52:21 -04002601 v1 = TLSv1_METHOD
2602 v2 = SSLv3_METHOD
2603 else:
Alex Gaynoraa32e712017-06-29 20:56:12 -07002604 pytest.skip("Test requires either OpenSSL 1.1.0 or SSLv3")
Alex Gaynor5af32d02016-09-24 01:52:21 -04002605
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002606 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2607 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
Alex Gaynor5af32d02016-09-24 01:52:21 -04002608 ctx = Context(v1)
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002609 ctx.use_privatekey(key)
2610 ctx.use_certificate(cert)
2611 ctx.set_session_id("unity-test")
2612
2613 def makeServer(socket):
2614 server = Connection(ctx, socket)
2615 server.set_accept_state()
2616 return server
2617
Alex Gaynor5af32d02016-09-24 01:52:21 -04002618 def makeOriginalClient(socket):
2619 client = Connection(Context(v1), socket)
2620 client.set_connect_state()
2621 return client
2622
Alex Chan1c0cb662017-01-30 07:13:30 +00002623 originalServer, originalClient = loopback(
2624 server_factory=makeServer, client_factory=makeOriginalClient)
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002625 originalSession = originalClient.get_session()
2626
2627 def makeClient(socket):
2628 # Intentionally use a different, incompatible method here.
Alex Gaynor5af32d02016-09-24 01:52:21 -04002629 client = Connection(Context(v2), socket)
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002630 client.set_connect_state()
2631 client.set_session(originalSession)
2632 return client
2633
Alex Chan1c0cb662017-01-30 07:13:30 +00002634 with pytest.raises(Error):
2635 loopback(client_factory=makeClient, server_factory=makeServer)
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002636
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002637 def test_wantWriteError(self):
2638 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002639 `Connection` methods which generate output raise
2640 `OpenSSL.SSL.WantWriteError` if writing to the connection's BIO
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002641 fail indicating a should-write state.
2642 """
2643 client_socket, server_socket = socket_pair()
2644 # Fill up the client's send buffer so Connection won't be able to write
Jean-Paul Calderonebbff8b92014-03-22 14:20:30 -04002645 # anything. Only write a single byte at a time so we can be sure we
2646 # completely fill the buffer. Even though the socket API is allowed to
2647 # signal a short write via its return value it seems this doesn't
2648 # always happen on all platforms (FreeBSD and OS X particular) for the
2649 # very last bit of available buffer space.
2650 msg = b"x"
caternb2777a42018-08-09 15:38:13 -04002651 for i in range(1024 * 1024 * 64):
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002652 try:
2653 client_socket.send(msg)
2654 except error as e:
2655 if e.errno == EWOULDBLOCK:
2656 break
2657 raise
2658 else:
Alex Chan1c0cb662017-01-30 07:13:30 +00002659 pytest.fail(
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002660 "Failed to fill socket buffer, cannot test BIO want write")
2661
2662 ctx = Context(TLSv1_METHOD)
2663 conn = Connection(ctx, client_socket)
2664 # Client's speak first, so make it an SSL client
2665 conn.set_connect_state()
Alex Chan1c0cb662017-01-30 07:13:30 +00002666 with pytest.raises(WantWriteError):
2667 conn.do_handshake()
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002668
2669 # XXX want_read
2670
Fedor Brunner416f4a12014-03-28 13:18:38 +01002671 def test_get_finished_before_connect(self):
Fedor Brunner5747b932014-03-05 14:22:34 +01002672 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002673 `Connection.get_finished` returns `None` before TLS handshake
2674 is completed.
Fedor Brunner5747b932014-03-05 14:22:34 +01002675 """
Fedor Brunner5747b932014-03-05 14:22:34 +01002676 ctx = Context(TLSv1_METHOD)
2677 connection = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002678 assert connection.get_finished() is None
Fedor Brunner416f4a12014-03-28 13:18:38 +01002679
2680 def test_get_peer_finished_before_connect(self):
2681 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002682 `Connection.get_peer_finished` returns `None` before TLS handshake
2683 is completed.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002684 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002685 ctx = Context(TLSv1_METHOD)
2686 connection = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002687 assert connection.get_peer_finished() is None
Fedor Brunner5747b932014-03-05 14:22:34 +01002688
Fedor Brunner416f4a12014-03-28 13:18:38 +01002689 def test_get_finished(self):
2690 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002691 `Connection.get_finished` method returns the TLS Finished message send
2692 from client, or server. Finished messages are send during
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002693 TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002694 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002695 server, client = loopback()
Fedor Brunner416f4a12014-03-28 13:18:38 +01002696
Alex Chan1c0cb662017-01-30 07:13:30 +00002697 assert server.get_finished() is not None
2698 assert len(server.get_finished()) > 0
Fedor Brunner416f4a12014-03-28 13:18:38 +01002699
2700 def test_get_peer_finished(self):
2701 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002702 `Connection.get_peer_finished` method returns the TLS Finished
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002703 message received from client, or server. Finished messages are send
2704 during TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002705 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002706 server, client = loopback()
Fedor Brunner416f4a12014-03-28 13:18:38 +01002707
Alex Chan1c0cb662017-01-30 07:13:30 +00002708 assert server.get_peer_finished() is not None
2709 assert len(server.get_peer_finished()) > 0
Fedor Brunner5747b932014-03-05 14:22:34 +01002710
Fedor Brunner416f4a12014-03-28 13:18:38 +01002711 def test_tls_finished_message_symmetry(self):
2712 """
Hynek Schlawackdddd1112015-09-05 21:12:30 +02002713 The TLS Finished message send by server must be the TLS Finished
2714 message received by client.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002715
Hynek Schlawackdddd1112015-09-05 21:12:30 +02002716 The TLS Finished message send by client must be the TLS Finished
2717 message received by server.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002718 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002719 server, client = loopback()
Fedor Brunner416f4a12014-03-28 13:18:38 +01002720
Alex Chan1c0cb662017-01-30 07:13:30 +00002721 assert server.get_finished() == client.get_peer_finished()
2722 assert client.get_finished() == server.get_peer_finished()
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002723
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002724 def test_get_cipher_name_before_connect(self):
2725 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002726 `Connection.get_cipher_name` returns `None` if no connection
2727 has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002728 """
2729 ctx = Context(TLSv1_METHOD)
2730 conn = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002731 assert conn.get_cipher_name() is None
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002732
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002733 def test_get_cipher_name(self):
2734 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002735 `Connection.get_cipher_name` returns a `unicode` string giving the
2736 name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002737 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002738 server, client = loopback()
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002739 server_cipher_name, client_cipher_name = \
2740 server.get_cipher_name(), client.get_cipher_name()
2741
Alex Chan1c0cb662017-01-30 07:13:30 +00002742 assert isinstance(server_cipher_name, text_type)
2743 assert isinstance(client_cipher_name, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002744
Alex Chan1c0cb662017-01-30 07:13:30 +00002745 assert server_cipher_name == client_cipher_name
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002746
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002747 def test_get_cipher_version_before_connect(self):
2748 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002749 `Connection.get_cipher_version` returns `None` if no connection
2750 has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002751 """
2752 ctx = Context(TLSv1_METHOD)
2753 conn = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002754 assert conn.get_cipher_version() is None
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002755
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002756 def test_get_cipher_version(self):
2757 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002758 `Connection.get_cipher_version` returns a `unicode` string giving
2759 the protocol name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002760 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002761 server, client = loopback()
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002762 server_cipher_version, client_cipher_version = \
2763 server.get_cipher_version(), client.get_cipher_version()
2764
Alex Chan1c0cb662017-01-30 07:13:30 +00002765 assert isinstance(server_cipher_version, text_type)
2766 assert isinstance(client_cipher_version, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002767
Alex Chan1c0cb662017-01-30 07:13:30 +00002768 assert server_cipher_version == client_cipher_version
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002769
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002770 def test_get_cipher_bits_before_connect(self):
2771 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002772 `Connection.get_cipher_bits` returns `None` if no connection has
2773 been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002774 """
2775 ctx = Context(TLSv1_METHOD)
2776 conn = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002777 assert conn.get_cipher_bits() is None
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002778
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002779 def test_get_cipher_bits(self):
2780 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002781 `Connection.get_cipher_bits` returns the number of secret bits
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002782 of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002783 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002784 server, client = loopback()
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002785 server_cipher_bits, client_cipher_bits = \
2786 server.get_cipher_bits(), client.get_cipher_bits()
2787
Alex Chan1c0cb662017-01-30 07:13:30 +00002788 assert isinstance(server_cipher_bits, int)
2789 assert isinstance(client_cipher_bits, int)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002790
Alex Chan1c0cb662017-01-30 07:13:30 +00002791 assert server_cipher_bits == client_cipher_bits
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002792
Jim Shaverabff1882015-05-27 09:15:55 -04002793 def test_get_protocol_version_name(self):
2794 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002795 `Connection.get_protocol_version_name()` returns a string giving the
2796 protocol version of the current connection.
Jim Shaverabff1882015-05-27 09:15:55 -04002797 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002798 server, client = loopback()
Jim Shaverabff1882015-05-27 09:15:55 -04002799 client_protocol_version_name = client.get_protocol_version_name()
2800 server_protocol_version_name = server.get_protocol_version_name()
2801
Alex Chan1c0cb662017-01-30 07:13:30 +00002802 assert isinstance(server_protocol_version_name, text_type)
2803 assert isinstance(client_protocol_version_name, text_type)
Jim Shaverabff1882015-05-27 09:15:55 -04002804
Alex Chan1c0cb662017-01-30 07:13:30 +00002805 assert server_protocol_version_name == client_protocol_version_name
Jim Shaverabff1882015-05-27 09:15:55 -04002806
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002807 def test_get_protocol_version(self):
2808 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002809 `Connection.get_protocol_version()` returns an integer
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002810 giving the protocol version of the current connection.
2811 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002812 server, client = loopback()
Jim Shaver85a4dff2015-04-27 17:42:46 -04002813 client_protocol_version = client.get_protocol_version()
2814 server_protocol_version = server.get_protocol_version()
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002815
Alex Chan1c0cb662017-01-30 07:13:30 +00002816 assert isinstance(server_protocol_version, int)
2817 assert isinstance(client_protocol_version, int)
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002818
Alex Chan1c0cb662017-01-30 07:13:30 +00002819 assert server_protocol_version == client_protocol_version
2820
2821 def test_wantReadError(self):
2822 """
2823 `Connection.bio_read` raises `OpenSSL.SSL.WantReadError` if there are
2824 no bytes available to be read from the BIO.
2825 """
2826 ctx = Context(TLSv1_METHOD)
2827 conn = Connection(ctx, None)
2828 with pytest.raises(WantReadError):
2829 conn.bio_read(1024)
2830
Alex Chanfb078d82017-04-20 11:16:15 +01002831 @pytest.mark.parametrize('bufsize', [1.0, None, object(), 'bufsize'])
2832 def test_bio_read_wrong_args(self, bufsize):
2833 """
2834 `Connection.bio_read` raises `TypeError` if passed a non-integer
2835 argument.
2836 """
2837 ctx = Context(TLSv1_METHOD)
2838 conn = Connection(ctx, None)
2839 with pytest.raises(TypeError):
2840 conn.bio_read(bufsize)
2841
Alex Chan1c0cb662017-01-30 07:13:30 +00002842 def test_buffer_size(self):
2843 """
2844 `Connection.bio_read` accepts an integer giving the maximum number
2845 of bytes to read and return.
2846 """
2847 ctx = Context(TLSv1_METHOD)
2848 conn = Connection(ctx, None)
2849 conn.set_connect_state()
2850 try:
2851 conn.do_handshake()
2852 except WantReadError:
2853 pass
2854 data = conn.bio_read(2)
2855 assert 2 == len(data)
2856
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002857
Alex Chanb7480992017-01-30 14:04:47 +00002858class TestConnectionGetCipherList(object):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002859 """
Alex Chanb7480992017-01-30 14:04:47 +00002860 Tests for `Connection.get_cipher_list`.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002861 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002862 def test_result(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002863 """
Alex Chanb7480992017-01-30 14:04:47 +00002864 `Connection.get_cipher_list` returns a list of `bytes` giving the
2865 names of the ciphers which might be used.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002866 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002867 connection = Connection(Context(TLSv1_METHOD), None)
2868 ciphers = connection.get_cipher_list()
Alex Chanb7480992017-01-30 14:04:47 +00002869 assert isinstance(ciphers, list)
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002870 for cipher in ciphers:
Alex Chanb7480992017-01-30 14:04:47 +00002871 assert isinstance(cipher, str)
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002872
2873
Maximilian Hils868dc3c2017-02-10 14:56:55 +01002874class VeryLarge(bytes):
2875 """
2876 Mock object so that we don't have to allocate 2**31 bytes
2877 """
2878 def __len__(self):
2879 return 2**31
2880
2881
Alex Chanb7480992017-01-30 14:04:47 +00002882class TestConnectionSend(object):
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002883 """
Alex Chanb7480992017-01-30 14:04:47 +00002884 Tests for `Connection.send`.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002885 """
2886 def test_wrong_args(self):
2887 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002888 When called with arguments other than string argument for its first
Alex Chanb7480992017-01-30 14:04:47 +00002889 parameter, `Connection.send` raises `TypeError`.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002890 """
2891 connection = Connection(Context(TLSv1_METHOD), None)
Alex Chanb7480992017-01-30 14:04:47 +00002892 with pytest.raises(TypeError):
2893 connection.send(object())
Daniel Holth079c9632019-11-17 22:45:52 -05002894 with pytest.raises(TypeError):
2895 connection.send([1, 2, 3])
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002896
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002897 def test_short_bytes(self):
2898 """
Alex Chanb7480992017-01-30 14:04:47 +00002899 When passed a short byte string, `Connection.send` transmits all of it
2900 and returns the number of bytes sent.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002901 """
Alex Chanb7480992017-01-30 14:04:47 +00002902 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002903 count = server.send(b'xy')
Alex Chanb7480992017-01-30 14:04:47 +00002904 assert count == 2
2905 assert client.recv(2) == b'xy'
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002906
Abraham Martinef063482015-03-25 14:06:24 +00002907 def test_text(self):
2908 """
Alex Chanb7480992017-01-30 14:04:47 +00002909 When passed a text, `Connection.send` transmits all of it and
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002910 returns the number of bytes sent. It also raises a DeprecationWarning.
Abraham Martinef063482015-03-25 14:06:24 +00002911 """
Alex Chanb7480992017-01-30 14:04:47 +00002912 server, client = loopback()
2913 with pytest.warns(DeprecationWarning) as w:
Abraham Martinef063482015-03-25 14:06:24 +00002914 simplefilter("always")
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002915 count = server.send(b"xy".decode("ascii"))
Alex Chanb7480992017-01-30 14:04:47 +00002916 assert (
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002917 "{0} for buf is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002918 WARNING_TYPE_EXPECTED
Alex Chanb7480992017-01-30 14:04:47 +00002919 ) == str(w[-1].message))
2920 assert count == 2
2921 assert client.recv(2) == b'xy'
Abraham Martinef063482015-03-25 14:06:24 +00002922
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002923 def test_short_memoryview(self):
2924 """
2925 When passed a memoryview onto a small number of bytes,
Alex Chanb7480992017-01-30 14:04:47 +00002926 `Connection.send` transmits all of them and returns the number
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002927 of bytes sent.
2928 """
Alex Chanb7480992017-01-30 14:04:47 +00002929 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002930 count = server.send(memoryview(b'xy'))
Alex Chanb7480992017-01-30 14:04:47 +00002931 assert count == 2
2932 assert client.recv(2) == b'xy'
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002933
Daniel Holth079c9632019-11-17 22:45:52 -05002934 def test_short_bytearray(self):
2935 """
2936 When passed a short bytearray, `Connection.send` transmits all of
2937 it and returns the number of bytes sent.
2938 """
2939 server, client = loopback()
2940 count = server.send(bytearray(b'xy'))
2941 assert count == 2
2942 assert client.recv(2) == b'xy'
2943
Hynek Schlawack8e94f1b2015-09-05 21:31:00 +02002944 @skip_if_py3
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002945 def test_short_buffer(self):
2946 """
2947 When passed a buffer containing a small number of bytes,
Alex Chanb7480992017-01-30 14:04:47 +00002948 `Connection.send` transmits all of them and returns the number
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002949 of bytes sent.
2950 """
Alex Chanb7480992017-01-30 14:04:47 +00002951 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002952 count = server.send(buffer(b'xy'))
Alex Chanb7480992017-01-30 14:04:47 +00002953 assert count == 2
2954 assert client.recv(2) == b'xy'
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02002955
Maximilian Hils868dc3c2017-02-10 14:56:55 +01002956 @pytest.mark.skipif(
2957 sys.maxsize < 2**31,
2958 reason="sys.maxsize < 2**31 - test requires 64 bit"
2959 )
2960 def test_buf_too_large(self):
2961 """
2962 When passed a buffer containing >= 2**31 bytes,
2963 `Connection.send` bails out as SSL_write only
2964 accepts an int for the buffer length.
2965 """
2966 connection = Connection(Context(TLSv1_METHOD), None)
2967 with pytest.raises(ValueError) as exc_info:
2968 connection.send(VeryLarge())
2969 exc_info.match(r"Cannot send more than .+ bytes at once")
2970
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05002971
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002972def _make_memoryview(size):
2973 """
2974 Create a new ``memoryview`` wrapped around a ``bytearray`` of the given
2975 size.
2976 """
2977 return memoryview(bytearray(size))
2978
2979
Alex Chanb7480992017-01-30 14:04:47 +00002980class TestConnectionRecvInto(object):
Cory Benfield62d10332014-06-15 10:03:41 +01002981 """
Alex Chanb7480992017-01-30 14:04:47 +00002982 Tests for `Connection.recv_into`.
Cory Benfield62d10332014-06-15 10:03:41 +01002983 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002984 def _no_length_test(self, factory):
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04002985 """
Alex Chanb7480992017-01-30 14:04:47 +00002986 Assert that when the given buffer is passed to `Connection.recv_into`,
2987 whatever bytes are available to be received that fit into that buffer
2988 are written into that buffer.
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04002989 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002990 output_buffer = factory(5)
2991
Alex Chanb7480992017-01-30 14:04:47 +00002992 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002993 server.send(b'xy')
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04002994
Alex Chanb7480992017-01-30 14:04:47 +00002995 assert client.recv_into(output_buffer) == 2
2996 assert output_buffer == bytearray(b'xy\x00\x00\x00')
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04002997
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002998 def test_bytearray_no_length(self):
Cory Benfield62d10332014-06-15 10:03:41 +01002999 """
Alex Chanb7480992017-01-30 14:04:47 +00003000 `Connection.recv_into` can be passed a `bytearray` instance and data
3001 in the receive buffer is written to it.
Cory Benfield62d10332014-06-15 10:03:41 +01003002 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003003 self._no_length_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01003004
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003005 def _respects_length_test(self, factory):
Cory Benfield62d10332014-06-15 10:03:41 +01003006 """
Alex Chanb7480992017-01-30 14:04:47 +00003007 Assert that when the given buffer is passed to `Connection.recv_into`
3008 along with a value for `nbytes` that is less than the size of that
3009 buffer, only `nbytes` bytes are written into the buffer.
Cory Benfield62d10332014-06-15 10:03:41 +01003010 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003011 output_buffer = factory(10)
3012
Alex Chanb7480992017-01-30 14:04:47 +00003013 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04003014 server.send(b'abcdefghij')
Cory Benfield62d10332014-06-15 10:03:41 +01003015
Alex Chanb7480992017-01-30 14:04:47 +00003016 assert client.recv_into(output_buffer, 5) == 5
3017 assert output_buffer == bytearray(b'abcde\x00\x00\x00\x00\x00')
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04003018
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04003019 def test_bytearray_respects_length(self):
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04003020 """
Alex Chanb7480992017-01-30 14:04:47 +00003021 When called with a `bytearray` instance, `Connection.recv_into`
3022 respects the `nbytes` parameter and doesn't copy in more than that
3023 number of bytes.
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04003024 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003025 self._respects_length_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01003026
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003027 def _doesnt_overfill_test(self, factory):
Cory Benfield62d10332014-06-15 10:03:41 +01003028 """
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04003029 Assert that if there are more bytes available to be read from the
3030 receive buffer than would fit into the buffer passed to
Alex Chanb7480992017-01-30 14:04:47 +00003031 `Connection.recv_into`, only as many as fit are written into it.
Cory Benfield62d10332014-06-15 10:03:41 +01003032 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003033 output_buffer = factory(5)
3034
Alex Chanb7480992017-01-30 14:04:47 +00003035 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04003036 server.send(b'abcdefghij')
Cory Benfield62d10332014-06-15 10:03:41 +01003037
Alex Chanb7480992017-01-30 14:04:47 +00003038 assert client.recv_into(output_buffer) == 5
3039 assert output_buffer == bytearray(b'abcde')
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04003040 rest = client.recv(5)
Alex Chanb7480992017-01-30 14:04:47 +00003041 assert b'fghij' == rest
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04003042
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04003043 def test_bytearray_doesnt_overfill(self):
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04003044 """
Alex Chanb7480992017-01-30 14:04:47 +00003045 When called with a `bytearray` instance, `Connection.recv_into`
3046 respects the size of the array and doesn't write more bytes into it
3047 than will fit.
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04003048 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003049 self._doesnt_overfill_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01003050
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04003051 def test_bytearray_really_doesnt_overfill(self):
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003052 """
Alex Chanb7480992017-01-30 14:04:47 +00003053 When called with a `bytearray` instance and an `nbytes` value that is
3054 too large, `Connection.recv_into` respects the size of the array and
3055 not the `nbytes` value and doesn't write more bytes into the buffer
3056 than will fit.
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003057 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003058 self._doesnt_overfill_test(bytearray)
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003059
Maximilian Hils1d95dea2015-08-17 19:27:20 +02003060 def test_peek(self):
Alex Chanb7480992017-01-30 14:04:47 +00003061 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04003062 server.send(b'xy')
Maximilian Hils1d95dea2015-08-17 19:27:20 +02003063
3064 for _ in range(2):
3065 output_buffer = bytearray(5)
Alex Chanb7480992017-01-30 14:04:47 +00003066 assert client.recv_into(output_buffer, flags=MSG_PEEK) == 2
3067 assert output_buffer == bytearray(b'xy\x00\x00\x00')
Maximilian Hils1d95dea2015-08-17 19:27:20 +02003068
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003069 def test_memoryview_no_length(self):
3070 """
Alex Chanb7480992017-01-30 14:04:47 +00003071 `Connection.recv_into` can be passed a `memoryview` instance and data
3072 in the receive buffer is written to it.
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003073 """
3074 self._no_length_test(_make_memoryview)
Maximilian Hils1d95dea2015-08-17 19:27:20 +02003075
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003076 def test_memoryview_respects_length(self):
3077 """
Alex Chanb7480992017-01-30 14:04:47 +00003078 When called with a `memoryview` instance, `Connection.recv_into`
3079 respects the ``nbytes`` parameter and doesn't copy more than that
3080 number of bytes in.
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003081 """
3082 self._respects_length_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01003083
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003084 def test_memoryview_doesnt_overfill(self):
3085 """
Alex Chanb7480992017-01-30 14:04:47 +00003086 When called with a `memoryview` instance, `Connection.recv_into`
3087 respects the size of the array and doesn't write more bytes into it
3088 than will fit.
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003089 """
3090 self._doesnt_overfill_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01003091
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003092 def test_memoryview_really_doesnt_overfill(self):
3093 """
Alex Chanb7480992017-01-30 14:04:47 +00003094 When called with a `memoryview` instance and an `nbytes` value that is
3095 too large, `Connection.recv_into` respects the size of the array and
3096 not the `nbytes` value and doesn't write more bytes into the buffer
3097 than will fit.
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003098 """
3099 self._doesnt_overfill_test(_make_memoryview)
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003100
Cory Benfield62d10332014-06-15 10:03:41 +01003101
Alex Chanb7480992017-01-30 14:04:47 +00003102class TestConnectionSendall(object):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003103 """
Alex Chanb7480992017-01-30 14:04:47 +00003104 Tests for `Connection.sendall`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003105 """
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003106 def test_wrong_args(self):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003107 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003108 When called with arguments other than a string argument for its first
Alex Chanb7480992017-01-30 14:04:47 +00003109 parameter, `Connection.sendall` raises `TypeError`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003110 """
3111 connection = Connection(Context(TLSv1_METHOD), None)
Alex Chanb7480992017-01-30 14:04:47 +00003112 with pytest.raises(TypeError):
3113 connection.sendall(object())
Daniel Holth079c9632019-11-17 22:45:52 -05003114 with pytest.raises(TypeError):
3115 connection.sendall([1, 2, 3])
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003116
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003117 def test_short(self):
3118 """
Alex Chanb7480992017-01-30 14:04:47 +00003119 `Connection.sendall` transmits all of the bytes in the string
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003120 passed to it.
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003121 """
Alex Chanb7480992017-01-30 14:04:47 +00003122 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04003123 server.sendall(b'x')
Alex Chanb7480992017-01-30 14:04:47 +00003124 assert client.recv(1) == b'x'
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003125
Abraham Martinef063482015-03-25 14:06:24 +00003126 def test_text(self):
3127 """
Alex Chanb7480992017-01-30 14:04:47 +00003128 `Connection.sendall` transmits all the content in the string passed
3129 to it, raising a DeprecationWarning in case of this being a text.
Abraham Martinef063482015-03-25 14:06:24 +00003130 """
Alex Chanb7480992017-01-30 14:04:47 +00003131 server, client = loopback()
3132 with pytest.warns(DeprecationWarning) as w:
Abraham Martinef063482015-03-25 14:06:24 +00003133 simplefilter("always")
Jean-Paul Calderone8dc37a12015-03-29 08:16:52 -04003134 server.sendall(b"x".decode("ascii"))
Alex Chanb7480992017-01-30 14:04:47 +00003135 assert (
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04003136 "{0} for buf is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04003137 WARNING_TYPE_EXPECTED
Alex Chanb7480992017-01-30 14:04:47 +00003138 ) == str(w[-1].message))
3139 assert client.recv(1) == b"x"
Abraham Martinef063482015-03-25 14:06:24 +00003140
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003141 def test_short_memoryview(self):
3142 """
3143 When passed a memoryview onto a small number of bytes,
Alex Chanb7480992017-01-30 14:04:47 +00003144 `Connection.sendall` transmits all of them.
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003145 """
Alex Chanb7480992017-01-30 14:04:47 +00003146 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04003147 server.sendall(memoryview(b'x'))
Alex Chanb7480992017-01-30 14:04:47 +00003148 assert client.recv(1) == b'x'
Abraham Martinef063482015-03-25 14:06:24 +00003149
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003150 @skip_if_py3
3151 def test_short_buffers(self):
3152 """
3153 When passed a buffer containing a small number of bytes,
Alex Chanb7480992017-01-30 14:04:47 +00003154 `Connection.sendall` transmits all of them.
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003155 """
Alex Chanb7480992017-01-30 14:04:47 +00003156 server, client = loopback()
Daniel Holth079c9632019-11-17 22:45:52 -05003157 count = server.sendall(buffer(b'xy'))
3158 assert count == 2
3159 assert client.recv(2) == b'xy'
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02003160
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003161 def test_long(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003162 """
Alex Chanb7480992017-01-30 14:04:47 +00003163 `Connection.sendall` transmits all the bytes in the string passed to it
3164 even if this requires multiple calls of an underlying write function.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003165 """
Alex Chanb7480992017-01-30 14:04:47 +00003166 server, client = loopback()
Jean-Paul Calderone6241c702010-09-16 19:59:24 -04003167 # Should be enough, underlying SSL_write should only do 16k at a time.
Hynek Schlawack35618382015-09-05 21:54:25 +02003168 # On Windows, after 32k of bytes the write will block (forever
3169 # - because no one is yet reading).
Alex Gaynore7f51982016-09-11 11:48:14 -04003170 message = b'x' * (1024 * 32 - 1) + b'y'
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003171 server.sendall(message)
3172 accum = []
3173 received = 0
3174 while received < len(message):
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04003175 data = client.recv(1024)
3176 accum.append(data)
3177 received += len(data)
Alex Chanb7480992017-01-30 14:04:47 +00003178 assert message == b''.join(accum)
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003179
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003180 def test_closed(self):
3181 """
Alex Chanb7480992017-01-30 14:04:47 +00003182 If the underlying socket is closed, `Connection.sendall` propagates the
3183 write error from the low level write call.
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003184 """
Alex Chanb7480992017-01-30 14:04:47 +00003185 server, client = loopback()
Jean-Paul Calderone05d43e82010-09-24 18:01:36 -04003186 server.sock_shutdown(2)
Alex Chanb7480992017-01-30 14:04:47 +00003187 with pytest.raises(SysCallError) as err:
3188 server.sendall(b"hello, world")
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +02003189 if platform == "win32":
Alex Chanb7480992017-01-30 14:04:47 +00003190 assert err.value.args[0] == ESHUTDOWN
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +02003191 else:
Alex Chanb7480992017-01-30 14:04:47 +00003192 assert err.value.args[0] == EPIPE
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003193
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003194
Alex Chanb7480992017-01-30 14:04:47 +00003195class TestConnectionRenegotiate(object):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003196 """
3197 Tests for SSL renegotiation APIs.
3198 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003199 def test_total_renegotiations(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003200 """
Alex Chanb7480992017-01-30 14:04:47 +00003201 `Connection.total_renegotiations` returns `0` before any renegotiations
3202 have happened.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003203 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003204 connection = Connection(Context(TLSv1_METHOD), None)
Alex Chanb7480992017-01-30 14:04:47 +00003205 assert connection.total_renegotiations() == 0
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003206
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003207 def test_renegotiate(self):
3208 """
3209 Go through a complete renegotiation cycle.
3210 """
Paul Kehrer7d5a3bf2019-01-21 12:24:02 -06003211 server, client = loopback(
3212 lambda s: loopback_server_factory(s, TLSv1_2_METHOD),
3213 lambda s: loopback_client_factory(s, TLSv1_2_METHOD),
3214 )
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003215
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003216 server.send(b"hello world")
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003217
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003218 assert b"hello world" == client.recv(len(b"hello world"))
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003219
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003220 assert 0 == server.total_renegotiations()
3221 assert False is server.renegotiate_pending()
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003222
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003223 assert True is server.renegotiate()
3224
3225 assert True is server.renegotiate_pending()
3226
3227 server.setblocking(False)
3228 client.setblocking(False)
3229
3230 client.do_handshake()
3231 server.do_handshake()
3232
3233 assert 1 == server.total_renegotiations()
3234 while False is server.renegotiate_pending():
3235 pass
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003236
3237
Alex Chanb7480992017-01-30 14:04:47 +00003238class TestError(object):
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003239 """
Alex Chanb7480992017-01-30 14:04:47 +00003240 Unit tests for `OpenSSL.SSL.Error`.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003241 """
3242 def test_type(self):
3243 """
Alex Chanb7480992017-01-30 14:04:47 +00003244 `Error` is an exception type.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003245 """
Alex Chanb7480992017-01-30 14:04:47 +00003246 assert issubclass(Error, Exception)
3247 assert Error.__name__ == 'Error'
Rick Deane15b1472009-07-09 15:53:42 -05003248
3249
Alex Chanb7480992017-01-30 14:04:47 +00003250class TestConstants(object):
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003251 """
Alex Chanb7480992017-01-30 14:04:47 +00003252 Tests for the values of constants exposed in `OpenSSL.SSL`.
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003253
3254 These are values defined by OpenSSL intended only to be used as flags to
3255 OpenSSL APIs. The only assertions it seems can be made about them is
3256 their values.
3257 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003258 @pytest.mark.skipif(
3259 OP_NO_QUERY_MTU is None,
3260 reason="OP_NO_QUERY_MTU unavailable - OpenSSL version may be too old"
3261 )
3262 def test_op_no_query_mtu(self):
3263 """
Alex Chanb7480992017-01-30 14:04:47 +00003264 The value of `OpenSSL.SSL.OP_NO_QUERY_MTU` is 0x1000, the value
3265 of `SSL_OP_NO_QUERY_MTU` defined by `openssl/ssl.h`.
Hynek Schlawack35618382015-09-05 21:54:25 +02003266 """
Alex Chanb7480992017-01-30 14:04:47 +00003267 assert OP_NO_QUERY_MTU == 0x1000
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003268
Hynek Schlawack35618382015-09-05 21:54:25 +02003269 @pytest.mark.skipif(
3270 OP_COOKIE_EXCHANGE is None,
3271 reason="OP_COOKIE_EXCHANGE unavailable - "
3272 "OpenSSL version may be too old"
3273 )
3274 def test_op_cookie_exchange(self):
3275 """
Alex Chanb7480992017-01-30 14:04:47 +00003276 The value of `OpenSSL.SSL.OP_COOKIE_EXCHANGE` is 0x2000, the
3277 value of `SSL_OP_COOKIE_EXCHANGE` defined by `openssl/ssl.h`.
Hynek Schlawack35618382015-09-05 21:54:25 +02003278 """
Alex Chanb7480992017-01-30 14:04:47 +00003279 assert OP_COOKIE_EXCHANGE == 0x2000
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003280
Hynek Schlawack35618382015-09-05 21:54:25 +02003281 @pytest.mark.skipif(
3282 OP_NO_TICKET is None,
3283 reason="OP_NO_TICKET unavailable - OpenSSL version may be too old"
3284 )
3285 def test_op_no_ticket(self):
3286 """
Alex Chanb7480992017-01-30 14:04:47 +00003287 The value of `OpenSSL.SSL.OP_NO_TICKET` is 0x4000, the value of
3288 `SSL_OP_NO_TICKET` defined by `openssl/ssl.h`.
Hynek Schlawack35618382015-09-05 21:54:25 +02003289 """
Alex Chanb7480992017-01-30 14:04:47 +00003290 assert OP_NO_TICKET == 0x4000
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003291
Hynek Schlawack35618382015-09-05 21:54:25 +02003292 @pytest.mark.skipif(
3293 OP_NO_COMPRESSION is None,
3294 reason="OP_NO_COMPRESSION unavailable - OpenSSL version may be too old"
3295 )
3296 def test_op_no_compression(self):
3297 """
Alex Chanb7480992017-01-30 14:04:47 +00003298 The value of `OpenSSL.SSL.OP_NO_COMPRESSION` is 0x20000, the
3299 value of `SSL_OP_NO_COMPRESSION` defined by `openssl/ssl.h`.
Hynek Schlawack35618382015-09-05 21:54:25 +02003300 """
Alex Chanb7480992017-01-30 14:04:47 +00003301 assert OP_NO_COMPRESSION == 0x20000
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04003302
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003303 def test_sess_cache_off(self):
3304 """
Alex Chanb7480992017-01-30 14:04:47 +00003305 The value of `OpenSSL.SSL.SESS_CACHE_OFF` 0x0, the value of
3306 `SSL_SESS_CACHE_OFF` defined by `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003307 """
Alex Chanb7480992017-01-30 14:04:47 +00003308 assert 0x0 == SESS_CACHE_OFF
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003309
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003310 def test_sess_cache_client(self):
3311 """
Alex Chanb7480992017-01-30 14:04:47 +00003312 The value of `OpenSSL.SSL.SESS_CACHE_CLIENT` 0x1, the value of
3313 `SSL_SESS_CACHE_CLIENT` defined by `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003314 """
Alex Chanb7480992017-01-30 14:04:47 +00003315 assert 0x1 == SESS_CACHE_CLIENT
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003316
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003317 def test_sess_cache_server(self):
3318 """
Alex Chanb7480992017-01-30 14:04:47 +00003319 The value of `OpenSSL.SSL.SESS_CACHE_SERVER` 0x2, the value of
3320 `SSL_SESS_CACHE_SERVER` defined by `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003321 """
Alex Chanb7480992017-01-30 14:04:47 +00003322 assert 0x2 == SESS_CACHE_SERVER
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003323
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003324 def test_sess_cache_both(self):
3325 """
Alex Chanb7480992017-01-30 14:04:47 +00003326 The value of `OpenSSL.SSL.SESS_CACHE_BOTH` 0x3, the value of
3327 `SSL_SESS_CACHE_BOTH` defined by `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003328 """
Alex Chanb7480992017-01-30 14:04:47 +00003329 assert 0x3 == SESS_CACHE_BOTH
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003330
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003331 def test_sess_cache_no_auto_clear(self):
3332 """
Alex Chanb7480992017-01-30 14:04:47 +00003333 The value of `OpenSSL.SSL.SESS_CACHE_NO_AUTO_CLEAR` 0x80, the
3334 value of `SSL_SESS_CACHE_NO_AUTO_CLEAR` defined by
3335 `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003336 """
Alex Chanb7480992017-01-30 14:04:47 +00003337 assert 0x80 == SESS_CACHE_NO_AUTO_CLEAR
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003338
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003339 def test_sess_cache_no_internal_lookup(self):
3340 """
Alex Chanb7480992017-01-30 14:04:47 +00003341 The value of `OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_LOOKUP` 0x100,
3342 the value of `SSL_SESS_CACHE_NO_INTERNAL_LOOKUP` defined by
3343 `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003344 """
Alex Chanb7480992017-01-30 14:04:47 +00003345 assert 0x100 == SESS_CACHE_NO_INTERNAL_LOOKUP
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003346
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003347 def test_sess_cache_no_internal_store(self):
3348 """
Alex Chanb7480992017-01-30 14:04:47 +00003349 The value of `OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_STORE` 0x200,
3350 the value of `SSL_SESS_CACHE_NO_INTERNAL_STORE` defined by
3351 `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003352 """
Alex Chanb7480992017-01-30 14:04:47 +00003353 assert 0x200 == SESS_CACHE_NO_INTERNAL_STORE
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003354
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003355 def test_sess_cache_no_internal(self):
3356 """
Alex Chanb7480992017-01-30 14:04:47 +00003357 The value of `OpenSSL.SSL.SESS_CACHE_NO_INTERNAL` 0x300, the
3358 value of `SSL_SESS_CACHE_NO_INTERNAL` defined by
3359 `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003360 """
Alex Chanb7480992017-01-30 14:04:47 +00003361 assert 0x300 == SESS_CACHE_NO_INTERNAL
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003362
3363
Alex Chanb7480992017-01-30 14:04:47 +00003364class TestMemoryBIO(object):
Rick Deanb71c0d22009-04-01 14:09:23 -05003365 """
Alex Chanb7480992017-01-30 14:04:47 +00003366 Tests for `OpenSSL.SSL.Connection` using a memory BIO.
Rick Deanb71c0d22009-04-01 14:09:23 -05003367 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003368 def _server(self, sock):
3369 """
Alex Chanb7480992017-01-30 14:04:47 +00003370 Create a new server-side SSL `Connection` object wrapped around `sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003371 """
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003372 # Create the server side Connection. This is mostly setup boilerplate
3373 # - use TLSv1, use a particular certificate, etc.
3374 server_ctx = Context(TLSv1_METHOD)
Alex Gaynor43307782015-09-04 09:05:45 -04003375 server_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE)
Hynek Schlawack35618382015-09-05 21:54:25 +02003376 server_ctx.set_verify(
3377 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT | VERIFY_CLIENT_ONCE,
3378 verify_cb
3379 )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003380 server_store = server_ctx.get_cert_store()
Hynek Schlawack35618382015-09-05 21:54:25 +02003381 server_ctx.use_privatekey(
3382 load_privatekey(FILETYPE_PEM, server_key_pem))
3383 server_ctx.use_certificate(
3384 load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003385 server_ctx.check_privatekey()
3386 server_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Hynek Schlawack35618382015-09-05 21:54:25 +02003387 # Here the Connection is actually created. If None is passed as the
3388 # 2nd parameter, it indicates a memory BIO should be created.
Rick Deanb1ccd562009-07-09 23:52:39 -05003389 server_conn = Connection(server_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003390 server_conn.set_accept_state()
3391 return server_conn
3392
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003393 def _client(self, sock):
3394 """
Alex Chanb7480992017-01-30 14:04:47 +00003395 Create a new client-side SSL `Connection` object wrapped around `sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003396 """
3397 # Now create the client side Connection. Similar boilerplate to the
3398 # above.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003399 client_ctx = Context(TLSv1_METHOD)
Alex Gaynor43307782015-09-04 09:05:45 -04003400 client_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE)
Hynek Schlawack35618382015-09-05 21:54:25 +02003401 client_ctx.set_verify(
3402 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT | VERIFY_CLIENT_ONCE,
3403 verify_cb
3404 )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003405 client_store = client_ctx.get_cert_store()
Hynek Schlawack35618382015-09-05 21:54:25 +02003406 client_ctx.use_privatekey(
3407 load_privatekey(FILETYPE_PEM, client_key_pem))
3408 client_ctx.use_certificate(
3409 load_certificate(FILETYPE_PEM, client_cert_pem))
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003410 client_ctx.check_privatekey()
3411 client_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05003412 client_conn = Connection(client_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003413 client_conn.set_connect_state()
3414 return client_conn
3415
Alex Chanb7480992017-01-30 14:04:47 +00003416 def test_memory_connect(self):
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003417 """
Alex Chanb7480992017-01-30 14:04:47 +00003418 Two `Connection`s which use memory BIOs can be manually connected by
3419 reading from the output of each and writing those bytes to the input of
3420 the other and in this way establish a connection and exchange
3421 application-level bytes with each other.
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003422 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003423 server_conn = self._server(None)
3424 client_conn = self._client(None)
Rick Deanb71c0d22009-04-01 14:09:23 -05003425
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003426 # There should be no key or nonces yet.
Alex Chanb7480992017-01-30 14:04:47 +00003427 assert server_conn.master_key() is None
3428 assert server_conn.client_random() is None
3429 assert server_conn.server_random() is None
Rick Deanb71c0d22009-04-01 14:09:23 -05003430
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003431 # First, the handshake needs to happen. We'll deliver bytes back and
3432 # forth between the client and server until neither of them feels like
3433 # speaking any more.
Alex Chanb7480992017-01-30 14:04:47 +00003434 assert interact_in_memory(client_conn, server_conn) is None
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003435
3436 # Now that the handshake is done, there should be a key and nonces.
Alex Chanb7480992017-01-30 14:04:47 +00003437 assert server_conn.master_key() is not None
3438 assert server_conn.client_random() is not None
3439 assert server_conn.server_random() is not None
3440 assert server_conn.client_random() == client_conn.client_random()
3441 assert server_conn.server_random() == client_conn.server_random()
3442 assert server_conn.client_random() != server_conn.server_random()
3443 assert client_conn.client_random() != client_conn.server_random()
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003444
Paul Kehrerbdb76392017-12-01 04:54:32 +08003445 # Export key material for other uses.
3446 cekm = client_conn.export_keying_material(b'LABEL', 32)
3447 sekm = server_conn.export_keying_material(b'LABEL', 32)
3448 assert cekm is not None
3449 assert sekm is not None
3450 assert cekm == sekm
3451 assert len(sekm) == 32
3452
3453 # Export key material for other uses with additional context.
3454 cekmc = client_conn.export_keying_material(b'LABEL', 32, b'CONTEXT')
3455 sekmc = server_conn.export_keying_material(b'LABEL', 32, b'CONTEXT')
3456 assert cekmc is not None
3457 assert sekmc is not None
3458 assert cekmc == sekmc
3459 assert cekmc != cekm
3460 assert sekmc != sekm
3461 # Export with alternate label
3462 cekmt = client_conn.export_keying_material(b'test', 32, b'CONTEXT')
3463 sekmt = server_conn.export_keying_material(b'test', 32, b'CONTEXT')
3464 assert cekmc != cekmt
3465 assert sekmc != sekmt
3466
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003467 # Here are the bytes we'll try to send.
Alex Gaynore7f51982016-09-11 11:48:14 -04003468 important_message = b'One if by land, two if by sea.'
Rick Deanb71c0d22009-04-01 14:09:23 -05003469
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003470 server_conn.write(important_message)
Alex Chanb7480992017-01-30 14:04:47 +00003471 assert (
3472 interact_in_memory(client_conn, server_conn) ==
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003473 (client_conn, important_message))
3474
3475 client_conn.write(important_message[::-1])
Alex Chanb7480992017-01-30 14:04:47 +00003476 assert (
3477 interact_in_memory(client_conn, server_conn) ==
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003478 (server_conn, important_message[::-1]))
Rick Deanb71c0d22009-04-01 14:09:23 -05003479
Alex Chanb7480992017-01-30 14:04:47 +00003480 def test_socket_connect(self):
Rick Deanb1ccd562009-07-09 23:52:39 -05003481 """
Alex Chanb7480992017-01-30 14:04:47 +00003482 Just like `test_memory_connect` but with an actual socket.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003483
Hynek Schlawack35618382015-09-05 21:54:25 +02003484 This is primarily to rule out the memory BIO code as the source of any
Alex Chanb7480992017-01-30 14:04:47 +00003485 problems encountered while passing data over a `Connection` (if
Hynek Schlawack35618382015-09-05 21:54:25 +02003486 this test fails, there must be a problem outside the memory BIO code,
3487 as no memory BIO is involved here). Even though this isn't a memory
3488 BIO test, it's convenient to have it here.
Rick Deanb1ccd562009-07-09 23:52:39 -05003489 """
Alex Chanb7480992017-01-30 14:04:47 +00003490 server_conn, client_conn = loopback()
Rick Deanb1ccd562009-07-09 23:52:39 -05003491
Alex Gaynore7f51982016-09-11 11:48:14 -04003492 important_message = b"Help me Obi Wan Kenobi, you're my only hope."
Rick Deanb1ccd562009-07-09 23:52:39 -05003493 client_conn.send(important_message)
3494 msg = server_conn.recv(1024)
Alex Chanb7480992017-01-30 14:04:47 +00003495 assert msg == important_message
Rick Deanb1ccd562009-07-09 23:52:39 -05003496
3497 # Again in the other direction, just for fun.
3498 important_message = important_message[::-1]
3499 server_conn.send(important_message)
3500 msg = client_conn.recv(1024)
Alex Chanb7480992017-01-30 14:04:47 +00003501 assert msg == important_message
Rick Deanb1ccd562009-07-09 23:52:39 -05003502
Alex Chanb7480992017-01-30 14:04:47 +00003503 def test_socket_overrides_memory(self):
Rick Deanb71c0d22009-04-01 14:09:23 -05003504 """
Alex Chanb7480992017-01-30 14:04:47 +00003505 Test that `OpenSSL.SSL.bio_read` and `OpenSSL.SSL.bio_write` don't
3506 work on `OpenSSL.SSL.Connection`() that use sockets.
Rick Deanb71c0d22009-04-01 14:09:23 -05003507 """
Alex Gaynor51d424c2016-09-10 14:50:11 -04003508 context = Context(TLSv1_METHOD)
David Benjamin1fbe0642019-04-15 17:05:13 -05003509 client = socket_any_family()
Rick Deanb71c0d22009-04-01 14:09:23 -05003510 clientSSL = Connection(context, client)
Alex Chanb7480992017-01-30 14:04:47 +00003511 with pytest.raises(TypeError):
3512 clientSSL.bio_read(100)
3513 with pytest.raises(TypeError):
3514 clientSSL.bio_write("foo")
3515 with pytest.raises(TypeError):
3516 clientSSL.bio_shutdown()
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003517
Alex Chanb7480992017-01-30 14:04:47 +00003518 def test_outgoing_overflow(self):
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003519 """
3520 If more bytes than can be written to the memory BIO are passed to
Alex Chanb7480992017-01-30 14:04:47 +00003521 `Connection.send` at once, the number of bytes which were written is
3522 returned and that many bytes from the beginning of the input can be
3523 read from the other end of the connection.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003524 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003525 server = self._server(None)
3526 client = self._client(None)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003527
Alex Chanb7480992017-01-30 14:04:47 +00003528 interact_in_memory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003529
3530 size = 2 ** 15
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003531 sent = client.send(b"x" * size)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003532 # Sanity check. We're trying to test what happens when the entire
3533 # input can't be sent. If the entire input was sent, this test is
3534 # meaningless.
Alex Chanb7480992017-01-30 14:04:47 +00003535 assert sent < size
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003536
Alex Chanb7480992017-01-30 14:04:47 +00003537 receiver, received = interact_in_memory(client, server)
3538 assert receiver is server
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003539
3540 # We can rely on all of these bytes being received at once because
Alex Chanb7480992017-01-30 14:04:47 +00003541 # loopback passes 2 ** 16 to recv - more than 2 ** 15.
3542 assert len(received) == sent
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003543
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003544 def test_shutdown(self):
3545 """
Alex Chanb7480992017-01-30 14:04:47 +00003546 `Connection.bio_shutdown` signals the end of the data stream
3547 from which the `Connection` reads.
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003548 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003549 server = self._server(None)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003550 server.bio_shutdown()
Alex Chanb7480992017-01-30 14:04:47 +00003551 with pytest.raises(Error) as err:
3552 server.recv(1024)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003553 # We don't want WantReadError or ZeroReturnError or anything - it's a
3554 # handshake failure.
Alex Chanb7480992017-01-30 14:04:47 +00003555 assert type(err.value) in [Error, SysCallError]
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003556
Alex Chanb7480992017-01-30 14:04:47 +00003557 def test_unexpected_EOF(self):
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003558 """
3559 If the connection is lost before an orderly SSL shutdown occurs,
Alex Chanb7480992017-01-30 14:04:47 +00003560 `OpenSSL.SSL.SysCallError` is raised with a message of
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003561 "Unexpected EOF".
3562 """
Alex Chanb7480992017-01-30 14:04:47 +00003563 server_conn, client_conn = loopback()
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003564 client_conn.sock_shutdown(SHUT_RDWR)
Alex Chanb7480992017-01-30 14:04:47 +00003565 with pytest.raises(SysCallError) as err:
3566 server_conn.recv(1024)
3567 assert err.value.args == (-1, "Unexpected EOF")
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003568
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003569 def _check_client_ca_list(self, func):
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003570 """
Alex Chanb7480992017-01-30 14:04:47 +00003571 Verify the return value of the `get_client_ca_list` method for
Hynek Schlawack35618382015-09-05 21:54:25 +02003572 server and client connections.
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003573
Jonathan Ballet78b92a22011-07-16 08:07:26 +09003574 :param func: A function which will be called with the server context
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003575 before the client and server are connected to each other. This
3576 function should specify a list of CAs for the server to send to the
3577 client and return that same list. The list will be used to verify
Alex Chanb7480992017-01-30 14:04:47 +00003578 that `get_client_ca_list` returns the proper value at
Hynek Schlawack35618382015-09-05 21:54:25 +02003579 various times.
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003580 """
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003581 server = self._server(None)
3582 client = self._client(None)
Alex Chanb7480992017-01-30 14:04:47 +00003583 assert client.get_client_ca_list() == []
3584 assert server.get_client_ca_list() == []
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003585 ctx = server.get_context()
3586 expected = func(ctx)
Alex Chanb7480992017-01-30 14:04:47 +00003587 assert client.get_client_ca_list() == []
3588 assert server.get_client_ca_list() == expected
3589 interact_in_memory(client, server)
3590 assert client.get_client_ca_list() == expected
3591 assert server.get_client_ca_list() == expected
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003592
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003593 def test_set_client_ca_list_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003594 """
Alex Chanb7480992017-01-30 14:04:47 +00003595 `Context.set_client_ca_list` raises a `TypeError` if called with a
3596 non-list or a list that contains objects other than X509Names.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003597 """
3598 ctx = Context(TLSv1_METHOD)
Alex Chanb7480992017-01-30 14:04:47 +00003599 with pytest.raises(TypeError):
3600 ctx.set_client_ca_list("spam")
3601 with pytest.raises(TypeError):
3602 ctx.set_client_ca_list(["spam"])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003603
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003604 def test_set_empty_ca_list(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003605 """
Alex Chanb7480992017-01-30 14:04:47 +00003606 If passed an empty list, `Context.set_client_ca_list` configures the
3607 context to send no CA names to the client and, on both the server and
3608 client sides, `Connection.get_client_ca_list` returns an empty list
3609 after the connection is set up.
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003610 """
3611 def no_ca(ctx):
3612 ctx.set_client_ca_list([])
3613 return []
3614 self._check_client_ca_list(no_ca)
3615
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003616 def test_set_one_ca_list(self):
3617 """
3618 If passed a list containing a single X509Name,
Alex Chanb7480992017-01-30 14:04:47 +00003619 `Context.set_client_ca_list` configures the context to send
Hynek Schlawack35618382015-09-05 21:54:25 +02003620 that CA name to the client and, on both the server and client sides,
Alex Chanb7480992017-01-30 14:04:47 +00003621 `Connection.get_client_ca_list` returns a list containing that
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003622 X509Name after the connection is set up.
3623 """
3624 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3625 cadesc = cacert.get_subject()
Hynek Schlawack35618382015-09-05 21:54:25 +02003626
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003627 def single_ca(ctx):
3628 ctx.set_client_ca_list([cadesc])
3629 return [cadesc]
3630 self._check_client_ca_list(single_ca)
3631
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003632 def test_set_multiple_ca_list(self):
3633 """
3634 If passed a list containing multiple X509Name objects,
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 those CA names 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 those
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003638 X509Names after the connection is set up.
3639 """
3640 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3641 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3642
3643 sedesc = secert.get_subject()
3644 cldesc = clcert.get_subject()
3645
3646 def multiple_ca(ctx):
3647 L = [sedesc, cldesc]
3648 ctx.set_client_ca_list(L)
3649 return L
3650 self._check_client_ca_list(multiple_ca)
3651
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003652 def test_reset_ca_list(self):
3653 """
3654 If called multiple times, only the X509Names passed to the final call
Alex Chanb7480992017-01-30 14:04:47 +00003655 of `Context.set_client_ca_list` are used to configure the CA
Hynek Schlawack35618382015-09-05 21:54:25 +02003656 names sent to the client.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003657 """
3658 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3659 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3660 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3661
3662 cadesc = cacert.get_subject()
3663 sedesc = secert.get_subject()
3664 cldesc = clcert.get_subject()
3665
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003666 def changed_ca(ctx):
3667 ctx.set_client_ca_list([sedesc, cldesc])
3668 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003669 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003670 self._check_client_ca_list(changed_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003671
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003672 def test_mutated_ca_list(self):
3673 """
Alex Chanb7480992017-01-30 14:04:47 +00003674 If the list passed to `Context.set_client_ca_list` is mutated
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003675 afterwards, this does not affect the list of CA names sent to the
3676 client.
3677 """
3678 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3679 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3680
3681 cadesc = cacert.get_subject()
3682 sedesc = secert.get_subject()
3683
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003684 def mutated_ca(ctx):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003685 L = [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003686 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003687 L.append(sedesc)
3688 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003689 self._check_client_ca_list(mutated_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003690
Alex Chanb7480992017-01-30 14:04:47 +00003691 def test_add_client_ca_wrong_args(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003692 """
Alex Chanb7480992017-01-30 14:04:47 +00003693 `Context.add_client_ca` raises `TypeError` if called with
3694 a non-X509 object.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003695 """
3696 ctx = Context(TLSv1_METHOD)
Alex Chanb7480992017-01-30 14:04:47 +00003697 with pytest.raises(TypeError):
3698 ctx.add_client_ca("spam")
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003699
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003700 def test_one_add_client_ca(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003701 """
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003702 A certificate's subject can be added as a CA to be sent to the client
Alex Chanb7480992017-01-30 14:04:47 +00003703 with `Context.add_client_ca`.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003704 """
3705 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3706 cadesc = cacert.get_subject()
Hynek Schlawack35618382015-09-05 21:54:25 +02003707
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003708 def single_ca(ctx):
3709 ctx.add_client_ca(cacert)
3710 return [cadesc]
3711 self._check_client_ca_list(single_ca)
3712
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003713 def test_multiple_add_client_ca(self):
3714 """
3715 Multiple CA names can be sent to the client by calling
Alex Chanb7480992017-01-30 14:04:47 +00003716 `Context.add_client_ca` with multiple X509 objects.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003717 """
3718 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3719 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3720
3721 cadesc = cacert.get_subject()
3722 sedesc = secert.get_subject()
3723
3724 def multiple_ca(ctx):
3725 ctx.add_client_ca(cacert)
3726 ctx.add_client_ca(secert)
3727 return [cadesc, sedesc]
3728 self._check_client_ca_list(multiple_ca)
3729
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003730 def test_set_and_add_client_ca(self):
3731 """
Alex Chanb7480992017-01-30 14:04:47 +00003732 A call to `Context.set_client_ca_list` followed by a call to
3733 `Context.add_client_ca` results in using the CA names from the
Hynek Schlawack35618382015-09-05 21:54:25 +02003734 first call and the CA name from the second call.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003735 """
3736 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3737 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3738 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3739
3740 cadesc = cacert.get_subject()
3741 sedesc = secert.get_subject()
3742 cldesc = clcert.get_subject()
3743
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003744 def mixed_set_add_ca(ctx):
3745 ctx.set_client_ca_list([cadesc, sedesc])
3746 ctx.add_client_ca(clcert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003747 return [cadesc, sedesc, cldesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003748 self._check_client_ca_list(mixed_set_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003749
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003750 def test_set_after_add_client_ca(self):
3751 """
Alex Chanb7480992017-01-30 14:04:47 +00003752 A call to `Context.set_client_ca_list` after a call to
3753 `Context.add_client_ca` replaces the CA name specified by the
Hynek Schlawack35618382015-09-05 21:54:25 +02003754 former call with the names specified by the latter call.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003755 """
3756 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3757 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3758 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3759
3760 cadesc = cacert.get_subject()
3761 sedesc = secert.get_subject()
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003762
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003763 def set_replaces_add_ca(ctx):
3764 ctx.add_client_ca(clcert)
3765 ctx.set_client_ca_list([cadesc])
3766 ctx.add_client_ca(secert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003767 return [cadesc, sedesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003768 self._check_client_ca_list(set_replaces_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003769
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003770
Alex Chanb7480992017-01-30 14:04:47 +00003771class TestInfoConstants(object):
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003772 """
3773 Tests for assorted constants exposed for use in info callbacks.
3774 """
3775 def test_integers(self):
3776 """
3777 All of the info constants are integers.
3778
3779 This is a very weak test. It would be nice to have one that actually
3780 verifies that as certain info events happen, the value passed to the
3781 info callback matches up with the constant exposed by OpenSSL.SSL.
3782 """
3783 for const in [
Alex Gaynor5af32d02016-09-24 01:52:21 -04003784 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK,
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003785 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
3786 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
3787 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
Hynek Schlawack35618382015-09-05 21:54:25 +02003788 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE
3789 ]:
Alex Gaynor5af32d02016-09-24 01:52:21 -04003790 assert isinstance(const, int)
3791
3792 # These constants don't exist on OpenSSL 1.1.0
3793 for const in [
3794 SSL_ST_INIT, SSL_ST_BEFORE, SSL_ST_OK, SSL_ST_RENEGOTIATE
3795 ]:
3796 assert const is None or isinstance(const, int)
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003797
Ziga Seilnacht44611bf2009-08-31 20:49:30 +02003798
Cory Benfield1d142142016-03-30 11:51:45 +01003799class TestRequires(object):
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003800 """
3801 Tests for the decorator factory used to conditionally raise
Cory Benfield1d142142016-03-30 11:51:45 +01003802 NotImplementedError when older OpenSSLs are used.
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003803 """
3804 def test_available(self):
3805 """
3806 When the OpenSSL functionality is available the decorated functions
3807 work appropriately.
3808 """
3809 feature_guard = _make_requires(True, "Error text")
3810 results = []
3811
3812 @feature_guard
3813 def inner():
3814 results.append(True)
3815 return True
3816
Cory Benfield2333e5e2016-03-30 14:24:16 +01003817 assert inner() is True
3818 assert [True] == results
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003819
3820 def test_unavailable(self):
3821 """
3822 When the OpenSSL functionality is not available the decorated function
3823 does not execute and NotImplementedError is raised.
3824 """
3825 feature_guard = _make_requires(False, "Error text")
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003826
3827 @feature_guard
Alex Chanfb078d82017-04-20 11:16:15 +01003828 def inner(): # pragma: nocover
3829 pytest.fail("Should not be called")
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003830
Cory Benfield1d142142016-03-30 11:51:45 +01003831 with pytest.raises(NotImplementedError) as e:
3832 inner()
3833
3834 assert "Error text" in str(e.value)
Cory Benfield496652a2017-01-24 11:42:56 +00003835
3836
Alex Chanb7480992017-01-30 14:04:47 +00003837class TestOCSP(object):
Cory Benfield496652a2017-01-24 11:42:56 +00003838 """
3839 Tests for PyOpenSSL's OCSP stapling support.
3840 """
3841 sample_ocsp_data = b"this is totally ocsp data"
3842
3843 def _client_connection(self, callback, data, request_ocsp=True):
3844 """
3845 Builds a client connection suitable for using OCSP.
3846
3847 :param callback: The callback to register for OCSP.
3848 :param data: The opaque data object that will be handed to the
3849 OCSP callback.
3850 :param request_ocsp: Whether the client will actually ask for OCSP
3851 stapling. Useful for testing only.
3852 """
3853 ctx = Context(SSLv23_METHOD)
3854 ctx.set_ocsp_client_callback(callback, data)
3855 client = Connection(ctx)
3856
3857 if request_ocsp:
3858 client.request_ocsp()
3859
3860 client.set_connect_state()
3861 return client
3862
3863 def _server_connection(self, callback, data):
3864 """
3865 Builds a server connection suitable for using OCSP.
3866
3867 :param callback: The callback to register for OCSP.
3868 :param data: The opaque data object that will be handed to the
3869 OCSP callback.
3870 """
3871 ctx = Context(SSLv23_METHOD)
3872 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
3873 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
3874 ctx.set_ocsp_server_callback(callback, data)
3875 server = Connection(ctx)
3876 server.set_accept_state()
3877 return server
3878
3879 def test_callbacks_arent_called_by_default(self):
3880 """
3881 If both the client and the server have registered OCSP callbacks, but
3882 the client does not send the OCSP request, neither callback gets
3883 called.
3884 """
Alex Chanfb078d82017-04-20 11:16:15 +01003885 def ocsp_callback(*args, **kwargs): # pragma: nocover
3886 pytest.fail("Should not be called")
Cory Benfield496652a2017-01-24 11:42:56 +00003887
3888 client = self._client_connection(
3889 callback=ocsp_callback, data=None, request_ocsp=False
3890 )
3891 server = self._server_connection(callback=ocsp_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00003892 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003893
Cory Benfield496652a2017-01-24 11:42:56 +00003894 def test_client_negotiates_without_server(self):
3895 """
3896 If the client wants to do OCSP but the server does not, the handshake
3897 succeeds, and the client callback fires with an empty byte string.
3898 """
3899 called = []
3900
3901 def ocsp_callback(conn, ocsp_data, ignored):
3902 called.append(ocsp_data)
3903 return True
3904
3905 client = self._client_connection(callback=ocsp_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00003906 server = loopback_server_factory(socket=None)
3907 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003908
3909 assert len(called) == 1
3910 assert called[0] == b''
3911
3912 def test_client_receives_servers_data(self):
3913 """
3914 The data the server sends in its callback is received by the client.
3915 """
3916 calls = []
3917
3918 def server_callback(*args, **kwargs):
3919 return self.sample_ocsp_data
3920
3921 def client_callback(conn, ocsp_data, ignored):
3922 calls.append(ocsp_data)
3923 return True
3924
3925 client = self._client_connection(callback=client_callback, data=None)
3926 server = self._server_connection(callback=server_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00003927 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003928
3929 assert len(calls) == 1
3930 assert calls[0] == self.sample_ocsp_data
3931
3932 def test_callbacks_are_invoked_with_connections(self):
3933 """
3934 The first arguments to both callbacks are their respective connections.
3935 """
3936 client_calls = []
3937 server_calls = []
3938
3939 def client_callback(conn, *args, **kwargs):
3940 client_calls.append(conn)
3941 return True
3942
3943 def server_callback(conn, *args, **kwargs):
3944 server_calls.append(conn)
3945 return self.sample_ocsp_data
3946
3947 client = self._client_connection(callback=client_callback, data=None)
3948 server = self._server_connection(callback=server_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00003949 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003950
3951 assert len(client_calls) == 1
3952 assert len(server_calls) == 1
3953 assert client_calls[0] is client
3954 assert server_calls[0] is server
3955
3956 def test_opaque_data_is_passed_through(self):
3957 """
3958 Both callbacks receive an opaque, user-provided piece of data in their
3959 callbacks as the final argument.
3960 """
3961 calls = []
3962
3963 def server_callback(*args):
3964 calls.append(args)
3965 return self.sample_ocsp_data
3966
3967 def client_callback(*args):
3968 calls.append(args)
3969 return True
3970
3971 sentinel = object()
3972
3973 client = self._client_connection(
3974 callback=client_callback, data=sentinel
3975 )
3976 server = self._server_connection(
3977 callback=server_callback, data=sentinel
3978 )
Alex Chanb7480992017-01-30 14:04:47 +00003979 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003980
3981 assert len(calls) == 2
3982 assert calls[0][-1] is sentinel
3983 assert calls[1][-1] is sentinel
3984
3985 def test_server_returns_empty_string(self):
3986 """
3987 If the server returns an empty bytestring from its callback, the
3988 client callback is called with the empty bytestring.
3989 """
3990 client_calls = []
3991
3992 def server_callback(*args):
3993 return b''
3994
3995 def client_callback(conn, ocsp_data, ignored):
3996 client_calls.append(ocsp_data)
3997 return True
3998
3999 client = self._client_connection(callback=client_callback, data=None)
4000 server = self._server_connection(callback=server_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00004001 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00004002
4003 assert len(client_calls) == 1
4004 assert client_calls[0] == b''
4005
4006 def test_client_returns_false_terminates_handshake(self):
4007 """
4008 If the client returns False from its callback, the handshake fails.
4009 """
4010 def server_callback(*args):
4011 return self.sample_ocsp_data
4012
4013 def client_callback(*args):
4014 return False
4015
4016 client = self._client_connection(callback=client_callback, data=None)
4017 server = self._server_connection(callback=server_callback, data=None)
4018
4019 with pytest.raises(Error):
Alex Chanb7480992017-01-30 14:04:47 +00004020 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00004021
4022 def test_exceptions_in_client_bubble_up(self):
4023 """
4024 The callbacks thrown in the client callback bubble up to the caller.
4025 """
4026 class SentinelException(Exception):
4027 pass
4028
4029 def server_callback(*args):
4030 return self.sample_ocsp_data
4031
4032 def client_callback(*args):
4033 raise SentinelException()
4034
4035 client = self._client_connection(callback=client_callback, data=None)
4036 server = self._server_connection(callback=server_callback, data=None)
4037
4038 with pytest.raises(SentinelException):
Alex Chanb7480992017-01-30 14:04:47 +00004039 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00004040
4041 def test_exceptions_in_server_bubble_up(self):
4042 """
4043 The callbacks thrown in the server callback bubble up to the caller.
4044 """
4045 class SentinelException(Exception):
4046 pass
4047
4048 def server_callback(*args):
4049 raise SentinelException()
4050
Alex Chanfb078d82017-04-20 11:16:15 +01004051 def client_callback(*args): # pragma: nocover
Cory Benfield496652a2017-01-24 11:42:56 +00004052 pytest.fail("Should not be called")
4053
4054 client = self._client_connection(callback=client_callback, data=None)
4055 server = self._server_connection(callback=server_callback, data=None)
4056
4057 with pytest.raises(SentinelException):
Alex Chanb7480992017-01-30 14:04:47 +00004058 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00004059
4060 def test_server_must_return_bytes(self):
4061 """
4062 The server callback must return a bytestring, or a TypeError is thrown.
4063 """
4064 def server_callback(*args):
4065 return self.sample_ocsp_data.decode('ascii')
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(TypeError):
Alex Chanb7480992017-01-30 14:04:47 +00004074 handshake_in_memory(client, server)