blob: ba5b638dede045a2549eda253e11577121d56384 [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 (
Alex Gaynor03737182020-07-23 20:40:46 -040014 EAFNOSUPPORT,
15 ECONNREFUSED,
16 EINPROGRESS,
17 EWOULDBLOCK,
18 EPIPE,
19 ESHUTDOWN,
20)
Jeremy Lainé1ae7cb62018-03-21 14:49:42 +010021from sys import platform, getfilesystemencoding
David Benjamin1fbe0642019-04-15 17:05:13 -050022from socket import AF_INET, AF_INET6, MSG_PEEK, SHUT_RDWR, error, socket
Jean-Paul Calderonea65cf6c2009-07-19 10:26:52 -040023from os import makedirs
Jean-Paul Calderone1461c492013-10-03 16:05:00 -040024from os.path import join
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -040025from weakref import ref
Alex Chanb7480992017-01-30 14:04:47 +000026from warnings import simplefilter
Jean-Paul Calderone460cc1f2009-03-07 11:31:12 -050027
Alex Gaynor963ae032019-07-06 17:38:32 -040028import flaky
29
Hynek Schlawack734d3022015-09-05 19:19:32 +020030import pytest
31
Paul Kehrer55fb3412017-06-29 18:44:08 -050032from pretend import raiser
33
Hugo van Kemenade60827f82019-08-30 00:39:35 +030034from six import PY2, text_type
Jean-Paul Calderonec76c61c2014-01-18 13:21:52 -050035
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +010036from cryptography import x509
37from cryptography.hazmat.backends import default_backend
38from cryptography.hazmat.primitives import hashes
39from cryptography.hazmat.primitives import serialization
40from cryptography.hazmat.primitives.asymmetric import rsa
41from cryptography.x509.oid import NameOID
42
43
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040044from OpenSSL.crypto import TYPE_RSA, FILETYPE_PEM
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -080045from OpenSSL.crypto import PKey, X509, X509Extension, X509Store
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040046from OpenSSL.crypto import dump_privatekey, load_privatekey
47from OpenSSL.crypto import dump_certificate, load_certificate
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -040048from OpenSSL.crypto import get_elliptic_curves
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040049
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -040050from OpenSSL.SSL import OPENSSL_VERSION_NUMBER, SSLEAY_VERSION, SSLEAY_CFLAGS
51from OpenSSL.SSL import SSLEAY_PLATFORM, SSLEAY_DIR, SSLEAY_BUILT_ON
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -040052from OpenSSL.SSL import SENT_SHUTDOWN, RECEIVED_SHUTDOWN
Jean-Paul Calderone1461c492013-10-03 16:05:00 -040053from OpenSSL.SSL import (
Alex Gaynor03737182020-07-23 20:40:46 -040054 SSLv2_METHOD,
55 SSLv3_METHOD,
56 SSLv23_METHOD,
57 TLSv1_METHOD,
58 TLSv1_1_METHOD,
59 TLSv1_2_METHOD,
60)
Jean-Paul Calderone1461c492013-10-03 16:05:00 -040061from OpenSSL.SSL import OP_SINGLE_DH_USE, OP_NO_SSLv2, OP_NO_SSLv3
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040062from OpenSSL.SSL import (
Alex Gaynor03737182020-07-23 20:40:46 -040063 VERIFY_PEER,
64 VERIFY_FAIL_IF_NO_PEER_CERT,
65 VERIFY_CLIENT_ONCE,
66 VERIFY_NONE,
67)
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040068
Paul Kehrer55fb3412017-06-29 18:44:08 -050069from OpenSSL import SSL
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040070from OpenSSL.SSL import (
Alex Gaynor03737182020-07-23 20:40:46 -040071 SESS_CACHE_OFF,
72 SESS_CACHE_CLIENT,
73 SESS_CACHE_SERVER,
74 SESS_CACHE_BOTH,
75 SESS_CACHE_NO_AUTO_CLEAR,
76 SESS_CACHE_NO_INTERNAL_LOOKUP,
77 SESS_CACHE_NO_INTERNAL_STORE,
78 SESS_CACHE_NO_INTERNAL,
79)
Jean-Paul Calderone313bf012012-02-08 13:02:49 -050080
81from OpenSSL.SSL import (
Alex Gaynor03737182020-07-23 20:40:46 -040082 Error,
83 SysCallError,
84 WantReadError,
85 WantWriteError,
86 ZeroReturnError,
87)
88from OpenSSL.SSL import Context, Session, Connection, SSLeay_version
Cory Benfield0ba57ec2016-03-30 09:35:05 +010089from OpenSSL.SSL import _make_requires
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040090
Paul Kehrer55fb3412017-06-29 18:44:08 -050091from OpenSSL._util import ffi as _ffi, lib as _lib
Cory Benfieldba1820d2015-04-13 17:39:12 -040092
Alex Gaynord3b5d9b2016-07-31 10:54:24 -040093from OpenSSL.SSL import (
Alex Gaynor03737182020-07-23 20:40:46 -040094 OP_NO_QUERY_MTU,
95 OP_COOKIE_EXCHANGE,
96 OP_NO_TICKET,
97 OP_NO_COMPRESSION,
98 MODE_RELEASE_BUFFERS,
99 NO_OVERLAPPING_PROTOCOLS,
100)
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400101
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -0400102from OpenSSL.SSL import (
Alex Gaynor03737182020-07-23 20:40:46 -0400103 SSL_ST_CONNECT,
104 SSL_ST_ACCEPT,
105 SSL_ST_MASK,
106 SSL_CB_LOOP,
107 SSL_CB_EXIT,
108 SSL_CB_READ,
109 SSL_CB_WRITE,
110 SSL_CB_ALERT,
111 SSL_CB_READ_ALERT,
112 SSL_CB_WRITE_ALERT,
113 SSL_CB_ACCEPT_LOOP,
114 SSL_CB_ACCEPT_EXIT,
115 SSL_CB_CONNECT_LOOP,
116 SSL_CB_CONNECT_EXIT,
117 SSL_CB_HANDSHAKE_START,
118 SSL_CB_HANDSHAKE_DONE,
119)
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400120
Alex Gaynor5af32d02016-09-24 01:52:21 -0400121try:
122 from OpenSSL.SSL import (
Alex Gaynor03737182020-07-23 20:40:46 -0400123 SSL_ST_INIT,
124 SSL_ST_BEFORE,
125 SSL_ST_OK,
126 SSL_ST_RENEGOTIATE,
Alex Gaynor5af32d02016-09-24 01:52:21 -0400127 )
128except ImportError:
129 SSL_ST_INIT = SSL_ST_BEFORE = SSL_ST_OK = SSL_ST_RENEGOTIATE = None
130
Alex Chanb7480992017-01-30 14:04:47 +0000131from .util import WARNING_TYPE_EXPECTED, NON_ASCII, is_consistent_type
Hynek Schlawackf0e66852015-10-16 20:18:38 +0200132from .test_crypto import (
Alex Gaynor03737182020-07-23 20:40:46 -0400133 cleartextCertificatePEM,
134 cleartextPrivateKeyPEM,
135 client_cert_pem,
136 client_key_pem,
137 server_cert_pem,
138 server_key_pem,
139 root_cert_pem,
140)
Hynek Schlawackf0e66852015-10-16 20:18:38 +0200141
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200142
Alex Gaynord0bdd2d2016-09-10 14:23:46 -0400143# openssl dhparam 1024 -out dh-1024.pem (note that 1024 is a small number of
144# bits to use)
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -0400145dhparam = """\
146-----BEGIN DH PARAMETERS-----
Alex Gaynord0bdd2d2016-09-10 14:23:46 -0400147MIGHAoGBALdUMvn+C9MM+y5BWZs11mSeH6HHoEq0UVbzVq7UojC1hbsZUuGukQ3a
148Qh2/pwqb18BZFykrWB0zv/OkLa0kx4cuUgNrUVq1EFheBiX6YqryJ7t2sO09NQiO
149V7H54LmltOT/hEh6QWsJqb6BQgH65bswvV/XkYGja8/T0GzvbaVzAgEC
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -0400150-----END DH PARAMETERS-----
151"""
152
153
Hugo van Kemenade60827f82019-08-30 00:39:35 +0300154skip_if_py3 = pytest.mark.skipif(not PY2, reason="Python 2 only")
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200155
156
David Benjamin1fbe0642019-04-15 17:05:13 -0500157def socket_any_family():
158 try:
159 return socket(AF_INET)
160 except error as e:
161 if e.errno == EAFNOSUPPORT:
162 return socket(AF_INET6)
163 raise
164
165
166def loopback_address(socket):
167 if socket.family == AF_INET:
168 return "127.0.0.1"
169 else:
170 assert socket.family == AF_INET6
171 return "::1"
172
173
Jean-Paul Calderone05826732015-04-12 11:38:49 -0400174def join_bytes_or_unicode(prefix, suffix):
175 """
176 Join two path components of either ``bytes`` or ``unicode``.
177
178 The return type is the same as the type of ``prefix``.
179 """
180 # If the types are the same, nothing special is necessary.
181 if type(prefix) == type(suffix):
182 return join(prefix, suffix)
183
184 # Otherwise, coerce suffix to the type of prefix.
185 if isinstance(prefix, text_type):
186 return join(prefix, suffix.decode(getfilesystemencoding()))
187 else:
188 return join(prefix, suffix.encode(getfilesystemencoding()))
189
190
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400191def verify_cb(conn, cert, errnum, depth, ok):
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400192 return ok
193
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400194
Rick Deanb1ccd562009-07-09 23:52:39 -0500195def socket_pair():
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400196 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400197 Establish and return a pair of network sockets connected to each other.
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400198 """
199 # Connect a pair of sockets
David Benjamin1fbe0642019-04-15 17:05:13 -0500200 port = socket_any_family()
Alex Gaynor03737182020-07-23 20:40:46 -0400201 port.bind(("", 0))
Rick Deanb1ccd562009-07-09 23:52:39 -0500202 port.listen(1)
David Benjamin1fbe0642019-04-15 17:05:13 -0500203 client = socket(port.family)
Rick Deanb1ccd562009-07-09 23:52:39 -0500204 client.setblocking(False)
David Benjamin1fbe0642019-04-15 17:05:13 -0500205 client.connect_ex((loopback_address(port), port.getsockname()[1]))
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400206 client.setblocking(True)
Rick Deanb1ccd562009-07-09 23:52:39 -0500207 server = port.accept()[0]
Rick Deanb1ccd562009-07-09 23:52:39 -0500208
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400209 # Let's pass some unencrypted data to make sure our socket connection is
210 # fine. Just one byte, so we don't have to worry about buffers getting
211 # filled up or fragmentation.
Alex Gaynore7f51982016-09-11 11:48:14 -0400212 server.send(b"x")
213 assert client.recv(1024) == b"x"
214 client.send(b"y")
215 assert server.recv(1024) == b"y"
Rick Deanb1ccd562009-07-09 23:52:39 -0500216
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -0400217 # Most of our callers want non-blocking sockets, make it easy for them.
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400218 server.setblocking(False)
219 client.setblocking(False)
Jim Shaver46f28912015-05-29 19:32:16 -0400220
Rick Deanb1ccd562009-07-09 23:52:39 -0500221 return (server, client)
222
223
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400224def handshake(client, server):
225 conns = [client, server]
226 while conns:
227 for conn in conns:
228 try:
229 conn.do_handshake()
230 except WantReadError:
231 pass
232 else:
233 conns.remove(conn)
234
235
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400236def _create_certificate_chain():
237 """
238 Construct and return a chain of certificates.
239
240 1. A new self-signed certificate authority certificate (cacert)
241 2. A new intermediate certificate signed by cacert (icert)
242 3. A new server certificate signed by icert (scert)
243 """
Alex Gaynor03737182020-07-23 20:40:46 -0400244 caext = X509Extension(b"basicConstraints", False, b"CA:true")
245 not_after_date = datetime.date.today() + datetime.timedelta(days=365)
Alex Gaynor675534c2020-01-12 11:59:49 -0600246 not_after = not_after_date.strftime("%Y%m%d%H%M%SZ").encode("ascii")
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400247
248 # Step 1
249 cakey = PKey()
Alex Gaynor0737a5e2016-09-10 14:35:09 -0400250 cakey.generate_key(TYPE_RSA, 1024)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400251 cacert = X509()
David Benjamin6b799472020-06-24 17:14:16 -0400252 cacert.set_version(2)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400253 cacert.get_subject().commonName = "Authority Certificate"
254 cacert.set_issuer(cacert.get_subject())
255 cacert.set_pubkey(cakey)
Alex Gaynore7f51982016-09-11 11:48:14 -0400256 cacert.set_notBefore(b"20000101000000Z")
Alex Gaynor675534c2020-01-12 11:59:49 -0600257 cacert.set_notAfter(not_after)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400258 cacert.add_extensions([caext])
259 cacert.set_serial_number(0)
260 cacert.sign(cakey, "sha1")
261
262 # Step 2
263 ikey = PKey()
Alex Gaynor0737a5e2016-09-10 14:35:09 -0400264 ikey.generate_key(TYPE_RSA, 1024)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400265 icert = X509()
David Benjamin6b799472020-06-24 17:14:16 -0400266 icert.set_version(2)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400267 icert.get_subject().commonName = "Intermediate Certificate"
268 icert.set_issuer(cacert.get_subject())
269 icert.set_pubkey(ikey)
Alex Gaynore7f51982016-09-11 11:48:14 -0400270 icert.set_notBefore(b"20000101000000Z")
Alex Gaynor675534c2020-01-12 11:59:49 -0600271 icert.set_notAfter(not_after)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400272 icert.add_extensions([caext])
273 icert.set_serial_number(0)
274 icert.sign(cakey, "sha1")
275
276 # Step 3
277 skey = PKey()
Alex Gaynor0737a5e2016-09-10 14:35:09 -0400278 skey.generate_key(TYPE_RSA, 1024)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400279 scert = X509()
David Benjamin6b799472020-06-24 17:14:16 -0400280 scert.set_version(2)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400281 scert.get_subject().commonName = "Server Certificate"
282 scert.set_issuer(icert.get_subject())
283 scert.set_pubkey(skey)
Alex Gaynore7f51982016-09-11 11:48:14 -0400284 scert.set_notBefore(b"20000101000000Z")
Alex Gaynor675534c2020-01-12 11:59:49 -0600285 scert.set_notAfter(not_after)
Alex Gaynor03737182020-07-23 20:40:46 -0400286 scert.add_extensions(
287 [X509Extension(b"basicConstraints", True, b"CA:false")]
288 )
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400289 scert.set_serial_number(0)
290 scert.sign(ikey, "sha1")
291
292 return [(cakey, cacert), (ikey, icert), (skey, scert)]
293
294
Paul Kehrer7d5a3bf2019-01-21 12:24:02 -0600295def loopback_client_factory(socket, version=SSLv23_METHOD):
296 client = Connection(Context(version), socket)
Alex Chan1c0cb662017-01-30 07:13:30 +0000297 client.set_connect_state()
298 return client
299
300
Paul Kehrer7d5a3bf2019-01-21 12:24:02 -0600301def loopback_server_factory(socket, version=SSLv23_METHOD):
302 ctx = Context(version)
Alex Chan1c0cb662017-01-30 07:13:30 +0000303 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
304 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
305 server = Connection(ctx, socket)
306 server.set_accept_state()
307 return server
308
309
310def loopback(server_factory=None, client_factory=None):
311 """
312 Create a connected socket pair and force two connected SSL sockets
313 to talk to each other via memory BIOs.
314 """
315 if server_factory is None:
316 server_factory = loopback_server_factory
317 if client_factory is None:
318 client_factory = loopback_client_factory
319
320 (server, client) = socket_pair()
321 server = server_factory(server)
322 client = client_factory(client)
323
324 handshake(client, server)
325
326 server.setblocking(True)
327 client.setblocking(True)
328 return server, client
329
330
Alex Chan1ca9e3a2016-11-05 13:01:51 +0000331def interact_in_memory(client_conn, server_conn):
332 """
333 Try to read application bytes from each of the two `Connection` objects.
334 Copy bytes back and forth between their send/receive buffers for as long
335 as there is anything to copy. When there is nothing more to copy,
336 return `None`. If one of them actually manages to deliver some application
337 bytes, return a two-tuple of the connection from which the bytes were read
338 and the bytes themselves.
339 """
340 wrote = True
341 while wrote:
342 # Loop until neither side has anything to say
343 wrote = False
344
345 # Copy stuff from each side's send buffer to the other side's
346 # receive buffer.
Alex Gaynor03737182020-07-23 20:40:46 -0400347 for (read, write) in [
348 (client_conn, server_conn),
349 (server_conn, client_conn),
350 ]:
Alex Chan1ca9e3a2016-11-05 13:01:51 +0000351
352 # Give the side a chance to generate some more bytes, or succeed.
353 try:
354 data = read.recv(2 ** 16)
355 except WantReadError:
356 # It didn't succeed, so we'll hope it generated some output.
357 pass
358 else:
359 # It did succeed, so we'll stop now and let the caller deal
360 # with it.
361 return (read, data)
362
363 while True:
364 # Keep copying as long as there's more stuff there.
365 try:
366 dirty = read.bio_read(4096)
367 except WantReadError:
368 # Okay, nothing more waiting to be sent. Stop
369 # processing this send buffer.
370 break
371 else:
372 # Keep track of the fact that someone generated some
373 # output.
374 wrote = True
375 write.bio_write(dirty)
376
377
Alex Chan532b79e2017-01-24 15:14:52 +0000378def handshake_in_memory(client_conn, server_conn):
379 """
380 Perform the TLS handshake between two `Connection` instances connected to
381 each other via memory BIOs.
382 """
383 client_conn.set_connect_state()
384 server_conn.set_accept_state()
385
386 for conn in [client_conn, server_conn]:
387 try:
388 conn.do_handshake()
389 except WantReadError:
390 pass
391
392 interact_in_memory(client_conn, server_conn)
393
394
Alex Chanb7480992017-01-30 14:04:47 +0000395class TestVersion(object):
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400396 """
Alex Chanb7480992017-01-30 14:04:47 +0000397 Tests for version information exposed by `OpenSSL.SSL.SSLeay_version` and
398 `OpenSSL.SSL.OPENSSL_VERSION_NUMBER`.
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400399 """
Alex Gaynor03737182020-07-23 20:40:46 -0400400
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400401 def test_OPENSSL_VERSION_NUMBER(self):
402 """
Alex Chanb7480992017-01-30 14:04:47 +0000403 `OPENSSL_VERSION_NUMBER` is an integer with status in the low byte and
404 the patch, fix, minor, and major versions in the nibbles above that.
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400405 """
Alex Chanb7480992017-01-30 14:04:47 +0000406 assert isinstance(OPENSSL_VERSION_NUMBER, int)
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400407
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400408 def test_SSLeay_version(self):
409 """
Alex Chanb7480992017-01-30 14:04:47 +0000410 `SSLeay_version` takes a version type indicator and returns one of a
411 number of version strings based on that indicator.
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400412 """
413 versions = {}
Alex Gaynor03737182020-07-23 20:40:46 -0400414 for t in [
415 SSLEAY_VERSION,
416 SSLEAY_CFLAGS,
417 SSLEAY_BUILT_ON,
418 SSLEAY_PLATFORM,
419 SSLEAY_DIR,
420 ]:
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400421 version = SSLeay_version(t)
422 versions[version] = t
Alex Chanb7480992017-01-30 14:04:47 +0000423 assert isinstance(version, bytes)
424 assert len(versions) == 5
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400425
426
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100427@pytest.fixture
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100428def ca_file(tmpdir):
429 """
430 Create a valid PEM file with CA certificates and return the path.
431 """
432 key = rsa.generate_private_key(
Alex Gaynor03737182020-07-23 20:40:46 -0400433 public_exponent=65537, key_size=2048, backend=default_backend()
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100434 )
435 public_key = key.public_key()
436
437 builder = x509.CertificateBuilder()
Alex Gaynor03737182020-07-23 20:40:46 -0400438 builder = builder.subject_name(
439 x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, u"pyopenssl.org")])
440 )
441 builder = builder.issuer_name(
442 x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, u"pyopenssl.org")])
443 )
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100444 one_day = datetime.timedelta(1, 0, 0)
445 builder = builder.not_valid_before(datetime.datetime.today() - one_day)
446 builder = builder.not_valid_after(datetime.datetime.today() + one_day)
447 builder = builder.serial_number(int(uuid.uuid4()))
448 builder = builder.public_key(public_key)
449 builder = builder.add_extension(
450 x509.BasicConstraints(ca=True, path_length=None), critical=True,
451 )
452
453 certificate = builder.sign(
Alex Gaynor03737182020-07-23 20:40:46 -0400454 private_key=key, algorithm=hashes.SHA256(), backend=default_backend()
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100455 )
456
457 ca_file = tmpdir.join("test.pem")
458 ca_file.write_binary(
Alex Gaynor03737182020-07-23 20:40:46 -0400459 certificate.public_bytes(encoding=serialization.Encoding.PEM,)
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100460 )
461
462 return str(ca_file).encode("ascii")
463
464
465@pytest.fixture
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100466def context():
467 """
468 A simple TLS 1.0 context.
469 """
470 return Context(TLSv1_METHOD)
471
472
473class TestContext(object):
Hynek Schlawackaa861212016-03-13 13:53:48 +0100474 """
Alex Chan532b79e2017-01-24 15:14:52 +0000475 Unit tests for `OpenSSL.SSL.Context`.
Hynek Schlawackaa861212016-03-13 13:53:48 +0100476 """
Alex Gaynor03737182020-07-23 20:40:46 -0400477
478 @pytest.mark.parametrize(
479 "cipher_string",
480 [b"hello world:AES128-SHA", u"hello world:AES128-SHA"],
481 )
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100482 def test_set_cipher_list(self, context, cipher_string):
483 """
Alex Chan532b79e2017-01-24 15:14:52 +0000484 `Context.set_cipher_list` accepts both byte and unicode strings
Hynek Schlawacka7a63af2016-03-11 12:05:26 +0100485 for naming the ciphers which connections created with the context
486 object will be able to choose from.
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100487 """
488 context.set_cipher_list(cipher_string)
489 conn = Connection(context, None)
490
491 assert "AES128-SHA" in conn.get_cipher_list()
492
Mark Williamsdf2480d2019-02-14 19:30:07 -0800493 def test_set_cipher_list_wrong_type(self, context):
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100494 """
Alex Chan532b79e2017-01-24 15:14:52 +0000495 `Context.set_cipher_list` raises `TypeError` when passed a non-string
Mark Williamsdf2480d2019-02-14 19:30:07 -0800496 argument.
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100497 """
Mark Williamsdf2480d2019-02-14 19:30:07 -0800498 with pytest.raises(TypeError):
499 context.set_cipher_list(object())
500
Alex Gaynor963ae032019-07-06 17:38:32 -0400501 @flaky.flaky
Mark Williamsdf2480d2019-02-14 19:30:07 -0800502 def test_set_cipher_list_no_cipher_match(self, context):
503 """
504 `Context.set_cipher_list` raises `OpenSSL.SSL.Error` with a
505 `"no cipher match"` reason string regardless of the TLS
506 version.
507 """
508 with pytest.raises(Error) as excinfo:
509 context.set_cipher_list(b"imaginary-cipher")
510 assert excinfo.value.args == (
Alex Gaynor03737182020-07-23 20:40:46 -0400511 [("SSL routines", "SSL_CTX_set_cipher_list", "no cipher match",)],
512 )
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100513
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100514 def test_load_client_ca(self, context, ca_file):
515 """
Alex Chan532b79e2017-01-24 15:14:52 +0000516 `Context.load_client_ca` works as far as we can tell.
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100517 """
518 context.load_client_ca(ca_file)
519
520 def test_load_client_ca_invalid(self, context, tmpdir):
521 """
Alex Chan532b79e2017-01-24 15:14:52 +0000522 `Context.load_client_ca` raises an Error if the ca file is invalid.
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100523 """
524 ca_file = tmpdir.join("test.pem")
525 ca_file.write("")
526
527 with pytest.raises(Error) as e:
528 context.load_client_ca(str(ca_file).encode("ascii"))
529
530 assert "PEM routines" == e.value.args[0][0][0]
531
532 def test_load_client_ca_unicode(self, context, ca_file):
533 """
534 Passing the path as unicode raises a warning but works.
535 """
Alex Gaynor03737182020-07-23 20:40:46 -0400536 pytest.deprecated_call(context.load_client_ca, ca_file.decode("ascii"))
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100537
538 def test_set_session_id(self, context):
539 """
Alex Chan532b79e2017-01-24 15:14:52 +0000540 `Context.set_session_id` works as far as we can tell.
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100541 """
542 context.set_session_id(b"abc")
543
544 def test_set_session_id_fail(self, context):
545 """
Alex Chan532b79e2017-01-24 15:14:52 +0000546 `Context.set_session_id` errors are propagated.
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100547 """
548 with pytest.raises(Error) as e:
549 context.set_session_id(b"abc" * 1000)
550
551 assert [
Alex Gaynor03737182020-07-23 20:40:46 -0400552 (
553 "SSL routines",
554 "SSL_CTX_set_session_id_context",
555 "ssl session id context too long",
556 )
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100557 ] == e.value.args[0]
558
559 def test_set_session_id_unicode(self, context):
560 """
Alex Chan532b79e2017-01-24 15:14:52 +0000561 `Context.set_session_id` raises a warning if a unicode string is
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100562 passed.
563 """
564 pytest.deprecated_call(context.set_session_id, u"abc")
565
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400566 def test_method(self):
567 """
Alex Chan532b79e2017-01-24 15:14:52 +0000568 `Context` can be instantiated with one of `SSLv2_METHOD`,
569 `SSLv3_METHOD`, `SSLv23_METHOD`, `TLSv1_METHOD`, `TLSv1_1_METHOD`,
570 or `TLSv1_2_METHOD`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400571 """
Alex Gaynor5af32d02016-09-24 01:52:21 -0400572 methods = [SSLv23_METHOD, TLSv1_METHOD]
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400573 for meth in methods:
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400574 Context(meth)
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400575
Alex Gaynor5af32d02016-09-24 01:52:21 -0400576 maybe = [SSLv2_METHOD, SSLv3_METHOD, TLSv1_1_METHOD, TLSv1_2_METHOD]
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400577 for meth in maybe:
578 try:
579 Context(meth)
580 except (Error, ValueError):
581 # Some versions of OpenSSL have SSLv2 / TLSv1.1 / TLSv1.2, some
582 # don't. Difficult to say in advance.
583 pass
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400584
Alex Chan532b79e2017-01-24 15:14:52 +0000585 with pytest.raises(TypeError):
586 Context("")
587 with pytest.raises(ValueError):
588 Context(10)
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400589
Rick Deane15b1472009-07-09 15:53:42 -0500590 def test_type(self):
591 """
Alex Gaynor01f90a12019-02-07 09:14:48 -0500592 `Context` can be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -0500593 """
Alex Gaynor03737182020-07-23 20:40:46 -0400594 assert is_consistent_type(Context, "Context", TLSv1_METHOD)
Rick Deane15b1472009-07-09 15:53:42 -0500595
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400596 def test_use_privatekey(self):
597 """
Alex Chan532b79e2017-01-24 15:14:52 +0000598 `Context.use_privatekey` takes an `OpenSSL.crypto.PKey` instance.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400599 """
600 key = PKey()
Alex Gaynor6e9f9762018-05-12 07:44:37 -0400601 key.generate_key(TYPE_RSA, 512)
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400602 ctx = Context(TLSv1_METHOD)
603 ctx.use_privatekey(key)
Alex Chan532b79e2017-01-24 15:14:52 +0000604 with pytest.raises(TypeError):
605 ctx.use_privatekey("")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400606
Alex Chan532b79e2017-01-24 15:14:52 +0000607 def test_use_privatekey_file_missing(self, tmpfile):
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800608 """
Alex Chan532b79e2017-01-24 15:14:52 +0000609 `Context.use_privatekey_file` raises `OpenSSL.SSL.Error` when passed
610 the name of a file which does not exist.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800611 """
612 ctx = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000613 with pytest.raises(Error):
614 ctx.use_privatekey_file(tmpfile)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800615
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400616 def _use_privatekey_file_test(self, pemfile, filetype):
617 """
618 Verify that calling ``Context.use_privatekey_file`` with the given
619 arguments does not raise an exception.
620 """
621 key = PKey()
Alex Gaynor6e9f9762018-05-12 07:44:37 -0400622 key.generate_key(TYPE_RSA, 512)
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400623
624 with open(pemfile, "wt") as pem:
Alex Gaynor03737182020-07-23 20:40:46 -0400625 pem.write(dump_privatekey(FILETYPE_PEM, key).decode("ascii"))
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400626
627 ctx = Context(TLSv1_METHOD)
628 ctx.use_privatekey_file(pemfile, filetype)
629
Alex Gaynor03737182020-07-23 20:40:46 -0400630 @pytest.mark.parametrize("filetype", [object(), "", None, 1.0])
Alex Chanfb078d82017-04-20 11:16:15 +0100631 def test_wrong_privatekey_file_wrong_args(self, tmpfile, filetype):
632 """
633 `Context.use_privatekey_file` raises `TypeError` when called with
634 a `filetype` which is not a valid file encoding.
635 """
636 ctx = Context(TLSv1_METHOD)
637 with pytest.raises(TypeError):
638 ctx.use_privatekey_file(tmpfile, filetype)
639
Alex Chan532b79e2017-01-24 15:14:52 +0000640 def test_use_privatekey_file_bytes(self, tmpfile):
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400641 """
642 A private key can be specified from a file by passing a ``bytes``
643 instance giving the file name to ``Context.use_privatekey_file``.
644 """
645 self._use_privatekey_file_test(
Alex Gaynor03737182020-07-23 20:40:46 -0400646 tmpfile + NON_ASCII.encode(getfilesystemencoding()), FILETYPE_PEM,
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400647 )
648
Alex Chan532b79e2017-01-24 15:14:52 +0000649 def test_use_privatekey_file_unicode(self, tmpfile):
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400650 """
651 A private key can be specified from a file by passing a ``unicode``
652 instance giving the file name to ``Context.use_privatekey_file``.
653 """
654 self._use_privatekey_file_test(
Alex Gaynor03737182020-07-23 20:40:46 -0400655 tmpfile.decode(getfilesystemencoding()) + NON_ASCII, FILETYPE_PEM,
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400656 )
657
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800658 def test_use_certificate_wrong_args(self):
659 """
Alex Chan532b79e2017-01-24 15:14:52 +0000660 `Context.use_certificate_wrong_args` raises `TypeError` when not passed
661 exactly one `OpenSSL.crypto.X509` instance as an argument.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800662 """
663 ctx = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000664 with pytest.raises(TypeError):
665 ctx.use_certificate("hello, world")
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800666
667 def test_use_certificate_uninitialized(self):
668 """
Alex Chan532b79e2017-01-24 15:14:52 +0000669 `Context.use_certificate` raises `OpenSSL.SSL.Error` when passed a
670 `OpenSSL.crypto.X509` instance which has not been initialized
671 (ie, which does not actually have any certificate data).
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800672 """
673 ctx = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000674 with pytest.raises(Error):
675 ctx.use_certificate(X509())
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800676
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800677 def test_use_certificate(self):
678 """
Alex Chan532b79e2017-01-24 15:14:52 +0000679 `Context.use_certificate` sets the certificate which will be
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800680 used to identify connections created using the context.
681 """
682 # TODO
683 # Hard to assert anything. But we could set a privatekey then ask
684 # OpenSSL if the cert and key agree using check_privatekey. Then as
685 # long as check_privatekey works right we're good...
686 ctx = Context(TLSv1_METHOD)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200687 ctx.use_certificate(
688 load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
689 )
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800690
691 def test_use_certificate_file_wrong_args(self):
692 """
Alex Chan532b79e2017-01-24 15:14:52 +0000693 `Context.use_certificate_file` raises `TypeError` if the first
694 argument is not a byte string or the second argument is not an integer.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800695 """
696 ctx = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000697 with pytest.raises(TypeError):
698 ctx.use_certificate_file(object(), FILETYPE_PEM)
699 with pytest.raises(TypeError):
700 ctx.use_certificate_file(b"somefile", object())
701 with pytest.raises(TypeError):
702 ctx.use_certificate_file(object(), FILETYPE_PEM)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800703
Alex Chan532b79e2017-01-24 15:14:52 +0000704 def test_use_certificate_file_missing(self, tmpfile):
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800705 """
Alex Chan532b79e2017-01-24 15:14:52 +0000706 `Context.use_certificate_file` raises `OpenSSL.SSL.Error` if passed
707 the name of a file which does not exist.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800708 """
709 ctx = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000710 with pytest.raises(Error):
711 ctx.use_certificate_file(tmpfile)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800712
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400713 def _use_certificate_file_test(self, certificate_file):
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800714 """
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400715 Verify that calling ``Context.use_certificate_file`` with the given
716 filename doesn't raise an exception.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800717 """
718 # TODO
719 # Hard to assert anything. But we could set a privatekey then ask
720 # OpenSSL if the cert and key agree using check_privatekey. Then as
721 # long as check_privatekey works right we're good...
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400722 with open(certificate_file, "wb") as pem_file:
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800723 pem_file.write(cleartextCertificatePEM)
724
725 ctx = Context(TLSv1_METHOD)
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400726 ctx.use_certificate_file(certificate_file)
727
Alex Chan532b79e2017-01-24 15:14:52 +0000728 def test_use_certificate_file_bytes(self, tmpfile):
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400729 """
Alex Chan532b79e2017-01-24 15:14:52 +0000730 `Context.use_certificate_file` sets the certificate (given as a
731 `bytes` filename) which will be used to identify connections created
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400732 using the context.
733 """
Alex Chan532b79e2017-01-24 15:14:52 +0000734 filename = tmpfile + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400735 self._use_certificate_file_test(filename)
736
Alex Chan532b79e2017-01-24 15:14:52 +0000737 def test_use_certificate_file_unicode(self, tmpfile):
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400738 """
Alex Chan532b79e2017-01-24 15:14:52 +0000739 `Context.use_certificate_file` sets the certificate (given as a
740 `bytes` filename) which will be used to identify connections created
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400741 using the context.
742 """
Alex Chan532b79e2017-01-24 15:14:52 +0000743 filename = tmpfile.decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400744 self._use_certificate_file_test(filename)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800745
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500746 def test_check_privatekey_valid(self):
747 """
Alex Chan532b79e2017-01-24 15:14:52 +0000748 `Context.check_privatekey` returns `None` if the `Context` instance
749 has been configured to use a matched key and certificate pair.
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500750 """
751 key = load_privatekey(FILETYPE_PEM, client_key_pem)
752 cert = load_certificate(FILETYPE_PEM, client_cert_pem)
753 context = Context(TLSv1_METHOD)
754 context.use_privatekey(key)
755 context.use_certificate(cert)
Alex Chan532b79e2017-01-24 15:14:52 +0000756 assert None is context.check_privatekey()
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500757
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500758 def test_check_privatekey_invalid(self):
759 """
Alex Chan532b79e2017-01-24 15:14:52 +0000760 `Context.check_privatekey` raises `Error` if the `Context` instance
761 has been configured to use a key and certificate pair which don't
762 relate to each other.
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500763 """
764 key = load_privatekey(FILETYPE_PEM, client_key_pem)
765 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
766 context = Context(TLSv1_METHOD)
767 context.use_privatekey(key)
768 context.use_certificate(cert)
Alex Chan532b79e2017-01-24 15:14:52 +0000769 with pytest.raises(Error):
770 context.check_privatekey()
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400771
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400772 def test_app_data(self):
773 """
Alex Chan532b79e2017-01-24 15:14:52 +0000774 `Context.set_app_data` stores an object for later retrieval
775 using `Context.get_app_data`.
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400776 """
777 app_data = object()
778 context = Context(TLSv1_METHOD)
779 context.set_app_data(app_data)
Alex Chan532b79e2017-01-24 15:14:52 +0000780 assert context.get_app_data() is app_data
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400781
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400782 def test_set_options_wrong_args(self):
783 """
Alex Chan532b79e2017-01-24 15:14:52 +0000784 `Context.set_options` raises `TypeError` if called with
785 a non-`int` argument.
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400786 """
787 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000788 with pytest.raises(TypeError):
789 context.set_options(None)
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400790
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500791 def test_set_options(self):
792 """
Alex Chan532b79e2017-01-24 15:14:52 +0000793 `Context.set_options` returns the new options value.
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500794 """
795 context = Context(TLSv1_METHOD)
796 options = context.set_options(OP_NO_SSLv2)
Alex Gaynor2310f8b2016-09-10 14:39:32 -0400797 assert options & OP_NO_SSLv2 == OP_NO_SSLv2
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500798
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300799 def test_set_mode_wrong_args(self):
800 """
Alex Chan532b79e2017-01-24 15:14:52 +0000801 `Context.set_mode` raises `TypeError` if called with
802 a non-`int` argument.
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300803 """
804 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000805 with pytest.raises(TypeError):
806 context.set_mode(None)
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300807
Alex Gaynord3b5d9b2016-07-31 10:54:24 -0400808 def test_set_mode(self):
809 """
Alex Chan532b79e2017-01-24 15:14:52 +0000810 `Context.set_mode` accepts a mode bitvector and returns the
Alex Gaynord3b5d9b2016-07-31 10:54:24 -0400811 newly set mode.
812 """
813 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000814 assert MODE_RELEASE_BUFFERS & context.set_mode(MODE_RELEASE_BUFFERS)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500815
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400816 def test_set_timeout_wrong_args(self):
817 """
Alex Chan532b79e2017-01-24 15:14:52 +0000818 `Context.set_timeout` raises `TypeError` if called with
819 a non-`int` argument.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400820 """
821 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000822 with pytest.raises(TypeError):
823 context.set_timeout(None)
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400824
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400825 def test_timeout(self):
826 """
Alex Chan532b79e2017-01-24 15:14:52 +0000827 `Context.set_timeout` sets the session timeout for all connections
828 created using the context object. `Context.get_timeout` retrieves
829 this value.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400830 """
831 context = Context(TLSv1_METHOD)
832 context.set_timeout(1234)
Alex Chan532b79e2017-01-24 15:14:52 +0000833 assert context.get_timeout() == 1234
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400834
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400835 def test_set_verify_depth_wrong_args(self):
836 """
Alex Chan532b79e2017-01-24 15:14:52 +0000837 `Context.set_verify_depth` raises `TypeError` if called with a
838 non-`int` argument.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400839 """
840 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000841 with pytest.raises(TypeError):
842 context.set_verify_depth(None)
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400843
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400844 def test_verify_depth(self):
845 """
Alex Chan532b79e2017-01-24 15:14:52 +0000846 `Context.set_verify_depth` sets the number of certificates in
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200847 a chain to follow before giving up. The value can be retrieved with
Alex Chan532b79e2017-01-24 15:14:52 +0000848 `Context.get_verify_depth`.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400849 """
850 context = Context(TLSv1_METHOD)
851 context.set_verify_depth(11)
Alex Chan532b79e2017-01-24 15:14:52 +0000852 assert context.get_verify_depth() == 11
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400853
Alex Chan532b79e2017-01-24 15:14:52 +0000854 def _write_encrypted_pem(self, passphrase, tmpfile):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400855 """
856 Write a new private key out to a new file, encrypted using the given
857 passphrase. Return the path to the new file.
858 """
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400859 key = PKey()
Alex Gaynor6e9f9762018-05-12 07:44:37 -0400860 key.generate_key(TYPE_RSA, 512)
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400861 pem = dump_privatekey(FILETYPE_PEM, key, "blowfish", passphrase)
Alex Gaynor03737182020-07-23 20:40:46 -0400862 with open(tmpfile, "w") as fObj:
863 fObj.write(pem.decode("ascii"))
Alex Chan532b79e2017-01-24 15:14:52 +0000864 return tmpfile
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400865
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400866 def test_set_passwd_cb_wrong_args(self):
867 """
Alex Chan532b79e2017-01-24 15:14:52 +0000868 `Context.set_passwd_cb` raises `TypeError` if called with a
869 non-callable first argument.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400870 """
871 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000872 with pytest.raises(TypeError):
873 context.set_passwd_cb(None)
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400874
Alex Chan532b79e2017-01-24 15:14:52 +0000875 def test_set_passwd_cb(self, tmpfile):
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400876 """
Alex Chan532b79e2017-01-24 15:14:52 +0000877 `Context.set_passwd_cb` accepts a callable which will be invoked when
878 a private key is loaded from an encrypted PEM.
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400879 """
Alex Gaynore7f51982016-09-11 11:48:14 -0400880 passphrase = b"foobar"
Alex Chan532b79e2017-01-24 15:14:52 +0000881 pemFile = self._write_encrypted_pem(passphrase, tmpfile)
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400882 calledWith = []
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200883
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400884 def passphraseCallback(maxlen, verify, extra):
885 calledWith.append((maxlen, verify, extra))
886 return passphrase
Alex Gaynor03737182020-07-23 20:40:46 -0400887
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400888 context = Context(TLSv1_METHOD)
889 context.set_passwd_cb(passphraseCallback)
890 context.use_privatekey_file(pemFile)
Alex Chan532b79e2017-01-24 15:14:52 +0000891 assert len(calledWith) == 1
892 assert isinstance(calledWith[0][0], int)
893 assert isinstance(calledWith[0][1], int)
894 assert calledWith[0][2] is None
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400895
Alex Chan532b79e2017-01-24 15:14:52 +0000896 def test_passwd_callback_exception(self, tmpfile):
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400897 """
Alex Chan532b79e2017-01-24 15:14:52 +0000898 `Context.use_privatekey_file` propagates any exception raised
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200899 by the passphrase callback.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400900 """
Alex Chan532b79e2017-01-24 15:14:52 +0000901 pemFile = self._write_encrypted_pem(b"monkeys are nice", tmpfile)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200902
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400903 def passphraseCallback(maxlen, verify, extra):
904 raise RuntimeError("Sorry, I am a fail.")
905
906 context = Context(TLSv1_METHOD)
907 context.set_passwd_cb(passphraseCallback)
Alex Chan532b79e2017-01-24 15:14:52 +0000908 with pytest.raises(RuntimeError):
909 context.use_privatekey_file(pemFile)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400910
Alex Chan532b79e2017-01-24 15:14:52 +0000911 def test_passwd_callback_false(self, tmpfile):
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400912 """
Alex Chan532b79e2017-01-24 15:14:52 +0000913 `Context.use_privatekey_file` raises `OpenSSL.SSL.Error` if the
914 passphrase callback returns a false value.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400915 """
Alex Chan532b79e2017-01-24 15:14:52 +0000916 pemFile = self._write_encrypted_pem(b"monkeys are nice", tmpfile)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200917
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400918 def passphraseCallback(maxlen, verify, extra):
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500919 return b""
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400920
921 context = Context(TLSv1_METHOD)
922 context.set_passwd_cb(passphraseCallback)
Alex Chan532b79e2017-01-24 15:14:52 +0000923 with pytest.raises(Error):
924 context.use_privatekey_file(pemFile)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400925
Alex Chan532b79e2017-01-24 15:14:52 +0000926 def test_passwd_callback_non_string(self, tmpfile):
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400927 """
Alex Chan532b79e2017-01-24 15:14:52 +0000928 `Context.use_privatekey_file` raises `OpenSSL.SSL.Error` if the
929 passphrase callback returns a true non-string value.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400930 """
Alex Chan532b79e2017-01-24 15:14:52 +0000931 pemFile = self._write_encrypted_pem(b"monkeys are nice", tmpfile)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200932
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400933 def passphraseCallback(maxlen, verify, extra):
934 return 10
935
936 context = Context(TLSv1_METHOD)
937 context.set_passwd_cb(passphraseCallback)
Alex Chan532b79e2017-01-24 15:14:52 +0000938 # TODO: Surely this is the wrong error?
939 with pytest.raises(ValueError):
940 context.use_privatekey_file(pemFile)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400941
Alex Chan532b79e2017-01-24 15:14:52 +0000942 def test_passwd_callback_too_long(self, tmpfile):
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400943 """
944 If the passphrase returned by the passphrase callback returns a string
945 longer than the indicated maximum length, it is truncated.
946 """
947 # A priori knowledge!
Alex Gaynore7f51982016-09-11 11:48:14 -0400948 passphrase = b"x" * 1024
Alex Chan532b79e2017-01-24 15:14:52 +0000949 pemFile = self._write_encrypted_pem(passphrase, tmpfile)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200950
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400951 def passphraseCallback(maxlen, verify, extra):
952 assert maxlen == 1024
Alex Gaynore7f51982016-09-11 11:48:14 -0400953 return passphrase + b"y"
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400954
955 context = Context(TLSv1_METHOD)
956 context.set_passwd_cb(passphraseCallback)
957 # This shall succeed because the truncated result is the correct
958 # passphrase.
959 context.use_privatekey_file(pemFile)
960
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400961 def test_set_info_callback(self):
962 """
Alex Chan532b79e2017-01-24 15:14:52 +0000963 `Context.set_info_callback` accepts a callable which will be
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200964 invoked when certain information about an SSL connection is available.
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400965 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500966 (server, client) = socket_pair()
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400967
968 clientSSL = Connection(Context(TLSv1_METHOD), client)
969 clientSSL.set_connect_state()
970
971 called = []
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200972
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400973 def info(conn, where, ret):
974 called.append((conn, where, ret))
Alex Gaynor03737182020-07-23 20:40:46 -0400975
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400976 context = Context(TLSv1_METHOD)
977 context.set_info_callback(info)
978 context.use_certificate(
Alex Gaynor03737182020-07-23 20:40:46 -0400979 load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
980 )
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400981 context.use_privatekey(
Alex Gaynor03737182020-07-23 20:40:46 -0400982 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
983 )
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400984
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400985 serverSSL = Connection(context, server)
986 serverSSL.set_accept_state()
987
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -0500988 handshake(clientSSL, serverSSL)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400989
Jean-Paul Calderone3835e522014-02-02 11:12:30 -0500990 # The callback must always be called with a Connection instance as the
991 # first argument. It would probably be better to split this into
992 # separate tests for client and server side info callbacks so we could
993 # assert it is called with the right Connection instance. It would
994 # also be good to assert *something* about `where` and `ret`.
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -0500995 notConnections = [
Alex Gaynor03737182020-07-23 20:40:46 -0400996 conn
997 for (conn, where, ret) in called
998 if not isinstance(conn, Connection)
999 ]
1000 assert (
1001 [] == notConnections
1002 ), "Some info callback arguments were not Connection instances."
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001003
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001004 def _load_verify_locations_test(self, *args):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001005 """
1006 Create a client context which will verify the peer certificate and call
Alex Chan532b79e2017-01-24 15:14:52 +00001007 its `load_verify_locations` method with the given arguments.
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04001008 Then connect it to a server and ensure that the handshake succeeds.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001009 """
Rick Deanb1ccd562009-07-09 23:52:39 -05001010 (server, client) = socket_pair()
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001011
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001012 clientContext = Context(TLSv1_METHOD)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001013 clientContext.load_verify_locations(*args)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001014 # Require that the server certificate verify properly or the
1015 # connection will fail.
1016 clientContext.set_verify(
1017 VERIFY_PEER,
Alex Gaynor03737182020-07-23 20:40:46 -04001018 lambda conn, cert, errno, depth, preverify_ok: preverify_ok,
1019 )
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001020
1021 clientSSL = Connection(clientContext, client)
1022 clientSSL.set_connect_state()
1023
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001024 serverContext = Context(TLSv1_METHOD)
1025 serverContext.use_certificate(
Alex Gaynor03737182020-07-23 20:40:46 -04001026 load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
1027 )
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001028 serverContext.use_privatekey(
Alex Gaynor03737182020-07-23 20:40:46 -04001029 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
1030 )
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001031
1032 serverSSL = Connection(serverContext, server)
1033 serverSSL.set_accept_state()
1034
Jean-Paul Calderonef8742032010-09-25 00:00:32 -04001035 # Without load_verify_locations above, the handshake
1036 # will fail:
1037 # Error: [('SSL routines', 'SSL3_GET_SERVER_CERTIFICATE',
1038 # 'certificate verify failed')]
1039 handshake(clientSSL, serverSSL)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001040
1041 cert = clientSSL.get_peer_certificate()
Alex Gaynor03737182020-07-23 20:40:46 -04001042 assert cert.get_subject().CN == "Testing Root CA"
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -04001043
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001044 def _load_verify_cafile(self, cafile):
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001045 """
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001046 Verify that if path to a file containing a certificate is passed to
Alex Chan532b79e2017-01-24 15:14:52 +00001047 `Context.load_verify_locations` for the ``cafile`` parameter, that
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001048 certificate is used as a trust root for the purposes of verifying
Alex Chan532b79e2017-01-24 15:14:52 +00001049 connections created using that `Context`.
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001050 """
Alex Gaynor03737182020-07-23 20:40:46 -04001051 with open(cafile, "w") as fObj:
1052 fObj.write(cleartextCertificatePEM.decode("ascii"))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001053
1054 self._load_verify_locations_test(cafile)
1055
Alex Chan532b79e2017-01-24 15:14:52 +00001056 def test_load_verify_bytes_cafile(self, tmpfile):
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001057 """
Alex Chan532b79e2017-01-24 15:14:52 +00001058 `Context.load_verify_locations` accepts a file name as a `bytes`
1059 instance and uses the certificates within for verification purposes.
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001060 """
Alex Chan532b79e2017-01-24 15:14:52 +00001061 cafile = tmpfile + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001062 self._load_verify_cafile(cafile)
1063
Alex Chan532b79e2017-01-24 15:14:52 +00001064 def test_load_verify_unicode_cafile(self, tmpfile):
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001065 """
Alex Chan532b79e2017-01-24 15:14:52 +00001066 `Context.load_verify_locations` accepts a file name as a `unicode`
1067 instance and uses the certificates within for verification purposes.
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001068 """
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001069 self._load_verify_cafile(
Alex Chan532b79e2017-01-24 15:14:52 +00001070 tmpfile.decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001071 )
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001072
Alex Chan532b79e2017-01-24 15:14:52 +00001073 def test_load_verify_invalid_file(self, tmpfile):
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -04001074 """
Alex Chan532b79e2017-01-24 15:14:52 +00001075 `Context.load_verify_locations` raises `Error` when passed a
1076 non-existent cafile.
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -04001077 """
1078 clientContext = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001079 with pytest.raises(Error):
1080 clientContext.load_verify_locations(tmpfile)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001081
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001082 def _load_verify_directory_locations_capath(self, capath):
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001083 """
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001084 Verify that if path to a directory containing certificate files is
1085 passed to ``Context.load_verify_locations`` for the ``capath``
1086 parameter, those certificates are used as trust roots for the purposes
1087 of verifying connections created using that ``Context``.
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001088 """
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001089 makedirs(capath)
Jean-Paul Calderone24dfb332011-05-04 18:10:26 -04001090 # Hash values computed manually with c_rehash to avoid depending on
1091 # c_rehash in the test suite. One is from OpenSSL 0.9.8, the other
1092 # from OpenSSL 1.0.0.
Alex Gaynor03737182020-07-23 20:40:46 -04001093 for name in [b"c7adac82.0", b"c3705638.0"]:
Jean-Paul Calderone05826732015-04-12 11:38:49 -04001094 cafile = join_bytes_or_unicode(capath, name)
Alex Gaynor03737182020-07-23 20:40:46 -04001095 with open(cafile, "w") as fObj:
1096 fObj.write(cleartextCertificatePEM.decode("ascii"))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001097
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001098 self._load_verify_locations_test(None, capath)
1099
Alex Chan532b79e2017-01-24 15:14:52 +00001100 def test_load_verify_directory_bytes_capath(self, tmpfile):
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001101 """
Alex Chan532b79e2017-01-24 15:14:52 +00001102 `Context.load_verify_locations` accepts a directory name as a `bytes`
1103 instance and uses the certificates within for verification purposes.
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001104 """
1105 self._load_verify_directory_locations_capath(
Alex Chan532b79e2017-01-24 15:14:52 +00001106 tmpfile + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001107 )
1108
Alex Chan532b79e2017-01-24 15:14:52 +00001109 def test_load_verify_directory_unicode_capath(self, tmpfile):
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001110 """
Alex Chan532b79e2017-01-24 15:14:52 +00001111 `Context.load_verify_locations` accepts a directory name as a `unicode`
1112 instance and uses the certificates within for verification purposes.
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001113 """
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001114 self._load_verify_directory_locations_capath(
Alex Chan532b79e2017-01-24 15:14:52 +00001115 tmpfile.decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001116 )
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001117
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001118 def test_load_verify_locations_wrong_args(self):
1119 """
Alex Chan532b79e2017-01-24 15:14:52 +00001120 `Context.load_verify_locations` raises `TypeError` if with non-`str`
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001121 arguments.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001122 """
1123 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001124 with pytest.raises(TypeError):
1125 context.load_verify_locations(object())
1126 with pytest.raises(TypeError):
1127 context.load_verify_locations(object(), object())
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001128
Hynek Schlawack734d3022015-09-05 19:19:32 +02001129 @pytest.mark.skipif(
Paul Kehrer55fb3412017-06-29 18:44:08 -05001130 not platform.startswith("linux"),
1131 reason="Loading fallback paths is a linux-specific behavior to "
Alex Gaynor03737182020-07-23 20:40:46 -04001132 "accommodate pyca/cryptography manylinux1 wheels",
Paul Kehrer55fb3412017-06-29 18:44:08 -05001133 )
1134 def test_fallback_default_verify_paths(self, monkeypatch):
1135 """
1136 Test that we load certificates successfully on linux from the fallback
1137 path. To do this we set the _CRYPTOGRAPHY_MANYLINUX1_CA_FILE and
1138 _CRYPTOGRAPHY_MANYLINUX1_CA_DIR vars to be equal to whatever the
1139 current OpenSSL default is and we disable
1140 SSL_CTX_SET_default_verify_paths so that it can't find certs unless
1141 it loads via fallback.
1142 """
1143 context = Context(TLSv1_METHOD)
1144 monkeypatch.setattr(
1145 _lib, "SSL_CTX_set_default_verify_paths", lambda x: 1
1146 )
1147 monkeypatch.setattr(
1148 SSL,
1149 "_CRYPTOGRAPHY_MANYLINUX1_CA_FILE",
Alex Gaynor03737182020-07-23 20:40:46 -04001150 _ffi.string(_lib.X509_get_default_cert_file()),
Paul Kehrer55fb3412017-06-29 18:44:08 -05001151 )
1152 monkeypatch.setattr(
1153 SSL,
1154 "_CRYPTOGRAPHY_MANYLINUX1_CA_DIR",
Alex Gaynor03737182020-07-23 20:40:46 -04001155 _ffi.string(_lib.X509_get_default_cert_dir()),
Paul Kehrer55fb3412017-06-29 18:44:08 -05001156 )
1157 context.set_default_verify_paths()
1158 store = context.get_cert_store()
1159 sk_obj = _lib.X509_STORE_get0_objects(store._store)
1160 assert sk_obj != _ffi.NULL
1161 num = _lib.sk_X509_OBJECT_num(sk_obj)
1162 assert num != 0
1163
1164 def test_check_env_vars(self, monkeypatch):
1165 """
1166 Test that we return True/False appropriately if the env vars are set.
1167 """
1168 context = Context(TLSv1_METHOD)
1169 dir_var = "CUSTOM_DIR_VAR"
1170 file_var = "CUSTOM_FILE_VAR"
1171 assert context._check_env_vars_set(dir_var, file_var) is False
1172 monkeypatch.setenv(dir_var, "value")
1173 monkeypatch.setenv(file_var, "value")
1174 assert context._check_env_vars_set(dir_var, file_var) is True
1175 assert context._check_env_vars_set(dir_var, file_var) is True
1176
1177 def test_verify_no_fallback_if_env_vars_set(self, monkeypatch):
1178 """
1179 Test that we don't use the fallback path if env vars are set.
1180 """
1181 context = Context(TLSv1_METHOD)
1182 monkeypatch.setattr(
1183 _lib, "SSL_CTX_set_default_verify_paths", lambda x: 1
1184 )
Alex Gaynor03737182020-07-23 20:40:46 -04001185 dir_env_var = _ffi.string(_lib.X509_get_default_cert_dir_env()).decode(
1186 "ascii"
1187 )
Paul Kehrer55fb3412017-06-29 18:44:08 -05001188 file_env_var = _ffi.string(
1189 _lib.X509_get_default_cert_file_env()
1190 ).decode("ascii")
1191 monkeypatch.setenv(dir_env_var, "value")
1192 monkeypatch.setenv(file_env_var, "value")
1193 context.set_default_verify_paths()
1194
1195 monkeypatch.setattr(
Alex Gaynor03737182020-07-23 20:40:46 -04001196 context, "_fallback_default_verify_paths", raiser(SystemError)
Paul Kehrer55fb3412017-06-29 18:44:08 -05001197 )
1198 context.set_default_verify_paths()
1199
1200 @pytest.mark.skipif(
Hynek Schlawack734d3022015-09-05 19:19:32 +02001201 platform == "win32",
1202 reason="set_default_verify_paths appears not to work on Windows. "
Alex Gaynor03737182020-07-23 20:40:46 -04001203 "See LP#404343 and LP#404344.",
Hynek Schlawack734d3022015-09-05 19:19:32 +02001204 )
1205 def test_set_default_verify_paths(self):
1206 """
Alex Chan532b79e2017-01-24 15:14:52 +00001207 `Context.set_default_verify_paths` causes the platform-specific CA
1208 certificate locations to be used for verification purposes.
Hynek Schlawack734d3022015-09-05 19:19:32 +02001209 """
1210 # Testing this requires a server with a certificate signed by one
1211 # of the CAs in the platform CA location. Getting one of those
1212 # costs money. Fortunately (or unfortunately, depending on your
1213 # perspective), it's easy to think of a public server on the
1214 # internet which has such a certificate. Connecting to the network
1215 # in a unit test is bad, but it's the only way I can think of to
1216 # really test this. -exarkun
Hynek Schlawackbf887932015-10-21 17:13:47 +02001217 context = Context(SSLv23_METHOD)
Hynek Schlawack734d3022015-09-05 19:19:32 +02001218 context.set_default_verify_paths()
1219 context.set_verify(
1220 VERIFY_PEER,
Alex Gaynor03737182020-07-23 20:40:46 -04001221 lambda conn, cert, errno, depth, preverify_ok: preverify_ok,
1222 )
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001223
David Benjamin1fbe0642019-04-15 17:05:13 -05001224 client = socket_any_family()
Hynek Schlawackbf887932015-10-21 17:13:47 +02001225 client.connect(("encrypted.google.com", 443))
Hynek Schlawack734d3022015-09-05 19:19:32 +02001226 clientSSL = Connection(context, client)
1227 clientSSL.set_connect_state()
Alex Gaynor373926c2018-05-12 07:43:07 -04001228 clientSSL.set_tlsext_host_name(b"encrypted.google.com")
Hynek Schlawack734d3022015-09-05 19:19:32 +02001229 clientSSL.do_handshake()
1230 clientSSL.send(b"GET / HTTP/1.0\r\n\r\n")
Alex Chan532b79e2017-01-24 15:14:52 +00001231 assert clientSSL.recv(1024)
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05001232
Paul Kehrer55fb3412017-06-29 18:44:08 -05001233 def test_fallback_path_is_not_file_or_dir(self):
1234 """
1235 Test that when passed empty arrays or paths that do not exist no
1236 errors are raised.
1237 """
1238 context = Context(TLSv1_METHOD)
1239 context._fallback_default_verify_paths([], [])
Alex Gaynor03737182020-07-23 20:40:46 -04001240 context._fallback_default_verify_paths(["/not/a/file"], ["/not/a/dir"])
Paul Kehrer55fb3412017-06-29 18:44:08 -05001241
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001242 def test_add_extra_chain_cert_invalid_cert(self):
1243 """
Alex Chan532b79e2017-01-24 15:14:52 +00001244 `Context.add_extra_chain_cert` raises `TypeError` if called with an
1245 object which is not an instance of `X509`.
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001246 """
1247 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001248 with pytest.raises(TypeError):
1249 context.add_extra_chain_cert(object())
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001250
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001251 def _handshake_test(self, serverContext, clientContext):
1252 """
1253 Verify that a client and server created with the given contexts can
1254 successfully handshake and communicate.
1255 """
1256 serverSocket, clientSocket = socket_pair()
1257
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001258 server = Connection(serverContext, serverSocket)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001259 server.set_accept_state()
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001260
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001261 client = Connection(clientContext, clientSocket)
1262 client.set_connect_state()
1263
1264 # Make them talk to each other.
Alex Chan532b79e2017-01-24 15:14:52 +00001265 # interact_in_memory(client, server)
1266 for _ in range(3):
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001267 for s in [client, server]:
1268 try:
1269 s.do_handshake()
1270 except WantReadError:
1271 pass
1272
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001273 def test_set_verify_callback_connection_argument(self):
1274 """
1275 The first argument passed to the verify callback is the
Alex Chan532b79e2017-01-24 15:14:52 +00001276 `Connection` instance for which verification is taking place.
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001277 """
1278 serverContext = Context(TLSv1_METHOD)
1279 serverContext.use_privatekey(
Alex Gaynor03737182020-07-23 20:40:46 -04001280 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
1281 )
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001282 serverContext.use_certificate(
Alex Gaynor03737182020-07-23 20:40:46 -04001283 load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
1284 )
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001285 serverConnection = Connection(serverContext, None)
1286
1287 class VerifyCallback(object):
1288 def callback(self, connection, *args):
1289 self.connection = connection
1290 return 1
1291
1292 verify = VerifyCallback()
1293 clientContext = Context(TLSv1_METHOD)
1294 clientContext.set_verify(VERIFY_PEER, verify.callback)
1295 clientConnection = Connection(clientContext, None)
1296 clientConnection.set_connect_state()
1297
Alex Chan532b79e2017-01-24 15:14:52 +00001298 handshake_in_memory(clientConnection, serverConnection)
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001299
Alex Chan532b79e2017-01-24 15:14:52 +00001300 assert verify.connection is clientConnection
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001301
Paul Kehrere7381862017-11-30 20:55:25 +08001302 def test_x509_in_verify_works(self):
1303 """
1304 We had a bug where the X509 cert instantiated in the callback wrapper
1305 didn't __init__ so it was missing objects needed when calling
1306 get_subject. This test sets up a handshake where we call get_subject
1307 on the cert provided to the verify callback.
1308 """
1309 serverContext = Context(TLSv1_METHOD)
1310 serverContext.use_privatekey(
Alex Gaynor03737182020-07-23 20:40:46 -04001311 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
1312 )
Paul Kehrere7381862017-11-30 20:55:25 +08001313 serverContext.use_certificate(
Alex Gaynor03737182020-07-23 20:40:46 -04001314 load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
1315 )
Paul Kehrere7381862017-11-30 20:55:25 +08001316 serverConnection = Connection(serverContext, None)
1317
1318 def verify_cb_get_subject(conn, cert, errnum, depth, ok):
1319 assert cert.get_subject()
1320 return 1
1321
1322 clientContext = Context(TLSv1_METHOD)
1323 clientContext.set_verify(VERIFY_PEER, verify_cb_get_subject)
1324 clientConnection = Connection(clientContext, None)
1325 clientConnection.set_connect_state()
1326
1327 handshake_in_memory(clientConnection, serverConnection)
1328
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001329 def test_set_verify_callback_exception(self):
1330 """
Alex Chan532b79e2017-01-24 15:14:52 +00001331 If the verify callback passed to `Context.set_verify` raises an
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001332 exception, verification fails and the exception is propagated to the
Alex Chan532b79e2017-01-24 15:14:52 +00001333 caller of `Connection.do_handshake`.
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001334 """
Paul Kehrer7d5a3bf2019-01-21 12:24:02 -06001335 serverContext = Context(TLSv1_2_METHOD)
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001336 serverContext.use_privatekey(
Alex Gaynor03737182020-07-23 20:40:46 -04001337 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
1338 )
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001339 serverContext.use_certificate(
Alex Gaynor03737182020-07-23 20:40:46 -04001340 load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
1341 )
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001342
Paul Kehrer7d5a3bf2019-01-21 12:24:02 -06001343 clientContext = Context(TLSv1_2_METHOD)
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001344
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001345 def verify_callback(*args):
1346 raise Exception("silly verify failure")
Alex Gaynor03737182020-07-23 20:40:46 -04001347
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001348 clientContext.set_verify(VERIFY_PEER, verify_callback)
1349
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01001350 with pytest.raises(Exception) as exc:
1351 self._handshake_test(serverContext, clientContext)
1352
Alex Chan532b79e2017-01-24 15:14:52 +00001353 assert "silly verify failure" == str(exc.value)
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001354
Alex Chan532b79e2017-01-24 15:14:52 +00001355 def test_add_extra_chain_cert(self, tmpdir):
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001356 """
Alex Chan532b79e2017-01-24 15:14:52 +00001357 `Context.add_extra_chain_cert` accepts an `X509`
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001358 instance to add to the certificate chain.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001359
Alex Chan532b79e2017-01-24 15:14:52 +00001360 See `_create_certificate_chain` for the details of the
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001361 certificate chain tested.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001362
1363 The chain is tested by starting a server with scert and connecting
1364 to it with a client which trusts cacert and requires verification to
1365 succeed.
1366 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001367 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001368 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1369
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001370 # Dump the CA certificate to a file because that's the only way to load
1371 # it as a trusted CA in the client context.
Alex Gaynor03737182020-07-23 20:40:46 -04001372 for cert, name in [
1373 (cacert, "ca.pem"),
1374 (icert, "i.pem"),
1375 (scert, "s.pem"),
1376 ]:
1377 with tmpdir.join(name).open("w") as f:
1378 f.write(dump_certificate(FILETYPE_PEM, cert).decode("ascii"))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001379
Alex Gaynor03737182020-07-23 20:40:46 -04001380 for key, name in [(cakey, "ca.key"), (ikey, "i.key"), (skey, "s.key")]:
1381 with tmpdir.join(name).open("w") as f:
1382 f.write(dump_privatekey(FILETYPE_PEM, key).decode("ascii"))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001383
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001384 # Create the server context
1385 serverContext = Context(TLSv1_METHOD)
1386 serverContext.use_privatekey(skey)
1387 serverContext.use_certificate(scert)
Jean-Paul Calderone16cf03d2010-09-08 18:53:39 -04001388 # The client already has cacert, we only need to give them icert.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001389 serverContext.add_extra_chain_cert(icert)
1390
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001391 # Create the client
1392 clientContext = Context(TLSv1_METHOD)
1393 clientContext.set_verify(
Alex Gaynor03737182020-07-23 20:40:46 -04001394 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb
1395 )
Alex Chan532b79e2017-01-24 15:14:52 +00001396 clientContext.load_verify_locations(str(tmpdir.join("ca.pem")))
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001397
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001398 # Try it out.
1399 self._handshake_test(serverContext, clientContext)
1400
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001401 def _use_certificate_chain_file_test(self, certdir):
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001402 """
Alex Chan532b79e2017-01-24 15:14:52 +00001403 Verify that `Context.use_certificate_chain_file` reads a
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001404 certificate chain from a specified file.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001405
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001406 The chain is tested by starting a server with scert and connecting to
1407 it with a client which trusts cacert and requires verification to
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001408 succeed.
1409 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001410 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001411 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1412
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001413 makedirs(certdir)
1414
Jean-Paul Calderone05826732015-04-12 11:38:49 -04001415 chainFile = join_bytes_or_unicode(certdir, "chain.pem")
1416 caFile = join_bytes_or_unicode(certdir, "ca.pem")
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001417
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001418 # Write out the chain file.
Alex Gaynor03737182020-07-23 20:40:46 -04001419 with open(chainFile, "wb") as fObj:
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001420 # Most specific to least general.
1421 fObj.write(dump_certificate(FILETYPE_PEM, scert))
1422 fObj.write(dump_certificate(FILETYPE_PEM, icert))
1423 fObj.write(dump_certificate(FILETYPE_PEM, cacert))
1424
Alex Gaynor03737182020-07-23 20:40:46 -04001425 with open(caFile, "w") as fObj:
1426 fObj.write(dump_certificate(FILETYPE_PEM, cacert).decode("ascii"))
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001427
1428 serverContext = Context(TLSv1_METHOD)
1429 serverContext.use_certificate_chain_file(chainFile)
1430 serverContext.use_privatekey(skey)
1431
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001432 clientContext = Context(TLSv1_METHOD)
1433 clientContext.set_verify(
Alex Gaynor03737182020-07-23 20:40:46 -04001434 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb
1435 )
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001436 clientContext.load_verify_locations(caFile)
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001437
1438 self._handshake_test(serverContext, clientContext)
1439
Alex Chan532b79e2017-01-24 15:14:52 +00001440 def test_use_certificate_chain_file_bytes(self, tmpfile):
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001441 """
1442 ``Context.use_certificate_chain_file`` accepts the name of a file (as
1443 an instance of ``bytes``) to specify additional certificates to use to
1444 construct and verify a trust chain.
1445 """
1446 self._use_certificate_chain_file_test(
Alex Chan532b79e2017-01-24 15:14:52 +00001447 tmpfile + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001448 )
1449
Alex Chan532b79e2017-01-24 15:14:52 +00001450 def test_use_certificate_chain_file_unicode(self, tmpfile):
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001451 """
1452 ``Context.use_certificate_chain_file`` accepts the name of a file (as
1453 an instance of ``unicode``) to specify additional certificates to use
1454 to construct and verify a trust chain.
1455 """
1456 self._use_certificate_chain_file_test(
Alex Chan532b79e2017-01-24 15:14:52 +00001457 tmpfile.decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001458 )
1459
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001460 def test_use_certificate_chain_file_wrong_args(self):
1461 """
Alex Chan532b79e2017-01-24 15:14:52 +00001462 `Context.use_certificate_chain_file` raises `TypeError` if passed a
1463 non-byte string single argument.
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001464 """
1465 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001466 with pytest.raises(TypeError):
1467 context.use_certificate_chain_file(object())
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001468
Alex Chan532b79e2017-01-24 15:14:52 +00001469 def test_use_certificate_chain_file_missing_file(self, tmpfile):
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001470 """
Alex Chan532b79e2017-01-24 15:14:52 +00001471 `Context.use_certificate_chain_file` raises `OpenSSL.SSL.Error` when
1472 passed a bad chain file name (for example, the name of a file which
1473 does not exist).
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001474 """
1475 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001476 with pytest.raises(Error):
1477 context.use_certificate_chain_file(tmpfile)
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001478
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001479 def test_set_verify_mode(self):
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001480 """
Alex Chan532b79e2017-01-24 15:14:52 +00001481 `Context.get_verify_mode` returns the verify mode flags previously
1482 passed to `Context.set_verify`.
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001483 """
1484 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001485 assert context.get_verify_mode() == 0
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001486 context.set_verify(
Alex Gaynor03737182020-07-23 20:40:46 -04001487 VERIFY_PEER | VERIFY_CLIENT_ONCE, lambda *args: None
1488 )
Alex Chan532b79e2017-01-24 15:14:52 +00001489 assert context.get_verify_mode() == (VERIFY_PEER | VERIFY_CLIENT_ONCE)
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001490
Alex Gaynor03737182020-07-23 20:40:46 -04001491 @pytest.mark.parametrize("mode", [None, 1.0, object(), "mode"])
Alex Chanfb078d82017-04-20 11:16:15 +01001492 def test_set_verify_wrong_mode_arg(self, mode):
1493 """
1494 `Context.set_verify` raises `TypeError` if the first argument is
1495 not an integer.
1496 """
1497 context = Context(TLSv1_METHOD)
1498 with pytest.raises(TypeError):
1499 context.set_verify(mode=mode, callback=lambda *args: None)
1500
Alex Gaynor03737182020-07-23 20:40:46 -04001501 @pytest.mark.parametrize("callback", [None, 1.0, "mode", ("foo", "bar")])
Alex Chanfb078d82017-04-20 11:16:15 +01001502 def test_set_verify_wrong_callable_arg(self, callback):
1503 """
Alex Gaynor40bc0f12018-05-14 14:06:16 -04001504 `Context.set_verify` raises `TypeError` if the second argument
Alex Chanfb078d82017-04-20 11:16:15 +01001505 is not callable.
1506 """
1507 context = Context(TLSv1_METHOD)
1508 with pytest.raises(TypeError):
1509 context.set_verify(mode=VERIFY_PEER, callback=callback)
1510
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001511 def test_load_tmp_dh_wrong_args(self):
1512 """
Alex Chan532b79e2017-01-24 15:14:52 +00001513 `Context.load_tmp_dh` raises `TypeError` if called with a
1514 non-`str` argument.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001515 """
1516 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001517 with pytest.raises(TypeError):
1518 context.load_tmp_dh(object())
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001519
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001520 def test_load_tmp_dh_missing_file(self):
1521 """
Alex Chan532b79e2017-01-24 15:14:52 +00001522 `Context.load_tmp_dh` raises `OpenSSL.SSL.Error` if the
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001523 specified file does not exist.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001524 """
1525 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001526 with pytest.raises(Error):
1527 context.load_tmp_dh(b"hello")
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001528
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001529 def _load_tmp_dh_test(self, dhfilename):
Jean-Paul Calderone4e0c43f2015-04-13 10:15:17 -04001530 """
1531 Verify that calling ``Context.load_tmp_dh`` with the given filename
1532 does not raise an exception.
1533 """
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001534 context = Context(TLSv1_METHOD)
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001535 with open(dhfilename, "w") as dhfile:
1536 dhfile.write(dhparam)
1537
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001538 context.load_tmp_dh(dhfilename)
1539 # XXX What should I assert here? -exarkun
1540
Alex Chan532b79e2017-01-24 15:14:52 +00001541 def test_load_tmp_dh_bytes(self, tmpfile):
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001542 """
Alex Chan532b79e2017-01-24 15:14:52 +00001543 `Context.load_tmp_dh` loads Diffie-Hellman parameters from the
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001544 specified file (given as ``bytes``).
1545 """
1546 self._load_tmp_dh_test(
Alex Chan532b79e2017-01-24 15:14:52 +00001547 tmpfile + NON_ASCII.encode(getfilesystemencoding()),
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001548 )
1549
Alex Chan532b79e2017-01-24 15:14:52 +00001550 def test_load_tmp_dh_unicode(self, tmpfile):
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001551 """
Alex Chan532b79e2017-01-24 15:14:52 +00001552 `Context.load_tmp_dh` loads Diffie-Hellman parameters from the
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001553 specified file (given as ``unicode``).
1554 """
1555 self._load_tmp_dh_test(
Alex Chan532b79e2017-01-24 15:14:52 +00001556 tmpfile.decode(getfilesystemencoding()) + NON_ASCII,
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001557 )
1558
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001559 def test_set_tmp_ecdh(self):
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001560 """
Alex Chan532b79e2017-01-24 15:14:52 +00001561 `Context.set_tmp_ecdh` sets the elliptic curve for Diffie-Hellman to
1562 the specified curve.
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001563 """
1564 context = Context(TLSv1_METHOD)
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001565 for curve in get_elliptic_curves():
Hynek Schlawacka07fa8c2015-10-17 10:15:28 +02001566 if curve.name.startswith(u"Oakley-"):
Hynek Schlawack7408aff2015-10-17 09:51:16 +02001567 # Setting Oakley-EC2N-4 and Oakley-EC2N-3 adds
1568 # ('bignum routines', 'BN_mod_inverse', 'no inverse') to the
1569 # error queue on OpenSSL 1.0.2.
1570 continue
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001571 # The only easily "assertable" thing is that it does not raise an
1572 # exception.
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001573 context.set_tmp_ecdh(curve)
Alex Gaynor12dc0842014-01-17 12:51:31 -06001574
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001575 def test_set_session_cache_mode_wrong_args(self):
1576 """
Alex Chan532b79e2017-01-24 15:14:52 +00001577 `Context.set_session_cache_mode` raises `TypeError` if called with
1578 a non-integer argument.
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001579 called with other than one integer argument.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001580 """
1581 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001582 with pytest.raises(TypeError):
1583 context.set_session_cache_mode(object())
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001584
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001585 def test_session_cache_mode(self):
1586 """
Alex Chan532b79e2017-01-24 15:14:52 +00001587 `Context.set_session_cache_mode` specifies how sessions are cached.
1588 The setting can be retrieved via `Context.get_session_cache_mode`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001589 """
1590 context = Context(TLSv1_METHOD)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001591 context.set_session_cache_mode(SESS_CACHE_OFF)
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001592 off = context.set_session_cache_mode(SESS_CACHE_BOTH)
Alex Chan532b79e2017-01-24 15:14:52 +00001593 assert SESS_CACHE_OFF == off
1594 assert SESS_CACHE_BOTH == context.get_session_cache_mode()
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001595
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001596 def test_get_cert_store(self):
1597 """
Alex Chan532b79e2017-01-24 15:14:52 +00001598 `Context.get_cert_store` returns a `X509Store` instance.
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001599 """
1600 context = Context(TLSv1_METHOD)
1601 store = context.get_cert_store()
Alex Chan532b79e2017-01-24 15:14:52 +00001602 assert isinstance(store, X509Store)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001603
Jeremy Lainé02261ad2018-05-16 18:33:25 +02001604 def test_set_tlsext_use_srtp_not_bytes(self):
1605 """
1606 `Context.set_tlsext_use_srtp' enables negotiating SRTP keying material.
1607
1608 It raises a TypeError if the list of profiles is not a byte string.
1609 """
1610 context = Context(TLSv1_METHOD)
1611 with pytest.raises(TypeError):
Alex Gaynor03737182020-07-23 20:40:46 -04001612 context.set_tlsext_use_srtp(text_type("SRTP_AES128_CM_SHA1_80"))
Jeremy Lainé02261ad2018-05-16 18:33:25 +02001613
1614 def test_set_tlsext_use_srtp_invalid_profile(self):
1615 """
1616 `Context.set_tlsext_use_srtp' enables negotiating SRTP keying material.
1617
1618 It raises an Error if the call to OpenSSL fails.
1619 """
1620 context = Context(TLSv1_METHOD)
1621 with pytest.raises(Error):
Alex Gaynor03737182020-07-23 20:40:46 -04001622 context.set_tlsext_use_srtp(b"SRTP_BOGUS")
Jeremy Lainé02261ad2018-05-16 18:33:25 +02001623
1624 def test_set_tlsext_use_srtp_valid(self):
1625 """
1626 `Context.set_tlsext_use_srtp' enables negotiating SRTP keying material.
1627
1628 It does not return anything.
1629 """
1630 context = Context(TLSv1_METHOD)
Alex Gaynor03737182020-07-23 20:40:46 -04001631 assert context.set_tlsext_use_srtp(b"SRTP_AES128_CM_SHA1_80") is None
Jeremy Lainé02261ad2018-05-16 18:33:25 +02001632
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001633
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001634class TestServerNameCallback(object):
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001635 """
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001636 Tests for `Context.set_tlsext_servername_callback` and its
1637 interaction with `Connection`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001638 """
Alex Gaynor03737182020-07-23 20:40:46 -04001639
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001640 def test_old_callback_forgotten(self):
1641 """
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001642 If `Context.set_tlsext_servername_callback` is used to specify
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001643 a new callback, the one it replaces is dereferenced.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001644 """
Alex Gaynor03737182020-07-23 20:40:46 -04001645
Alex Chanfb078d82017-04-20 11:16:15 +01001646 def callback(connection): # pragma: no cover
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001647 pass
1648
Alex Chanfb078d82017-04-20 11:16:15 +01001649 def replacement(connection): # pragma: no cover
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001650 pass
1651
1652 context = Context(TLSv1_METHOD)
1653 context.set_tlsext_servername_callback(callback)
1654
1655 tracker = ref(callback)
1656 del callback
1657
1658 context.set_tlsext_servername_callback(replacement)
Jean-Paul Calderoned4033eb2014-01-11 08:21:46 -05001659
1660 # One run of the garbage collector happens to work on CPython. PyPy
1661 # doesn't collect the underlying object until a second run for whatever
1662 # reason. That's fine, it still demonstrates our code has properly
1663 # dropped the reference.
1664 collect()
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001665 collect()
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001666
1667 callback = tracker()
1668 if callback is not None:
1669 referrers = get_referrers(callback)
Alex Chanfb078d82017-04-20 11:16:15 +01001670 if len(referrers) > 1: # pragma: nocover
1671 pytest.fail("Some references remain: %r" % (referrers,))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001672
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001673 def test_no_servername(self):
1674 """
1675 When a client specifies no server name, the callback passed to
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001676 `Context.set_tlsext_servername_callback` is invoked and the
1677 result of `Connection.get_servername` is `None`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001678 """
1679 args = []
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001680
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001681 def servername(conn):
1682 args.append((conn, conn.get_servername()))
Alex Gaynor03737182020-07-23 20:40:46 -04001683
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001684 context = Context(TLSv1_METHOD)
1685 context.set_tlsext_servername_callback(servername)
1686
1687 # Lose our reference to it. The Context is responsible for keeping it
1688 # alive now.
1689 del servername
1690 collect()
1691
1692 # Necessary to actually accept the connection
1693 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001694 context.use_certificate(
Alex Gaynor03737182020-07-23 20:40:46 -04001695 load_certificate(FILETYPE_PEM, server_cert_pem)
1696 )
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001697
1698 # Do a little connection to trigger the logic
1699 server = Connection(context, None)
1700 server.set_accept_state()
1701
1702 client = Connection(Context(TLSv1_METHOD), None)
1703 client.set_connect_state()
1704
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001705 interact_in_memory(server, client)
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001706
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001707 assert args == [(server, None)]
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001708
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001709 def test_servername(self):
1710 """
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001711 When a client specifies a server name in its hello message, the
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001712 callback passed to `Contexts.set_tlsext_servername_callback` is
1713 invoked and the result of `Connection.get_servername` is that
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001714 server name.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001715 """
1716 args = []
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001717
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001718 def servername(conn):
1719 args.append((conn, conn.get_servername()))
Alex Gaynor03737182020-07-23 20:40:46 -04001720
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001721 context = Context(TLSv1_METHOD)
1722 context.set_tlsext_servername_callback(servername)
1723
1724 # Necessary to actually accept the connection
1725 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001726 context.use_certificate(
Alex Gaynor03737182020-07-23 20:40:46 -04001727 load_certificate(FILETYPE_PEM, server_cert_pem)
1728 )
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001729
1730 # Do a little connection to trigger the logic
1731 server = Connection(context, None)
1732 server.set_accept_state()
1733
1734 client = Connection(Context(TLSv1_METHOD), None)
1735 client.set_connect_state()
Alex Gaynore7f51982016-09-11 11:48:14 -04001736 client.set_tlsext_host_name(b"foo1.example.com")
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001737
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001738 interact_in_memory(server, client)
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001739
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001740 assert args == [(server, b"foo1.example.com")]
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001741
1742
Paul Kehrer4d575902019-02-26 21:42:12 +08001743@pytest.mark.skipif(
1744 not _lib.Cryptography_HAS_NEXTPROTONEG, reason="NPN is not available"
1745)
Alex Chan9e08b3e2016-11-10 12:18:54 +00001746class TestNextProtoNegotiation(object):
Cory Benfield84a121e2014-03-31 20:30:25 +01001747 """
1748 Test for Next Protocol Negotiation in PyOpenSSL.
1749 """
Alex Gaynor03737182020-07-23 20:40:46 -04001750
Alex Chan9e08b3e2016-11-10 12:18:54 +00001751 def test_npn_success(self):
1752 """
1753 Tests that clients and servers that agree on the negotiated next
1754 protocol can correct establish a connection, and that the agreed
1755 protocol is reported by the connections.
1756 """
1757 advertise_args = []
1758 select_args = []
1759
1760 def advertise(conn):
1761 advertise_args.append((conn,))
Alex Gaynor03737182020-07-23 20:40:46 -04001762 return [b"http/1.1", b"spdy/2"]
Alex Chan9e08b3e2016-11-10 12:18:54 +00001763
1764 def select(conn, options):
1765 select_args.append((conn, options))
Alex Gaynor03737182020-07-23 20:40:46 -04001766 return b"spdy/2"
Alex Chan9e08b3e2016-11-10 12:18:54 +00001767
1768 server_context = Context(TLSv1_METHOD)
1769 server_context.set_npn_advertise_callback(advertise)
1770
1771 client_context = Context(TLSv1_METHOD)
1772 client_context.set_npn_select_callback(select)
1773
1774 # Necessary to actually accept the connection
1775 server_context.use_privatekey(
Alex Gaynor03737182020-07-23 20:40:46 -04001776 load_privatekey(FILETYPE_PEM, server_key_pem)
1777 )
Alex Chan9e08b3e2016-11-10 12:18:54 +00001778 server_context.use_certificate(
Alex Gaynor03737182020-07-23 20:40:46 -04001779 load_certificate(FILETYPE_PEM, server_cert_pem)
1780 )
Alex Chan9e08b3e2016-11-10 12:18:54 +00001781
1782 # Do a little connection to trigger the logic
1783 server = Connection(server_context, None)
1784 server.set_accept_state()
1785
1786 client = Connection(client_context, None)
1787 client.set_connect_state()
1788
1789 interact_in_memory(server, client)
1790
1791 assert advertise_args == [(server,)]
Alex Gaynor03737182020-07-23 20:40:46 -04001792 assert select_args == [(client, [b"http/1.1", b"spdy/2"])]
Alex Chan9e08b3e2016-11-10 12:18:54 +00001793
Alex Gaynor03737182020-07-23 20:40:46 -04001794 assert server.get_next_proto_negotiated() == b"spdy/2"
1795 assert client.get_next_proto_negotiated() == b"spdy/2"
Alex Chan9e08b3e2016-11-10 12:18:54 +00001796
1797 def test_npn_client_fail(self):
1798 """
1799 Tests that when clients and servers cannot agree on what protocol
1800 to use next that the TLS connection does not get established.
1801 """
1802 advertise_args = []
1803 select_args = []
1804
1805 def advertise(conn):
1806 advertise_args.append((conn,))
Alex Gaynor03737182020-07-23 20:40:46 -04001807 return [b"http/1.1", b"spdy/2"]
Alex Chan9e08b3e2016-11-10 12:18:54 +00001808
1809 def select(conn, options):
1810 select_args.append((conn, options))
Alex Gaynor03737182020-07-23 20:40:46 -04001811 return b""
Alex Chan9e08b3e2016-11-10 12:18:54 +00001812
1813 server_context = Context(TLSv1_METHOD)
1814 server_context.set_npn_advertise_callback(advertise)
1815
1816 client_context = Context(TLSv1_METHOD)
1817 client_context.set_npn_select_callback(select)
1818
1819 # Necessary to actually accept the connection
1820 server_context.use_privatekey(
Alex Gaynor03737182020-07-23 20:40:46 -04001821 load_privatekey(FILETYPE_PEM, server_key_pem)
1822 )
Alex Chan9e08b3e2016-11-10 12:18:54 +00001823 server_context.use_certificate(
Alex Gaynor03737182020-07-23 20:40:46 -04001824 load_certificate(FILETYPE_PEM, server_cert_pem)
1825 )
Alex Chan9e08b3e2016-11-10 12:18:54 +00001826
1827 # Do a little connection to trigger the logic
1828 server = Connection(server_context, None)
1829 server.set_accept_state()
1830
1831 client = Connection(client_context, None)
1832 client.set_connect_state()
1833
1834 # If the client doesn't return anything, the connection will fail.
1835 with pytest.raises(Error):
1836 interact_in_memory(server, client)
1837
1838 assert advertise_args == [(server,)]
Alex Gaynor03737182020-07-23 20:40:46 -04001839 assert select_args == [(client, [b"http/1.1", b"spdy/2"])]
Alex Chan9e08b3e2016-11-10 12:18:54 +00001840
1841 def test_npn_select_error(self):
1842 """
1843 Test that we can handle exceptions in the select callback. If
1844 select fails it should be fatal to the connection.
1845 """
1846 advertise_args = []
1847
1848 def advertise(conn):
1849 advertise_args.append((conn,))
Alex Gaynor03737182020-07-23 20:40:46 -04001850 return [b"http/1.1", b"spdy/2"]
Alex Chan9e08b3e2016-11-10 12:18:54 +00001851
1852 def select(conn, options):
1853 raise TypeError
1854
1855 server_context = Context(TLSv1_METHOD)
1856 server_context.set_npn_advertise_callback(advertise)
1857
1858 client_context = Context(TLSv1_METHOD)
1859 client_context.set_npn_select_callback(select)
1860
1861 # Necessary to actually accept the connection
1862 server_context.use_privatekey(
Alex Gaynor03737182020-07-23 20:40:46 -04001863 load_privatekey(FILETYPE_PEM, server_key_pem)
1864 )
Alex Chan9e08b3e2016-11-10 12:18:54 +00001865 server_context.use_certificate(
Alex Gaynor03737182020-07-23 20:40:46 -04001866 load_certificate(FILETYPE_PEM, server_cert_pem)
1867 )
Alex Chan9e08b3e2016-11-10 12:18:54 +00001868
1869 # Do a little connection to trigger the logic
1870 server = Connection(server_context, None)
1871 server.set_accept_state()
1872
1873 client = Connection(client_context, None)
1874 client.set_connect_state()
1875
1876 # If the callback throws an exception it should be raised here.
1877 with pytest.raises(TypeError):
1878 interact_in_memory(server, client)
Alex Gaynor03737182020-07-23 20:40:46 -04001879 assert advertise_args == [
1880 (server,),
1881 ]
Alex Chan9e08b3e2016-11-10 12:18:54 +00001882
1883 def test_npn_advertise_error(self):
1884 """
1885 Test that we can handle exceptions in the advertise callback. If
1886 advertise fails no NPN is advertised to the client.
1887 """
1888 select_args = []
1889
1890 def advertise(conn):
1891 raise TypeError
1892
1893 def select(conn, options): # pragma: nocover
Cory Benfieldba1820d2015-04-13 17:39:12 -04001894 """
Alex Chan9e08b3e2016-11-10 12:18:54 +00001895 Assert later that no args are actually appended.
Cory Benfieldba1820d2015-04-13 17:39:12 -04001896 """
Alex Chan9e08b3e2016-11-10 12:18:54 +00001897 select_args.append((conn, options))
Alex Gaynor03737182020-07-23 20:40:46 -04001898 return b""
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001899
Alex Chan9e08b3e2016-11-10 12:18:54 +00001900 server_context = Context(TLSv1_METHOD)
1901 server_context.set_npn_advertise_callback(advertise)
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001902
Alex Chan9e08b3e2016-11-10 12:18:54 +00001903 client_context = Context(TLSv1_METHOD)
1904 client_context.set_npn_select_callback(select)
Cory Benfield84a121e2014-03-31 20:30:25 +01001905
Alex Chan9e08b3e2016-11-10 12:18:54 +00001906 # Necessary to actually accept the connection
1907 server_context.use_privatekey(
Alex Gaynor03737182020-07-23 20:40:46 -04001908 load_privatekey(FILETYPE_PEM, server_key_pem)
1909 )
Alex Chan9e08b3e2016-11-10 12:18:54 +00001910 server_context.use_certificate(
Alex Gaynor03737182020-07-23 20:40:46 -04001911 load_certificate(FILETYPE_PEM, server_cert_pem)
1912 )
Cory Benfield84a121e2014-03-31 20:30:25 +01001913
Alex Chan9e08b3e2016-11-10 12:18:54 +00001914 # Do a little connection to trigger the logic
1915 server = Connection(server_context, None)
1916 server.set_accept_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001917
Alex Chan9e08b3e2016-11-10 12:18:54 +00001918 client = Connection(client_context, None)
1919 client.set_connect_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001920
Alex Chan9e08b3e2016-11-10 12:18:54 +00001921 # If the client doesn't return anything, the connection will fail.
1922 with pytest.raises(TypeError):
1923 interact_in_memory(server, client)
1924 assert select_args == []
Cory Benfield0ea76e72015-03-22 09:05:28 +00001925
1926
Alex Chanec1e32d2016-11-10 14:11:45 +00001927class TestApplicationLayerProtoNegotiation(object):
Cory Benfield12eae892014-06-07 15:42:56 +01001928 """
1929 Tests for ALPN in PyOpenSSL.
1930 """
Alex Gaynor03737182020-07-23 20:40:46 -04001931
Alex Gaynor77debda2020-04-07 13:40:59 -04001932 def test_alpn_success(self):
1933 """
1934 Clients and servers that agree on the negotiated ALPN protocol can
1935 correct establish a connection, and the agreed protocol is reported
1936 by the connections.
1937 """
1938 select_args = []
Cory Benfield12eae892014-06-07 15:42:56 +01001939
Alex Gaynor77debda2020-04-07 13:40:59 -04001940 def select(conn, options):
1941 select_args.append((conn, options))
Alex Gaynor03737182020-07-23 20:40:46 -04001942 return b"spdy/2"
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001943
Alex Gaynor77debda2020-04-07 13:40:59 -04001944 client_context = Context(TLSv1_METHOD)
Alex Gaynor03737182020-07-23 20:40:46 -04001945 client_context.set_alpn_protos([b"http/1.1", b"spdy/2"])
Cory Benfield12eae892014-06-07 15:42:56 +01001946
Alex Gaynor77debda2020-04-07 13:40:59 -04001947 server_context = Context(TLSv1_METHOD)
1948 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01001949
Alex Gaynor77debda2020-04-07 13:40:59 -04001950 # Necessary to actually accept the connection
1951 server_context.use_privatekey(
Alex Gaynor03737182020-07-23 20:40:46 -04001952 load_privatekey(FILETYPE_PEM, server_key_pem)
1953 )
Alex Gaynor77debda2020-04-07 13:40:59 -04001954 server_context.use_certificate(
Alex Gaynor03737182020-07-23 20:40:46 -04001955 load_certificate(FILETYPE_PEM, server_cert_pem)
1956 )
Cory Benfield12eae892014-06-07 15:42:56 +01001957
Alex Gaynor77debda2020-04-07 13:40:59 -04001958 # Do a little connection to trigger the logic
1959 server = Connection(server_context, None)
1960 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001961
Alex Gaynor77debda2020-04-07 13:40:59 -04001962 client = Connection(client_context, None)
1963 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001964
Alex Gaynor77debda2020-04-07 13:40:59 -04001965 interact_in_memory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001966
Alex Gaynor03737182020-07-23 20:40:46 -04001967 assert select_args == [(server, [b"http/1.1", b"spdy/2"])]
Alex Gaynor77debda2020-04-07 13:40:59 -04001968
Alex Gaynor03737182020-07-23 20:40:46 -04001969 assert server.get_alpn_proto_negotiated() == b"spdy/2"
1970 assert client.get_alpn_proto_negotiated() == b"spdy/2"
Alex Gaynor77debda2020-04-07 13:40:59 -04001971
1972 def test_alpn_set_on_connection(self):
1973 """
1974 The same as test_alpn_success, but setting the ALPN protocols on
1975 the connection rather than the context.
1976 """
1977 select_args = []
1978
1979 def select(conn, options):
1980 select_args.append((conn, options))
Alex Gaynor03737182020-07-23 20:40:46 -04001981 return b"spdy/2"
Alex Gaynor77debda2020-04-07 13:40:59 -04001982
1983 # Setup the client context but don't set any ALPN protocols.
1984 client_context = Context(TLSv1_METHOD)
1985
1986 server_context = Context(TLSv1_METHOD)
1987 server_context.set_alpn_select_callback(select)
1988
1989 # Necessary to actually accept the connection
1990 server_context.use_privatekey(
Alex Gaynor03737182020-07-23 20:40:46 -04001991 load_privatekey(FILETYPE_PEM, server_key_pem)
1992 )
Alex Gaynor77debda2020-04-07 13:40:59 -04001993 server_context.use_certificate(
Alex Gaynor03737182020-07-23 20:40:46 -04001994 load_certificate(FILETYPE_PEM, server_cert_pem)
1995 )
Alex Gaynor77debda2020-04-07 13:40:59 -04001996
1997 # Do a little connection to trigger the logic
1998 server = Connection(server_context, None)
1999 server.set_accept_state()
2000
2001 # Set the ALPN protocols on the client connection.
2002 client = Connection(client_context, None)
Alex Gaynor03737182020-07-23 20:40:46 -04002003 client.set_alpn_protos([b"http/1.1", b"spdy/2"])
Alex Gaynor77debda2020-04-07 13:40:59 -04002004 client.set_connect_state()
2005
2006 interact_in_memory(server, client)
2007
Alex Gaynor03737182020-07-23 20:40:46 -04002008 assert select_args == [(server, [b"http/1.1", b"spdy/2"])]
Alex Gaynor77debda2020-04-07 13:40:59 -04002009
Alex Gaynor03737182020-07-23 20:40:46 -04002010 assert server.get_alpn_proto_negotiated() == b"spdy/2"
2011 assert client.get_alpn_proto_negotiated() == b"spdy/2"
Alex Gaynor77debda2020-04-07 13:40:59 -04002012
2013 def test_alpn_server_fail(self):
2014 """
2015 When clients and servers cannot agree on what protocol to use next
2016 the TLS connection does not get established.
2017 """
2018 select_args = []
2019
2020 def select(conn, options):
2021 select_args.append((conn, options))
Alex Gaynor03737182020-07-23 20:40:46 -04002022 return b""
Alex Gaynor77debda2020-04-07 13:40:59 -04002023
2024 client_context = Context(TLSv1_METHOD)
Alex Gaynor03737182020-07-23 20:40:46 -04002025 client_context.set_alpn_protos([b"http/1.1", b"spdy/2"])
Alex Gaynor77debda2020-04-07 13:40:59 -04002026
2027 server_context = Context(TLSv1_METHOD)
2028 server_context.set_alpn_select_callback(select)
2029
2030 # Necessary to actually accept the connection
2031 server_context.use_privatekey(
Alex Gaynor03737182020-07-23 20:40:46 -04002032 load_privatekey(FILETYPE_PEM, server_key_pem)
2033 )
Alex Gaynor77debda2020-04-07 13:40:59 -04002034 server_context.use_certificate(
Alex Gaynor03737182020-07-23 20:40:46 -04002035 load_certificate(FILETYPE_PEM, server_cert_pem)
2036 )
Alex Gaynor77debda2020-04-07 13:40:59 -04002037
2038 # Do a little connection to trigger the logic
2039 server = Connection(server_context, None)
2040 server.set_accept_state()
2041
2042 client = Connection(client_context, None)
2043 client.set_connect_state()
2044
2045 # If the client doesn't return anything, the connection will fail.
2046 with pytest.raises(Error):
Alex Chanec1e32d2016-11-10 14:11:45 +00002047 interact_in_memory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01002048
Alex Gaynor03737182020-07-23 20:40:46 -04002049 assert select_args == [(server, [b"http/1.1", b"spdy/2"])]
Cory Benfielde46fa842015-04-13 16:50:49 -04002050
Alex Gaynor77debda2020-04-07 13:40:59 -04002051 def test_alpn_no_server_overlap(self):
2052 """
2053 A server can allow a TLS handshake to complete without
2054 agreeing to an application protocol by returning
2055 ``NO_OVERLAPPING_PROTOCOLS``.
2056 """
2057 refusal_args = []
Cory Benfield12eae892014-06-07 15:42:56 +01002058
Alex Gaynor77debda2020-04-07 13:40:59 -04002059 def refusal(conn, options):
2060 refusal_args.append((conn, options))
2061 return NO_OVERLAPPING_PROTOCOLS
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002062
Alex Gaynor77debda2020-04-07 13:40:59 -04002063 client_context = Context(SSLv23_METHOD)
Alex Gaynor03737182020-07-23 20:40:46 -04002064 client_context.set_alpn_protos([b"http/1.1", b"spdy/2"])
Cory Benfield12eae892014-06-07 15:42:56 +01002065
Alex Gaynor77debda2020-04-07 13:40:59 -04002066 server_context = Context(SSLv23_METHOD)
2067 server_context.set_alpn_select_callback(refusal)
Cory Benfield12eae892014-06-07 15:42:56 +01002068
Alex Gaynor77debda2020-04-07 13:40:59 -04002069 # Necessary to actually accept the connection
2070 server_context.use_privatekey(
Alex Gaynor03737182020-07-23 20:40:46 -04002071 load_privatekey(FILETYPE_PEM, server_key_pem)
2072 )
Alex Gaynor77debda2020-04-07 13:40:59 -04002073 server_context.use_certificate(
Alex Gaynor03737182020-07-23 20:40:46 -04002074 load_certificate(FILETYPE_PEM, server_cert_pem)
2075 )
Cory Benfield12eae892014-06-07 15:42:56 +01002076
Alex Gaynor77debda2020-04-07 13:40:59 -04002077 # Do a little connection to trigger the logic
2078 server = Connection(server_context, None)
2079 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01002080
Alex Gaynor77debda2020-04-07 13:40:59 -04002081 client = Connection(client_context, None)
2082 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01002083
Alex Gaynor77debda2020-04-07 13:40:59 -04002084 # Do the dance.
2085 interact_in_memory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01002086
Alex Gaynor03737182020-07-23 20:40:46 -04002087 assert refusal_args == [(server, [b"http/1.1", b"spdy/2"])]
Alex Gaynor77debda2020-04-07 13:40:59 -04002088
Alex Gaynor03737182020-07-23 20:40:46 -04002089 assert client.get_alpn_proto_negotiated() == b""
Alex Gaynor77debda2020-04-07 13:40:59 -04002090
2091 def test_alpn_select_cb_returns_invalid_value(self):
2092 """
2093 If the ALPN selection callback returns anything other than
2094 a bytestring or ``NO_OVERLAPPING_PROTOCOLS``, a
2095 :py:exc:`TypeError` is raised.
2096 """
2097 invalid_cb_args = []
2098
2099 def invalid_cb(conn, options):
2100 invalid_cb_args.append((conn, options))
2101 return u"can't return unicode"
2102
2103 client_context = Context(SSLv23_METHOD)
Alex Gaynor03737182020-07-23 20:40:46 -04002104 client_context.set_alpn_protos([b"http/1.1", b"spdy/2"])
Alex Gaynor77debda2020-04-07 13:40:59 -04002105
2106 server_context = Context(SSLv23_METHOD)
2107 server_context.set_alpn_select_callback(invalid_cb)
2108
2109 # Necessary to actually accept the connection
2110 server_context.use_privatekey(
Alex Gaynor03737182020-07-23 20:40:46 -04002111 load_privatekey(FILETYPE_PEM, server_key_pem)
2112 )
Alex Gaynor77debda2020-04-07 13:40:59 -04002113 server_context.use_certificate(
Alex Gaynor03737182020-07-23 20:40:46 -04002114 load_certificate(FILETYPE_PEM, server_cert_pem)
2115 )
Alex Gaynor77debda2020-04-07 13:40:59 -04002116
2117 # Do a little connection to trigger the logic
2118 server = Connection(server_context, None)
2119 server.set_accept_state()
2120
2121 client = Connection(client_context, None)
2122 client.set_connect_state()
2123
2124 # Do the dance.
2125 with pytest.raises(TypeError):
Alex Chanec1e32d2016-11-10 14:11:45 +00002126 interact_in_memory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01002127
Alex Gaynor03737182020-07-23 20:40:46 -04002128 assert invalid_cb_args == [(server, [b"http/1.1", b"spdy/2"])]
Cory Benfield12eae892014-06-07 15:42:56 +01002129
Alex Gaynor03737182020-07-23 20:40:46 -04002130 assert client.get_alpn_proto_negotiated() == b""
Cory Benfield12eae892014-06-07 15:42:56 +01002131
Alex Gaynor77debda2020-04-07 13:40:59 -04002132 def test_alpn_no_server(self):
2133 """
2134 When clients and servers cannot agree on what protocol to use next
2135 because the server doesn't offer ALPN, no protocol is negotiated.
2136 """
2137 client_context = Context(TLSv1_METHOD)
Alex Gaynor03737182020-07-23 20:40:46 -04002138 client_context.set_alpn_protos([b"http/1.1", b"spdy/2"])
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002139
Alex Gaynor77debda2020-04-07 13:40:59 -04002140 server_context = Context(TLSv1_METHOD)
Cory Benfield12eae892014-06-07 15:42:56 +01002141
Alex Gaynor77debda2020-04-07 13:40:59 -04002142 # Necessary to actually accept the connection
2143 server_context.use_privatekey(
Alex Gaynor03737182020-07-23 20:40:46 -04002144 load_privatekey(FILETYPE_PEM, server_key_pem)
2145 )
Alex Gaynor77debda2020-04-07 13:40:59 -04002146 server_context.use_certificate(
Alex Gaynor03737182020-07-23 20:40:46 -04002147 load_certificate(FILETYPE_PEM, server_cert_pem)
2148 )
Cory Benfield12eae892014-06-07 15:42:56 +01002149
Alex Gaynor77debda2020-04-07 13:40:59 -04002150 # Do a little connection to trigger the logic
2151 server = Connection(server_context, None)
2152 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01002153
Alex Gaynor77debda2020-04-07 13:40:59 -04002154 client = Connection(client_context, None)
2155 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01002156
Alex Gaynor77debda2020-04-07 13:40:59 -04002157 # Do the dance.
2158 interact_in_memory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01002159
Alex Gaynor03737182020-07-23 20:40:46 -04002160 assert client.get_alpn_proto_negotiated() == b""
Cory Benfield12eae892014-06-07 15:42:56 +01002161
Alex Gaynor77debda2020-04-07 13:40:59 -04002162 def test_alpn_callback_exception(self):
2163 """
2164 We can handle exceptions in the ALPN select callback.
2165 """
2166 select_args = []
Cory Benfield12eae892014-06-07 15:42:56 +01002167
Alex Gaynor77debda2020-04-07 13:40:59 -04002168 def select(conn, options):
2169 select_args.append((conn, options))
2170 raise TypeError()
Cory Benfield12eae892014-06-07 15:42:56 +01002171
Alex Gaynor77debda2020-04-07 13:40:59 -04002172 client_context = Context(TLSv1_METHOD)
Alex Gaynor03737182020-07-23 20:40:46 -04002173 client_context.set_alpn_protos([b"http/1.1", b"spdy/2"])
Mark Williams5d890a02019-11-17 19:56:26 -08002174
Alex Gaynor77debda2020-04-07 13:40:59 -04002175 server_context = Context(TLSv1_METHOD)
2176 server_context.set_alpn_select_callback(select)
Mark Williams5d890a02019-11-17 19:56:26 -08002177
Alex Gaynor77debda2020-04-07 13:40:59 -04002178 # Necessary to actually accept the connection
2179 server_context.use_privatekey(
Alex Gaynor03737182020-07-23 20:40:46 -04002180 load_privatekey(FILETYPE_PEM, server_key_pem)
2181 )
Alex Gaynor77debda2020-04-07 13:40:59 -04002182 server_context.use_certificate(
Alex Gaynor03737182020-07-23 20:40:46 -04002183 load_certificate(FILETYPE_PEM, server_cert_pem)
2184 )
Mark Williams5d890a02019-11-17 19:56:26 -08002185
Alex Gaynor77debda2020-04-07 13:40:59 -04002186 # Do a little connection to trigger the logic
2187 server = Connection(server_context, None)
2188 server.set_accept_state()
Mark Williams5d890a02019-11-17 19:56:26 -08002189
Alex Gaynor77debda2020-04-07 13:40:59 -04002190 client = Connection(client_context, None)
2191 client.set_connect_state()
Mark Williams5d890a02019-11-17 19:56:26 -08002192
Alex Gaynor77debda2020-04-07 13:40:59 -04002193 with pytest.raises(TypeError):
Mark Williams5d890a02019-11-17 19:56:26 -08002194 interact_in_memory(server, client)
Alex Gaynor03737182020-07-23 20:40:46 -04002195 assert select_args == [(server, [b"http/1.1", b"spdy/2"])]
Cory Benfield0f7b04c2015-04-13 17:51:12 -04002196
Cory Benfieldf1177e72015-04-12 09:11:49 -04002197
Alex Chanec1e32d2016-11-10 14:11:45 +00002198class TestSession(object):
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05002199 """
2200 Unit tests for :py:obj:`OpenSSL.SSL.Session`.
2201 """
Alex Gaynor03737182020-07-23 20:40:46 -04002202
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05002203 def test_construction(self):
2204 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002205 :py:class:`Session` can be constructed with no arguments, creating
2206 a new instance of that type.
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05002207 """
2208 new_session = Session()
Alex Chanec1e32d2016-11-10 14:11:45 +00002209 assert isinstance(new_session, Session)
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05002210
2211
Alex Chan1c0cb662017-01-30 07:13:30 +00002212class TestConnection(object):
Rick Deane15b1472009-07-09 15:53:42 -05002213 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002214 Unit tests for `OpenSSL.SSL.Connection`.
Rick Deane15b1472009-07-09 15:53:42 -05002215 """
Alex Gaynor03737182020-07-23 20:40:46 -04002216
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04002217 # XXX get_peer_certificate -> None
2218 # XXX sock_shutdown
2219 # XXX master_key -> TypeError
2220 # XXX server_random -> TypeError
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04002221 # XXX connect -> TypeError
2222 # XXX connect_ex -> TypeError
2223 # XXX set_connect_state -> TypeError
2224 # XXX set_accept_state -> TypeError
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04002225 # XXX do_handshake -> TypeError
2226 # XXX bio_read -> TypeError
2227 # XXX recv -> TypeError
2228 # XXX send -> TypeError
2229 # XXX bio_write -> TypeError
2230
Rick Deane15b1472009-07-09 15:53:42 -05002231 def test_type(self):
2232 """
Alex Gaynor01f90a12019-02-07 09:14:48 -05002233 `Connection` can be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -05002234 """
2235 ctx = Context(TLSv1_METHOD)
Alex Gaynor03737182020-07-23 20:40:46 -04002236 assert is_consistent_type(Connection, "Connection", ctx, None)
Rick Deane15b1472009-07-09 15:53:42 -05002237
Alex Gaynor03737182020-07-23 20:40:46 -04002238 @pytest.mark.parametrize("bad_context", [object(), "context", None, 1])
Alex Chanfb078d82017-04-20 11:16:15 +01002239 def test_wrong_args(self, bad_context):
2240 """
2241 `Connection.__init__` raises `TypeError` if called with a non-`Context`
2242 instance argument.
2243 """
2244 with pytest.raises(TypeError):
2245 Connection(bad_context)
2246
Alex Gaynor03737182020-07-23 20:40:46 -04002247 @pytest.mark.parametrize("bad_bio", [object(), None, 1, [1, 2, 3]])
Daniel Holth079c9632019-11-17 22:45:52 -05002248 def test_bio_write_wrong_args(self, bad_bio):
2249 """
2250 `Connection.bio_write` raises `TypeError` if called with a non-bytes
2251 (or text) argument.
2252 """
2253 context = Context(TLSv1_METHOD)
2254 connection = Connection(context, None)
2255 with pytest.raises(TypeError):
2256 connection.bio_write(bad_bio)
2257
2258 def test_bio_write(self):
2259 """
2260 `Connection.bio_write` does not raise if called with bytes or
2261 bytearray, warns if called with text.
2262 """
2263 context = Context(TLSv1_METHOD)
2264 connection = Connection(context, None)
Alex Gaynor03737182020-07-23 20:40:46 -04002265 connection.bio_write(b"xy")
2266 connection.bio_write(bytearray(b"za"))
Daniel Holth079c9632019-11-17 22:45:52 -05002267 with pytest.warns(DeprecationWarning):
Alex Gaynor03737182020-07-23 20:40:46 -04002268 connection.bio_write(u"deprecated")
Daniel Holth079c9632019-11-17 22:45:52 -05002269
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002270 def test_get_context(self):
2271 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002272 `Connection.get_context` returns the `Context` instance used to
2273 construct the `Connection` instance.
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002274 """
2275 context = Context(TLSv1_METHOD)
2276 connection = Connection(context, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002277 assert connection.get_context() is context
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002278
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002279 def test_set_context_wrong_args(self):
2280 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002281 `Connection.set_context` raises `TypeError` if called with a
Alex Chanfb078d82017-04-20 11:16:15 +01002282 non-`Context` instance argument.
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002283 """
2284 ctx = Context(TLSv1_METHOD)
2285 connection = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002286 with pytest.raises(TypeError):
2287 connection.set_context(object())
2288 with pytest.raises(TypeError):
2289 connection.set_context("hello")
2290 with pytest.raises(TypeError):
2291 connection.set_context(1)
2292 assert ctx is connection.get_context()
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002293
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002294 def test_set_context(self):
2295 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002296 `Connection.set_context` specifies a new `Context` instance to be
2297 used for the connection.
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002298 """
2299 original = Context(SSLv23_METHOD)
2300 replacement = Context(TLSv1_METHOD)
2301 connection = Connection(original, None)
2302 connection.set_context(replacement)
Alex Chan1c0cb662017-01-30 07:13:30 +00002303 assert replacement is connection.get_context()
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002304 # Lose our references to the contexts, just in case the Connection
2305 # isn't properly managing its own contributions to their reference
2306 # counts.
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002307 del original, replacement
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002308 collect()
2309
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002310 def test_set_tlsext_host_name_wrong_args(self):
2311 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002312 If `Connection.set_tlsext_host_name` is called with a non-byte string
2313 argument or a byte string with an embedded NUL, `TypeError` is raised.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002314 """
2315 conn = Connection(Context(TLSv1_METHOD), None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002316 with pytest.raises(TypeError):
2317 conn.set_tlsext_host_name(object())
2318 with pytest.raises(TypeError):
2319 conn.set_tlsext_host_name(b"with\0null")
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002320
Hugo van Kemenade60827f82019-08-30 00:39:35 +03002321 if not PY2:
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002322 # On Python 3.x, don't accidentally implicitly convert from text.
Alex Chan1c0cb662017-01-30 07:13:30 +00002323 with pytest.raises(TypeError):
2324 conn.set_tlsext_host_name(b"example.com".decode("ascii"))
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04002325
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002326 def test_pending(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002327 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002328 `Connection.pending` returns the number of bytes available for
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002329 immediate read.
2330 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002331 connection = Connection(Context(TLSv1_METHOD), None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002332 assert connection.pending() == 0
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002333
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002334 def test_peek(self):
2335 """
Hynek Schlawack3bcf3152017-02-18 08:25:34 +01002336 `Connection.recv` peeks into the connection if `socket.MSG_PEEK` is
2337 passed.
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002338 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002339 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04002340 server.send(b"xy")
2341 assert client.recv(2, MSG_PEEK) == b"xy"
2342 assert client.recv(2, MSG_PEEK) == b"xy"
2343 assert client.recv(2) == b"xy"
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002344
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002345 def test_connect_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002346 """
Hynek Schlawack3bcf3152017-02-18 08:25:34 +01002347 `Connection.connect` raises `TypeError` if called with a non-address
2348 argument.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002349 """
David Benjamin1fbe0642019-04-15 17:05:13 -05002350 connection = Connection(Context(TLSv1_METHOD), socket_any_family())
Alex Chan1c0cb662017-01-30 07:13:30 +00002351 with pytest.raises(TypeError):
2352 connection.connect(None)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002353
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002354 def test_connect_refused(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002355 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002356 `Connection.connect` raises `socket.error` if the underlying socket
2357 connect method raises it.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002358 """
David Benjamin1fbe0642019-04-15 17:05:13 -05002359 client = socket_any_family()
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002360 context = Context(TLSv1_METHOD)
2361 clientSSL = Connection(context, client)
Alex Gaynor122717b2015-09-05 14:14:18 -04002362 # pytest.raises here doesn't work because of a bug in py.test on Python
2363 # 2.6: https://github.com/pytest-dev/pytest/issues/988
Alex Gaynore69c2782015-09-05 14:07:48 -04002364 try:
David Benjamin1fbe0642019-04-15 17:05:13 -05002365 clientSSL.connect((loopback_address(client), 1))
Alex Gaynore69c2782015-09-05 14:07:48 -04002366 except error as e:
Alex Gaynor20a4c082015-09-05 14:24:15 -04002367 exc = e
2368 assert exc.args[0] == ECONNREFUSED
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002369
2370 def test_connect(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002371 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002372 `Connection.connect` establishes a connection to the specified address.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002373 """
David Benjamin1fbe0642019-04-15 17:05:13 -05002374 port = socket_any_family()
Alex Gaynor03737182020-07-23 20:40:46 -04002375 port.bind(("", 0))
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002376 port.listen(3)
2377
David Benjamin1fbe0642019-04-15 17:05:13 -05002378 clientSSL = Connection(Context(TLSv1_METHOD), socket(port.family))
2379 clientSSL.connect((loopback_address(port), port.getsockname()[1]))
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002380 # XXX An assertion? Or something?
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002381
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002382 @pytest.mark.skipif(
2383 platform == "darwin",
Alex Gaynor03737182020-07-23 20:40:46 -04002384 reason="connect_ex sometimes causes a kernel panic on OS X 10.6.4",
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002385 )
2386 def test_connect_ex(self):
2387 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002388 If there is a connection error, `Connection.connect_ex` returns the
2389 errno instead of raising an exception.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002390 """
David Benjamin1fbe0642019-04-15 17:05:13 -05002391 port = socket_any_family()
Alex Gaynor03737182020-07-23 20:40:46 -04002392 port.bind(("", 0))
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002393 port.listen(3)
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002394
David Benjamin1fbe0642019-04-15 17:05:13 -05002395 clientSSL = Connection(Context(TLSv1_METHOD), socket(port.family))
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002396 clientSSL.setblocking(False)
2397 result = clientSSL.connect_ex(port.getsockname())
2398 expected = (EINPROGRESS, EWOULDBLOCK)
Alex Chan1c0cb662017-01-30 07:13:30 +00002399 assert result in expected
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002400
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002401 def test_accept(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002402 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002403 `Connection.accept` accepts a pending connection attempt and returns a
2404 tuple of a new `Connection` (the accepted client) and the address the
2405 connection originated from.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002406 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002407 ctx = Context(TLSv1_METHOD)
2408 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2409 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
David Benjamin1fbe0642019-04-15 17:05:13 -05002410 port = socket_any_family()
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002411 portSSL = Connection(ctx, port)
Alex Gaynor03737182020-07-23 20:40:46 -04002412 portSSL.bind(("", 0))
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002413 portSSL.listen(3)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002414
David Benjamin1fbe0642019-04-15 17:05:13 -05002415 clientSSL = Connection(Context(TLSv1_METHOD), socket(port.family))
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002416
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002417 # Calling portSSL.getsockname() here to get the server IP address
2418 # sounds great, but frequently fails on Windows.
David Benjamin1fbe0642019-04-15 17:05:13 -05002419 clientSSL.connect((loopback_address(port), portSSL.getsockname()[1]))
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002420
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002421 serverSSL, address = portSSL.accept()
2422
Alex Chan1c0cb662017-01-30 07:13:30 +00002423 assert isinstance(serverSSL, Connection)
2424 assert serverSSL.get_context() is ctx
2425 assert address == clientSSL.getsockname()
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002426
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002427 def test_shutdown_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002428 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002429 `Connection.set_shutdown` raises `TypeError` if called with arguments
2430 other than integers.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002431 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002432 connection = Connection(Context(TLSv1_METHOD), None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002433 with pytest.raises(TypeError):
2434 connection.set_shutdown(None)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002435
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002436 def test_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002437 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002438 `Connection.shutdown` performs an SSL-level connection shutdown.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002439 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002440 server, client = loopback()
2441 assert not server.shutdown()
2442 assert server.get_shutdown() == SENT_SHUTDOWN
2443 with pytest.raises(ZeroReturnError):
2444 client.recv(1024)
2445 assert client.get_shutdown() == RECEIVED_SHUTDOWN
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04002446 client.shutdown()
Alex Chan1c0cb662017-01-30 07:13:30 +00002447 assert client.get_shutdown() == (SENT_SHUTDOWN | RECEIVED_SHUTDOWN)
2448 with pytest.raises(ZeroReturnError):
2449 server.recv(1024)
2450 assert server.get_shutdown() == (SENT_SHUTDOWN | RECEIVED_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002451
Paul Aurichc85e0862015-01-08 08:34:33 -08002452 def test_shutdown_closed(self):
2453 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002454 If the underlying socket is closed, `Connection.shutdown` propagates
2455 the write error from the low level write call.
Paul Aurichc85e0862015-01-08 08:34:33 -08002456 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002457 server, client = loopback()
Paul Aurichc85e0862015-01-08 08:34:33 -08002458 server.sock_shutdown(2)
Alex Chan1c0cb662017-01-30 07:13:30 +00002459 with pytest.raises(SysCallError) as exc:
2460 server.shutdown()
Alex Chanfb078d82017-04-20 11:16:15 +01002461 if platform == "win32":
2462 assert exc.value.args[0] == ESHUTDOWN
2463 else:
2464 assert exc.value.args[0] == EPIPE
Paul Aurichc85e0862015-01-08 08:34:33 -08002465
Glyph89389472015-04-14 17:29:26 -04002466 def test_shutdown_truncated(self):
Glyph6064ec32015-04-14 16:38:22 -04002467 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002468 If the underlying connection is truncated, `Connection.shutdown`
2469 raises an `Error`.
Glyph6064ec32015-04-14 16:38:22 -04002470 """
Glyph89389472015-04-14 17:29:26 -04002471 server_ctx = Context(TLSv1_METHOD)
2472 client_ctx = Context(TLSv1_METHOD)
2473 server_ctx.use_privatekey(
Alex Gaynor03737182020-07-23 20:40:46 -04002474 load_privatekey(FILETYPE_PEM, server_key_pem)
2475 )
Glyph89389472015-04-14 17:29:26 -04002476 server_ctx.use_certificate(
Alex Gaynor03737182020-07-23 20:40:46 -04002477 load_certificate(FILETYPE_PEM, server_cert_pem)
2478 )
Glyph89389472015-04-14 17:29:26 -04002479 server = Connection(server_ctx, None)
2480 client = Connection(client_ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002481 handshake_in_memory(client, server)
2482 assert not server.shutdown()
2483 with pytest.raises(WantReadError):
2484 server.shutdown()
Glyph89389472015-04-14 17:29:26 -04002485 server.bio_shutdown()
Alex Chan1c0cb662017-01-30 07:13:30 +00002486 with pytest.raises(Error):
2487 server.shutdown()
Glyph6064ec32015-04-14 16:38:22 -04002488
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002489 def test_set_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002490 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002491 `Connection.set_shutdown` sets the state of the SSL connection
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002492 shutdown process.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002493 """
David Benjamin1fbe0642019-04-15 17:05:13 -05002494 connection = Connection(Context(TLSv1_METHOD), socket_any_family())
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002495 connection.set_shutdown(RECEIVED_SHUTDOWN)
Alex Chan1c0cb662017-01-30 07:13:30 +00002496 assert connection.get_shutdown() == RECEIVED_SHUTDOWN
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002497
kjavaf248592015-09-07 12:14:01 +01002498 def test_state_string(self):
2499 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002500 `Connection.state_string` verbosely describes the current state of
2501 the `Connection`.
kjavaf248592015-09-07 12:14:01 +01002502 """
Hynek Schlawackb0274ce2015-10-16 19:56:26 +02002503 server, client = socket_pair()
Alex Chan1c0cb662017-01-30 07:13:30 +00002504 server = loopback_server_factory(server)
2505 client = loopback_client_factory(client)
kjavaf248592015-09-07 12:14:01 +01002506
Alex Gaynor5af32d02016-09-24 01:52:21 -04002507 assert server.get_state_string() in [
Alex Gaynor03737182020-07-23 20:40:46 -04002508 b"before/accept initialization",
2509 b"before SSL initialization",
Alex Gaynor5af32d02016-09-24 01:52:21 -04002510 ]
2511 assert client.get_state_string() in [
Alex Gaynor03737182020-07-23 20:40:46 -04002512 b"before/connect initialization",
2513 b"before SSL initialization",
Alex Gaynor5af32d02016-09-24 01:52:21 -04002514 ]
kjavaf248592015-09-07 12:14:01 +01002515
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002516 def test_app_data(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002517 """
2518 Any object can be set as app data by passing it to
Alex Chan1c0cb662017-01-30 07:13:30 +00002519 `Connection.set_app_data` and later retrieved with
2520 `Connection.get_app_data`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002521 """
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002522 conn = Connection(Context(TLSv1_METHOD), None)
Todd Chapman4f73e4f2015-08-27 11:26:43 -04002523 assert None is conn.get_app_data()
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002524 app_data = object()
2525 conn.set_app_data(app_data)
Todd Chapman4f73e4f2015-08-27 11:26:43 -04002526 assert conn.get_app_data() is app_data
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002527
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002528 def test_makefile(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002529 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002530 `Connection.makefile` is not implemented and calling that
2531 method raises `NotImplementedError`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002532 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002533 conn = Connection(Context(TLSv1_METHOD), None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002534 with pytest.raises(NotImplementedError):
2535 conn.makefile()
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002536
Jeremy Lainé460a19d2018-05-16 19:44:19 +02002537 def test_get_certificate(self):
2538 """
2539 `Connection.get_certificate` returns the local certificate.
2540 """
2541 chain = _create_certificate_chain()
2542 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
2543
2544 context = Context(TLSv1_METHOD)
2545 context.use_certificate(scert)
2546 client = Connection(context, None)
2547 cert = client.get_certificate()
2548 assert cert is not None
2549 assert "Server Certificate" == cert.get_subject().CN
2550
2551 def test_get_certificate_none(self):
2552 """
2553 `Connection.get_certificate` returns the local certificate.
2554
2555 If there is no certificate, it returns None.
2556 """
2557 context = Context(TLSv1_METHOD)
2558 client = Connection(context, None)
2559 cert = client.get_certificate()
2560 assert cert is None
2561
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002562 def test_get_peer_cert_chain(self):
2563 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002564 `Connection.get_peer_cert_chain` returns a list of certificates
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002565 which the connected server returned for the certification verification.
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002566 """
2567 chain = _create_certificate_chain()
2568 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
2569
2570 serverContext = Context(TLSv1_METHOD)
2571 serverContext.use_privatekey(skey)
2572 serverContext.use_certificate(scert)
2573 serverContext.add_extra_chain_cert(icert)
2574 serverContext.add_extra_chain_cert(cacert)
2575 server = Connection(serverContext, None)
2576 server.set_accept_state()
2577
2578 # Create the client
2579 clientContext = Context(TLSv1_METHOD)
2580 clientContext.set_verify(VERIFY_NONE, verify_cb)
2581 client = Connection(clientContext, None)
2582 client.set_connect_state()
2583
Alex Chan1c0cb662017-01-30 07:13:30 +00002584 interact_in_memory(client, server)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002585
2586 chain = client.get_peer_cert_chain()
Alex Chan1c0cb662017-01-30 07:13:30 +00002587 assert len(chain) == 3
2588 assert "Server Certificate" == chain[0].get_subject().CN
2589 assert "Intermediate Certificate" == chain[1].get_subject().CN
2590 assert "Authority Certificate" == chain[2].get_subject().CN
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002591
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002592 def test_get_peer_cert_chain_none(self):
2593 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002594 `Connection.get_peer_cert_chain` returns `None` if the peer sends
2595 no certificate chain.
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002596 """
2597 ctx = Context(TLSv1_METHOD)
2598 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2599 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
2600 server = Connection(ctx, None)
2601 server.set_accept_state()
2602 client = Connection(Context(TLSv1_METHOD), None)
2603 client.set_connect_state()
Alex Chan1c0cb662017-01-30 07:13:30 +00002604 interact_in_memory(client, server)
2605 assert None is server.get_peer_cert_chain()
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002606
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002607 def test_get_session_unconnected(self):
2608 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002609 `Connection.get_session` returns `None` when used with an object
2610 which has not been connected.
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002611 """
2612 ctx = Context(TLSv1_METHOD)
2613 server = Connection(ctx, None)
2614 session = server.get_session()
Alex Chan1c0cb662017-01-30 07:13:30 +00002615 assert None is session
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002616
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002617 def test_server_get_session(self):
2618 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002619 On the server side of a connection, `Connection.get_session` returns a
2620 `Session` instance representing the SSL session for that connection.
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002621 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002622 server, client = loopback()
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002623 session = server.get_session()
Alex Chan1c0cb662017-01-30 07:13:30 +00002624 assert isinstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002625
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002626 def test_client_get_session(self):
2627 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002628 On the client side of a connection, `Connection.get_session`
2629 returns a `Session` instance representing the SSL session for
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002630 that connection.
2631 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002632 server, client = loopback()
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002633 session = client.get_session()
Alex Chan1c0cb662017-01-30 07:13:30 +00002634 assert isinstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002635
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002636 def test_set_session_wrong_args(self):
2637 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002638 `Connection.set_session` raises `TypeError` if called with an object
2639 that is not an instance of `Session`.
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002640 """
2641 ctx = Context(TLSv1_METHOD)
2642 connection = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002643 with pytest.raises(TypeError):
2644 connection.set_session(123)
2645 with pytest.raises(TypeError):
2646 connection.set_session("hello")
2647 with pytest.raises(TypeError):
2648 connection.set_session(object())
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002649
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002650 def test_client_set_session(self):
2651 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002652 `Connection.set_session`, when used prior to a connection being
2653 established, accepts a `Session` instance and causes an attempt to
2654 re-use the session it represents when the SSL handshake is performed.
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002655 """
2656 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2657 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
Paul Kehrer7d5a3bf2019-01-21 12:24:02 -06002658 ctx = Context(TLSv1_2_METHOD)
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002659 ctx.use_privatekey(key)
2660 ctx.use_certificate(cert)
2661 ctx.set_session_id("unity-test")
2662
2663 def makeServer(socket):
2664 server = Connection(ctx, socket)
2665 server.set_accept_state()
2666 return server
2667
Alex Gaynor03737182020-07-23 20:40:46 -04002668 originalServer, originalClient = loopback(server_factory=makeServer)
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002669 originalSession = originalClient.get_session()
2670
2671 def makeClient(socket):
Alex Chan1c0cb662017-01-30 07:13:30 +00002672 client = loopback_client_factory(socket)
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002673 client.set_session(originalSession)
2674 return client
Alex Gaynor03737182020-07-23 20:40:46 -04002675
Alex Chan1c0cb662017-01-30 07:13:30 +00002676 resumedServer, resumedClient = loopback(
Alex Gaynor03737182020-07-23 20:40:46 -04002677 server_factory=makeServer, client_factory=makeClient
2678 )
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002679
2680 # This is a proxy: in general, we have no access to any unique
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002681 # identifier for the session (new enough versions of OpenSSL expose
2682 # a hash which could be usable, but "new enough" is very, very new).
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002683 # Instead, exploit the fact that the master key is re-used if the
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002684 # session is re-used. As long as the master key for the two
2685 # connections is the same, the session was re-used!
Alex Chan1c0cb662017-01-30 07:13:30 +00002686 assert originalServer.master_key() == resumedServer.master_key()
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002687
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002688 def test_set_session_wrong_method(self):
2689 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002690 If `Connection.set_session` is passed a `Session` instance associated
2691 with a context using a different SSL method than the `Connection`
2692 is using, a `OpenSSL.SSL.Error` is raised.
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002693 """
Alex Gaynor5af32d02016-09-24 01:52:21 -04002694 # Make this work on both OpenSSL 1.0.0, which doesn't support TLSv1.2
2695 # and also on OpenSSL 1.1.0 which doesn't support SSLv3. (SSL_ST_INIT
2696 # is a way to check for 1.1.0)
Alex Gaynoraa32e712017-06-29 20:56:12 -07002697 if SSL_ST_INIT is None:
2698 v1 = TLSv1_2_METHOD
2699 v2 = TLSv1_METHOD
2700 elif hasattr(_lib, "SSLv3_method"):
Alex Gaynor5af32d02016-09-24 01:52:21 -04002701 v1 = TLSv1_METHOD
2702 v2 = SSLv3_METHOD
2703 else:
Alex Gaynoraa32e712017-06-29 20:56:12 -07002704 pytest.skip("Test requires either OpenSSL 1.1.0 or SSLv3")
Alex Gaynor5af32d02016-09-24 01:52:21 -04002705
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002706 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2707 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
Alex Gaynor5af32d02016-09-24 01:52:21 -04002708 ctx = Context(v1)
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002709 ctx.use_privatekey(key)
2710 ctx.use_certificate(cert)
2711 ctx.set_session_id("unity-test")
2712
2713 def makeServer(socket):
2714 server = Connection(ctx, socket)
2715 server.set_accept_state()
2716 return server
2717
Alex Gaynor5af32d02016-09-24 01:52:21 -04002718 def makeOriginalClient(socket):
2719 client = Connection(Context(v1), socket)
2720 client.set_connect_state()
2721 return client
2722
Alex Chan1c0cb662017-01-30 07:13:30 +00002723 originalServer, originalClient = loopback(
Alex Gaynor03737182020-07-23 20:40:46 -04002724 server_factory=makeServer, client_factory=makeOriginalClient
2725 )
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002726 originalSession = originalClient.get_session()
2727
2728 def makeClient(socket):
2729 # Intentionally use a different, incompatible method here.
Alex Gaynor5af32d02016-09-24 01:52:21 -04002730 client = Connection(Context(v2), socket)
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002731 client.set_connect_state()
2732 client.set_session(originalSession)
2733 return client
2734
Alex Chan1c0cb662017-01-30 07:13:30 +00002735 with pytest.raises(Error):
2736 loopback(client_factory=makeClient, server_factory=makeServer)
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002737
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002738 def test_wantWriteError(self):
2739 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002740 `Connection` methods which generate output raise
2741 `OpenSSL.SSL.WantWriteError` if writing to the connection's BIO
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002742 fail indicating a should-write state.
2743 """
2744 client_socket, server_socket = socket_pair()
2745 # Fill up the client's send buffer so Connection won't be able to write
Jean-Paul Calderonebbff8b92014-03-22 14:20:30 -04002746 # anything. Only write a single byte at a time so we can be sure we
2747 # completely fill the buffer. Even though the socket API is allowed to
2748 # signal a short write via its return value it seems this doesn't
2749 # always happen on all platforms (FreeBSD and OS X particular) for the
2750 # very last bit of available buffer space.
2751 msg = b"x"
caternb2777a42018-08-09 15:38:13 -04002752 for i in range(1024 * 1024 * 64):
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002753 try:
2754 client_socket.send(msg)
2755 except error as e:
2756 if e.errno == EWOULDBLOCK:
2757 break
2758 raise
2759 else:
Alex Chan1c0cb662017-01-30 07:13:30 +00002760 pytest.fail(
Alex Gaynor03737182020-07-23 20:40:46 -04002761 "Failed to fill socket buffer, cannot test BIO want write"
2762 )
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002763
2764 ctx = Context(TLSv1_METHOD)
2765 conn = Connection(ctx, client_socket)
2766 # Client's speak first, so make it an SSL client
2767 conn.set_connect_state()
Alex Chan1c0cb662017-01-30 07:13:30 +00002768 with pytest.raises(WantWriteError):
2769 conn.do_handshake()
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002770
2771 # XXX want_read
2772
Fedor Brunner416f4a12014-03-28 13:18:38 +01002773 def test_get_finished_before_connect(self):
Fedor Brunner5747b932014-03-05 14:22:34 +01002774 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002775 `Connection.get_finished` returns `None` before TLS handshake
2776 is completed.
Fedor Brunner5747b932014-03-05 14:22:34 +01002777 """
Fedor Brunner5747b932014-03-05 14:22:34 +01002778 ctx = Context(TLSv1_METHOD)
2779 connection = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002780 assert connection.get_finished() is None
Fedor Brunner416f4a12014-03-28 13:18:38 +01002781
2782 def test_get_peer_finished_before_connect(self):
2783 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002784 `Connection.get_peer_finished` returns `None` before TLS handshake
2785 is completed.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002786 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002787 ctx = Context(TLSv1_METHOD)
2788 connection = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002789 assert connection.get_peer_finished() is None
Fedor Brunner5747b932014-03-05 14:22:34 +01002790
Fedor Brunner416f4a12014-03-28 13:18:38 +01002791 def test_get_finished(self):
2792 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002793 `Connection.get_finished` method returns the TLS Finished message send
2794 from client, or server. Finished messages are send during
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002795 TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002796 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002797 server, client = loopback()
Fedor Brunner416f4a12014-03-28 13:18:38 +01002798
Alex Chan1c0cb662017-01-30 07:13:30 +00002799 assert server.get_finished() is not None
2800 assert len(server.get_finished()) > 0
Fedor Brunner416f4a12014-03-28 13:18:38 +01002801
2802 def test_get_peer_finished(self):
2803 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002804 `Connection.get_peer_finished` method returns the TLS Finished
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002805 message received from client, or server. Finished messages are send
2806 during TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002807 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002808 server, client = loopback()
Fedor Brunner416f4a12014-03-28 13:18:38 +01002809
Alex Chan1c0cb662017-01-30 07:13:30 +00002810 assert server.get_peer_finished() is not None
2811 assert len(server.get_peer_finished()) > 0
Fedor Brunner5747b932014-03-05 14:22:34 +01002812
Fedor Brunner416f4a12014-03-28 13:18:38 +01002813 def test_tls_finished_message_symmetry(self):
2814 """
Hynek Schlawackdddd1112015-09-05 21:12:30 +02002815 The TLS Finished message send by server must be the TLS Finished
2816 message received by client.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002817
Hynek Schlawackdddd1112015-09-05 21:12:30 +02002818 The TLS Finished message send by client must be the TLS Finished
2819 message received by server.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002820 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002821 server, client = loopback()
Fedor Brunner416f4a12014-03-28 13:18:38 +01002822
Alex Chan1c0cb662017-01-30 07:13:30 +00002823 assert server.get_finished() == client.get_peer_finished()
2824 assert client.get_finished() == server.get_peer_finished()
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002825
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002826 def test_get_cipher_name_before_connect(self):
2827 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002828 `Connection.get_cipher_name` returns `None` if no connection
2829 has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002830 """
2831 ctx = Context(TLSv1_METHOD)
2832 conn = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002833 assert conn.get_cipher_name() is None
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002834
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002835 def test_get_cipher_name(self):
2836 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002837 `Connection.get_cipher_name` returns a `unicode` string giving the
2838 name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002839 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002840 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04002841 server_cipher_name, client_cipher_name = (
2842 server.get_cipher_name(),
2843 client.get_cipher_name(),
2844 )
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002845
Alex Chan1c0cb662017-01-30 07:13:30 +00002846 assert isinstance(server_cipher_name, text_type)
2847 assert isinstance(client_cipher_name, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002848
Alex Chan1c0cb662017-01-30 07:13:30 +00002849 assert server_cipher_name == client_cipher_name
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002850
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002851 def test_get_cipher_version_before_connect(self):
2852 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002853 `Connection.get_cipher_version` returns `None` if no connection
2854 has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002855 """
2856 ctx = Context(TLSv1_METHOD)
2857 conn = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002858 assert conn.get_cipher_version() is None
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002859
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002860 def test_get_cipher_version(self):
2861 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002862 `Connection.get_cipher_version` returns a `unicode` string giving
2863 the protocol name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002864 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002865 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04002866 server_cipher_version, client_cipher_version = (
2867 server.get_cipher_version(),
2868 client.get_cipher_version(),
2869 )
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002870
Alex Chan1c0cb662017-01-30 07:13:30 +00002871 assert isinstance(server_cipher_version, text_type)
2872 assert isinstance(client_cipher_version, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002873
Alex Chan1c0cb662017-01-30 07:13:30 +00002874 assert server_cipher_version == client_cipher_version
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002875
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002876 def test_get_cipher_bits_before_connect(self):
2877 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002878 `Connection.get_cipher_bits` returns `None` if no connection has
2879 been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002880 """
2881 ctx = Context(TLSv1_METHOD)
2882 conn = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002883 assert conn.get_cipher_bits() is None
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002884
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002885 def test_get_cipher_bits(self):
2886 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002887 `Connection.get_cipher_bits` returns the number of secret bits
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002888 of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002889 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002890 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04002891 server_cipher_bits, client_cipher_bits = (
2892 server.get_cipher_bits(),
2893 client.get_cipher_bits(),
2894 )
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002895
Alex Chan1c0cb662017-01-30 07:13:30 +00002896 assert isinstance(server_cipher_bits, int)
2897 assert isinstance(client_cipher_bits, int)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002898
Alex Chan1c0cb662017-01-30 07:13:30 +00002899 assert server_cipher_bits == client_cipher_bits
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002900
Jim Shaverabff1882015-05-27 09:15:55 -04002901 def test_get_protocol_version_name(self):
2902 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002903 `Connection.get_protocol_version_name()` returns a string giving the
2904 protocol version of the current connection.
Jim Shaverabff1882015-05-27 09:15:55 -04002905 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002906 server, client = loopback()
Jim Shaverabff1882015-05-27 09:15:55 -04002907 client_protocol_version_name = client.get_protocol_version_name()
2908 server_protocol_version_name = server.get_protocol_version_name()
2909
Alex Chan1c0cb662017-01-30 07:13:30 +00002910 assert isinstance(server_protocol_version_name, text_type)
2911 assert isinstance(client_protocol_version_name, text_type)
Jim Shaverabff1882015-05-27 09:15:55 -04002912
Alex Chan1c0cb662017-01-30 07:13:30 +00002913 assert server_protocol_version_name == client_protocol_version_name
Jim Shaverabff1882015-05-27 09:15:55 -04002914
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002915 def test_get_protocol_version(self):
2916 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002917 `Connection.get_protocol_version()` returns an integer
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002918 giving the protocol version of the current connection.
2919 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002920 server, client = loopback()
Jim Shaver85a4dff2015-04-27 17:42:46 -04002921 client_protocol_version = client.get_protocol_version()
2922 server_protocol_version = server.get_protocol_version()
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002923
Alex Chan1c0cb662017-01-30 07:13:30 +00002924 assert isinstance(server_protocol_version, int)
2925 assert isinstance(client_protocol_version, int)
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002926
Alex Chan1c0cb662017-01-30 07:13:30 +00002927 assert server_protocol_version == client_protocol_version
2928
2929 def test_wantReadError(self):
2930 """
2931 `Connection.bio_read` raises `OpenSSL.SSL.WantReadError` if there are
2932 no bytes available to be read from the BIO.
2933 """
2934 ctx = Context(TLSv1_METHOD)
2935 conn = Connection(ctx, None)
2936 with pytest.raises(WantReadError):
2937 conn.bio_read(1024)
2938
Alex Gaynor03737182020-07-23 20:40:46 -04002939 @pytest.mark.parametrize("bufsize", [1.0, None, object(), "bufsize"])
Alex Chanfb078d82017-04-20 11:16:15 +01002940 def test_bio_read_wrong_args(self, bufsize):
2941 """
2942 `Connection.bio_read` raises `TypeError` if passed a non-integer
2943 argument.
2944 """
2945 ctx = Context(TLSv1_METHOD)
2946 conn = Connection(ctx, None)
2947 with pytest.raises(TypeError):
2948 conn.bio_read(bufsize)
2949
Alex Chan1c0cb662017-01-30 07:13:30 +00002950 def test_buffer_size(self):
2951 """
2952 `Connection.bio_read` accepts an integer giving the maximum number
2953 of bytes to read and return.
2954 """
2955 ctx = Context(TLSv1_METHOD)
2956 conn = Connection(ctx, None)
2957 conn.set_connect_state()
2958 try:
2959 conn.do_handshake()
2960 except WantReadError:
2961 pass
2962 data = conn.bio_read(2)
2963 assert 2 == len(data)
2964
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002965
Alex Chanb7480992017-01-30 14:04:47 +00002966class TestConnectionGetCipherList(object):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002967 """
Alex Chanb7480992017-01-30 14:04:47 +00002968 Tests for `Connection.get_cipher_list`.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002969 """
Alex Gaynor03737182020-07-23 20:40:46 -04002970
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002971 def test_result(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002972 """
Alex Chanb7480992017-01-30 14:04:47 +00002973 `Connection.get_cipher_list` returns a list of `bytes` giving the
2974 names of the ciphers which might be used.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002975 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002976 connection = Connection(Context(TLSv1_METHOD), None)
2977 ciphers = connection.get_cipher_list()
Alex Chanb7480992017-01-30 14:04:47 +00002978 assert isinstance(ciphers, list)
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002979 for cipher in ciphers:
Alex Chanb7480992017-01-30 14:04:47 +00002980 assert isinstance(cipher, str)
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002981
2982
Maximilian Hils868dc3c2017-02-10 14:56:55 +01002983class VeryLarge(bytes):
2984 """
2985 Mock object so that we don't have to allocate 2**31 bytes
2986 """
Alex Gaynor03737182020-07-23 20:40:46 -04002987
Maximilian Hils868dc3c2017-02-10 14:56:55 +01002988 def __len__(self):
Alex Gaynor03737182020-07-23 20:40:46 -04002989 return 2 ** 31
Maximilian Hils868dc3c2017-02-10 14:56:55 +01002990
2991
Alex Chanb7480992017-01-30 14:04:47 +00002992class TestConnectionSend(object):
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002993 """
Alex Chanb7480992017-01-30 14:04:47 +00002994 Tests for `Connection.send`.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002995 """
Alex Gaynor03737182020-07-23 20:40:46 -04002996
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002997 def test_wrong_args(self):
2998 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002999 When called with arguments other than string argument for its first
Alex Chanb7480992017-01-30 14:04:47 +00003000 parameter, `Connection.send` raises `TypeError`.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05003001 """
3002 connection = Connection(Context(TLSv1_METHOD), None)
Alex Chanb7480992017-01-30 14:04:47 +00003003 with pytest.raises(TypeError):
3004 connection.send(object())
Daniel Holth079c9632019-11-17 22:45:52 -05003005 with pytest.raises(TypeError):
3006 connection.send([1, 2, 3])
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05003007
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05003008 def test_short_bytes(self):
3009 """
Alex Chanb7480992017-01-30 14:04:47 +00003010 When passed a short byte string, `Connection.send` transmits all of it
3011 and returns the number of bytes sent.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05003012 """
Alex Chanb7480992017-01-30 14:04:47 +00003013 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04003014 count = server.send(b"xy")
Alex Chanb7480992017-01-30 14:04:47 +00003015 assert count == 2
Alex Gaynor03737182020-07-23 20:40:46 -04003016 assert client.recv(2) == b"xy"
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05003017
Abraham Martinef063482015-03-25 14:06:24 +00003018 def test_text(self):
3019 """
Alex Chanb7480992017-01-30 14:04:47 +00003020 When passed a text, `Connection.send` transmits all of it and
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04003021 returns the number of bytes sent. It also raises a DeprecationWarning.
Abraham Martinef063482015-03-25 14:06:24 +00003022 """
Alex Chanb7480992017-01-30 14:04:47 +00003023 server, client = loopback()
3024 with pytest.warns(DeprecationWarning) as w:
Abraham Martinef063482015-03-25 14:06:24 +00003025 simplefilter("always")
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04003026 count = server.send(b"xy".decode("ascii"))
Alex Gaynor03737182020-07-23 20:40:46 -04003027 assert "{0} for buf is no longer accepted, use bytes".format(
3028 WARNING_TYPE_EXPECTED
3029 ) == str(w[-1].message)
Alex Chanb7480992017-01-30 14:04:47 +00003030 assert count == 2
Alex Gaynor03737182020-07-23 20:40:46 -04003031 assert client.recv(2) == b"xy"
Abraham Martinef063482015-03-25 14:06:24 +00003032
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003033 def test_short_memoryview(self):
3034 """
3035 When passed a memoryview onto a small number of bytes,
Alex Chanb7480992017-01-30 14:04:47 +00003036 `Connection.send` transmits all of them and returns the number
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003037 of bytes sent.
3038 """
Alex Chanb7480992017-01-30 14:04:47 +00003039 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04003040 count = server.send(memoryview(b"xy"))
Alex Chanb7480992017-01-30 14:04:47 +00003041 assert count == 2
Alex Gaynor03737182020-07-23 20:40:46 -04003042 assert client.recv(2) == b"xy"
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05003043
Daniel Holth079c9632019-11-17 22:45:52 -05003044 def test_short_bytearray(self):
3045 """
3046 When passed a short bytearray, `Connection.send` transmits all of
3047 it and returns the number of bytes sent.
3048 """
3049 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04003050 count = server.send(bytearray(b"xy"))
Daniel Holth079c9632019-11-17 22:45:52 -05003051 assert count == 2
Alex Gaynor03737182020-07-23 20:40:46 -04003052 assert client.recv(2) == b"xy"
Daniel Holth079c9632019-11-17 22:45:52 -05003053
Hynek Schlawack8e94f1b2015-09-05 21:31:00 +02003054 @skip_if_py3
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003055 def test_short_buffer(self):
3056 """
3057 When passed a buffer containing a small number of bytes,
Alex Chanb7480992017-01-30 14:04:47 +00003058 `Connection.send` transmits all of them and returns the number
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003059 of bytes sent.
3060 """
Alex Chanb7480992017-01-30 14:04:47 +00003061 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04003062 count = server.send(buffer(b"xy")) # noqa: F821
Alex Chanb7480992017-01-30 14:04:47 +00003063 assert count == 2
Alex Gaynor03737182020-07-23 20:40:46 -04003064 assert client.recv(2) == b"xy"
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02003065
Maximilian Hils868dc3c2017-02-10 14:56:55 +01003066 @pytest.mark.skipif(
Alex Gaynor03737182020-07-23 20:40:46 -04003067 sys.maxsize < 2 ** 31,
3068 reason="sys.maxsize < 2**31 - test requires 64 bit",
Maximilian Hils868dc3c2017-02-10 14:56:55 +01003069 )
3070 def test_buf_too_large(self):
3071 """
3072 When passed a buffer containing >= 2**31 bytes,
3073 `Connection.send` bails out as SSL_write only
3074 accepts an int for the buffer length.
3075 """
3076 connection = Connection(Context(TLSv1_METHOD), None)
3077 with pytest.raises(ValueError) as exc_info:
3078 connection.send(VeryLarge())
3079 exc_info.match(r"Cannot send more than .+ bytes at once")
3080
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05003081
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003082def _make_memoryview(size):
3083 """
3084 Create a new ``memoryview`` wrapped around a ``bytearray`` of the given
3085 size.
3086 """
3087 return memoryview(bytearray(size))
3088
3089
Alex Chanb7480992017-01-30 14:04:47 +00003090class TestConnectionRecvInto(object):
Cory Benfield62d10332014-06-15 10:03:41 +01003091 """
Alex Chanb7480992017-01-30 14:04:47 +00003092 Tests for `Connection.recv_into`.
Cory Benfield62d10332014-06-15 10:03:41 +01003093 """
Alex Gaynor03737182020-07-23 20:40:46 -04003094
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003095 def _no_length_test(self, factory):
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04003096 """
Alex Chanb7480992017-01-30 14:04:47 +00003097 Assert that when the given buffer is passed to `Connection.recv_into`,
3098 whatever bytes are available to be received that fit into that buffer
3099 are written into that buffer.
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04003100 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003101 output_buffer = factory(5)
3102
Alex Chanb7480992017-01-30 14:04:47 +00003103 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04003104 server.send(b"xy")
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04003105
Alex Chanb7480992017-01-30 14:04:47 +00003106 assert client.recv_into(output_buffer) == 2
Alex Gaynor03737182020-07-23 20:40:46 -04003107 assert output_buffer == bytearray(b"xy\x00\x00\x00")
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04003108
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04003109 def test_bytearray_no_length(self):
Cory Benfield62d10332014-06-15 10:03:41 +01003110 """
Alex Chanb7480992017-01-30 14:04:47 +00003111 `Connection.recv_into` can be passed a `bytearray` instance and data
3112 in the receive buffer is written to it.
Cory Benfield62d10332014-06-15 10:03:41 +01003113 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003114 self._no_length_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01003115
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003116 def _respects_length_test(self, factory):
Cory Benfield62d10332014-06-15 10:03:41 +01003117 """
Alex Chanb7480992017-01-30 14:04:47 +00003118 Assert that when the given buffer is passed to `Connection.recv_into`
3119 along with a value for `nbytes` that is less than the size of that
3120 buffer, only `nbytes` bytes are written into the buffer.
Cory Benfield62d10332014-06-15 10:03:41 +01003121 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003122 output_buffer = factory(10)
3123
Alex Chanb7480992017-01-30 14:04:47 +00003124 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04003125 server.send(b"abcdefghij")
Cory Benfield62d10332014-06-15 10:03:41 +01003126
Alex Chanb7480992017-01-30 14:04:47 +00003127 assert client.recv_into(output_buffer, 5) == 5
Alex Gaynor03737182020-07-23 20:40:46 -04003128 assert output_buffer == bytearray(b"abcde\x00\x00\x00\x00\x00")
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04003129
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04003130 def test_bytearray_respects_length(self):
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04003131 """
Alex Chanb7480992017-01-30 14:04:47 +00003132 When called with a `bytearray` instance, `Connection.recv_into`
3133 respects the `nbytes` parameter and doesn't copy in more than that
3134 number of bytes.
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04003135 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003136 self._respects_length_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01003137
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003138 def _doesnt_overfill_test(self, factory):
Cory Benfield62d10332014-06-15 10:03:41 +01003139 """
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04003140 Assert that if there are more bytes available to be read from the
3141 receive buffer than would fit into the buffer passed to
Alex Chanb7480992017-01-30 14:04:47 +00003142 `Connection.recv_into`, only as many as fit are written into it.
Cory Benfield62d10332014-06-15 10:03:41 +01003143 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003144 output_buffer = factory(5)
3145
Alex Chanb7480992017-01-30 14:04:47 +00003146 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04003147 server.send(b"abcdefghij")
Cory Benfield62d10332014-06-15 10:03:41 +01003148
Alex Chanb7480992017-01-30 14:04:47 +00003149 assert client.recv_into(output_buffer) == 5
Alex Gaynor03737182020-07-23 20:40:46 -04003150 assert output_buffer == bytearray(b"abcde")
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04003151 rest = client.recv(5)
Alex Gaynor03737182020-07-23 20:40:46 -04003152 assert b"fghij" == rest
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04003153
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04003154 def test_bytearray_doesnt_overfill(self):
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04003155 """
Alex Chanb7480992017-01-30 14:04:47 +00003156 When called with a `bytearray` instance, `Connection.recv_into`
3157 respects the size of the array and doesn't write more bytes into it
3158 than will fit.
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04003159 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003160 self._doesnt_overfill_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01003161
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04003162 def test_bytearray_really_doesnt_overfill(self):
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003163 """
Alex Chanb7480992017-01-30 14:04:47 +00003164 When called with a `bytearray` instance and an `nbytes` value that is
3165 too large, `Connection.recv_into` respects the size of the array and
3166 not the `nbytes` value and doesn't write more bytes into the buffer
3167 than will fit.
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003168 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003169 self._doesnt_overfill_test(bytearray)
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003170
Maximilian Hils1d95dea2015-08-17 19:27:20 +02003171 def test_peek(self):
Alex Chanb7480992017-01-30 14:04:47 +00003172 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04003173 server.send(b"xy")
Maximilian Hils1d95dea2015-08-17 19:27:20 +02003174
3175 for _ in range(2):
3176 output_buffer = bytearray(5)
Alex Chanb7480992017-01-30 14:04:47 +00003177 assert client.recv_into(output_buffer, flags=MSG_PEEK) == 2
Alex Gaynor03737182020-07-23 20:40:46 -04003178 assert output_buffer == bytearray(b"xy\x00\x00\x00")
Maximilian Hils1d95dea2015-08-17 19:27:20 +02003179
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003180 def test_memoryview_no_length(self):
3181 """
Alex Chanb7480992017-01-30 14:04:47 +00003182 `Connection.recv_into` can be passed a `memoryview` instance and data
3183 in the receive buffer is written to it.
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003184 """
3185 self._no_length_test(_make_memoryview)
Maximilian Hils1d95dea2015-08-17 19:27:20 +02003186
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003187 def test_memoryview_respects_length(self):
3188 """
Alex Chanb7480992017-01-30 14:04:47 +00003189 When called with a `memoryview` instance, `Connection.recv_into`
3190 respects the ``nbytes`` parameter and doesn't copy more than that
3191 number of bytes in.
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003192 """
3193 self._respects_length_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01003194
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003195 def test_memoryview_doesnt_overfill(self):
3196 """
Alex Chanb7480992017-01-30 14:04:47 +00003197 When called with a `memoryview` instance, `Connection.recv_into`
3198 respects the size of the array and doesn't write more bytes into it
3199 than will fit.
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003200 """
3201 self._doesnt_overfill_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01003202
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003203 def test_memoryview_really_doesnt_overfill(self):
3204 """
Alex Chanb7480992017-01-30 14:04:47 +00003205 When called with a `memoryview` instance and an `nbytes` value that is
3206 too large, `Connection.recv_into` respects the size of the array and
3207 not the `nbytes` value and doesn't write more bytes into the buffer
3208 than will fit.
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003209 """
3210 self._doesnt_overfill_test(_make_memoryview)
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003211
Cory Benfield62d10332014-06-15 10:03:41 +01003212
Alex Chanb7480992017-01-30 14:04:47 +00003213class TestConnectionSendall(object):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003214 """
Alex Chanb7480992017-01-30 14:04:47 +00003215 Tests for `Connection.sendall`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003216 """
Alex Gaynor03737182020-07-23 20:40:46 -04003217
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003218 def test_wrong_args(self):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003219 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003220 When called with arguments other than a string argument for its first
Alex Chanb7480992017-01-30 14:04:47 +00003221 parameter, `Connection.sendall` raises `TypeError`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003222 """
3223 connection = Connection(Context(TLSv1_METHOD), None)
Alex Chanb7480992017-01-30 14:04:47 +00003224 with pytest.raises(TypeError):
3225 connection.sendall(object())
Daniel Holth079c9632019-11-17 22:45:52 -05003226 with pytest.raises(TypeError):
3227 connection.sendall([1, 2, 3])
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003228
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003229 def test_short(self):
3230 """
Alex Chanb7480992017-01-30 14:04:47 +00003231 `Connection.sendall` transmits all of the bytes in the string
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003232 passed to it.
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003233 """
Alex Chanb7480992017-01-30 14:04:47 +00003234 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04003235 server.sendall(b"x")
3236 assert client.recv(1) == b"x"
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003237
Abraham Martinef063482015-03-25 14:06:24 +00003238 def test_text(self):
3239 """
Alex Chanb7480992017-01-30 14:04:47 +00003240 `Connection.sendall` transmits all the content in the string passed
3241 to it, raising a DeprecationWarning in case of this being a text.
Abraham Martinef063482015-03-25 14:06:24 +00003242 """
Alex Chanb7480992017-01-30 14:04:47 +00003243 server, client = loopback()
3244 with pytest.warns(DeprecationWarning) as w:
Abraham Martinef063482015-03-25 14:06:24 +00003245 simplefilter("always")
Jean-Paul Calderone8dc37a12015-03-29 08:16:52 -04003246 server.sendall(b"x".decode("ascii"))
Alex Gaynor03737182020-07-23 20:40:46 -04003247 assert "{0} for buf is no longer accepted, use bytes".format(
3248 WARNING_TYPE_EXPECTED
3249 ) == str(w[-1].message)
Alex Chanb7480992017-01-30 14:04:47 +00003250 assert client.recv(1) == b"x"
Abraham Martinef063482015-03-25 14:06:24 +00003251
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003252 def test_short_memoryview(self):
3253 """
3254 When passed a memoryview onto a small number of bytes,
Alex Chanb7480992017-01-30 14:04:47 +00003255 `Connection.sendall` transmits all of them.
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003256 """
Alex Chanb7480992017-01-30 14:04:47 +00003257 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04003258 server.sendall(memoryview(b"x"))
3259 assert client.recv(1) == b"x"
Abraham Martinef063482015-03-25 14:06:24 +00003260
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003261 @skip_if_py3
3262 def test_short_buffers(self):
3263 """
3264 When passed a buffer containing a small number of bytes,
Alex Chanb7480992017-01-30 14:04:47 +00003265 `Connection.sendall` transmits all of them.
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003266 """
Alex Chanb7480992017-01-30 14:04:47 +00003267 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04003268 count = server.sendall(buffer(b"xy")) # noqa: F821
Daniel Holth079c9632019-11-17 22:45:52 -05003269 assert count == 2
Alex Gaynor03737182020-07-23 20:40:46 -04003270 assert client.recv(2) == b"xy"
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02003271
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003272 def test_long(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003273 """
Alex Chanb7480992017-01-30 14:04:47 +00003274 `Connection.sendall` transmits all the bytes in the string passed to it
3275 even if this requires multiple calls of an underlying write function.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003276 """
Alex Chanb7480992017-01-30 14:04:47 +00003277 server, client = loopback()
Jean-Paul Calderone6241c702010-09-16 19:59:24 -04003278 # Should be enough, underlying SSL_write should only do 16k at a time.
Hynek Schlawack35618382015-09-05 21:54:25 +02003279 # On Windows, after 32k of bytes the write will block (forever
3280 # - because no one is yet reading).
Alex Gaynor03737182020-07-23 20:40:46 -04003281 message = b"x" * (1024 * 32 - 1) + b"y"
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003282 server.sendall(message)
3283 accum = []
3284 received = 0
3285 while received < len(message):
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04003286 data = client.recv(1024)
3287 accum.append(data)
3288 received += len(data)
Alex Gaynor03737182020-07-23 20:40:46 -04003289 assert message == b"".join(accum)
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003290
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003291 def test_closed(self):
3292 """
Alex Chanb7480992017-01-30 14:04:47 +00003293 If the underlying socket is closed, `Connection.sendall` propagates the
3294 write error from the low level write call.
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003295 """
Alex Chanb7480992017-01-30 14:04:47 +00003296 server, client = loopback()
Jean-Paul Calderone05d43e82010-09-24 18:01:36 -04003297 server.sock_shutdown(2)
Alex Chanb7480992017-01-30 14:04:47 +00003298 with pytest.raises(SysCallError) as err:
3299 server.sendall(b"hello, world")
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +02003300 if platform == "win32":
Alex Chanb7480992017-01-30 14:04:47 +00003301 assert err.value.args[0] == ESHUTDOWN
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +02003302 else:
Alex Chanb7480992017-01-30 14:04:47 +00003303 assert err.value.args[0] == EPIPE
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003304
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003305
Alex Chanb7480992017-01-30 14:04:47 +00003306class TestConnectionRenegotiate(object):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003307 """
3308 Tests for SSL renegotiation APIs.
3309 """
Alex Gaynor03737182020-07-23 20:40:46 -04003310
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003311 def test_total_renegotiations(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003312 """
Alex Chanb7480992017-01-30 14:04:47 +00003313 `Connection.total_renegotiations` returns `0` before any renegotiations
3314 have happened.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003315 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003316 connection = Connection(Context(TLSv1_METHOD), None)
Alex Chanb7480992017-01-30 14:04:47 +00003317 assert connection.total_renegotiations() == 0
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003318
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003319 def test_renegotiate(self):
3320 """
3321 Go through a complete renegotiation cycle.
3322 """
Paul Kehrer7d5a3bf2019-01-21 12:24:02 -06003323 server, client = loopback(
3324 lambda s: loopback_server_factory(s, TLSv1_2_METHOD),
3325 lambda s: loopback_client_factory(s, TLSv1_2_METHOD),
3326 )
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003327
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003328 server.send(b"hello world")
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003329
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003330 assert b"hello world" == client.recv(len(b"hello world"))
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003331
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003332 assert 0 == server.total_renegotiations()
3333 assert False is server.renegotiate_pending()
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003334
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003335 assert True is server.renegotiate()
3336
3337 assert True is server.renegotiate_pending()
3338
3339 server.setblocking(False)
3340 client.setblocking(False)
3341
3342 client.do_handshake()
3343 server.do_handshake()
3344
3345 assert 1 == server.total_renegotiations()
3346 while False is server.renegotiate_pending():
3347 pass
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003348
3349
Alex Chanb7480992017-01-30 14:04:47 +00003350class TestError(object):
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003351 """
Alex Chanb7480992017-01-30 14:04:47 +00003352 Unit tests for `OpenSSL.SSL.Error`.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003353 """
Alex Gaynor03737182020-07-23 20:40:46 -04003354
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003355 def test_type(self):
3356 """
Alex Chanb7480992017-01-30 14:04:47 +00003357 `Error` is an exception type.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003358 """
Alex Chanb7480992017-01-30 14:04:47 +00003359 assert issubclass(Error, Exception)
Alex Gaynor03737182020-07-23 20:40:46 -04003360 assert Error.__name__ == "Error"
Rick Deane15b1472009-07-09 15:53:42 -05003361
3362
Alex Chanb7480992017-01-30 14:04:47 +00003363class TestConstants(object):
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003364 """
Alex Chanb7480992017-01-30 14:04:47 +00003365 Tests for the values of constants exposed in `OpenSSL.SSL`.
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003366
3367 These are values defined by OpenSSL intended only to be used as flags to
3368 OpenSSL APIs. The only assertions it seems can be made about them is
3369 their values.
3370 """
Alex Gaynor03737182020-07-23 20:40:46 -04003371
Hynek Schlawack35618382015-09-05 21:54:25 +02003372 @pytest.mark.skipif(
3373 OP_NO_QUERY_MTU is None,
Alex Gaynor03737182020-07-23 20:40:46 -04003374 reason="OP_NO_QUERY_MTU unavailable - OpenSSL version may be too old",
Hynek Schlawack35618382015-09-05 21:54:25 +02003375 )
3376 def test_op_no_query_mtu(self):
3377 """
Alex Chanb7480992017-01-30 14:04:47 +00003378 The value of `OpenSSL.SSL.OP_NO_QUERY_MTU` is 0x1000, the value
3379 of `SSL_OP_NO_QUERY_MTU` defined by `openssl/ssl.h`.
Hynek Schlawack35618382015-09-05 21:54:25 +02003380 """
Alex Chanb7480992017-01-30 14:04:47 +00003381 assert OP_NO_QUERY_MTU == 0x1000
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003382
Hynek Schlawack35618382015-09-05 21:54:25 +02003383 @pytest.mark.skipif(
3384 OP_COOKIE_EXCHANGE is None,
3385 reason="OP_COOKIE_EXCHANGE unavailable - "
Alex Gaynor03737182020-07-23 20:40:46 -04003386 "OpenSSL version may be too old",
Hynek Schlawack35618382015-09-05 21:54:25 +02003387 )
3388 def test_op_cookie_exchange(self):
3389 """
Alex Chanb7480992017-01-30 14:04:47 +00003390 The value of `OpenSSL.SSL.OP_COOKIE_EXCHANGE` is 0x2000, the
3391 value of `SSL_OP_COOKIE_EXCHANGE` defined by `openssl/ssl.h`.
Hynek Schlawack35618382015-09-05 21:54:25 +02003392 """
Alex Chanb7480992017-01-30 14:04:47 +00003393 assert OP_COOKIE_EXCHANGE == 0x2000
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003394
Hynek Schlawack35618382015-09-05 21:54:25 +02003395 @pytest.mark.skipif(
3396 OP_NO_TICKET is None,
Alex Gaynor03737182020-07-23 20:40:46 -04003397 reason="OP_NO_TICKET unavailable - OpenSSL version may be too old",
Hynek Schlawack35618382015-09-05 21:54:25 +02003398 )
3399 def test_op_no_ticket(self):
3400 """
Alex Chanb7480992017-01-30 14:04:47 +00003401 The value of `OpenSSL.SSL.OP_NO_TICKET` is 0x4000, the value of
3402 `SSL_OP_NO_TICKET` defined by `openssl/ssl.h`.
Hynek Schlawack35618382015-09-05 21:54:25 +02003403 """
Alex Chanb7480992017-01-30 14:04:47 +00003404 assert OP_NO_TICKET == 0x4000
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003405
Hynek Schlawack35618382015-09-05 21:54:25 +02003406 @pytest.mark.skipif(
3407 OP_NO_COMPRESSION is None,
Alex Gaynor03737182020-07-23 20:40:46 -04003408 reason=(
3409 "OP_NO_COMPRESSION unavailable - OpenSSL version may be too old"
3410 ),
Hynek Schlawack35618382015-09-05 21:54:25 +02003411 )
3412 def test_op_no_compression(self):
3413 """
Alex Chanb7480992017-01-30 14:04:47 +00003414 The value of `OpenSSL.SSL.OP_NO_COMPRESSION` is 0x20000, the
3415 value of `SSL_OP_NO_COMPRESSION` defined by `openssl/ssl.h`.
Hynek Schlawack35618382015-09-05 21:54:25 +02003416 """
Alex Chanb7480992017-01-30 14:04:47 +00003417 assert OP_NO_COMPRESSION == 0x20000
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04003418
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003419 def test_sess_cache_off(self):
3420 """
Alex Chanb7480992017-01-30 14:04:47 +00003421 The value of `OpenSSL.SSL.SESS_CACHE_OFF` 0x0, the value of
3422 `SSL_SESS_CACHE_OFF` defined by `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003423 """
Alex Chanb7480992017-01-30 14:04:47 +00003424 assert 0x0 == SESS_CACHE_OFF
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003425
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003426 def test_sess_cache_client(self):
3427 """
Alex Chanb7480992017-01-30 14:04:47 +00003428 The value of `OpenSSL.SSL.SESS_CACHE_CLIENT` 0x1, the value of
3429 `SSL_SESS_CACHE_CLIENT` defined by `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003430 """
Alex Chanb7480992017-01-30 14:04:47 +00003431 assert 0x1 == SESS_CACHE_CLIENT
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003432
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003433 def test_sess_cache_server(self):
3434 """
Alex Chanb7480992017-01-30 14:04:47 +00003435 The value of `OpenSSL.SSL.SESS_CACHE_SERVER` 0x2, the value of
3436 `SSL_SESS_CACHE_SERVER` defined by `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003437 """
Alex Chanb7480992017-01-30 14:04:47 +00003438 assert 0x2 == SESS_CACHE_SERVER
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003439
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003440 def test_sess_cache_both(self):
3441 """
Alex Chanb7480992017-01-30 14:04:47 +00003442 The value of `OpenSSL.SSL.SESS_CACHE_BOTH` 0x3, the value of
3443 `SSL_SESS_CACHE_BOTH` defined by `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003444 """
Alex Chanb7480992017-01-30 14:04:47 +00003445 assert 0x3 == SESS_CACHE_BOTH
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003446
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003447 def test_sess_cache_no_auto_clear(self):
3448 """
Alex Chanb7480992017-01-30 14:04:47 +00003449 The value of `OpenSSL.SSL.SESS_CACHE_NO_AUTO_CLEAR` 0x80, the
3450 value of `SSL_SESS_CACHE_NO_AUTO_CLEAR` defined by
3451 `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003452 """
Alex Chanb7480992017-01-30 14:04:47 +00003453 assert 0x80 == SESS_CACHE_NO_AUTO_CLEAR
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003454
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003455 def test_sess_cache_no_internal_lookup(self):
3456 """
Alex Chanb7480992017-01-30 14:04:47 +00003457 The value of `OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_LOOKUP` 0x100,
3458 the value of `SSL_SESS_CACHE_NO_INTERNAL_LOOKUP` defined by
3459 `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003460 """
Alex Chanb7480992017-01-30 14:04:47 +00003461 assert 0x100 == SESS_CACHE_NO_INTERNAL_LOOKUP
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003462
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003463 def test_sess_cache_no_internal_store(self):
3464 """
Alex Chanb7480992017-01-30 14:04:47 +00003465 The value of `OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_STORE` 0x200,
3466 the value of `SSL_SESS_CACHE_NO_INTERNAL_STORE` defined by
3467 `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003468 """
Alex Chanb7480992017-01-30 14:04:47 +00003469 assert 0x200 == SESS_CACHE_NO_INTERNAL_STORE
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003470
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003471 def test_sess_cache_no_internal(self):
3472 """
Alex Chanb7480992017-01-30 14:04:47 +00003473 The value of `OpenSSL.SSL.SESS_CACHE_NO_INTERNAL` 0x300, the
3474 value of `SSL_SESS_CACHE_NO_INTERNAL` defined by
3475 `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003476 """
Alex Chanb7480992017-01-30 14:04:47 +00003477 assert 0x300 == SESS_CACHE_NO_INTERNAL
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003478
3479
Alex Chanb7480992017-01-30 14:04:47 +00003480class TestMemoryBIO(object):
Rick Deanb71c0d22009-04-01 14:09:23 -05003481 """
Alex Chanb7480992017-01-30 14:04:47 +00003482 Tests for `OpenSSL.SSL.Connection` using a memory BIO.
Rick Deanb71c0d22009-04-01 14:09:23 -05003483 """
Alex Gaynor03737182020-07-23 20:40:46 -04003484
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003485 def _server(self, sock):
3486 """
Alex Chanb7480992017-01-30 14:04:47 +00003487 Create a new server-side SSL `Connection` object wrapped around `sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003488 """
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003489 # Create the server side Connection. This is mostly setup boilerplate
3490 # - use TLSv1, use a particular certificate, etc.
3491 server_ctx = Context(TLSv1_METHOD)
Alex Gaynor43307782015-09-04 09:05:45 -04003492 server_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE)
Hynek Schlawack35618382015-09-05 21:54:25 +02003493 server_ctx.set_verify(
3494 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT | VERIFY_CLIENT_ONCE,
Alex Gaynor03737182020-07-23 20:40:46 -04003495 verify_cb,
Hynek Schlawack35618382015-09-05 21:54:25 +02003496 )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003497 server_store = server_ctx.get_cert_store()
Hynek Schlawack35618382015-09-05 21:54:25 +02003498 server_ctx.use_privatekey(
Alex Gaynor03737182020-07-23 20:40:46 -04003499 load_privatekey(FILETYPE_PEM, server_key_pem)
3500 )
Hynek Schlawack35618382015-09-05 21:54:25 +02003501 server_ctx.use_certificate(
Alex Gaynor03737182020-07-23 20:40:46 -04003502 load_certificate(FILETYPE_PEM, server_cert_pem)
3503 )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003504 server_ctx.check_privatekey()
3505 server_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Hynek Schlawack35618382015-09-05 21:54:25 +02003506 # Here the Connection is actually created. If None is passed as the
3507 # 2nd parameter, it indicates a memory BIO should be created.
Rick Deanb1ccd562009-07-09 23:52:39 -05003508 server_conn = Connection(server_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003509 server_conn.set_accept_state()
3510 return server_conn
3511
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003512 def _client(self, sock):
3513 """
Alex Chanb7480992017-01-30 14:04:47 +00003514 Create a new client-side SSL `Connection` object wrapped around `sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003515 """
3516 # Now create the client side Connection. Similar boilerplate to the
3517 # above.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003518 client_ctx = Context(TLSv1_METHOD)
Alex Gaynor43307782015-09-04 09:05:45 -04003519 client_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE)
Hynek Schlawack35618382015-09-05 21:54:25 +02003520 client_ctx.set_verify(
3521 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT | VERIFY_CLIENT_ONCE,
Alex Gaynor03737182020-07-23 20:40:46 -04003522 verify_cb,
Hynek Schlawack35618382015-09-05 21:54:25 +02003523 )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003524 client_store = client_ctx.get_cert_store()
Hynek Schlawack35618382015-09-05 21:54:25 +02003525 client_ctx.use_privatekey(
Alex Gaynor03737182020-07-23 20:40:46 -04003526 load_privatekey(FILETYPE_PEM, client_key_pem)
3527 )
Hynek Schlawack35618382015-09-05 21:54:25 +02003528 client_ctx.use_certificate(
Alex Gaynor03737182020-07-23 20:40:46 -04003529 load_certificate(FILETYPE_PEM, client_cert_pem)
3530 )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003531 client_ctx.check_privatekey()
3532 client_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05003533 client_conn = Connection(client_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003534 client_conn.set_connect_state()
3535 return client_conn
3536
Alex Chanb7480992017-01-30 14:04:47 +00003537 def test_memory_connect(self):
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003538 """
Alex Chanb7480992017-01-30 14:04:47 +00003539 Two `Connection`s which use memory BIOs can be manually connected by
3540 reading from the output of each and writing those bytes to the input of
3541 the other and in this way establish a connection and exchange
3542 application-level bytes with each other.
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003543 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003544 server_conn = self._server(None)
3545 client_conn = self._client(None)
Rick Deanb71c0d22009-04-01 14:09:23 -05003546
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003547 # There should be no key or nonces yet.
Alex Chanb7480992017-01-30 14:04:47 +00003548 assert server_conn.master_key() is None
3549 assert server_conn.client_random() is None
3550 assert server_conn.server_random() is None
Rick Deanb71c0d22009-04-01 14:09:23 -05003551
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003552 # First, the handshake needs to happen. We'll deliver bytes back and
3553 # forth between the client and server until neither of them feels like
3554 # speaking any more.
Alex Chanb7480992017-01-30 14:04:47 +00003555 assert interact_in_memory(client_conn, server_conn) is None
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003556
3557 # Now that the handshake is done, there should be a key and nonces.
Alex Chanb7480992017-01-30 14:04:47 +00003558 assert server_conn.master_key() is not None
3559 assert server_conn.client_random() is not None
3560 assert server_conn.server_random() is not None
3561 assert server_conn.client_random() == client_conn.client_random()
3562 assert server_conn.server_random() == client_conn.server_random()
3563 assert server_conn.client_random() != server_conn.server_random()
3564 assert client_conn.client_random() != client_conn.server_random()
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003565
Paul Kehrerbdb76392017-12-01 04:54:32 +08003566 # Export key material for other uses.
Alex Gaynor03737182020-07-23 20:40:46 -04003567 cekm = client_conn.export_keying_material(b"LABEL", 32)
3568 sekm = server_conn.export_keying_material(b"LABEL", 32)
Paul Kehrerbdb76392017-12-01 04:54:32 +08003569 assert cekm is not None
3570 assert sekm is not None
3571 assert cekm == sekm
3572 assert len(sekm) == 32
3573
3574 # Export key material for other uses with additional context.
Alex Gaynor03737182020-07-23 20:40:46 -04003575 cekmc = client_conn.export_keying_material(b"LABEL", 32, b"CONTEXT")
3576 sekmc = server_conn.export_keying_material(b"LABEL", 32, b"CONTEXT")
Paul Kehrerbdb76392017-12-01 04:54:32 +08003577 assert cekmc is not None
3578 assert sekmc is not None
3579 assert cekmc == sekmc
3580 assert cekmc != cekm
3581 assert sekmc != sekm
3582 # Export with alternate label
Alex Gaynor03737182020-07-23 20:40:46 -04003583 cekmt = client_conn.export_keying_material(b"test", 32, b"CONTEXT")
3584 sekmt = server_conn.export_keying_material(b"test", 32, b"CONTEXT")
Paul Kehrerbdb76392017-12-01 04:54:32 +08003585 assert cekmc != cekmt
3586 assert sekmc != sekmt
3587
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003588 # Here are the bytes we'll try to send.
Alex Gaynor03737182020-07-23 20:40:46 -04003589 important_message = b"One if by land, two if by sea."
Rick Deanb71c0d22009-04-01 14:09:23 -05003590
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003591 server_conn.write(important_message)
Alex Gaynor03737182020-07-23 20:40:46 -04003592 assert interact_in_memory(client_conn, server_conn) == (
3593 client_conn,
3594 important_message,
3595 )
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003596
3597 client_conn.write(important_message[::-1])
Alex Gaynor03737182020-07-23 20:40:46 -04003598 assert interact_in_memory(client_conn, server_conn) == (
3599 server_conn,
3600 important_message[::-1],
3601 )
Rick Deanb71c0d22009-04-01 14:09:23 -05003602
Alex Chanb7480992017-01-30 14:04:47 +00003603 def test_socket_connect(self):
Rick Deanb1ccd562009-07-09 23:52:39 -05003604 """
Alex Chanb7480992017-01-30 14:04:47 +00003605 Just like `test_memory_connect` but with an actual socket.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003606
Hynek Schlawack35618382015-09-05 21:54:25 +02003607 This is primarily to rule out the memory BIO code as the source of any
Alex Chanb7480992017-01-30 14:04:47 +00003608 problems encountered while passing data over a `Connection` (if
Hynek Schlawack35618382015-09-05 21:54:25 +02003609 this test fails, there must be a problem outside the memory BIO code,
3610 as no memory BIO is involved here). Even though this isn't a memory
3611 BIO test, it's convenient to have it here.
Rick Deanb1ccd562009-07-09 23:52:39 -05003612 """
Alex Chanb7480992017-01-30 14:04:47 +00003613 server_conn, client_conn = loopback()
Rick Deanb1ccd562009-07-09 23:52:39 -05003614
Alex Gaynore7f51982016-09-11 11:48:14 -04003615 important_message = b"Help me Obi Wan Kenobi, you're my only hope."
Rick Deanb1ccd562009-07-09 23:52:39 -05003616 client_conn.send(important_message)
3617 msg = server_conn.recv(1024)
Alex Chanb7480992017-01-30 14:04:47 +00003618 assert msg == important_message
Rick Deanb1ccd562009-07-09 23:52:39 -05003619
3620 # Again in the other direction, just for fun.
3621 important_message = important_message[::-1]
3622 server_conn.send(important_message)
3623 msg = client_conn.recv(1024)
Alex Chanb7480992017-01-30 14:04:47 +00003624 assert msg == important_message
Rick Deanb1ccd562009-07-09 23:52:39 -05003625
Alex Chanb7480992017-01-30 14:04:47 +00003626 def test_socket_overrides_memory(self):
Rick Deanb71c0d22009-04-01 14:09:23 -05003627 """
Alex Chanb7480992017-01-30 14:04:47 +00003628 Test that `OpenSSL.SSL.bio_read` and `OpenSSL.SSL.bio_write` don't
3629 work on `OpenSSL.SSL.Connection`() that use sockets.
Rick Deanb71c0d22009-04-01 14:09:23 -05003630 """
Alex Gaynor51d424c2016-09-10 14:50:11 -04003631 context = Context(TLSv1_METHOD)
David Benjamin1fbe0642019-04-15 17:05:13 -05003632 client = socket_any_family()
Rick Deanb71c0d22009-04-01 14:09:23 -05003633 clientSSL = Connection(context, client)
Alex Chanb7480992017-01-30 14:04:47 +00003634 with pytest.raises(TypeError):
3635 clientSSL.bio_read(100)
3636 with pytest.raises(TypeError):
3637 clientSSL.bio_write("foo")
3638 with pytest.raises(TypeError):
3639 clientSSL.bio_shutdown()
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003640
Alex Chanb7480992017-01-30 14:04:47 +00003641 def test_outgoing_overflow(self):
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003642 """
3643 If more bytes than can be written to the memory BIO are passed to
Alex Chanb7480992017-01-30 14:04:47 +00003644 `Connection.send` at once, the number of bytes which were written is
3645 returned and that many bytes from the beginning of the input can be
3646 read from the other end of the connection.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003647 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003648 server = self._server(None)
3649 client = self._client(None)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003650
Alex Chanb7480992017-01-30 14:04:47 +00003651 interact_in_memory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003652
3653 size = 2 ** 15
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003654 sent = client.send(b"x" * size)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003655 # Sanity check. We're trying to test what happens when the entire
3656 # input can't be sent. If the entire input was sent, this test is
3657 # meaningless.
Alex Chanb7480992017-01-30 14:04:47 +00003658 assert sent < size
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003659
Alex Chanb7480992017-01-30 14:04:47 +00003660 receiver, received = interact_in_memory(client, server)
3661 assert receiver is server
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003662
3663 # We can rely on all of these bytes being received at once because
Alex Chanb7480992017-01-30 14:04:47 +00003664 # loopback passes 2 ** 16 to recv - more than 2 ** 15.
3665 assert len(received) == sent
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003666
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003667 def test_shutdown(self):
3668 """
Alex Chanb7480992017-01-30 14:04:47 +00003669 `Connection.bio_shutdown` signals the end of the data stream
3670 from which the `Connection` reads.
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003671 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003672 server = self._server(None)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003673 server.bio_shutdown()
Alex Chanb7480992017-01-30 14:04:47 +00003674 with pytest.raises(Error) as err:
3675 server.recv(1024)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003676 # We don't want WantReadError or ZeroReturnError or anything - it's a
3677 # handshake failure.
Alex Chanb7480992017-01-30 14:04:47 +00003678 assert type(err.value) in [Error, SysCallError]
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003679
Alex Chanb7480992017-01-30 14:04:47 +00003680 def test_unexpected_EOF(self):
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003681 """
3682 If the connection is lost before an orderly SSL shutdown occurs,
Alex Chanb7480992017-01-30 14:04:47 +00003683 `OpenSSL.SSL.SysCallError` is raised with a message of
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003684 "Unexpected EOF".
3685 """
Alex Chanb7480992017-01-30 14:04:47 +00003686 server_conn, client_conn = loopback()
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003687 client_conn.sock_shutdown(SHUT_RDWR)
Alex Chanb7480992017-01-30 14:04:47 +00003688 with pytest.raises(SysCallError) as err:
3689 server_conn.recv(1024)
3690 assert err.value.args == (-1, "Unexpected EOF")
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003691
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003692 def _check_client_ca_list(self, func):
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003693 """
Alex Chanb7480992017-01-30 14:04:47 +00003694 Verify the return value of the `get_client_ca_list` method for
Hynek Schlawack35618382015-09-05 21:54:25 +02003695 server and client connections.
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003696
Jonathan Ballet78b92a22011-07-16 08:07:26 +09003697 :param func: A function which will be called with the server context
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003698 before the client and server are connected to each other. This
3699 function should specify a list of CAs for the server to send to the
3700 client and return that same list. The list will be used to verify
Alex Chanb7480992017-01-30 14:04:47 +00003701 that `get_client_ca_list` returns the proper value at
Hynek Schlawack35618382015-09-05 21:54:25 +02003702 various times.
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003703 """
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003704 server = self._server(None)
3705 client = self._client(None)
Alex Chanb7480992017-01-30 14:04:47 +00003706 assert client.get_client_ca_list() == []
3707 assert server.get_client_ca_list() == []
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003708 ctx = server.get_context()
3709 expected = func(ctx)
Alex Chanb7480992017-01-30 14:04:47 +00003710 assert client.get_client_ca_list() == []
3711 assert server.get_client_ca_list() == expected
3712 interact_in_memory(client, server)
3713 assert client.get_client_ca_list() == expected
3714 assert server.get_client_ca_list() == expected
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003715
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003716 def test_set_client_ca_list_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003717 """
Alex Chanb7480992017-01-30 14:04:47 +00003718 `Context.set_client_ca_list` raises a `TypeError` if called with a
3719 non-list or a list that contains objects other than X509Names.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003720 """
3721 ctx = Context(TLSv1_METHOD)
Alex Chanb7480992017-01-30 14:04:47 +00003722 with pytest.raises(TypeError):
3723 ctx.set_client_ca_list("spam")
3724 with pytest.raises(TypeError):
3725 ctx.set_client_ca_list(["spam"])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003726
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003727 def test_set_empty_ca_list(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003728 """
Alex Chanb7480992017-01-30 14:04:47 +00003729 If passed an empty list, `Context.set_client_ca_list` configures the
3730 context to send no CA names to the client and, on both the server and
3731 client sides, `Connection.get_client_ca_list` returns an empty list
3732 after the connection is set up.
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003733 """
Alex Gaynor03737182020-07-23 20:40:46 -04003734
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003735 def no_ca(ctx):
3736 ctx.set_client_ca_list([])
3737 return []
Alex Gaynor03737182020-07-23 20:40:46 -04003738
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003739 self._check_client_ca_list(no_ca)
3740
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003741 def test_set_one_ca_list(self):
3742 """
3743 If passed a list containing a single X509Name,
Alex Chanb7480992017-01-30 14:04:47 +00003744 `Context.set_client_ca_list` configures the context to send
Hynek Schlawack35618382015-09-05 21:54:25 +02003745 that CA name to the client and, on both the server and client sides,
Alex Chanb7480992017-01-30 14:04:47 +00003746 `Connection.get_client_ca_list` returns a list containing that
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003747 X509Name after the connection is set up.
3748 """
3749 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3750 cadesc = cacert.get_subject()
Hynek Schlawack35618382015-09-05 21:54:25 +02003751
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003752 def single_ca(ctx):
3753 ctx.set_client_ca_list([cadesc])
3754 return [cadesc]
Alex Gaynor03737182020-07-23 20:40:46 -04003755
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003756 self._check_client_ca_list(single_ca)
3757
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003758 def test_set_multiple_ca_list(self):
3759 """
3760 If passed a list containing multiple X509Name objects,
Alex Chanb7480992017-01-30 14:04:47 +00003761 `Context.set_client_ca_list` configures the context to send
Hynek Schlawack35618382015-09-05 21:54:25 +02003762 those CA names to the client and, on both the server and client sides,
Alex Chanb7480992017-01-30 14:04:47 +00003763 `Connection.get_client_ca_list` returns a list containing those
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003764 X509Names after the connection is set up.
3765 """
3766 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3767 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3768
3769 sedesc = secert.get_subject()
3770 cldesc = clcert.get_subject()
3771
3772 def multiple_ca(ctx):
3773 L = [sedesc, cldesc]
3774 ctx.set_client_ca_list(L)
3775 return L
Alex Gaynor03737182020-07-23 20:40:46 -04003776
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003777 self._check_client_ca_list(multiple_ca)
3778
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003779 def test_reset_ca_list(self):
3780 """
3781 If called multiple times, only the X509Names passed to the final call
Alex Chanb7480992017-01-30 14:04:47 +00003782 of `Context.set_client_ca_list` are used to configure the CA
Hynek Schlawack35618382015-09-05 21:54:25 +02003783 names sent to the client.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003784 """
3785 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3786 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3787 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3788
3789 cadesc = cacert.get_subject()
3790 sedesc = secert.get_subject()
3791 cldesc = clcert.get_subject()
3792
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003793 def changed_ca(ctx):
3794 ctx.set_client_ca_list([sedesc, cldesc])
3795 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003796 return [cadesc]
Alex Gaynor03737182020-07-23 20:40:46 -04003797
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003798 self._check_client_ca_list(changed_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003799
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003800 def test_mutated_ca_list(self):
3801 """
Alex Chanb7480992017-01-30 14:04:47 +00003802 If the list passed to `Context.set_client_ca_list` is mutated
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003803 afterwards, this does not affect the list of CA names sent to the
3804 client.
3805 """
3806 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3807 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3808
3809 cadesc = cacert.get_subject()
3810 sedesc = secert.get_subject()
3811
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003812 def mutated_ca(ctx):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003813 L = [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003814 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003815 L.append(sedesc)
3816 return [cadesc]
Alex Gaynor03737182020-07-23 20:40:46 -04003817
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003818 self._check_client_ca_list(mutated_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003819
Alex Chanb7480992017-01-30 14:04:47 +00003820 def test_add_client_ca_wrong_args(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003821 """
Alex Chanb7480992017-01-30 14:04:47 +00003822 `Context.add_client_ca` raises `TypeError` if called with
3823 a non-X509 object.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003824 """
3825 ctx = Context(TLSv1_METHOD)
Alex Chanb7480992017-01-30 14:04:47 +00003826 with pytest.raises(TypeError):
3827 ctx.add_client_ca("spam")
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003828
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003829 def test_one_add_client_ca(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003830 """
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003831 A certificate's subject can be added as a CA to be sent to the client
Alex Chanb7480992017-01-30 14:04:47 +00003832 with `Context.add_client_ca`.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003833 """
3834 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3835 cadesc = cacert.get_subject()
Hynek Schlawack35618382015-09-05 21:54:25 +02003836
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003837 def single_ca(ctx):
3838 ctx.add_client_ca(cacert)
3839 return [cadesc]
Alex Gaynor03737182020-07-23 20:40:46 -04003840
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003841 self._check_client_ca_list(single_ca)
3842
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003843 def test_multiple_add_client_ca(self):
3844 """
3845 Multiple CA names can be sent to the client by calling
Alex Chanb7480992017-01-30 14:04:47 +00003846 `Context.add_client_ca` with multiple X509 objects.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003847 """
3848 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3849 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3850
3851 cadesc = cacert.get_subject()
3852 sedesc = secert.get_subject()
3853
3854 def multiple_ca(ctx):
3855 ctx.add_client_ca(cacert)
3856 ctx.add_client_ca(secert)
3857 return [cadesc, sedesc]
Alex Gaynor03737182020-07-23 20:40:46 -04003858
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003859 self._check_client_ca_list(multiple_ca)
3860
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003861 def test_set_and_add_client_ca(self):
3862 """
Alex Chanb7480992017-01-30 14:04:47 +00003863 A call to `Context.set_client_ca_list` followed by a call to
3864 `Context.add_client_ca` results in using the CA names from the
Hynek Schlawack35618382015-09-05 21:54:25 +02003865 first call and the CA name from the second call.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003866 """
3867 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3868 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3869 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3870
3871 cadesc = cacert.get_subject()
3872 sedesc = secert.get_subject()
3873 cldesc = clcert.get_subject()
3874
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003875 def mixed_set_add_ca(ctx):
3876 ctx.set_client_ca_list([cadesc, sedesc])
3877 ctx.add_client_ca(clcert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003878 return [cadesc, sedesc, cldesc]
Alex Gaynor03737182020-07-23 20:40:46 -04003879
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003880 self._check_client_ca_list(mixed_set_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003881
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003882 def test_set_after_add_client_ca(self):
3883 """
Alex Chanb7480992017-01-30 14:04:47 +00003884 A call to `Context.set_client_ca_list` after a call to
3885 `Context.add_client_ca` replaces the CA name specified by the
Hynek Schlawack35618382015-09-05 21:54:25 +02003886 former call with the names specified by the latter call.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003887 """
3888 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3889 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3890 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3891
3892 cadesc = cacert.get_subject()
3893 sedesc = secert.get_subject()
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003894
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003895 def set_replaces_add_ca(ctx):
3896 ctx.add_client_ca(clcert)
3897 ctx.set_client_ca_list([cadesc])
3898 ctx.add_client_ca(secert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003899 return [cadesc, sedesc]
Alex Gaynor03737182020-07-23 20:40:46 -04003900
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003901 self._check_client_ca_list(set_replaces_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003902
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003903
Alex Chanb7480992017-01-30 14:04:47 +00003904class TestInfoConstants(object):
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003905 """
3906 Tests for assorted constants exposed for use in info callbacks.
3907 """
Alex Gaynor03737182020-07-23 20:40:46 -04003908
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003909 def test_integers(self):
3910 """
3911 All of the info constants are integers.
3912
3913 This is a very weak test. It would be nice to have one that actually
3914 verifies that as certain info events happen, the value passed to the
3915 info callback matches up with the constant exposed by OpenSSL.SSL.
3916 """
3917 for const in [
Alex Gaynor03737182020-07-23 20:40:46 -04003918 SSL_ST_CONNECT,
3919 SSL_ST_ACCEPT,
3920 SSL_ST_MASK,
3921 SSL_CB_LOOP,
3922 SSL_CB_EXIT,
3923 SSL_CB_READ,
3924 SSL_CB_WRITE,
3925 SSL_CB_ALERT,
3926 SSL_CB_READ_ALERT,
3927 SSL_CB_WRITE_ALERT,
3928 SSL_CB_ACCEPT_LOOP,
3929 SSL_CB_ACCEPT_EXIT,
3930 SSL_CB_CONNECT_LOOP,
3931 SSL_CB_CONNECT_EXIT,
3932 SSL_CB_HANDSHAKE_START,
3933 SSL_CB_HANDSHAKE_DONE,
Hynek Schlawack35618382015-09-05 21:54:25 +02003934 ]:
Alex Gaynor5af32d02016-09-24 01:52:21 -04003935 assert isinstance(const, int)
3936
3937 # These constants don't exist on OpenSSL 1.1.0
3938 for const in [
Alex Gaynor03737182020-07-23 20:40:46 -04003939 SSL_ST_INIT,
3940 SSL_ST_BEFORE,
3941 SSL_ST_OK,
3942 SSL_ST_RENEGOTIATE,
Alex Gaynor5af32d02016-09-24 01:52:21 -04003943 ]:
3944 assert const is None or isinstance(const, int)
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003945
Ziga Seilnacht44611bf2009-08-31 20:49:30 +02003946
Cory Benfield1d142142016-03-30 11:51:45 +01003947class TestRequires(object):
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003948 """
3949 Tests for the decorator factory used to conditionally raise
Cory Benfield1d142142016-03-30 11:51:45 +01003950 NotImplementedError when older OpenSSLs are used.
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003951 """
Alex Gaynor03737182020-07-23 20:40:46 -04003952
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003953 def test_available(self):
3954 """
3955 When the OpenSSL functionality is available the decorated functions
3956 work appropriately.
3957 """
3958 feature_guard = _make_requires(True, "Error text")
3959 results = []
3960
3961 @feature_guard
3962 def inner():
3963 results.append(True)
3964 return True
3965
Cory Benfield2333e5e2016-03-30 14:24:16 +01003966 assert inner() is True
3967 assert [True] == results
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003968
3969 def test_unavailable(self):
3970 """
3971 When the OpenSSL functionality is not available the decorated function
3972 does not execute and NotImplementedError is raised.
3973 """
3974 feature_guard = _make_requires(False, "Error text")
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003975
3976 @feature_guard
Alex Chanfb078d82017-04-20 11:16:15 +01003977 def inner(): # pragma: nocover
3978 pytest.fail("Should not be called")
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003979
Cory Benfield1d142142016-03-30 11:51:45 +01003980 with pytest.raises(NotImplementedError) as e:
3981 inner()
3982
3983 assert "Error text" in str(e.value)
Cory Benfield496652a2017-01-24 11:42:56 +00003984
3985
Alex Chanb7480992017-01-30 14:04:47 +00003986class TestOCSP(object):
Cory Benfield496652a2017-01-24 11:42:56 +00003987 """
3988 Tests for PyOpenSSL's OCSP stapling support.
3989 """
Alex Gaynor03737182020-07-23 20:40:46 -04003990
Cory Benfield496652a2017-01-24 11:42:56 +00003991 sample_ocsp_data = b"this is totally ocsp data"
3992
3993 def _client_connection(self, callback, data, request_ocsp=True):
3994 """
3995 Builds a client connection suitable for using OCSP.
3996
3997 :param callback: The callback to register for OCSP.
3998 :param data: The opaque data object that will be handed to the
3999 OCSP callback.
4000 :param request_ocsp: Whether the client will actually ask for OCSP
4001 stapling. Useful for testing only.
4002 """
4003 ctx = Context(SSLv23_METHOD)
4004 ctx.set_ocsp_client_callback(callback, data)
4005 client = Connection(ctx)
4006
4007 if request_ocsp:
4008 client.request_ocsp()
4009
4010 client.set_connect_state()
4011 return client
4012
4013 def _server_connection(self, callback, data):
4014 """
4015 Builds a server connection suitable for using OCSP.
4016
4017 :param callback: The callback to register for OCSP.
4018 :param data: The opaque data object that will be handed to the
4019 OCSP callback.
4020 """
4021 ctx = Context(SSLv23_METHOD)
4022 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
4023 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
4024 ctx.set_ocsp_server_callback(callback, data)
4025 server = Connection(ctx)
4026 server.set_accept_state()
4027 return server
4028
4029 def test_callbacks_arent_called_by_default(self):
4030 """
4031 If both the client and the server have registered OCSP callbacks, but
4032 the client does not send the OCSP request, neither callback gets
4033 called.
4034 """
Alex Gaynor03737182020-07-23 20:40:46 -04004035
Alex Chanfb078d82017-04-20 11:16:15 +01004036 def ocsp_callback(*args, **kwargs): # pragma: nocover
4037 pytest.fail("Should not be called")
Cory Benfield496652a2017-01-24 11:42:56 +00004038
4039 client = self._client_connection(
4040 callback=ocsp_callback, data=None, request_ocsp=False
4041 )
4042 server = self._server_connection(callback=ocsp_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00004043 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00004044
Cory Benfield496652a2017-01-24 11:42:56 +00004045 def test_client_negotiates_without_server(self):
4046 """
4047 If the client wants to do OCSP but the server does not, the handshake
4048 succeeds, and the client callback fires with an empty byte string.
4049 """
4050 called = []
4051
4052 def ocsp_callback(conn, ocsp_data, ignored):
4053 called.append(ocsp_data)
4054 return True
4055
4056 client = self._client_connection(callback=ocsp_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00004057 server = loopback_server_factory(socket=None)
4058 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00004059
4060 assert len(called) == 1
Alex Gaynor03737182020-07-23 20:40:46 -04004061 assert called[0] == b""
Cory Benfield496652a2017-01-24 11:42:56 +00004062
4063 def test_client_receives_servers_data(self):
4064 """
4065 The data the server sends in its callback is received by the client.
4066 """
4067 calls = []
4068
4069 def server_callback(*args, **kwargs):
4070 return self.sample_ocsp_data
4071
4072 def client_callback(conn, ocsp_data, ignored):
4073 calls.append(ocsp_data)
4074 return True
4075
4076 client = self._client_connection(callback=client_callback, data=None)
4077 server = self._server_connection(callback=server_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00004078 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00004079
4080 assert len(calls) == 1
4081 assert calls[0] == self.sample_ocsp_data
4082
4083 def test_callbacks_are_invoked_with_connections(self):
4084 """
4085 The first arguments to both callbacks are their respective connections.
4086 """
4087 client_calls = []
4088 server_calls = []
4089
4090 def client_callback(conn, *args, **kwargs):
4091 client_calls.append(conn)
4092 return True
4093
4094 def server_callback(conn, *args, **kwargs):
4095 server_calls.append(conn)
4096 return self.sample_ocsp_data
4097
4098 client = self._client_connection(callback=client_callback, data=None)
4099 server = self._server_connection(callback=server_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00004100 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00004101
4102 assert len(client_calls) == 1
4103 assert len(server_calls) == 1
4104 assert client_calls[0] is client
4105 assert server_calls[0] is server
4106
4107 def test_opaque_data_is_passed_through(self):
4108 """
4109 Both callbacks receive an opaque, user-provided piece of data in their
4110 callbacks as the final argument.
4111 """
4112 calls = []
4113
4114 def server_callback(*args):
4115 calls.append(args)
4116 return self.sample_ocsp_data
4117
4118 def client_callback(*args):
4119 calls.append(args)
4120 return True
4121
4122 sentinel = object()
4123
4124 client = self._client_connection(
4125 callback=client_callback, data=sentinel
4126 )
4127 server = self._server_connection(
4128 callback=server_callback, data=sentinel
4129 )
Alex Chanb7480992017-01-30 14:04:47 +00004130 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00004131
4132 assert len(calls) == 2
4133 assert calls[0][-1] is sentinel
4134 assert calls[1][-1] is sentinel
4135
4136 def test_server_returns_empty_string(self):
4137 """
4138 If the server returns an empty bytestring from its callback, the
4139 client callback is called with the empty bytestring.
4140 """
4141 client_calls = []
4142
4143 def server_callback(*args):
Alex Gaynor03737182020-07-23 20:40:46 -04004144 return b""
Cory Benfield496652a2017-01-24 11:42:56 +00004145
4146 def client_callback(conn, ocsp_data, ignored):
4147 client_calls.append(ocsp_data)
4148 return True
4149
4150 client = self._client_connection(callback=client_callback, data=None)
4151 server = self._server_connection(callback=server_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00004152 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00004153
4154 assert len(client_calls) == 1
Alex Gaynor03737182020-07-23 20:40:46 -04004155 assert client_calls[0] == b""
Cory Benfield496652a2017-01-24 11:42:56 +00004156
4157 def test_client_returns_false_terminates_handshake(self):
4158 """
4159 If the client returns False from its callback, the handshake fails.
4160 """
Alex Gaynor03737182020-07-23 20:40:46 -04004161
Cory Benfield496652a2017-01-24 11:42:56 +00004162 def server_callback(*args):
4163 return self.sample_ocsp_data
4164
4165 def client_callback(*args):
4166 return False
4167
4168 client = self._client_connection(callback=client_callback, data=None)
4169 server = self._server_connection(callback=server_callback, data=None)
4170
4171 with pytest.raises(Error):
Alex Chanb7480992017-01-30 14:04:47 +00004172 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00004173
4174 def test_exceptions_in_client_bubble_up(self):
4175 """
4176 The callbacks thrown in the client callback bubble up to the caller.
4177 """
Alex Gaynor03737182020-07-23 20:40:46 -04004178
Cory Benfield496652a2017-01-24 11:42:56 +00004179 class SentinelException(Exception):
4180 pass
4181
4182 def server_callback(*args):
4183 return self.sample_ocsp_data
4184
4185 def client_callback(*args):
4186 raise SentinelException()
4187
4188 client = self._client_connection(callback=client_callback, data=None)
4189 server = self._server_connection(callback=server_callback, data=None)
4190
4191 with pytest.raises(SentinelException):
Alex Chanb7480992017-01-30 14:04:47 +00004192 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00004193
4194 def test_exceptions_in_server_bubble_up(self):
4195 """
4196 The callbacks thrown in the server callback bubble up to the caller.
4197 """
Alex Gaynor03737182020-07-23 20:40:46 -04004198
Cory Benfield496652a2017-01-24 11:42:56 +00004199 class SentinelException(Exception):
4200 pass
4201
4202 def server_callback(*args):
4203 raise SentinelException()
4204
Alex Chanfb078d82017-04-20 11:16:15 +01004205 def client_callback(*args): # pragma: nocover
Cory Benfield496652a2017-01-24 11:42:56 +00004206 pytest.fail("Should not be called")
4207
4208 client = self._client_connection(callback=client_callback, data=None)
4209 server = self._server_connection(callback=server_callback, data=None)
4210
4211 with pytest.raises(SentinelException):
Alex Chanb7480992017-01-30 14:04:47 +00004212 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00004213
4214 def test_server_must_return_bytes(self):
4215 """
4216 The server callback must return a bytestring, or a TypeError is thrown.
4217 """
Alex Gaynor03737182020-07-23 20:40:46 -04004218
Cory Benfield496652a2017-01-24 11:42:56 +00004219 def server_callback(*args):
Alex Gaynor03737182020-07-23 20:40:46 -04004220 return self.sample_ocsp_data.decode("ascii")
Cory Benfield496652a2017-01-24 11:42:56 +00004221
Alex Chanfb078d82017-04-20 11:16:15 +01004222 def client_callback(*args): # pragma: nocover
Cory Benfield496652a2017-01-24 11:42:56 +00004223 pytest.fail("Should not be called")
4224
4225 client = self._client_connection(callback=client_callback, data=None)
4226 server = self._server_connection(callback=server_callback, data=None)
4227
4228 with pytest.raises(TypeError):
Alex Chanb7480992017-01-30 14:04:47 +00004229 handshake_in_memory(client, server)