blob: 9a3f29473e8363585d33340a8e977d083e0b387c [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 """
Cory Benfielde46fa842015-04-13 16:50:49 -04001849 # Skip tests on versions that don't support ALPN.
1850 if _lib.Cryptography_HAS_ALPN:
Cory Benfield12eae892014-06-07 15:42:56 +01001851
Cory Benfielde46fa842015-04-13 16:50:49 -04001852 def test_alpn_success(self):
1853 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04001854 Clients and servers that agree on the negotiated ALPN protocol can
1855 correct establish a connection, and the agreed protocol is reported
1856 by the connections.
Cory Benfielde46fa842015-04-13 16:50:49 -04001857 """
1858 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001859
Cory Benfielde46fa842015-04-13 16:50:49 -04001860 def select(conn, options):
1861 select_args.append((conn, options))
1862 return b'spdy/2'
Cory Benfield12eae892014-06-07 15:42:56 +01001863
Cory Benfielde46fa842015-04-13 16:50:49 -04001864 client_context = Context(TLSv1_METHOD)
1865 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfield12eae892014-06-07 15:42:56 +01001866
Cory Benfielde46fa842015-04-13 16:50:49 -04001867 server_context = Context(TLSv1_METHOD)
1868 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01001869
Cory Benfielde46fa842015-04-13 16:50:49 -04001870 # Necessary to actually accept the connection
1871 server_context.use_privatekey(
1872 load_privatekey(FILETYPE_PEM, server_key_pem))
1873 server_context.use_certificate(
1874 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield12eae892014-06-07 15:42:56 +01001875
Cory Benfielde46fa842015-04-13 16:50:49 -04001876 # Do a little connection to trigger the logic
1877 server = Connection(server_context, None)
1878 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001879
Cory Benfielde46fa842015-04-13 16:50:49 -04001880 client = Connection(client_context, None)
1881 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001882
Alex Chanec1e32d2016-11-10 14:11:45 +00001883 interact_in_memory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001884
Alex Chanec1e32d2016-11-10 14:11:45 +00001885 assert select_args == [(server, [b'http/1.1', b'spdy/2'])]
Cory Benfielde46fa842015-04-13 16:50:49 -04001886
Alex Chanec1e32d2016-11-10 14:11:45 +00001887 assert server.get_alpn_proto_negotiated() == b'spdy/2'
1888 assert client.get_alpn_proto_negotiated() == b'spdy/2'
Cory Benfield12eae892014-06-07 15:42:56 +01001889
Cory Benfielde46fa842015-04-13 16:50:49 -04001890 def test_alpn_set_on_connection(self):
1891 """
1892 The same as test_alpn_success, but setting the ALPN protocols on
1893 the connection rather than the context.
1894 """
1895 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001896
Cory Benfielde46fa842015-04-13 16:50:49 -04001897 def select(conn, options):
1898 select_args.append((conn, options))
1899 return b'spdy/2'
Cory Benfield12eae892014-06-07 15:42:56 +01001900
Cory Benfielde46fa842015-04-13 16:50:49 -04001901 # Setup the client context but don't set any ALPN protocols.
1902 client_context = Context(TLSv1_METHOD)
Cory Benfield12eae892014-06-07 15:42:56 +01001903
Cory Benfielde46fa842015-04-13 16:50:49 -04001904 server_context = Context(TLSv1_METHOD)
1905 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01001906
Cory Benfielde46fa842015-04-13 16:50:49 -04001907 # Necessary to actually accept the connection
1908 server_context.use_privatekey(
1909 load_privatekey(FILETYPE_PEM, server_key_pem))
1910 server_context.use_certificate(
1911 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield12eae892014-06-07 15:42:56 +01001912
Cory Benfielde46fa842015-04-13 16:50:49 -04001913 # Do a little connection to trigger the logic
1914 server = Connection(server_context, None)
1915 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001916
Cory Benfielde46fa842015-04-13 16:50:49 -04001917 # Set the ALPN protocols on the client connection.
1918 client = Connection(client_context, None)
1919 client.set_alpn_protos([b'http/1.1', b'spdy/2'])
1920 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001921
Alex Chanec1e32d2016-11-10 14:11:45 +00001922 interact_in_memory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001923
Alex Chanec1e32d2016-11-10 14:11:45 +00001924 assert select_args == [(server, [b'http/1.1', b'spdy/2'])]
Cory Benfield12eae892014-06-07 15:42:56 +01001925
Alex Chanec1e32d2016-11-10 14:11:45 +00001926 assert server.get_alpn_proto_negotiated() == b'spdy/2'
1927 assert client.get_alpn_proto_negotiated() == b'spdy/2'
Cory Benfield12eae892014-06-07 15:42:56 +01001928
Cory Benfielde46fa842015-04-13 16:50:49 -04001929 def test_alpn_server_fail(self):
1930 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04001931 When clients and servers cannot agree on what protocol to use next
1932 the TLS connection does not get established.
Cory Benfielde46fa842015-04-13 16:50:49 -04001933 """
1934 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001935
Cory Benfielde46fa842015-04-13 16:50:49 -04001936 def select(conn, options):
1937 select_args.append((conn, options))
1938 return b''
Cory Benfield12eae892014-06-07 15:42:56 +01001939
Cory Benfielde46fa842015-04-13 16:50:49 -04001940 client_context = Context(TLSv1_METHOD)
1941 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfield12eae892014-06-07 15:42:56 +01001942
Cory Benfielde46fa842015-04-13 16:50:49 -04001943 server_context = Context(TLSv1_METHOD)
1944 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01001945
Cory Benfielde46fa842015-04-13 16:50:49 -04001946 # Necessary to actually accept the connection
1947 server_context.use_privatekey(
1948 load_privatekey(FILETYPE_PEM, server_key_pem))
1949 server_context.use_certificate(
1950 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield12eae892014-06-07 15:42:56 +01001951
Cory Benfielde46fa842015-04-13 16:50:49 -04001952 # Do a little connection to trigger the logic
1953 server = Connection(server_context, None)
1954 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001955
Cory Benfielde46fa842015-04-13 16:50:49 -04001956 client = Connection(client_context, None)
1957 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001958
Cory Benfielde46fa842015-04-13 16:50:49 -04001959 # If the client doesn't return anything, the connection will fail.
Alex Chanec1e32d2016-11-10 14:11:45 +00001960 with pytest.raises(Error):
1961 interact_in_memory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001962
Alex Chanec1e32d2016-11-10 14:11:45 +00001963 assert select_args == [(server, [b'http/1.1', b'spdy/2'])]
Cory Benfield12eae892014-06-07 15:42:56 +01001964
Mark Williams5d890a02019-11-17 19:56:26 -08001965 def test_alpn_no_server_overlap(self):
1966 """
1967 A server can allow a TLS handshake to complete without
1968 agreeing to an application protocol by returning
1969 ``NO_OVERLAPPING_PROTOCOLS``.
1970 """
1971 refusal_args = []
1972
1973 def refusal(conn, options):
1974 refusal_args.append((conn, options))
1975 return NO_OVERLAPPING_PROTOCOLS
1976
1977 client_context = Context(SSLv23_METHOD)
1978 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
1979
1980 server_context = Context(SSLv23_METHOD)
1981 server_context.set_alpn_select_callback(refusal)
1982
1983 # Necessary to actually accept the connection
1984 server_context.use_privatekey(
1985 load_privatekey(FILETYPE_PEM, server_key_pem))
1986 server_context.use_certificate(
1987 load_certificate(FILETYPE_PEM, server_cert_pem))
1988
1989 # Do a little connection to trigger the logic
1990 server = Connection(server_context, None)
1991 server.set_accept_state()
1992
1993 client = Connection(client_context, None)
1994 client.set_connect_state()
1995
1996 # Do the dance.
1997 interact_in_memory(server, client)
1998
1999 assert refusal_args == [(server, [b'http/1.1', b'spdy/2'])]
2000
2001 assert client.get_alpn_proto_negotiated() == b''
2002
2003 def test_alpn_select_cb_returns_invalid_value(self):
2004 """
2005 If the ALPN selection callback returns anything other than
2006 a bytestring or ``NO_OVERLAPPING_PROTOCOLS``, a
2007 :py:exc:`TypeError` is raised.
2008 """
2009 invalid_cb_args = []
2010
2011 def invalid_cb(conn, options):
2012 invalid_cb_args.append((conn, options))
2013 return u"can't return unicode"
2014
2015 client_context = Context(SSLv23_METHOD)
2016 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
2017
2018 server_context = Context(SSLv23_METHOD)
2019 server_context.set_alpn_select_callback(invalid_cb)
2020
2021 # Necessary to actually accept the connection
2022 server_context.use_privatekey(
2023 load_privatekey(FILETYPE_PEM, server_key_pem))
2024 server_context.use_certificate(
2025 load_certificate(FILETYPE_PEM, server_cert_pem))
2026
2027 # Do a little connection to trigger the logic
2028 server = Connection(server_context, None)
2029 server.set_accept_state()
2030
2031 client = Connection(client_context, None)
2032 client.set_connect_state()
2033
2034 # Do the dance.
2035 with pytest.raises(TypeError):
2036 interact_in_memory(server, client)
2037
2038 assert invalid_cb_args == [(server, [b'http/1.1', b'spdy/2'])]
2039
2040 assert client.get_alpn_proto_negotiated() == b''
2041
Cory Benfielde46fa842015-04-13 16:50:49 -04002042 def test_alpn_no_server(self):
2043 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04002044 When clients and servers cannot agree on what protocol to use next
2045 because the server doesn't offer ALPN, no protocol is negotiated.
Cory Benfielde46fa842015-04-13 16:50:49 -04002046 """
2047 client_context = Context(TLSv1_METHOD)
2048 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfielde3d57152015-04-11 17:57:35 -04002049
Cory Benfielde46fa842015-04-13 16:50:49 -04002050 server_context = Context(TLSv1_METHOD)
Cory Benfielde3d57152015-04-11 17:57:35 -04002051
Cory Benfielde46fa842015-04-13 16:50:49 -04002052 # Necessary to actually accept the connection
2053 server_context.use_privatekey(
2054 load_privatekey(FILETYPE_PEM, server_key_pem))
2055 server_context.use_certificate(
2056 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfielde3d57152015-04-11 17:57:35 -04002057
Cory Benfielde46fa842015-04-13 16:50:49 -04002058 # Do a little connection to trigger the logic
2059 server = Connection(server_context, None)
2060 server.set_accept_state()
Cory Benfielde3d57152015-04-11 17:57:35 -04002061
Cory Benfielde46fa842015-04-13 16:50:49 -04002062 client = Connection(client_context, None)
2063 client.set_connect_state()
Cory Benfielde3d57152015-04-11 17:57:35 -04002064
Cory Benfielde46fa842015-04-13 16:50:49 -04002065 # Do the dance.
Alex Chanec1e32d2016-11-10 14:11:45 +00002066 interact_in_memory(server, client)
Cory Benfielde3d57152015-04-11 17:57:35 -04002067
Alex Chanec1e32d2016-11-10 14:11:45 +00002068 assert client.get_alpn_proto_negotiated() == b''
Cory Benfielde3d57152015-04-11 17:57:35 -04002069
Cory Benfielde46fa842015-04-13 16:50:49 -04002070 def test_alpn_callback_exception(self):
2071 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04002072 We can handle exceptions in the ALPN select callback.
Cory Benfielde46fa842015-04-13 16:50:49 -04002073 """
2074 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002075
Cory Benfielde46fa842015-04-13 16:50:49 -04002076 def select(conn, options):
2077 select_args.append((conn, options))
Cory Benfieldef401452015-04-13 18:17:36 -04002078 raise TypeError()
Cory Benfieldf1177e72015-04-12 09:11:49 -04002079
Cory Benfielde46fa842015-04-13 16:50:49 -04002080 client_context = Context(TLSv1_METHOD)
2081 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfieldf1177e72015-04-12 09:11:49 -04002082
Cory Benfielde46fa842015-04-13 16:50:49 -04002083 server_context = Context(TLSv1_METHOD)
2084 server_context.set_alpn_select_callback(select)
Cory Benfieldf1177e72015-04-12 09:11:49 -04002085
Cory Benfielde46fa842015-04-13 16:50:49 -04002086 # Necessary to actually accept the connection
2087 server_context.use_privatekey(
2088 load_privatekey(FILETYPE_PEM, server_key_pem))
2089 server_context.use_certificate(
2090 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfieldf1177e72015-04-12 09:11:49 -04002091
Cory Benfielde46fa842015-04-13 16:50:49 -04002092 # Do a little connection to trigger the logic
2093 server = Connection(server_context, None)
2094 server.set_accept_state()
Cory Benfieldf1177e72015-04-12 09:11:49 -04002095
Cory Benfielde46fa842015-04-13 16:50:49 -04002096 client = Connection(client_context, None)
2097 client.set_connect_state()
Cory Benfieldf1177e72015-04-12 09:11:49 -04002098
Alex Chanec1e32d2016-11-10 14:11:45 +00002099 with pytest.raises(TypeError):
2100 interact_in_memory(server, client)
2101 assert select_args == [(server, [b'http/1.1', b'spdy/2'])]
Cory Benfieldf1177e72015-04-12 09:11:49 -04002102
Cory Benfield0f7b04c2015-04-13 17:51:12 -04002103 else:
2104 # No ALPN.
2105 def test_alpn_not_implemented(self):
Cory Benfieldef401452015-04-13 18:17:36 -04002106 """
2107 If ALPN is not in OpenSSL, we should raise NotImplementedError.
2108 """
Cory Benfield0f7b04c2015-04-13 17:51:12 -04002109 # Test the context methods first.
2110 context = Context(TLSv1_METHOD)
Alex Chanec1e32d2016-11-10 14:11:45 +00002111 with pytest.raises(NotImplementedError):
2112 context.set_alpn_protos(None)
2113 with pytest.raises(NotImplementedError):
2114 context.set_alpn_select_callback(None)
Cory Benfield0f7b04c2015-04-13 17:51:12 -04002115
2116 # Now test a connection.
2117 conn = Connection(context)
Alex Chanec1e32d2016-11-10 14:11:45 +00002118 with pytest.raises(NotImplementedError):
2119 conn.set_alpn_protos(None)
Cory Benfield0f7b04c2015-04-13 17:51:12 -04002120
Cory Benfieldf1177e72015-04-12 09:11:49 -04002121
Alex Chanec1e32d2016-11-10 14:11:45 +00002122class TestSession(object):
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05002123 """
2124 Unit tests for :py:obj:`OpenSSL.SSL.Session`.
2125 """
2126 def test_construction(self):
2127 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002128 :py:class:`Session` can be constructed with no arguments, creating
2129 a new instance of that type.
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05002130 """
2131 new_session = Session()
Alex Chanec1e32d2016-11-10 14:11:45 +00002132 assert isinstance(new_session, Session)
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05002133
2134
Alex Chan1c0cb662017-01-30 07:13:30 +00002135class TestConnection(object):
Rick Deane15b1472009-07-09 15:53:42 -05002136 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002137 Unit tests for `OpenSSL.SSL.Connection`.
Rick Deane15b1472009-07-09 15:53:42 -05002138 """
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04002139 # XXX get_peer_certificate -> None
2140 # XXX sock_shutdown
2141 # XXX master_key -> TypeError
2142 # XXX server_random -> TypeError
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04002143 # XXX connect -> TypeError
2144 # XXX connect_ex -> TypeError
2145 # XXX set_connect_state -> TypeError
2146 # XXX set_accept_state -> TypeError
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04002147 # XXX do_handshake -> TypeError
2148 # XXX bio_read -> TypeError
2149 # XXX recv -> TypeError
2150 # XXX send -> TypeError
2151 # XXX bio_write -> TypeError
2152
Rick Deane15b1472009-07-09 15:53:42 -05002153 def test_type(self):
2154 """
Alex Gaynor01f90a12019-02-07 09:14:48 -05002155 `Connection` can be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -05002156 """
2157 ctx = Context(TLSv1_METHOD)
Alex Chan1c0cb662017-01-30 07:13:30 +00002158 assert is_consistent_type(Connection, 'Connection', ctx, None)
Rick Deane15b1472009-07-09 15:53:42 -05002159
Alex Chanfb078d82017-04-20 11:16:15 +01002160 @pytest.mark.parametrize('bad_context', [object(), 'context', None, 1])
2161 def test_wrong_args(self, bad_context):
2162 """
2163 `Connection.__init__` raises `TypeError` if called with a non-`Context`
2164 instance argument.
2165 """
2166 with pytest.raises(TypeError):
2167 Connection(bad_context)
2168
Daniel Holth079c9632019-11-17 22:45:52 -05002169 @pytest.mark.parametrize('bad_bio', [object(), None, 1, [1, 2, 3]])
2170 def test_bio_write_wrong_args(self, bad_bio):
2171 """
2172 `Connection.bio_write` raises `TypeError` if called with a non-bytes
2173 (or text) argument.
2174 """
2175 context = Context(TLSv1_METHOD)
2176 connection = Connection(context, None)
2177 with pytest.raises(TypeError):
2178 connection.bio_write(bad_bio)
2179
2180 def test_bio_write(self):
2181 """
2182 `Connection.bio_write` does not raise if called with bytes or
2183 bytearray, warns if called with text.
2184 """
2185 context = Context(TLSv1_METHOD)
2186 connection = Connection(context, None)
2187 connection.bio_write(b'xy')
2188 connection.bio_write(bytearray(b'za'))
2189 with pytest.warns(DeprecationWarning):
2190 connection.bio_write(u'deprecated')
2191
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002192 def test_get_context(self):
2193 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002194 `Connection.get_context` returns the `Context` instance used to
2195 construct the `Connection` instance.
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002196 """
2197 context = Context(TLSv1_METHOD)
2198 connection = Connection(context, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002199 assert connection.get_context() is context
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002200
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002201 def test_set_context_wrong_args(self):
2202 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002203 `Connection.set_context` raises `TypeError` if called with a
Alex Chanfb078d82017-04-20 11:16:15 +01002204 non-`Context` instance argument.
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002205 """
2206 ctx = Context(TLSv1_METHOD)
2207 connection = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002208 with pytest.raises(TypeError):
2209 connection.set_context(object())
2210 with pytest.raises(TypeError):
2211 connection.set_context("hello")
2212 with pytest.raises(TypeError):
2213 connection.set_context(1)
2214 assert ctx is connection.get_context()
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002215
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002216 def test_set_context(self):
2217 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002218 `Connection.set_context` specifies a new `Context` instance to be
2219 used for the connection.
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002220 """
2221 original = Context(SSLv23_METHOD)
2222 replacement = Context(TLSv1_METHOD)
2223 connection = Connection(original, None)
2224 connection.set_context(replacement)
Alex Chan1c0cb662017-01-30 07:13:30 +00002225 assert replacement is connection.get_context()
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002226 # Lose our references to the contexts, just in case the Connection
2227 # isn't properly managing its own contributions to their reference
2228 # counts.
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002229 del original, replacement
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002230 collect()
2231
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002232 def test_set_tlsext_host_name_wrong_args(self):
2233 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002234 If `Connection.set_tlsext_host_name` is called with a non-byte string
2235 argument or a byte string with an embedded NUL, `TypeError` is raised.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002236 """
2237 conn = Connection(Context(TLSv1_METHOD), None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002238 with pytest.raises(TypeError):
2239 conn.set_tlsext_host_name(object())
2240 with pytest.raises(TypeError):
2241 conn.set_tlsext_host_name(b"with\0null")
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002242
Hugo van Kemenade60827f82019-08-30 00:39:35 +03002243 if not PY2:
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002244 # On Python 3.x, don't accidentally implicitly convert from text.
Alex Chan1c0cb662017-01-30 07:13:30 +00002245 with pytest.raises(TypeError):
2246 conn.set_tlsext_host_name(b"example.com".decode("ascii"))
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04002247
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002248 def test_pending(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002249 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002250 `Connection.pending` returns the number of bytes available for
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002251 immediate read.
2252 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002253 connection = Connection(Context(TLSv1_METHOD), None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002254 assert connection.pending() == 0
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002255
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002256 def test_peek(self):
2257 """
Hynek Schlawack3bcf3152017-02-18 08:25:34 +01002258 `Connection.recv` peeks into the connection if `socket.MSG_PEEK` is
2259 passed.
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002260 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002261 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002262 server.send(b'xy')
Alex Chan1c0cb662017-01-30 07:13:30 +00002263 assert client.recv(2, MSG_PEEK) == b'xy'
2264 assert client.recv(2, MSG_PEEK) == b'xy'
2265 assert client.recv(2) == b'xy'
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002266
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002267 def test_connect_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002268 """
Hynek Schlawack3bcf3152017-02-18 08:25:34 +01002269 `Connection.connect` raises `TypeError` if called with a non-address
2270 argument.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002271 """
David Benjamin1fbe0642019-04-15 17:05:13 -05002272 connection = Connection(Context(TLSv1_METHOD), socket_any_family())
Alex Chan1c0cb662017-01-30 07:13:30 +00002273 with pytest.raises(TypeError):
2274 connection.connect(None)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002275
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002276 def test_connect_refused(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002277 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002278 `Connection.connect` raises `socket.error` if the underlying socket
2279 connect method raises it.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002280 """
David Benjamin1fbe0642019-04-15 17:05:13 -05002281 client = socket_any_family()
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002282 context = Context(TLSv1_METHOD)
2283 clientSSL = Connection(context, client)
Alex Gaynor122717b2015-09-05 14:14:18 -04002284 # pytest.raises here doesn't work because of a bug in py.test on Python
2285 # 2.6: https://github.com/pytest-dev/pytest/issues/988
Alex Gaynore69c2782015-09-05 14:07:48 -04002286 try:
David Benjamin1fbe0642019-04-15 17:05:13 -05002287 clientSSL.connect((loopback_address(client), 1))
Alex Gaynore69c2782015-09-05 14:07:48 -04002288 except error as e:
Alex Gaynor20a4c082015-09-05 14:24:15 -04002289 exc = e
2290 assert exc.args[0] == ECONNREFUSED
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002291
2292 def test_connect(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002293 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002294 `Connection.connect` establishes a connection to the specified address.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002295 """
David Benjamin1fbe0642019-04-15 17:05:13 -05002296 port = socket_any_family()
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002297 port.bind(('', 0))
2298 port.listen(3)
2299
David Benjamin1fbe0642019-04-15 17:05:13 -05002300 clientSSL = Connection(Context(TLSv1_METHOD), socket(port.family))
2301 clientSSL.connect((loopback_address(port), port.getsockname()[1]))
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002302 # XXX An assertion? Or something?
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002303
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002304 @pytest.mark.skipif(
2305 platform == "darwin",
2306 reason="connect_ex sometimes causes a kernel panic on OS X 10.6.4"
2307 )
2308 def test_connect_ex(self):
2309 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002310 If there is a connection error, `Connection.connect_ex` returns the
2311 errno instead of raising an exception.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002312 """
David Benjamin1fbe0642019-04-15 17:05:13 -05002313 port = socket_any_family()
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002314 port.bind(('', 0))
2315 port.listen(3)
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002316
David Benjamin1fbe0642019-04-15 17:05:13 -05002317 clientSSL = Connection(Context(TLSv1_METHOD), socket(port.family))
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002318 clientSSL.setblocking(False)
2319 result = clientSSL.connect_ex(port.getsockname())
2320 expected = (EINPROGRESS, EWOULDBLOCK)
Alex Chan1c0cb662017-01-30 07:13:30 +00002321 assert result in expected
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002322
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002323 def test_accept(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002324 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002325 `Connection.accept` accepts a pending connection attempt and returns a
2326 tuple of a new `Connection` (the accepted client) and the address the
2327 connection originated from.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002328 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002329 ctx = Context(TLSv1_METHOD)
2330 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2331 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
David Benjamin1fbe0642019-04-15 17:05:13 -05002332 port = socket_any_family()
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002333 portSSL = Connection(ctx, port)
2334 portSSL.bind(('', 0))
2335 portSSL.listen(3)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002336
David Benjamin1fbe0642019-04-15 17:05:13 -05002337 clientSSL = Connection(Context(TLSv1_METHOD), socket(port.family))
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002338
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002339 # Calling portSSL.getsockname() here to get the server IP address
2340 # sounds great, but frequently fails on Windows.
David Benjamin1fbe0642019-04-15 17:05:13 -05002341 clientSSL.connect((loopback_address(port), portSSL.getsockname()[1]))
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002342
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002343 serverSSL, address = portSSL.accept()
2344
Alex Chan1c0cb662017-01-30 07:13:30 +00002345 assert isinstance(serverSSL, Connection)
2346 assert serverSSL.get_context() is ctx
2347 assert address == clientSSL.getsockname()
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002348
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002349 def test_shutdown_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002350 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002351 `Connection.set_shutdown` raises `TypeError` if called with arguments
2352 other than integers.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002353 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002354 connection = Connection(Context(TLSv1_METHOD), None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002355 with pytest.raises(TypeError):
2356 connection.set_shutdown(None)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002357
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002358 def test_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002359 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002360 `Connection.shutdown` performs an SSL-level connection shutdown.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002361 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002362 server, client = loopback()
2363 assert not server.shutdown()
2364 assert server.get_shutdown() == SENT_SHUTDOWN
2365 with pytest.raises(ZeroReturnError):
2366 client.recv(1024)
2367 assert client.get_shutdown() == RECEIVED_SHUTDOWN
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04002368 client.shutdown()
Alex Chan1c0cb662017-01-30 07:13:30 +00002369 assert client.get_shutdown() == (SENT_SHUTDOWN | RECEIVED_SHUTDOWN)
2370 with pytest.raises(ZeroReturnError):
2371 server.recv(1024)
2372 assert server.get_shutdown() == (SENT_SHUTDOWN | RECEIVED_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002373
Paul Aurichc85e0862015-01-08 08:34:33 -08002374 def test_shutdown_closed(self):
2375 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002376 If the underlying socket is closed, `Connection.shutdown` propagates
2377 the write error from the low level write call.
Paul Aurichc85e0862015-01-08 08:34:33 -08002378 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002379 server, client = loopback()
Paul Aurichc85e0862015-01-08 08:34:33 -08002380 server.sock_shutdown(2)
Alex Chan1c0cb662017-01-30 07:13:30 +00002381 with pytest.raises(SysCallError) as exc:
2382 server.shutdown()
Alex Chanfb078d82017-04-20 11:16:15 +01002383 if platform == "win32":
2384 assert exc.value.args[0] == ESHUTDOWN
2385 else:
2386 assert exc.value.args[0] == EPIPE
Paul Aurichc85e0862015-01-08 08:34:33 -08002387
Glyph89389472015-04-14 17:29:26 -04002388 def test_shutdown_truncated(self):
Glyph6064ec32015-04-14 16:38:22 -04002389 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002390 If the underlying connection is truncated, `Connection.shutdown`
2391 raises an `Error`.
Glyph6064ec32015-04-14 16:38:22 -04002392 """
Glyph89389472015-04-14 17:29:26 -04002393 server_ctx = Context(TLSv1_METHOD)
2394 client_ctx = Context(TLSv1_METHOD)
2395 server_ctx.use_privatekey(
2396 load_privatekey(FILETYPE_PEM, server_key_pem))
2397 server_ctx.use_certificate(
2398 load_certificate(FILETYPE_PEM, server_cert_pem))
2399 server = Connection(server_ctx, None)
2400 client = Connection(client_ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002401 handshake_in_memory(client, server)
2402 assert not server.shutdown()
2403 with pytest.raises(WantReadError):
2404 server.shutdown()
Glyph89389472015-04-14 17:29:26 -04002405 server.bio_shutdown()
Alex Chan1c0cb662017-01-30 07:13:30 +00002406 with pytest.raises(Error):
2407 server.shutdown()
Glyph6064ec32015-04-14 16:38:22 -04002408
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002409 def test_set_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002410 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002411 `Connection.set_shutdown` sets the state of the SSL connection
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002412 shutdown process.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002413 """
David Benjamin1fbe0642019-04-15 17:05:13 -05002414 connection = Connection(Context(TLSv1_METHOD), socket_any_family())
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002415 connection.set_shutdown(RECEIVED_SHUTDOWN)
Alex Chan1c0cb662017-01-30 07:13:30 +00002416 assert connection.get_shutdown() == RECEIVED_SHUTDOWN
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002417
kjavaf248592015-09-07 12:14:01 +01002418 def test_state_string(self):
2419 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002420 `Connection.state_string` verbosely describes the current state of
2421 the `Connection`.
kjavaf248592015-09-07 12:14:01 +01002422 """
Hynek Schlawackb0274ce2015-10-16 19:56:26 +02002423 server, client = socket_pair()
Alex Chan1c0cb662017-01-30 07:13:30 +00002424 server = loopback_server_factory(server)
2425 client = loopback_client_factory(client)
kjavaf248592015-09-07 12:14:01 +01002426
Alex Gaynor5af32d02016-09-24 01:52:21 -04002427 assert server.get_state_string() in [
2428 b"before/accept initialization", b"before SSL initialization"
2429 ]
2430 assert client.get_state_string() in [
2431 b"before/connect initialization", b"before SSL initialization"
2432 ]
kjavaf248592015-09-07 12:14:01 +01002433
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002434 def test_app_data(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002435 """
2436 Any object can be set as app data by passing it to
Alex Chan1c0cb662017-01-30 07:13:30 +00002437 `Connection.set_app_data` and later retrieved with
2438 `Connection.get_app_data`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002439 """
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002440 conn = Connection(Context(TLSv1_METHOD), None)
Todd Chapman4f73e4f2015-08-27 11:26:43 -04002441 assert None is conn.get_app_data()
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002442 app_data = object()
2443 conn.set_app_data(app_data)
Todd Chapman4f73e4f2015-08-27 11:26:43 -04002444 assert conn.get_app_data() is app_data
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002445
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002446 def test_makefile(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002447 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002448 `Connection.makefile` is not implemented and calling that
2449 method raises `NotImplementedError`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002450 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002451 conn = Connection(Context(TLSv1_METHOD), None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002452 with pytest.raises(NotImplementedError):
2453 conn.makefile()
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002454
Jeremy Lainé460a19d2018-05-16 19:44:19 +02002455 def test_get_certificate(self):
2456 """
2457 `Connection.get_certificate` returns the local certificate.
2458 """
2459 chain = _create_certificate_chain()
2460 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
2461
2462 context = Context(TLSv1_METHOD)
2463 context.use_certificate(scert)
2464 client = Connection(context, None)
2465 cert = client.get_certificate()
2466 assert cert is not None
2467 assert "Server Certificate" == cert.get_subject().CN
2468
2469 def test_get_certificate_none(self):
2470 """
2471 `Connection.get_certificate` returns the local certificate.
2472
2473 If there is no certificate, it returns None.
2474 """
2475 context = Context(TLSv1_METHOD)
2476 client = Connection(context, None)
2477 cert = client.get_certificate()
2478 assert cert is None
2479
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002480 def test_get_peer_cert_chain(self):
2481 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002482 `Connection.get_peer_cert_chain` returns a list of certificates
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002483 which the connected server returned for the certification verification.
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002484 """
2485 chain = _create_certificate_chain()
2486 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
2487
2488 serverContext = Context(TLSv1_METHOD)
2489 serverContext.use_privatekey(skey)
2490 serverContext.use_certificate(scert)
2491 serverContext.add_extra_chain_cert(icert)
2492 serverContext.add_extra_chain_cert(cacert)
2493 server = Connection(serverContext, None)
2494 server.set_accept_state()
2495
2496 # Create the client
2497 clientContext = Context(TLSv1_METHOD)
2498 clientContext.set_verify(VERIFY_NONE, verify_cb)
2499 client = Connection(clientContext, None)
2500 client.set_connect_state()
2501
Alex Chan1c0cb662017-01-30 07:13:30 +00002502 interact_in_memory(client, server)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002503
2504 chain = client.get_peer_cert_chain()
Alex Chan1c0cb662017-01-30 07:13:30 +00002505 assert len(chain) == 3
2506 assert "Server Certificate" == chain[0].get_subject().CN
2507 assert "Intermediate Certificate" == chain[1].get_subject().CN
2508 assert "Authority Certificate" == chain[2].get_subject().CN
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002509
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002510 def test_get_peer_cert_chain_none(self):
2511 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002512 `Connection.get_peer_cert_chain` returns `None` if the peer sends
2513 no certificate chain.
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002514 """
2515 ctx = Context(TLSv1_METHOD)
2516 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2517 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
2518 server = Connection(ctx, None)
2519 server.set_accept_state()
2520 client = Connection(Context(TLSv1_METHOD), None)
2521 client.set_connect_state()
Alex Chan1c0cb662017-01-30 07:13:30 +00002522 interact_in_memory(client, server)
2523 assert None is server.get_peer_cert_chain()
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002524
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002525 def test_get_session_unconnected(self):
2526 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002527 `Connection.get_session` returns `None` when used with an object
2528 which has not been connected.
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002529 """
2530 ctx = Context(TLSv1_METHOD)
2531 server = Connection(ctx, None)
2532 session = server.get_session()
Alex Chan1c0cb662017-01-30 07:13:30 +00002533 assert None is session
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002534
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002535 def test_server_get_session(self):
2536 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002537 On the server side of a connection, `Connection.get_session` returns a
2538 `Session` instance representing the SSL session for that connection.
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002539 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002540 server, client = loopback()
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002541 session = server.get_session()
Alex Chan1c0cb662017-01-30 07:13:30 +00002542 assert isinstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002543
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002544 def test_client_get_session(self):
2545 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002546 On the client side of a connection, `Connection.get_session`
2547 returns a `Session` instance representing the SSL session for
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002548 that connection.
2549 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002550 server, client = loopback()
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002551 session = client.get_session()
Alex Chan1c0cb662017-01-30 07:13:30 +00002552 assert isinstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002553
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002554 def test_set_session_wrong_args(self):
2555 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002556 `Connection.set_session` raises `TypeError` if called with an object
2557 that is not an instance of `Session`.
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002558 """
2559 ctx = Context(TLSv1_METHOD)
2560 connection = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002561 with pytest.raises(TypeError):
2562 connection.set_session(123)
2563 with pytest.raises(TypeError):
2564 connection.set_session("hello")
2565 with pytest.raises(TypeError):
2566 connection.set_session(object())
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002567
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002568 def test_client_set_session(self):
2569 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002570 `Connection.set_session`, when used prior to a connection being
2571 established, accepts a `Session` instance and causes an attempt to
2572 re-use the session it represents when the SSL handshake is performed.
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002573 """
2574 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2575 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
Paul Kehrer7d5a3bf2019-01-21 12:24:02 -06002576 ctx = Context(TLSv1_2_METHOD)
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002577 ctx.use_privatekey(key)
2578 ctx.use_certificate(cert)
2579 ctx.set_session_id("unity-test")
2580
2581 def makeServer(socket):
2582 server = Connection(ctx, socket)
2583 server.set_accept_state()
2584 return server
2585
Alex Chan1c0cb662017-01-30 07:13:30 +00002586 originalServer, originalClient = loopback(
2587 server_factory=makeServer)
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002588 originalSession = originalClient.get_session()
2589
2590 def makeClient(socket):
Alex Chan1c0cb662017-01-30 07:13:30 +00002591 client = loopback_client_factory(socket)
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002592 client.set_session(originalSession)
2593 return client
Alex Chan1c0cb662017-01-30 07:13:30 +00002594 resumedServer, resumedClient = loopback(
2595 server_factory=makeServer,
2596 client_factory=makeClient)
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002597
2598 # This is a proxy: in general, we have no access to any unique
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002599 # identifier for the session (new enough versions of OpenSSL expose
2600 # a hash which could be usable, but "new enough" is very, very new).
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002601 # Instead, exploit the fact that the master key is re-used if the
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002602 # session is re-used. As long as the master key for the two
2603 # connections is the same, the session was re-used!
Alex Chan1c0cb662017-01-30 07:13:30 +00002604 assert originalServer.master_key() == resumedServer.master_key()
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002605
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002606 def test_set_session_wrong_method(self):
2607 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002608 If `Connection.set_session` is passed a `Session` instance associated
2609 with a context using a different SSL method than the `Connection`
2610 is using, a `OpenSSL.SSL.Error` is raised.
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002611 """
Alex Gaynor5af32d02016-09-24 01:52:21 -04002612 # Make this work on both OpenSSL 1.0.0, which doesn't support TLSv1.2
2613 # and also on OpenSSL 1.1.0 which doesn't support SSLv3. (SSL_ST_INIT
2614 # is a way to check for 1.1.0)
Alex Gaynoraa32e712017-06-29 20:56:12 -07002615 if SSL_ST_INIT is None:
2616 v1 = TLSv1_2_METHOD
2617 v2 = TLSv1_METHOD
2618 elif hasattr(_lib, "SSLv3_method"):
Alex Gaynor5af32d02016-09-24 01:52:21 -04002619 v1 = TLSv1_METHOD
2620 v2 = SSLv3_METHOD
2621 else:
Alex Gaynoraa32e712017-06-29 20:56:12 -07002622 pytest.skip("Test requires either OpenSSL 1.1.0 or SSLv3")
Alex Gaynor5af32d02016-09-24 01:52:21 -04002623
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002624 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2625 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
Alex Gaynor5af32d02016-09-24 01:52:21 -04002626 ctx = Context(v1)
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002627 ctx.use_privatekey(key)
2628 ctx.use_certificate(cert)
2629 ctx.set_session_id("unity-test")
2630
2631 def makeServer(socket):
2632 server = Connection(ctx, socket)
2633 server.set_accept_state()
2634 return server
2635
Alex Gaynor5af32d02016-09-24 01:52:21 -04002636 def makeOriginalClient(socket):
2637 client = Connection(Context(v1), socket)
2638 client.set_connect_state()
2639 return client
2640
Alex Chan1c0cb662017-01-30 07:13:30 +00002641 originalServer, originalClient = loopback(
2642 server_factory=makeServer, client_factory=makeOriginalClient)
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002643 originalSession = originalClient.get_session()
2644
2645 def makeClient(socket):
2646 # Intentionally use a different, incompatible method here.
Alex Gaynor5af32d02016-09-24 01:52:21 -04002647 client = Connection(Context(v2), socket)
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002648 client.set_connect_state()
2649 client.set_session(originalSession)
2650 return client
2651
Alex Chan1c0cb662017-01-30 07:13:30 +00002652 with pytest.raises(Error):
2653 loopback(client_factory=makeClient, server_factory=makeServer)
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002654
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002655 def test_wantWriteError(self):
2656 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002657 `Connection` methods which generate output raise
2658 `OpenSSL.SSL.WantWriteError` if writing to the connection's BIO
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002659 fail indicating a should-write state.
2660 """
2661 client_socket, server_socket = socket_pair()
2662 # Fill up the client's send buffer so Connection won't be able to write
Jean-Paul Calderonebbff8b92014-03-22 14:20:30 -04002663 # anything. Only write a single byte at a time so we can be sure we
2664 # completely fill the buffer. Even though the socket API is allowed to
2665 # signal a short write via its return value it seems this doesn't
2666 # always happen on all platforms (FreeBSD and OS X particular) for the
2667 # very last bit of available buffer space.
2668 msg = b"x"
caternb2777a42018-08-09 15:38:13 -04002669 for i in range(1024 * 1024 * 64):
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002670 try:
2671 client_socket.send(msg)
2672 except error as e:
2673 if e.errno == EWOULDBLOCK:
2674 break
2675 raise
2676 else:
Alex Chan1c0cb662017-01-30 07:13:30 +00002677 pytest.fail(
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002678 "Failed to fill socket buffer, cannot test BIO want write")
2679
2680 ctx = Context(TLSv1_METHOD)
2681 conn = Connection(ctx, client_socket)
2682 # Client's speak first, so make it an SSL client
2683 conn.set_connect_state()
Alex Chan1c0cb662017-01-30 07:13:30 +00002684 with pytest.raises(WantWriteError):
2685 conn.do_handshake()
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002686
2687 # XXX want_read
2688
Fedor Brunner416f4a12014-03-28 13:18:38 +01002689 def test_get_finished_before_connect(self):
Fedor Brunner5747b932014-03-05 14:22:34 +01002690 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002691 `Connection.get_finished` returns `None` before TLS handshake
2692 is completed.
Fedor Brunner5747b932014-03-05 14:22:34 +01002693 """
Fedor Brunner5747b932014-03-05 14:22:34 +01002694 ctx = Context(TLSv1_METHOD)
2695 connection = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002696 assert connection.get_finished() is None
Fedor Brunner416f4a12014-03-28 13:18:38 +01002697
2698 def test_get_peer_finished_before_connect(self):
2699 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002700 `Connection.get_peer_finished` returns `None` before TLS handshake
2701 is completed.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002702 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002703 ctx = Context(TLSv1_METHOD)
2704 connection = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002705 assert connection.get_peer_finished() is None
Fedor Brunner5747b932014-03-05 14:22:34 +01002706
Fedor Brunner416f4a12014-03-28 13:18:38 +01002707 def test_get_finished(self):
2708 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002709 `Connection.get_finished` method returns the TLS Finished message send
2710 from client, or server. Finished messages are send during
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002711 TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002712 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002713 server, client = loopback()
Fedor Brunner416f4a12014-03-28 13:18:38 +01002714
Alex Chan1c0cb662017-01-30 07:13:30 +00002715 assert server.get_finished() is not None
2716 assert len(server.get_finished()) > 0
Fedor Brunner416f4a12014-03-28 13:18:38 +01002717
2718 def test_get_peer_finished(self):
2719 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002720 `Connection.get_peer_finished` method returns the TLS Finished
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002721 message received from client, or server. Finished messages are send
2722 during TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002723 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002724 server, client = loopback()
Fedor Brunner416f4a12014-03-28 13:18:38 +01002725
Alex Chan1c0cb662017-01-30 07:13:30 +00002726 assert server.get_peer_finished() is not None
2727 assert len(server.get_peer_finished()) > 0
Fedor Brunner5747b932014-03-05 14:22:34 +01002728
Fedor Brunner416f4a12014-03-28 13:18:38 +01002729 def test_tls_finished_message_symmetry(self):
2730 """
Hynek Schlawackdddd1112015-09-05 21:12:30 +02002731 The TLS Finished message send by server must be the TLS Finished
2732 message received by client.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002733
Hynek Schlawackdddd1112015-09-05 21:12:30 +02002734 The TLS Finished message send by client must be the TLS Finished
2735 message received by server.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002736 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002737 server, client = loopback()
Fedor Brunner416f4a12014-03-28 13:18:38 +01002738
Alex Chan1c0cb662017-01-30 07:13:30 +00002739 assert server.get_finished() == client.get_peer_finished()
2740 assert client.get_finished() == server.get_peer_finished()
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002741
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002742 def test_get_cipher_name_before_connect(self):
2743 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002744 `Connection.get_cipher_name` returns `None` if no connection
2745 has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002746 """
2747 ctx = Context(TLSv1_METHOD)
2748 conn = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002749 assert conn.get_cipher_name() is None
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002750
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002751 def test_get_cipher_name(self):
2752 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002753 `Connection.get_cipher_name` returns a `unicode` string giving the
2754 name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002755 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002756 server, client = loopback()
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002757 server_cipher_name, client_cipher_name = \
2758 server.get_cipher_name(), client.get_cipher_name()
2759
Alex Chan1c0cb662017-01-30 07:13:30 +00002760 assert isinstance(server_cipher_name, text_type)
2761 assert isinstance(client_cipher_name, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002762
Alex Chan1c0cb662017-01-30 07:13:30 +00002763 assert server_cipher_name == client_cipher_name
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002764
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002765 def test_get_cipher_version_before_connect(self):
2766 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002767 `Connection.get_cipher_version` returns `None` if no connection
2768 has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002769 """
2770 ctx = Context(TLSv1_METHOD)
2771 conn = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002772 assert conn.get_cipher_version() is None
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002773
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002774 def test_get_cipher_version(self):
2775 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002776 `Connection.get_cipher_version` returns a `unicode` string giving
2777 the protocol name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002778 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002779 server, client = loopback()
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002780 server_cipher_version, client_cipher_version = \
2781 server.get_cipher_version(), client.get_cipher_version()
2782
Alex Chan1c0cb662017-01-30 07:13:30 +00002783 assert isinstance(server_cipher_version, text_type)
2784 assert isinstance(client_cipher_version, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002785
Alex Chan1c0cb662017-01-30 07:13:30 +00002786 assert server_cipher_version == client_cipher_version
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002787
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002788 def test_get_cipher_bits_before_connect(self):
2789 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002790 `Connection.get_cipher_bits` returns `None` if no connection has
2791 been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002792 """
2793 ctx = Context(TLSv1_METHOD)
2794 conn = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002795 assert conn.get_cipher_bits() is None
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002796
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002797 def test_get_cipher_bits(self):
2798 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002799 `Connection.get_cipher_bits` returns the number of secret bits
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002800 of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002801 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002802 server, client = loopback()
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002803 server_cipher_bits, client_cipher_bits = \
2804 server.get_cipher_bits(), client.get_cipher_bits()
2805
Alex Chan1c0cb662017-01-30 07:13:30 +00002806 assert isinstance(server_cipher_bits, int)
2807 assert isinstance(client_cipher_bits, int)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002808
Alex Chan1c0cb662017-01-30 07:13:30 +00002809 assert server_cipher_bits == client_cipher_bits
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002810
Jim Shaverabff1882015-05-27 09:15:55 -04002811 def test_get_protocol_version_name(self):
2812 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002813 `Connection.get_protocol_version_name()` returns a string giving the
2814 protocol version of the current connection.
Jim Shaverabff1882015-05-27 09:15:55 -04002815 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002816 server, client = loopback()
Jim Shaverabff1882015-05-27 09:15:55 -04002817 client_protocol_version_name = client.get_protocol_version_name()
2818 server_protocol_version_name = server.get_protocol_version_name()
2819
Alex Chan1c0cb662017-01-30 07:13:30 +00002820 assert isinstance(server_protocol_version_name, text_type)
2821 assert isinstance(client_protocol_version_name, text_type)
Jim Shaverabff1882015-05-27 09:15:55 -04002822
Alex Chan1c0cb662017-01-30 07:13:30 +00002823 assert server_protocol_version_name == client_protocol_version_name
Jim Shaverabff1882015-05-27 09:15:55 -04002824
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002825 def test_get_protocol_version(self):
2826 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002827 `Connection.get_protocol_version()` returns an integer
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002828 giving the protocol version of the current connection.
2829 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002830 server, client = loopback()
Jim Shaver85a4dff2015-04-27 17:42:46 -04002831 client_protocol_version = client.get_protocol_version()
2832 server_protocol_version = server.get_protocol_version()
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002833
Alex Chan1c0cb662017-01-30 07:13:30 +00002834 assert isinstance(server_protocol_version, int)
2835 assert isinstance(client_protocol_version, int)
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002836
Alex Chan1c0cb662017-01-30 07:13:30 +00002837 assert server_protocol_version == client_protocol_version
2838
2839 def test_wantReadError(self):
2840 """
2841 `Connection.bio_read` raises `OpenSSL.SSL.WantReadError` if there are
2842 no bytes available to be read from the BIO.
2843 """
2844 ctx = Context(TLSv1_METHOD)
2845 conn = Connection(ctx, None)
2846 with pytest.raises(WantReadError):
2847 conn.bio_read(1024)
2848
Alex Chanfb078d82017-04-20 11:16:15 +01002849 @pytest.mark.parametrize('bufsize', [1.0, None, object(), 'bufsize'])
2850 def test_bio_read_wrong_args(self, bufsize):
2851 """
2852 `Connection.bio_read` raises `TypeError` if passed a non-integer
2853 argument.
2854 """
2855 ctx = Context(TLSv1_METHOD)
2856 conn = Connection(ctx, None)
2857 with pytest.raises(TypeError):
2858 conn.bio_read(bufsize)
2859
Alex Chan1c0cb662017-01-30 07:13:30 +00002860 def test_buffer_size(self):
2861 """
2862 `Connection.bio_read` accepts an integer giving the maximum number
2863 of bytes to read and return.
2864 """
2865 ctx = Context(TLSv1_METHOD)
2866 conn = Connection(ctx, None)
2867 conn.set_connect_state()
2868 try:
2869 conn.do_handshake()
2870 except WantReadError:
2871 pass
2872 data = conn.bio_read(2)
2873 assert 2 == len(data)
2874
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002875
Alex Chanb7480992017-01-30 14:04:47 +00002876class TestConnectionGetCipherList(object):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002877 """
Alex Chanb7480992017-01-30 14:04:47 +00002878 Tests for `Connection.get_cipher_list`.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002879 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002880 def test_result(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002881 """
Alex Chanb7480992017-01-30 14:04:47 +00002882 `Connection.get_cipher_list` returns a list of `bytes` giving the
2883 names of the ciphers which might be used.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002884 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002885 connection = Connection(Context(TLSv1_METHOD), None)
2886 ciphers = connection.get_cipher_list()
Alex Chanb7480992017-01-30 14:04:47 +00002887 assert isinstance(ciphers, list)
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002888 for cipher in ciphers:
Alex Chanb7480992017-01-30 14:04:47 +00002889 assert isinstance(cipher, str)
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002890
2891
Maximilian Hils868dc3c2017-02-10 14:56:55 +01002892class VeryLarge(bytes):
2893 """
2894 Mock object so that we don't have to allocate 2**31 bytes
2895 """
2896 def __len__(self):
2897 return 2**31
2898
2899
Alex Chanb7480992017-01-30 14:04:47 +00002900class TestConnectionSend(object):
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002901 """
Alex Chanb7480992017-01-30 14:04:47 +00002902 Tests for `Connection.send`.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002903 """
2904 def test_wrong_args(self):
2905 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002906 When called with arguments other than string argument for its first
Alex Chanb7480992017-01-30 14:04:47 +00002907 parameter, `Connection.send` raises `TypeError`.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002908 """
2909 connection = Connection(Context(TLSv1_METHOD), None)
Alex Chanb7480992017-01-30 14:04:47 +00002910 with pytest.raises(TypeError):
2911 connection.send(object())
Daniel Holth079c9632019-11-17 22:45:52 -05002912 with pytest.raises(TypeError):
2913 connection.send([1, 2, 3])
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002914
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002915 def test_short_bytes(self):
2916 """
Alex Chanb7480992017-01-30 14:04:47 +00002917 When passed a short byte string, `Connection.send` transmits all of it
2918 and returns the number of bytes sent.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002919 """
Alex Chanb7480992017-01-30 14:04:47 +00002920 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002921 count = server.send(b'xy')
Alex Chanb7480992017-01-30 14:04:47 +00002922 assert count == 2
2923 assert client.recv(2) == b'xy'
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002924
Abraham Martinef063482015-03-25 14:06:24 +00002925 def test_text(self):
2926 """
Alex Chanb7480992017-01-30 14:04:47 +00002927 When passed a text, `Connection.send` transmits all of it and
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002928 returns the number of bytes sent. It also raises a DeprecationWarning.
Abraham Martinef063482015-03-25 14:06:24 +00002929 """
Alex Chanb7480992017-01-30 14:04:47 +00002930 server, client = loopback()
2931 with pytest.warns(DeprecationWarning) as w:
Abraham Martinef063482015-03-25 14:06:24 +00002932 simplefilter("always")
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002933 count = server.send(b"xy".decode("ascii"))
Alex Chanb7480992017-01-30 14:04:47 +00002934 assert (
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002935 "{0} for buf is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002936 WARNING_TYPE_EXPECTED
Alex Chanb7480992017-01-30 14:04:47 +00002937 ) == str(w[-1].message))
2938 assert count == 2
2939 assert client.recv(2) == b'xy'
Abraham Martinef063482015-03-25 14:06:24 +00002940
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002941 def test_short_memoryview(self):
2942 """
2943 When passed a memoryview onto a small number of bytes,
Alex Chanb7480992017-01-30 14:04:47 +00002944 `Connection.send` transmits all of them and returns the number
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002945 of bytes sent.
2946 """
Alex Chanb7480992017-01-30 14:04:47 +00002947 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002948 count = server.send(memoryview(b'xy'))
Alex Chanb7480992017-01-30 14:04:47 +00002949 assert count == 2
2950 assert client.recv(2) == b'xy'
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002951
Daniel Holth079c9632019-11-17 22:45:52 -05002952 def test_short_bytearray(self):
2953 """
2954 When passed a short bytearray, `Connection.send` transmits all of
2955 it and returns the number of bytes sent.
2956 """
2957 server, client = loopback()
2958 count = server.send(bytearray(b'xy'))
2959 assert count == 2
2960 assert client.recv(2) == b'xy'
2961
Hynek Schlawack8e94f1b2015-09-05 21:31:00 +02002962 @skip_if_py3
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002963 def test_short_buffer(self):
2964 """
2965 When passed a buffer containing a small number of bytes,
Alex Chanb7480992017-01-30 14:04:47 +00002966 `Connection.send` transmits all of them and returns the number
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002967 of bytes sent.
2968 """
Alex Chanb7480992017-01-30 14:04:47 +00002969 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002970 count = server.send(buffer(b'xy'))
Alex Chanb7480992017-01-30 14:04:47 +00002971 assert count == 2
2972 assert client.recv(2) == b'xy'
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02002973
Maximilian Hils868dc3c2017-02-10 14:56:55 +01002974 @pytest.mark.skipif(
2975 sys.maxsize < 2**31,
2976 reason="sys.maxsize < 2**31 - test requires 64 bit"
2977 )
2978 def test_buf_too_large(self):
2979 """
2980 When passed a buffer containing >= 2**31 bytes,
2981 `Connection.send` bails out as SSL_write only
2982 accepts an int for the buffer length.
2983 """
2984 connection = Connection(Context(TLSv1_METHOD), None)
2985 with pytest.raises(ValueError) as exc_info:
2986 connection.send(VeryLarge())
2987 exc_info.match(r"Cannot send more than .+ bytes at once")
2988
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05002989
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002990def _make_memoryview(size):
2991 """
2992 Create a new ``memoryview`` wrapped around a ``bytearray`` of the given
2993 size.
2994 """
2995 return memoryview(bytearray(size))
2996
2997
Alex Chanb7480992017-01-30 14:04:47 +00002998class TestConnectionRecvInto(object):
Cory Benfield62d10332014-06-15 10:03:41 +01002999 """
Alex Chanb7480992017-01-30 14:04:47 +00003000 Tests for `Connection.recv_into`.
Cory Benfield62d10332014-06-15 10:03:41 +01003001 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003002 def _no_length_test(self, factory):
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04003003 """
Alex Chanb7480992017-01-30 14:04:47 +00003004 Assert that when the given buffer is passed to `Connection.recv_into`,
3005 whatever bytes are available to be received that fit into that buffer
3006 are written into that buffer.
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04003007 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003008 output_buffer = factory(5)
3009
Alex Chanb7480992017-01-30 14:04:47 +00003010 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04003011 server.send(b'xy')
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04003012
Alex Chanb7480992017-01-30 14:04:47 +00003013 assert client.recv_into(output_buffer) == 2
3014 assert output_buffer == bytearray(b'xy\x00\x00\x00')
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04003015
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04003016 def test_bytearray_no_length(self):
Cory Benfield62d10332014-06-15 10:03:41 +01003017 """
Alex Chanb7480992017-01-30 14:04:47 +00003018 `Connection.recv_into` can be passed a `bytearray` instance and data
3019 in the receive buffer is written to it.
Cory Benfield62d10332014-06-15 10:03:41 +01003020 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003021 self._no_length_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01003022
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003023 def _respects_length_test(self, factory):
Cory Benfield62d10332014-06-15 10:03:41 +01003024 """
Alex Chanb7480992017-01-30 14:04:47 +00003025 Assert that when the given buffer is passed to `Connection.recv_into`
3026 along with a value for `nbytes` that is less than the size of that
3027 buffer, only `nbytes` bytes are written into the buffer.
Cory Benfield62d10332014-06-15 10:03:41 +01003028 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003029 output_buffer = factory(10)
3030
Alex Chanb7480992017-01-30 14:04:47 +00003031 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04003032 server.send(b'abcdefghij')
Cory Benfield62d10332014-06-15 10:03:41 +01003033
Alex Chanb7480992017-01-30 14:04:47 +00003034 assert client.recv_into(output_buffer, 5) == 5
3035 assert output_buffer == bytearray(b'abcde\x00\x00\x00\x00\x00')
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04003036
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04003037 def test_bytearray_respects_length(self):
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04003038 """
Alex Chanb7480992017-01-30 14:04:47 +00003039 When called with a `bytearray` instance, `Connection.recv_into`
3040 respects the `nbytes` parameter and doesn't copy in more than that
3041 number of bytes.
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04003042 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003043 self._respects_length_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01003044
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003045 def _doesnt_overfill_test(self, factory):
Cory Benfield62d10332014-06-15 10:03:41 +01003046 """
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04003047 Assert that if there are more bytes available to be read from the
3048 receive buffer than would fit into the buffer passed to
Alex Chanb7480992017-01-30 14:04:47 +00003049 `Connection.recv_into`, only as many as fit are written into it.
Cory Benfield62d10332014-06-15 10:03:41 +01003050 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003051 output_buffer = factory(5)
3052
Alex Chanb7480992017-01-30 14:04:47 +00003053 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04003054 server.send(b'abcdefghij')
Cory Benfield62d10332014-06-15 10:03:41 +01003055
Alex Chanb7480992017-01-30 14:04:47 +00003056 assert client.recv_into(output_buffer) == 5
3057 assert output_buffer == bytearray(b'abcde')
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04003058 rest = client.recv(5)
Alex Chanb7480992017-01-30 14:04:47 +00003059 assert b'fghij' == rest
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04003060
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04003061 def test_bytearray_doesnt_overfill(self):
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04003062 """
Alex Chanb7480992017-01-30 14:04:47 +00003063 When called with a `bytearray` instance, `Connection.recv_into`
3064 respects the size of the array and doesn't write more bytes into it
3065 than will fit.
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04003066 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003067 self._doesnt_overfill_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01003068
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04003069 def test_bytearray_really_doesnt_overfill(self):
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003070 """
Alex Chanb7480992017-01-30 14:04:47 +00003071 When called with a `bytearray` instance and an `nbytes` value that is
3072 too large, `Connection.recv_into` respects the size of the array and
3073 not the `nbytes` value and doesn't write more bytes into the buffer
3074 than will fit.
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003075 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003076 self._doesnt_overfill_test(bytearray)
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003077
Maximilian Hils1d95dea2015-08-17 19:27:20 +02003078 def test_peek(self):
Alex Chanb7480992017-01-30 14:04:47 +00003079 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04003080 server.send(b'xy')
Maximilian Hils1d95dea2015-08-17 19:27:20 +02003081
3082 for _ in range(2):
3083 output_buffer = bytearray(5)
Alex Chanb7480992017-01-30 14:04:47 +00003084 assert client.recv_into(output_buffer, flags=MSG_PEEK) == 2
3085 assert output_buffer == bytearray(b'xy\x00\x00\x00')
Maximilian Hils1d95dea2015-08-17 19:27:20 +02003086
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003087 def test_memoryview_no_length(self):
3088 """
Alex Chanb7480992017-01-30 14:04:47 +00003089 `Connection.recv_into` can be passed a `memoryview` instance and data
3090 in the receive buffer is written to it.
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003091 """
3092 self._no_length_test(_make_memoryview)
Maximilian Hils1d95dea2015-08-17 19:27:20 +02003093
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003094 def test_memoryview_respects_length(self):
3095 """
Alex Chanb7480992017-01-30 14:04:47 +00003096 When called with a `memoryview` instance, `Connection.recv_into`
3097 respects the ``nbytes`` parameter and doesn't copy more than that
3098 number of bytes in.
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003099 """
3100 self._respects_length_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01003101
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003102 def test_memoryview_doesnt_overfill(self):
3103 """
Alex Chanb7480992017-01-30 14:04:47 +00003104 When called with a `memoryview` instance, `Connection.recv_into`
3105 respects the size of the array and doesn't write more bytes into it
3106 than will fit.
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003107 """
3108 self._doesnt_overfill_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01003109
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003110 def test_memoryview_really_doesnt_overfill(self):
3111 """
Alex Chanb7480992017-01-30 14:04:47 +00003112 When called with a `memoryview` instance and an `nbytes` value that is
3113 too large, `Connection.recv_into` respects the size of the array and
3114 not the `nbytes` value and doesn't write more bytes into the buffer
3115 than will fit.
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003116 """
3117 self._doesnt_overfill_test(_make_memoryview)
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003118
Cory Benfield62d10332014-06-15 10:03:41 +01003119
Alex Chanb7480992017-01-30 14:04:47 +00003120class TestConnectionSendall(object):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003121 """
Alex Chanb7480992017-01-30 14:04:47 +00003122 Tests for `Connection.sendall`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003123 """
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003124 def test_wrong_args(self):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003125 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003126 When called with arguments other than a string argument for its first
Alex Chanb7480992017-01-30 14:04:47 +00003127 parameter, `Connection.sendall` raises `TypeError`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003128 """
3129 connection = Connection(Context(TLSv1_METHOD), None)
Alex Chanb7480992017-01-30 14:04:47 +00003130 with pytest.raises(TypeError):
3131 connection.sendall(object())
Daniel Holth079c9632019-11-17 22:45:52 -05003132 with pytest.raises(TypeError):
3133 connection.sendall([1, 2, 3])
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003134
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003135 def test_short(self):
3136 """
Alex Chanb7480992017-01-30 14:04:47 +00003137 `Connection.sendall` transmits all of the bytes in the string
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003138 passed to it.
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003139 """
Alex Chanb7480992017-01-30 14:04:47 +00003140 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04003141 server.sendall(b'x')
Alex Chanb7480992017-01-30 14:04:47 +00003142 assert client.recv(1) == b'x'
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003143
Abraham Martinef063482015-03-25 14:06:24 +00003144 def test_text(self):
3145 """
Alex Chanb7480992017-01-30 14:04:47 +00003146 `Connection.sendall` transmits all the content in the string passed
3147 to it, raising a DeprecationWarning in case of this being a text.
Abraham Martinef063482015-03-25 14:06:24 +00003148 """
Alex Chanb7480992017-01-30 14:04:47 +00003149 server, client = loopback()
3150 with pytest.warns(DeprecationWarning) as w:
Abraham Martinef063482015-03-25 14:06:24 +00003151 simplefilter("always")
Jean-Paul Calderone8dc37a12015-03-29 08:16:52 -04003152 server.sendall(b"x".decode("ascii"))
Alex Chanb7480992017-01-30 14:04:47 +00003153 assert (
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04003154 "{0} for buf is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04003155 WARNING_TYPE_EXPECTED
Alex Chanb7480992017-01-30 14:04:47 +00003156 ) == str(w[-1].message))
3157 assert client.recv(1) == b"x"
Abraham Martinef063482015-03-25 14:06:24 +00003158
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003159 def test_short_memoryview(self):
3160 """
3161 When passed a memoryview onto a small number of bytes,
Alex Chanb7480992017-01-30 14:04:47 +00003162 `Connection.sendall` transmits all of them.
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003163 """
Alex Chanb7480992017-01-30 14:04:47 +00003164 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04003165 server.sendall(memoryview(b'x'))
Alex Chanb7480992017-01-30 14:04:47 +00003166 assert client.recv(1) == b'x'
Abraham Martinef063482015-03-25 14:06:24 +00003167
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003168 @skip_if_py3
3169 def test_short_buffers(self):
3170 """
3171 When passed a buffer containing a small number of bytes,
Alex Chanb7480992017-01-30 14:04:47 +00003172 `Connection.sendall` transmits all of them.
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003173 """
Alex Chanb7480992017-01-30 14:04:47 +00003174 server, client = loopback()
Daniel Holth079c9632019-11-17 22:45:52 -05003175 count = server.sendall(buffer(b'xy'))
3176 assert count == 2
3177 assert client.recv(2) == b'xy'
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02003178
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003179 def test_long(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003180 """
Alex Chanb7480992017-01-30 14:04:47 +00003181 `Connection.sendall` transmits all the bytes in the string passed to it
3182 even if this requires multiple calls of an underlying write function.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003183 """
Alex Chanb7480992017-01-30 14:04:47 +00003184 server, client = loopback()
Jean-Paul Calderone6241c702010-09-16 19:59:24 -04003185 # Should be enough, underlying SSL_write should only do 16k at a time.
Hynek Schlawack35618382015-09-05 21:54:25 +02003186 # On Windows, after 32k of bytes the write will block (forever
3187 # - because no one is yet reading).
Alex Gaynore7f51982016-09-11 11:48:14 -04003188 message = b'x' * (1024 * 32 - 1) + b'y'
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003189 server.sendall(message)
3190 accum = []
3191 received = 0
3192 while received < len(message):
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04003193 data = client.recv(1024)
3194 accum.append(data)
3195 received += len(data)
Alex Chanb7480992017-01-30 14:04:47 +00003196 assert message == b''.join(accum)
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003197
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003198 def test_closed(self):
3199 """
Alex Chanb7480992017-01-30 14:04:47 +00003200 If the underlying socket is closed, `Connection.sendall` propagates the
3201 write error from the low level write call.
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003202 """
Alex Chanb7480992017-01-30 14:04:47 +00003203 server, client = loopback()
Jean-Paul Calderone05d43e82010-09-24 18:01:36 -04003204 server.sock_shutdown(2)
Alex Chanb7480992017-01-30 14:04:47 +00003205 with pytest.raises(SysCallError) as err:
3206 server.sendall(b"hello, world")
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +02003207 if platform == "win32":
Alex Chanb7480992017-01-30 14:04:47 +00003208 assert err.value.args[0] == ESHUTDOWN
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +02003209 else:
Alex Chanb7480992017-01-30 14:04:47 +00003210 assert err.value.args[0] == EPIPE
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003211
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003212
Alex Chanb7480992017-01-30 14:04:47 +00003213class TestConnectionRenegotiate(object):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003214 """
3215 Tests for SSL renegotiation APIs.
3216 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003217 def test_total_renegotiations(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003218 """
Alex Chanb7480992017-01-30 14:04:47 +00003219 `Connection.total_renegotiations` returns `0` before any renegotiations
3220 have happened.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003221 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003222 connection = Connection(Context(TLSv1_METHOD), None)
Alex Chanb7480992017-01-30 14:04:47 +00003223 assert connection.total_renegotiations() == 0
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003224
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003225 def test_renegotiate(self):
3226 """
3227 Go through a complete renegotiation cycle.
3228 """
Paul Kehrer7d5a3bf2019-01-21 12:24:02 -06003229 server, client = loopback(
3230 lambda s: loopback_server_factory(s, TLSv1_2_METHOD),
3231 lambda s: loopback_client_factory(s, TLSv1_2_METHOD),
3232 )
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003233
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003234 server.send(b"hello world")
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003235
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003236 assert b"hello world" == client.recv(len(b"hello world"))
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003237
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003238 assert 0 == server.total_renegotiations()
3239 assert False is server.renegotiate_pending()
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003240
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003241 assert True is server.renegotiate()
3242
3243 assert True is server.renegotiate_pending()
3244
3245 server.setblocking(False)
3246 client.setblocking(False)
3247
3248 client.do_handshake()
3249 server.do_handshake()
3250
3251 assert 1 == server.total_renegotiations()
3252 while False is server.renegotiate_pending():
3253 pass
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003254
3255
Alex Chanb7480992017-01-30 14:04:47 +00003256class TestError(object):
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003257 """
Alex Chanb7480992017-01-30 14:04:47 +00003258 Unit tests for `OpenSSL.SSL.Error`.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003259 """
3260 def test_type(self):
3261 """
Alex Chanb7480992017-01-30 14:04:47 +00003262 `Error` is an exception type.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003263 """
Alex Chanb7480992017-01-30 14:04:47 +00003264 assert issubclass(Error, Exception)
3265 assert Error.__name__ == 'Error'
Rick Deane15b1472009-07-09 15:53:42 -05003266
3267
Alex Chanb7480992017-01-30 14:04:47 +00003268class TestConstants(object):
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003269 """
Alex Chanb7480992017-01-30 14:04:47 +00003270 Tests for the values of constants exposed in `OpenSSL.SSL`.
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003271
3272 These are values defined by OpenSSL intended only to be used as flags to
3273 OpenSSL APIs. The only assertions it seems can be made about them is
3274 their values.
3275 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003276 @pytest.mark.skipif(
3277 OP_NO_QUERY_MTU is None,
3278 reason="OP_NO_QUERY_MTU unavailable - OpenSSL version may be too old"
3279 )
3280 def test_op_no_query_mtu(self):
3281 """
Alex Chanb7480992017-01-30 14:04:47 +00003282 The value of `OpenSSL.SSL.OP_NO_QUERY_MTU` is 0x1000, the value
3283 of `SSL_OP_NO_QUERY_MTU` defined by `openssl/ssl.h`.
Hynek Schlawack35618382015-09-05 21:54:25 +02003284 """
Alex Chanb7480992017-01-30 14:04:47 +00003285 assert OP_NO_QUERY_MTU == 0x1000
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003286
Hynek Schlawack35618382015-09-05 21:54:25 +02003287 @pytest.mark.skipif(
3288 OP_COOKIE_EXCHANGE is None,
3289 reason="OP_COOKIE_EXCHANGE unavailable - "
3290 "OpenSSL version may be too old"
3291 )
3292 def test_op_cookie_exchange(self):
3293 """
Alex Chanb7480992017-01-30 14:04:47 +00003294 The value of `OpenSSL.SSL.OP_COOKIE_EXCHANGE` is 0x2000, the
3295 value of `SSL_OP_COOKIE_EXCHANGE` defined by `openssl/ssl.h`.
Hynek Schlawack35618382015-09-05 21:54:25 +02003296 """
Alex Chanb7480992017-01-30 14:04:47 +00003297 assert OP_COOKIE_EXCHANGE == 0x2000
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003298
Hynek Schlawack35618382015-09-05 21:54:25 +02003299 @pytest.mark.skipif(
3300 OP_NO_TICKET is None,
3301 reason="OP_NO_TICKET unavailable - OpenSSL version may be too old"
3302 )
3303 def test_op_no_ticket(self):
3304 """
Alex Chanb7480992017-01-30 14:04:47 +00003305 The value of `OpenSSL.SSL.OP_NO_TICKET` is 0x4000, the value of
3306 `SSL_OP_NO_TICKET` defined by `openssl/ssl.h`.
Hynek Schlawack35618382015-09-05 21:54:25 +02003307 """
Alex Chanb7480992017-01-30 14:04:47 +00003308 assert OP_NO_TICKET == 0x4000
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003309
Hynek Schlawack35618382015-09-05 21:54:25 +02003310 @pytest.mark.skipif(
3311 OP_NO_COMPRESSION is None,
3312 reason="OP_NO_COMPRESSION unavailable - OpenSSL version may be too old"
3313 )
3314 def test_op_no_compression(self):
3315 """
Alex Chanb7480992017-01-30 14:04:47 +00003316 The value of `OpenSSL.SSL.OP_NO_COMPRESSION` is 0x20000, the
3317 value of `SSL_OP_NO_COMPRESSION` defined by `openssl/ssl.h`.
Hynek Schlawack35618382015-09-05 21:54:25 +02003318 """
Alex Chanb7480992017-01-30 14:04:47 +00003319 assert OP_NO_COMPRESSION == 0x20000
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04003320
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003321 def test_sess_cache_off(self):
3322 """
Alex Chanb7480992017-01-30 14:04:47 +00003323 The value of `OpenSSL.SSL.SESS_CACHE_OFF` 0x0, the value of
3324 `SSL_SESS_CACHE_OFF` defined by `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003325 """
Alex Chanb7480992017-01-30 14:04:47 +00003326 assert 0x0 == SESS_CACHE_OFF
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003327
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003328 def test_sess_cache_client(self):
3329 """
Alex Chanb7480992017-01-30 14:04:47 +00003330 The value of `OpenSSL.SSL.SESS_CACHE_CLIENT` 0x1, the value of
3331 `SSL_SESS_CACHE_CLIENT` defined by `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003332 """
Alex Chanb7480992017-01-30 14:04:47 +00003333 assert 0x1 == SESS_CACHE_CLIENT
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003334
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003335 def test_sess_cache_server(self):
3336 """
Alex Chanb7480992017-01-30 14:04:47 +00003337 The value of `OpenSSL.SSL.SESS_CACHE_SERVER` 0x2, the value of
3338 `SSL_SESS_CACHE_SERVER` defined by `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003339 """
Alex Chanb7480992017-01-30 14:04:47 +00003340 assert 0x2 == SESS_CACHE_SERVER
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003341
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003342 def test_sess_cache_both(self):
3343 """
Alex Chanb7480992017-01-30 14:04:47 +00003344 The value of `OpenSSL.SSL.SESS_CACHE_BOTH` 0x3, the value of
3345 `SSL_SESS_CACHE_BOTH` defined by `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003346 """
Alex Chanb7480992017-01-30 14:04:47 +00003347 assert 0x3 == SESS_CACHE_BOTH
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003348
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003349 def test_sess_cache_no_auto_clear(self):
3350 """
Alex Chanb7480992017-01-30 14:04:47 +00003351 The value of `OpenSSL.SSL.SESS_CACHE_NO_AUTO_CLEAR` 0x80, the
3352 value of `SSL_SESS_CACHE_NO_AUTO_CLEAR` defined by
3353 `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003354 """
Alex Chanb7480992017-01-30 14:04:47 +00003355 assert 0x80 == SESS_CACHE_NO_AUTO_CLEAR
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003356
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003357 def test_sess_cache_no_internal_lookup(self):
3358 """
Alex Chanb7480992017-01-30 14:04:47 +00003359 The value of `OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_LOOKUP` 0x100,
3360 the value of `SSL_SESS_CACHE_NO_INTERNAL_LOOKUP` defined by
3361 `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003362 """
Alex Chanb7480992017-01-30 14:04:47 +00003363 assert 0x100 == SESS_CACHE_NO_INTERNAL_LOOKUP
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003364
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003365 def test_sess_cache_no_internal_store(self):
3366 """
Alex Chanb7480992017-01-30 14:04:47 +00003367 The value of `OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_STORE` 0x200,
3368 the value of `SSL_SESS_CACHE_NO_INTERNAL_STORE` defined by
3369 `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003370 """
Alex Chanb7480992017-01-30 14:04:47 +00003371 assert 0x200 == SESS_CACHE_NO_INTERNAL_STORE
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003372
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003373 def test_sess_cache_no_internal(self):
3374 """
Alex Chanb7480992017-01-30 14:04:47 +00003375 The value of `OpenSSL.SSL.SESS_CACHE_NO_INTERNAL` 0x300, the
3376 value of `SSL_SESS_CACHE_NO_INTERNAL` defined by
3377 `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003378 """
Alex Chanb7480992017-01-30 14:04:47 +00003379 assert 0x300 == SESS_CACHE_NO_INTERNAL
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003380
3381
Alex Chanb7480992017-01-30 14:04:47 +00003382class TestMemoryBIO(object):
Rick Deanb71c0d22009-04-01 14:09:23 -05003383 """
Alex Chanb7480992017-01-30 14:04:47 +00003384 Tests for `OpenSSL.SSL.Connection` using a memory BIO.
Rick Deanb71c0d22009-04-01 14:09:23 -05003385 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003386 def _server(self, sock):
3387 """
Alex Chanb7480992017-01-30 14:04:47 +00003388 Create a new server-side SSL `Connection` object wrapped around `sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003389 """
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003390 # Create the server side Connection. This is mostly setup boilerplate
3391 # - use TLSv1, use a particular certificate, etc.
3392 server_ctx = Context(TLSv1_METHOD)
Alex Gaynor43307782015-09-04 09:05:45 -04003393 server_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE)
Hynek Schlawack35618382015-09-05 21:54:25 +02003394 server_ctx.set_verify(
3395 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT | VERIFY_CLIENT_ONCE,
3396 verify_cb
3397 )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003398 server_store = server_ctx.get_cert_store()
Hynek Schlawack35618382015-09-05 21:54:25 +02003399 server_ctx.use_privatekey(
3400 load_privatekey(FILETYPE_PEM, server_key_pem))
3401 server_ctx.use_certificate(
3402 load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003403 server_ctx.check_privatekey()
3404 server_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Hynek Schlawack35618382015-09-05 21:54:25 +02003405 # Here the Connection is actually created. If None is passed as the
3406 # 2nd parameter, it indicates a memory BIO should be created.
Rick Deanb1ccd562009-07-09 23:52:39 -05003407 server_conn = Connection(server_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003408 server_conn.set_accept_state()
3409 return server_conn
3410
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003411 def _client(self, sock):
3412 """
Alex Chanb7480992017-01-30 14:04:47 +00003413 Create a new client-side SSL `Connection` object wrapped around `sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003414 """
3415 # Now create the client side Connection. Similar boilerplate to the
3416 # above.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003417 client_ctx = Context(TLSv1_METHOD)
Alex Gaynor43307782015-09-04 09:05:45 -04003418 client_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE)
Hynek Schlawack35618382015-09-05 21:54:25 +02003419 client_ctx.set_verify(
3420 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT | VERIFY_CLIENT_ONCE,
3421 verify_cb
3422 )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003423 client_store = client_ctx.get_cert_store()
Hynek Schlawack35618382015-09-05 21:54:25 +02003424 client_ctx.use_privatekey(
3425 load_privatekey(FILETYPE_PEM, client_key_pem))
3426 client_ctx.use_certificate(
3427 load_certificate(FILETYPE_PEM, client_cert_pem))
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003428 client_ctx.check_privatekey()
3429 client_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05003430 client_conn = Connection(client_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003431 client_conn.set_connect_state()
3432 return client_conn
3433
Alex Chanb7480992017-01-30 14:04:47 +00003434 def test_memory_connect(self):
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003435 """
Alex Chanb7480992017-01-30 14:04:47 +00003436 Two `Connection`s which use memory BIOs can be manually connected by
3437 reading from the output of each and writing those bytes to the input of
3438 the other and in this way establish a connection and exchange
3439 application-level bytes with each other.
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003440 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003441 server_conn = self._server(None)
3442 client_conn = self._client(None)
Rick Deanb71c0d22009-04-01 14:09:23 -05003443
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003444 # There should be no key or nonces yet.
Alex Chanb7480992017-01-30 14:04:47 +00003445 assert server_conn.master_key() is None
3446 assert server_conn.client_random() is None
3447 assert server_conn.server_random() is None
Rick Deanb71c0d22009-04-01 14:09:23 -05003448
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003449 # First, the handshake needs to happen. We'll deliver bytes back and
3450 # forth between the client and server until neither of them feels like
3451 # speaking any more.
Alex Chanb7480992017-01-30 14:04:47 +00003452 assert interact_in_memory(client_conn, server_conn) is None
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003453
3454 # Now that the handshake is done, there should be a key and nonces.
Alex Chanb7480992017-01-30 14:04:47 +00003455 assert server_conn.master_key() is not None
3456 assert server_conn.client_random() is not None
3457 assert server_conn.server_random() is not None
3458 assert server_conn.client_random() == client_conn.client_random()
3459 assert server_conn.server_random() == client_conn.server_random()
3460 assert server_conn.client_random() != server_conn.server_random()
3461 assert client_conn.client_random() != client_conn.server_random()
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003462
Paul Kehrerbdb76392017-12-01 04:54:32 +08003463 # Export key material for other uses.
3464 cekm = client_conn.export_keying_material(b'LABEL', 32)
3465 sekm = server_conn.export_keying_material(b'LABEL', 32)
3466 assert cekm is not None
3467 assert sekm is not None
3468 assert cekm == sekm
3469 assert len(sekm) == 32
3470
3471 # Export key material for other uses with additional context.
3472 cekmc = client_conn.export_keying_material(b'LABEL', 32, b'CONTEXT')
3473 sekmc = server_conn.export_keying_material(b'LABEL', 32, b'CONTEXT')
3474 assert cekmc is not None
3475 assert sekmc is not None
3476 assert cekmc == sekmc
3477 assert cekmc != cekm
3478 assert sekmc != sekm
3479 # Export with alternate label
3480 cekmt = client_conn.export_keying_material(b'test', 32, b'CONTEXT')
3481 sekmt = server_conn.export_keying_material(b'test', 32, b'CONTEXT')
3482 assert cekmc != cekmt
3483 assert sekmc != sekmt
3484
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003485 # Here are the bytes we'll try to send.
Alex Gaynore7f51982016-09-11 11:48:14 -04003486 important_message = b'One if by land, two if by sea.'
Rick Deanb71c0d22009-04-01 14:09:23 -05003487
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003488 server_conn.write(important_message)
Alex Chanb7480992017-01-30 14:04:47 +00003489 assert (
3490 interact_in_memory(client_conn, server_conn) ==
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003491 (client_conn, important_message))
3492
3493 client_conn.write(important_message[::-1])
Alex Chanb7480992017-01-30 14:04:47 +00003494 assert (
3495 interact_in_memory(client_conn, server_conn) ==
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003496 (server_conn, important_message[::-1]))
Rick Deanb71c0d22009-04-01 14:09:23 -05003497
Alex Chanb7480992017-01-30 14:04:47 +00003498 def test_socket_connect(self):
Rick Deanb1ccd562009-07-09 23:52:39 -05003499 """
Alex Chanb7480992017-01-30 14:04:47 +00003500 Just like `test_memory_connect` but with an actual socket.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003501
Hynek Schlawack35618382015-09-05 21:54:25 +02003502 This is primarily to rule out the memory BIO code as the source of any
Alex Chanb7480992017-01-30 14:04:47 +00003503 problems encountered while passing data over a `Connection` (if
Hynek Schlawack35618382015-09-05 21:54:25 +02003504 this test fails, there must be a problem outside the memory BIO code,
3505 as no memory BIO is involved here). Even though this isn't a memory
3506 BIO test, it's convenient to have it here.
Rick Deanb1ccd562009-07-09 23:52:39 -05003507 """
Alex Chanb7480992017-01-30 14:04:47 +00003508 server_conn, client_conn = loopback()
Rick Deanb1ccd562009-07-09 23:52:39 -05003509
Alex Gaynore7f51982016-09-11 11:48:14 -04003510 important_message = b"Help me Obi Wan Kenobi, you're my only hope."
Rick Deanb1ccd562009-07-09 23:52:39 -05003511 client_conn.send(important_message)
3512 msg = server_conn.recv(1024)
Alex Chanb7480992017-01-30 14:04:47 +00003513 assert msg == important_message
Rick Deanb1ccd562009-07-09 23:52:39 -05003514
3515 # Again in the other direction, just for fun.
3516 important_message = important_message[::-1]
3517 server_conn.send(important_message)
3518 msg = client_conn.recv(1024)
Alex Chanb7480992017-01-30 14:04:47 +00003519 assert msg == important_message
Rick Deanb1ccd562009-07-09 23:52:39 -05003520
Alex Chanb7480992017-01-30 14:04:47 +00003521 def test_socket_overrides_memory(self):
Rick Deanb71c0d22009-04-01 14:09:23 -05003522 """
Alex Chanb7480992017-01-30 14:04:47 +00003523 Test that `OpenSSL.SSL.bio_read` and `OpenSSL.SSL.bio_write` don't
3524 work on `OpenSSL.SSL.Connection`() that use sockets.
Rick Deanb71c0d22009-04-01 14:09:23 -05003525 """
Alex Gaynor51d424c2016-09-10 14:50:11 -04003526 context = Context(TLSv1_METHOD)
David Benjamin1fbe0642019-04-15 17:05:13 -05003527 client = socket_any_family()
Rick Deanb71c0d22009-04-01 14:09:23 -05003528 clientSSL = Connection(context, client)
Alex Chanb7480992017-01-30 14:04:47 +00003529 with pytest.raises(TypeError):
3530 clientSSL.bio_read(100)
3531 with pytest.raises(TypeError):
3532 clientSSL.bio_write("foo")
3533 with pytest.raises(TypeError):
3534 clientSSL.bio_shutdown()
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003535
Alex Chanb7480992017-01-30 14:04:47 +00003536 def test_outgoing_overflow(self):
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003537 """
3538 If more bytes than can be written to the memory BIO are passed to
Alex Chanb7480992017-01-30 14:04:47 +00003539 `Connection.send` at once, the number of bytes which were written is
3540 returned and that many bytes from the beginning of the input can be
3541 read from the other end of the connection.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003542 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003543 server = self._server(None)
3544 client = self._client(None)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003545
Alex Chanb7480992017-01-30 14:04:47 +00003546 interact_in_memory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003547
3548 size = 2 ** 15
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003549 sent = client.send(b"x" * size)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003550 # Sanity check. We're trying to test what happens when the entire
3551 # input can't be sent. If the entire input was sent, this test is
3552 # meaningless.
Alex Chanb7480992017-01-30 14:04:47 +00003553 assert sent < size
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003554
Alex Chanb7480992017-01-30 14:04:47 +00003555 receiver, received = interact_in_memory(client, server)
3556 assert receiver is server
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003557
3558 # We can rely on all of these bytes being received at once because
Alex Chanb7480992017-01-30 14:04:47 +00003559 # loopback passes 2 ** 16 to recv - more than 2 ** 15.
3560 assert len(received) == sent
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003561
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003562 def test_shutdown(self):
3563 """
Alex Chanb7480992017-01-30 14:04:47 +00003564 `Connection.bio_shutdown` signals the end of the data stream
3565 from which the `Connection` reads.
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003566 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003567 server = self._server(None)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003568 server.bio_shutdown()
Alex Chanb7480992017-01-30 14:04:47 +00003569 with pytest.raises(Error) as err:
3570 server.recv(1024)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003571 # We don't want WantReadError or ZeroReturnError or anything - it's a
3572 # handshake failure.
Alex Chanb7480992017-01-30 14:04:47 +00003573 assert type(err.value) in [Error, SysCallError]
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003574
Alex Chanb7480992017-01-30 14:04:47 +00003575 def test_unexpected_EOF(self):
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003576 """
3577 If the connection is lost before an orderly SSL shutdown occurs,
Alex Chanb7480992017-01-30 14:04:47 +00003578 `OpenSSL.SSL.SysCallError` is raised with a message of
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003579 "Unexpected EOF".
3580 """
Alex Chanb7480992017-01-30 14:04:47 +00003581 server_conn, client_conn = loopback()
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003582 client_conn.sock_shutdown(SHUT_RDWR)
Alex Chanb7480992017-01-30 14:04:47 +00003583 with pytest.raises(SysCallError) as err:
3584 server_conn.recv(1024)
3585 assert err.value.args == (-1, "Unexpected EOF")
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003586
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003587 def _check_client_ca_list(self, func):
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003588 """
Alex Chanb7480992017-01-30 14:04:47 +00003589 Verify the return value of the `get_client_ca_list` method for
Hynek Schlawack35618382015-09-05 21:54:25 +02003590 server and client connections.
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003591
Jonathan Ballet78b92a22011-07-16 08:07:26 +09003592 :param func: A function which will be called with the server context
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003593 before the client and server are connected to each other. This
3594 function should specify a list of CAs for the server to send to the
3595 client and return that same list. The list will be used to verify
Alex Chanb7480992017-01-30 14:04:47 +00003596 that `get_client_ca_list` returns the proper value at
Hynek Schlawack35618382015-09-05 21:54:25 +02003597 various times.
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003598 """
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003599 server = self._server(None)
3600 client = self._client(None)
Alex Chanb7480992017-01-30 14:04:47 +00003601 assert client.get_client_ca_list() == []
3602 assert server.get_client_ca_list() == []
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003603 ctx = server.get_context()
3604 expected = func(ctx)
Alex Chanb7480992017-01-30 14:04:47 +00003605 assert client.get_client_ca_list() == []
3606 assert server.get_client_ca_list() == expected
3607 interact_in_memory(client, server)
3608 assert client.get_client_ca_list() == expected
3609 assert server.get_client_ca_list() == expected
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003610
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003611 def test_set_client_ca_list_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003612 """
Alex Chanb7480992017-01-30 14:04:47 +00003613 `Context.set_client_ca_list` raises a `TypeError` if called with a
3614 non-list or a list that contains objects other than X509Names.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003615 """
3616 ctx = Context(TLSv1_METHOD)
Alex Chanb7480992017-01-30 14:04:47 +00003617 with pytest.raises(TypeError):
3618 ctx.set_client_ca_list("spam")
3619 with pytest.raises(TypeError):
3620 ctx.set_client_ca_list(["spam"])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003621
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003622 def test_set_empty_ca_list(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003623 """
Alex Chanb7480992017-01-30 14:04:47 +00003624 If passed an empty list, `Context.set_client_ca_list` configures the
3625 context to send no CA names to the client and, on both the server and
3626 client sides, `Connection.get_client_ca_list` returns an empty list
3627 after the connection is set up.
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003628 """
3629 def no_ca(ctx):
3630 ctx.set_client_ca_list([])
3631 return []
3632 self._check_client_ca_list(no_ca)
3633
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003634 def test_set_one_ca_list(self):
3635 """
3636 If passed a list containing a single X509Name,
Alex Chanb7480992017-01-30 14:04:47 +00003637 `Context.set_client_ca_list` configures the context to send
Hynek Schlawack35618382015-09-05 21:54:25 +02003638 that CA name to the client and, on both the server and client sides,
Alex Chanb7480992017-01-30 14:04:47 +00003639 `Connection.get_client_ca_list` returns a list containing that
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003640 X509Name after the connection is set up.
3641 """
3642 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3643 cadesc = cacert.get_subject()
Hynek Schlawack35618382015-09-05 21:54:25 +02003644
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003645 def single_ca(ctx):
3646 ctx.set_client_ca_list([cadesc])
3647 return [cadesc]
3648 self._check_client_ca_list(single_ca)
3649
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003650 def test_set_multiple_ca_list(self):
3651 """
3652 If passed a list containing multiple X509Name objects,
Alex Chanb7480992017-01-30 14:04:47 +00003653 `Context.set_client_ca_list` configures the context to send
Hynek Schlawack35618382015-09-05 21:54:25 +02003654 those CA names to the client and, on both the server and client sides,
Alex Chanb7480992017-01-30 14:04:47 +00003655 `Connection.get_client_ca_list` returns a list containing those
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003656 X509Names after the connection is set up.
3657 """
3658 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3659 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3660
3661 sedesc = secert.get_subject()
3662 cldesc = clcert.get_subject()
3663
3664 def multiple_ca(ctx):
3665 L = [sedesc, cldesc]
3666 ctx.set_client_ca_list(L)
3667 return L
3668 self._check_client_ca_list(multiple_ca)
3669
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003670 def test_reset_ca_list(self):
3671 """
3672 If called multiple times, only the X509Names passed to the final call
Alex Chanb7480992017-01-30 14:04:47 +00003673 of `Context.set_client_ca_list` are used to configure the CA
Hynek Schlawack35618382015-09-05 21:54:25 +02003674 names sent to the client.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003675 """
3676 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3677 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3678 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3679
3680 cadesc = cacert.get_subject()
3681 sedesc = secert.get_subject()
3682 cldesc = clcert.get_subject()
3683
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003684 def changed_ca(ctx):
3685 ctx.set_client_ca_list([sedesc, cldesc])
3686 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003687 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003688 self._check_client_ca_list(changed_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003689
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003690 def test_mutated_ca_list(self):
3691 """
Alex Chanb7480992017-01-30 14:04:47 +00003692 If the list passed to `Context.set_client_ca_list` is mutated
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003693 afterwards, this does not affect the list of CA names sent to the
3694 client.
3695 """
3696 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3697 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3698
3699 cadesc = cacert.get_subject()
3700 sedesc = secert.get_subject()
3701
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003702 def mutated_ca(ctx):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003703 L = [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003704 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003705 L.append(sedesc)
3706 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003707 self._check_client_ca_list(mutated_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003708
Alex Chanb7480992017-01-30 14:04:47 +00003709 def test_add_client_ca_wrong_args(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003710 """
Alex Chanb7480992017-01-30 14:04:47 +00003711 `Context.add_client_ca` raises `TypeError` if called with
3712 a non-X509 object.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003713 """
3714 ctx = Context(TLSv1_METHOD)
Alex Chanb7480992017-01-30 14:04:47 +00003715 with pytest.raises(TypeError):
3716 ctx.add_client_ca("spam")
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003717
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003718 def test_one_add_client_ca(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003719 """
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003720 A certificate's subject can be added as a CA to be sent to the client
Alex Chanb7480992017-01-30 14:04:47 +00003721 with `Context.add_client_ca`.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003722 """
3723 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3724 cadesc = cacert.get_subject()
Hynek Schlawack35618382015-09-05 21:54:25 +02003725
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003726 def single_ca(ctx):
3727 ctx.add_client_ca(cacert)
3728 return [cadesc]
3729 self._check_client_ca_list(single_ca)
3730
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003731 def test_multiple_add_client_ca(self):
3732 """
3733 Multiple CA names can be sent to the client by calling
Alex Chanb7480992017-01-30 14:04:47 +00003734 `Context.add_client_ca` with multiple X509 objects.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003735 """
3736 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3737 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3738
3739 cadesc = cacert.get_subject()
3740 sedesc = secert.get_subject()
3741
3742 def multiple_ca(ctx):
3743 ctx.add_client_ca(cacert)
3744 ctx.add_client_ca(secert)
3745 return [cadesc, sedesc]
3746 self._check_client_ca_list(multiple_ca)
3747
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003748 def test_set_and_add_client_ca(self):
3749 """
Alex Chanb7480992017-01-30 14:04:47 +00003750 A call to `Context.set_client_ca_list` followed by a call to
3751 `Context.add_client_ca` results in using the CA names from the
Hynek Schlawack35618382015-09-05 21:54:25 +02003752 first call and the CA name from the second call.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003753 """
3754 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3755 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3756 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3757
3758 cadesc = cacert.get_subject()
3759 sedesc = secert.get_subject()
3760 cldesc = clcert.get_subject()
3761
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003762 def mixed_set_add_ca(ctx):
3763 ctx.set_client_ca_list([cadesc, sedesc])
3764 ctx.add_client_ca(clcert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003765 return [cadesc, sedesc, cldesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003766 self._check_client_ca_list(mixed_set_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003767
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003768 def test_set_after_add_client_ca(self):
3769 """
Alex Chanb7480992017-01-30 14:04:47 +00003770 A call to `Context.set_client_ca_list` after a call to
3771 `Context.add_client_ca` replaces the CA name specified by the
Hynek Schlawack35618382015-09-05 21:54:25 +02003772 former call with the names specified by the latter call.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003773 """
3774 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3775 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3776 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3777
3778 cadesc = cacert.get_subject()
3779 sedesc = secert.get_subject()
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003780
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003781 def set_replaces_add_ca(ctx):
3782 ctx.add_client_ca(clcert)
3783 ctx.set_client_ca_list([cadesc])
3784 ctx.add_client_ca(secert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003785 return [cadesc, sedesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003786 self._check_client_ca_list(set_replaces_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003787
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003788
Alex Chanb7480992017-01-30 14:04:47 +00003789class TestInfoConstants(object):
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003790 """
3791 Tests for assorted constants exposed for use in info callbacks.
3792 """
3793 def test_integers(self):
3794 """
3795 All of the info constants are integers.
3796
3797 This is a very weak test. It would be nice to have one that actually
3798 verifies that as certain info events happen, the value passed to the
3799 info callback matches up with the constant exposed by OpenSSL.SSL.
3800 """
3801 for const in [
Alex Gaynor5af32d02016-09-24 01:52:21 -04003802 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK,
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003803 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
3804 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
3805 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
Hynek Schlawack35618382015-09-05 21:54:25 +02003806 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE
3807 ]:
Alex Gaynor5af32d02016-09-24 01:52:21 -04003808 assert isinstance(const, int)
3809
3810 # These constants don't exist on OpenSSL 1.1.0
3811 for const in [
3812 SSL_ST_INIT, SSL_ST_BEFORE, SSL_ST_OK, SSL_ST_RENEGOTIATE
3813 ]:
3814 assert const is None or isinstance(const, int)
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003815
Ziga Seilnacht44611bf2009-08-31 20:49:30 +02003816
Cory Benfield1d142142016-03-30 11:51:45 +01003817class TestRequires(object):
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003818 """
3819 Tests for the decorator factory used to conditionally raise
Cory Benfield1d142142016-03-30 11:51:45 +01003820 NotImplementedError when older OpenSSLs are used.
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003821 """
3822 def test_available(self):
3823 """
3824 When the OpenSSL functionality is available the decorated functions
3825 work appropriately.
3826 """
3827 feature_guard = _make_requires(True, "Error text")
3828 results = []
3829
3830 @feature_guard
3831 def inner():
3832 results.append(True)
3833 return True
3834
Cory Benfield2333e5e2016-03-30 14:24:16 +01003835 assert inner() is True
3836 assert [True] == results
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003837
3838 def test_unavailable(self):
3839 """
3840 When the OpenSSL functionality is not available the decorated function
3841 does not execute and NotImplementedError is raised.
3842 """
3843 feature_guard = _make_requires(False, "Error text")
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003844
3845 @feature_guard
Alex Chanfb078d82017-04-20 11:16:15 +01003846 def inner(): # pragma: nocover
3847 pytest.fail("Should not be called")
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003848
Cory Benfield1d142142016-03-30 11:51:45 +01003849 with pytest.raises(NotImplementedError) as e:
3850 inner()
3851
3852 assert "Error text" in str(e.value)
Cory Benfield496652a2017-01-24 11:42:56 +00003853
3854
Alex Chanb7480992017-01-30 14:04:47 +00003855class TestOCSP(object):
Cory Benfield496652a2017-01-24 11:42:56 +00003856 """
3857 Tests for PyOpenSSL's OCSP stapling support.
3858 """
3859 sample_ocsp_data = b"this is totally ocsp data"
3860
3861 def _client_connection(self, callback, data, request_ocsp=True):
3862 """
3863 Builds a client connection suitable for using OCSP.
3864
3865 :param callback: The callback to register for OCSP.
3866 :param data: The opaque data object that will be handed to the
3867 OCSP callback.
3868 :param request_ocsp: Whether the client will actually ask for OCSP
3869 stapling. Useful for testing only.
3870 """
3871 ctx = Context(SSLv23_METHOD)
3872 ctx.set_ocsp_client_callback(callback, data)
3873 client = Connection(ctx)
3874
3875 if request_ocsp:
3876 client.request_ocsp()
3877
3878 client.set_connect_state()
3879 return client
3880
3881 def _server_connection(self, callback, data):
3882 """
3883 Builds a server connection suitable for using OCSP.
3884
3885 :param callback: The callback to register for OCSP.
3886 :param data: The opaque data object that will be handed to the
3887 OCSP callback.
3888 """
3889 ctx = Context(SSLv23_METHOD)
3890 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
3891 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
3892 ctx.set_ocsp_server_callback(callback, data)
3893 server = Connection(ctx)
3894 server.set_accept_state()
3895 return server
3896
3897 def test_callbacks_arent_called_by_default(self):
3898 """
3899 If both the client and the server have registered OCSP callbacks, but
3900 the client does not send the OCSP request, neither callback gets
3901 called.
3902 """
Alex Chanfb078d82017-04-20 11:16:15 +01003903 def ocsp_callback(*args, **kwargs): # pragma: nocover
3904 pytest.fail("Should not be called")
Cory Benfield496652a2017-01-24 11:42:56 +00003905
3906 client = self._client_connection(
3907 callback=ocsp_callback, data=None, request_ocsp=False
3908 )
3909 server = self._server_connection(callback=ocsp_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00003910 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003911
Cory Benfield496652a2017-01-24 11:42:56 +00003912 def test_client_negotiates_without_server(self):
3913 """
3914 If the client wants to do OCSP but the server does not, the handshake
3915 succeeds, and the client callback fires with an empty byte string.
3916 """
3917 called = []
3918
3919 def ocsp_callback(conn, ocsp_data, ignored):
3920 called.append(ocsp_data)
3921 return True
3922
3923 client = self._client_connection(callback=ocsp_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00003924 server = loopback_server_factory(socket=None)
3925 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003926
3927 assert len(called) == 1
3928 assert called[0] == b''
3929
3930 def test_client_receives_servers_data(self):
3931 """
3932 The data the server sends in its callback is received by the client.
3933 """
3934 calls = []
3935
3936 def server_callback(*args, **kwargs):
3937 return self.sample_ocsp_data
3938
3939 def client_callback(conn, ocsp_data, ignored):
3940 calls.append(ocsp_data)
3941 return True
3942
3943 client = self._client_connection(callback=client_callback, data=None)
3944 server = self._server_connection(callback=server_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00003945 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003946
3947 assert len(calls) == 1
3948 assert calls[0] == self.sample_ocsp_data
3949
3950 def test_callbacks_are_invoked_with_connections(self):
3951 """
3952 The first arguments to both callbacks are their respective connections.
3953 """
3954 client_calls = []
3955 server_calls = []
3956
3957 def client_callback(conn, *args, **kwargs):
3958 client_calls.append(conn)
3959 return True
3960
3961 def server_callback(conn, *args, **kwargs):
3962 server_calls.append(conn)
3963 return self.sample_ocsp_data
3964
3965 client = self._client_connection(callback=client_callback, data=None)
3966 server = self._server_connection(callback=server_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00003967 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003968
3969 assert len(client_calls) == 1
3970 assert len(server_calls) == 1
3971 assert client_calls[0] is client
3972 assert server_calls[0] is server
3973
3974 def test_opaque_data_is_passed_through(self):
3975 """
3976 Both callbacks receive an opaque, user-provided piece of data in their
3977 callbacks as the final argument.
3978 """
3979 calls = []
3980
3981 def server_callback(*args):
3982 calls.append(args)
3983 return self.sample_ocsp_data
3984
3985 def client_callback(*args):
3986 calls.append(args)
3987 return True
3988
3989 sentinel = object()
3990
3991 client = self._client_connection(
3992 callback=client_callback, data=sentinel
3993 )
3994 server = self._server_connection(
3995 callback=server_callback, data=sentinel
3996 )
Alex Chanb7480992017-01-30 14:04:47 +00003997 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003998
3999 assert len(calls) == 2
4000 assert calls[0][-1] is sentinel
4001 assert calls[1][-1] is sentinel
4002
4003 def test_server_returns_empty_string(self):
4004 """
4005 If the server returns an empty bytestring from its callback, the
4006 client callback is called with the empty bytestring.
4007 """
4008 client_calls = []
4009
4010 def server_callback(*args):
4011 return b''
4012
4013 def client_callback(conn, ocsp_data, ignored):
4014 client_calls.append(ocsp_data)
4015 return True
4016
4017 client = self._client_connection(callback=client_callback, data=None)
4018 server = self._server_connection(callback=server_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00004019 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00004020
4021 assert len(client_calls) == 1
4022 assert client_calls[0] == b''
4023
4024 def test_client_returns_false_terminates_handshake(self):
4025 """
4026 If the client returns False from its callback, the handshake fails.
4027 """
4028 def server_callback(*args):
4029 return self.sample_ocsp_data
4030
4031 def client_callback(*args):
4032 return False
4033
4034 client = self._client_connection(callback=client_callback, data=None)
4035 server = self._server_connection(callback=server_callback, data=None)
4036
4037 with pytest.raises(Error):
Alex Chanb7480992017-01-30 14:04:47 +00004038 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00004039
4040 def test_exceptions_in_client_bubble_up(self):
4041 """
4042 The callbacks thrown in the client callback bubble up to the caller.
4043 """
4044 class SentinelException(Exception):
4045 pass
4046
4047 def server_callback(*args):
4048 return self.sample_ocsp_data
4049
4050 def client_callback(*args):
4051 raise SentinelException()
4052
4053 client = self._client_connection(callback=client_callback, data=None)
4054 server = self._server_connection(callback=server_callback, data=None)
4055
4056 with pytest.raises(SentinelException):
Alex Chanb7480992017-01-30 14:04:47 +00004057 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00004058
4059 def test_exceptions_in_server_bubble_up(self):
4060 """
4061 The callbacks thrown in the server callback bubble up to the caller.
4062 """
4063 class SentinelException(Exception):
4064 pass
4065
4066 def server_callback(*args):
4067 raise SentinelException()
4068
Alex Chanfb078d82017-04-20 11:16:15 +01004069 def client_callback(*args): # pragma: nocover
Cory Benfield496652a2017-01-24 11:42:56 +00004070 pytest.fail("Should not be called")
4071
4072 client = self._client_connection(callback=client_callback, data=None)
4073 server = self._server_connection(callback=server_callback, data=None)
4074
4075 with pytest.raises(SentinelException):
Alex Chanb7480992017-01-30 14:04:47 +00004076 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00004077
4078 def test_server_must_return_bytes(self):
4079 """
4080 The server callback must return a bytestring, or a TypeError is thrown.
4081 """
4082 def server_callback(*args):
4083 return self.sample_ocsp_data.decode('ascii')
4084
Alex Chanfb078d82017-04-20 11:16:15 +01004085 def client_callback(*args): # pragma: nocover
Cory Benfield496652a2017-01-24 11:42:56 +00004086 pytest.fail("Should not be called")
4087
4088 client = self._client_connection(callback=client_callback, data=None)
4089 server = self._server_connection(callback=server_callback, data=None)
4090
4091 with pytest.raises(TypeError):
Alex Chanb7480992017-01-30 14:04:47 +00004092 handshake_in_memory(client, server)