blob: 50e20261cd50a8562d59573fb2ffa2ecb43a2ac3 [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()
202 cacert.get_subject().commonName = "Authority Certificate"
203 cacert.set_issuer(cacert.get_subject())
204 cacert.set_pubkey(cakey)
Alex Gaynore7f51982016-09-11 11:48:14 -0400205 cacert.set_notBefore(b"20000101000000Z")
Alex Gaynor675534c2020-01-12 11:59:49 -0600206 cacert.set_notAfter(not_after)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400207 cacert.add_extensions([caext])
208 cacert.set_serial_number(0)
209 cacert.sign(cakey, "sha1")
210
211 # Step 2
212 ikey = PKey()
Alex Gaynor0737a5e2016-09-10 14:35:09 -0400213 ikey.generate_key(TYPE_RSA, 1024)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400214 icert = X509()
215 icert.get_subject().commonName = "Intermediate Certificate"
216 icert.set_issuer(cacert.get_subject())
217 icert.set_pubkey(ikey)
Alex Gaynore7f51982016-09-11 11:48:14 -0400218 icert.set_notBefore(b"20000101000000Z")
Alex Gaynor675534c2020-01-12 11:59:49 -0600219 icert.set_notAfter(not_after)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400220 icert.add_extensions([caext])
221 icert.set_serial_number(0)
222 icert.sign(cakey, "sha1")
223
224 # Step 3
225 skey = PKey()
Alex Gaynor0737a5e2016-09-10 14:35:09 -0400226 skey.generate_key(TYPE_RSA, 1024)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400227 scert = X509()
228 scert.get_subject().commonName = "Server Certificate"
229 scert.set_issuer(icert.get_subject())
230 scert.set_pubkey(skey)
Alex Gaynore7f51982016-09-11 11:48:14 -0400231 scert.set_notBefore(b"20000101000000Z")
Alex Gaynor675534c2020-01-12 11:59:49 -0600232 scert.set_notAfter(not_after)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400233 scert.add_extensions([
Alex Gaynore7f51982016-09-11 11:48:14 -0400234 X509Extension(b'basicConstraints', True, b'CA:false')])
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400235 scert.set_serial_number(0)
236 scert.sign(ikey, "sha1")
237
238 return [(cakey, cacert), (ikey, icert), (skey, scert)]
239
240
Paul Kehrer7d5a3bf2019-01-21 12:24:02 -0600241def loopback_client_factory(socket, version=SSLv23_METHOD):
242 client = Connection(Context(version), socket)
Alex Chan1c0cb662017-01-30 07:13:30 +0000243 client.set_connect_state()
244 return client
245
246
Paul Kehrer7d5a3bf2019-01-21 12:24:02 -0600247def loopback_server_factory(socket, version=SSLv23_METHOD):
248 ctx = Context(version)
Alex Chan1c0cb662017-01-30 07:13:30 +0000249 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
250 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
251 server = Connection(ctx, socket)
252 server.set_accept_state()
253 return server
254
255
256def loopback(server_factory=None, client_factory=None):
257 """
258 Create a connected socket pair and force two connected SSL sockets
259 to talk to each other via memory BIOs.
260 """
261 if server_factory is None:
262 server_factory = loopback_server_factory
263 if client_factory is None:
264 client_factory = loopback_client_factory
265
266 (server, client) = socket_pair()
267 server = server_factory(server)
268 client = client_factory(client)
269
270 handshake(client, server)
271
272 server.setblocking(True)
273 client.setblocking(True)
274 return server, client
275
276
Alex Chan1ca9e3a2016-11-05 13:01:51 +0000277def interact_in_memory(client_conn, server_conn):
278 """
279 Try to read application bytes from each of the two `Connection` objects.
280 Copy bytes back and forth between their send/receive buffers for as long
281 as there is anything to copy. When there is nothing more to copy,
282 return `None`. If one of them actually manages to deliver some application
283 bytes, return a two-tuple of the connection from which the bytes were read
284 and the bytes themselves.
285 """
286 wrote = True
287 while wrote:
288 # Loop until neither side has anything to say
289 wrote = False
290
291 # Copy stuff from each side's send buffer to the other side's
292 # receive buffer.
293 for (read, write) in [(client_conn, server_conn),
294 (server_conn, client_conn)]:
295
296 # Give the side a chance to generate some more bytes, or succeed.
297 try:
298 data = read.recv(2 ** 16)
299 except WantReadError:
300 # It didn't succeed, so we'll hope it generated some output.
301 pass
302 else:
303 # It did succeed, so we'll stop now and let the caller deal
304 # with it.
305 return (read, data)
306
307 while True:
308 # Keep copying as long as there's more stuff there.
309 try:
310 dirty = read.bio_read(4096)
311 except WantReadError:
312 # Okay, nothing more waiting to be sent. Stop
313 # processing this send buffer.
314 break
315 else:
316 # Keep track of the fact that someone generated some
317 # output.
318 wrote = True
319 write.bio_write(dirty)
320
321
Alex Chan532b79e2017-01-24 15:14:52 +0000322def handshake_in_memory(client_conn, server_conn):
323 """
324 Perform the TLS handshake between two `Connection` instances connected to
325 each other via memory BIOs.
326 """
327 client_conn.set_connect_state()
328 server_conn.set_accept_state()
329
330 for conn in [client_conn, server_conn]:
331 try:
332 conn.do_handshake()
333 except WantReadError:
334 pass
335
336 interact_in_memory(client_conn, server_conn)
337
338
Alex Chanb7480992017-01-30 14:04:47 +0000339class TestVersion(object):
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400340 """
Alex Chanb7480992017-01-30 14:04:47 +0000341 Tests for version information exposed by `OpenSSL.SSL.SSLeay_version` and
342 `OpenSSL.SSL.OPENSSL_VERSION_NUMBER`.
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400343 """
344 def test_OPENSSL_VERSION_NUMBER(self):
345 """
Alex Chanb7480992017-01-30 14:04:47 +0000346 `OPENSSL_VERSION_NUMBER` is an integer with status in the low byte and
347 the patch, fix, minor, and major versions in the nibbles above that.
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400348 """
Alex Chanb7480992017-01-30 14:04:47 +0000349 assert isinstance(OPENSSL_VERSION_NUMBER, int)
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400350
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400351 def test_SSLeay_version(self):
352 """
Alex Chanb7480992017-01-30 14:04:47 +0000353 `SSLeay_version` takes a version type indicator and returns one of a
354 number of version strings based on that indicator.
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400355 """
356 versions = {}
357 for t in [SSLEAY_VERSION, SSLEAY_CFLAGS, SSLEAY_BUILT_ON,
358 SSLEAY_PLATFORM, SSLEAY_DIR]:
359 version = SSLeay_version(t)
360 versions[version] = t
Alex Chanb7480992017-01-30 14:04:47 +0000361 assert isinstance(version, bytes)
362 assert len(versions) == 5
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400363
364
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100365@pytest.fixture
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100366def ca_file(tmpdir):
367 """
368 Create a valid PEM file with CA certificates and return the path.
369 """
370 key = rsa.generate_private_key(
371 public_exponent=65537,
372 key_size=2048,
373 backend=default_backend()
374 )
375 public_key = key.public_key()
376
377 builder = x509.CertificateBuilder()
378 builder = builder.subject_name(x509.Name([
379 x509.NameAttribute(NameOID.COMMON_NAME, u"pyopenssl.org"),
380 ]))
381 builder = builder.issuer_name(x509.Name([
382 x509.NameAttribute(NameOID.COMMON_NAME, u"pyopenssl.org"),
383 ]))
384 one_day = datetime.timedelta(1, 0, 0)
385 builder = builder.not_valid_before(datetime.datetime.today() - one_day)
386 builder = builder.not_valid_after(datetime.datetime.today() + one_day)
387 builder = builder.serial_number(int(uuid.uuid4()))
388 builder = builder.public_key(public_key)
389 builder = builder.add_extension(
390 x509.BasicConstraints(ca=True, path_length=None), critical=True,
391 )
392
393 certificate = builder.sign(
394 private_key=key, algorithm=hashes.SHA256(),
395 backend=default_backend()
396 )
397
398 ca_file = tmpdir.join("test.pem")
399 ca_file.write_binary(
400 certificate.public_bytes(
401 encoding=serialization.Encoding.PEM,
402 )
403 )
404
405 return str(ca_file).encode("ascii")
406
407
408@pytest.fixture
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100409def context():
410 """
411 A simple TLS 1.0 context.
412 """
413 return Context(TLSv1_METHOD)
414
415
416class TestContext(object):
Hynek Schlawackaa861212016-03-13 13:53:48 +0100417 """
Alex Chan532b79e2017-01-24 15:14:52 +0000418 Unit tests for `OpenSSL.SSL.Context`.
Hynek Schlawackaa861212016-03-13 13:53:48 +0100419 """
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100420 @pytest.mark.parametrize("cipher_string", [
421 b"hello world:AES128-SHA",
422 u"hello world:AES128-SHA",
423 ])
424 def test_set_cipher_list(self, context, cipher_string):
425 """
Alex Chan532b79e2017-01-24 15:14:52 +0000426 `Context.set_cipher_list` accepts both byte and unicode strings
Hynek Schlawacka7a63af2016-03-11 12:05:26 +0100427 for naming the ciphers which connections created with the context
428 object will be able to choose from.
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100429 """
430 context.set_cipher_list(cipher_string)
431 conn = Connection(context, None)
432
433 assert "AES128-SHA" in conn.get_cipher_list()
434
Mark Williamsdf2480d2019-02-14 19:30:07 -0800435 def test_set_cipher_list_wrong_type(self, context):
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100436 """
Alex Chan532b79e2017-01-24 15:14:52 +0000437 `Context.set_cipher_list` raises `TypeError` when passed a non-string
Mark Williamsdf2480d2019-02-14 19:30:07 -0800438 argument.
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100439 """
Mark Williamsdf2480d2019-02-14 19:30:07 -0800440 with pytest.raises(TypeError):
441 context.set_cipher_list(object())
442
Alex Gaynor963ae032019-07-06 17:38:32 -0400443 @flaky.flaky
Mark Williamsdf2480d2019-02-14 19:30:07 -0800444 def test_set_cipher_list_no_cipher_match(self, context):
445 """
446 `Context.set_cipher_list` raises `OpenSSL.SSL.Error` with a
447 `"no cipher match"` reason string regardless of the TLS
448 version.
449 """
450 with pytest.raises(Error) as excinfo:
451 context.set_cipher_list(b"imaginary-cipher")
452 assert excinfo.value.args == (
453 [
454 (
455 'SSL routines',
456 'SSL_CTX_set_cipher_list',
457 'no cipher match',
458 ),
459 ],
460 )
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100461
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100462 def test_load_client_ca(self, context, ca_file):
463 """
Alex Chan532b79e2017-01-24 15:14:52 +0000464 `Context.load_client_ca` works as far as we can tell.
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100465 """
466 context.load_client_ca(ca_file)
467
468 def test_load_client_ca_invalid(self, context, tmpdir):
469 """
Alex Chan532b79e2017-01-24 15:14:52 +0000470 `Context.load_client_ca` raises an Error if the ca file is invalid.
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100471 """
472 ca_file = tmpdir.join("test.pem")
473 ca_file.write("")
474
475 with pytest.raises(Error) as e:
476 context.load_client_ca(str(ca_file).encode("ascii"))
477
478 assert "PEM routines" == e.value.args[0][0][0]
479
480 def test_load_client_ca_unicode(self, context, ca_file):
481 """
482 Passing the path as unicode raises a warning but works.
483 """
484 pytest.deprecated_call(
485 context.load_client_ca, ca_file.decode("ascii")
486 )
487
488 def test_set_session_id(self, context):
489 """
Alex Chan532b79e2017-01-24 15:14:52 +0000490 `Context.set_session_id` works as far as we can tell.
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100491 """
492 context.set_session_id(b"abc")
493
494 def test_set_session_id_fail(self, context):
495 """
Alex Chan532b79e2017-01-24 15:14:52 +0000496 `Context.set_session_id` errors are propagated.
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100497 """
498 with pytest.raises(Error) as e:
499 context.set_session_id(b"abc" * 1000)
500
501 assert [
502 ("SSL routines",
503 "SSL_CTX_set_session_id_context",
504 "ssl session id context too long")
505 ] == e.value.args[0]
506
507 def test_set_session_id_unicode(self, context):
508 """
Alex Chan532b79e2017-01-24 15:14:52 +0000509 `Context.set_session_id` raises a warning if a unicode string is
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100510 passed.
511 """
512 pytest.deprecated_call(context.set_session_id, u"abc")
513
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400514 def test_method(self):
515 """
Alex Chan532b79e2017-01-24 15:14:52 +0000516 `Context` can be instantiated with one of `SSLv2_METHOD`,
517 `SSLv3_METHOD`, `SSLv23_METHOD`, `TLSv1_METHOD`, `TLSv1_1_METHOD`,
518 or `TLSv1_2_METHOD`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400519 """
Alex Gaynor5af32d02016-09-24 01:52:21 -0400520 methods = [SSLv23_METHOD, TLSv1_METHOD]
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400521 for meth in methods:
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400522 Context(meth)
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400523
Alex Gaynor5af32d02016-09-24 01:52:21 -0400524 maybe = [SSLv2_METHOD, SSLv3_METHOD, TLSv1_1_METHOD, TLSv1_2_METHOD]
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400525 for meth in maybe:
526 try:
527 Context(meth)
528 except (Error, ValueError):
529 # Some versions of OpenSSL have SSLv2 / TLSv1.1 / TLSv1.2, some
530 # don't. Difficult to say in advance.
531 pass
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400532
Alex Chan532b79e2017-01-24 15:14:52 +0000533 with pytest.raises(TypeError):
534 Context("")
535 with pytest.raises(ValueError):
536 Context(10)
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400537
Rick Deane15b1472009-07-09 15:53:42 -0500538 def test_type(self):
539 """
Alex Gaynor01f90a12019-02-07 09:14:48 -0500540 `Context` can be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -0500541 """
Alex Chan532b79e2017-01-24 15:14:52 +0000542 assert is_consistent_type(Context, 'Context', TLSv1_METHOD)
Rick Deane15b1472009-07-09 15:53:42 -0500543
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400544 def test_use_privatekey(self):
545 """
Alex Chan532b79e2017-01-24 15:14:52 +0000546 `Context.use_privatekey` takes an `OpenSSL.crypto.PKey` instance.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400547 """
548 key = PKey()
Alex Gaynor6e9f9762018-05-12 07:44:37 -0400549 key.generate_key(TYPE_RSA, 512)
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400550 ctx = Context(TLSv1_METHOD)
551 ctx.use_privatekey(key)
Alex Chan532b79e2017-01-24 15:14:52 +0000552 with pytest.raises(TypeError):
553 ctx.use_privatekey("")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400554
Alex Chan532b79e2017-01-24 15:14:52 +0000555 def test_use_privatekey_file_missing(self, tmpfile):
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800556 """
Alex Chan532b79e2017-01-24 15:14:52 +0000557 `Context.use_privatekey_file` raises `OpenSSL.SSL.Error` when passed
558 the name of a file which does not exist.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800559 """
560 ctx = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000561 with pytest.raises(Error):
562 ctx.use_privatekey_file(tmpfile)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800563
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400564 def _use_privatekey_file_test(self, pemfile, filetype):
565 """
566 Verify that calling ``Context.use_privatekey_file`` with the given
567 arguments does not raise an exception.
568 """
569 key = PKey()
Alex Gaynor6e9f9762018-05-12 07:44:37 -0400570 key.generate_key(TYPE_RSA, 512)
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400571
572 with open(pemfile, "wt") as pem:
573 pem.write(
574 dump_privatekey(FILETYPE_PEM, key).decode("ascii")
575 )
576
577 ctx = Context(TLSv1_METHOD)
578 ctx.use_privatekey_file(pemfile, filetype)
579
Alex Chanfb078d82017-04-20 11:16:15 +0100580 @pytest.mark.parametrize('filetype', [object(), "", None, 1.0])
581 def test_wrong_privatekey_file_wrong_args(self, tmpfile, filetype):
582 """
583 `Context.use_privatekey_file` raises `TypeError` when called with
584 a `filetype` which is not a valid file encoding.
585 """
586 ctx = Context(TLSv1_METHOD)
587 with pytest.raises(TypeError):
588 ctx.use_privatekey_file(tmpfile, filetype)
589
Alex Chan532b79e2017-01-24 15:14:52 +0000590 def test_use_privatekey_file_bytes(self, tmpfile):
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400591 """
592 A private key can be specified from a file by passing a ``bytes``
593 instance giving the file name to ``Context.use_privatekey_file``.
594 """
595 self._use_privatekey_file_test(
Alex Chan532b79e2017-01-24 15:14:52 +0000596 tmpfile + NON_ASCII.encode(getfilesystemencoding()),
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400597 FILETYPE_PEM,
598 )
599
Alex Chan532b79e2017-01-24 15:14:52 +0000600 def test_use_privatekey_file_unicode(self, tmpfile):
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400601 """
602 A private key can be specified from a file by passing a ``unicode``
603 instance giving the file name to ``Context.use_privatekey_file``.
604 """
605 self._use_privatekey_file_test(
Alex Chan532b79e2017-01-24 15:14:52 +0000606 tmpfile.decode(getfilesystemencoding()) + NON_ASCII,
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400607 FILETYPE_PEM,
608 )
609
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800610 def test_use_certificate_wrong_args(self):
611 """
Alex Chan532b79e2017-01-24 15:14:52 +0000612 `Context.use_certificate_wrong_args` raises `TypeError` when not passed
613 exactly one `OpenSSL.crypto.X509` instance as an argument.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800614 """
615 ctx = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000616 with pytest.raises(TypeError):
617 ctx.use_certificate("hello, world")
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800618
619 def test_use_certificate_uninitialized(self):
620 """
Alex Chan532b79e2017-01-24 15:14:52 +0000621 `Context.use_certificate` raises `OpenSSL.SSL.Error` when passed a
622 `OpenSSL.crypto.X509` instance which has not been initialized
623 (ie, which does not actually have any certificate data).
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800624 """
625 ctx = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000626 with pytest.raises(Error):
627 ctx.use_certificate(X509())
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800628
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800629 def test_use_certificate(self):
630 """
Alex Chan532b79e2017-01-24 15:14:52 +0000631 `Context.use_certificate` sets the certificate which will be
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800632 used to identify connections created using the context.
633 """
634 # TODO
635 # Hard to assert anything. But we could set a privatekey then ask
636 # OpenSSL if the cert and key agree using check_privatekey. Then as
637 # long as check_privatekey works right we're good...
638 ctx = Context(TLSv1_METHOD)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200639 ctx.use_certificate(
640 load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
641 )
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800642
643 def test_use_certificate_file_wrong_args(self):
644 """
Alex Chan532b79e2017-01-24 15:14:52 +0000645 `Context.use_certificate_file` raises `TypeError` if the first
646 argument is not a byte string or the second argument is not an integer.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800647 """
648 ctx = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000649 with pytest.raises(TypeError):
650 ctx.use_certificate_file(object(), FILETYPE_PEM)
651 with pytest.raises(TypeError):
652 ctx.use_certificate_file(b"somefile", object())
653 with pytest.raises(TypeError):
654 ctx.use_certificate_file(object(), FILETYPE_PEM)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800655
Alex Chan532b79e2017-01-24 15:14:52 +0000656 def test_use_certificate_file_missing(self, tmpfile):
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800657 """
Alex Chan532b79e2017-01-24 15:14:52 +0000658 `Context.use_certificate_file` raises `OpenSSL.SSL.Error` if passed
659 the name of a file which does not exist.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800660 """
661 ctx = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000662 with pytest.raises(Error):
663 ctx.use_certificate_file(tmpfile)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800664
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400665 def _use_certificate_file_test(self, certificate_file):
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800666 """
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400667 Verify that calling ``Context.use_certificate_file`` with the given
668 filename doesn't raise an exception.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800669 """
670 # TODO
671 # Hard to assert anything. But we could set a privatekey then ask
672 # OpenSSL if the cert and key agree using check_privatekey. Then as
673 # long as check_privatekey works right we're good...
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400674 with open(certificate_file, "wb") as pem_file:
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800675 pem_file.write(cleartextCertificatePEM)
676
677 ctx = Context(TLSv1_METHOD)
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400678 ctx.use_certificate_file(certificate_file)
679
Alex Chan532b79e2017-01-24 15:14:52 +0000680 def test_use_certificate_file_bytes(self, tmpfile):
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400681 """
Alex Chan532b79e2017-01-24 15:14:52 +0000682 `Context.use_certificate_file` sets the certificate (given as a
683 `bytes` filename) which will be used to identify connections created
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400684 using the context.
685 """
Alex Chan532b79e2017-01-24 15:14:52 +0000686 filename = tmpfile + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400687 self._use_certificate_file_test(filename)
688
Alex Chan532b79e2017-01-24 15:14:52 +0000689 def test_use_certificate_file_unicode(self, tmpfile):
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400690 """
Alex Chan532b79e2017-01-24 15:14:52 +0000691 `Context.use_certificate_file` sets the certificate (given as a
692 `bytes` filename) which will be used to identify connections created
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400693 using the context.
694 """
Alex Chan532b79e2017-01-24 15:14:52 +0000695 filename = tmpfile.decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400696 self._use_certificate_file_test(filename)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800697
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500698 def test_check_privatekey_valid(self):
699 """
Alex Chan532b79e2017-01-24 15:14:52 +0000700 `Context.check_privatekey` returns `None` if the `Context` instance
701 has been configured to use a matched key and certificate pair.
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500702 """
703 key = load_privatekey(FILETYPE_PEM, client_key_pem)
704 cert = load_certificate(FILETYPE_PEM, client_cert_pem)
705 context = Context(TLSv1_METHOD)
706 context.use_privatekey(key)
707 context.use_certificate(cert)
Alex Chan532b79e2017-01-24 15:14:52 +0000708 assert None is context.check_privatekey()
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500709
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500710 def test_check_privatekey_invalid(self):
711 """
Alex Chan532b79e2017-01-24 15:14:52 +0000712 `Context.check_privatekey` raises `Error` if the `Context` instance
713 has been configured to use a key and certificate pair which don't
714 relate to each other.
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500715 """
716 key = load_privatekey(FILETYPE_PEM, client_key_pem)
717 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
718 context = Context(TLSv1_METHOD)
719 context.use_privatekey(key)
720 context.use_certificate(cert)
Alex Chan532b79e2017-01-24 15:14:52 +0000721 with pytest.raises(Error):
722 context.check_privatekey()
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400723
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400724 def test_app_data(self):
725 """
Alex Chan532b79e2017-01-24 15:14:52 +0000726 `Context.set_app_data` stores an object for later retrieval
727 using `Context.get_app_data`.
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400728 """
729 app_data = object()
730 context = Context(TLSv1_METHOD)
731 context.set_app_data(app_data)
Alex Chan532b79e2017-01-24 15:14:52 +0000732 assert context.get_app_data() is app_data
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400733
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400734 def test_set_options_wrong_args(self):
735 """
Alex Chan532b79e2017-01-24 15:14:52 +0000736 `Context.set_options` raises `TypeError` if called with
737 a non-`int` argument.
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400738 """
739 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000740 with pytest.raises(TypeError):
741 context.set_options(None)
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400742
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500743 def test_set_options(self):
744 """
Alex Chan532b79e2017-01-24 15:14:52 +0000745 `Context.set_options` returns the new options value.
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500746 """
747 context = Context(TLSv1_METHOD)
748 options = context.set_options(OP_NO_SSLv2)
Alex Gaynor2310f8b2016-09-10 14:39:32 -0400749 assert options & OP_NO_SSLv2 == OP_NO_SSLv2
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500750
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300751 def test_set_mode_wrong_args(self):
752 """
Alex Chan532b79e2017-01-24 15:14:52 +0000753 `Context.set_mode` raises `TypeError` if called with
754 a non-`int` argument.
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300755 """
756 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000757 with pytest.raises(TypeError):
758 context.set_mode(None)
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300759
Alex Gaynord3b5d9b2016-07-31 10:54:24 -0400760 def test_set_mode(self):
761 """
Alex Chan532b79e2017-01-24 15:14:52 +0000762 `Context.set_mode` accepts a mode bitvector and returns the
Alex Gaynord3b5d9b2016-07-31 10:54:24 -0400763 newly set mode.
764 """
765 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000766 assert MODE_RELEASE_BUFFERS & context.set_mode(MODE_RELEASE_BUFFERS)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500767
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400768 def test_set_timeout_wrong_args(self):
769 """
Alex Chan532b79e2017-01-24 15:14:52 +0000770 `Context.set_timeout` raises `TypeError` if called with
771 a non-`int` argument.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400772 """
773 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000774 with pytest.raises(TypeError):
775 context.set_timeout(None)
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400776
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400777 def test_timeout(self):
778 """
Alex Chan532b79e2017-01-24 15:14:52 +0000779 `Context.set_timeout` sets the session timeout for all connections
780 created using the context object. `Context.get_timeout` retrieves
781 this value.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400782 """
783 context = Context(TLSv1_METHOD)
784 context.set_timeout(1234)
Alex Chan532b79e2017-01-24 15:14:52 +0000785 assert context.get_timeout() == 1234
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400786
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400787 def test_set_verify_depth_wrong_args(self):
788 """
Alex Chan532b79e2017-01-24 15:14:52 +0000789 `Context.set_verify_depth` raises `TypeError` if called with a
790 non-`int` argument.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400791 """
792 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000793 with pytest.raises(TypeError):
794 context.set_verify_depth(None)
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400795
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400796 def test_verify_depth(self):
797 """
Alex Chan532b79e2017-01-24 15:14:52 +0000798 `Context.set_verify_depth` sets the number of certificates in
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200799 a chain to follow before giving up. The value can be retrieved with
Alex Chan532b79e2017-01-24 15:14:52 +0000800 `Context.get_verify_depth`.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400801 """
802 context = Context(TLSv1_METHOD)
803 context.set_verify_depth(11)
Alex Chan532b79e2017-01-24 15:14:52 +0000804 assert context.get_verify_depth() == 11
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400805
Alex Chan532b79e2017-01-24 15:14:52 +0000806 def _write_encrypted_pem(self, passphrase, tmpfile):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400807 """
808 Write a new private key out to a new file, encrypted using the given
809 passphrase. Return the path to the new file.
810 """
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400811 key = PKey()
Alex Gaynor6e9f9762018-05-12 07:44:37 -0400812 key.generate_key(TYPE_RSA, 512)
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400813 pem = dump_privatekey(FILETYPE_PEM, key, "blowfish", passphrase)
Alex Chan532b79e2017-01-24 15:14:52 +0000814 with open(tmpfile, 'w') as fObj:
815 fObj.write(pem.decode('ascii'))
816 return tmpfile
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400817
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400818 def test_set_passwd_cb_wrong_args(self):
819 """
Alex Chan532b79e2017-01-24 15:14:52 +0000820 `Context.set_passwd_cb` raises `TypeError` if called with a
821 non-callable first argument.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400822 """
823 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000824 with pytest.raises(TypeError):
825 context.set_passwd_cb(None)
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400826
Alex Chan532b79e2017-01-24 15:14:52 +0000827 def test_set_passwd_cb(self, tmpfile):
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400828 """
Alex Chan532b79e2017-01-24 15:14:52 +0000829 `Context.set_passwd_cb` accepts a callable which will be invoked when
830 a private key is loaded from an encrypted PEM.
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400831 """
Alex Gaynore7f51982016-09-11 11:48:14 -0400832 passphrase = b"foobar"
Alex Chan532b79e2017-01-24 15:14:52 +0000833 pemFile = self._write_encrypted_pem(passphrase, tmpfile)
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400834 calledWith = []
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200835
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400836 def passphraseCallback(maxlen, verify, extra):
837 calledWith.append((maxlen, verify, extra))
838 return passphrase
839 context = Context(TLSv1_METHOD)
840 context.set_passwd_cb(passphraseCallback)
841 context.use_privatekey_file(pemFile)
Alex Chan532b79e2017-01-24 15:14:52 +0000842 assert len(calledWith) == 1
843 assert isinstance(calledWith[0][0], int)
844 assert isinstance(calledWith[0][1], int)
845 assert calledWith[0][2] is None
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400846
Alex Chan532b79e2017-01-24 15:14:52 +0000847 def test_passwd_callback_exception(self, tmpfile):
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400848 """
Alex Chan532b79e2017-01-24 15:14:52 +0000849 `Context.use_privatekey_file` propagates any exception raised
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200850 by the passphrase callback.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400851 """
Alex Chan532b79e2017-01-24 15:14:52 +0000852 pemFile = self._write_encrypted_pem(b"monkeys are nice", tmpfile)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200853
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400854 def passphraseCallback(maxlen, verify, extra):
855 raise RuntimeError("Sorry, I am a fail.")
856
857 context = Context(TLSv1_METHOD)
858 context.set_passwd_cb(passphraseCallback)
Alex Chan532b79e2017-01-24 15:14:52 +0000859 with pytest.raises(RuntimeError):
860 context.use_privatekey_file(pemFile)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400861
Alex Chan532b79e2017-01-24 15:14:52 +0000862 def test_passwd_callback_false(self, tmpfile):
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400863 """
Alex Chan532b79e2017-01-24 15:14:52 +0000864 `Context.use_privatekey_file` raises `OpenSSL.SSL.Error` if the
865 passphrase callback returns a false value.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400866 """
Alex Chan532b79e2017-01-24 15:14:52 +0000867 pemFile = self._write_encrypted_pem(b"monkeys are nice", tmpfile)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200868
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400869 def passphraseCallback(maxlen, verify, extra):
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500870 return b""
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400871
872 context = Context(TLSv1_METHOD)
873 context.set_passwd_cb(passphraseCallback)
Alex Chan532b79e2017-01-24 15:14:52 +0000874 with pytest.raises(Error):
875 context.use_privatekey_file(pemFile)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400876
Alex Chan532b79e2017-01-24 15:14:52 +0000877 def test_passwd_callback_non_string(self, tmpfile):
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400878 """
Alex Chan532b79e2017-01-24 15:14:52 +0000879 `Context.use_privatekey_file` raises `OpenSSL.SSL.Error` if the
880 passphrase callback returns a true non-string value.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400881 """
Alex Chan532b79e2017-01-24 15:14:52 +0000882 pemFile = self._write_encrypted_pem(b"monkeys are nice", tmpfile)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200883
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400884 def passphraseCallback(maxlen, verify, extra):
885 return 10
886
887 context = Context(TLSv1_METHOD)
888 context.set_passwd_cb(passphraseCallback)
Alex Chan532b79e2017-01-24 15:14:52 +0000889 # TODO: Surely this is the wrong error?
890 with pytest.raises(ValueError):
891 context.use_privatekey_file(pemFile)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400892
Alex Chan532b79e2017-01-24 15:14:52 +0000893 def test_passwd_callback_too_long(self, tmpfile):
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400894 """
895 If the passphrase returned by the passphrase callback returns a string
896 longer than the indicated maximum length, it is truncated.
897 """
898 # A priori knowledge!
Alex Gaynore7f51982016-09-11 11:48:14 -0400899 passphrase = b"x" * 1024
Alex Chan532b79e2017-01-24 15:14:52 +0000900 pemFile = self._write_encrypted_pem(passphrase, tmpfile)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200901
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400902 def passphraseCallback(maxlen, verify, extra):
903 assert maxlen == 1024
Alex Gaynore7f51982016-09-11 11:48:14 -0400904 return passphrase + b"y"
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400905
906 context = Context(TLSv1_METHOD)
907 context.set_passwd_cb(passphraseCallback)
908 # This shall succeed because the truncated result is the correct
909 # passphrase.
910 context.use_privatekey_file(pemFile)
911
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400912 def test_set_info_callback(self):
913 """
Alex Chan532b79e2017-01-24 15:14:52 +0000914 `Context.set_info_callback` accepts a callable which will be
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200915 invoked when certain information about an SSL connection is available.
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400916 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500917 (server, client) = socket_pair()
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400918
919 clientSSL = Connection(Context(TLSv1_METHOD), client)
920 clientSSL.set_connect_state()
921
922 called = []
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200923
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400924 def info(conn, where, ret):
925 called.append((conn, where, ret))
926 context = Context(TLSv1_METHOD)
927 context.set_info_callback(info)
928 context.use_certificate(
929 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
930 context.use_privatekey(
931 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
932
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400933 serverSSL = Connection(context, server)
934 serverSSL.set_accept_state()
935
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -0500936 handshake(clientSSL, serverSSL)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400937
Jean-Paul Calderone3835e522014-02-02 11:12:30 -0500938 # The callback must always be called with a Connection instance as the
939 # first argument. It would probably be better to split this into
940 # separate tests for client and server side info callbacks so we could
941 # assert it is called with the right Connection instance. It would
942 # also be good to assert *something* about `where` and `ret`.
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -0500943 notConnections = [
944 conn for (conn, where, ret) in called
945 if not isinstance(conn, Connection)]
Alex Chan532b79e2017-01-24 15:14:52 +0000946 assert [] == notConnections, (
947 "Some info callback arguments were not Connection instances.")
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400948
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400949 def _load_verify_locations_test(self, *args):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400950 """
951 Create a client context which will verify the peer certificate and call
Alex Chan532b79e2017-01-24 15:14:52 +0000952 its `load_verify_locations` method with the given arguments.
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -0400953 Then connect it to a server and ensure that the handshake succeeds.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400954 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500955 (server, client) = socket_pair()
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400956
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400957 clientContext = Context(TLSv1_METHOD)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400958 clientContext.load_verify_locations(*args)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400959 # Require that the server certificate verify properly or the
960 # connection will fail.
961 clientContext.set_verify(
962 VERIFY_PEER,
963 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
964
965 clientSSL = Connection(clientContext, client)
966 clientSSL.set_connect_state()
967
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400968 serverContext = Context(TLSv1_METHOD)
969 serverContext.use_certificate(
970 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
971 serverContext.use_privatekey(
972 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
973
974 serverSSL = Connection(serverContext, server)
975 serverSSL.set_accept_state()
976
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400977 # Without load_verify_locations above, the handshake
978 # will fail:
979 # Error: [('SSL routines', 'SSL3_GET_SERVER_CERTIFICATE',
980 # 'certificate verify failed')]
981 handshake(clientSSL, serverSSL)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400982
983 cert = clientSSL.get_peer_certificate()
Alex Chan532b79e2017-01-24 15:14:52 +0000984 assert cert.get_subject().CN == 'Testing Root CA'
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400985
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400986 def _load_verify_cafile(self, cafile):
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400987 """
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400988 Verify that if path to a file containing a certificate is passed to
Alex Chan532b79e2017-01-24 15:14:52 +0000989 `Context.load_verify_locations` for the ``cafile`` parameter, that
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400990 certificate is used as a trust root for the purposes of verifying
Alex Chan532b79e2017-01-24 15:14:52 +0000991 connections created using that `Context`.
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400992 """
Alex Chan532b79e2017-01-24 15:14:52 +0000993 with open(cafile, 'w') as fObj:
994 fObj.write(cleartextCertificatePEM.decode('ascii'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400995
996 self._load_verify_locations_test(cafile)
997
Alex Chan532b79e2017-01-24 15:14:52 +0000998 def test_load_verify_bytes_cafile(self, tmpfile):
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400999 """
Alex Chan532b79e2017-01-24 15:14:52 +00001000 `Context.load_verify_locations` accepts a file name as a `bytes`
1001 instance and uses the certificates within for verification purposes.
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001002 """
Alex Chan532b79e2017-01-24 15:14:52 +00001003 cafile = tmpfile + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001004 self._load_verify_cafile(cafile)
1005
Alex Chan532b79e2017-01-24 15:14:52 +00001006 def test_load_verify_unicode_cafile(self, tmpfile):
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001007 """
Alex Chan532b79e2017-01-24 15:14:52 +00001008 `Context.load_verify_locations` accepts a file name as a `unicode`
1009 instance and uses the certificates within for verification purposes.
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001010 """
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001011 self._load_verify_cafile(
Alex Chan532b79e2017-01-24 15:14:52 +00001012 tmpfile.decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001013 )
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001014
Alex Chan532b79e2017-01-24 15:14:52 +00001015 def test_load_verify_invalid_file(self, tmpfile):
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -04001016 """
Alex Chan532b79e2017-01-24 15:14:52 +00001017 `Context.load_verify_locations` raises `Error` when passed a
1018 non-existent cafile.
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -04001019 """
1020 clientContext = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001021 with pytest.raises(Error):
1022 clientContext.load_verify_locations(tmpfile)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001023
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001024 def _load_verify_directory_locations_capath(self, capath):
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001025 """
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001026 Verify that if path to a directory containing certificate files is
1027 passed to ``Context.load_verify_locations`` for the ``capath``
1028 parameter, those certificates are used as trust roots for the purposes
1029 of verifying connections created using that ``Context``.
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001030 """
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001031 makedirs(capath)
Jean-Paul Calderone24dfb332011-05-04 18:10:26 -04001032 # Hash values computed manually with c_rehash to avoid depending on
1033 # c_rehash in the test suite. One is from OpenSSL 0.9.8, the other
1034 # from OpenSSL 1.0.0.
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001035 for name in [b'c7adac82.0', b'c3705638.0']:
Jean-Paul Calderone05826732015-04-12 11:38:49 -04001036 cafile = join_bytes_or_unicode(capath, name)
1037 with open(cafile, 'w') as fObj:
1038 fObj.write(cleartextCertificatePEM.decode('ascii'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001039
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001040 self._load_verify_locations_test(None, capath)
1041
Alex Chan532b79e2017-01-24 15:14:52 +00001042 def test_load_verify_directory_bytes_capath(self, tmpfile):
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001043 """
Alex Chan532b79e2017-01-24 15:14:52 +00001044 `Context.load_verify_locations` accepts a directory name as a `bytes`
1045 instance and uses the certificates within for verification purposes.
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001046 """
1047 self._load_verify_directory_locations_capath(
Alex Chan532b79e2017-01-24 15:14:52 +00001048 tmpfile + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001049 )
1050
Alex Chan532b79e2017-01-24 15:14:52 +00001051 def test_load_verify_directory_unicode_capath(self, tmpfile):
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001052 """
Alex Chan532b79e2017-01-24 15:14:52 +00001053 `Context.load_verify_locations` accepts a directory name as a `unicode`
1054 instance and uses the certificates within for verification purposes.
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001055 """
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001056 self._load_verify_directory_locations_capath(
Alex Chan532b79e2017-01-24 15:14:52 +00001057 tmpfile.decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001058 )
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001059
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001060 def test_load_verify_locations_wrong_args(self):
1061 """
Alex Chan532b79e2017-01-24 15:14:52 +00001062 `Context.load_verify_locations` raises `TypeError` if with non-`str`
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001063 arguments.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001064 """
1065 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001066 with pytest.raises(TypeError):
1067 context.load_verify_locations(object())
1068 with pytest.raises(TypeError):
1069 context.load_verify_locations(object(), object())
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001070
Hynek Schlawack734d3022015-09-05 19:19:32 +02001071 @pytest.mark.skipif(
Paul Kehrer55fb3412017-06-29 18:44:08 -05001072 not platform.startswith("linux"),
1073 reason="Loading fallback paths is a linux-specific behavior to "
1074 "accommodate pyca/cryptography manylinux1 wheels"
1075 )
1076 def test_fallback_default_verify_paths(self, monkeypatch):
1077 """
1078 Test that we load certificates successfully on linux from the fallback
1079 path. To do this we set the _CRYPTOGRAPHY_MANYLINUX1_CA_FILE and
1080 _CRYPTOGRAPHY_MANYLINUX1_CA_DIR vars to be equal to whatever the
1081 current OpenSSL default is and we disable
1082 SSL_CTX_SET_default_verify_paths so that it can't find certs unless
1083 it loads via fallback.
1084 """
1085 context = Context(TLSv1_METHOD)
1086 monkeypatch.setattr(
1087 _lib, "SSL_CTX_set_default_verify_paths", lambda x: 1
1088 )
1089 monkeypatch.setattr(
1090 SSL,
1091 "_CRYPTOGRAPHY_MANYLINUX1_CA_FILE",
1092 _ffi.string(_lib.X509_get_default_cert_file())
1093 )
1094 monkeypatch.setattr(
1095 SSL,
1096 "_CRYPTOGRAPHY_MANYLINUX1_CA_DIR",
1097 _ffi.string(_lib.X509_get_default_cert_dir())
1098 )
1099 context.set_default_verify_paths()
1100 store = context.get_cert_store()
1101 sk_obj = _lib.X509_STORE_get0_objects(store._store)
1102 assert sk_obj != _ffi.NULL
1103 num = _lib.sk_X509_OBJECT_num(sk_obj)
1104 assert num != 0
1105
1106 def test_check_env_vars(self, monkeypatch):
1107 """
1108 Test that we return True/False appropriately if the env vars are set.
1109 """
1110 context = Context(TLSv1_METHOD)
1111 dir_var = "CUSTOM_DIR_VAR"
1112 file_var = "CUSTOM_FILE_VAR"
1113 assert context._check_env_vars_set(dir_var, file_var) is False
1114 monkeypatch.setenv(dir_var, "value")
1115 monkeypatch.setenv(file_var, "value")
1116 assert context._check_env_vars_set(dir_var, file_var) is True
1117 assert context._check_env_vars_set(dir_var, file_var) is True
1118
1119 def test_verify_no_fallback_if_env_vars_set(self, monkeypatch):
1120 """
1121 Test that we don't use the fallback path if env vars are set.
1122 """
1123 context = Context(TLSv1_METHOD)
1124 monkeypatch.setattr(
1125 _lib, "SSL_CTX_set_default_verify_paths", lambda x: 1
1126 )
1127 dir_env_var = _ffi.string(
1128 _lib.X509_get_default_cert_dir_env()
1129 ).decode("ascii")
1130 file_env_var = _ffi.string(
1131 _lib.X509_get_default_cert_file_env()
1132 ).decode("ascii")
1133 monkeypatch.setenv(dir_env_var, "value")
1134 monkeypatch.setenv(file_env_var, "value")
1135 context.set_default_verify_paths()
1136
1137 monkeypatch.setattr(
1138 context,
1139 "_fallback_default_verify_paths",
1140 raiser(SystemError)
1141 )
1142 context.set_default_verify_paths()
1143
1144 @pytest.mark.skipif(
Hynek Schlawack734d3022015-09-05 19:19:32 +02001145 platform == "win32",
1146 reason="set_default_verify_paths appears not to work on Windows. "
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -04001147 "See LP#404343 and LP#404344."
Hynek Schlawack734d3022015-09-05 19:19:32 +02001148 )
1149 def test_set_default_verify_paths(self):
1150 """
Alex Chan532b79e2017-01-24 15:14:52 +00001151 `Context.set_default_verify_paths` causes the platform-specific CA
1152 certificate locations to be used for verification purposes.
Hynek Schlawack734d3022015-09-05 19:19:32 +02001153 """
1154 # Testing this requires a server with a certificate signed by one
1155 # of the CAs in the platform CA location. Getting one of those
1156 # costs money. Fortunately (or unfortunately, depending on your
1157 # perspective), it's easy to think of a public server on the
1158 # internet which has such a certificate. Connecting to the network
1159 # in a unit test is bad, but it's the only way I can think of to
1160 # really test this. -exarkun
Hynek Schlawackbf887932015-10-21 17:13:47 +02001161 context = Context(SSLv23_METHOD)
Hynek Schlawack734d3022015-09-05 19:19:32 +02001162 context.set_default_verify_paths()
1163 context.set_verify(
1164 VERIFY_PEER,
1165 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001166
David Benjamin1fbe0642019-04-15 17:05:13 -05001167 client = socket_any_family()
Hynek Schlawackbf887932015-10-21 17:13:47 +02001168 client.connect(("encrypted.google.com", 443))
Hynek Schlawack734d3022015-09-05 19:19:32 +02001169 clientSSL = Connection(context, client)
1170 clientSSL.set_connect_state()
Alex Gaynor373926c2018-05-12 07:43:07 -04001171 clientSSL.set_tlsext_host_name(b"encrypted.google.com")
Hynek Schlawack734d3022015-09-05 19:19:32 +02001172 clientSSL.do_handshake()
1173 clientSSL.send(b"GET / HTTP/1.0\r\n\r\n")
Alex Chan532b79e2017-01-24 15:14:52 +00001174 assert clientSSL.recv(1024)
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05001175
Paul Kehrer55fb3412017-06-29 18:44:08 -05001176 def test_fallback_path_is_not_file_or_dir(self):
1177 """
1178 Test that when passed empty arrays or paths that do not exist no
1179 errors are raised.
1180 """
1181 context = Context(TLSv1_METHOD)
1182 context._fallback_default_verify_paths([], [])
1183 context._fallback_default_verify_paths(
1184 ["/not/a/file"], ["/not/a/dir"]
1185 )
1186
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001187 def test_add_extra_chain_cert_invalid_cert(self):
1188 """
Alex Chan532b79e2017-01-24 15:14:52 +00001189 `Context.add_extra_chain_cert` raises `TypeError` if called with an
1190 object which is not an instance of `X509`.
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001191 """
1192 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001193 with pytest.raises(TypeError):
1194 context.add_extra_chain_cert(object())
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001195
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001196 def _handshake_test(self, serverContext, clientContext):
1197 """
1198 Verify that a client and server created with the given contexts can
1199 successfully handshake and communicate.
1200 """
1201 serverSocket, clientSocket = socket_pair()
1202
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001203 server = Connection(serverContext, serverSocket)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001204 server.set_accept_state()
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001205
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001206 client = Connection(clientContext, clientSocket)
1207 client.set_connect_state()
1208
1209 # Make them talk to each other.
Alex Chan532b79e2017-01-24 15:14:52 +00001210 # interact_in_memory(client, server)
1211 for _ in range(3):
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001212 for s in [client, server]:
1213 try:
1214 s.do_handshake()
1215 except WantReadError:
1216 pass
1217
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001218 def test_set_verify_callback_connection_argument(self):
1219 """
1220 The first argument passed to the verify callback is the
Alex Chan532b79e2017-01-24 15:14:52 +00001221 `Connection` instance for which verification is taking place.
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001222 """
1223 serverContext = Context(TLSv1_METHOD)
1224 serverContext.use_privatekey(
1225 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1226 serverContext.use_certificate(
1227 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1228 serverConnection = Connection(serverContext, None)
1229
1230 class VerifyCallback(object):
1231 def callback(self, connection, *args):
1232 self.connection = connection
1233 return 1
1234
1235 verify = VerifyCallback()
1236 clientContext = Context(TLSv1_METHOD)
1237 clientContext.set_verify(VERIFY_PEER, verify.callback)
1238 clientConnection = Connection(clientContext, None)
1239 clientConnection.set_connect_state()
1240
Alex Chan532b79e2017-01-24 15:14:52 +00001241 handshake_in_memory(clientConnection, serverConnection)
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001242
Alex Chan532b79e2017-01-24 15:14:52 +00001243 assert verify.connection is clientConnection
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001244
Paul Kehrere7381862017-11-30 20:55:25 +08001245 def test_x509_in_verify_works(self):
1246 """
1247 We had a bug where the X509 cert instantiated in the callback wrapper
1248 didn't __init__ so it was missing objects needed when calling
1249 get_subject. This test sets up a handshake where we call get_subject
1250 on the cert provided to the verify callback.
1251 """
1252 serverContext = Context(TLSv1_METHOD)
1253 serverContext.use_privatekey(
1254 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1255 serverContext.use_certificate(
1256 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1257 serverConnection = Connection(serverContext, None)
1258
1259 def verify_cb_get_subject(conn, cert, errnum, depth, ok):
1260 assert cert.get_subject()
1261 return 1
1262
1263 clientContext = Context(TLSv1_METHOD)
1264 clientContext.set_verify(VERIFY_PEER, verify_cb_get_subject)
1265 clientConnection = Connection(clientContext, None)
1266 clientConnection.set_connect_state()
1267
1268 handshake_in_memory(clientConnection, serverConnection)
1269
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001270 def test_set_verify_callback_exception(self):
1271 """
Alex Chan532b79e2017-01-24 15:14:52 +00001272 If the verify callback passed to `Context.set_verify` raises an
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001273 exception, verification fails and the exception is propagated to the
Alex Chan532b79e2017-01-24 15:14:52 +00001274 caller of `Connection.do_handshake`.
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001275 """
Paul Kehrer7d5a3bf2019-01-21 12:24:02 -06001276 serverContext = Context(TLSv1_2_METHOD)
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001277 serverContext.use_privatekey(
1278 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1279 serverContext.use_certificate(
1280 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1281
Paul Kehrer7d5a3bf2019-01-21 12:24:02 -06001282 clientContext = Context(TLSv1_2_METHOD)
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001283
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001284 def verify_callback(*args):
1285 raise Exception("silly verify failure")
1286 clientContext.set_verify(VERIFY_PEER, verify_callback)
1287
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01001288 with pytest.raises(Exception) as exc:
1289 self._handshake_test(serverContext, clientContext)
1290
Alex Chan532b79e2017-01-24 15:14:52 +00001291 assert "silly verify failure" == str(exc.value)
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001292
Alex Chan532b79e2017-01-24 15:14:52 +00001293 def test_add_extra_chain_cert(self, tmpdir):
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001294 """
Alex Chan532b79e2017-01-24 15:14:52 +00001295 `Context.add_extra_chain_cert` accepts an `X509`
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001296 instance to add to the certificate chain.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001297
Alex Chan532b79e2017-01-24 15:14:52 +00001298 See `_create_certificate_chain` for the details of the
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001299 certificate chain tested.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001300
1301 The chain is tested by starting a server with scert and connecting
1302 to it with a client which trusts cacert and requires verification to
1303 succeed.
1304 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001305 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001306 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1307
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001308 # Dump the CA certificate to a file because that's the only way to load
1309 # it as a trusted CA in the client context.
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001310 for cert, name in [(cacert, 'ca.pem'),
1311 (icert, 'i.pem'),
1312 (scert, 's.pem')]:
Alex Chan532b79e2017-01-24 15:14:52 +00001313 with tmpdir.join(name).open('w') as f:
Hynek Schlawacke90680f2015-04-16 15:09:27 -04001314 f.write(dump_certificate(FILETYPE_PEM, cert).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001315
Hynek Schlawack1902c012015-04-16 15:06:41 -04001316 for key, name in [(cakey, 'ca.key'),
1317 (ikey, 'i.key'),
1318 (skey, 's.key')]:
Alex Chan532b79e2017-01-24 15:14:52 +00001319 with tmpdir.join(name).open('w') as f:
Hynek Schlawacke90680f2015-04-16 15:09:27 -04001320 f.write(dump_privatekey(FILETYPE_PEM, key).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001321
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001322 # Create the server context
1323 serverContext = Context(TLSv1_METHOD)
1324 serverContext.use_privatekey(skey)
1325 serverContext.use_certificate(scert)
Jean-Paul Calderone16cf03d2010-09-08 18:53:39 -04001326 # The client already has cacert, we only need to give them icert.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001327 serverContext.add_extra_chain_cert(icert)
1328
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001329 # Create the client
1330 clientContext = Context(TLSv1_METHOD)
1331 clientContext.set_verify(
1332 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Alex Chan532b79e2017-01-24 15:14:52 +00001333 clientContext.load_verify_locations(str(tmpdir.join("ca.pem")))
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001334
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001335 # Try it out.
1336 self._handshake_test(serverContext, clientContext)
1337
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001338 def _use_certificate_chain_file_test(self, certdir):
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001339 """
Alex Chan532b79e2017-01-24 15:14:52 +00001340 Verify that `Context.use_certificate_chain_file` reads a
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001341 certificate chain from a specified file.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001342
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001343 The chain is tested by starting a server with scert and connecting to
1344 it with a client which trusts cacert and requires verification to
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001345 succeed.
1346 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001347 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001348 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1349
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001350 makedirs(certdir)
1351
Jean-Paul Calderone05826732015-04-12 11:38:49 -04001352 chainFile = join_bytes_or_unicode(certdir, "chain.pem")
1353 caFile = join_bytes_or_unicode(certdir, "ca.pem")
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001354
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001355 # Write out the chain file.
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001356 with open(chainFile, 'wb') as fObj:
1357 # Most specific to least general.
1358 fObj.write(dump_certificate(FILETYPE_PEM, scert))
1359 fObj.write(dump_certificate(FILETYPE_PEM, icert))
1360 fObj.write(dump_certificate(FILETYPE_PEM, cacert))
1361
1362 with open(caFile, 'w') as fObj:
1363 fObj.write(dump_certificate(FILETYPE_PEM, cacert).decode('ascii'))
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001364
1365 serverContext = Context(TLSv1_METHOD)
1366 serverContext.use_certificate_chain_file(chainFile)
1367 serverContext.use_privatekey(skey)
1368
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001369 clientContext = Context(TLSv1_METHOD)
1370 clientContext.set_verify(
1371 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001372 clientContext.load_verify_locations(caFile)
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001373
1374 self._handshake_test(serverContext, clientContext)
1375
Alex Chan532b79e2017-01-24 15:14:52 +00001376 def test_use_certificate_chain_file_bytes(self, tmpfile):
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001377 """
1378 ``Context.use_certificate_chain_file`` accepts the name of a file (as
1379 an instance of ``bytes``) to specify additional certificates to use to
1380 construct and verify a trust chain.
1381 """
1382 self._use_certificate_chain_file_test(
Alex Chan532b79e2017-01-24 15:14:52 +00001383 tmpfile + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001384 )
1385
Alex Chan532b79e2017-01-24 15:14:52 +00001386 def test_use_certificate_chain_file_unicode(self, tmpfile):
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001387 """
1388 ``Context.use_certificate_chain_file`` accepts the name of a file (as
1389 an instance of ``unicode``) to specify additional certificates to use
1390 to construct and verify a trust chain.
1391 """
1392 self._use_certificate_chain_file_test(
Alex Chan532b79e2017-01-24 15:14:52 +00001393 tmpfile.decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001394 )
1395
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001396 def test_use_certificate_chain_file_wrong_args(self):
1397 """
Alex Chan532b79e2017-01-24 15:14:52 +00001398 `Context.use_certificate_chain_file` raises `TypeError` if passed a
1399 non-byte string single argument.
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001400 """
1401 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001402 with pytest.raises(TypeError):
1403 context.use_certificate_chain_file(object())
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001404
Alex Chan532b79e2017-01-24 15:14:52 +00001405 def test_use_certificate_chain_file_missing_file(self, tmpfile):
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001406 """
Alex Chan532b79e2017-01-24 15:14:52 +00001407 `Context.use_certificate_chain_file` raises `OpenSSL.SSL.Error` when
1408 passed a bad chain file name (for example, the name of a file which
1409 does not exist).
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001410 """
1411 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001412 with pytest.raises(Error):
1413 context.use_certificate_chain_file(tmpfile)
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001414
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001415 def test_set_verify_mode(self):
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001416 """
Alex Chan532b79e2017-01-24 15:14:52 +00001417 `Context.get_verify_mode` returns the verify mode flags previously
1418 passed to `Context.set_verify`.
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001419 """
1420 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001421 assert context.get_verify_mode() == 0
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001422 context.set_verify(
1423 VERIFY_PEER | VERIFY_CLIENT_ONCE, lambda *args: None)
Alex Chan532b79e2017-01-24 15:14:52 +00001424 assert context.get_verify_mode() == (VERIFY_PEER | VERIFY_CLIENT_ONCE)
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001425
Alex Chanfb078d82017-04-20 11:16:15 +01001426 @pytest.mark.parametrize('mode', [None, 1.0, object(), 'mode'])
1427 def test_set_verify_wrong_mode_arg(self, mode):
1428 """
1429 `Context.set_verify` raises `TypeError` if the first argument is
1430 not an integer.
1431 """
1432 context = Context(TLSv1_METHOD)
1433 with pytest.raises(TypeError):
1434 context.set_verify(mode=mode, callback=lambda *args: None)
1435
1436 @pytest.mark.parametrize('callback', [None, 1.0, 'mode', ('foo', 'bar')])
1437 def test_set_verify_wrong_callable_arg(self, callback):
1438 """
Alex Gaynor40bc0f12018-05-14 14:06:16 -04001439 `Context.set_verify` raises `TypeError` if the second argument
Alex Chanfb078d82017-04-20 11:16:15 +01001440 is not callable.
1441 """
1442 context = Context(TLSv1_METHOD)
1443 with pytest.raises(TypeError):
1444 context.set_verify(mode=VERIFY_PEER, callback=callback)
1445
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001446 def test_load_tmp_dh_wrong_args(self):
1447 """
Alex Chan532b79e2017-01-24 15:14:52 +00001448 `Context.load_tmp_dh` raises `TypeError` if called with a
1449 non-`str` argument.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001450 """
1451 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001452 with pytest.raises(TypeError):
1453 context.load_tmp_dh(object())
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001454
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001455 def test_load_tmp_dh_missing_file(self):
1456 """
Alex Chan532b79e2017-01-24 15:14:52 +00001457 `Context.load_tmp_dh` raises `OpenSSL.SSL.Error` if the
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001458 specified file does not exist.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001459 """
1460 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001461 with pytest.raises(Error):
1462 context.load_tmp_dh(b"hello")
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001463
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001464 def _load_tmp_dh_test(self, dhfilename):
Jean-Paul Calderone4e0c43f2015-04-13 10:15:17 -04001465 """
1466 Verify that calling ``Context.load_tmp_dh`` with the given filename
1467 does not raise an exception.
1468 """
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001469 context = Context(TLSv1_METHOD)
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001470 with open(dhfilename, "w") as dhfile:
1471 dhfile.write(dhparam)
1472
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001473 context.load_tmp_dh(dhfilename)
1474 # XXX What should I assert here? -exarkun
1475
Alex Chan532b79e2017-01-24 15:14:52 +00001476 def test_load_tmp_dh_bytes(self, tmpfile):
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001477 """
Alex Chan532b79e2017-01-24 15:14:52 +00001478 `Context.load_tmp_dh` loads Diffie-Hellman parameters from the
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001479 specified file (given as ``bytes``).
1480 """
1481 self._load_tmp_dh_test(
Alex Chan532b79e2017-01-24 15:14:52 +00001482 tmpfile + NON_ASCII.encode(getfilesystemencoding()),
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001483 )
1484
Alex Chan532b79e2017-01-24 15:14:52 +00001485 def test_load_tmp_dh_unicode(self, tmpfile):
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001486 """
Alex Chan532b79e2017-01-24 15:14:52 +00001487 `Context.load_tmp_dh` loads Diffie-Hellman parameters from the
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001488 specified file (given as ``unicode``).
1489 """
1490 self._load_tmp_dh_test(
Alex Chan532b79e2017-01-24 15:14:52 +00001491 tmpfile.decode(getfilesystemencoding()) + NON_ASCII,
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001492 )
1493
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001494 def test_set_tmp_ecdh(self):
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001495 """
Alex Chan532b79e2017-01-24 15:14:52 +00001496 `Context.set_tmp_ecdh` sets the elliptic curve for Diffie-Hellman to
1497 the specified curve.
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001498 """
1499 context = Context(TLSv1_METHOD)
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001500 for curve in get_elliptic_curves():
Hynek Schlawacka07fa8c2015-10-17 10:15:28 +02001501 if curve.name.startswith(u"Oakley-"):
Hynek Schlawack7408aff2015-10-17 09:51:16 +02001502 # Setting Oakley-EC2N-4 and Oakley-EC2N-3 adds
1503 # ('bignum routines', 'BN_mod_inverse', 'no inverse') to the
1504 # error queue on OpenSSL 1.0.2.
1505 continue
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001506 # The only easily "assertable" thing is that it does not raise an
1507 # exception.
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001508 context.set_tmp_ecdh(curve)
Alex Gaynor12dc0842014-01-17 12:51:31 -06001509
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001510 def test_set_session_cache_mode_wrong_args(self):
1511 """
Alex Chan532b79e2017-01-24 15:14:52 +00001512 `Context.set_session_cache_mode` raises `TypeError` if called with
1513 a non-integer argument.
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001514 called with other than one integer argument.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001515 """
1516 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001517 with pytest.raises(TypeError):
1518 context.set_session_cache_mode(object())
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001519
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001520 def test_session_cache_mode(self):
1521 """
Alex Chan532b79e2017-01-24 15:14:52 +00001522 `Context.set_session_cache_mode` specifies how sessions are cached.
1523 The setting can be retrieved via `Context.get_session_cache_mode`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001524 """
1525 context = Context(TLSv1_METHOD)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001526 context.set_session_cache_mode(SESS_CACHE_OFF)
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001527 off = context.set_session_cache_mode(SESS_CACHE_BOTH)
Alex Chan532b79e2017-01-24 15:14:52 +00001528 assert SESS_CACHE_OFF == off
1529 assert SESS_CACHE_BOTH == context.get_session_cache_mode()
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001530
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001531 def test_get_cert_store(self):
1532 """
Alex Chan532b79e2017-01-24 15:14:52 +00001533 `Context.get_cert_store` returns a `X509Store` instance.
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001534 """
1535 context = Context(TLSv1_METHOD)
1536 store = context.get_cert_store()
Alex Chan532b79e2017-01-24 15:14:52 +00001537 assert isinstance(store, X509Store)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001538
Jeremy Lainé02261ad2018-05-16 18:33:25 +02001539 def test_set_tlsext_use_srtp_not_bytes(self):
1540 """
1541 `Context.set_tlsext_use_srtp' enables negotiating SRTP keying material.
1542
1543 It raises a TypeError if the list of profiles is not a byte string.
1544 """
1545 context = Context(TLSv1_METHOD)
1546 with pytest.raises(TypeError):
1547 context.set_tlsext_use_srtp(text_type('SRTP_AES128_CM_SHA1_80'))
1548
1549 def test_set_tlsext_use_srtp_invalid_profile(self):
1550 """
1551 `Context.set_tlsext_use_srtp' enables negotiating SRTP keying material.
1552
1553 It raises an Error if the call to OpenSSL fails.
1554 """
1555 context = Context(TLSv1_METHOD)
1556 with pytest.raises(Error):
1557 context.set_tlsext_use_srtp(b'SRTP_BOGUS')
1558
1559 def test_set_tlsext_use_srtp_valid(self):
1560 """
1561 `Context.set_tlsext_use_srtp' enables negotiating SRTP keying material.
1562
1563 It does not return anything.
1564 """
1565 context = Context(TLSv1_METHOD)
1566 assert context.set_tlsext_use_srtp(b'SRTP_AES128_CM_SHA1_80') is None
1567
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001568
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001569class TestServerNameCallback(object):
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001570 """
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001571 Tests for `Context.set_tlsext_servername_callback` and its
1572 interaction with `Connection`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001573 """
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001574 def test_old_callback_forgotten(self):
1575 """
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001576 If `Context.set_tlsext_servername_callback` is used to specify
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001577 a new callback, the one it replaces is dereferenced.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001578 """
Alex Chanfb078d82017-04-20 11:16:15 +01001579 def callback(connection): # pragma: no cover
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001580 pass
1581
Alex Chanfb078d82017-04-20 11:16:15 +01001582 def replacement(connection): # pragma: no cover
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001583 pass
1584
1585 context = Context(TLSv1_METHOD)
1586 context.set_tlsext_servername_callback(callback)
1587
1588 tracker = ref(callback)
1589 del callback
1590
1591 context.set_tlsext_servername_callback(replacement)
Jean-Paul Calderoned4033eb2014-01-11 08:21:46 -05001592
1593 # One run of the garbage collector happens to work on CPython. PyPy
1594 # doesn't collect the underlying object until a second run for whatever
1595 # reason. That's fine, it still demonstrates our code has properly
1596 # dropped the reference.
1597 collect()
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001598 collect()
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001599
1600 callback = tracker()
1601 if callback is not None:
1602 referrers = get_referrers(callback)
Alex Chanfb078d82017-04-20 11:16:15 +01001603 if len(referrers) > 1: # pragma: nocover
1604 pytest.fail("Some references remain: %r" % (referrers,))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001605
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001606 def test_no_servername(self):
1607 """
1608 When a client specifies no server name, the callback passed to
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001609 `Context.set_tlsext_servername_callback` is invoked and the
1610 result of `Connection.get_servername` is `None`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001611 """
1612 args = []
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001613
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001614 def servername(conn):
1615 args.append((conn, conn.get_servername()))
1616 context = Context(TLSv1_METHOD)
1617 context.set_tlsext_servername_callback(servername)
1618
1619 # Lose our reference to it. The Context is responsible for keeping it
1620 # alive now.
1621 del servername
1622 collect()
1623
1624 # Necessary to actually accept the connection
1625 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001626 context.use_certificate(
1627 load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001628
1629 # Do a little connection to trigger the logic
1630 server = Connection(context, None)
1631 server.set_accept_state()
1632
1633 client = Connection(Context(TLSv1_METHOD), None)
1634 client.set_connect_state()
1635
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001636 interact_in_memory(server, client)
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001637
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001638 assert args == [(server, None)]
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001639
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001640 def test_servername(self):
1641 """
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001642 When a client specifies a server name in its hello message, the
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001643 callback passed to `Contexts.set_tlsext_servername_callback` is
1644 invoked and the result of `Connection.get_servername` is that
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001645 server name.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001646 """
1647 args = []
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001648
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001649 def servername(conn):
1650 args.append((conn, conn.get_servername()))
1651 context = Context(TLSv1_METHOD)
1652 context.set_tlsext_servername_callback(servername)
1653
1654 # Necessary to actually accept the connection
1655 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001656 context.use_certificate(
1657 load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001658
1659 # Do a little connection to trigger the logic
1660 server = Connection(context, None)
1661 server.set_accept_state()
1662
1663 client = Connection(Context(TLSv1_METHOD), None)
1664 client.set_connect_state()
Alex Gaynore7f51982016-09-11 11:48:14 -04001665 client.set_tlsext_host_name(b"foo1.example.com")
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001666
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001667 interact_in_memory(server, client)
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001668
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001669 assert args == [(server, b"foo1.example.com")]
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001670
1671
Paul Kehrer4d575902019-02-26 21:42:12 +08001672@pytest.mark.skipif(
1673 not _lib.Cryptography_HAS_NEXTPROTONEG, reason="NPN is not available"
1674)
Alex Chan9e08b3e2016-11-10 12:18:54 +00001675class TestNextProtoNegotiation(object):
Cory Benfield84a121e2014-03-31 20:30:25 +01001676 """
1677 Test for Next Protocol Negotiation in PyOpenSSL.
1678 """
Alex Chan9e08b3e2016-11-10 12:18:54 +00001679 def test_npn_success(self):
1680 """
1681 Tests that clients and servers that agree on the negotiated next
1682 protocol can correct establish a connection, and that the agreed
1683 protocol is reported by the connections.
1684 """
1685 advertise_args = []
1686 select_args = []
1687
1688 def advertise(conn):
1689 advertise_args.append((conn,))
1690 return [b'http/1.1', b'spdy/2']
1691
1692 def select(conn, options):
1693 select_args.append((conn, options))
1694 return b'spdy/2'
1695
1696 server_context = Context(TLSv1_METHOD)
1697 server_context.set_npn_advertise_callback(advertise)
1698
1699 client_context = Context(TLSv1_METHOD)
1700 client_context.set_npn_select_callback(select)
1701
1702 # Necessary to actually accept the connection
1703 server_context.use_privatekey(
1704 load_privatekey(FILETYPE_PEM, server_key_pem))
1705 server_context.use_certificate(
1706 load_certificate(FILETYPE_PEM, server_cert_pem))
1707
1708 # Do a little connection to trigger the logic
1709 server = Connection(server_context, None)
1710 server.set_accept_state()
1711
1712 client = Connection(client_context, None)
1713 client.set_connect_state()
1714
1715 interact_in_memory(server, client)
1716
1717 assert advertise_args == [(server,)]
1718 assert select_args == [(client, [b'http/1.1', b'spdy/2'])]
1719
1720 assert server.get_next_proto_negotiated() == b'spdy/2'
1721 assert client.get_next_proto_negotiated() == b'spdy/2'
1722
1723 def test_npn_client_fail(self):
1724 """
1725 Tests that when clients and servers cannot agree on what protocol
1726 to use next that the TLS connection does not get established.
1727 """
1728 advertise_args = []
1729 select_args = []
1730
1731 def advertise(conn):
1732 advertise_args.append((conn,))
1733 return [b'http/1.1', b'spdy/2']
1734
1735 def select(conn, options):
1736 select_args.append((conn, options))
1737 return b''
1738
1739 server_context = Context(TLSv1_METHOD)
1740 server_context.set_npn_advertise_callback(advertise)
1741
1742 client_context = Context(TLSv1_METHOD)
1743 client_context.set_npn_select_callback(select)
1744
1745 # Necessary to actually accept the connection
1746 server_context.use_privatekey(
1747 load_privatekey(FILETYPE_PEM, server_key_pem))
1748 server_context.use_certificate(
1749 load_certificate(FILETYPE_PEM, server_cert_pem))
1750
1751 # Do a little connection to trigger the logic
1752 server = Connection(server_context, None)
1753 server.set_accept_state()
1754
1755 client = Connection(client_context, None)
1756 client.set_connect_state()
1757
1758 # If the client doesn't return anything, the connection will fail.
1759 with pytest.raises(Error):
1760 interact_in_memory(server, client)
1761
1762 assert advertise_args == [(server,)]
1763 assert select_args == [(client, [b'http/1.1', b'spdy/2'])]
1764
1765 def test_npn_select_error(self):
1766 """
1767 Test that we can handle exceptions in the select callback. If
1768 select fails it should be fatal to the connection.
1769 """
1770 advertise_args = []
1771
1772 def advertise(conn):
1773 advertise_args.append((conn,))
1774 return [b'http/1.1', b'spdy/2']
1775
1776 def select(conn, options):
1777 raise TypeError
1778
1779 server_context = Context(TLSv1_METHOD)
1780 server_context.set_npn_advertise_callback(advertise)
1781
1782 client_context = Context(TLSv1_METHOD)
1783 client_context.set_npn_select_callback(select)
1784
1785 # Necessary to actually accept the connection
1786 server_context.use_privatekey(
1787 load_privatekey(FILETYPE_PEM, server_key_pem))
1788 server_context.use_certificate(
1789 load_certificate(FILETYPE_PEM, server_cert_pem))
1790
1791 # Do a little connection to trigger the logic
1792 server = Connection(server_context, None)
1793 server.set_accept_state()
1794
1795 client = Connection(client_context, None)
1796 client.set_connect_state()
1797
1798 # If the callback throws an exception it should be raised here.
1799 with pytest.raises(TypeError):
1800 interact_in_memory(server, client)
1801 assert advertise_args == [(server,), ]
1802
1803 def test_npn_advertise_error(self):
1804 """
1805 Test that we can handle exceptions in the advertise callback. If
1806 advertise fails no NPN is advertised to the client.
1807 """
1808 select_args = []
1809
1810 def advertise(conn):
1811 raise TypeError
1812
1813 def select(conn, options): # pragma: nocover
Cory Benfieldba1820d2015-04-13 17:39:12 -04001814 """
Alex Chan9e08b3e2016-11-10 12:18:54 +00001815 Assert later that no args are actually appended.
Cory Benfieldba1820d2015-04-13 17:39:12 -04001816 """
Alex Chan9e08b3e2016-11-10 12:18:54 +00001817 select_args.append((conn, options))
1818 return b''
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001819
Alex Chan9e08b3e2016-11-10 12:18:54 +00001820 server_context = Context(TLSv1_METHOD)
1821 server_context.set_npn_advertise_callback(advertise)
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001822
Alex Chan9e08b3e2016-11-10 12:18:54 +00001823 client_context = Context(TLSv1_METHOD)
1824 client_context.set_npn_select_callback(select)
Cory Benfield84a121e2014-03-31 20:30:25 +01001825
Alex Chan9e08b3e2016-11-10 12:18:54 +00001826 # Necessary to actually accept the connection
1827 server_context.use_privatekey(
1828 load_privatekey(FILETYPE_PEM, server_key_pem))
1829 server_context.use_certificate(
1830 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield84a121e2014-03-31 20:30:25 +01001831
Alex Chan9e08b3e2016-11-10 12:18:54 +00001832 # Do a little connection to trigger the logic
1833 server = Connection(server_context, None)
1834 server.set_accept_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001835
Alex Chan9e08b3e2016-11-10 12:18:54 +00001836 client = Connection(client_context, None)
1837 client.set_connect_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001838
Alex Chan9e08b3e2016-11-10 12:18:54 +00001839 # If the client doesn't return anything, the connection will fail.
1840 with pytest.raises(TypeError):
1841 interact_in_memory(server, client)
1842 assert select_args == []
Cory Benfield0ea76e72015-03-22 09:05:28 +00001843
1844
Alex Chanec1e32d2016-11-10 14:11:45 +00001845class TestApplicationLayerProtoNegotiation(object):
Cory Benfield12eae892014-06-07 15:42:56 +01001846 """
1847 Tests for ALPN in PyOpenSSL.
1848 """
Alex Gaynor77debda2020-04-07 13:40:59 -04001849 def test_alpn_success(self):
1850 """
1851 Clients and servers that agree on the negotiated ALPN protocol can
1852 correct establish a connection, and the agreed protocol is reported
1853 by the connections.
1854 """
1855 select_args = []
Cory Benfield12eae892014-06-07 15:42:56 +01001856
Alex Gaynor77debda2020-04-07 13:40:59 -04001857 def select(conn, options):
1858 select_args.append((conn, options))
1859 return b'spdy/2'
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001860
Alex Gaynor77debda2020-04-07 13:40:59 -04001861 client_context = Context(TLSv1_METHOD)
1862 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfield12eae892014-06-07 15:42:56 +01001863
Alex Gaynor77debda2020-04-07 13:40:59 -04001864 server_context = Context(TLSv1_METHOD)
1865 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01001866
Alex Gaynor77debda2020-04-07 13:40:59 -04001867 # Necessary to actually accept the connection
1868 server_context.use_privatekey(
1869 load_privatekey(FILETYPE_PEM, server_key_pem))
1870 server_context.use_certificate(
1871 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield12eae892014-06-07 15:42:56 +01001872
Alex Gaynor77debda2020-04-07 13:40:59 -04001873 # Do a little connection to trigger the logic
1874 server = Connection(server_context, None)
1875 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001876
Alex Gaynor77debda2020-04-07 13:40:59 -04001877 client = Connection(client_context, None)
1878 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001879
Alex Gaynor77debda2020-04-07 13:40:59 -04001880 interact_in_memory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001881
Alex Gaynor77debda2020-04-07 13:40:59 -04001882 assert select_args == [(server, [b'http/1.1', b'spdy/2'])]
1883
1884 assert server.get_alpn_proto_negotiated() == b'spdy/2'
1885 assert client.get_alpn_proto_negotiated() == b'spdy/2'
1886
1887 def test_alpn_set_on_connection(self):
1888 """
1889 The same as test_alpn_success, but setting the ALPN protocols on
1890 the connection rather than the context.
1891 """
1892 select_args = []
1893
1894 def select(conn, options):
1895 select_args.append((conn, options))
1896 return b'spdy/2'
1897
1898 # Setup the client context but don't set any ALPN protocols.
1899 client_context = Context(TLSv1_METHOD)
1900
1901 server_context = Context(TLSv1_METHOD)
1902 server_context.set_alpn_select_callback(select)
1903
1904 # Necessary to actually accept the connection
1905 server_context.use_privatekey(
1906 load_privatekey(FILETYPE_PEM, server_key_pem))
1907 server_context.use_certificate(
1908 load_certificate(FILETYPE_PEM, server_cert_pem))
1909
1910 # Do a little connection to trigger the logic
1911 server = Connection(server_context, None)
1912 server.set_accept_state()
1913
1914 # Set the ALPN protocols on the client connection.
1915 client = Connection(client_context, None)
1916 client.set_alpn_protos([b'http/1.1', b'spdy/2'])
1917 client.set_connect_state()
1918
1919 interact_in_memory(server, client)
1920
1921 assert select_args == [(server, [b'http/1.1', b'spdy/2'])]
1922
1923 assert server.get_alpn_proto_negotiated() == b'spdy/2'
1924 assert client.get_alpn_proto_negotiated() == b'spdy/2'
1925
1926 def test_alpn_server_fail(self):
1927 """
1928 When clients and servers cannot agree on what protocol to use next
1929 the TLS connection does not get established.
1930 """
1931 select_args = []
1932
1933 def select(conn, options):
1934 select_args.append((conn, options))
1935 return b''
1936
1937 client_context = Context(TLSv1_METHOD)
1938 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
1939
1940 server_context = Context(TLSv1_METHOD)
1941 server_context.set_alpn_select_callback(select)
1942
1943 # Necessary to actually accept the connection
1944 server_context.use_privatekey(
1945 load_privatekey(FILETYPE_PEM, server_key_pem))
1946 server_context.use_certificate(
1947 load_certificate(FILETYPE_PEM, server_cert_pem))
1948
1949 # Do a little connection to trigger the logic
1950 server = Connection(server_context, None)
1951 server.set_accept_state()
1952
1953 client = Connection(client_context, None)
1954 client.set_connect_state()
1955
1956 # If the client doesn't return anything, the connection will fail.
1957 with pytest.raises(Error):
Alex Chanec1e32d2016-11-10 14:11:45 +00001958 interact_in_memory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001959
Alex Gaynor77debda2020-04-07 13:40:59 -04001960 assert select_args == [(server, [b'http/1.1', b'spdy/2'])]
Cory Benfielde46fa842015-04-13 16:50:49 -04001961
Alex Gaynor77debda2020-04-07 13:40:59 -04001962 def test_alpn_no_server_overlap(self):
1963 """
1964 A server can allow a TLS handshake to complete without
1965 agreeing to an application protocol by returning
1966 ``NO_OVERLAPPING_PROTOCOLS``.
1967 """
1968 refusal_args = []
Cory Benfield12eae892014-06-07 15:42:56 +01001969
Alex Gaynor77debda2020-04-07 13:40:59 -04001970 def refusal(conn, options):
1971 refusal_args.append((conn, options))
1972 return NO_OVERLAPPING_PROTOCOLS
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001973
Alex Gaynor77debda2020-04-07 13:40:59 -04001974 client_context = Context(SSLv23_METHOD)
1975 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfield12eae892014-06-07 15:42:56 +01001976
Alex Gaynor77debda2020-04-07 13:40:59 -04001977 server_context = Context(SSLv23_METHOD)
1978 server_context.set_alpn_select_callback(refusal)
Cory Benfield12eae892014-06-07 15:42:56 +01001979
Alex Gaynor77debda2020-04-07 13:40:59 -04001980 # Necessary to actually accept the connection
1981 server_context.use_privatekey(
1982 load_privatekey(FILETYPE_PEM, server_key_pem))
1983 server_context.use_certificate(
1984 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield12eae892014-06-07 15:42:56 +01001985
Alex Gaynor77debda2020-04-07 13:40:59 -04001986 # Do a little connection to trigger the logic
1987 server = Connection(server_context, None)
1988 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001989
Alex Gaynor77debda2020-04-07 13:40:59 -04001990 client = Connection(client_context, None)
1991 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001992
Alex Gaynor77debda2020-04-07 13:40:59 -04001993 # Do the dance.
1994 interact_in_memory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001995
Alex Gaynor77debda2020-04-07 13:40:59 -04001996 assert refusal_args == [(server, [b'http/1.1', b'spdy/2'])]
1997
1998 assert client.get_alpn_proto_negotiated() == b''
1999
2000 def test_alpn_select_cb_returns_invalid_value(self):
2001 """
2002 If the ALPN selection callback returns anything other than
2003 a bytestring or ``NO_OVERLAPPING_PROTOCOLS``, a
2004 :py:exc:`TypeError` is raised.
2005 """
2006 invalid_cb_args = []
2007
2008 def invalid_cb(conn, options):
2009 invalid_cb_args.append((conn, options))
2010 return u"can't return unicode"
2011
2012 client_context = Context(SSLv23_METHOD)
2013 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
2014
2015 server_context = Context(SSLv23_METHOD)
2016 server_context.set_alpn_select_callback(invalid_cb)
2017
2018 # Necessary to actually accept the connection
2019 server_context.use_privatekey(
2020 load_privatekey(FILETYPE_PEM, server_key_pem))
2021 server_context.use_certificate(
2022 load_certificate(FILETYPE_PEM, server_cert_pem))
2023
2024 # Do a little connection to trigger the logic
2025 server = Connection(server_context, None)
2026 server.set_accept_state()
2027
2028 client = Connection(client_context, None)
2029 client.set_connect_state()
2030
2031 # Do the dance.
2032 with pytest.raises(TypeError):
Alex Chanec1e32d2016-11-10 14:11:45 +00002033 interact_in_memory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01002034
Alex Gaynor77debda2020-04-07 13:40:59 -04002035 assert invalid_cb_args == [(server, [b'http/1.1', b'spdy/2'])]
Cory Benfield12eae892014-06-07 15:42:56 +01002036
Alex Gaynor77debda2020-04-07 13:40:59 -04002037 assert client.get_alpn_proto_negotiated() == b''
Cory Benfield12eae892014-06-07 15:42:56 +01002038
Alex Gaynor77debda2020-04-07 13:40:59 -04002039 def test_alpn_no_server(self):
2040 """
2041 When clients and servers cannot agree on what protocol to use next
2042 because the server doesn't offer ALPN, no protocol is negotiated.
2043 """
2044 client_context = Context(TLSv1_METHOD)
2045 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002046
Alex Gaynor77debda2020-04-07 13:40:59 -04002047 server_context = Context(TLSv1_METHOD)
Cory Benfield12eae892014-06-07 15:42:56 +01002048
Alex Gaynor77debda2020-04-07 13:40:59 -04002049 # Necessary to actually accept the connection
2050 server_context.use_privatekey(
2051 load_privatekey(FILETYPE_PEM, server_key_pem))
2052 server_context.use_certificate(
2053 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield12eae892014-06-07 15:42:56 +01002054
Alex Gaynor77debda2020-04-07 13:40:59 -04002055 # Do a little connection to trigger the logic
2056 server = Connection(server_context, None)
2057 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01002058
Alex Gaynor77debda2020-04-07 13:40:59 -04002059 client = Connection(client_context, None)
2060 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01002061
Alex Gaynor77debda2020-04-07 13:40:59 -04002062 # Do the dance.
2063 interact_in_memory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01002064
Alex Gaynor77debda2020-04-07 13:40:59 -04002065 assert client.get_alpn_proto_negotiated() == b''
Cory Benfield12eae892014-06-07 15:42:56 +01002066
Alex Gaynor77debda2020-04-07 13:40:59 -04002067 def test_alpn_callback_exception(self):
2068 """
2069 We can handle exceptions in the ALPN select callback.
2070 """
2071 select_args = []
Cory Benfield12eae892014-06-07 15:42:56 +01002072
Alex Gaynor77debda2020-04-07 13:40:59 -04002073 def select(conn, options):
2074 select_args.append((conn, options))
2075 raise TypeError()
Cory Benfield12eae892014-06-07 15:42:56 +01002076
Alex Gaynor77debda2020-04-07 13:40:59 -04002077 client_context = Context(TLSv1_METHOD)
2078 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Mark Williams5d890a02019-11-17 19:56:26 -08002079
Alex Gaynor77debda2020-04-07 13:40:59 -04002080 server_context = Context(TLSv1_METHOD)
2081 server_context.set_alpn_select_callback(select)
Mark Williams5d890a02019-11-17 19:56:26 -08002082
Alex Gaynor77debda2020-04-07 13:40:59 -04002083 # Necessary to actually accept the connection
2084 server_context.use_privatekey(
2085 load_privatekey(FILETYPE_PEM, server_key_pem))
2086 server_context.use_certificate(
2087 load_certificate(FILETYPE_PEM, server_cert_pem))
Mark Williams5d890a02019-11-17 19:56:26 -08002088
Alex Gaynor77debda2020-04-07 13:40:59 -04002089 # Do a little connection to trigger the logic
2090 server = Connection(server_context, None)
2091 server.set_accept_state()
Mark Williams5d890a02019-11-17 19:56:26 -08002092
Alex Gaynor77debda2020-04-07 13:40:59 -04002093 client = Connection(client_context, None)
2094 client.set_connect_state()
Mark Williams5d890a02019-11-17 19:56:26 -08002095
Alex Gaynor77debda2020-04-07 13:40:59 -04002096 with pytest.raises(TypeError):
Mark Williams5d890a02019-11-17 19:56:26 -08002097 interact_in_memory(server, client)
Alex Gaynor77debda2020-04-07 13:40:59 -04002098 assert select_args == [(server, [b'http/1.1', b'spdy/2'])]
Cory Benfield0f7b04c2015-04-13 17:51:12 -04002099
Cory Benfieldf1177e72015-04-12 09:11:49 -04002100
Alex Chanec1e32d2016-11-10 14:11:45 +00002101class TestSession(object):
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05002102 """
2103 Unit tests for :py:obj:`OpenSSL.SSL.Session`.
2104 """
2105 def test_construction(self):
2106 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002107 :py:class:`Session` can be constructed with no arguments, creating
2108 a new instance of that type.
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05002109 """
2110 new_session = Session()
Alex Chanec1e32d2016-11-10 14:11:45 +00002111 assert isinstance(new_session, Session)
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05002112
2113
Alex Chan1c0cb662017-01-30 07:13:30 +00002114class TestConnection(object):
Rick Deane15b1472009-07-09 15:53:42 -05002115 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002116 Unit tests for `OpenSSL.SSL.Connection`.
Rick Deane15b1472009-07-09 15:53:42 -05002117 """
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04002118 # XXX get_peer_certificate -> None
2119 # XXX sock_shutdown
2120 # XXX master_key -> TypeError
2121 # XXX server_random -> TypeError
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04002122 # XXX connect -> TypeError
2123 # XXX connect_ex -> TypeError
2124 # XXX set_connect_state -> TypeError
2125 # XXX set_accept_state -> TypeError
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04002126 # XXX do_handshake -> TypeError
2127 # XXX bio_read -> TypeError
2128 # XXX recv -> TypeError
2129 # XXX send -> TypeError
2130 # XXX bio_write -> TypeError
2131
Rick Deane15b1472009-07-09 15:53:42 -05002132 def test_type(self):
2133 """
Alex Gaynor01f90a12019-02-07 09:14:48 -05002134 `Connection` can be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -05002135 """
2136 ctx = Context(TLSv1_METHOD)
Alex Chan1c0cb662017-01-30 07:13:30 +00002137 assert is_consistent_type(Connection, 'Connection', ctx, None)
Rick Deane15b1472009-07-09 15:53:42 -05002138
Alex Chanfb078d82017-04-20 11:16:15 +01002139 @pytest.mark.parametrize('bad_context', [object(), 'context', None, 1])
2140 def test_wrong_args(self, bad_context):
2141 """
2142 `Connection.__init__` raises `TypeError` if called with a non-`Context`
2143 instance argument.
2144 """
2145 with pytest.raises(TypeError):
2146 Connection(bad_context)
2147
Daniel Holth079c9632019-11-17 22:45:52 -05002148 @pytest.mark.parametrize('bad_bio', [object(), None, 1, [1, 2, 3]])
2149 def test_bio_write_wrong_args(self, bad_bio):
2150 """
2151 `Connection.bio_write` raises `TypeError` if called with a non-bytes
2152 (or text) argument.
2153 """
2154 context = Context(TLSv1_METHOD)
2155 connection = Connection(context, None)
2156 with pytest.raises(TypeError):
2157 connection.bio_write(bad_bio)
2158
2159 def test_bio_write(self):
2160 """
2161 `Connection.bio_write` does not raise if called with bytes or
2162 bytearray, warns if called with text.
2163 """
2164 context = Context(TLSv1_METHOD)
2165 connection = Connection(context, None)
2166 connection.bio_write(b'xy')
2167 connection.bio_write(bytearray(b'za'))
2168 with pytest.warns(DeprecationWarning):
2169 connection.bio_write(u'deprecated')
2170
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002171 def test_get_context(self):
2172 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002173 `Connection.get_context` returns the `Context` instance used to
2174 construct the `Connection` instance.
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002175 """
2176 context = Context(TLSv1_METHOD)
2177 connection = Connection(context, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002178 assert connection.get_context() is context
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002179
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002180 def test_set_context_wrong_args(self):
2181 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002182 `Connection.set_context` raises `TypeError` if called with a
Alex Chanfb078d82017-04-20 11:16:15 +01002183 non-`Context` instance argument.
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002184 """
2185 ctx = Context(TLSv1_METHOD)
2186 connection = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002187 with pytest.raises(TypeError):
2188 connection.set_context(object())
2189 with pytest.raises(TypeError):
2190 connection.set_context("hello")
2191 with pytest.raises(TypeError):
2192 connection.set_context(1)
2193 assert ctx is connection.get_context()
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002194
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002195 def test_set_context(self):
2196 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002197 `Connection.set_context` specifies a new `Context` instance to be
2198 used for the connection.
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002199 """
2200 original = Context(SSLv23_METHOD)
2201 replacement = Context(TLSv1_METHOD)
2202 connection = Connection(original, None)
2203 connection.set_context(replacement)
Alex Chan1c0cb662017-01-30 07:13:30 +00002204 assert replacement is connection.get_context()
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002205 # Lose our references to the contexts, just in case the Connection
2206 # isn't properly managing its own contributions to their reference
2207 # counts.
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002208 del original, replacement
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002209 collect()
2210
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002211 def test_set_tlsext_host_name_wrong_args(self):
2212 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002213 If `Connection.set_tlsext_host_name` is called with a non-byte string
2214 argument or a byte string with an embedded NUL, `TypeError` is raised.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002215 """
2216 conn = Connection(Context(TLSv1_METHOD), None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002217 with pytest.raises(TypeError):
2218 conn.set_tlsext_host_name(object())
2219 with pytest.raises(TypeError):
2220 conn.set_tlsext_host_name(b"with\0null")
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002221
Hugo van Kemenade60827f82019-08-30 00:39:35 +03002222 if not PY2:
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002223 # On Python 3.x, don't accidentally implicitly convert from text.
Alex Chan1c0cb662017-01-30 07:13:30 +00002224 with pytest.raises(TypeError):
2225 conn.set_tlsext_host_name(b"example.com".decode("ascii"))
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04002226
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002227 def test_pending(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002228 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002229 `Connection.pending` returns the number of bytes available for
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002230 immediate read.
2231 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002232 connection = Connection(Context(TLSv1_METHOD), None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002233 assert connection.pending() == 0
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002234
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002235 def test_peek(self):
2236 """
Hynek Schlawack3bcf3152017-02-18 08:25:34 +01002237 `Connection.recv` peeks into the connection if `socket.MSG_PEEK` is
2238 passed.
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002239 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002240 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002241 server.send(b'xy')
Alex Chan1c0cb662017-01-30 07:13:30 +00002242 assert client.recv(2, MSG_PEEK) == b'xy'
2243 assert client.recv(2, MSG_PEEK) == b'xy'
2244 assert client.recv(2) == b'xy'
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002245
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002246 def test_connect_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002247 """
Hynek Schlawack3bcf3152017-02-18 08:25:34 +01002248 `Connection.connect` raises `TypeError` if called with a non-address
2249 argument.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002250 """
David Benjamin1fbe0642019-04-15 17:05:13 -05002251 connection = Connection(Context(TLSv1_METHOD), socket_any_family())
Alex Chan1c0cb662017-01-30 07:13:30 +00002252 with pytest.raises(TypeError):
2253 connection.connect(None)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002254
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002255 def test_connect_refused(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002256 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002257 `Connection.connect` raises `socket.error` if the underlying socket
2258 connect method raises it.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002259 """
David Benjamin1fbe0642019-04-15 17:05:13 -05002260 client = socket_any_family()
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002261 context = Context(TLSv1_METHOD)
2262 clientSSL = Connection(context, client)
Alex Gaynor122717b2015-09-05 14:14:18 -04002263 # pytest.raises here doesn't work because of a bug in py.test on Python
2264 # 2.6: https://github.com/pytest-dev/pytest/issues/988
Alex Gaynore69c2782015-09-05 14:07:48 -04002265 try:
David Benjamin1fbe0642019-04-15 17:05:13 -05002266 clientSSL.connect((loopback_address(client), 1))
Alex Gaynore69c2782015-09-05 14:07:48 -04002267 except error as e:
Alex Gaynor20a4c082015-09-05 14:24:15 -04002268 exc = e
2269 assert exc.args[0] == ECONNREFUSED
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002270
2271 def test_connect(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002272 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002273 `Connection.connect` establishes a connection to the specified address.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002274 """
David Benjamin1fbe0642019-04-15 17:05:13 -05002275 port = socket_any_family()
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002276 port.bind(('', 0))
2277 port.listen(3)
2278
David Benjamin1fbe0642019-04-15 17:05:13 -05002279 clientSSL = Connection(Context(TLSv1_METHOD), socket(port.family))
2280 clientSSL.connect((loopback_address(port), port.getsockname()[1]))
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002281 # XXX An assertion? Or something?
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002282
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002283 @pytest.mark.skipif(
2284 platform == "darwin",
2285 reason="connect_ex sometimes causes a kernel panic on OS X 10.6.4"
2286 )
2287 def test_connect_ex(self):
2288 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002289 If there is a connection error, `Connection.connect_ex` returns the
2290 errno instead of raising an exception.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002291 """
David Benjamin1fbe0642019-04-15 17:05:13 -05002292 port = socket_any_family()
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002293 port.bind(('', 0))
2294 port.listen(3)
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002295
David Benjamin1fbe0642019-04-15 17:05:13 -05002296 clientSSL = Connection(Context(TLSv1_METHOD), socket(port.family))
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002297 clientSSL.setblocking(False)
2298 result = clientSSL.connect_ex(port.getsockname())
2299 expected = (EINPROGRESS, EWOULDBLOCK)
Alex Chan1c0cb662017-01-30 07:13:30 +00002300 assert result in expected
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002301
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002302 def test_accept(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002303 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002304 `Connection.accept` accepts a pending connection attempt and returns a
2305 tuple of a new `Connection` (the accepted client) and the address the
2306 connection originated from.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002307 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002308 ctx = Context(TLSv1_METHOD)
2309 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2310 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
David Benjamin1fbe0642019-04-15 17:05:13 -05002311 port = socket_any_family()
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002312 portSSL = Connection(ctx, port)
2313 portSSL.bind(('', 0))
2314 portSSL.listen(3)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002315
David Benjamin1fbe0642019-04-15 17:05:13 -05002316 clientSSL = Connection(Context(TLSv1_METHOD), socket(port.family))
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002317
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002318 # Calling portSSL.getsockname() here to get the server IP address
2319 # sounds great, but frequently fails on Windows.
David Benjamin1fbe0642019-04-15 17:05:13 -05002320 clientSSL.connect((loopback_address(port), portSSL.getsockname()[1]))
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002321
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002322 serverSSL, address = portSSL.accept()
2323
Alex Chan1c0cb662017-01-30 07:13:30 +00002324 assert isinstance(serverSSL, Connection)
2325 assert serverSSL.get_context() is ctx
2326 assert address == clientSSL.getsockname()
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002327
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002328 def test_shutdown_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002329 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002330 `Connection.set_shutdown` raises `TypeError` if called with arguments
2331 other than integers.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002332 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002333 connection = Connection(Context(TLSv1_METHOD), None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002334 with pytest.raises(TypeError):
2335 connection.set_shutdown(None)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002336
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002337 def test_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002338 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002339 `Connection.shutdown` performs an SSL-level connection shutdown.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002340 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002341 server, client = loopback()
2342 assert not server.shutdown()
2343 assert server.get_shutdown() == SENT_SHUTDOWN
2344 with pytest.raises(ZeroReturnError):
2345 client.recv(1024)
2346 assert client.get_shutdown() == RECEIVED_SHUTDOWN
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04002347 client.shutdown()
Alex Chan1c0cb662017-01-30 07:13:30 +00002348 assert client.get_shutdown() == (SENT_SHUTDOWN | RECEIVED_SHUTDOWN)
2349 with pytest.raises(ZeroReturnError):
2350 server.recv(1024)
2351 assert server.get_shutdown() == (SENT_SHUTDOWN | RECEIVED_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002352
Paul Aurichc85e0862015-01-08 08:34:33 -08002353 def test_shutdown_closed(self):
2354 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002355 If the underlying socket is closed, `Connection.shutdown` propagates
2356 the write error from the low level write call.
Paul Aurichc85e0862015-01-08 08:34:33 -08002357 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002358 server, client = loopback()
Paul Aurichc85e0862015-01-08 08:34:33 -08002359 server.sock_shutdown(2)
Alex Chan1c0cb662017-01-30 07:13:30 +00002360 with pytest.raises(SysCallError) as exc:
2361 server.shutdown()
Alex Chanfb078d82017-04-20 11:16:15 +01002362 if platform == "win32":
2363 assert exc.value.args[0] == ESHUTDOWN
2364 else:
2365 assert exc.value.args[0] == EPIPE
Paul Aurichc85e0862015-01-08 08:34:33 -08002366
Glyph89389472015-04-14 17:29:26 -04002367 def test_shutdown_truncated(self):
Glyph6064ec32015-04-14 16:38:22 -04002368 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002369 If the underlying connection is truncated, `Connection.shutdown`
2370 raises an `Error`.
Glyph6064ec32015-04-14 16:38:22 -04002371 """
Glyph89389472015-04-14 17:29:26 -04002372 server_ctx = Context(TLSv1_METHOD)
2373 client_ctx = Context(TLSv1_METHOD)
2374 server_ctx.use_privatekey(
2375 load_privatekey(FILETYPE_PEM, server_key_pem))
2376 server_ctx.use_certificate(
2377 load_certificate(FILETYPE_PEM, server_cert_pem))
2378 server = Connection(server_ctx, None)
2379 client = Connection(client_ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002380 handshake_in_memory(client, server)
2381 assert not server.shutdown()
2382 with pytest.raises(WantReadError):
2383 server.shutdown()
Glyph89389472015-04-14 17:29:26 -04002384 server.bio_shutdown()
Alex Chan1c0cb662017-01-30 07:13:30 +00002385 with pytest.raises(Error):
2386 server.shutdown()
Glyph6064ec32015-04-14 16:38:22 -04002387
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002388 def test_set_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002389 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002390 `Connection.set_shutdown` sets the state of the SSL connection
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002391 shutdown process.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002392 """
David Benjamin1fbe0642019-04-15 17:05:13 -05002393 connection = Connection(Context(TLSv1_METHOD), socket_any_family())
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002394 connection.set_shutdown(RECEIVED_SHUTDOWN)
Alex Chan1c0cb662017-01-30 07:13:30 +00002395 assert connection.get_shutdown() == RECEIVED_SHUTDOWN
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002396
kjavaf248592015-09-07 12:14:01 +01002397 def test_state_string(self):
2398 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002399 `Connection.state_string` verbosely describes the current state of
2400 the `Connection`.
kjavaf248592015-09-07 12:14:01 +01002401 """
Hynek Schlawackb0274ce2015-10-16 19:56:26 +02002402 server, client = socket_pair()
Alex Chan1c0cb662017-01-30 07:13:30 +00002403 server = loopback_server_factory(server)
2404 client = loopback_client_factory(client)
kjavaf248592015-09-07 12:14:01 +01002405
Alex Gaynor5af32d02016-09-24 01:52:21 -04002406 assert server.get_state_string() in [
2407 b"before/accept initialization", b"before SSL initialization"
2408 ]
2409 assert client.get_state_string() in [
2410 b"before/connect initialization", b"before SSL initialization"
2411 ]
kjavaf248592015-09-07 12:14:01 +01002412
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002413 def test_app_data(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002414 """
2415 Any object can be set as app data by passing it to
Alex Chan1c0cb662017-01-30 07:13:30 +00002416 `Connection.set_app_data` and later retrieved with
2417 `Connection.get_app_data`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002418 """
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002419 conn = Connection(Context(TLSv1_METHOD), None)
Todd Chapman4f73e4f2015-08-27 11:26:43 -04002420 assert None is conn.get_app_data()
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002421 app_data = object()
2422 conn.set_app_data(app_data)
Todd Chapman4f73e4f2015-08-27 11:26:43 -04002423 assert conn.get_app_data() is app_data
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002424
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002425 def test_makefile(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002426 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002427 `Connection.makefile` is not implemented and calling that
2428 method raises `NotImplementedError`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002429 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002430 conn = Connection(Context(TLSv1_METHOD), None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002431 with pytest.raises(NotImplementedError):
2432 conn.makefile()
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002433
Jeremy Lainé460a19d2018-05-16 19:44:19 +02002434 def test_get_certificate(self):
2435 """
2436 `Connection.get_certificate` returns the local certificate.
2437 """
2438 chain = _create_certificate_chain()
2439 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
2440
2441 context = Context(TLSv1_METHOD)
2442 context.use_certificate(scert)
2443 client = Connection(context, None)
2444 cert = client.get_certificate()
2445 assert cert is not None
2446 assert "Server Certificate" == cert.get_subject().CN
2447
2448 def test_get_certificate_none(self):
2449 """
2450 `Connection.get_certificate` returns the local certificate.
2451
2452 If there is no certificate, it returns None.
2453 """
2454 context = Context(TLSv1_METHOD)
2455 client = Connection(context, None)
2456 cert = client.get_certificate()
2457 assert cert is None
2458
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002459 def test_get_peer_cert_chain(self):
2460 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002461 `Connection.get_peer_cert_chain` returns a list of certificates
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002462 which the connected server returned for the certification verification.
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002463 """
2464 chain = _create_certificate_chain()
2465 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
2466
2467 serverContext = Context(TLSv1_METHOD)
2468 serverContext.use_privatekey(skey)
2469 serverContext.use_certificate(scert)
2470 serverContext.add_extra_chain_cert(icert)
2471 serverContext.add_extra_chain_cert(cacert)
2472 server = Connection(serverContext, None)
2473 server.set_accept_state()
2474
2475 # Create the client
2476 clientContext = Context(TLSv1_METHOD)
2477 clientContext.set_verify(VERIFY_NONE, verify_cb)
2478 client = Connection(clientContext, None)
2479 client.set_connect_state()
2480
Alex Chan1c0cb662017-01-30 07:13:30 +00002481 interact_in_memory(client, server)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002482
2483 chain = client.get_peer_cert_chain()
Alex Chan1c0cb662017-01-30 07:13:30 +00002484 assert len(chain) == 3
2485 assert "Server Certificate" == chain[0].get_subject().CN
2486 assert "Intermediate Certificate" == chain[1].get_subject().CN
2487 assert "Authority Certificate" == chain[2].get_subject().CN
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002488
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002489 def test_get_peer_cert_chain_none(self):
2490 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002491 `Connection.get_peer_cert_chain` returns `None` if the peer sends
2492 no certificate chain.
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002493 """
2494 ctx = Context(TLSv1_METHOD)
2495 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2496 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
2497 server = Connection(ctx, None)
2498 server.set_accept_state()
2499 client = Connection(Context(TLSv1_METHOD), None)
2500 client.set_connect_state()
Alex Chan1c0cb662017-01-30 07:13:30 +00002501 interact_in_memory(client, server)
2502 assert None is server.get_peer_cert_chain()
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002503
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002504 def test_get_session_unconnected(self):
2505 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002506 `Connection.get_session` returns `None` when used with an object
2507 which has not been connected.
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002508 """
2509 ctx = Context(TLSv1_METHOD)
2510 server = Connection(ctx, None)
2511 session = server.get_session()
Alex Chan1c0cb662017-01-30 07:13:30 +00002512 assert None is session
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002513
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002514 def test_server_get_session(self):
2515 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002516 On the server side of a connection, `Connection.get_session` returns a
2517 `Session` instance representing the SSL session for that connection.
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002518 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002519 server, client = loopback()
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002520 session = server.get_session()
Alex Chan1c0cb662017-01-30 07:13:30 +00002521 assert isinstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002522
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002523 def test_client_get_session(self):
2524 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002525 On the client side of a connection, `Connection.get_session`
2526 returns a `Session` instance representing the SSL session for
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002527 that connection.
2528 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002529 server, client = loopback()
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002530 session = client.get_session()
Alex Chan1c0cb662017-01-30 07:13:30 +00002531 assert isinstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002532
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002533 def test_set_session_wrong_args(self):
2534 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002535 `Connection.set_session` raises `TypeError` if called with an object
2536 that is not an instance of `Session`.
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002537 """
2538 ctx = Context(TLSv1_METHOD)
2539 connection = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002540 with pytest.raises(TypeError):
2541 connection.set_session(123)
2542 with pytest.raises(TypeError):
2543 connection.set_session("hello")
2544 with pytest.raises(TypeError):
2545 connection.set_session(object())
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002546
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002547 def test_client_set_session(self):
2548 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002549 `Connection.set_session`, when used prior to a connection being
2550 established, accepts a `Session` instance and causes an attempt to
2551 re-use the session it represents when the SSL handshake is performed.
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002552 """
2553 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2554 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
Paul Kehrer7d5a3bf2019-01-21 12:24:02 -06002555 ctx = Context(TLSv1_2_METHOD)
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002556 ctx.use_privatekey(key)
2557 ctx.use_certificate(cert)
2558 ctx.set_session_id("unity-test")
2559
2560 def makeServer(socket):
2561 server = Connection(ctx, socket)
2562 server.set_accept_state()
2563 return server
2564
Alex Chan1c0cb662017-01-30 07:13:30 +00002565 originalServer, originalClient = loopback(
2566 server_factory=makeServer)
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002567 originalSession = originalClient.get_session()
2568
2569 def makeClient(socket):
Alex Chan1c0cb662017-01-30 07:13:30 +00002570 client = loopback_client_factory(socket)
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002571 client.set_session(originalSession)
2572 return client
Alex Chan1c0cb662017-01-30 07:13:30 +00002573 resumedServer, resumedClient = loopback(
2574 server_factory=makeServer,
2575 client_factory=makeClient)
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002576
2577 # This is a proxy: in general, we have no access to any unique
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002578 # identifier for the session (new enough versions of OpenSSL expose
2579 # a hash which could be usable, but "new enough" is very, very new).
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002580 # Instead, exploit the fact that the master key is re-used if the
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002581 # session is re-used. As long as the master key for the two
2582 # connections is the same, the session was re-used!
Alex Chan1c0cb662017-01-30 07:13:30 +00002583 assert originalServer.master_key() == resumedServer.master_key()
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002584
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002585 def test_set_session_wrong_method(self):
2586 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002587 If `Connection.set_session` is passed a `Session` instance associated
2588 with a context using a different SSL method than the `Connection`
2589 is using, a `OpenSSL.SSL.Error` is raised.
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002590 """
Alex Gaynor5af32d02016-09-24 01:52:21 -04002591 # Make this work on both OpenSSL 1.0.0, which doesn't support TLSv1.2
2592 # and also on OpenSSL 1.1.0 which doesn't support SSLv3. (SSL_ST_INIT
2593 # is a way to check for 1.1.0)
Alex Gaynoraa32e712017-06-29 20:56:12 -07002594 if SSL_ST_INIT is None:
2595 v1 = TLSv1_2_METHOD
2596 v2 = TLSv1_METHOD
2597 elif hasattr(_lib, "SSLv3_method"):
Alex Gaynor5af32d02016-09-24 01:52:21 -04002598 v1 = TLSv1_METHOD
2599 v2 = SSLv3_METHOD
2600 else:
Alex Gaynoraa32e712017-06-29 20:56:12 -07002601 pytest.skip("Test requires either OpenSSL 1.1.0 or SSLv3")
Alex Gaynor5af32d02016-09-24 01:52:21 -04002602
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002603 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2604 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
Alex Gaynor5af32d02016-09-24 01:52:21 -04002605 ctx = Context(v1)
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002606 ctx.use_privatekey(key)
2607 ctx.use_certificate(cert)
2608 ctx.set_session_id("unity-test")
2609
2610 def makeServer(socket):
2611 server = Connection(ctx, socket)
2612 server.set_accept_state()
2613 return server
2614
Alex Gaynor5af32d02016-09-24 01:52:21 -04002615 def makeOriginalClient(socket):
2616 client = Connection(Context(v1), socket)
2617 client.set_connect_state()
2618 return client
2619
Alex Chan1c0cb662017-01-30 07:13:30 +00002620 originalServer, originalClient = loopback(
2621 server_factory=makeServer, client_factory=makeOriginalClient)
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002622 originalSession = originalClient.get_session()
2623
2624 def makeClient(socket):
2625 # Intentionally use a different, incompatible method here.
Alex Gaynor5af32d02016-09-24 01:52:21 -04002626 client = Connection(Context(v2), socket)
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002627 client.set_connect_state()
2628 client.set_session(originalSession)
2629 return client
2630
Alex Chan1c0cb662017-01-30 07:13:30 +00002631 with pytest.raises(Error):
2632 loopback(client_factory=makeClient, server_factory=makeServer)
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002633
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002634 def test_wantWriteError(self):
2635 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002636 `Connection` methods which generate output raise
2637 `OpenSSL.SSL.WantWriteError` if writing to the connection's BIO
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002638 fail indicating a should-write state.
2639 """
2640 client_socket, server_socket = socket_pair()
2641 # Fill up the client's send buffer so Connection won't be able to write
Jean-Paul Calderonebbff8b92014-03-22 14:20:30 -04002642 # anything. Only write a single byte at a time so we can be sure we
2643 # completely fill the buffer. Even though the socket API is allowed to
2644 # signal a short write via its return value it seems this doesn't
2645 # always happen on all platforms (FreeBSD and OS X particular) for the
2646 # very last bit of available buffer space.
2647 msg = b"x"
caternb2777a42018-08-09 15:38:13 -04002648 for i in range(1024 * 1024 * 64):
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002649 try:
2650 client_socket.send(msg)
2651 except error as e:
2652 if e.errno == EWOULDBLOCK:
2653 break
2654 raise
2655 else:
Alex Chan1c0cb662017-01-30 07:13:30 +00002656 pytest.fail(
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002657 "Failed to fill socket buffer, cannot test BIO want write")
2658
2659 ctx = Context(TLSv1_METHOD)
2660 conn = Connection(ctx, client_socket)
2661 # Client's speak first, so make it an SSL client
2662 conn.set_connect_state()
Alex Chan1c0cb662017-01-30 07:13:30 +00002663 with pytest.raises(WantWriteError):
2664 conn.do_handshake()
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002665
2666 # XXX want_read
2667
Fedor Brunner416f4a12014-03-28 13:18:38 +01002668 def test_get_finished_before_connect(self):
Fedor Brunner5747b932014-03-05 14:22:34 +01002669 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002670 `Connection.get_finished` returns `None` before TLS handshake
2671 is completed.
Fedor Brunner5747b932014-03-05 14:22:34 +01002672 """
Fedor Brunner5747b932014-03-05 14:22:34 +01002673 ctx = Context(TLSv1_METHOD)
2674 connection = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002675 assert connection.get_finished() is None
Fedor Brunner416f4a12014-03-28 13:18:38 +01002676
2677 def test_get_peer_finished_before_connect(self):
2678 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002679 `Connection.get_peer_finished` returns `None` before TLS handshake
2680 is completed.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002681 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002682 ctx = Context(TLSv1_METHOD)
2683 connection = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002684 assert connection.get_peer_finished() is None
Fedor Brunner5747b932014-03-05 14:22:34 +01002685
Fedor Brunner416f4a12014-03-28 13:18:38 +01002686 def test_get_finished(self):
2687 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002688 `Connection.get_finished` method returns the TLS Finished message send
2689 from client, or server. Finished messages are send during
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002690 TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002691 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002692 server, client = loopback()
Fedor Brunner416f4a12014-03-28 13:18:38 +01002693
Alex Chan1c0cb662017-01-30 07:13:30 +00002694 assert server.get_finished() is not None
2695 assert len(server.get_finished()) > 0
Fedor Brunner416f4a12014-03-28 13:18:38 +01002696
2697 def test_get_peer_finished(self):
2698 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002699 `Connection.get_peer_finished` method returns the TLS Finished
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002700 message received from client, or server. Finished messages are send
2701 during TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002702 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002703 server, client = loopback()
Fedor Brunner416f4a12014-03-28 13:18:38 +01002704
Alex Chan1c0cb662017-01-30 07:13:30 +00002705 assert server.get_peer_finished() is not None
2706 assert len(server.get_peer_finished()) > 0
Fedor Brunner5747b932014-03-05 14:22:34 +01002707
Fedor Brunner416f4a12014-03-28 13:18:38 +01002708 def test_tls_finished_message_symmetry(self):
2709 """
Hynek Schlawackdddd1112015-09-05 21:12:30 +02002710 The TLS Finished message send by server must be the TLS Finished
2711 message received by client.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002712
Hynek Schlawackdddd1112015-09-05 21:12:30 +02002713 The TLS Finished message send by client must be the TLS Finished
2714 message received by server.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002715 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002716 server, client = loopback()
Fedor Brunner416f4a12014-03-28 13:18:38 +01002717
Alex Chan1c0cb662017-01-30 07:13:30 +00002718 assert server.get_finished() == client.get_peer_finished()
2719 assert client.get_finished() == server.get_peer_finished()
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002720
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002721 def test_get_cipher_name_before_connect(self):
2722 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002723 `Connection.get_cipher_name` returns `None` if no connection
2724 has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002725 """
2726 ctx = Context(TLSv1_METHOD)
2727 conn = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002728 assert conn.get_cipher_name() is None
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002729
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002730 def test_get_cipher_name(self):
2731 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002732 `Connection.get_cipher_name` returns a `unicode` string giving the
2733 name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002734 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002735 server, client = loopback()
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002736 server_cipher_name, client_cipher_name = \
2737 server.get_cipher_name(), client.get_cipher_name()
2738
Alex Chan1c0cb662017-01-30 07:13:30 +00002739 assert isinstance(server_cipher_name, text_type)
2740 assert isinstance(client_cipher_name, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002741
Alex Chan1c0cb662017-01-30 07:13:30 +00002742 assert server_cipher_name == client_cipher_name
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002743
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002744 def test_get_cipher_version_before_connect(self):
2745 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002746 `Connection.get_cipher_version` returns `None` if no connection
2747 has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002748 """
2749 ctx = Context(TLSv1_METHOD)
2750 conn = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002751 assert conn.get_cipher_version() is None
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002752
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002753 def test_get_cipher_version(self):
2754 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002755 `Connection.get_cipher_version` returns a `unicode` string giving
2756 the protocol name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002757 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002758 server, client = loopback()
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002759 server_cipher_version, client_cipher_version = \
2760 server.get_cipher_version(), client.get_cipher_version()
2761
Alex Chan1c0cb662017-01-30 07:13:30 +00002762 assert isinstance(server_cipher_version, text_type)
2763 assert isinstance(client_cipher_version, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002764
Alex Chan1c0cb662017-01-30 07:13:30 +00002765 assert server_cipher_version == client_cipher_version
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002766
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002767 def test_get_cipher_bits_before_connect(self):
2768 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002769 `Connection.get_cipher_bits` returns `None` if no connection has
2770 been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002771 """
2772 ctx = Context(TLSv1_METHOD)
2773 conn = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002774 assert conn.get_cipher_bits() is None
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002775
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002776 def test_get_cipher_bits(self):
2777 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002778 `Connection.get_cipher_bits` returns the number of secret bits
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002779 of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002780 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002781 server, client = loopback()
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002782 server_cipher_bits, client_cipher_bits = \
2783 server.get_cipher_bits(), client.get_cipher_bits()
2784
Alex Chan1c0cb662017-01-30 07:13:30 +00002785 assert isinstance(server_cipher_bits, int)
2786 assert isinstance(client_cipher_bits, int)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002787
Alex Chan1c0cb662017-01-30 07:13:30 +00002788 assert server_cipher_bits == client_cipher_bits
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002789
Jim Shaverabff1882015-05-27 09:15:55 -04002790 def test_get_protocol_version_name(self):
2791 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002792 `Connection.get_protocol_version_name()` returns a string giving the
2793 protocol version of the current connection.
Jim Shaverabff1882015-05-27 09:15:55 -04002794 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002795 server, client = loopback()
Jim Shaverabff1882015-05-27 09:15:55 -04002796 client_protocol_version_name = client.get_protocol_version_name()
2797 server_protocol_version_name = server.get_protocol_version_name()
2798
Alex Chan1c0cb662017-01-30 07:13:30 +00002799 assert isinstance(server_protocol_version_name, text_type)
2800 assert isinstance(client_protocol_version_name, text_type)
Jim Shaverabff1882015-05-27 09:15:55 -04002801
Alex Chan1c0cb662017-01-30 07:13:30 +00002802 assert server_protocol_version_name == client_protocol_version_name
Jim Shaverabff1882015-05-27 09:15:55 -04002803
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002804 def test_get_protocol_version(self):
2805 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002806 `Connection.get_protocol_version()` returns an integer
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002807 giving the protocol version of the current connection.
2808 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002809 server, client = loopback()
Jim Shaver85a4dff2015-04-27 17:42:46 -04002810 client_protocol_version = client.get_protocol_version()
2811 server_protocol_version = server.get_protocol_version()
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002812
Alex Chan1c0cb662017-01-30 07:13:30 +00002813 assert isinstance(server_protocol_version, int)
2814 assert isinstance(client_protocol_version, int)
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002815
Alex Chan1c0cb662017-01-30 07:13:30 +00002816 assert server_protocol_version == client_protocol_version
2817
2818 def test_wantReadError(self):
2819 """
2820 `Connection.bio_read` raises `OpenSSL.SSL.WantReadError` if there are
2821 no bytes available to be read from the BIO.
2822 """
2823 ctx = Context(TLSv1_METHOD)
2824 conn = Connection(ctx, None)
2825 with pytest.raises(WantReadError):
2826 conn.bio_read(1024)
2827
Alex Chanfb078d82017-04-20 11:16:15 +01002828 @pytest.mark.parametrize('bufsize', [1.0, None, object(), 'bufsize'])
2829 def test_bio_read_wrong_args(self, bufsize):
2830 """
2831 `Connection.bio_read` raises `TypeError` if passed a non-integer
2832 argument.
2833 """
2834 ctx = Context(TLSv1_METHOD)
2835 conn = Connection(ctx, None)
2836 with pytest.raises(TypeError):
2837 conn.bio_read(bufsize)
2838
Alex Chan1c0cb662017-01-30 07:13:30 +00002839 def test_buffer_size(self):
2840 """
2841 `Connection.bio_read` accepts an integer giving the maximum number
2842 of bytes to read and return.
2843 """
2844 ctx = Context(TLSv1_METHOD)
2845 conn = Connection(ctx, None)
2846 conn.set_connect_state()
2847 try:
2848 conn.do_handshake()
2849 except WantReadError:
2850 pass
2851 data = conn.bio_read(2)
2852 assert 2 == len(data)
2853
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002854
Alex Chanb7480992017-01-30 14:04:47 +00002855class TestConnectionGetCipherList(object):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002856 """
Alex Chanb7480992017-01-30 14:04:47 +00002857 Tests for `Connection.get_cipher_list`.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002858 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002859 def test_result(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002860 """
Alex Chanb7480992017-01-30 14:04:47 +00002861 `Connection.get_cipher_list` returns a list of `bytes` giving the
2862 names of the ciphers which might be used.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002863 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002864 connection = Connection(Context(TLSv1_METHOD), None)
2865 ciphers = connection.get_cipher_list()
Alex Chanb7480992017-01-30 14:04:47 +00002866 assert isinstance(ciphers, list)
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002867 for cipher in ciphers:
Alex Chanb7480992017-01-30 14:04:47 +00002868 assert isinstance(cipher, str)
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002869
2870
Maximilian Hils868dc3c2017-02-10 14:56:55 +01002871class VeryLarge(bytes):
2872 """
2873 Mock object so that we don't have to allocate 2**31 bytes
2874 """
2875 def __len__(self):
2876 return 2**31
2877
2878
Alex Chanb7480992017-01-30 14:04:47 +00002879class TestConnectionSend(object):
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002880 """
Alex Chanb7480992017-01-30 14:04:47 +00002881 Tests for `Connection.send`.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002882 """
2883 def test_wrong_args(self):
2884 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002885 When called with arguments other than string argument for its first
Alex Chanb7480992017-01-30 14:04:47 +00002886 parameter, `Connection.send` raises `TypeError`.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002887 """
2888 connection = Connection(Context(TLSv1_METHOD), None)
Alex Chanb7480992017-01-30 14:04:47 +00002889 with pytest.raises(TypeError):
2890 connection.send(object())
Daniel Holth079c9632019-11-17 22:45:52 -05002891 with pytest.raises(TypeError):
2892 connection.send([1, 2, 3])
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002893
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002894 def test_short_bytes(self):
2895 """
Alex Chanb7480992017-01-30 14:04:47 +00002896 When passed a short byte string, `Connection.send` transmits all of it
2897 and returns the number of bytes sent.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002898 """
Alex Chanb7480992017-01-30 14:04:47 +00002899 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002900 count = server.send(b'xy')
Alex Chanb7480992017-01-30 14:04:47 +00002901 assert count == 2
2902 assert client.recv(2) == b'xy'
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002903
Abraham Martinef063482015-03-25 14:06:24 +00002904 def test_text(self):
2905 """
Alex Chanb7480992017-01-30 14:04:47 +00002906 When passed a text, `Connection.send` transmits all of it and
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002907 returns the number of bytes sent. It also raises a DeprecationWarning.
Abraham Martinef063482015-03-25 14:06:24 +00002908 """
Alex Chanb7480992017-01-30 14:04:47 +00002909 server, client = loopback()
2910 with pytest.warns(DeprecationWarning) as w:
Abraham Martinef063482015-03-25 14:06:24 +00002911 simplefilter("always")
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002912 count = server.send(b"xy".decode("ascii"))
Alex Chanb7480992017-01-30 14:04:47 +00002913 assert (
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002914 "{0} for buf is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002915 WARNING_TYPE_EXPECTED
Alex Chanb7480992017-01-30 14:04:47 +00002916 ) == str(w[-1].message))
2917 assert count == 2
2918 assert client.recv(2) == b'xy'
Abraham Martinef063482015-03-25 14:06:24 +00002919
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002920 def test_short_memoryview(self):
2921 """
2922 When passed a memoryview onto a small number of bytes,
Alex Chanb7480992017-01-30 14:04:47 +00002923 `Connection.send` transmits all of them and returns the number
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002924 of bytes sent.
2925 """
Alex Chanb7480992017-01-30 14:04:47 +00002926 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002927 count = server.send(memoryview(b'xy'))
Alex Chanb7480992017-01-30 14:04:47 +00002928 assert count == 2
2929 assert client.recv(2) == b'xy'
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002930
Daniel Holth079c9632019-11-17 22:45:52 -05002931 def test_short_bytearray(self):
2932 """
2933 When passed a short bytearray, `Connection.send` transmits all of
2934 it and returns the number of bytes sent.
2935 """
2936 server, client = loopback()
2937 count = server.send(bytearray(b'xy'))
2938 assert count == 2
2939 assert client.recv(2) == b'xy'
2940
Hynek Schlawack8e94f1b2015-09-05 21:31:00 +02002941 @skip_if_py3
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002942 def test_short_buffer(self):
2943 """
2944 When passed a buffer containing a small number of bytes,
Alex Chanb7480992017-01-30 14:04:47 +00002945 `Connection.send` transmits all of them and returns the number
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002946 of bytes sent.
2947 """
Alex Chanb7480992017-01-30 14:04:47 +00002948 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002949 count = server.send(buffer(b'xy'))
Alex Chanb7480992017-01-30 14:04:47 +00002950 assert count == 2
2951 assert client.recv(2) == b'xy'
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02002952
Maximilian Hils868dc3c2017-02-10 14:56:55 +01002953 @pytest.mark.skipif(
2954 sys.maxsize < 2**31,
2955 reason="sys.maxsize < 2**31 - test requires 64 bit"
2956 )
2957 def test_buf_too_large(self):
2958 """
2959 When passed a buffer containing >= 2**31 bytes,
2960 `Connection.send` bails out as SSL_write only
2961 accepts an int for the buffer length.
2962 """
2963 connection = Connection(Context(TLSv1_METHOD), None)
2964 with pytest.raises(ValueError) as exc_info:
2965 connection.send(VeryLarge())
2966 exc_info.match(r"Cannot send more than .+ bytes at once")
2967
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05002968
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002969def _make_memoryview(size):
2970 """
2971 Create a new ``memoryview`` wrapped around a ``bytearray`` of the given
2972 size.
2973 """
2974 return memoryview(bytearray(size))
2975
2976
Alex Chanb7480992017-01-30 14:04:47 +00002977class TestConnectionRecvInto(object):
Cory Benfield62d10332014-06-15 10:03:41 +01002978 """
Alex Chanb7480992017-01-30 14:04:47 +00002979 Tests for `Connection.recv_into`.
Cory Benfield62d10332014-06-15 10:03:41 +01002980 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002981 def _no_length_test(self, factory):
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04002982 """
Alex Chanb7480992017-01-30 14:04:47 +00002983 Assert that when the given buffer is passed to `Connection.recv_into`,
2984 whatever bytes are available to be received that fit into that buffer
2985 are written into that buffer.
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04002986 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002987 output_buffer = factory(5)
2988
Alex Chanb7480992017-01-30 14:04:47 +00002989 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002990 server.send(b'xy')
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04002991
Alex Chanb7480992017-01-30 14:04:47 +00002992 assert client.recv_into(output_buffer) == 2
2993 assert output_buffer == bytearray(b'xy\x00\x00\x00')
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04002994
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002995 def test_bytearray_no_length(self):
Cory Benfield62d10332014-06-15 10:03:41 +01002996 """
Alex Chanb7480992017-01-30 14:04:47 +00002997 `Connection.recv_into` can be passed a `bytearray` instance and data
2998 in the receive buffer is written to it.
Cory Benfield62d10332014-06-15 10:03:41 +01002999 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003000 self._no_length_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01003001
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003002 def _respects_length_test(self, factory):
Cory Benfield62d10332014-06-15 10:03:41 +01003003 """
Alex Chanb7480992017-01-30 14:04:47 +00003004 Assert that when the given buffer is passed to `Connection.recv_into`
3005 along with a value for `nbytes` that is less than the size of that
3006 buffer, only `nbytes` bytes are written into the buffer.
Cory Benfield62d10332014-06-15 10:03:41 +01003007 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003008 output_buffer = factory(10)
3009
Alex Chanb7480992017-01-30 14:04:47 +00003010 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04003011 server.send(b'abcdefghij')
Cory Benfield62d10332014-06-15 10:03:41 +01003012
Alex Chanb7480992017-01-30 14:04:47 +00003013 assert client.recv_into(output_buffer, 5) == 5
3014 assert output_buffer == bytearray(b'abcde\x00\x00\x00\x00\x00')
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04003015
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04003016 def test_bytearray_respects_length(self):
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04003017 """
Alex Chanb7480992017-01-30 14:04:47 +00003018 When called with a `bytearray` instance, `Connection.recv_into`
3019 respects the `nbytes` parameter and doesn't copy in more than that
3020 number of bytes.
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04003021 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003022 self._respects_length_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01003023
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003024 def _doesnt_overfill_test(self, factory):
Cory Benfield62d10332014-06-15 10:03:41 +01003025 """
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04003026 Assert that if there are more bytes available to be read from the
3027 receive buffer than would fit into the buffer passed to
Alex Chanb7480992017-01-30 14:04:47 +00003028 `Connection.recv_into`, only as many as fit are written into it.
Cory Benfield62d10332014-06-15 10:03:41 +01003029 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003030 output_buffer = factory(5)
3031
Alex Chanb7480992017-01-30 14:04:47 +00003032 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04003033 server.send(b'abcdefghij')
Cory Benfield62d10332014-06-15 10:03:41 +01003034
Alex Chanb7480992017-01-30 14:04:47 +00003035 assert client.recv_into(output_buffer) == 5
3036 assert output_buffer == bytearray(b'abcde')
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04003037 rest = client.recv(5)
Alex Chanb7480992017-01-30 14:04:47 +00003038 assert b'fghij' == rest
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04003039
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04003040 def test_bytearray_doesnt_overfill(self):
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04003041 """
Alex Chanb7480992017-01-30 14:04:47 +00003042 When called with a `bytearray` instance, `Connection.recv_into`
3043 respects the size of the array and doesn't write more bytes into it
3044 than will fit.
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04003045 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003046 self._doesnt_overfill_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01003047
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04003048 def test_bytearray_really_doesnt_overfill(self):
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003049 """
Alex Chanb7480992017-01-30 14:04:47 +00003050 When called with a `bytearray` instance and an `nbytes` value that is
3051 too large, `Connection.recv_into` respects the size of the array and
3052 not the `nbytes` value and doesn't write more bytes into the buffer
3053 than will fit.
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003054 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003055 self._doesnt_overfill_test(bytearray)
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003056
Maximilian Hils1d95dea2015-08-17 19:27:20 +02003057 def test_peek(self):
Alex Chanb7480992017-01-30 14:04:47 +00003058 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04003059 server.send(b'xy')
Maximilian Hils1d95dea2015-08-17 19:27:20 +02003060
3061 for _ in range(2):
3062 output_buffer = bytearray(5)
Alex Chanb7480992017-01-30 14:04:47 +00003063 assert client.recv_into(output_buffer, flags=MSG_PEEK) == 2
3064 assert output_buffer == bytearray(b'xy\x00\x00\x00')
Maximilian Hils1d95dea2015-08-17 19:27:20 +02003065
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003066 def test_memoryview_no_length(self):
3067 """
Alex Chanb7480992017-01-30 14:04:47 +00003068 `Connection.recv_into` can be passed a `memoryview` instance and data
3069 in the receive buffer is written to it.
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003070 """
3071 self._no_length_test(_make_memoryview)
Maximilian Hils1d95dea2015-08-17 19:27:20 +02003072
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003073 def test_memoryview_respects_length(self):
3074 """
Alex Chanb7480992017-01-30 14:04:47 +00003075 When called with a `memoryview` instance, `Connection.recv_into`
3076 respects the ``nbytes`` parameter and doesn't copy more than that
3077 number of bytes in.
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003078 """
3079 self._respects_length_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01003080
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003081 def test_memoryview_doesnt_overfill(self):
3082 """
Alex Chanb7480992017-01-30 14:04:47 +00003083 When called with a `memoryview` instance, `Connection.recv_into`
3084 respects the size of the array and doesn't write more bytes into it
3085 than will fit.
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003086 """
3087 self._doesnt_overfill_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01003088
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003089 def test_memoryview_really_doesnt_overfill(self):
3090 """
Alex Chanb7480992017-01-30 14:04:47 +00003091 When called with a `memoryview` instance and an `nbytes` value that is
3092 too large, `Connection.recv_into` respects the size of the array and
3093 not the `nbytes` value and doesn't write more bytes into the buffer
3094 than will fit.
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003095 """
3096 self._doesnt_overfill_test(_make_memoryview)
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003097
Cory Benfield62d10332014-06-15 10:03:41 +01003098
Alex Chanb7480992017-01-30 14:04:47 +00003099class TestConnectionSendall(object):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003100 """
Alex Chanb7480992017-01-30 14:04:47 +00003101 Tests for `Connection.sendall`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003102 """
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003103 def test_wrong_args(self):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003104 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003105 When called with arguments other than a string argument for its first
Alex Chanb7480992017-01-30 14:04:47 +00003106 parameter, `Connection.sendall` raises `TypeError`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003107 """
3108 connection = Connection(Context(TLSv1_METHOD), None)
Alex Chanb7480992017-01-30 14:04:47 +00003109 with pytest.raises(TypeError):
3110 connection.sendall(object())
Daniel Holth079c9632019-11-17 22:45:52 -05003111 with pytest.raises(TypeError):
3112 connection.sendall([1, 2, 3])
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003113
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003114 def test_short(self):
3115 """
Alex Chanb7480992017-01-30 14:04:47 +00003116 `Connection.sendall` transmits all of the bytes in the string
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003117 passed to it.
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003118 """
Alex Chanb7480992017-01-30 14:04:47 +00003119 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04003120 server.sendall(b'x')
Alex Chanb7480992017-01-30 14:04:47 +00003121 assert client.recv(1) == b'x'
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003122
Abraham Martinef063482015-03-25 14:06:24 +00003123 def test_text(self):
3124 """
Alex Chanb7480992017-01-30 14:04:47 +00003125 `Connection.sendall` transmits all the content in the string passed
3126 to it, raising a DeprecationWarning in case of this being a text.
Abraham Martinef063482015-03-25 14:06:24 +00003127 """
Alex Chanb7480992017-01-30 14:04:47 +00003128 server, client = loopback()
3129 with pytest.warns(DeprecationWarning) as w:
Abraham Martinef063482015-03-25 14:06:24 +00003130 simplefilter("always")
Jean-Paul Calderone8dc37a12015-03-29 08:16:52 -04003131 server.sendall(b"x".decode("ascii"))
Alex Chanb7480992017-01-30 14:04:47 +00003132 assert (
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04003133 "{0} for buf is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04003134 WARNING_TYPE_EXPECTED
Alex Chanb7480992017-01-30 14:04:47 +00003135 ) == str(w[-1].message))
3136 assert client.recv(1) == b"x"
Abraham Martinef063482015-03-25 14:06:24 +00003137
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003138 def test_short_memoryview(self):
3139 """
3140 When passed a memoryview onto a small number of bytes,
Alex Chanb7480992017-01-30 14:04:47 +00003141 `Connection.sendall` transmits all of them.
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003142 """
Alex Chanb7480992017-01-30 14:04:47 +00003143 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04003144 server.sendall(memoryview(b'x'))
Alex Chanb7480992017-01-30 14:04:47 +00003145 assert client.recv(1) == b'x'
Abraham Martinef063482015-03-25 14:06:24 +00003146
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003147 @skip_if_py3
3148 def test_short_buffers(self):
3149 """
3150 When passed a buffer containing a small number of bytes,
Alex Chanb7480992017-01-30 14:04:47 +00003151 `Connection.sendall` transmits all of them.
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003152 """
Alex Chanb7480992017-01-30 14:04:47 +00003153 server, client = loopback()
Daniel Holth079c9632019-11-17 22:45:52 -05003154 count = server.sendall(buffer(b'xy'))
3155 assert count == 2
3156 assert client.recv(2) == b'xy'
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02003157
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003158 def test_long(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003159 """
Alex Chanb7480992017-01-30 14:04:47 +00003160 `Connection.sendall` transmits all the bytes in the string passed to it
3161 even if this requires multiple calls of an underlying write function.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003162 """
Alex Chanb7480992017-01-30 14:04:47 +00003163 server, client = loopback()
Jean-Paul Calderone6241c702010-09-16 19:59:24 -04003164 # Should be enough, underlying SSL_write should only do 16k at a time.
Hynek Schlawack35618382015-09-05 21:54:25 +02003165 # On Windows, after 32k of bytes the write will block (forever
3166 # - because no one is yet reading).
Alex Gaynore7f51982016-09-11 11:48:14 -04003167 message = b'x' * (1024 * 32 - 1) + b'y'
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003168 server.sendall(message)
3169 accum = []
3170 received = 0
3171 while received < len(message):
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04003172 data = client.recv(1024)
3173 accum.append(data)
3174 received += len(data)
Alex Chanb7480992017-01-30 14:04:47 +00003175 assert message == b''.join(accum)
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003176
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003177 def test_closed(self):
3178 """
Alex Chanb7480992017-01-30 14:04:47 +00003179 If the underlying socket is closed, `Connection.sendall` propagates the
3180 write error from the low level write call.
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003181 """
Alex Chanb7480992017-01-30 14:04:47 +00003182 server, client = loopback()
Jean-Paul Calderone05d43e82010-09-24 18:01:36 -04003183 server.sock_shutdown(2)
Alex Chanb7480992017-01-30 14:04:47 +00003184 with pytest.raises(SysCallError) as err:
3185 server.sendall(b"hello, world")
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +02003186 if platform == "win32":
Alex Chanb7480992017-01-30 14:04:47 +00003187 assert err.value.args[0] == ESHUTDOWN
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +02003188 else:
Alex Chanb7480992017-01-30 14:04:47 +00003189 assert err.value.args[0] == EPIPE
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003190
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003191
Alex Chanb7480992017-01-30 14:04:47 +00003192class TestConnectionRenegotiate(object):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003193 """
3194 Tests for SSL renegotiation APIs.
3195 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003196 def test_total_renegotiations(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003197 """
Alex Chanb7480992017-01-30 14:04:47 +00003198 `Connection.total_renegotiations` returns `0` before any renegotiations
3199 have happened.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003200 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003201 connection = Connection(Context(TLSv1_METHOD), None)
Alex Chanb7480992017-01-30 14:04:47 +00003202 assert connection.total_renegotiations() == 0
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003203
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003204 def test_renegotiate(self):
3205 """
3206 Go through a complete renegotiation cycle.
3207 """
Paul Kehrer7d5a3bf2019-01-21 12:24:02 -06003208 server, client = loopback(
3209 lambda s: loopback_server_factory(s, TLSv1_2_METHOD),
3210 lambda s: loopback_client_factory(s, TLSv1_2_METHOD),
3211 )
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003212
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003213 server.send(b"hello world")
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003214
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003215 assert b"hello world" == client.recv(len(b"hello world"))
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003216
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003217 assert 0 == server.total_renegotiations()
3218 assert False is server.renegotiate_pending()
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003219
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003220 assert True is server.renegotiate()
3221
3222 assert True is server.renegotiate_pending()
3223
3224 server.setblocking(False)
3225 client.setblocking(False)
3226
3227 client.do_handshake()
3228 server.do_handshake()
3229
3230 assert 1 == server.total_renegotiations()
3231 while False is server.renegotiate_pending():
3232 pass
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003233
3234
Alex Chanb7480992017-01-30 14:04:47 +00003235class TestError(object):
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003236 """
Alex Chanb7480992017-01-30 14:04:47 +00003237 Unit tests for `OpenSSL.SSL.Error`.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003238 """
3239 def test_type(self):
3240 """
Alex Chanb7480992017-01-30 14:04:47 +00003241 `Error` is an exception type.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003242 """
Alex Chanb7480992017-01-30 14:04:47 +00003243 assert issubclass(Error, Exception)
3244 assert Error.__name__ == 'Error'
Rick Deane15b1472009-07-09 15:53:42 -05003245
3246
Alex Chanb7480992017-01-30 14:04:47 +00003247class TestConstants(object):
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003248 """
Alex Chanb7480992017-01-30 14:04:47 +00003249 Tests for the values of constants exposed in `OpenSSL.SSL`.
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003250
3251 These are values defined by OpenSSL intended only to be used as flags to
3252 OpenSSL APIs. The only assertions it seems can be made about them is
3253 their values.
3254 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003255 @pytest.mark.skipif(
3256 OP_NO_QUERY_MTU is None,
3257 reason="OP_NO_QUERY_MTU unavailable - OpenSSL version may be too old"
3258 )
3259 def test_op_no_query_mtu(self):
3260 """
Alex Chanb7480992017-01-30 14:04:47 +00003261 The value of `OpenSSL.SSL.OP_NO_QUERY_MTU` is 0x1000, the value
3262 of `SSL_OP_NO_QUERY_MTU` defined by `openssl/ssl.h`.
Hynek Schlawack35618382015-09-05 21:54:25 +02003263 """
Alex Chanb7480992017-01-30 14:04:47 +00003264 assert OP_NO_QUERY_MTU == 0x1000
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003265
Hynek Schlawack35618382015-09-05 21:54:25 +02003266 @pytest.mark.skipif(
3267 OP_COOKIE_EXCHANGE is None,
3268 reason="OP_COOKIE_EXCHANGE unavailable - "
3269 "OpenSSL version may be too old"
3270 )
3271 def test_op_cookie_exchange(self):
3272 """
Alex Chanb7480992017-01-30 14:04:47 +00003273 The value of `OpenSSL.SSL.OP_COOKIE_EXCHANGE` is 0x2000, the
3274 value of `SSL_OP_COOKIE_EXCHANGE` defined by `openssl/ssl.h`.
Hynek Schlawack35618382015-09-05 21:54:25 +02003275 """
Alex Chanb7480992017-01-30 14:04:47 +00003276 assert OP_COOKIE_EXCHANGE == 0x2000
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003277
Hynek Schlawack35618382015-09-05 21:54:25 +02003278 @pytest.mark.skipif(
3279 OP_NO_TICKET is None,
3280 reason="OP_NO_TICKET unavailable - OpenSSL version may be too old"
3281 )
3282 def test_op_no_ticket(self):
3283 """
Alex Chanb7480992017-01-30 14:04:47 +00003284 The value of `OpenSSL.SSL.OP_NO_TICKET` is 0x4000, the value of
3285 `SSL_OP_NO_TICKET` defined by `openssl/ssl.h`.
Hynek Schlawack35618382015-09-05 21:54:25 +02003286 """
Alex Chanb7480992017-01-30 14:04:47 +00003287 assert OP_NO_TICKET == 0x4000
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003288
Hynek Schlawack35618382015-09-05 21:54:25 +02003289 @pytest.mark.skipif(
3290 OP_NO_COMPRESSION is None,
3291 reason="OP_NO_COMPRESSION unavailable - OpenSSL version may be too old"
3292 )
3293 def test_op_no_compression(self):
3294 """
Alex Chanb7480992017-01-30 14:04:47 +00003295 The value of `OpenSSL.SSL.OP_NO_COMPRESSION` is 0x20000, the
3296 value of `SSL_OP_NO_COMPRESSION` defined by `openssl/ssl.h`.
Hynek Schlawack35618382015-09-05 21:54:25 +02003297 """
Alex Chanb7480992017-01-30 14:04:47 +00003298 assert OP_NO_COMPRESSION == 0x20000
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04003299
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003300 def test_sess_cache_off(self):
3301 """
Alex Chanb7480992017-01-30 14:04:47 +00003302 The value of `OpenSSL.SSL.SESS_CACHE_OFF` 0x0, the value of
3303 `SSL_SESS_CACHE_OFF` defined by `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003304 """
Alex Chanb7480992017-01-30 14:04:47 +00003305 assert 0x0 == SESS_CACHE_OFF
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003306
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003307 def test_sess_cache_client(self):
3308 """
Alex Chanb7480992017-01-30 14:04:47 +00003309 The value of `OpenSSL.SSL.SESS_CACHE_CLIENT` 0x1, the value of
3310 `SSL_SESS_CACHE_CLIENT` defined by `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003311 """
Alex Chanb7480992017-01-30 14:04:47 +00003312 assert 0x1 == SESS_CACHE_CLIENT
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003313
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003314 def test_sess_cache_server(self):
3315 """
Alex Chanb7480992017-01-30 14:04:47 +00003316 The value of `OpenSSL.SSL.SESS_CACHE_SERVER` 0x2, the value of
3317 `SSL_SESS_CACHE_SERVER` defined by `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003318 """
Alex Chanb7480992017-01-30 14:04:47 +00003319 assert 0x2 == SESS_CACHE_SERVER
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003320
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003321 def test_sess_cache_both(self):
3322 """
Alex Chanb7480992017-01-30 14:04:47 +00003323 The value of `OpenSSL.SSL.SESS_CACHE_BOTH` 0x3, the value of
3324 `SSL_SESS_CACHE_BOTH` defined by `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003325 """
Alex Chanb7480992017-01-30 14:04:47 +00003326 assert 0x3 == SESS_CACHE_BOTH
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003327
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003328 def test_sess_cache_no_auto_clear(self):
3329 """
Alex Chanb7480992017-01-30 14:04:47 +00003330 The value of `OpenSSL.SSL.SESS_CACHE_NO_AUTO_CLEAR` 0x80, the
3331 value of `SSL_SESS_CACHE_NO_AUTO_CLEAR` defined by
3332 `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003333 """
Alex Chanb7480992017-01-30 14:04:47 +00003334 assert 0x80 == SESS_CACHE_NO_AUTO_CLEAR
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003335
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003336 def test_sess_cache_no_internal_lookup(self):
3337 """
Alex Chanb7480992017-01-30 14:04:47 +00003338 The value of `OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_LOOKUP` 0x100,
3339 the value of `SSL_SESS_CACHE_NO_INTERNAL_LOOKUP` defined by
3340 `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003341 """
Alex Chanb7480992017-01-30 14:04:47 +00003342 assert 0x100 == SESS_CACHE_NO_INTERNAL_LOOKUP
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003343
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003344 def test_sess_cache_no_internal_store(self):
3345 """
Alex Chanb7480992017-01-30 14:04:47 +00003346 The value of `OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_STORE` 0x200,
3347 the value of `SSL_SESS_CACHE_NO_INTERNAL_STORE` defined by
3348 `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003349 """
Alex Chanb7480992017-01-30 14:04:47 +00003350 assert 0x200 == SESS_CACHE_NO_INTERNAL_STORE
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003351
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003352 def test_sess_cache_no_internal(self):
3353 """
Alex Chanb7480992017-01-30 14:04:47 +00003354 The value of `OpenSSL.SSL.SESS_CACHE_NO_INTERNAL` 0x300, the
3355 value of `SSL_SESS_CACHE_NO_INTERNAL` defined by
3356 `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003357 """
Alex Chanb7480992017-01-30 14:04:47 +00003358 assert 0x300 == SESS_CACHE_NO_INTERNAL
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003359
3360
Alex Chanb7480992017-01-30 14:04:47 +00003361class TestMemoryBIO(object):
Rick Deanb71c0d22009-04-01 14:09:23 -05003362 """
Alex Chanb7480992017-01-30 14:04:47 +00003363 Tests for `OpenSSL.SSL.Connection` using a memory BIO.
Rick Deanb71c0d22009-04-01 14:09:23 -05003364 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003365 def _server(self, sock):
3366 """
Alex Chanb7480992017-01-30 14:04:47 +00003367 Create a new server-side SSL `Connection` object wrapped around `sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003368 """
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003369 # Create the server side Connection. This is mostly setup boilerplate
3370 # - use TLSv1, use a particular certificate, etc.
3371 server_ctx = Context(TLSv1_METHOD)
Alex Gaynor43307782015-09-04 09:05:45 -04003372 server_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE)
Hynek Schlawack35618382015-09-05 21:54:25 +02003373 server_ctx.set_verify(
3374 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT | VERIFY_CLIENT_ONCE,
3375 verify_cb
3376 )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003377 server_store = server_ctx.get_cert_store()
Hynek Schlawack35618382015-09-05 21:54:25 +02003378 server_ctx.use_privatekey(
3379 load_privatekey(FILETYPE_PEM, server_key_pem))
3380 server_ctx.use_certificate(
3381 load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003382 server_ctx.check_privatekey()
3383 server_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Hynek Schlawack35618382015-09-05 21:54:25 +02003384 # Here the Connection is actually created. If None is passed as the
3385 # 2nd parameter, it indicates a memory BIO should be created.
Rick Deanb1ccd562009-07-09 23:52:39 -05003386 server_conn = Connection(server_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003387 server_conn.set_accept_state()
3388 return server_conn
3389
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003390 def _client(self, sock):
3391 """
Alex Chanb7480992017-01-30 14:04:47 +00003392 Create a new client-side SSL `Connection` object wrapped around `sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003393 """
3394 # Now create the client side Connection. Similar boilerplate to the
3395 # above.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003396 client_ctx = Context(TLSv1_METHOD)
Alex Gaynor43307782015-09-04 09:05:45 -04003397 client_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE)
Hynek Schlawack35618382015-09-05 21:54:25 +02003398 client_ctx.set_verify(
3399 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT | VERIFY_CLIENT_ONCE,
3400 verify_cb
3401 )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003402 client_store = client_ctx.get_cert_store()
Hynek Schlawack35618382015-09-05 21:54:25 +02003403 client_ctx.use_privatekey(
3404 load_privatekey(FILETYPE_PEM, client_key_pem))
3405 client_ctx.use_certificate(
3406 load_certificate(FILETYPE_PEM, client_cert_pem))
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003407 client_ctx.check_privatekey()
3408 client_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05003409 client_conn = Connection(client_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003410 client_conn.set_connect_state()
3411 return client_conn
3412
Alex Chanb7480992017-01-30 14:04:47 +00003413 def test_memory_connect(self):
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003414 """
Alex Chanb7480992017-01-30 14:04:47 +00003415 Two `Connection`s which use memory BIOs can be manually connected by
3416 reading from the output of each and writing those bytes to the input of
3417 the other and in this way establish a connection and exchange
3418 application-level bytes with each other.
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003419 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003420 server_conn = self._server(None)
3421 client_conn = self._client(None)
Rick Deanb71c0d22009-04-01 14:09:23 -05003422
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003423 # There should be no key or nonces yet.
Alex Chanb7480992017-01-30 14:04:47 +00003424 assert server_conn.master_key() is None
3425 assert server_conn.client_random() is None
3426 assert server_conn.server_random() is None
Rick Deanb71c0d22009-04-01 14:09:23 -05003427
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003428 # First, the handshake needs to happen. We'll deliver bytes back and
3429 # forth between the client and server until neither of them feels like
3430 # speaking any more.
Alex Chanb7480992017-01-30 14:04:47 +00003431 assert interact_in_memory(client_conn, server_conn) is None
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003432
3433 # Now that the handshake is done, there should be a key and nonces.
Alex Chanb7480992017-01-30 14:04:47 +00003434 assert server_conn.master_key() is not None
3435 assert server_conn.client_random() is not None
3436 assert server_conn.server_random() is not None
3437 assert server_conn.client_random() == client_conn.client_random()
3438 assert server_conn.server_random() == client_conn.server_random()
3439 assert server_conn.client_random() != server_conn.server_random()
3440 assert client_conn.client_random() != client_conn.server_random()
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003441
Paul Kehrerbdb76392017-12-01 04:54:32 +08003442 # Export key material for other uses.
3443 cekm = client_conn.export_keying_material(b'LABEL', 32)
3444 sekm = server_conn.export_keying_material(b'LABEL', 32)
3445 assert cekm is not None
3446 assert sekm is not None
3447 assert cekm == sekm
3448 assert len(sekm) == 32
3449
3450 # Export key material for other uses with additional context.
3451 cekmc = client_conn.export_keying_material(b'LABEL', 32, b'CONTEXT')
3452 sekmc = server_conn.export_keying_material(b'LABEL', 32, b'CONTEXT')
3453 assert cekmc is not None
3454 assert sekmc is not None
3455 assert cekmc == sekmc
3456 assert cekmc != cekm
3457 assert sekmc != sekm
3458 # Export with alternate label
3459 cekmt = client_conn.export_keying_material(b'test', 32, b'CONTEXT')
3460 sekmt = server_conn.export_keying_material(b'test', 32, b'CONTEXT')
3461 assert cekmc != cekmt
3462 assert sekmc != sekmt
3463
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003464 # Here are the bytes we'll try to send.
Alex Gaynore7f51982016-09-11 11:48:14 -04003465 important_message = b'One if by land, two if by sea.'
Rick Deanb71c0d22009-04-01 14:09:23 -05003466
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003467 server_conn.write(important_message)
Alex Chanb7480992017-01-30 14:04:47 +00003468 assert (
3469 interact_in_memory(client_conn, server_conn) ==
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003470 (client_conn, important_message))
3471
3472 client_conn.write(important_message[::-1])
Alex Chanb7480992017-01-30 14:04:47 +00003473 assert (
3474 interact_in_memory(client_conn, server_conn) ==
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003475 (server_conn, important_message[::-1]))
Rick Deanb71c0d22009-04-01 14:09:23 -05003476
Alex Chanb7480992017-01-30 14:04:47 +00003477 def test_socket_connect(self):
Rick Deanb1ccd562009-07-09 23:52:39 -05003478 """
Alex Chanb7480992017-01-30 14:04:47 +00003479 Just like `test_memory_connect` but with an actual socket.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003480
Hynek Schlawack35618382015-09-05 21:54:25 +02003481 This is primarily to rule out the memory BIO code as the source of any
Alex Chanb7480992017-01-30 14:04:47 +00003482 problems encountered while passing data over a `Connection` (if
Hynek Schlawack35618382015-09-05 21:54:25 +02003483 this test fails, there must be a problem outside the memory BIO code,
3484 as no memory BIO is involved here). Even though this isn't a memory
3485 BIO test, it's convenient to have it here.
Rick Deanb1ccd562009-07-09 23:52:39 -05003486 """
Alex Chanb7480992017-01-30 14:04:47 +00003487 server_conn, client_conn = loopback()
Rick Deanb1ccd562009-07-09 23:52:39 -05003488
Alex Gaynore7f51982016-09-11 11:48:14 -04003489 important_message = b"Help me Obi Wan Kenobi, you're my only hope."
Rick Deanb1ccd562009-07-09 23:52:39 -05003490 client_conn.send(important_message)
3491 msg = server_conn.recv(1024)
Alex Chanb7480992017-01-30 14:04:47 +00003492 assert msg == important_message
Rick Deanb1ccd562009-07-09 23:52:39 -05003493
3494 # Again in the other direction, just for fun.
3495 important_message = important_message[::-1]
3496 server_conn.send(important_message)
3497 msg = client_conn.recv(1024)
Alex Chanb7480992017-01-30 14:04:47 +00003498 assert msg == important_message
Rick Deanb1ccd562009-07-09 23:52:39 -05003499
Alex Chanb7480992017-01-30 14:04:47 +00003500 def test_socket_overrides_memory(self):
Rick Deanb71c0d22009-04-01 14:09:23 -05003501 """
Alex Chanb7480992017-01-30 14:04:47 +00003502 Test that `OpenSSL.SSL.bio_read` and `OpenSSL.SSL.bio_write` don't
3503 work on `OpenSSL.SSL.Connection`() that use sockets.
Rick Deanb71c0d22009-04-01 14:09:23 -05003504 """
Alex Gaynor51d424c2016-09-10 14:50:11 -04003505 context = Context(TLSv1_METHOD)
David Benjamin1fbe0642019-04-15 17:05:13 -05003506 client = socket_any_family()
Rick Deanb71c0d22009-04-01 14:09:23 -05003507 clientSSL = Connection(context, client)
Alex Chanb7480992017-01-30 14:04:47 +00003508 with pytest.raises(TypeError):
3509 clientSSL.bio_read(100)
3510 with pytest.raises(TypeError):
3511 clientSSL.bio_write("foo")
3512 with pytest.raises(TypeError):
3513 clientSSL.bio_shutdown()
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003514
Alex Chanb7480992017-01-30 14:04:47 +00003515 def test_outgoing_overflow(self):
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003516 """
3517 If more bytes than can be written to the memory BIO are passed to
Alex Chanb7480992017-01-30 14:04:47 +00003518 `Connection.send` at once, the number of bytes which were written is
3519 returned and that many bytes from the beginning of the input can be
3520 read from the other end of the connection.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003521 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003522 server = self._server(None)
3523 client = self._client(None)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003524
Alex Chanb7480992017-01-30 14:04:47 +00003525 interact_in_memory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003526
3527 size = 2 ** 15
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003528 sent = client.send(b"x" * size)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003529 # Sanity check. We're trying to test what happens when the entire
3530 # input can't be sent. If the entire input was sent, this test is
3531 # meaningless.
Alex Chanb7480992017-01-30 14:04:47 +00003532 assert sent < size
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003533
Alex Chanb7480992017-01-30 14:04:47 +00003534 receiver, received = interact_in_memory(client, server)
3535 assert receiver is server
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003536
3537 # We can rely on all of these bytes being received at once because
Alex Chanb7480992017-01-30 14:04:47 +00003538 # loopback passes 2 ** 16 to recv - more than 2 ** 15.
3539 assert len(received) == sent
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003540
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003541 def test_shutdown(self):
3542 """
Alex Chanb7480992017-01-30 14:04:47 +00003543 `Connection.bio_shutdown` signals the end of the data stream
3544 from which the `Connection` reads.
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003545 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003546 server = self._server(None)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003547 server.bio_shutdown()
Alex Chanb7480992017-01-30 14:04:47 +00003548 with pytest.raises(Error) as err:
3549 server.recv(1024)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003550 # We don't want WantReadError or ZeroReturnError or anything - it's a
3551 # handshake failure.
Alex Chanb7480992017-01-30 14:04:47 +00003552 assert type(err.value) in [Error, SysCallError]
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003553
Alex Chanb7480992017-01-30 14:04:47 +00003554 def test_unexpected_EOF(self):
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003555 """
3556 If the connection is lost before an orderly SSL shutdown occurs,
Alex Chanb7480992017-01-30 14:04:47 +00003557 `OpenSSL.SSL.SysCallError` is raised with a message of
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003558 "Unexpected EOF".
3559 """
Alex Chanb7480992017-01-30 14:04:47 +00003560 server_conn, client_conn = loopback()
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003561 client_conn.sock_shutdown(SHUT_RDWR)
Alex Chanb7480992017-01-30 14:04:47 +00003562 with pytest.raises(SysCallError) as err:
3563 server_conn.recv(1024)
3564 assert err.value.args == (-1, "Unexpected EOF")
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003565
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003566 def _check_client_ca_list(self, func):
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003567 """
Alex Chanb7480992017-01-30 14:04:47 +00003568 Verify the return value of the `get_client_ca_list` method for
Hynek Schlawack35618382015-09-05 21:54:25 +02003569 server and client connections.
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003570
Jonathan Ballet78b92a22011-07-16 08:07:26 +09003571 :param func: A function which will be called with the server context
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003572 before the client and server are connected to each other. This
3573 function should specify a list of CAs for the server to send to the
3574 client and return that same list. The list will be used to verify
Alex Chanb7480992017-01-30 14:04:47 +00003575 that `get_client_ca_list` returns the proper value at
Hynek Schlawack35618382015-09-05 21:54:25 +02003576 various times.
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003577 """
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003578 server = self._server(None)
3579 client = self._client(None)
Alex Chanb7480992017-01-30 14:04:47 +00003580 assert client.get_client_ca_list() == []
3581 assert server.get_client_ca_list() == []
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003582 ctx = server.get_context()
3583 expected = func(ctx)
Alex Chanb7480992017-01-30 14:04:47 +00003584 assert client.get_client_ca_list() == []
3585 assert server.get_client_ca_list() == expected
3586 interact_in_memory(client, server)
3587 assert client.get_client_ca_list() == expected
3588 assert server.get_client_ca_list() == expected
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003589
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003590 def test_set_client_ca_list_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003591 """
Alex Chanb7480992017-01-30 14:04:47 +00003592 `Context.set_client_ca_list` raises a `TypeError` if called with a
3593 non-list or a list that contains objects other than X509Names.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003594 """
3595 ctx = Context(TLSv1_METHOD)
Alex Chanb7480992017-01-30 14:04:47 +00003596 with pytest.raises(TypeError):
3597 ctx.set_client_ca_list("spam")
3598 with pytest.raises(TypeError):
3599 ctx.set_client_ca_list(["spam"])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003600
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003601 def test_set_empty_ca_list(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003602 """
Alex Chanb7480992017-01-30 14:04:47 +00003603 If passed an empty list, `Context.set_client_ca_list` configures the
3604 context to send no CA names to the client and, on both the server and
3605 client sides, `Connection.get_client_ca_list` returns an empty list
3606 after the connection is set up.
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003607 """
3608 def no_ca(ctx):
3609 ctx.set_client_ca_list([])
3610 return []
3611 self._check_client_ca_list(no_ca)
3612
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003613 def test_set_one_ca_list(self):
3614 """
3615 If passed a list containing a single X509Name,
Alex Chanb7480992017-01-30 14:04:47 +00003616 `Context.set_client_ca_list` configures the context to send
Hynek Schlawack35618382015-09-05 21:54:25 +02003617 that CA name to the client and, on both the server and client sides,
Alex Chanb7480992017-01-30 14:04:47 +00003618 `Connection.get_client_ca_list` returns a list containing that
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003619 X509Name after the connection is set up.
3620 """
3621 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3622 cadesc = cacert.get_subject()
Hynek Schlawack35618382015-09-05 21:54:25 +02003623
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003624 def single_ca(ctx):
3625 ctx.set_client_ca_list([cadesc])
3626 return [cadesc]
3627 self._check_client_ca_list(single_ca)
3628
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003629 def test_set_multiple_ca_list(self):
3630 """
3631 If passed a list containing multiple X509Name objects,
Alex Chanb7480992017-01-30 14:04:47 +00003632 `Context.set_client_ca_list` configures the context to send
Hynek Schlawack35618382015-09-05 21:54:25 +02003633 those CA names to the client and, on both the server and client sides,
Alex Chanb7480992017-01-30 14:04:47 +00003634 `Connection.get_client_ca_list` returns a list containing those
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003635 X509Names after the connection is set up.
3636 """
3637 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3638 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3639
3640 sedesc = secert.get_subject()
3641 cldesc = clcert.get_subject()
3642
3643 def multiple_ca(ctx):
3644 L = [sedesc, cldesc]
3645 ctx.set_client_ca_list(L)
3646 return L
3647 self._check_client_ca_list(multiple_ca)
3648
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003649 def test_reset_ca_list(self):
3650 """
3651 If called multiple times, only the X509Names passed to the final call
Alex Chanb7480992017-01-30 14:04:47 +00003652 of `Context.set_client_ca_list` are used to configure the CA
Hynek Schlawack35618382015-09-05 21:54:25 +02003653 names sent to the client.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003654 """
3655 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3656 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3657 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3658
3659 cadesc = cacert.get_subject()
3660 sedesc = secert.get_subject()
3661 cldesc = clcert.get_subject()
3662
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003663 def changed_ca(ctx):
3664 ctx.set_client_ca_list([sedesc, cldesc])
3665 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003666 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003667 self._check_client_ca_list(changed_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003668
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003669 def test_mutated_ca_list(self):
3670 """
Alex Chanb7480992017-01-30 14:04:47 +00003671 If the list passed to `Context.set_client_ca_list` is mutated
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003672 afterwards, this does not affect the list of CA names sent to the
3673 client.
3674 """
3675 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3676 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3677
3678 cadesc = cacert.get_subject()
3679 sedesc = secert.get_subject()
3680
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003681 def mutated_ca(ctx):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003682 L = [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003683 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003684 L.append(sedesc)
3685 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003686 self._check_client_ca_list(mutated_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003687
Alex Chanb7480992017-01-30 14:04:47 +00003688 def test_add_client_ca_wrong_args(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003689 """
Alex Chanb7480992017-01-30 14:04:47 +00003690 `Context.add_client_ca` raises `TypeError` if called with
3691 a non-X509 object.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003692 """
3693 ctx = Context(TLSv1_METHOD)
Alex Chanb7480992017-01-30 14:04:47 +00003694 with pytest.raises(TypeError):
3695 ctx.add_client_ca("spam")
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003696
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003697 def test_one_add_client_ca(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003698 """
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003699 A certificate's subject can be added as a CA to be sent to the client
Alex Chanb7480992017-01-30 14:04:47 +00003700 with `Context.add_client_ca`.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003701 """
3702 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3703 cadesc = cacert.get_subject()
Hynek Schlawack35618382015-09-05 21:54:25 +02003704
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003705 def single_ca(ctx):
3706 ctx.add_client_ca(cacert)
3707 return [cadesc]
3708 self._check_client_ca_list(single_ca)
3709
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003710 def test_multiple_add_client_ca(self):
3711 """
3712 Multiple CA names can be sent to the client by calling
Alex Chanb7480992017-01-30 14:04:47 +00003713 `Context.add_client_ca` with multiple X509 objects.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003714 """
3715 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3716 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3717
3718 cadesc = cacert.get_subject()
3719 sedesc = secert.get_subject()
3720
3721 def multiple_ca(ctx):
3722 ctx.add_client_ca(cacert)
3723 ctx.add_client_ca(secert)
3724 return [cadesc, sedesc]
3725 self._check_client_ca_list(multiple_ca)
3726
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003727 def test_set_and_add_client_ca(self):
3728 """
Alex Chanb7480992017-01-30 14:04:47 +00003729 A call to `Context.set_client_ca_list` followed by a call to
3730 `Context.add_client_ca` results in using the CA names from the
Hynek Schlawack35618382015-09-05 21:54:25 +02003731 first call and the CA name from the second call.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003732 """
3733 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3734 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3735 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3736
3737 cadesc = cacert.get_subject()
3738 sedesc = secert.get_subject()
3739 cldesc = clcert.get_subject()
3740
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003741 def mixed_set_add_ca(ctx):
3742 ctx.set_client_ca_list([cadesc, sedesc])
3743 ctx.add_client_ca(clcert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003744 return [cadesc, sedesc, cldesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003745 self._check_client_ca_list(mixed_set_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003746
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003747 def test_set_after_add_client_ca(self):
3748 """
Alex Chanb7480992017-01-30 14:04:47 +00003749 A call to `Context.set_client_ca_list` after a call to
3750 `Context.add_client_ca` replaces the CA name specified by the
Hynek Schlawack35618382015-09-05 21:54:25 +02003751 former call with the names specified by the latter call.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003752 """
3753 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3754 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3755 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3756
3757 cadesc = cacert.get_subject()
3758 sedesc = secert.get_subject()
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003759
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003760 def set_replaces_add_ca(ctx):
3761 ctx.add_client_ca(clcert)
3762 ctx.set_client_ca_list([cadesc])
3763 ctx.add_client_ca(secert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003764 return [cadesc, sedesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003765 self._check_client_ca_list(set_replaces_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003766
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003767
Alex Chanb7480992017-01-30 14:04:47 +00003768class TestInfoConstants(object):
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003769 """
3770 Tests for assorted constants exposed for use in info callbacks.
3771 """
3772 def test_integers(self):
3773 """
3774 All of the info constants are integers.
3775
3776 This is a very weak test. It would be nice to have one that actually
3777 verifies that as certain info events happen, the value passed to the
3778 info callback matches up with the constant exposed by OpenSSL.SSL.
3779 """
3780 for const in [
Alex Gaynor5af32d02016-09-24 01:52:21 -04003781 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK,
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003782 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
3783 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
3784 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
Hynek Schlawack35618382015-09-05 21:54:25 +02003785 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE
3786 ]:
Alex Gaynor5af32d02016-09-24 01:52:21 -04003787 assert isinstance(const, int)
3788
3789 # These constants don't exist on OpenSSL 1.1.0
3790 for const in [
3791 SSL_ST_INIT, SSL_ST_BEFORE, SSL_ST_OK, SSL_ST_RENEGOTIATE
3792 ]:
3793 assert const is None or isinstance(const, int)
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003794
Ziga Seilnacht44611bf2009-08-31 20:49:30 +02003795
Cory Benfield1d142142016-03-30 11:51:45 +01003796class TestRequires(object):
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003797 """
3798 Tests for the decorator factory used to conditionally raise
Cory Benfield1d142142016-03-30 11:51:45 +01003799 NotImplementedError when older OpenSSLs are used.
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003800 """
3801 def test_available(self):
3802 """
3803 When the OpenSSL functionality is available the decorated functions
3804 work appropriately.
3805 """
3806 feature_guard = _make_requires(True, "Error text")
3807 results = []
3808
3809 @feature_guard
3810 def inner():
3811 results.append(True)
3812 return True
3813
Cory Benfield2333e5e2016-03-30 14:24:16 +01003814 assert inner() is True
3815 assert [True] == results
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003816
3817 def test_unavailable(self):
3818 """
3819 When the OpenSSL functionality is not available the decorated function
3820 does not execute and NotImplementedError is raised.
3821 """
3822 feature_guard = _make_requires(False, "Error text")
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003823
3824 @feature_guard
Alex Chanfb078d82017-04-20 11:16:15 +01003825 def inner(): # pragma: nocover
3826 pytest.fail("Should not be called")
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003827
Cory Benfield1d142142016-03-30 11:51:45 +01003828 with pytest.raises(NotImplementedError) as e:
3829 inner()
3830
3831 assert "Error text" in str(e.value)
Cory Benfield496652a2017-01-24 11:42:56 +00003832
3833
Alex Chanb7480992017-01-30 14:04:47 +00003834class TestOCSP(object):
Cory Benfield496652a2017-01-24 11:42:56 +00003835 """
3836 Tests for PyOpenSSL's OCSP stapling support.
3837 """
3838 sample_ocsp_data = b"this is totally ocsp data"
3839
3840 def _client_connection(self, callback, data, request_ocsp=True):
3841 """
3842 Builds a client connection suitable for using OCSP.
3843
3844 :param callback: The callback to register for OCSP.
3845 :param data: The opaque data object that will be handed to the
3846 OCSP callback.
3847 :param request_ocsp: Whether the client will actually ask for OCSP
3848 stapling. Useful for testing only.
3849 """
3850 ctx = Context(SSLv23_METHOD)
3851 ctx.set_ocsp_client_callback(callback, data)
3852 client = Connection(ctx)
3853
3854 if request_ocsp:
3855 client.request_ocsp()
3856
3857 client.set_connect_state()
3858 return client
3859
3860 def _server_connection(self, callback, data):
3861 """
3862 Builds a server connection suitable for using OCSP.
3863
3864 :param callback: The callback to register for OCSP.
3865 :param data: The opaque data object that will be handed to the
3866 OCSP callback.
3867 """
3868 ctx = Context(SSLv23_METHOD)
3869 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
3870 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
3871 ctx.set_ocsp_server_callback(callback, data)
3872 server = Connection(ctx)
3873 server.set_accept_state()
3874 return server
3875
3876 def test_callbacks_arent_called_by_default(self):
3877 """
3878 If both the client and the server have registered OCSP callbacks, but
3879 the client does not send the OCSP request, neither callback gets
3880 called.
3881 """
Alex Chanfb078d82017-04-20 11:16:15 +01003882 def ocsp_callback(*args, **kwargs): # pragma: nocover
3883 pytest.fail("Should not be called")
Cory Benfield496652a2017-01-24 11:42:56 +00003884
3885 client = self._client_connection(
3886 callback=ocsp_callback, data=None, request_ocsp=False
3887 )
3888 server = self._server_connection(callback=ocsp_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00003889 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003890
Cory Benfield496652a2017-01-24 11:42:56 +00003891 def test_client_negotiates_without_server(self):
3892 """
3893 If the client wants to do OCSP but the server does not, the handshake
3894 succeeds, and the client callback fires with an empty byte string.
3895 """
3896 called = []
3897
3898 def ocsp_callback(conn, ocsp_data, ignored):
3899 called.append(ocsp_data)
3900 return True
3901
3902 client = self._client_connection(callback=ocsp_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00003903 server = loopback_server_factory(socket=None)
3904 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003905
3906 assert len(called) == 1
3907 assert called[0] == b''
3908
3909 def test_client_receives_servers_data(self):
3910 """
3911 The data the server sends in its callback is received by the client.
3912 """
3913 calls = []
3914
3915 def server_callback(*args, **kwargs):
3916 return self.sample_ocsp_data
3917
3918 def client_callback(conn, ocsp_data, ignored):
3919 calls.append(ocsp_data)
3920 return True
3921
3922 client = self._client_connection(callback=client_callback, data=None)
3923 server = self._server_connection(callback=server_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00003924 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003925
3926 assert len(calls) == 1
3927 assert calls[0] == self.sample_ocsp_data
3928
3929 def test_callbacks_are_invoked_with_connections(self):
3930 """
3931 The first arguments to both callbacks are their respective connections.
3932 """
3933 client_calls = []
3934 server_calls = []
3935
3936 def client_callback(conn, *args, **kwargs):
3937 client_calls.append(conn)
3938 return True
3939
3940 def server_callback(conn, *args, **kwargs):
3941 server_calls.append(conn)
3942 return self.sample_ocsp_data
3943
3944 client = self._client_connection(callback=client_callback, data=None)
3945 server = self._server_connection(callback=server_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00003946 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003947
3948 assert len(client_calls) == 1
3949 assert len(server_calls) == 1
3950 assert client_calls[0] is client
3951 assert server_calls[0] is server
3952
3953 def test_opaque_data_is_passed_through(self):
3954 """
3955 Both callbacks receive an opaque, user-provided piece of data in their
3956 callbacks as the final argument.
3957 """
3958 calls = []
3959
3960 def server_callback(*args):
3961 calls.append(args)
3962 return self.sample_ocsp_data
3963
3964 def client_callback(*args):
3965 calls.append(args)
3966 return True
3967
3968 sentinel = object()
3969
3970 client = self._client_connection(
3971 callback=client_callback, data=sentinel
3972 )
3973 server = self._server_connection(
3974 callback=server_callback, data=sentinel
3975 )
Alex Chanb7480992017-01-30 14:04:47 +00003976 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003977
3978 assert len(calls) == 2
3979 assert calls[0][-1] is sentinel
3980 assert calls[1][-1] is sentinel
3981
3982 def test_server_returns_empty_string(self):
3983 """
3984 If the server returns an empty bytestring from its callback, the
3985 client callback is called with the empty bytestring.
3986 """
3987 client_calls = []
3988
3989 def server_callback(*args):
3990 return b''
3991
3992 def client_callback(conn, ocsp_data, ignored):
3993 client_calls.append(ocsp_data)
3994 return True
3995
3996 client = self._client_connection(callback=client_callback, data=None)
3997 server = self._server_connection(callback=server_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00003998 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003999
4000 assert len(client_calls) == 1
4001 assert client_calls[0] == b''
4002
4003 def test_client_returns_false_terminates_handshake(self):
4004 """
4005 If the client returns False from its callback, the handshake fails.
4006 """
4007 def server_callback(*args):
4008 return self.sample_ocsp_data
4009
4010 def client_callback(*args):
4011 return False
4012
4013 client = self._client_connection(callback=client_callback, data=None)
4014 server = self._server_connection(callback=server_callback, data=None)
4015
4016 with pytest.raises(Error):
Alex Chanb7480992017-01-30 14:04:47 +00004017 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00004018
4019 def test_exceptions_in_client_bubble_up(self):
4020 """
4021 The callbacks thrown in the client callback bubble up to the caller.
4022 """
4023 class SentinelException(Exception):
4024 pass
4025
4026 def server_callback(*args):
4027 return self.sample_ocsp_data
4028
4029 def client_callback(*args):
4030 raise SentinelException()
4031
4032 client = self._client_connection(callback=client_callback, data=None)
4033 server = self._server_connection(callback=server_callback, data=None)
4034
4035 with pytest.raises(SentinelException):
Alex Chanb7480992017-01-30 14:04:47 +00004036 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00004037
4038 def test_exceptions_in_server_bubble_up(self):
4039 """
4040 The callbacks thrown in the server callback bubble up to the caller.
4041 """
4042 class SentinelException(Exception):
4043 pass
4044
4045 def server_callback(*args):
4046 raise SentinelException()
4047
Alex Chanfb078d82017-04-20 11:16:15 +01004048 def client_callback(*args): # pragma: nocover
Cory Benfield496652a2017-01-24 11:42:56 +00004049 pytest.fail("Should not be called")
4050
4051 client = self._client_connection(callback=client_callback, data=None)
4052 server = self._server_connection(callback=server_callback, data=None)
4053
4054 with pytest.raises(SentinelException):
Alex Chanb7480992017-01-30 14:04:47 +00004055 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00004056
4057 def test_server_must_return_bytes(self):
4058 """
4059 The server callback must return a bytestring, or a TypeError is thrown.
4060 """
4061 def server_callback(*args):
4062 return self.sample_ocsp_data.decode('ascii')
4063
Alex Chanfb078d82017-04-20 11:16:15 +01004064 def client_callback(*args): # pragma: nocover
Cory Benfield496652a2017-01-24 11:42:56 +00004065 pytest.fail("Should not be called")
4066
4067 client = self._client_connection(callback=client_callback, data=None)
4068 server = self._server_connection(callback=server_callback, data=None)
4069
4070 with pytest.raises(TypeError):
Alex Chanb7480992017-01-30 14:04:47 +00004071 handshake_in_memory(client, server)