blob: daaafae98156108468ef0cc8f89744625a025c9e [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 client_cert_pem,
134 client_key_pem,
135 server_cert_pem,
136 server_key_pem,
137 root_cert_pem,
Paul Kehrerbeaf9f52020-08-03 17:50:31 -0500138 root_key_pem,
Alex Gaynor03737182020-07-23 20:40:46 -0400139)
Hynek Schlawackf0e66852015-10-16 20:18:38 +0200140
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200141
Alex Gaynord0bdd2d2016-09-10 14:23:46 -0400142# openssl dhparam 1024 -out dh-1024.pem (note that 1024 is a small number of
143# bits to use)
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -0400144dhparam = """\
145-----BEGIN DH PARAMETERS-----
Alex Gaynord0bdd2d2016-09-10 14:23:46 -0400146MIGHAoGBALdUMvn+C9MM+y5BWZs11mSeH6HHoEq0UVbzVq7UojC1hbsZUuGukQ3a
147Qh2/pwqb18BZFykrWB0zv/OkLa0kx4cuUgNrUVq1EFheBiX6YqryJ7t2sO09NQiO
148V7H54LmltOT/hEh6QWsJqb6BQgH65bswvV/XkYGja8/T0GzvbaVzAgEC
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -0400149-----END DH PARAMETERS-----
150"""
151
152
Hugo van Kemenade60827f82019-08-30 00:39:35 +0300153skip_if_py3 = pytest.mark.skipif(not PY2, reason="Python 2 only")
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200154
155
David Benjamin1fbe0642019-04-15 17:05:13 -0500156def socket_any_family():
157 try:
158 return socket(AF_INET)
159 except error as e:
160 if e.errno == EAFNOSUPPORT:
161 return socket(AF_INET6)
162 raise
163
164
165def loopback_address(socket):
166 if socket.family == AF_INET:
167 return "127.0.0.1"
168 else:
169 assert socket.family == AF_INET6
170 return "::1"
171
172
Jean-Paul Calderone05826732015-04-12 11:38:49 -0400173def join_bytes_or_unicode(prefix, suffix):
174 """
175 Join two path components of either ``bytes`` or ``unicode``.
176
177 The return type is the same as the type of ``prefix``.
178 """
179 # If the types are the same, nothing special is necessary.
180 if type(prefix) == type(suffix):
181 return join(prefix, suffix)
182
183 # Otherwise, coerce suffix to the type of prefix.
184 if isinstance(prefix, text_type):
185 return join(prefix, suffix.decode(getfilesystemencoding()))
186 else:
187 return join(prefix, suffix.encode(getfilesystemencoding()))
188
189
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400190def verify_cb(conn, cert, errnum, depth, ok):
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400191 return ok
192
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400193
Rick Deanb1ccd562009-07-09 23:52:39 -0500194def socket_pair():
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400195 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400196 Establish and return a pair of network sockets connected to each other.
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400197 """
198 # Connect a pair of sockets
David Benjamin1fbe0642019-04-15 17:05:13 -0500199 port = socket_any_family()
Alex Gaynor03737182020-07-23 20:40:46 -0400200 port.bind(("", 0))
Rick Deanb1ccd562009-07-09 23:52:39 -0500201 port.listen(1)
David Benjamin1fbe0642019-04-15 17:05:13 -0500202 client = socket(port.family)
Rick Deanb1ccd562009-07-09 23:52:39 -0500203 client.setblocking(False)
David Benjamin1fbe0642019-04-15 17:05:13 -0500204 client.connect_ex((loopback_address(port), port.getsockname()[1]))
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400205 client.setblocking(True)
Rick Deanb1ccd562009-07-09 23:52:39 -0500206 server = port.accept()[0]
Rick Deanb1ccd562009-07-09 23:52:39 -0500207
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400208 # Let's pass some unencrypted data to make sure our socket connection is
209 # fine. Just one byte, so we don't have to worry about buffers getting
210 # filled up or fragmentation.
Alex Gaynore7f51982016-09-11 11:48:14 -0400211 server.send(b"x")
212 assert client.recv(1024) == b"x"
213 client.send(b"y")
214 assert server.recv(1024) == b"y"
Rick Deanb1ccd562009-07-09 23:52:39 -0500215
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -0400216 # Most of our callers want non-blocking sockets, make it easy for them.
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400217 server.setblocking(False)
218 client.setblocking(False)
Jim Shaver46f28912015-05-29 19:32:16 -0400219
Rick Deanb1ccd562009-07-09 23:52:39 -0500220 return (server, client)
221
222
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400223def handshake(client, server):
224 conns = [client, server]
225 while conns:
226 for conn in conns:
227 try:
228 conn.do_handshake()
229 except WantReadError:
230 pass
231 else:
232 conns.remove(conn)
233
234
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400235def _create_certificate_chain():
236 """
237 Construct and return a chain of certificates.
238
239 1. A new self-signed certificate authority certificate (cacert)
240 2. A new intermediate certificate signed by cacert (icert)
241 3. A new server certificate signed by icert (scert)
242 """
Alex Gaynor03737182020-07-23 20:40:46 -0400243 caext = X509Extension(b"basicConstraints", False, b"CA:true")
244 not_after_date = datetime.date.today() + datetime.timedelta(days=365)
Alex Gaynor675534c2020-01-12 11:59:49 -0600245 not_after = not_after_date.strftime("%Y%m%d%H%M%SZ").encode("ascii")
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400246
247 # Step 1
248 cakey = PKey()
Alex Gaynor8cd336e2020-08-03 10:36:32 -0400249 cakey.generate_key(TYPE_RSA, 2048)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400250 cacert = X509()
David Benjamin6b799472020-06-24 17:14:16 -0400251 cacert.set_version(2)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400252 cacert.get_subject().commonName = "Authority Certificate"
253 cacert.set_issuer(cacert.get_subject())
254 cacert.set_pubkey(cakey)
Alex Gaynore7f51982016-09-11 11:48:14 -0400255 cacert.set_notBefore(b"20000101000000Z")
Alex Gaynor675534c2020-01-12 11:59:49 -0600256 cacert.set_notAfter(not_after)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400257 cacert.add_extensions([caext])
258 cacert.set_serial_number(0)
Paul Kehrerd4b60462020-08-03 18:26:03 -0500259 cacert.sign(cakey, "sha256")
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400260
261 # Step 2
262 ikey = PKey()
Alex Gaynor8cd336e2020-08-03 10:36:32 -0400263 ikey.generate_key(TYPE_RSA, 2048)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400264 icert = X509()
David Benjamin6b799472020-06-24 17:14:16 -0400265 icert.set_version(2)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400266 icert.get_subject().commonName = "Intermediate Certificate"
267 icert.set_issuer(cacert.get_subject())
268 icert.set_pubkey(ikey)
Alex Gaynore7f51982016-09-11 11:48:14 -0400269 icert.set_notBefore(b"20000101000000Z")
Alex Gaynor675534c2020-01-12 11:59:49 -0600270 icert.set_notAfter(not_after)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400271 icert.add_extensions([caext])
272 icert.set_serial_number(0)
Paul Kehrerd4b60462020-08-03 18:26:03 -0500273 icert.sign(cakey, "sha256")
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400274
275 # Step 3
276 skey = PKey()
Alex Gaynor8cd336e2020-08-03 10:36:32 -0400277 skey.generate_key(TYPE_RSA, 2048)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400278 scert = X509()
David Benjamin6b799472020-06-24 17:14:16 -0400279 scert.set_version(2)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400280 scert.get_subject().commonName = "Server Certificate"
281 scert.set_issuer(icert.get_subject())
282 scert.set_pubkey(skey)
Alex Gaynore7f51982016-09-11 11:48:14 -0400283 scert.set_notBefore(b"20000101000000Z")
Alex Gaynor675534c2020-01-12 11:59:49 -0600284 scert.set_notAfter(not_after)
Alex Gaynor03737182020-07-23 20:40:46 -0400285 scert.add_extensions(
286 [X509Extension(b"basicConstraints", True, b"CA:false")]
287 )
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400288 scert.set_serial_number(0)
Paul Kehrerd4b60462020-08-03 18:26:03 -0500289 scert.sign(ikey, "sha256")
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400290
291 return [(cakey, cacert), (ikey, icert), (skey, scert)]
292
293
Paul Kehrer7d5a3bf2019-01-21 12:24:02 -0600294def loopback_client_factory(socket, version=SSLv23_METHOD):
295 client = Connection(Context(version), socket)
Alex Chan1c0cb662017-01-30 07:13:30 +0000296 client.set_connect_state()
297 return client
298
299
Paul Kehrer7d5a3bf2019-01-21 12:24:02 -0600300def loopback_server_factory(socket, version=SSLv23_METHOD):
301 ctx = Context(version)
Alex Chan1c0cb662017-01-30 07:13:30 +0000302 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
303 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
304 server = Connection(ctx, socket)
305 server.set_accept_state()
306 return server
307
308
309def loopback(server_factory=None, client_factory=None):
310 """
311 Create a connected socket pair and force two connected SSL sockets
312 to talk to each other via memory BIOs.
313 """
314 if server_factory is None:
315 server_factory = loopback_server_factory
316 if client_factory is None:
317 client_factory = loopback_client_factory
318
319 (server, client) = socket_pair()
320 server = server_factory(server)
321 client = client_factory(client)
322
323 handshake(client, server)
324
325 server.setblocking(True)
326 client.setblocking(True)
327 return server, client
328
329
Alex Chan1ca9e3a2016-11-05 13:01:51 +0000330def interact_in_memory(client_conn, server_conn):
331 """
332 Try to read application bytes from each of the two `Connection` objects.
333 Copy bytes back and forth between their send/receive buffers for as long
334 as there is anything to copy. When there is nothing more to copy,
335 return `None`. If one of them actually manages to deliver some application
336 bytes, return a two-tuple of the connection from which the bytes were read
337 and the bytes themselves.
338 """
339 wrote = True
340 while wrote:
341 # Loop until neither side has anything to say
342 wrote = False
343
344 # Copy stuff from each side's send buffer to the other side's
345 # receive buffer.
Alex Gaynor03737182020-07-23 20:40:46 -0400346 for (read, write) in [
347 (client_conn, server_conn),
348 (server_conn, client_conn),
349 ]:
Alex Chan1ca9e3a2016-11-05 13:01:51 +0000350
351 # Give the side a chance to generate some more bytes, or succeed.
352 try:
353 data = read.recv(2 ** 16)
354 except WantReadError:
355 # It didn't succeed, so we'll hope it generated some output.
356 pass
357 else:
358 # It did succeed, so we'll stop now and let the caller deal
359 # with it.
360 return (read, data)
361
362 while True:
363 # Keep copying as long as there's more stuff there.
364 try:
365 dirty = read.bio_read(4096)
366 except WantReadError:
367 # Okay, nothing more waiting to be sent. Stop
368 # processing this send buffer.
369 break
370 else:
371 # Keep track of the fact that someone generated some
372 # output.
373 wrote = True
374 write.bio_write(dirty)
375
376
Alex Chan532b79e2017-01-24 15:14:52 +0000377def handshake_in_memory(client_conn, server_conn):
378 """
379 Perform the TLS handshake between two `Connection` instances connected to
380 each other via memory BIOs.
381 """
382 client_conn.set_connect_state()
383 server_conn.set_accept_state()
384
385 for conn in [client_conn, server_conn]:
386 try:
387 conn.do_handshake()
388 except WantReadError:
389 pass
390
391 interact_in_memory(client_conn, server_conn)
392
393
Alex Chanb7480992017-01-30 14:04:47 +0000394class TestVersion(object):
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400395 """
Alex Chanb7480992017-01-30 14:04:47 +0000396 Tests for version information exposed by `OpenSSL.SSL.SSLeay_version` and
397 `OpenSSL.SSL.OPENSSL_VERSION_NUMBER`.
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400398 """
Alex Gaynor03737182020-07-23 20:40:46 -0400399
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400400 def test_OPENSSL_VERSION_NUMBER(self):
401 """
Alex Chanb7480992017-01-30 14:04:47 +0000402 `OPENSSL_VERSION_NUMBER` is an integer with status in the low byte and
403 the patch, fix, minor, and major versions in the nibbles above that.
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400404 """
Alex Chanb7480992017-01-30 14:04:47 +0000405 assert isinstance(OPENSSL_VERSION_NUMBER, int)
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400406
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400407 def test_SSLeay_version(self):
408 """
Alex Chanb7480992017-01-30 14:04:47 +0000409 `SSLeay_version` takes a version type indicator and returns one of a
410 number of version strings based on that indicator.
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400411 """
412 versions = {}
Alex Gaynor03737182020-07-23 20:40:46 -0400413 for t in [
414 SSLEAY_VERSION,
415 SSLEAY_CFLAGS,
416 SSLEAY_BUILT_ON,
417 SSLEAY_PLATFORM,
418 SSLEAY_DIR,
419 ]:
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400420 version = SSLeay_version(t)
421 versions[version] = t
Alex Chanb7480992017-01-30 14:04:47 +0000422 assert isinstance(version, bytes)
423 assert len(versions) == 5
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400424
425
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100426@pytest.fixture
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100427def ca_file(tmpdir):
428 """
429 Create a valid PEM file with CA certificates and return the path.
430 """
431 key = rsa.generate_private_key(
Alex Gaynor03737182020-07-23 20:40:46 -0400432 public_exponent=65537, key_size=2048, backend=default_backend()
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100433 )
434 public_key = key.public_key()
435
436 builder = x509.CertificateBuilder()
Alex Gaynor03737182020-07-23 20:40:46 -0400437 builder = builder.subject_name(
438 x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, u"pyopenssl.org")])
439 )
440 builder = builder.issuer_name(
441 x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, u"pyopenssl.org")])
442 )
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100443 one_day = datetime.timedelta(1, 0, 0)
444 builder = builder.not_valid_before(datetime.datetime.today() - one_day)
445 builder = builder.not_valid_after(datetime.datetime.today() + one_day)
446 builder = builder.serial_number(int(uuid.uuid4()))
447 builder = builder.public_key(public_key)
448 builder = builder.add_extension(
449 x509.BasicConstraints(ca=True, path_length=None), critical=True,
450 )
451
452 certificate = builder.sign(
Alex Gaynor03737182020-07-23 20:40:46 -0400453 private_key=key, algorithm=hashes.SHA256(), backend=default_backend()
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100454 )
455
456 ca_file = tmpdir.join("test.pem")
457 ca_file.write_binary(
Alex Gaynor03737182020-07-23 20:40:46 -0400458 certificate.public_bytes(encoding=serialization.Encoding.PEM,)
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100459 )
460
461 return str(ca_file).encode("ascii")
462
463
464@pytest.fixture
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100465def context():
466 """
Paul Kehrer688538c2020-08-03 19:18:15 -0500467 A simple "best TLS you can get" context. TLS 1.2+ in any reasonable OpenSSL
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100468 """
Paul Kehrer688538c2020-08-03 19:18:15 -0500469 return Context(SSLv23_METHOD)
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100470
471
472class TestContext(object):
Hynek Schlawackaa861212016-03-13 13:53:48 +0100473 """
Alex Chan532b79e2017-01-24 15:14:52 +0000474 Unit tests for `OpenSSL.SSL.Context`.
Hynek Schlawackaa861212016-03-13 13:53:48 +0100475 """
Alex Gaynor03737182020-07-23 20:40:46 -0400476
477 @pytest.mark.parametrize(
478 "cipher_string",
479 [b"hello world:AES128-SHA", u"hello world:AES128-SHA"],
480 )
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100481 def test_set_cipher_list(self, context, cipher_string):
482 """
Alex Chan532b79e2017-01-24 15:14:52 +0000483 `Context.set_cipher_list` accepts both byte and unicode strings
Hynek Schlawacka7a63af2016-03-11 12:05:26 +0100484 for naming the ciphers which connections created with the context
485 object will be able to choose from.
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100486 """
487 context.set_cipher_list(cipher_string)
488 conn = Connection(context, None)
489
490 assert "AES128-SHA" in conn.get_cipher_list()
491
Mark Williamsdf2480d2019-02-14 19:30:07 -0800492 def test_set_cipher_list_wrong_type(self, context):
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100493 """
Alex Chan532b79e2017-01-24 15:14:52 +0000494 `Context.set_cipher_list` raises `TypeError` when passed a non-string
Mark Williamsdf2480d2019-02-14 19:30:07 -0800495 argument.
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100496 """
Mark Williamsdf2480d2019-02-14 19:30:07 -0800497 with pytest.raises(TypeError):
498 context.set_cipher_list(object())
499
Alex Gaynor963ae032019-07-06 17:38:32 -0400500 @flaky.flaky
Mark Williamsdf2480d2019-02-14 19:30:07 -0800501 def test_set_cipher_list_no_cipher_match(self, context):
502 """
503 `Context.set_cipher_list` raises `OpenSSL.SSL.Error` with a
504 `"no cipher match"` reason string regardless of the TLS
505 version.
506 """
507 with pytest.raises(Error) as excinfo:
508 context.set_cipher_list(b"imaginary-cipher")
509 assert excinfo.value.args == (
Alex Gaynor03737182020-07-23 20:40:46 -0400510 [("SSL routines", "SSL_CTX_set_cipher_list", "no cipher match",)],
511 )
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100512
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100513 def test_load_client_ca(self, context, ca_file):
514 """
Alex Chan532b79e2017-01-24 15:14:52 +0000515 `Context.load_client_ca` works as far as we can tell.
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100516 """
517 context.load_client_ca(ca_file)
518
519 def test_load_client_ca_invalid(self, context, tmpdir):
520 """
Alex Chan532b79e2017-01-24 15:14:52 +0000521 `Context.load_client_ca` raises an Error if the ca file is invalid.
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100522 """
523 ca_file = tmpdir.join("test.pem")
524 ca_file.write("")
525
526 with pytest.raises(Error) as e:
527 context.load_client_ca(str(ca_file).encode("ascii"))
528
529 assert "PEM routines" == e.value.args[0][0][0]
530
531 def test_load_client_ca_unicode(self, context, ca_file):
532 """
533 Passing the path as unicode raises a warning but works.
534 """
Alex Gaynor03737182020-07-23 20:40:46 -0400535 pytest.deprecated_call(context.load_client_ca, ca_file.decode("ascii"))
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100536
537 def test_set_session_id(self, context):
538 """
Alex Chan532b79e2017-01-24 15:14:52 +0000539 `Context.set_session_id` works as far as we can tell.
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100540 """
541 context.set_session_id(b"abc")
542
543 def test_set_session_id_fail(self, context):
544 """
Alex Chan532b79e2017-01-24 15:14:52 +0000545 `Context.set_session_id` errors are propagated.
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100546 """
547 with pytest.raises(Error) as e:
548 context.set_session_id(b"abc" * 1000)
549
550 assert [
Alex Gaynor03737182020-07-23 20:40:46 -0400551 (
552 "SSL routines",
553 "SSL_CTX_set_session_id_context",
554 "ssl session id context too long",
555 )
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100556 ] == e.value.args[0]
557
558 def test_set_session_id_unicode(self, context):
559 """
Alex Chan532b79e2017-01-24 15:14:52 +0000560 `Context.set_session_id` raises a warning if a unicode string is
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100561 passed.
562 """
563 pytest.deprecated_call(context.set_session_id, u"abc")
564
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400565 def test_method(self):
566 """
Alex Chan532b79e2017-01-24 15:14:52 +0000567 `Context` can be instantiated with one of `SSLv2_METHOD`,
568 `SSLv3_METHOD`, `SSLv23_METHOD`, `TLSv1_METHOD`, `TLSv1_1_METHOD`,
569 or `TLSv1_2_METHOD`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400570 """
Alex Gaynor5af32d02016-09-24 01:52:21 -0400571 methods = [SSLv23_METHOD, TLSv1_METHOD]
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400572 for meth in methods:
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400573 Context(meth)
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400574
Alex Gaynor5af32d02016-09-24 01:52:21 -0400575 maybe = [SSLv2_METHOD, SSLv3_METHOD, TLSv1_1_METHOD, TLSv1_2_METHOD]
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400576 for meth in maybe:
577 try:
578 Context(meth)
579 except (Error, ValueError):
580 # Some versions of OpenSSL have SSLv2 / TLSv1.1 / TLSv1.2, some
581 # don't. Difficult to say in advance.
582 pass
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400583
Alex Chan532b79e2017-01-24 15:14:52 +0000584 with pytest.raises(TypeError):
585 Context("")
586 with pytest.raises(ValueError):
587 Context(10)
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400588
Rick Deane15b1472009-07-09 15:53:42 -0500589 def test_type(self):
590 """
Alex Gaynor01f90a12019-02-07 09:14:48 -0500591 `Context` can be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -0500592 """
Alex Gaynor03737182020-07-23 20:40:46 -0400593 assert is_consistent_type(Context, "Context", TLSv1_METHOD)
Rick Deane15b1472009-07-09 15:53:42 -0500594
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400595 def test_use_privatekey(self):
596 """
Alex Chan532b79e2017-01-24 15:14:52 +0000597 `Context.use_privatekey` takes an `OpenSSL.crypto.PKey` instance.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400598 """
599 key = PKey()
Paul Kehrerc45a6ea2020-08-03 15:54:20 -0500600 key.generate_key(TYPE_RSA, 1024)
Paul Kehrer688538c2020-08-03 19:18:15 -0500601 ctx = Context(SSLv23_METHOD)
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400602 ctx.use_privatekey(key)
Alex Chan532b79e2017-01-24 15:14:52 +0000603 with pytest.raises(TypeError):
604 ctx.use_privatekey("")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400605
Alex Chan532b79e2017-01-24 15:14:52 +0000606 def test_use_privatekey_file_missing(self, tmpfile):
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800607 """
Alex Chan532b79e2017-01-24 15:14:52 +0000608 `Context.use_privatekey_file` raises `OpenSSL.SSL.Error` when passed
609 the name of a file which does not exist.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800610 """
Paul Kehrer688538c2020-08-03 19:18:15 -0500611 ctx = Context(SSLv23_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000612 with pytest.raises(Error):
613 ctx.use_privatekey_file(tmpfile)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800614
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400615 def _use_privatekey_file_test(self, pemfile, filetype):
616 """
617 Verify that calling ``Context.use_privatekey_file`` with the given
618 arguments does not raise an exception.
619 """
620 key = PKey()
Paul Kehrerc45a6ea2020-08-03 15:54:20 -0500621 key.generate_key(TYPE_RSA, 1024)
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400622
623 with open(pemfile, "wt") as pem:
Alex Gaynor03737182020-07-23 20:40:46 -0400624 pem.write(dump_privatekey(FILETYPE_PEM, key).decode("ascii"))
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400625
Paul Kehrer688538c2020-08-03 19:18:15 -0500626 ctx = Context(SSLv23_METHOD)
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400627 ctx.use_privatekey_file(pemfile, filetype)
628
Alex Gaynor03737182020-07-23 20:40:46 -0400629 @pytest.mark.parametrize("filetype", [object(), "", None, 1.0])
Alex Chanfb078d82017-04-20 11:16:15 +0100630 def test_wrong_privatekey_file_wrong_args(self, tmpfile, filetype):
631 """
632 `Context.use_privatekey_file` raises `TypeError` when called with
633 a `filetype` which is not a valid file encoding.
634 """
Paul Kehrer688538c2020-08-03 19:18:15 -0500635 ctx = Context(SSLv23_METHOD)
Alex Chanfb078d82017-04-20 11:16:15 +0100636 with pytest.raises(TypeError):
637 ctx.use_privatekey_file(tmpfile, filetype)
638
Alex Chan532b79e2017-01-24 15:14:52 +0000639 def test_use_privatekey_file_bytes(self, tmpfile):
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400640 """
641 A private key can be specified from a file by passing a ``bytes``
642 instance giving the file name to ``Context.use_privatekey_file``.
643 """
644 self._use_privatekey_file_test(
Alex Gaynor03737182020-07-23 20:40:46 -0400645 tmpfile + NON_ASCII.encode(getfilesystemencoding()), FILETYPE_PEM,
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400646 )
647
Alex Chan532b79e2017-01-24 15:14:52 +0000648 def test_use_privatekey_file_unicode(self, tmpfile):
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400649 """
650 A private key can be specified from a file by passing a ``unicode``
651 instance giving the file name to ``Context.use_privatekey_file``.
652 """
653 self._use_privatekey_file_test(
Alex Gaynor03737182020-07-23 20:40:46 -0400654 tmpfile.decode(getfilesystemencoding()) + NON_ASCII, FILETYPE_PEM,
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400655 )
656
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800657 def test_use_certificate_wrong_args(self):
658 """
Alex Chan532b79e2017-01-24 15:14:52 +0000659 `Context.use_certificate_wrong_args` raises `TypeError` when not passed
660 exactly one `OpenSSL.crypto.X509` instance as an argument.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800661 """
Paul Kehrer688538c2020-08-03 19:18:15 -0500662 ctx = Context(SSLv23_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000663 with pytest.raises(TypeError):
664 ctx.use_certificate("hello, world")
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800665
666 def test_use_certificate_uninitialized(self):
667 """
Alex Chan532b79e2017-01-24 15:14:52 +0000668 `Context.use_certificate` raises `OpenSSL.SSL.Error` when passed a
669 `OpenSSL.crypto.X509` instance which has not been initialized
670 (ie, which does not actually have any certificate data).
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800671 """
Paul Kehrer688538c2020-08-03 19:18:15 -0500672 ctx = Context(SSLv23_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000673 with pytest.raises(Error):
674 ctx.use_certificate(X509())
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800675
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800676 def test_use_certificate(self):
677 """
Alex Chan532b79e2017-01-24 15:14:52 +0000678 `Context.use_certificate` sets the certificate which will be
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800679 used to identify connections created using the context.
680 """
681 # TODO
682 # Hard to assert anything. But we could set a privatekey then ask
683 # OpenSSL if the cert and key agree using check_privatekey. Then as
684 # long as check_privatekey works right we're good...
Paul Kehrer688538c2020-08-03 19:18:15 -0500685 ctx = Context(SSLv23_METHOD)
Paul Kehrerbeaf9f52020-08-03 17:50:31 -0500686 ctx.use_certificate(load_certificate(FILETYPE_PEM, root_cert_pem))
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800687
688 def test_use_certificate_file_wrong_args(self):
689 """
Alex Chan532b79e2017-01-24 15:14:52 +0000690 `Context.use_certificate_file` raises `TypeError` if the first
691 argument is not a byte string or the second argument is not an integer.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800692 """
Paul Kehrer688538c2020-08-03 19:18:15 -0500693 ctx = Context(SSLv23_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000694 with pytest.raises(TypeError):
695 ctx.use_certificate_file(object(), FILETYPE_PEM)
696 with pytest.raises(TypeError):
697 ctx.use_certificate_file(b"somefile", object())
698 with pytest.raises(TypeError):
699 ctx.use_certificate_file(object(), FILETYPE_PEM)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800700
Alex Chan532b79e2017-01-24 15:14:52 +0000701 def test_use_certificate_file_missing(self, tmpfile):
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800702 """
Alex Chan532b79e2017-01-24 15:14:52 +0000703 `Context.use_certificate_file` raises `OpenSSL.SSL.Error` if passed
704 the name of a file which does not exist.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800705 """
Paul Kehrer688538c2020-08-03 19:18:15 -0500706 ctx = Context(SSLv23_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000707 with pytest.raises(Error):
708 ctx.use_certificate_file(tmpfile)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800709
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400710 def _use_certificate_file_test(self, certificate_file):
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800711 """
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400712 Verify that calling ``Context.use_certificate_file`` with the given
713 filename doesn't raise an exception.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800714 """
715 # TODO
716 # Hard to assert anything. But we could set a privatekey then ask
717 # OpenSSL if the cert and key agree using check_privatekey. Then as
718 # long as check_privatekey works right we're good...
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400719 with open(certificate_file, "wb") as pem_file:
Paul Kehrerbeaf9f52020-08-03 17:50:31 -0500720 pem_file.write(root_cert_pem)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800721
Paul Kehrer688538c2020-08-03 19:18:15 -0500722 ctx = Context(SSLv23_METHOD)
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400723 ctx.use_certificate_file(certificate_file)
724
Alex Chan532b79e2017-01-24 15:14:52 +0000725 def test_use_certificate_file_bytes(self, tmpfile):
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400726 """
Alex Chan532b79e2017-01-24 15:14:52 +0000727 `Context.use_certificate_file` sets the certificate (given as a
728 `bytes` filename) which will be used to identify connections created
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400729 using the context.
730 """
Alex Chan532b79e2017-01-24 15:14:52 +0000731 filename = tmpfile + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400732 self._use_certificate_file_test(filename)
733
Alex Chan532b79e2017-01-24 15:14:52 +0000734 def test_use_certificate_file_unicode(self, tmpfile):
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400735 """
Alex Chan532b79e2017-01-24 15:14:52 +0000736 `Context.use_certificate_file` sets the certificate (given as a
737 `bytes` filename) which will be used to identify connections created
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400738 using the context.
739 """
Alex Chan532b79e2017-01-24 15:14:52 +0000740 filename = tmpfile.decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400741 self._use_certificate_file_test(filename)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800742
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500743 def test_check_privatekey_valid(self):
744 """
Alex Chan532b79e2017-01-24 15:14:52 +0000745 `Context.check_privatekey` returns `None` if the `Context` instance
746 has been configured to use a matched key and certificate pair.
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500747 """
748 key = load_privatekey(FILETYPE_PEM, client_key_pem)
749 cert = load_certificate(FILETYPE_PEM, client_cert_pem)
Paul Kehrer688538c2020-08-03 19:18:15 -0500750 context = Context(SSLv23_METHOD)
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500751 context.use_privatekey(key)
752 context.use_certificate(cert)
Alex Chan532b79e2017-01-24 15:14:52 +0000753 assert None is context.check_privatekey()
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500754
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500755 def test_check_privatekey_invalid(self):
756 """
Alex Chan532b79e2017-01-24 15:14:52 +0000757 `Context.check_privatekey` raises `Error` if the `Context` instance
758 has been configured to use a key and certificate pair which don't
759 relate to each other.
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500760 """
761 key = load_privatekey(FILETYPE_PEM, client_key_pem)
762 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
Paul Kehrer688538c2020-08-03 19:18:15 -0500763 context = Context(SSLv23_METHOD)
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500764 context.use_privatekey(key)
765 context.use_certificate(cert)
Alex Chan532b79e2017-01-24 15:14:52 +0000766 with pytest.raises(Error):
767 context.check_privatekey()
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400768
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400769 def test_app_data(self):
770 """
Alex Chan532b79e2017-01-24 15:14:52 +0000771 `Context.set_app_data` stores an object for later retrieval
772 using `Context.get_app_data`.
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400773 """
774 app_data = object()
Paul Kehrer688538c2020-08-03 19:18:15 -0500775 context = Context(SSLv23_METHOD)
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400776 context.set_app_data(app_data)
Alex Chan532b79e2017-01-24 15:14:52 +0000777 assert context.get_app_data() is app_data
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400778
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400779 def test_set_options_wrong_args(self):
780 """
Alex Chan532b79e2017-01-24 15:14:52 +0000781 `Context.set_options` raises `TypeError` if called with
782 a non-`int` argument.
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400783 """
Paul Kehrer688538c2020-08-03 19:18:15 -0500784 context = Context(SSLv23_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000785 with pytest.raises(TypeError):
786 context.set_options(None)
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400787
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500788 def test_set_options(self):
789 """
Alex Chan532b79e2017-01-24 15:14:52 +0000790 `Context.set_options` returns the new options value.
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500791 """
Paul Kehrer688538c2020-08-03 19:18:15 -0500792 context = Context(SSLv23_METHOD)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500793 options = context.set_options(OP_NO_SSLv2)
Alex Gaynor2310f8b2016-09-10 14:39:32 -0400794 assert options & OP_NO_SSLv2 == OP_NO_SSLv2
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500795
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300796 def test_set_mode_wrong_args(self):
797 """
Alex Chan532b79e2017-01-24 15:14:52 +0000798 `Context.set_mode` raises `TypeError` if called with
799 a non-`int` argument.
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300800 """
Paul Kehrer688538c2020-08-03 19:18:15 -0500801 context = Context(SSLv23_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000802 with pytest.raises(TypeError):
803 context.set_mode(None)
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300804
Alex Gaynord3b5d9b2016-07-31 10:54:24 -0400805 def test_set_mode(self):
806 """
Alex Chan532b79e2017-01-24 15:14:52 +0000807 `Context.set_mode` accepts a mode bitvector and returns the
Alex Gaynord3b5d9b2016-07-31 10:54:24 -0400808 newly set mode.
809 """
Paul Kehrer688538c2020-08-03 19:18:15 -0500810 context = Context(SSLv23_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000811 assert MODE_RELEASE_BUFFERS & context.set_mode(MODE_RELEASE_BUFFERS)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500812
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400813 def test_set_timeout_wrong_args(self):
814 """
Alex Chan532b79e2017-01-24 15:14:52 +0000815 `Context.set_timeout` raises `TypeError` if called with
816 a non-`int` argument.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400817 """
Paul Kehrer688538c2020-08-03 19:18:15 -0500818 context = Context(SSLv23_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000819 with pytest.raises(TypeError):
820 context.set_timeout(None)
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400821
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400822 def test_timeout(self):
823 """
Alex Chan532b79e2017-01-24 15:14:52 +0000824 `Context.set_timeout` sets the session timeout for all connections
825 created using the context object. `Context.get_timeout` retrieves
826 this value.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400827 """
Paul Kehrer688538c2020-08-03 19:18:15 -0500828 context = Context(SSLv23_METHOD)
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400829 context.set_timeout(1234)
Alex Chan532b79e2017-01-24 15:14:52 +0000830 assert context.get_timeout() == 1234
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400831
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400832 def test_set_verify_depth_wrong_args(self):
833 """
Alex Chan532b79e2017-01-24 15:14:52 +0000834 `Context.set_verify_depth` raises `TypeError` if called with a
835 non-`int` argument.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400836 """
Paul Kehrer688538c2020-08-03 19:18:15 -0500837 context = Context(SSLv23_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000838 with pytest.raises(TypeError):
839 context.set_verify_depth(None)
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400840
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400841 def test_verify_depth(self):
842 """
Alex Chan532b79e2017-01-24 15:14:52 +0000843 `Context.set_verify_depth` sets the number of certificates in
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200844 a chain to follow before giving up. The value can be retrieved with
Alex Chan532b79e2017-01-24 15:14:52 +0000845 `Context.get_verify_depth`.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400846 """
Paul Kehrer688538c2020-08-03 19:18:15 -0500847 context = Context(SSLv23_METHOD)
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400848 context.set_verify_depth(11)
Alex Chan532b79e2017-01-24 15:14:52 +0000849 assert context.get_verify_depth() == 11
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400850
Alex Chan532b79e2017-01-24 15:14:52 +0000851 def _write_encrypted_pem(self, passphrase, tmpfile):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400852 """
853 Write a new private key out to a new file, encrypted using the given
854 passphrase. Return the path to the new file.
855 """
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400856 key = PKey()
Paul Kehrerc45a6ea2020-08-03 15:54:20 -0500857 key.generate_key(TYPE_RSA, 1024)
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400858 pem = dump_privatekey(FILETYPE_PEM, key, "blowfish", passphrase)
Alex Gaynor03737182020-07-23 20:40:46 -0400859 with open(tmpfile, "w") as fObj:
860 fObj.write(pem.decode("ascii"))
Alex Chan532b79e2017-01-24 15:14:52 +0000861 return tmpfile
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400862
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400863 def test_set_passwd_cb_wrong_args(self):
864 """
Alex Chan532b79e2017-01-24 15:14:52 +0000865 `Context.set_passwd_cb` raises `TypeError` if called with a
866 non-callable first argument.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400867 """
Paul Kehrer688538c2020-08-03 19:18:15 -0500868 context = Context(SSLv23_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000869 with pytest.raises(TypeError):
870 context.set_passwd_cb(None)
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400871
Alex Chan532b79e2017-01-24 15:14:52 +0000872 def test_set_passwd_cb(self, tmpfile):
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400873 """
Alex Chan532b79e2017-01-24 15:14:52 +0000874 `Context.set_passwd_cb` accepts a callable which will be invoked when
875 a private key is loaded from an encrypted PEM.
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400876 """
Alex Gaynore7f51982016-09-11 11:48:14 -0400877 passphrase = b"foobar"
Alex Chan532b79e2017-01-24 15:14:52 +0000878 pemFile = self._write_encrypted_pem(passphrase, tmpfile)
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400879 calledWith = []
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200880
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400881 def passphraseCallback(maxlen, verify, extra):
882 calledWith.append((maxlen, verify, extra))
883 return passphrase
Alex Gaynor03737182020-07-23 20:40:46 -0400884
Paul Kehrer688538c2020-08-03 19:18:15 -0500885 context = Context(SSLv23_METHOD)
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400886 context.set_passwd_cb(passphraseCallback)
887 context.use_privatekey_file(pemFile)
Alex Chan532b79e2017-01-24 15:14:52 +0000888 assert len(calledWith) == 1
889 assert isinstance(calledWith[0][0], int)
890 assert isinstance(calledWith[0][1], int)
891 assert calledWith[0][2] is None
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400892
Alex Chan532b79e2017-01-24 15:14:52 +0000893 def test_passwd_callback_exception(self, tmpfile):
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400894 """
Alex Chan532b79e2017-01-24 15:14:52 +0000895 `Context.use_privatekey_file` propagates any exception raised
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200896 by the passphrase callback.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400897 """
Alex Chan532b79e2017-01-24 15:14:52 +0000898 pemFile = self._write_encrypted_pem(b"monkeys are nice", tmpfile)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200899
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400900 def passphraseCallback(maxlen, verify, extra):
901 raise RuntimeError("Sorry, I am a fail.")
902
Paul Kehrer688538c2020-08-03 19:18:15 -0500903 context = Context(SSLv23_METHOD)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400904 context.set_passwd_cb(passphraseCallback)
Alex Chan532b79e2017-01-24 15:14:52 +0000905 with pytest.raises(RuntimeError):
906 context.use_privatekey_file(pemFile)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400907
Alex Chan532b79e2017-01-24 15:14:52 +0000908 def test_passwd_callback_false(self, tmpfile):
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400909 """
Alex Chan532b79e2017-01-24 15:14:52 +0000910 `Context.use_privatekey_file` raises `OpenSSL.SSL.Error` if the
911 passphrase callback returns a false value.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400912 """
Alex Chan532b79e2017-01-24 15:14:52 +0000913 pemFile = self._write_encrypted_pem(b"monkeys are nice", tmpfile)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200914
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400915 def passphraseCallback(maxlen, verify, extra):
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500916 return b""
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400917
Paul Kehrer688538c2020-08-03 19:18:15 -0500918 context = Context(SSLv23_METHOD)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400919 context.set_passwd_cb(passphraseCallback)
Alex Chan532b79e2017-01-24 15:14:52 +0000920 with pytest.raises(Error):
921 context.use_privatekey_file(pemFile)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400922
Alex Chan532b79e2017-01-24 15:14:52 +0000923 def test_passwd_callback_non_string(self, tmpfile):
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400924 """
Alex Chan532b79e2017-01-24 15:14:52 +0000925 `Context.use_privatekey_file` raises `OpenSSL.SSL.Error` if the
926 passphrase callback returns a true non-string value.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400927 """
Alex Chan532b79e2017-01-24 15:14:52 +0000928 pemFile = self._write_encrypted_pem(b"monkeys are nice", tmpfile)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200929
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400930 def passphraseCallback(maxlen, verify, extra):
931 return 10
932
Paul Kehrer688538c2020-08-03 19:18:15 -0500933 context = Context(SSLv23_METHOD)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400934 context.set_passwd_cb(passphraseCallback)
Alex Chan532b79e2017-01-24 15:14:52 +0000935 # TODO: Surely this is the wrong error?
936 with pytest.raises(ValueError):
937 context.use_privatekey_file(pemFile)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400938
Alex Chan532b79e2017-01-24 15:14:52 +0000939 def test_passwd_callback_too_long(self, tmpfile):
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400940 """
941 If the passphrase returned by the passphrase callback returns a string
942 longer than the indicated maximum length, it is truncated.
943 """
944 # A priori knowledge!
Alex Gaynore7f51982016-09-11 11:48:14 -0400945 passphrase = b"x" * 1024
Alex Chan532b79e2017-01-24 15:14:52 +0000946 pemFile = self._write_encrypted_pem(passphrase, tmpfile)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200947
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400948 def passphraseCallback(maxlen, verify, extra):
949 assert maxlen == 1024
Alex Gaynore7f51982016-09-11 11:48:14 -0400950 return passphrase + b"y"
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400951
Paul Kehrer688538c2020-08-03 19:18:15 -0500952 context = Context(SSLv23_METHOD)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400953 context.set_passwd_cb(passphraseCallback)
954 # This shall succeed because the truncated result is the correct
955 # passphrase.
956 context.use_privatekey_file(pemFile)
957
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400958 def test_set_info_callback(self):
959 """
Alex Chan532b79e2017-01-24 15:14:52 +0000960 `Context.set_info_callback` accepts a callable which will be
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200961 invoked when certain information about an SSL connection is available.
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400962 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500963 (server, client) = socket_pair()
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400964
Paul Kehrer688538c2020-08-03 19:18:15 -0500965 clientSSL = Connection(Context(SSLv23_METHOD), client)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400966 clientSSL.set_connect_state()
967
968 called = []
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200969
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400970 def info(conn, where, ret):
971 called.append((conn, where, ret))
Alex Gaynor03737182020-07-23 20:40:46 -0400972
Paul Kehrer688538c2020-08-03 19:18:15 -0500973 context = Context(SSLv23_METHOD)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400974 context.set_info_callback(info)
Paul Kehrerbeaf9f52020-08-03 17:50:31 -0500975 context.use_certificate(load_certificate(FILETYPE_PEM, root_cert_pem))
976 context.use_privatekey(load_privatekey(FILETYPE_PEM, root_key_pem))
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400977
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400978 serverSSL = Connection(context, server)
979 serverSSL.set_accept_state()
980
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -0500981 handshake(clientSSL, serverSSL)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400982
Jean-Paul Calderone3835e522014-02-02 11:12:30 -0500983 # The callback must always be called with a Connection instance as the
984 # first argument. It would probably be better to split this into
985 # separate tests for client and server side info callbacks so we could
986 # assert it is called with the right Connection instance. It would
987 # also be good to assert *something* about `where` and `ret`.
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -0500988 notConnections = [
Alex Gaynor03737182020-07-23 20:40:46 -0400989 conn
990 for (conn, where, ret) in called
991 if not isinstance(conn, Connection)
992 ]
993 assert (
994 [] == notConnections
995 ), "Some info callback arguments were not Connection instances."
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400996
Maximilian Hilsb2bca412020-07-28 16:31:22 +0200997 @pytest.mark.skipif(
998 not getattr(_lib, "Cryptography_HAS_KEYLOG", None),
999 reason="SSL_CTX_set_keylog_callback unavailable",
1000 )
1001 def test_set_keylog_callback(self):
1002 """
1003 `Context.set_keylog_callback` accepts a callable which will be
1004 invoked when key material is generated or received.
1005 """
1006 called = []
1007
1008 def keylog(conn, line):
1009 called.append((conn, line))
1010
Paul Kehrer688538c2020-08-03 19:18:15 -05001011 server_context = Context(TLSv1_2_METHOD)
Maximilian Hilsb2bca412020-07-28 16:31:22 +02001012 server_context.set_keylog_callback(keylog)
1013 server_context.use_certificate(
Paul Kehrerbeaf9f52020-08-03 17:50:31 -05001014 load_certificate(FILETYPE_PEM, root_cert_pem)
Maximilian Hilsb2bca412020-07-28 16:31:22 +02001015 )
1016 server_context.use_privatekey(
Paul Kehrerbeaf9f52020-08-03 17:50:31 -05001017 load_privatekey(FILETYPE_PEM, root_key_pem)
Maximilian Hilsb2bca412020-07-28 16:31:22 +02001018 )
1019
Paul Kehrer688538c2020-08-03 19:18:15 -05001020 client_context = Context(SSLv23_METHOD)
Maximilian Hilsb2bca412020-07-28 16:31:22 +02001021
1022 self._handshake_test(server_context, client_context)
1023
1024 assert called
1025 assert all(isinstance(conn, Connection) for conn, line in called)
1026 assert all(b"CLIENT_RANDOM" in line for conn, line in called)
1027
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001028 def _load_verify_locations_test(self, *args):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001029 """
1030 Create a client context which will verify the peer certificate and call
Alex Chan532b79e2017-01-24 15:14:52 +00001031 its `load_verify_locations` method with the given arguments.
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04001032 Then connect it to a server and ensure that the handshake succeeds.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001033 """
Rick Deanb1ccd562009-07-09 23:52:39 -05001034 (server, client) = socket_pair()
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001035
Paul Kehrer688538c2020-08-03 19:18:15 -05001036 clientContext = Context(SSLv23_METHOD)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001037 clientContext.load_verify_locations(*args)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001038 # Require that the server certificate verify properly or the
1039 # connection will fail.
1040 clientContext.set_verify(
1041 VERIFY_PEER,
Alex Gaynor03737182020-07-23 20:40:46 -04001042 lambda conn, cert, errno, depth, preverify_ok: preverify_ok,
1043 )
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001044
1045 clientSSL = Connection(clientContext, client)
1046 clientSSL.set_connect_state()
1047
Paul Kehrer688538c2020-08-03 19:18:15 -05001048 serverContext = Context(SSLv23_METHOD)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001049 serverContext.use_certificate(
Paul Kehrerbeaf9f52020-08-03 17:50:31 -05001050 load_certificate(FILETYPE_PEM, root_cert_pem)
Alex Gaynor03737182020-07-23 20:40:46 -04001051 )
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001052 serverContext.use_privatekey(
Paul Kehrerbeaf9f52020-08-03 17:50:31 -05001053 load_privatekey(FILETYPE_PEM, root_key_pem)
Alex Gaynor03737182020-07-23 20:40:46 -04001054 )
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001055
1056 serverSSL = Connection(serverContext, server)
1057 serverSSL.set_accept_state()
1058
Jean-Paul Calderonef8742032010-09-25 00:00:32 -04001059 # Without load_verify_locations above, the handshake
1060 # will fail:
1061 # Error: [('SSL routines', 'SSL3_GET_SERVER_CERTIFICATE',
1062 # 'certificate verify failed')]
1063 handshake(clientSSL, serverSSL)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001064
1065 cert = clientSSL.get_peer_certificate()
Alex Gaynor03737182020-07-23 20:40:46 -04001066 assert cert.get_subject().CN == "Testing Root CA"
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -04001067
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001068 def _load_verify_cafile(self, cafile):
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001069 """
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001070 Verify that if path to a file containing a certificate is passed to
Alex Chan532b79e2017-01-24 15:14:52 +00001071 `Context.load_verify_locations` for the ``cafile`` parameter, that
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001072 certificate is used as a trust root for the purposes of verifying
Alex Chan532b79e2017-01-24 15:14:52 +00001073 connections created using that `Context`.
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001074 """
Alex Gaynor03737182020-07-23 20:40:46 -04001075 with open(cafile, "w") as fObj:
Paul Kehrerbeaf9f52020-08-03 17:50:31 -05001076 fObj.write(root_cert_pem.decode("ascii"))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001077
1078 self._load_verify_locations_test(cafile)
1079
Alex Chan532b79e2017-01-24 15:14:52 +00001080 def test_load_verify_bytes_cafile(self, tmpfile):
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001081 """
Alex Chan532b79e2017-01-24 15:14:52 +00001082 `Context.load_verify_locations` accepts a file name as a `bytes`
1083 instance and uses the certificates within for verification purposes.
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001084 """
Alex Chan532b79e2017-01-24 15:14:52 +00001085 cafile = tmpfile + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001086 self._load_verify_cafile(cafile)
1087
Alex Chan532b79e2017-01-24 15:14:52 +00001088 def test_load_verify_unicode_cafile(self, tmpfile):
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001089 """
Alex Chan532b79e2017-01-24 15:14:52 +00001090 `Context.load_verify_locations` accepts a file name as a `unicode`
1091 instance and uses the certificates within for verification purposes.
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001092 """
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001093 self._load_verify_cafile(
Alex Chan532b79e2017-01-24 15:14:52 +00001094 tmpfile.decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001095 )
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001096
Alex Chan532b79e2017-01-24 15:14:52 +00001097 def test_load_verify_invalid_file(self, tmpfile):
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -04001098 """
Alex Chan532b79e2017-01-24 15:14:52 +00001099 `Context.load_verify_locations` raises `Error` when passed a
1100 non-existent cafile.
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -04001101 """
Paul Kehrer688538c2020-08-03 19:18:15 -05001102 clientContext = Context(SSLv23_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001103 with pytest.raises(Error):
1104 clientContext.load_verify_locations(tmpfile)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001105
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001106 def _load_verify_directory_locations_capath(self, capath):
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001107 """
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001108 Verify that if path to a directory containing certificate files is
1109 passed to ``Context.load_verify_locations`` for the ``capath``
1110 parameter, those certificates are used as trust roots for the purposes
1111 of verifying connections created using that ``Context``.
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001112 """
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001113 makedirs(capath)
Jean-Paul Calderone24dfb332011-05-04 18:10:26 -04001114 # Hash values computed manually with c_rehash to avoid depending on
1115 # c_rehash in the test suite. One is from OpenSSL 0.9.8, the other
1116 # from OpenSSL 1.0.0.
Alex Gaynor03737182020-07-23 20:40:46 -04001117 for name in [b"c7adac82.0", b"c3705638.0"]:
Jean-Paul Calderone05826732015-04-12 11:38:49 -04001118 cafile = join_bytes_or_unicode(capath, name)
Alex Gaynor03737182020-07-23 20:40:46 -04001119 with open(cafile, "w") as fObj:
Paul Kehrerbeaf9f52020-08-03 17:50:31 -05001120 fObj.write(root_cert_pem.decode("ascii"))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001121
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001122 self._load_verify_locations_test(None, capath)
1123
Alex Chan532b79e2017-01-24 15:14:52 +00001124 def test_load_verify_directory_bytes_capath(self, tmpfile):
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001125 """
Alex Chan532b79e2017-01-24 15:14:52 +00001126 `Context.load_verify_locations` accepts a directory name as a `bytes`
1127 instance and uses the certificates within for verification purposes.
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001128 """
1129 self._load_verify_directory_locations_capath(
Alex Chan532b79e2017-01-24 15:14:52 +00001130 tmpfile + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001131 )
1132
Alex Chan532b79e2017-01-24 15:14:52 +00001133 def test_load_verify_directory_unicode_capath(self, tmpfile):
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001134 """
Alex Chan532b79e2017-01-24 15:14:52 +00001135 `Context.load_verify_locations` accepts a directory name as a `unicode`
1136 instance and uses the certificates within for verification purposes.
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001137 """
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001138 self._load_verify_directory_locations_capath(
Alex Chan532b79e2017-01-24 15:14:52 +00001139 tmpfile.decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001140 )
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001141
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001142 def test_load_verify_locations_wrong_args(self):
1143 """
Alex Chan532b79e2017-01-24 15:14:52 +00001144 `Context.load_verify_locations` raises `TypeError` if with non-`str`
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001145 arguments.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001146 """
Paul Kehrer688538c2020-08-03 19:18:15 -05001147 context = Context(SSLv23_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001148 with pytest.raises(TypeError):
1149 context.load_verify_locations(object())
1150 with pytest.raises(TypeError):
1151 context.load_verify_locations(object(), object())
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001152
Hynek Schlawack734d3022015-09-05 19:19:32 +02001153 @pytest.mark.skipif(
Paul Kehrer55fb3412017-06-29 18:44:08 -05001154 not platform.startswith("linux"),
1155 reason="Loading fallback paths is a linux-specific behavior to "
Alex Gaynor03737182020-07-23 20:40:46 -04001156 "accommodate pyca/cryptography manylinux1 wheels",
Paul Kehrer55fb3412017-06-29 18:44:08 -05001157 )
1158 def test_fallback_default_verify_paths(self, monkeypatch):
1159 """
1160 Test that we load certificates successfully on linux from the fallback
1161 path. To do this we set the _CRYPTOGRAPHY_MANYLINUX1_CA_FILE and
1162 _CRYPTOGRAPHY_MANYLINUX1_CA_DIR vars to be equal to whatever the
1163 current OpenSSL default is and we disable
1164 SSL_CTX_SET_default_verify_paths so that it can't find certs unless
1165 it loads via fallback.
1166 """
Paul Kehrer688538c2020-08-03 19:18:15 -05001167 context = Context(SSLv23_METHOD)
Paul Kehrer55fb3412017-06-29 18:44:08 -05001168 monkeypatch.setattr(
1169 _lib, "SSL_CTX_set_default_verify_paths", lambda x: 1
1170 )
1171 monkeypatch.setattr(
1172 SSL,
1173 "_CRYPTOGRAPHY_MANYLINUX1_CA_FILE",
Alex Gaynor03737182020-07-23 20:40:46 -04001174 _ffi.string(_lib.X509_get_default_cert_file()),
Paul Kehrer55fb3412017-06-29 18:44:08 -05001175 )
1176 monkeypatch.setattr(
1177 SSL,
1178 "_CRYPTOGRAPHY_MANYLINUX1_CA_DIR",
Alex Gaynor03737182020-07-23 20:40:46 -04001179 _ffi.string(_lib.X509_get_default_cert_dir()),
Paul Kehrer55fb3412017-06-29 18:44:08 -05001180 )
1181 context.set_default_verify_paths()
1182 store = context.get_cert_store()
1183 sk_obj = _lib.X509_STORE_get0_objects(store._store)
1184 assert sk_obj != _ffi.NULL
1185 num = _lib.sk_X509_OBJECT_num(sk_obj)
1186 assert num != 0
1187
1188 def test_check_env_vars(self, monkeypatch):
1189 """
1190 Test that we return True/False appropriately if the env vars are set.
1191 """
Paul Kehrer688538c2020-08-03 19:18:15 -05001192 context = Context(SSLv23_METHOD)
Paul Kehrer55fb3412017-06-29 18:44:08 -05001193 dir_var = "CUSTOM_DIR_VAR"
1194 file_var = "CUSTOM_FILE_VAR"
1195 assert context._check_env_vars_set(dir_var, file_var) is False
1196 monkeypatch.setenv(dir_var, "value")
1197 monkeypatch.setenv(file_var, "value")
1198 assert context._check_env_vars_set(dir_var, file_var) is True
1199 assert context._check_env_vars_set(dir_var, file_var) is True
1200
1201 def test_verify_no_fallback_if_env_vars_set(self, monkeypatch):
1202 """
1203 Test that we don't use the fallback path if env vars are set.
1204 """
Paul Kehrer688538c2020-08-03 19:18:15 -05001205 context = Context(SSLv23_METHOD)
Paul Kehrer55fb3412017-06-29 18:44:08 -05001206 monkeypatch.setattr(
1207 _lib, "SSL_CTX_set_default_verify_paths", lambda x: 1
1208 )
Alex Gaynor03737182020-07-23 20:40:46 -04001209 dir_env_var = _ffi.string(_lib.X509_get_default_cert_dir_env()).decode(
1210 "ascii"
1211 )
Paul Kehrer55fb3412017-06-29 18:44:08 -05001212 file_env_var = _ffi.string(
1213 _lib.X509_get_default_cert_file_env()
1214 ).decode("ascii")
1215 monkeypatch.setenv(dir_env_var, "value")
1216 monkeypatch.setenv(file_env_var, "value")
1217 context.set_default_verify_paths()
1218
1219 monkeypatch.setattr(
Alex Gaynor03737182020-07-23 20:40:46 -04001220 context, "_fallback_default_verify_paths", raiser(SystemError)
Paul Kehrer55fb3412017-06-29 18:44:08 -05001221 )
1222 context.set_default_verify_paths()
1223
1224 @pytest.mark.skipif(
Hynek Schlawack734d3022015-09-05 19:19:32 +02001225 platform == "win32",
1226 reason="set_default_verify_paths appears not to work on Windows. "
Alex Gaynor03737182020-07-23 20:40:46 -04001227 "See LP#404343 and LP#404344.",
Hynek Schlawack734d3022015-09-05 19:19:32 +02001228 )
1229 def test_set_default_verify_paths(self):
1230 """
Alex Chan532b79e2017-01-24 15:14:52 +00001231 `Context.set_default_verify_paths` causes the platform-specific CA
1232 certificate locations to be used for verification purposes.
Hynek Schlawack734d3022015-09-05 19:19:32 +02001233 """
1234 # Testing this requires a server with a certificate signed by one
1235 # of the CAs in the platform CA location. Getting one of those
1236 # costs money. Fortunately (or unfortunately, depending on your
1237 # perspective), it's easy to think of a public server on the
1238 # internet which has such a certificate. Connecting to the network
1239 # in a unit test is bad, but it's the only way I can think of to
1240 # really test this. -exarkun
Hynek Schlawackbf887932015-10-21 17:13:47 +02001241 context = Context(SSLv23_METHOD)
Hynek Schlawack734d3022015-09-05 19:19:32 +02001242 context.set_default_verify_paths()
1243 context.set_verify(
1244 VERIFY_PEER,
Alex Gaynor03737182020-07-23 20:40:46 -04001245 lambda conn, cert, errno, depth, preverify_ok: preverify_ok,
1246 )
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001247
David Benjamin1fbe0642019-04-15 17:05:13 -05001248 client = socket_any_family()
Hynek Schlawackbf887932015-10-21 17:13:47 +02001249 client.connect(("encrypted.google.com", 443))
Hynek Schlawack734d3022015-09-05 19:19:32 +02001250 clientSSL = Connection(context, client)
1251 clientSSL.set_connect_state()
Alex Gaynor373926c2018-05-12 07:43:07 -04001252 clientSSL.set_tlsext_host_name(b"encrypted.google.com")
Hynek Schlawack734d3022015-09-05 19:19:32 +02001253 clientSSL.do_handshake()
1254 clientSSL.send(b"GET / HTTP/1.0\r\n\r\n")
Alex Chan532b79e2017-01-24 15:14:52 +00001255 assert clientSSL.recv(1024)
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05001256
Paul Kehrer55fb3412017-06-29 18:44:08 -05001257 def test_fallback_path_is_not_file_or_dir(self):
1258 """
1259 Test that when passed empty arrays or paths that do not exist no
1260 errors are raised.
1261 """
Paul Kehrer688538c2020-08-03 19:18:15 -05001262 context = Context(SSLv23_METHOD)
Paul Kehrer55fb3412017-06-29 18:44:08 -05001263 context._fallback_default_verify_paths([], [])
Alex Gaynor03737182020-07-23 20:40:46 -04001264 context._fallback_default_verify_paths(["/not/a/file"], ["/not/a/dir"])
Paul Kehrer55fb3412017-06-29 18:44:08 -05001265
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001266 def test_add_extra_chain_cert_invalid_cert(self):
1267 """
Alex Chan532b79e2017-01-24 15:14:52 +00001268 `Context.add_extra_chain_cert` raises `TypeError` if called with an
1269 object which is not an instance of `X509`.
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001270 """
Paul Kehrer688538c2020-08-03 19:18:15 -05001271 context = Context(SSLv23_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001272 with pytest.raises(TypeError):
1273 context.add_extra_chain_cert(object())
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001274
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001275 def _handshake_test(self, serverContext, clientContext):
1276 """
1277 Verify that a client and server created with the given contexts can
1278 successfully handshake and communicate.
1279 """
1280 serverSocket, clientSocket = socket_pair()
1281
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001282 server = Connection(serverContext, serverSocket)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001283 server.set_accept_state()
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001284
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001285 client = Connection(clientContext, clientSocket)
1286 client.set_connect_state()
1287
1288 # Make them talk to each other.
Alex Chan532b79e2017-01-24 15:14:52 +00001289 # interact_in_memory(client, server)
1290 for _ in range(3):
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001291 for s in [client, server]:
1292 try:
1293 s.do_handshake()
1294 except WantReadError:
1295 pass
1296
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001297 def test_set_verify_callback_connection_argument(self):
1298 """
1299 The first argument passed to the verify callback is the
Alex Chan532b79e2017-01-24 15:14:52 +00001300 `Connection` instance for which verification is taking place.
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001301 """
Paul Kehrer688538c2020-08-03 19:18:15 -05001302 serverContext = Context(SSLv23_METHOD)
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001303 serverContext.use_privatekey(
Paul Kehrerbeaf9f52020-08-03 17:50:31 -05001304 load_privatekey(FILETYPE_PEM, root_key_pem)
Alex Gaynor03737182020-07-23 20:40:46 -04001305 )
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001306 serverContext.use_certificate(
Paul Kehrerbeaf9f52020-08-03 17:50:31 -05001307 load_certificate(FILETYPE_PEM, root_cert_pem)
Alex Gaynor03737182020-07-23 20:40:46 -04001308 )
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001309 serverConnection = Connection(serverContext, None)
1310
1311 class VerifyCallback(object):
1312 def callback(self, connection, *args):
1313 self.connection = connection
1314 return 1
1315
1316 verify = VerifyCallback()
Paul Kehrer688538c2020-08-03 19:18:15 -05001317 clientContext = Context(SSLv23_METHOD)
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001318 clientContext.set_verify(VERIFY_PEER, verify.callback)
1319 clientConnection = Connection(clientContext, None)
1320 clientConnection.set_connect_state()
1321
Alex Chan532b79e2017-01-24 15:14:52 +00001322 handshake_in_memory(clientConnection, serverConnection)
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001323
Alex Chan532b79e2017-01-24 15:14:52 +00001324 assert verify.connection is clientConnection
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001325
Paul Kehrere7381862017-11-30 20:55:25 +08001326 def test_x509_in_verify_works(self):
1327 """
1328 We had a bug where the X509 cert instantiated in the callback wrapper
1329 didn't __init__ so it was missing objects needed when calling
1330 get_subject. This test sets up a handshake where we call get_subject
1331 on the cert provided to the verify callback.
1332 """
Paul Kehrer688538c2020-08-03 19:18:15 -05001333 serverContext = Context(SSLv23_METHOD)
Paul Kehrere7381862017-11-30 20:55:25 +08001334 serverContext.use_privatekey(
Paul Kehrerbeaf9f52020-08-03 17:50:31 -05001335 load_privatekey(FILETYPE_PEM, root_key_pem)
Alex Gaynor03737182020-07-23 20:40:46 -04001336 )
Paul Kehrere7381862017-11-30 20:55:25 +08001337 serverContext.use_certificate(
Paul Kehrerbeaf9f52020-08-03 17:50:31 -05001338 load_certificate(FILETYPE_PEM, root_cert_pem)
Alex Gaynor03737182020-07-23 20:40:46 -04001339 )
Paul Kehrere7381862017-11-30 20:55:25 +08001340 serverConnection = Connection(serverContext, None)
1341
1342 def verify_cb_get_subject(conn, cert, errnum, depth, ok):
1343 assert cert.get_subject()
1344 return 1
1345
Paul Kehrer688538c2020-08-03 19:18:15 -05001346 clientContext = Context(SSLv23_METHOD)
Paul Kehrere7381862017-11-30 20:55:25 +08001347 clientContext.set_verify(VERIFY_PEER, verify_cb_get_subject)
1348 clientConnection = Connection(clientContext, None)
1349 clientConnection.set_connect_state()
1350
1351 handshake_in_memory(clientConnection, serverConnection)
1352
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001353 def test_set_verify_callback_exception(self):
1354 """
Alex Chan532b79e2017-01-24 15:14:52 +00001355 If the verify callback passed to `Context.set_verify` raises an
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001356 exception, verification fails and the exception is propagated to the
Alex Chan532b79e2017-01-24 15:14:52 +00001357 caller of `Connection.do_handshake`.
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001358 """
Paul Kehrer7d5a3bf2019-01-21 12:24:02 -06001359 serverContext = Context(TLSv1_2_METHOD)
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001360 serverContext.use_privatekey(
Paul Kehrerbeaf9f52020-08-03 17:50:31 -05001361 load_privatekey(FILETYPE_PEM, root_key_pem)
Alex Gaynor03737182020-07-23 20:40:46 -04001362 )
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001363 serverContext.use_certificate(
Paul Kehrerbeaf9f52020-08-03 17:50:31 -05001364 load_certificate(FILETYPE_PEM, root_cert_pem)
Alex Gaynor03737182020-07-23 20:40:46 -04001365 )
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001366
Paul Kehrer7d5a3bf2019-01-21 12:24:02 -06001367 clientContext = Context(TLSv1_2_METHOD)
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001368
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001369 def verify_callback(*args):
1370 raise Exception("silly verify failure")
Alex Gaynor03737182020-07-23 20:40:46 -04001371
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001372 clientContext.set_verify(VERIFY_PEER, verify_callback)
1373
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01001374 with pytest.raises(Exception) as exc:
1375 self._handshake_test(serverContext, clientContext)
1376
Alex Chan532b79e2017-01-24 15:14:52 +00001377 assert "silly verify failure" == str(exc.value)
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001378
Alex Chan532b79e2017-01-24 15:14:52 +00001379 def test_add_extra_chain_cert(self, tmpdir):
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001380 """
Alex Chan532b79e2017-01-24 15:14:52 +00001381 `Context.add_extra_chain_cert` accepts an `X509`
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001382 instance to add to the certificate chain.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001383
Alex Chan532b79e2017-01-24 15:14:52 +00001384 See `_create_certificate_chain` for the details of the
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001385 certificate chain tested.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001386
1387 The chain is tested by starting a server with scert and connecting
1388 to it with a client which trusts cacert and requires verification to
1389 succeed.
1390 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001391 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001392 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1393
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001394 # Dump the CA certificate to a file because that's the only way to load
1395 # it as a trusted CA in the client context.
Alex Gaynor03737182020-07-23 20:40:46 -04001396 for cert, name in [
1397 (cacert, "ca.pem"),
1398 (icert, "i.pem"),
1399 (scert, "s.pem"),
1400 ]:
1401 with tmpdir.join(name).open("w") as f:
1402 f.write(dump_certificate(FILETYPE_PEM, cert).decode("ascii"))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001403
Alex Gaynor03737182020-07-23 20:40:46 -04001404 for key, name in [(cakey, "ca.key"), (ikey, "i.key"), (skey, "s.key")]:
1405 with tmpdir.join(name).open("w") as f:
1406 f.write(dump_privatekey(FILETYPE_PEM, key).decode("ascii"))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001407
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001408 # Create the server context
Paul Kehrer688538c2020-08-03 19:18:15 -05001409 serverContext = Context(SSLv23_METHOD)
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001410 serverContext.use_privatekey(skey)
1411 serverContext.use_certificate(scert)
Jean-Paul Calderone16cf03d2010-09-08 18:53:39 -04001412 # The client already has cacert, we only need to give them icert.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001413 serverContext.add_extra_chain_cert(icert)
1414
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001415 # Create the client
Paul Kehrer688538c2020-08-03 19:18:15 -05001416 clientContext = Context(SSLv23_METHOD)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001417 clientContext.set_verify(
Alex Gaynor03737182020-07-23 20:40:46 -04001418 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb
1419 )
Alex Chan532b79e2017-01-24 15:14:52 +00001420 clientContext.load_verify_locations(str(tmpdir.join("ca.pem")))
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001421
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001422 # Try it out.
1423 self._handshake_test(serverContext, clientContext)
1424
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001425 def _use_certificate_chain_file_test(self, certdir):
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001426 """
Alex Chan532b79e2017-01-24 15:14:52 +00001427 Verify that `Context.use_certificate_chain_file` reads a
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001428 certificate chain from a specified file.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001429
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001430 The chain is tested by starting a server with scert and connecting to
1431 it with a client which trusts cacert and requires verification to
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001432 succeed.
1433 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001434 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001435 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1436
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001437 makedirs(certdir)
1438
Jean-Paul Calderone05826732015-04-12 11:38:49 -04001439 chainFile = join_bytes_or_unicode(certdir, "chain.pem")
1440 caFile = join_bytes_or_unicode(certdir, "ca.pem")
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001441
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001442 # Write out the chain file.
Alex Gaynor03737182020-07-23 20:40:46 -04001443 with open(chainFile, "wb") as fObj:
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001444 # Most specific to least general.
1445 fObj.write(dump_certificate(FILETYPE_PEM, scert))
1446 fObj.write(dump_certificate(FILETYPE_PEM, icert))
1447 fObj.write(dump_certificate(FILETYPE_PEM, cacert))
1448
Alex Gaynor03737182020-07-23 20:40:46 -04001449 with open(caFile, "w") as fObj:
1450 fObj.write(dump_certificate(FILETYPE_PEM, cacert).decode("ascii"))
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001451
Paul Kehrer688538c2020-08-03 19:18:15 -05001452 serverContext = Context(SSLv23_METHOD)
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001453 serverContext.use_certificate_chain_file(chainFile)
1454 serverContext.use_privatekey(skey)
1455
Paul Kehrer688538c2020-08-03 19:18:15 -05001456 clientContext = Context(SSLv23_METHOD)
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001457 clientContext.set_verify(
Alex Gaynor03737182020-07-23 20:40:46 -04001458 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb
1459 )
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001460 clientContext.load_verify_locations(caFile)
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001461
1462 self._handshake_test(serverContext, clientContext)
1463
Alex Chan532b79e2017-01-24 15:14:52 +00001464 def test_use_certificate_chain_file_bytes(self, tmpfile):
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001465 """
1466 ``Context.use_certificate_chain_file`` accepts the name of a file (as
1467 an instance of ``bytes``) to specify additional certificates to use to
1468 construct and verify a trust chain.
1469 """
1470 self._use_certificate_chain_file_test(
Alex Chan532b79e2017-01-24 15:14:52 +00001471 tmpfile + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001472 )
1473
Alex Chan532b79e2017-01-24 15:14:52 +00001474 def test_use_certificate_chain_file_unicode(self, tmpfile):
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001475 """
1476 ``Context.use_certificate_chain_file`` accepts the name of a file (as
1477 an instance of ``unicode``) to specify additional certificates to use
1478 to construct and verify a trust chain.
1479 """
1480 self._use_certificate_chain_file_test(
Alex Chan532b79e2017-01-24 15:14:52 +00001481 tmpfile.decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001482 )
1483
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001484 def test_use_certificate_chain_file_wrong_args(self):
1485 """
Alex Chan532b79e2017-01-24 15:14:52 +00001486 `Context.use_certificate_chain_file` raises `TypeError` if passed a
1487 non-byte string single argument.
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001488 """
Paul Kehrer688538c2020-08-03 19:18:15 -05001489 context = Context(SSLv23_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001490 with pytest.raises(TypeError):
1491 context.use_certificate_chain_file(object())
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001492
Alex Chan532b79e2017-01-24 15:14:52 +00001493 def test_use_certificate_chain_file_missing_file(self, tmpfile):
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001494 """
Alex Chan532b79e2017-01-24 15:14:52 +00001495 `Context.use_certificate_chain_file` raises `OpenSSL.SSL.Error` when
1496 passed a bad chain file name (for example, the name of a file which
1497 does not exist).
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001498 """
Paul Kehrer688538c2020-08-03 19:18:15 -05001499 context = Context(SSLv23_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001500 with pytest.raises(Error):
1501 context.use_certificate_chain_file(tmpfile)
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001502
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001503 def test_set_verify_mode(self):
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001504 """
Alex Chan532b79e2017-01-24 15:14:52 +00001505 `Context.get_verify_mode` returns the verify mode flags previously
1506 passed to `Context.set_verify`.
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001507 """
Paul Kehrer688538c2020-08-03 19:18:15 -05001508 context = Context(SSLv23_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001509 assert context.get_verify_mode() == 0
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001510 context.set_verify(
Alex Gaynor03737182020-07-23 20:40:46 -04001511 VERIFY_PEER | VERIFY_CLIENT_ONCE, lambda *args: None
1512 )
Alex Chan532b79e2017-01-24 15:14:52 +00001513 assert context.get_verify_mode() == (VERIFY_PEER | VERIFY_CLIENT_ONCE)
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001514
Alex Gaynor03737182020-07-23 20:40:46 -04001515 @pytest.mark.parametrize("mode", [None, 1.0, object(), "mode"])
Alex Chanfb078d82017-04-20 11:16:15 +01001516 def test_set_verify_wrong_mode_arg(self, mode):
1517 """
1518 `Context.set_verify` raises `TypeError` if the first argument is
1519 not an integer.
1520 """
Paul Kehrer688538c2020-08-03 19:18:15 -05001521 context = Context(SSLv23_METHOD)
Alex Chanfb078d82017-04-20 11:16:15 +01001522 with pytest.raises(TypeError):
1523 context.set_verify(mode=mode, callback=lambda *args: None)
1524
Alex Gaynor03737182020-07-23 20:40:46 -04001525 @pytest.mark.parametrize("callback", [None, 1.0, "mode", ("foo", "bar")])
Alex Chanfb078d82017-04-20 11:16:15 +01001526 def test_set_verify_wrong_callable_arg(self, callback):
1527 """
Alex Gaynor40bc0f12018-05-14 14:06:16 -04001528 `Context.set_verify` raises `TypeError` if the second argument
Alex Chanfb078d82017-04-20 11:16:15 +01001529 is not callable.
1530 """
Paul Kehrer688538c2020-08-03 19:18:15 -05001531 context = Context(SSLv23_METHOD)
Alex Chanfb078d82017-04-20 11:16:15 +01001532 with pytest.raises(TypeError):
1533 context.set_verify(mode=VERIFY_PEER, callback=callback)
1534
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001535 def test_load_tmp_dh_wrong_args(self):
1536 """
Alex Chan532b79e2017-01-24 15:14:52 +00001537 `Context.load_tmp_dh` raises `TypeError` if called with a
1538 non-`str` argument.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001539 """
Paul Kehrer688538c2020-08-03 19:18:15 -05001540 context = Context(SSLv23_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001541 with pytest.raises(TypeError):
1542 context.load_tmp_dh(object())
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001543
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001544 def test_load_tmp_dh_missing_file(self):
1545 """
Alex Chan532b79e2017-01-24 15:14:52 +00001546 `Context.load_tmp_dh` raises `OpenSSL.SSL.Error` if the
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001547 specified file does not exist.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001548 """
Paul Kehrer688538c2020-08-03 19:18:15 -05001549 context = Context(SSLv23_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001550 with pytest.raises(Error):
1551 context.load_tmp_dh(b"hello")
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001552
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001553 def _load_tmp_dh_test(self, dhfilename):
Jean-Paul Calderone4e0c43f2015-04-13 10:15:17 -04001554 """
1555 Verify that calling ``Context.load_tmp_dh`` with the given filename
1556 does not raise an exception.
1557 """
Paul Kehrer688538c2020-08-03 19:18:15 -05001558 context = Context(SSLv23_METHOD)
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001559 with open(dhfilename, "w") as dhfile:
1560 dhfile.write(dhparam)
1561
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001562 context.load_tmp_dh(dhfilename)
1563 # XXX What should I assert here? -exarkun
1564
Alex Chan532b79e2017-01-24 15:14:52 +00001565 def test_load_tmp_dh_bytes(self, tmpfile):
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001566 """
Alex Chan532b79e2017-01-24 15:14:52 +00001567 `Context.load_tmp_dh` loads Diffie-Hellman parameters from the
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001568 specified file (given as ``bytes``).
1569 """
1570 self._load_tmp_dh_test(
Alex Chan532b79e2017-01-24 15:14:52 +00001571 tmpfile + NON_ASCII.encode(getfilesystemencoding()),
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001572 )
1573
Alex Chan532b79e2017-01-24 15:14:52 +00001574 def test_load_tmp_dh_unicode(self, tmpfile):
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001575 """
Alex Chan532b79e2017-01-24 15:14:52 +00001576 `Context.load_tmp_dh` loads Diffie-Hellman parameters from the
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001577 specified file (given as ``unicode``).
1578 """
1579 self._load_tmp_dh_test(
Alex Chan532b79e2017-01-24 15:14:52 +00001580 tmpfile.decode(getfilesystemencoding()) + NON_ASCII,
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001581 )
1582
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001583 def test_set_tmp_ecdh(self):
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001584 """
Alex Chan532b79e2017-01-24 15:14:52 +00001585 `Context.set_tmp_ecdh` sets the elliptic curve for Diffie-Hellman to
1586 the specified curve.
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001587 """
Paul Kehrer688538c2020-08-03 19:18:15 -05001588 context = Context(SSLv23_METHOD)
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001589 for curve in get_elliptic_curves():
Hynek Schlawacka07fa8c2015-10-17 10:15:28 +02001590 if curve.name.startswith(u"Oakley-"):
Hynek Schlawack7408aff2015-10-17 09:51:16 +02001591 # Setting Oakley-EC2N-4 and Oakley-EC2N-3 adds
1592 # ('bignum routines', 'BN_mod_inverse', 'no inverse') to the
1593 # error queue on OpenSSL 1.0.2.
1594 continue
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001595 # The only easily "assertable" thing is that it does not raise an
1596 # exception.
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001597 context.set_tmp_ecdh(curve)
Alex Gaynor12dc0842014-01-17 12:51:31 -06001598
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001599 def test_set_session_cache_mode_wrong_args(self):
1600 """
Alex Chan532b79e2017-01-24 15:14:52 +00001601 `Context.set_session_cache_mode` raises `TypeError` if called with
1602 a non-integer argument.
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001603 called with other than one integer argument.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001604 """
Paul Kehrer688538c2020-08-03 19:18:15 -05001605 context = Context(SSLv23_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001606 with pytest.raises(TypeError):
1607 context.set_session_cache_mode(object())
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001608
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001609 def test_session_cache_mode(self):
1610 """
Alex Chan532b79e2017-01-24 15:14:52 +00001611 `Context.set_session_cache_mode` specifies how sessions are cached.
1612 The setting can be retrieved via `Context.get_session_cache_mode`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001613 """
Paul Kehrer688538c2020-08-03 19:18:15 -05001614 context = Context(SSLv23_METHOD)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001615 context.set_session_cache_mode(SESS_CACHE_OFF)
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001616 off = context.set_session_cache_mode(SESS_CACHE_BOTH)
Alex Chan532b79e2017-01-24 15:14:52 +00001617 assert SESS_CACHE_OFF == off
1618 assert SESS_CACHE_BOTH == context.get_session_cache_mode()
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001619
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001620 def test_get_cert_store(self):
1621 """
Alex Chan532b79e2017-01-24 15:14:52 +00001622 `Context.get_cert_store` returns a `X509Store` instance.
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001623 """
Paul Kehrer688538c2020-08-03 19:18:15 -05001624 context = Context(SSLv23_METHOD)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001625 store = context.get_cert_store()
Alex Chan532b79e2017-01-24 15:14:52 +00001626 assert isinstance(store, X509Store)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001627
Jeremy Lainé02261ad2018-05-16 18:33:25 +02001628 def test_set_tlsext_use_srtp_not_bytes(self):
1629 """
1630 `Context.set_tlsext_use_srtp' enables negotiating SRTP keying material.
1631
1632 It raises a TypeError if the list of profiles is not a byte string.
1633 """
Paul Kehrer688538c2020-08-03 19:18:15 -05001634 context = Context(SSLv23_METHOD)
Jeremy Lainé02261ad2018-05-16 18:33:25 +02001635 with pytest.raises(TypeError):
Alex Gaynor03737182020-07-23 20:40:46 -04001636 context.set_tlsext_use_srtp(text_type("SRTP_AES128_CM_SHA1_80"))
Jeremy Lainé02261ad2018-05-16 18:33:25 +02001637
1638 def test_set_tlsext_use_srtp_invalid_profile(self):
1639 """
1640 `Context.set_tlsext_use_srtp' enables negotiating SRTP keying material.
1641
1642 It raises an Error if the call to OpenSSL fails.
1643 """
Paul Kehrer688538c2020-08-03 19:18:15 -05001644 context = Context(SSLv23_METHOD)
Jeremy Lainé02261ad2018-05-16 18:33:25 +02001645 with pytest.raises(Error):
Alex Gaynor03737182020-07-23 20:40:46 -04001646 context.set_tlsext_use_srtp(b"SRTP_BOGUS")
Jeremy Lainé02261ad2018-05-16 18:33:25 +02001647
1648 def test_set_tlsext_use_srtp_valid(self):
1649 """
1650 `Context.set_tlsext_use_srtp' enables negotiating SRTP keying material.
1651
1652 It does not return anything.
1653 """
Paul Kehrer688538c2020-08-03 19:18:15 -05001654 context = Context(SSLv23_METHOD)
Alex Gaynor03737182020-07-23 20:40:46 -04001655 assert context.set_tlsext_use_srtp(b"SRTP_AES128_CM_SHA1_80") is None
Jeremy Lainé02261ad2018-05-16 18:33:25 +02001656
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001657
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001658class TestServerNameCallback(object):
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001659 """
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001660 Tests for `Context.set_tlsext_servername_callback` and its
1661 interaction with `Connection`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001662 """
Alex Gaynor03737182020-07-23 20:40:46 -04001663
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001664 def test_old_callback_forgotten(self):
1665 """
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001666 If `Context.set_tlsext_servername_callback` is used to specify
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001667 a new callback, the one it replaces is dereferenced.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001668 """
Alex Gaynor03737182020-07-23 20:40:46 -04001669
Alex Chanfb078d82017-04-20 11:16:15 +01001670 def callback(connection): # pragma: no cover
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001671 pass
1672
Alex Chanfb078d82017-04-20 11:16:15 +01001673 def replacement(connection): # pragma: no cover
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001674 pass
1675
Paul Kehrer688538c2020-08-03 19:18:15 -05001676 context = Context(SSLv23_METHOD)
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001677 context.set_tlsext_servername_callback(callback)
1678
1679 tracker = ref(callback)
1680 del callback
1681
1682 context.set_tlsext_servername_callback(replacement)
Jean-Paul Calderoned4033eb2014-01-11 08:21:46 -05001683
1684 # One run of the garbage collector happens to work on CPython. PyPy
1685 # doesn't collect the underlying object until a second run for whatever
1686 # reason. That's fine, it still demonstrates our code has properly
1687 # dropped the reference.
1688 collect()
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001689 collect()
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001690
1691 callback = tracker()
1692 if callback is not None:
1693 referrers = get_referrers(callback)
Alex Chanfb078d82017-04-20 11:16:15 +01001694 if len(referrers) > 1: # pragma: nocover
1695 pytest.fail("Some references remain: %r" % (referrers,))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001696
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001697 def test_no_servername(self):
1698 """
1699 When a client specifies no server name, the callback passed to
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001700 `Context.set_tlsext_servername_callback` is invoked and the
1701 result of `Connection.get_servername` is `None`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001702 """
1703 args = []
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001704
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001705 def servername(conn):
1706 args.append((conn, conn.get_servername()))
Alex Gaynor03737182020-07-23 20:40:46 -04001707
Paul Kehrer688538c2020-08-03 19:18:15 -05001708 context = Context(SSLv23_METHOD)
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001709 context.set_tlsext_servername_callback(servername)
1710
1711 # Lose our reference to it. The Context is responsible for keeping it
1712 # alive now.
1713 del servername
1714 collect()
1715
1716 # Necessary to actually accept the connection
1717 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001718 context.use_certificate(
Alex Gaynor03737182020-07-23 20:40:46 -04001719 load_certificate(FILETYPE_PEM, server_cert_pem)
1720 )
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001721
1722 # Do a little connection to trigger the logic
1723 server = Connection(context, None)
1724 server.set_accept_state()
1725
Paul Kehrer688538c2020-08-03 19:18:15 -05001726 client = Connection(Context(SSLv23_METHOD), None)
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001727 client.set_connect_state()
1728
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001729 interact_in_memory(server, client)
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001730
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001731 assert args == [(server, None)]
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001732
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001733 def test_servername(self):
1734 """
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001735 When a client specifies a server name in its hello message, the
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001736 callback passed to `Contexts.set_tlsext_servername_callback` is
1737 invoked and the result of `Connection.get_servername` is that
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001738 server name.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001739 """
1740 args = []
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001741
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001742 def servername(conn):
1743 args.append((conn, conn.get_servername()))
Alex Gaynor03737182020-07-23 20:40:46 -04001744
Paul Kehrer688538c2020-08-03 19:18:15 -05001745 context = Context(SSLv23_METHOD)
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001746 context.set_tlsext_servername_callback(servername)
1747
1748 # Necessary to actually accept the connection
1749 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001750 context.use_certificate(
Alex Gaynor03737182020-07-23 20:40:46 -04001751 load_certificate(FILETYPE_PEM, server_cert_pem)
1752 )
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001753
1754 # Do a little connection to trigger the logic
1755 server = Connection(context, None)
1756 server.set_accept_state()
1757
Paul Kehrer688538c2020-08-03 19:18:15 -05001758 client = Connection(Context(SSLv23_METHOD), None)
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001759 client.set_connect_state()
Alex Gaynore7f51982016-09-11 11:48:14 -04001760 client.set_tlsext_host_name(b"foo1.example.com")
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001761
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001762 interact_in_memory(server, client)
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001763
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001764 assert args == [(server, b"foo1.example.com")]
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001765
1766
Paul Kehrer4d575902019-02-26 21:42:12 +08001767@pytest.mark.skipif(
1768 not _lib.Cryptography_HAS_NEXTPROTONEG, reason="NPN is not available"
1769)
Alex Chan9e08b3e2016-11-10 12:18:54 +00001770class TestNextProtoNegotiation(object):
Cory Benfield84a121e2014-03-31 20:30:25 +01001771 """
1772 Test for Next Protocol Negotiation in PyOpenSSL.
1773 """
Alex Gaynor03737182020-07-23 20:40:46 -04001774
Alex Chan9e08b3e2016-11-10 12:18:54 +00001775 def test_npn_success(self):
1776 """
1777 Tests that clients and servers that agree on the negotiated next
1778 protocol can correct establish a connection, and that the agreed
1779 protocol is reported by the connections.
1780 """
1781 advertise_args = []
1782 select_args = []
1783
1784 def advertise(conn):
1785 advertise_args.append((conn,))
Alex Gaynor03737182020-07-23 20:40:46 -04001786 return [b"http/1.1", b"spdy/2"]
Alex Chan9e08b3e2016-11-10 12:18:54 +00001787
1788 def select(conn, options):
1789 select_args.append((conn, options))
Alex Gaynor03737182020-07-23 20:40:46 -04001790 return b"spdy/2"
Alex Chan9e08b3e2016-11-10 12:18:54 +00001791
Paul Kehrer688538c2020-08-03 19:18:15 -05001792 server_context = Context(SSLv23_METHOD)
Alex Chan9e08b3e2016-11-10 12:18:54 +00001793 server_context.set_npn_advertise_callback(advertise)
1794
Paul Kehrer688538c2020-08-03 19:18:15 -05001795 client_context = Context(SSLv23_METHOD)
Alex Chan9e08b3e2016-11-10 12:18:54 +00001796 client_context.set_npn_select_callback(select)
1797
1798 # Necessary to actually accept the connection
1799 server_context.use_privatekey(
Alex Gaynor03737182020-07-23 20:40:46 -04001800 load_privatekey(FILETYPE_PEM, server_key_pem)
1801 )
Alex Chan9e08b3e2016-11-10 12:18:54 +00001802 server_context.use_certificate(
Alex Gaynor03737182020-07-23 20:40:46 -04001803 load_certificate(FILETYPE_PEM, server_cert_pem)
1804 )
Alex Chan9e08b3e2016-11-10 12:18:54 +00001805
1806 # Do a little connection to trigger the logic
1807 server = Connection(server_context, None)
1808 server.set_accept_state()
1809
1810 client = Connection(client_context, None)
1811 client.set_connect_state()
1812
1813 interact_in_memory(server, client)
1814
1815 assert advertise_args == [(server,)]
Alex Gaynor03737182020-07-23 20:40:46 -04001816 assert select_args == [(client, [b"http/1.1", b"spdy/2"])]
Alex Chan9e08b3e2016-11-10 12:18:54 +00001817
Alex Gaynor03737182020-07-23 20:40:46 -04001818 assert server.get_next_proto_negotiated() == b"spdy/2"
1819 assert client.get_next_proto_negotiated() == b"spdy/2"
Alex Chan9e08b3e2016-11-10 12:18:54 +00001820
1821 def test_npn_client_fail(self):
1822 """
1823 Tests that when clients and servers cannot agree on what protocol
1824 to use next that the TLS connection does not get established.
1825 """
1826 advertise_args = []
1827 select_args = []
1828
1829 def advertise(conn):
1830 advertise_args.append((conn,))
Alex Gaynor03737182020-07-23 20:40:46 -04001831 return [b"http/1.1", b"spdy/2"]
Alex Chan9e08b3e2016-11-10 12:18:54 +00001832
1833 def select(conn, options):
1834 select_args.append((conn, options))
Alex Gaynor03737182020-07-23 20:40:46 -04001835 return b""
Alex Chan9e08b3e2016-11-10 12:18:54 +00001836
Paul Kehrer688538c2020-08-03 19:18:15 -05001837 server_context = Context(SSLv23_METHOD)
Alex Chan9e08b3e2016-11-10 12:18:54 +00001838 server_context.set_npn_advertise_callback(advertise)
1839
Paul Kehrer688538c2020-08-03 19:18:15 -05001840 client_context = Context(SSLv23_METHOD)
Alex Chan9e08b3e2016-11-10 12:18:54 +00001841 client_context.set_npn_select_callback(select)
1842
1843 # Necessary to actually accept the connection
1844 server_context.use_privatekey(
Alex Gaynor03737182020-07-23 20:40:46 -04001845 load_privatekey(FILETYPE_PEM, server_key_pem)
1846 )
Alex Chan9e08b3e2016-11-10 12:18:54 +00001847 server_context.use_certificate(
Alex Gaynor03737182020-07-23 20:40:46 -04001848 load_certificate(FILETYPE_PEM, server_cert_pem)
1849 )
Alex Chan9e08b3e2016-11-10 12:18:54 +00001850
1851 # Do a little connection to trigger the logic
1852 server = Connection(server_context, None)
1853 server.set_accept_state()
1854
1855 client = Connection(client_context, None)
1856 client.set_connect_state()
1857
1858 # If the client doesn't return anything, the connection will fail.
1859 with pytest.raises(Error):
1860 interact_in_memory(server, client)
1861
1862 assert advertise_args == [(server,)]
Alex Gaynor03737182020-07-23 20:40:46 -04001863 assert select_args == [(client, [b"http/1.1", b"spdy/2"])]
Alex Chan9e08b3e2016-11-10 12:18:54 +00001864
1865 def test_npn_select_error(self):
1866 """
1867 Test that we can handle exceptions in the select callback. If
1868 select fails it should be fatal to the connection.
1869 """
1870 advertise_args = []
1871
1872 def advertise(conn):
1873 advertise_args.append((conn,))
Alex Gaynor03737182020-07-23 20:40:46 -04001874 return [b"http/1.1", b"spdy/2"]
Alex Chan9e08b3e2016-11-10 12:18:54 +00001875
1876 def select(conn, options):
1877 raise TypeError
1878
Paul Kehrer688538c2020-08-03 19:18:15 -05001879 server_context = Context(SSLv23_METHOD)
Alex Chan9e08b3e2016-11-10 12:18:54 +00001880 server_context.set_npn_advertise_callback(advertise)
1881
Paul Kehrer688538c2020-08-03 19:18:15 -05001882 client_context = Context(SSLv23_METHOD)
Alex Chan9e08b3e2016-11-10 12:18:54 +00001883 client_context.set_npn_select_callback(select)
1884
1885 # Necessary to actually accept the connection
1886 server_context.use_privatekey(
Alex Gaynor03737182020-07-23 20:40:46 -04001887 load_privatekey(FILETYPE_PEM, server_key_pem)
1888 )
Alex Chan9e08b3e2016-11-10 12:18:54 +00001889 server_context.use_certificate(
Alex Gaynor03737182020-07-23 20:40:46 -04001890 load_certificate(FILETYPE_PEM, server_cert_pem)
1891 )
Alex Chan9e08b3e2016-11-10 12:18:54 +00001892
1893 # Do a little connection to trigger the logic
1894 server = Connection(server_context, None)
1895 server.set_accept_state()
1896
1897 client = Connection(client_context, None)
1898 client.set_connect_state()
1899
1900 # If the callback throws an exception it should be raised here.
1901 with pytest.raises(TypeError):
1902 interact_in_memory(server, client)
Alex Gaynor03737182020-07-23 20:40:46 -04001903 assert advertise_args == [
1904 (server,),
1905 ]
Alex Chan9e08b3e2016-11-10 12:18:54 +00001906
1907 def test_npn_advertise_error(self):
1908 """
1909 Test that we can handle exceptions in the advertise callback. If
1910 advertise fails no NPN is advertised to the client.
1911 """
1912 select_args = []
1913
1914 def advertise(conn):
1915 raise TypeError
1916
1917 def select(conn, options): # pragma: nocover
Cory Benfieldba1820d2015-04-13 17:39:12 -04001918 """
Alex Chan9e08b3e2016-11-10 12:18:54 +00001919 Assert later that no args are actually appended.
Cory Benfieldba1820d2015-04-13 17:39:12 -04001920 """
Alex Chan9e08b3e2016-11-10 12:18:54 +00001921 select_args.append((conn, options))
Alex Gaynor03737182020-07-23 20:40:46 -04001922 return b""
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001923
Paul Kehrer688538c2020-08-03 19:18:15 -05001924 server_context = Context(SSLv23_METHOD)
Alex Chan9e08b3e2016-11-10 12:18:54 +00001925 server_context.set_npn_advertise_callback(advertise)
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001926
Paul Kehrer688538c2020-08-03 19:18:15 -05001927 client_context = Context(SSLv23_METHOD)
Alex Chan9e08b3e2016-11-10 12:18:54 +00001928 client_context.set_npn_select_callback(select)
Cory Benfield84a121e2014-03-31 20:30:25 +01001929
Alex Chan9e08b3e2016-11-10 12:18:54 +00001930 # Necessary to actually accept the connection
1931 server_context.use_privatekey(
Alex Gaynor03737182020-07-23 20:40:46 -04001932 load_privatekey(FILETYPE_PEM, server_key_pem)
1933 )
Alex Chan9e08b3e2016-11-10 12:18:54 +00001934 server_context.use_certificate(
Alex Gaynor03737182020-07-23 20:40:46 -04001935 load_certificate(FILETYPE_PEM, server_cert_pem)
1936 )
Cory Benfield84a121e2014-03-31 20:30:25 +01001937
Alex Chan9e08b3e2016-11-10 12:18:54 +00001938 # Do a little connection to trigger the logic
1939 server = Connection(server_context, None)
1940 server.set_accept_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001941
Alex Chan9e08b3e2016-11-10 12:18:54 +00001942 client = Connection(client_context, None)
1943 client.set_connect_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001944
Alex Chan9e08b3e2016-11-10 12:18:54 +00001945 # If the client doesn't return anything, the connection will fail.
1946 with pytest.raises(TypeError):
1947 interact_in_memory(server, client)
1948 assert select_args == []
Cory Benfield0ea76e72015-03-22 09:05:28 +00001949
1950
Alex Chanec1e32d2016-11-10 14:11:45 +00001951class TestApplicationLayerProtoNegotiation(object):
Cory Benfield12eae892014-06-07 15:42:56 +01001952 """
1953 Tests for ALPN in PyOpenSSL.
1954 """
Alex Gaynor03737182020-07-23 20:40:46 -04001955
Alex Gaynor77debda2020-04-07 13:40:59 -04001956 def test_alpn_success(self):
1957 """
1958 Clients and servers that agree on the negotiated ALPN protocol can
1959 correct establish a connection, and the agreed protocol is reported
1960 by the connections.
1961 """
1962 select_args = []
Cory Benfield12eae892014-06-07 15:42:56 +01001963
Alex Gaynor77debda2020-04-07 13:40:59 -04001964 def select(conn, options):
1965 select_args.append((conn, options))
Alex Gaynor03737182020-07-23 20:40:46 -04001966 return b"spdy/2"
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001967
Paul Kehrer688538c2020-08-03 19:18:15 -05001968 client_context = Context(SSLv23_METHOD)
Alex Gaynor03737182020-07-23 20:40:46 -04001969 client_context.set_alpn_protos([b"http/1.1", b"spdy/2"])
Cory Benfield12eae892014-06-07 15:42:56 +01001970
Paul Kehrer688538c2020-08-03 19:18:15 -05001971 server_context = Context(SSLv23_METHOD)
Alex Gaynor77debda2020-04-07 13:40:59 -04001972 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01001973
Alex Gaynor77debda2020-04-07 13:40:59 -04001974 # Necessary to actually accept the connection
1975 server_context.use_privatekey(
Alex Gaynor03737182020-07-23 20:40:46 -04001976 load_privatekey(FILETYPE_PEM, server_key_pem)
1977 )
Alex Gaynor77debda2020-04-07 13:40:59 -04001978 server_context.use_certificate(
Alex Gaynor03737182020-07-23 20:40:46 -04001979 load_certificate(FILETYPE_PEM, server_cert_pem)
1980 )
Cory Benfield12eae892014-06-07 15:42:56 +01001981
Alex Gaynor77debda2020-04-07 13:40:59 -04001982 # Do a little connection to trigger the logic
1983 server = Connection(server_context, None)
1984 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001985
Alex Gaynor77debda2020-04-07 13:40:59 -04001986 client = Connection(client_context, None)
1987 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001988
Alex Gaynor77debda2020-04-07 13:40:59 -04001989 interact_in_memory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001990
Alex Gaynor03737182020-07-23 20:40:46 -04001991 assert select_args == [(server, [b"http/1.1", b"spdy/2"])]
Alex Gaynor77debda2020-04-07 13:40:59 -04001992
Alex Gaynor03737182020-07-23 20:40:46 -04001993 assert server.get_alpn_proto_negotiated() == b"spdy/2"
1994 assert client.get_alpn_proto_negotiated() == b"spdy/2"
Alex Gaynor77debda2020-04-07 13:40:59 -04001995
1996 def test_alpn_set_on_connection(self):
1997 """
1998 The same as test_alpn_success, but setting the ALPN protocols on
1999 the connection rather than the context.
2000 """
2001 select_args = []
2002
2003 def select(conn, options):
2004 select_args.append((conn, options))
Alex Gaynor03737182020-07-23 20:40:46 -04002005 return b"spdy/2"
Alex Gaynor77debda2020-04-07 13:40:59 -04002006
2007 # Setup the client context but don't set any ALPN protocols.
Paul Kehrer688538c2020-08-03 19:18:15 -05002008 client_context = Context(SSLv23_METHOD)
Alex Gaynor77debda2020-04-07 13:40:59 -04002009
Paul Kehrer688538c2020-08-03 19:18:15 -05002010 server_context = Context(SSLv23_METHOD)
Alex Gaynor77debda2020-04-07 13:40:59 -04002011 server_context.set_alpn_select_callback(select)
2012
2013 # Necessary to actually accept the connection
2014 server_context.use_privatekey(
Alex Gaynor03737182020-07-23 20:40:46 -04002015 load_privatekey(FILETYPE_PEM, server_key_pem)
2016 )
Alex Gaynor77debda2020-04-07 13:40:59 -04002017 server_context.use_certificate(
Alex Gaynor03737182020-07-23 20:40:46 -04002018 load_certificate(FILETYPE_PEM, server_cert_pem)
2019 )
Alex Gaynor77debda2020-04-07 13:40:59 -04002020
2021 # Do a little connection to trigger the logic
2022 server = Connection(server_context, None)
2023 server.set_accept_state()
2024
2025 # Set the ALPN protocols on the client connection.
2026 client = Connection(client_context, None)
Alex Gaynor03737182020-07-23 20:40:46 -04002027 client.set_alpn_protos([b"http/1.1", b"spdy/2"])
Alex Gaynor77debda2020-04-07 13:40:59 -04002028 client.set_connect_state()
2029
2030 interact_in_memory(server, client)
2031
Alex Gaynor03737182020-07-23 20:40:46 -04002032 assert select_args == [(server, [b"http/1.1", b"spdy/2"])]
Alex Gaynor77debda2020-04-07 13:40:59 -04002033
Alex Gaynor03737182020-07-23 20:40:46 -04002034 assert server.get_alpn_proto_negotiated() == b"spdy/2"
2035 assert client.get_alpn_proto_negotiated() == b"spdy/2"
Alex Gaynor77debda2020-04-07 13:40:59 -04002036
2037 def test_alpn_server_fail(self):
2038 """
2039 When clients and servers cannot agree on what protocol to use next
2040 the TLS connection does not get established.
2041 """
2042 select_args = []
2043
2044 def select(conn, options):
2045 select_args.append((conn, options))
Alex Gaynor03737182020-07-23 20:40:46 -04002046 return b""
Alex Gaynor77debda2020-04-07 13:40:59 -04002047
Paul Kehrer688538c2020-08-03 19:18:15 -05002048 client_context = Context(SSLv23_METHOD)
Alex Gaynor03737182020-07-23 20:40:46 -04002049 client_context.set_alpn_protos([b"http/1.1", b"spdy/2"])
Alex Gaynor77debda2020-04-07 13:40:59 -04002050
Paul Kehrer688538c2020-08-03 19:18:15 -05002051 server_context = Context(SSLv23_METHOD)
Alex Gaynor77debda2020-04-07 13:40:59 -04002052 server_context.set_alpn_select_callback(select)
2053
2054 # Necessary to actually accept the connection
2055 server_context.use_privatekey(
Alex Gaynor03737182020-07-23 20:40:46 -04002056 load_privatekey(FILETYPE_PEM, server_key_pem)
2057 )
Alex Gaynor77debda2020-04-07 13:40:59 -04002058 server_context.use_certificate(
Alex Gaynor03737182020-07-23 20:40:46 -04002059 load_certificate(FILETYPE_PEM, server_cert_pem)
2060 )
Alex Gaynor77debda2020-04-07 13:40:59 -04002061
2062 # Do a little connection to trigger the logic
2063 server = Connection(server_context, None)
2064 server.set_accept_state()
2065
2066 client = Connection(client_context, None)
2067 client.set_connect_state()
2068
2069 # If the client doesn't return anything, the connection will fail.
2070 with pytest.raises(Error):
Alex Chanec1e32d2016-11-10 14:11:45 +00002071 interact_in_memory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01002072
Alex Gaynor03737182020-07-23 20:40:46 -04002073 assert select_args == [(server, [b"http/1.1", b"spdy/2"])]
Cory Benfielde46fa842015-04-13 16:50:49 -04002074
Alex Gaynor77debda2020-04-07 13:40:59 -04002075 def test_alpn_no_server_overlap(self):
2076 """
2077 A server can allow a TLS handshake to complete without
2078 agreeing to an application protocol by returning
2079 ``NO_OVERLAPPING_PROTOCOLS``.
2080 """
2081 refusal_args = []
Cory Benfield12eae892014-06-07 15:42:56 +01002082
Alex Gaynor77debda2020-04-07 13:40:59 -04002083 def refusal(conn, options):
2084 refusal_args.append((conn, options))
2085 return NO_OVERLAPPING_PROTOCOLS
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002086
Alex Gaynor77debda2020-04-07 13:40:59 -04002087 client_context = Context(SSLv23_METHOD)
Alex Gaynor03737182020-07-23 20:40:46 -04002088 client_context.set_alpn_protos([b"http/1.1", b"spdy/2"])
Cory Benfield12eae892014-06-07 15:42:56 +01002089
Alex Gaynor77debda2020-04-07 13:40:59 -04002090 server_context = Context(SSLv23_METHOD)
2091 server_context.set_alpn_select_callback(refusal)
Cory Benfield12eae892014-06-07 15:42:56 +01002092
Alex Gaynor77debda2020-04-07 13:40:59 -04002093 # Necessary to actually accept the connection
2094 server_context.use_privatekey(
Alex Gaynor03737182020-07-23 20:40:46 -04002095 load_privatekey(FILETYPE_PEM, server_key_pem)
2096 )
Alex Gaynor77debda2020-04-07 13:40:59 -04002097 server_context.use_certificate(
Alex Gaynor03737182020-07-23 20:40:46 -04002098 load_certificate(FILETYPE_PEM, server_cert_pem)
2099 )
Cory Benfield12eae892014-06-07 15:42:56 +01002100
Alex Gaynor77debda2020-04-07 13:40:59 -04002101 # Do a little connection to trigger the logic
2102 server = Connection(server_context, None)
2103 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01002104
Alex Gaynor77debda2020-04-07 13:40:59 -04002105 client = Connection(client_context, None)
2106 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01002107
Alex Gaynor77debda2020-04-07 13:40:59 -04002108 # Do the dance.
2109 interact_in_memory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01002110
Alex Gaynor03737182020-07-23 20:40:46 -04002111 assert refusal_args == [(server, [b"http/1.1", b"spdy/2"])]
Alex Gaynor77debda2020-04-07 13:40:59 -04002112
Alex Gaynor03737182020-07-23 20:40:46 -04002113 assert client.get_alpn_proto_negotiated() == b""
Alex Gaynor77debda2020-04-07 13:40:59 -04002114
2115 def test_alpn_select_cb_returns_invalid_value(self):
2116 """
2117 If the ALPN selection callback returns anything other than
2118 a bytestring or ``NO_OVERLAPPING_PROTOCOLS``, a
2119 :py:exc:`TypeError` is raised.
2120 """
2121 invalid_cb_args = []
2122
2123 def invalid_cb(conn, options):
2124 invalid_cb_args.append((conn, options))
2125 return u"can't return unicode"
2126
2127 client_context = Context(SSLv23_METHOD)
Alex Gaynor03737182020-07-23 20:40:46 -04002128 client_context.set_alpn_protos([b"http/1.1", b"spdy/2"])
Alex Gaynor77debda2020-04-07 13:40:59 -04002129
2130 server_context = Context(SSLv23_METHOD)
2131 server_context.set_alpn_select_callback(invalid_cb)
2132
2133 # Necessary to actually accept the connection
2134 server_context.use_privatekey(
Alex Gaynor03737182020-07-23 20:40:46 -04002135 load_privatekey(FILETYPE_PEM, server_key_pem)
2136 )
Alex Gaynor77debda2020-04-07 13:40:59 -04002137 server_context.use_certificate(
Alex Gaynor03737182020-07-23 20:40:46 -04002138 load_certificate(FILETYPE_PEM, server_cert_pem)
2139 )
Alex Gaynor77debda2020-04-07 13:40:59 -04002140
2141 # Do a little connection to trigger the logic
2142 server = Connection(server_context, None)
2143 server.set_accept_state()
2144
2145 client = Connection(client_context, None)
2146 client.set_connect_state()
2147
2148 # Do the dance.
2149 with pytest.raises(TypeError):
Alex Chanec1e32d2016-11-10 14:11:45 +00002150 interact_in_memory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01002151
Alex Gaynor03737182020-07-23 20:40:46 -04002152 assert invalid_cb_args == [(server, [b"http/1.1", b"spdy/2"])]
Cory Benfield12eae892014-06-07 15:42:56 +01002153
Alex Gaynor03737182020-07-23 20:40:46 -04002154 assert client.get_alpn_proto_negotiated() == b""
Cory Benfield12eae892014-06-07 15:42:56 +01002155
Alex Gaynor77debda2020-04-07 13:40:59 -04002156 def test_alpn_no_server(self):
2157 """
2158 When clients and servers cannot agree on what protocol to use next
2159 because the server doesn't offer ALPN, no protocol is negotiated.
2160 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002161 client_context = Context(SSLv23_METHOD)
Alex Gaynor03737182020-07-23 20:40:46 -04002162 client_context.set_alpn_protos([b"http/1.1", b"spdy/2"])
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002163
Paul Kehrer688538c2020-08-03 19:18:15 -05002164 server_context = Context(SSLv23_METHOD)
Cory Benfield12eae892014-06-07 15:42:56 +01002165
Alex Gaynor77debda2020-04-07 13:40:59 -04002166 # Necessary to actually accept the connection
2167 server_context.use_privatekey(
Alex Gaynor03737182020-07-23 20:40:46 -04002168 load_privatekey(FILETYPE_PEM, server_key_pem)
2169 )
Alex Gaynor77debda2020-04-07 13:40:59 -04002170 server_context.use_certificate(
Alex Gaynor03737182020-07-23 20:40:46 -04002171 load_certificate(FILETYPE_PEM, server_cert_pem)
2172 )
Cory Benfield12eae892014-06-07 15:42:56 +01002173
Alex Gaynor77debda2020-04-07 13:40:59 -04002174 # Do a little connection to trigger the logic
2175 server = Connection(server_context, None)
2176 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01002177
Alex Gaynor77debda2020-04-07 13:40:59 -04002178 client = Connection(client_context, None)
2179 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01002180
Alex Gaynor77debda2020-04-07 13:40:59 -04002181 # Do the dance.
2182 interact_in_memory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01002183
Alex Gaynor03737182020-07-23 20:40:46 -04002184 assert client.get_alpn_proto_negotiated() == b""
Cory Benfield12eae892014-06-07 15:42:56 +01002185
Alex Gaynor77debda2020-04-07 13:40:59 -04002186 def test_alpn_callback_exception(self):
2187 """
2188 We can handle exceptions in the ALPN select callback.
2189 """
2190 select_args = []
Cory Benfield12eae892014-06-07 15:42:56 +01002191
Alex Gaynor77debda2020-04-07 13:40:59 -04002192 def select(conn, options):
2193 select_args.append((conn, options))
2194 raise TypeError()
Cory Benfield12eae892014-06-07 15:42:56 +01002195
Paul Kehrer688538c2020-08-03 19:18:15 -05002196 client_context = Context(SSLv23_METHOD)
Alex Gaynor03737182020-07-23 20:40:46 -04002197 client_context.set_alpn_protos([b"http/1.1", b"spdy/2"])
Mark Williams5d890a02019-11-17 19:56:26 -08002198
Paul Kehrer688538c2020-08-03 19:18:15 -05002199 server_context = Context(SSLv23_METHOD)
Alex Gaynor77debda2020-04-07 13:40:59 -04002200 server_context.set_alpn_select_callback(select)
Mark Williams5d890a02019-11-17 19:56:26 -08002201
Alex Gaynor77debda2020-04-07 13:40:59 -04002202 # Necessary to actually accept the connection
2203 server_context.use_privatekey(
Alex Gaynor03737182020-07-23 20:40:46 -04002204 load_privatekey(FILETYPE_PEM, server_key_pem)
2205 )
Alex Gaynor77debda2020-04-07 13:40:59 -04002206 server_context.use_certificate(
Alex Gaynor03737182020-07-23 20:40:46 -04002207 load_certificate(FILETYPE_PEM, server_cert_pem)
2208 )
Mark Williams5d890a02019-11-17 19:56:26 -08002209
Alex Gaynor77debda2020-04-07 13:40:59 -04002210 # Do a little connection to trigger the logic
2211 server = Connection(server_context, None)
2212 server.set_accept_state()
Mark Williams5d890a02019-11-17 19:56:26 -08002213
Alex Gaynor77debda2020-04-07 13:40:59 -04002214 client = Connection(client_context, None)
2215 client.set_connect_state()
Mark Williams5d890a02019-11-17 19:56:26 -08002216
Alex Gaynor77debda2020-04-07 13:40:59 -04002217 with pytest.raises(TypeError):
Mark Williams5d890a02019-11-17 19:56:26 -08002218 interact_in_memory(server, client)
Alex Gaynor03737182020-07-23 20:40:46 -04002219 assert select_args == [(server, [b"http/1.1", b"spdy/2"])]
Cory Benfield0f7b04c2015-04-13 17:51:12 -04002220
Cory Benfieldf1177e72015-04-12 09:11:49 -04002221
Alex Chanec1e32d2016-11-10 14:11:45 +00002222class TestSession(object):
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05002223 """
2224 Unit tests for :py:obj:`OpenSSL.SSL.Session`.
2225 """
Alex Gaynor03737182020-07-23 20:40:46 -04002226
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05002227 def test_construction(self):
2228 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002229 :py:class:`Session` can be constructed with no arguments, creating
2230 a new instance of that type.
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05002231 """
2232 new_session = Session()
Alex Chanec1e32d2016-11-10 14:11:45 +00002233 assert isinstance(new_session, Session)
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05002234
2235
Alex Chan1c0cb662017-01-30 07:13:30 +00002236class TestConnection(object):
Rick Deane15b1472009-07-09 15:53:42 -05002237 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002238 Unit tests for `OpenSSL.SSL.Connection`.
Rick Deane15b1472009-07-09 15:53:42 -05002239 """
Alex Gaynor03737182020-07-23 20:40:46 -04002240
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04002241 # XXX get_peer_certificate -> None
2242 # XXX sock_shutdown
2243 # XXX master_key -> TypeError
2244 # XXX server_random -> TypeError
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04002245 # XXX connect -> TypeError
2246 # XXX connect_ex -> TypeError
2247 # XXX set_connect_state -> TypeError
2248 # XXX set_accept_state -> TypeError
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04002249 # XXX do_handshake -> TypeError
2250 # XXX bio_read -> TypeError
2251 # XXX recv -> TypeError
2252 # XXX send -> TypeError
2253 # XXX bio_write -> TypeError
2254
Rick Deane15b1472009-07-09 15:53:42 -05002255 def test_type(self):
2256 """
Alex Gaynor01f90a12019-02-07 09:14:48 -05002257 `Connection` can be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -05002258 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002259 ctx = Context(SSLv23_METHOD)
Alex Gaynor03737182020-07-23 20:40:46 -04002260 assert is_consistent_type(Connection, "Connection", ctx, None)
Rick Deane15b1472009-07-09 15:53:42 -05002261
Alex Gaynor03737182020-07-23 20:40:46 -04002262 @pytest.mark.parametrize("bad_context", [object(), "context", None, 1])
Alex Chanfb078d82017-04-20 11:16:15 +01002263 def test_wrong_args(self, bad_context):
2264 """
2265 `Connection.__init__` raises `TypeError` if called with a non-`Context`
2266 instance argument.
2267 """
2268 with pytest.raises(TypeError):
2269 Connection(bad_context)
2270
Alex Gaynor03737182020-07-23 20:40:46 -04002271 @pytest.mark.parametrize("bad_bio", [object(), None, 1, [1, 2, 3]])
Daniel Holth079c9632019-11-17 22:45:52 -05002272 def test_bio_write_wrong_args(self, bad_bio):
2273 """
2274 `Connection.bio_write` raises `TypeError` if called with a non-bytes
2275 (or text) argument.
2276 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002277 context = Context(SSLv23_METHOD)
Daniel Holth079c9632019-11-17 22:45:52 -05002278 connection = Connection(context, None)
2279 with pytest.raises(TypeError):
2280 connection.bio_write(bad_bio)
2281
2282 def test_bio_write(self):
2283 """
2284 `Connection.bio_write` does not raise if called with bytes or
2285 bytearray, warns if called with text.
2286 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002287 context = Context(SSLv23_METHOD)
Daniel Holth079c9632019-11-17 22:45:52 -05002288 connection = Connection(context, None)
Alex Gaynor03737182020-07-23 20:40:46 -04002289 connection.bio_write(b"xy")
2290 connection.bio_write(bytearray(b"za"))
Daniel Holth079c9632019-11-17 22:45:52 -05002291 with pytest.warns(DeprecationWarning):
Alex Gaynor03737182020-07-23 20:40:46 -04002292 connection.bio_write(u"deprecated")
Daniel Holth079c9632019-11-17 22:45:52 -05002293
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002294 def test_get_context(self):
2295 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002296 `Connection.get_context` returns the `Context` instance used to
2297 construct the `Connection` instance.
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002298 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002299 context = Context(SSLv23_METHOD)
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002300 connection = Connection(context, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002301 assert connection.get_context() is context
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002302
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002303 def test_set_context_wrong_args(self):
2304 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002305 `Connection.set_context` raises `TypeError` if called with a
Alex Chanfb078d82017-04-20 11:16:15 +01002306 non-`Context` instance argument.
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002307 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002308 ctx = Context(SSLv23_METHOD)
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002309 connection = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002310 with pytest.raises(TypeError):
2311 connection.set_context(object())
2312 with pytest.raises(TypeError):
2313 connection.set_context("hello")
2314 with pytest.raises(TypeError):
2315 connection.set_context(1)
2316 assert ctx is connection.get_context()
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002317
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002318 def test_set_context(self):
2319 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002320 `Connection.set_context` specifies a new `Context` instance to be
2321 used for the connection.
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002322 """
2323 original = Context(SSLv23_METHOD)
Paul Kehrer688538c2020-08-03 19:18:15 -05002324 replacement = Context(SSLv23_METHOD)
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002325 connection = Connection(original, None)
2326 connection.set_context(replacement)
Alex Chan1c0cb662017-01-30 07:13:30 +00002327 assert replacement is connection.get_context()
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002328 # Lose our references to the contexts, just in case the Connection
2329 # isn't properly managing its own contributions to their reference
2330 # counts.
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002331 del original, replacement
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002332 collect()
2333
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002334 def test_set_tlsext_host_name_wrong_args(self):
2335 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002336 If `Connection.set_tlsext_host_name` is called with a non-byte string
2337 argument or a byte string with an embedded NUL, `TypeError` is raised.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002338 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002339 conn = Connection(Context(SSLv23_METHOD), None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002340 with pytest.raises(TypeError):
2341 conn.set_tlsext_host_name(object())
2342 with pytest.raises(TypeError):
2343 conn.set_tlsext_host_name(b"with\0null")
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002344
Hugo van Kemenade60827f82019-08-30 00:39:35 +03002345 if not PY2:
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002346 # On Python 3.x, don't accidentally implicitly convert from text.
Alex Chan1c0cb662017-01-30 07:13:30 +00002347 with pytest.raises(TypeError):
2348 conn.set_tlsext_host_name(b"example.com".decode("ascii"))
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04002349
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002350 def test_pending(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002351 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002352 `Connection.pending` returns the number of bytes available for
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002353 immediate read.
2354 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002355 connection = Connection(Context(SSLv23_METHOD), None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002356 assert connection.pending() == 0
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002357
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002358 def test_peek(self):
2359 """
Hynek Schlawack3bcf3152017-02-18 08:25:34 +01002360 `Connection.recv` peeks into the connection if `socket.MSG_PEEK` is
2361 passed.
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002362 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002363 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04002364 server.send(b"xy")
2365 assert client.recv(2, MSG_PEEK) == b"xy"
2366 assert client.recv(2, MSG_PEEK) == b"xy"
2367 assert client.recv(2) == b"xy"
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002368
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002369 def test_connect_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002370 """
Hynek Schlawack3bcf3152017-02-18 08:25:34 +01002371 `Connection.connect` raises `TypeError` if called with a non-address
2372 argument.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002373 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002374 connection = Connection(Context(SSLv23_METHOD), socket_any_family())
Alex Chan1c0cb662017-01-30 07:13:30 +00002375 with pytest.raises(TypeError):
2376 connection.connect(None)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002377
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002378 def test_connect_refused(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002379 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002380 `Connection.connect` raises `socket.error` if the underlying socket
2381 connect method raises it.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002382 """
David Benjamin1fbe0642019-04-15 17:05:13 -05002383 client = socket_any_family()
Paul Kehrer688538c2020-08-03 19:18:15 -05002384 context = Context(SSLv23_METHOD)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002385 clientSSL = Connection(context, client)
Alex Gaynor122717b2015-09-05 14:14:18 -04002386 # pytest.raises here doesn't work because of a bug in py.test on Python
2387 # 2.6: https://github.com/pytest-dev/pytest/issues/988
Alex Gaynore69c2782015-09-05 14:07:48 -04002388 try:
David Benjamin1fbe0642019-04-15 17:05:13 -05002389 clientSSL.connect((loopback_address(client), 1))
Alex Gaynore69c2782015-09-05 14:07:48 -04002390 except error as e:
Alex Gaynor20a4c082015-09-05 14:24:15 -04002391 exc = e
2392 assert exc.args[0] == ECONNREFUSED
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002393
2394 def test_connect(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002395 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002396 `Connection.connect` establishes a connection to the specified address.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002397 """
David Benjamin1fbe0642019-04-15 17:05:13 -05002398 port = socket_any_family()
Alex Gaynor03737182020-07-23 20:40:46 -04002399 port.bind(("", 0))
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002400 port.listen(3)
2401
Paul Kehrer688538c2020-08-03 19:18:15 -05002402 clientSSL = Connection(Context(SSLv23_METHOD), socket(port.family))
David Benjamin1fbe0642019-04-15 17:05:13 -05002403 clientSSL.connect((loopback_address(port), port.getsockname()[1]))
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002404 # XXX An assertion? Or something?
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002405
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002406 @pytest.mark.skipif(
2407 platform == "darwin",
Alex Gaynor03737182020-07-23 20:40:46 -04002408 reason="connect_ex sometimes causes a kernel panic on OS X 10.6.4",
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002409 )
2410 def test_connect_ex(self):
2411 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002412 If there is a connection error, `Connection.connect_ex` returns the
2413 errno instead of raising an exception.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002414 """
David Benjamin1fbe0642019-04-15 17:05:13 -05002415 port = socket_any_family()
Alex Gaynor03737182020-07-23 20:40:46 -04002416 port.bind(("", 0))
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002417 port.listen(3)
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002418
Paul Kehrer688538c2020-08-03 19:18:15 -05002419 clientSSL = Connection(Context(SSLv23_METHOD), socket(port.family))
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002420 clientSSL.setblocking(False)
2421 result = clientSSL.connect_ex(port.getsockname())
2422 expected = (EINPROGRESS, EWOULDBLOCK)
Alex Chan1c0cb662017-01-30 07:13:30 +00002423 assert result in expected
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002424
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002425 def test_accept(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002426 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002427 `Connection.accept` accepts a pending connection attempt and returns a
2428 tuple of a new `Connection` (the accepted client) and the address the
2429 connection originated from.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002430 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002431 ctx = Context(SSLv23_METHOD)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002432 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2433 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
David Benjamin1fbe0642019-04-15 17:05:13 -05002434 port = socket_any_family()
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002435 portSSL = Connection(ctx, port)
Alex Gaynor03737182020-07-23 20:40:46 -04002436 portSSL.bind(("", 0))
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002437 portSSL.listen(3)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002438
Paul Kehrer688538c2020-08-03 19:18:15 -05002439 clientSSL = Connection(Context(SSLv23_METHOD), socket(port.family))
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002440
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002441 # Calling portSSL.getsockname() here to get the server IP address
2442 # sounds great, but frequently fails on Windows.
David Benjamin1fbe0642019-04-15 17:05:13 -05002443 clientSSL.connect((loopback_address(port), portSSL.getsockname()[1]))
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002444
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002445 serverSSL, address = portSSL.accept()
2446
Alex Chan1c0cb662017-01-30 07:13:30 +00002447 assert isinstance(serverSSL, Connection)
2448 assert serverSSL.get_context() is ctx
2449 assert address == clientSSL.getsockname()
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002450
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002451 def test_shutdown_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002452 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002453 `Connection.set_shutdown` raises `TypeError` if called with arguments
2454 other than integers.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002455 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002456 connection = Connection(Context(SSLv23_METHOD), None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002457 with pytest.raises(TypeError):
2458 connection.set_shutdown(None)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002459
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002460 def test_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002461 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002462 `Connection.shutdown` performs an SSL-level connection shutdown.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002463 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002464 server, client = loopback()
2465 assert not server.shutdown()
2466 assert server.get_shutdown() == SENT_SHUTDOWN
2467 with pytest.raises(ZeroReturnError):
2468 client.recv(1024)
2469 assert client.get_shutdown() == RECEIVED_SHUTDOWN
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04002470 client.shutdown()
Alex Chan1c0cb662017-01-30 07:13:30 +00002471 assert client.get_shutdown() == (SENT_SHUTDOWN | RECEIVED_SHUTDOWN)
2472 with pytest.raises(ZeroReturnError):
2473 server.recv(1024)
2474 assert server.get_shutdown() == (SENT_SHUTDOWN | RECEIVED_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002475
Paul Aurichc85e0862015-01-08 08:34:33 -08002476 def test_shutdown_closed(self):
2477 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002478 If the underlying socket is closed, `Connection.shutdown` propagates
2479 the write error from the low level write call.
Paul Aurichc85e0862015-01-08 08:34:33 -08002480 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002481 server, client = loopback()
Paul Aurichc85e0862015-01-08 08:34:33 -08002482 server.sock_shutdown(2)
Alex Chan1c0cb662017-01-30 07:13:30 +00002483 with pytest.raises(SysCallError) as exc:
2484 server.shutdown()
Alex Chanfb078d82017-04-20 11:16:15 +01002485 if platform == "win32":
2486 assert exc.value.args[0] == ESHUTDOWN
2487 else:
2488 assert exc.value.args[0] == EPIPE
Paul Aurichc85e0862015-01-08 08:34:33 -08002489
Glyph89389472015-04-14 17:29:26 -04002490 def test_shutdown_truncated(self):
Glyph6064ec32015-04-14 16:38:22 -04002491 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002492 If the underlying connection is truncated, `Connection.shutdown`
2493 raises an `Error`.
Glyph6064ec32015-04-14 16:38:22 -04002494 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002495 server_ctx = Context(SSLv23_METHOD)
2496 client_ctx = Context(SSLv23_METHOD)
Glyph89389472015-04-14 17:29:26 -04002497 server_ctx.use_privatekey(
Alex Gaynor03737182020-07-23 20:40:46 -04002498 load_privatekey(FILETYPE_PEM, server_key_pem)
2499 )
Glyph89389472015-04-14 17:29:26 -04002500 server_ctx.use_certificate(
Alex Gaynor03737182020-07-23 20:40:46 -04002501 load_certificate(FILETYPE_PEM, server_cert_pem)
2502 )
Glyph89389472015-04-14 17:29:26 -04002503 server = Connection(server_ctx, None)
2504 client = Connection(client_ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002505 handshake_in_memory(client, server)
2506 assert not server.shutdown()
2507 with pytest.raises(WantReadError):
2508 server.shutdown()
Glyph89389472015-04-14 17:29:26 -04002509 server.bio_shutdown()
Alex Chan1c0cb662017-01-30 07:13:30 +00002510 with pytest.raises(Error):
2511 server.shutdown()
Glyph6064ec32015-04-14 16:38:22 -04002512
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002513 def test_set_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002514 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002515 `Connection.set_shutdown` sets the state of the SSL connection
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002516 shutdown process.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002517 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002518 connection = Connection(Context(SSLv23_METHOD), socket_any_family())
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002519 connection.set_shutdown(RECEIVED_SHUTDOWN)
Alex Chan1c0cb662017-01-30 07:13:30 +00002520 assert connection.get_shutdown() == RECEIVED_SHUTDOWN
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002521
kjavaf248592015-09-07 12:14:01 +01002522 def test_state_string(self):
2523 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002524 `Connection.state_string` verbosely describes the current state of
2525 the `Connection`.
kjavaf248592015-09-07 12:14:01 +01002526 """
Hynek Schlawackb0274ce2015-10-16 19:56:26 +02002527 server, client = socket_pair()
Alex Chan1c0cb662017-01-30 07:13:30 +00002528 server = loopback_server_factory(server)
2529 client = loopback_client_factory(client)
kjavaf248592015-09-07 12:14:01 +01002530
Alex Gaynor5af32d02016-09-24 01:52:21 -04002531 assert server.get_state_string() in [
Alex Gaynor03737182020-07-23 20:40:46 -04002532 b"before/accept initialization",
2533 b"before SSL initialization",
Alex Gaynor5af32d02016-09-24 01:52:21 -04002534 ]
2535 assert client.get_state_string() in [
Alex Gaynor03737182020-07-23 20:40:46 -04002536 b"before/connect initialization",
2537 b"before SSL initialization",
Alex Gaynor5af32d02016-09-24 01:52:21 -04002538 ]
kjavaf248592015-09-07 12:14:01 +01002539
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002540 def test_app_data(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002541 """
2542 Any object can be set as app data by passing it to
Alex Chan1c0cb662017-01-30 07:13:30 +00002543 `Connection.set_app_data` and later retrieved with
2544 `Connection.get_app_data`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002545 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002546 conn = Connection(Context(SSLv23_METHOD), None)
Todd Chapman4f73e4f2015-08-27 11:26:43 -04002547 assert None is conn.get_app_data()
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002548 app_data = object()
2549 conn.set_app_data(app_data)
Todd Chapman4f73e4f2015-08-27 11:26:43 -04002550 assert conn.get_app_data() is app_data
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002551
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002552 def test_makefile(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002553 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002554 `Connection.makefile` is not implemented and calling that
2555 method raises `NotImplementedError`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002556 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002557 conn = Connection(Context(SSLv23_METHOD), None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002558 with pytest.raises(NotImplementedError):
2559 conn.makefile()
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002560
Jeremy Lainé460a19d2018-05-16 19:44:19 +02002561 def test_get_certificate(self):
2562 """
2563 `Connection.get_certificate` returns the local certificate.
2564 """
2565 chain = _create_certificate_chain()
2566 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
2567
Paul Kehrer688538c2020-08-03 19:18:15 -05002568 context = Context(SSLv23_METHOD)
Jeremy Lainé460a19d2018-05-16 19:44:19 +02002569 context.use_certificate(scert)
2570 client = Connection(context, None)
2571 cert = client.get_certificate()
2572 assert cert is not None
2573 assert "Server Certificate" == cert.get_subject().CN
2574
2575 def test_get_certificate_none(self):
2576 """
2577 `Connection.get_certificate` returns the local certificate.
2578
2579 If there is no certificate, it returns None.
2580 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002581 context = Context(SSLv23_METHOD)
Jeremy Lainé460a19d2018-05-16 19:44:19 +02002582 client = Connection(context, None)
2583 cert = client.get_certificate()
2584 assert cert is None
2585
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002586 def test_get_peer_cert_chain(self):
2587 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002588 `Connection.get_peer_cert_chain` returns a list of certificates
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002589 which the connected server returned for the certification verification.
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002590 """
2591 chain = _create_certificate_chain()
2592 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
2593
Paul Kehrer688538c2020-08-03 19:18:15 -05002594 serverContext = Context(SSLv23_METHOD)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002595 serverContext.use_privatekey(skey)
2596 serverContext.use_certificate(scert)
2597 serverContext.add_extra_chain_cert(icert)
2598 serverContext.add_extra_chain_cert(cacert)
2599 server = Connection(serverContext, None)
2600 server.set_accept_state()
2601
2602 # Create the client
Paul Kehrer688538c2020-08-03 19:18:15 -05002603 clientContext = Context(SSLv23_METHOD)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002604 clientContext.set_verify(VERIFY_NONE, verify_cb)
2605 client = Connection(clientContext, None)
2606 client.set_connect_state()
2607
Alex Chan1c0cb662017-01-30 07:13:30 +00002608 interact_in_memory(client, server)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002609
2610 chain = client.get_peer_cert_chain()
Alex Chan1c0cb662017-01-30 07:13:30 +00002611 assert len(chain) == 3
2612 assert "Server Certificate" == chain[0].get_subject().CN
2613 assert "Intermediate Certificate" == chain[1].get_subject().CN
2614 assert "Authority Certificate" == chain[2].get_subject().CN
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002615
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002616 def test_get_peer_cert_chain_none(self):
2617 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002618 `Connection.get_peer_cert_chain` returns `None` if the peer sends
2619 no certificate chain.
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002620 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002621 ctx = Context(SSLv23_METHOD)
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002622 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2623 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
2624 server = Connection(ctx, None)
2625 server.set_accept_state()
Paul Kehrer688538c2020-08-03 19:18:15 -05002626 client = Connection(Context(SSLv23_METHOD), None)
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002627 client.set_connect_state()
Alex Chan1c0cb662017-01-30 07:13:30 +00002628 interact_in_memory(client, server)
2629 assert None is server.get_peer_cert_chain()
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002630
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002631 def test_get_session_unconnected(self):
2632 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002633 `Connection.get_session` returns `None` when used with an object
2634 which has not been connected.
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002635 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002636 ctx = Context(SSLv23_METHOD)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002637 server = Connection(ctx, None)
2638 session = server.get_session()
Alex Chan1c0cb662017-01-30 07:13:30 +00002639 assert None is session
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002640
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002641 def test_server_get_session(self):
2642 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002643 On the server side of a connection, `Connection.get_session` returns a
2644 `Session` instance representing the SSL session for that connection.
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002645 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002646 server, client = loopback()
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002647 session = server.get_session()
Alex Chan1c0cb662017-01-30 07:13:30 +00002648 assert isinstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002649
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002650 def test_client_get_session(self):
2651 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002652 On the client side of a connection, `Connection.get_session`
2653 returns a `Session` instance representing the SSL session for
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002654 that connection.
2655 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002656 server, client = loopback()
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002657 session = client.get_session()
Alex Chan1c0cb662017-01-30 07:13:30 +00002658 assert isinstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002659
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002660 def test_set_session_wrong_args(self):
2661 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002662 `Connection.set_session` raises `TypeError` if called with an object
2663 that is not an instance of `Session`.
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002664 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002665 ctx = Context(SSLv23_METHOD)
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002666 connection = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002667 with pytest.raises(TypeError):
2668 connection.set_session(123)
2669 with pytest.raises(TypeError):
2670 connection.set_session("hello")
2671 with pytest.raises(TypeError):
2672 connection.set_session(object())
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002673
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002674 def test_client_set_session(self):
2675 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002676 `Connection.set_session`, when used prior to a connection being
2677 established, accepts a `Session` instance and causes an attempt to
2678 re-use the session it represents when the SSL handshake is performed.
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002679 """
2680 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2681 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
Paul Kehrer7d5a3bf2019-01-21 12:24:02 -06002682 ctx = Context(TLSv1_2_METHOD)
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002683 ctx.use_privatekey(key)
2684 ctx.use_certificate(cert)
2685 ctx.set_session_id("unity-test")
2686
2687 def makeServer(socket):
2688 server = Connection(ctx, socket)
2689 server.set_accept_state()
2690 return server
2691
Alex Gaynor03737182020-07-23 20:40:46 -04002692 originalServer, originalClient = loopback(server_factory=makeServer)
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002693 originalSession = originalClient.get_session()
2694
2695 def makeClient(socket):
Alex Chan1c0cb662017-01-30 07:13:30 +00002696 client = loopback_client_factory(socket)
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002697 client.set_session(originalSession)
2698 return client
Alex Gaynor03737182020-07-23 20:40:46 -04002699
Alex Chan1c0cb662017-01-30 07:13:30 +00002700 resumedServer, resumedClient = loopback(
Alex Gaynor03737182020-07-23 20:40:46 -04002701 server_factory=makeServer, client_factory=makeClient
2702 )
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002703
2704 # This is a proxy: in general, we have no access to any unique
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002705 # identifier for the session (new enough versions of OpenSSL expose
2706 # a hash which could be usable, but "new enough" is very, very new).
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002707 # Instead, exploit the fact that the master key is re-used if the
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002708 # session is re-used. As long as the master key for the two
2709 # connections is the same, the session was re-used!
Alex Chan1c0cb662017-01-30 07:13:30 +00002710 assert originalServer.master_key() == resumedServer.master_key()
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002711
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002712 def test_set_session_wrong_method(self):
2713 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002714 If `Connection.set_session` is passed a `Session` instance associated
2715 with a context using a different SSL method than the `Connection`
2716 is using, a `OpenSSL.SSL.Error` is raised.
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002717 """
Alex Gaynor5af32d02016-09-24 01:52:21 -04002718 # Make this work on both OpenSSL 1.0.0, which doesn't support TLSv1.2
2719 # and also on OpenSSL 1.1.0 which doesn't support SSLv3. (SSL_ST_INIT
2720 # is a way to check for 1.1.0)
Alex Gaynoraa32e712017-06-29 20:56:12 -07002721 if SSL_ST_INIT is None:
2722 v1 = TLSv1_2_METHOD
2723 v2 = TLSv1_METHOD
2724 elif hasattr(_lib, "SSLv3_method"):
Alex Gaynor5af32d02016-09-24 01:52:21 -04002725 v1 = TLSv1_METHOD
2726 v2 = SSLv3_METHOD
2727 else:
Alex Gaynoraa32e712017-06-29 20:56:12 -07002728 pytest.skip("Test requires either OpenSSL 1.1.0 or SSLv3")
Alex Gaynor5af32d02016-09-24 01:52:21 -04002729
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002730 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2731 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
Alex Gaynor5af32d02016-09-24 01:52:21 -04002732 ctx = Context(v1)
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002733 ctx.use_privatekey(key)
2734 ctx.use_certificate(cert)
Paul Kehrerc45a6ea2020-08-03 15:54:20 -05002735 ctx.set_session_id(b"unity-test")
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002736
2737 def makeServer(socket):
2738 server = Connection(ctx, socket)
2739 server.set_accept_state()
2740 return server
2741
Alex Gaynor5af32d02016-09-24 01:52:21 -04002742 def makeOriginalClient(socket):
2743 client = Connection(Context(v1), socket)
2744 client.set_connect_state()
2745 return client
2746
Alex Chan1c0cb662017-01-30 07:13:30 +00002747 originalServer, originalClient = loopback(
Alex Gaynor03737182020-07-23 20:40:46 -04002748 server_factory=makeServer, client_factory=makeOriginalClient
2749 )
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002750 originalSession = originalClient.get_session()
2751
2752 def makeClient(socket):
2753 # Intentionally use a different, incompatible method here.
Alex Gaynor5af32d02016-09-24 01:52:21 -04002754 client = Connection(Context(v2), socket)
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002755 client.set_connect_state()
2756 client.set_session(originalSession)
2757 return client
2758
Alex Chan1c0cb662017-01-30 07:13:30 +00002759 with pytest.raises(Error):
2760 loopback(client_factory=makeClient, server_factory=makeServer)
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002761
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002762 def test_wantWriteError(self):
2763 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002764 `Connection` methods which generate output raise
2765 `OpenSSL.SSL.WantWriteError` if writing to the connection's BIO
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002766 fail indicating a should-write state.
2767 """
2768 client_socket, server_socket = socket_pair()
2769 # Fill up the client's send buffer so Connection won't be able to write
Jean-Paul Calderonebbff8b92014-03-22 14:20:30 -04002770 # anything. Only write a single byte at a time so we can be sure we
2771 # completely fill the buffer. Even though the socket API is allowed to
2772 # signal a short write via its return value it seems this doesn't
2773 # always happen on all platforms (FreeBSD and OS X particular) for the
2774 # very last bit of available buffer space.
2775 msg = b"x"
caternb2777a42018-08-09 15:38:13 -04002776 for i in range(1024 * 1024 * 64):
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002777 try:
2778 client_socket.send(msg)
2779 except error as e:
2780 if e.errno == EWOULDBLOCK:
2781 break
2782 raise
2783 else:
Alex Chan1c0cb662017-01-30 07:13:30 +00002784 pytest.fail(
Alex Gaynor03737182020-07-23 20:40:46 -04002785 "Failed to fill socket buffer, cannot test BIO want write"
2786 )
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002787
Paul Kehrer688538c2020-08-03 19:18:15 -05002788 ctx = Context(SSLv23_METHOD)
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002789 conn = Connection(ctx, client_socket)
2790 # Client's speak first, so make it an SSL client
2791 conn.set_connect_state()
Alex Chan1c0cb662017-01-30 07:13:30 +00002792 with pytest.raises(WantWriteError):
2793 conn.do_handshake()
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002794
2795 # XXX want_read
2796
Fedor Brunner416f4a12014-03-28 13:18:38 +01002797 def test_get_finished_before_connect(self):
Fedor Brunner5747b932014-03-05 14:22:34 +01002798 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002799 `Connection.get_finished` returns `None` before TLS handshake
2800 is completed.
Fedor Brunner5747b932014-03-05 14:22:34 +01002801 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002802 ctx = Context(SSLv23_METHOD)
Fedor Brunner5747b932014-03-05 14:22:34 +01002803 connection = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002804 assert connection.get_finished() is None
Fedor Brunner416f4a12014-03-28 13:18:38 +01002805
2806 def test_get_peer_finished_before_connect(self):
2807 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002808 `Connection.get_peer_finished` returns `None` before TLS handshake
2809 is completed.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002810 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002811 ctx = Context(SSLv23_METHOD)
Fedor Brunner416f4a12014-03-28 13:18:38 +01002812 connection = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002813 assert connection.get_peer_finished() is None
Fedor Brunner5747b932014-03-05 14:22:34 +01002814
Fedor Brunner416f4a12014-03-28 13:18:38 +01002815 def test_get_finished(self):
2816 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002817 `Connection.get_finished` method returns the TLS Finished message send
2818 from client, or server. Finished messages are send during
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002819 TLS handshake.
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() is not None
2824 assert len(server.get_finished()) > 0
Fedor Brunner416f4a12014-03-28 13:18:38 +01002825
2826 def test_get_peer_finished(self):
2827 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002828 `Connection.get_peer_finished` method returns the TLS Finished
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002829 message received from client, or server. Finished messages are send
2830 during TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002831 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002832 server, client = loopback()
Fedor Brunner416f4a12014-03-28 13:18:38 +01002833
Alex Chan1c0cb662017-01-30 07:13:30 +00002834 assert server.get_peer_finished() is not None
2835 assert len(server.get_peer_finished()) > 0
Fedor Brunner5747b932014-03-05 14:22:34 +01002836
Fedor Brunner416f4a12014-03-28 13:18:38 +01002837 def test_tls_finished_message_symmetry(self):
2838 """
Hynek Schlawackdddd1112015-09-05 21:12:30 +02002839 The TLS Finished message send by server must be the TLS Finished
2840 message received by client.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002841
Hynek Schlawackdddd1112015-09-05 21:12:30 +02002842 The TLS Finished message send by client must be the TLS Finished
2843 message received by server.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002844 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002845 server, client = loopback()
Fedor Brunner416f4a12014-03-28 13:18:38 +01002846
Alex Chan1c0cb662017-01-30 07:13:30 +00002847 assert server.get_finished() == client.get_peer_finished()
2848 assert client.get_finished() == server.get_peer_finished()
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002849
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002850 def test_get_cipher_name_before_connect(self):
2851 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002852 `Connection.get_cipher_name` returns `None` if no connection
2853 has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002854 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002855 ctx = Context(SSLv23_METHOD)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002856 conn = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002857 assert conn.get_cipher_name() is None
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002858
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002859 def test_get_cipher_name(self):
2860 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002861 `Connection.get_cipher_name` returns a `unicode` string giving the
2862 name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002863 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002864 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04002865 server_cipher_name, client_cipher_name = (
2866 server.get_cipher_name(),
2867 client.get_cipher_name(),
2868 )
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002869
Alex Chan1c0cb662017-01-30 07:13:30 +00002870 assert isinstance(server_cipher_name, text_type)
2871 assert isinstance(client_cipher_name, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002872
Alex Chan1c0cb662017-01-30 07:13:30 +00002873 assert server_cipher_name == client_cipher_name
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002874
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002875 def test_get_cipher_version_before_connect(self):
2876 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002877 `Connection.get_cipher_version` returns `None` if no connection
2878 has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002879 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002880 ctx = Context(SSLv23_METHOD)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002881 conn = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002882 assert conn.get_cipher_version() is None
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002883
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002884 def test_get_cipher_version(self):
2885 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002886 `Connection.get_cipher_version` returns a `unicode` string giving
2887 the protocol name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002888 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002889 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04002890 server_cipher_version, client_cipher_version = (
2891 server.get_cipher_version(),
2892 client.get_cipher_version(),
2893 )
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002894
Alex Chan1c0cb662017-01-30 07:13:30 +00002895 assert isinstance(server_cipher_version, text_type)
2896 assert isinstance(client_cipher_version, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002897
Alex Chan1c0cb662017-01-30 07:13:30 +00002898 assert server_cipher_version == client_cipher_version
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002899
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002900 def test_get_cipher_bits_before_connect(self):
2901 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002902 `Connection.get_cipher_bits` returns `None` if no connection has
2903 been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002904 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002905 ctx = Context(SSLv23_METHOD)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002906 conn = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002907 assert conn.get_cipher_bits() is None
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002908
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002909 def test_get_cipher_bits(self):
2910 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002911 `Connection.get_cipher_bits` returns the number of secret bits
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002912 of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002913 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002914 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04002915 server_cipher_bits, client_cipher_bits = (
2916 server.get_cipher_bits(),
2917 client.get_cipher_bits(),
2918 )
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002919
Alex Chan1c0cb662017-01-30 07:13:30 +00002920 assert isinstance(server_cipher_bits, int)
2921 assert isinstance(client_cipher_bits, int)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002922
Alex Chan1c0cb662017-01-30 07:13:30 +00002923 assert server_cipher_bits == client_cipher_bits
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002924
Jim Shaverabff1882015-05-27 09:15:55 -04002925 def test_get_protocol_version_name(self):
2926 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002927 `Connection.get_protocol_version_name()` returns a string giving the
2928 protocol version of the current connection.
Jim Shaverabff1882015-05-27 09:15:55 -04002929 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002930 server, client = loopback()
Jim Shaverabff1882015-05-27 09:15:55 -04002931 client_protocol_version_name = client.get_protocol_version_name()
2932 server_protocol_version_name = server.get_protocol_version_name()
2933
Alex Chan1c0cb662017-01-30 07:13:30 +00002934 assert isinstance(server_protocol_version_name, text_type)
2935 assert isinstance(client_protocol_version_name, text_type)
Jim Shaverabff1882015-05-27 09:15:55 -04002936
Alex Chan1c0cb662017-01-30 07:13:30 +00002937 assert server_protocol_version_name == client_protocol_version_name
Jim Shaverabff1882015-05-27 09:15:55 -04002938
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002939 def test_get_protocol_version(self):
2940 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002941 `Connection.get_protocol_version()` returns an integer
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002942 giving the protocol version of the current connection.
2943 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002944 server, client = loopback()
Jim Shaver85a4dff2015-04-27 17:42:46 -04002945 client_protocol_version = client.get_protocol_version()
2946 server_protocol_version = server.get_protocol_version()
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002947
Alex Chan1c0cb662017-01-30 07:13:30 +00002948 assert isinstance(server_protocol_version, int)
2949 assert isinstance(client_protocol_version, int)
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002950
Alex Chan1c0cb662017-01-30 07:13:30 +00002951 assert server_protocol_version == client_protocol_version
2952
2953 def test_wantReadError(self):
2954 """
2955 `Connection.bio_read` raises `OpenSSL.SSL.WantReadError` if there are
2956 no bytes available to be read from the BIO.
2957 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002958 ctx = Context(SSLv23_METHOD)
Alex Chan1c0cb662017-01-30 07:13:30 +00002959 conn = Connection(ctx, None)
2960 with pytest.raises(WantReadError):
2961 conn.bio_read(1024)
2962
Alex Gaynor03737182020-07-23 20:40:46 -04002963 @pytest.mark.parametrize("bufsize", [1.0, None, object(), "bufsize"])
Alex Chanfb078d82017-04-20 11:16:15 +01002964 def test_bio_read_wrong_args(self, bufsize):
2965 """
2966 `Connection.bio_read` raises `TypeError` if passed a non-integer
2967 argument.
2968 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002969 ctx = Context(SSLv23_METHOD)
Alex Chanfb078d82017-04-20 11:16:15 +01002970 conn = Connection(ctx, None)
2971 with pytest.raises(TypeError):
2972 conn.bio_read(bufsize)
2973
Alex Chan1c0cb662017-01-30 07:13:30 +00002974 def test_buffer_size(self):
2975 """
2976 `Connection.bio_read` accepts an integer giving the maximum number
2977 of bytes to read and return.
2978 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002979 ctx = Context(SSLv23_METHOD)
Alex Chan1c0cb662017-01-30 07:13:30 +00002980 conn = Connection(ctx, None)
2981 conn.set_connect_state()
2982 try:
2983 conn.do_handshake()
2984 except WantReadError:
2985 pass
2986 data = conn.bio_read(2)
2987 assert 2 == len(data)
2988
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002989
Alex Chanb7480992017-01-30 14:04:47 +00002990class TestConnectionGetCipherList(object):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002991 """
Alex Chanb7480992017-01-30 14:04:47 +00002992 Tests for `Connection.get_cipher_list`.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002993 """
Alex Gaynor03737182020-07-23 20:40:46 -04002994
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002995 def test_result(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002996 """
Alex Chanb7480992017-01-30 14:04:47 +00002997 `Connection.get_cipher_list` returns a list of `bytes` giving the
2998 names of the ciphers which might be used.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002999 """
Paul Kehrer688538c2020-08-03 19:18:15 -05003000 connection = Connection(Context(SSLv23_METHOD), None)
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04003001 ciphers = connection.get_cipher_list()
Alex Chanb7480992017-01-30 14:04:47 +00003002 assert isinstance(ciphers, list)
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04003003 for cipher in ciphers:
Alex Chanb7480992017-01-30 14:04:47 +00003004 assert isinstance(cipher, str)
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04003005
3006
Maximilian Hils868dc3c2017-02-10 14:56:55 +01003007class VeryLarge(bytes):
3008 """
3009 Mock object so that we don't have to allocate 2**31 bytes
3010 """
Alex Gaynor03737182020-07-23 20:40:46 -04003011
Maximilian Hils868dc3c2017-02-10 14:56:55 +01003012 def __len__(self):
Alex Gaynor03737182020-07-23 20:40:46 -04003013 return 2 ** 31
Maximilian Hils868dc3c2017-02-10 14:56:55 +01003014
3015
Alex Chanb7480992017-01-30 14:04:47 +00003016class TestConnectionSend(object):
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05003017 """
Alex Chanb7480992017-01-30 14:04:47 +00003018 Tests for `Connection.send`.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05003019 """
Alex Gaynor03737182020-07-23 20:40:46 -04003020
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05003021 def test_wrong_args(self):
3022 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003023 When called with arguments other than string argument for its first
Alex Chanb7480992017-01-30 14:04:47 +00003024 parameter, `Connection.send` raises `TypeError`.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05003025 """
Paul Kehrer688538c2020-08-03 19:18:15 -05003026 connection = Connection(Context(SSLv23_METHOD), None)
Alex Chanb7480992017-01-30 14:04:47 +00003027 with pytest.raises(TypeError):
3028 connection.send(object())
Daniel Holth079c9632019-11-17 22:45:52 -05003029 with pytest.raises(TypeError):
3030 connection.send([1, 2, 3])
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05003031
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05003032 def test_short_bytes(self):
3033 """
Alex Chanb7480992017-01-30 14:04:47 +00003034 When passed a short byte string, `Connection.send` transmits all of it
3035 and returns the number of bytes sent.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05003036 """
Alex Chanb7480992017-01-30 14:04:47 +00003037 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04003038 count = server.send(b"xy")
Alex Chanb7480992017-01-30 14:04:47 +00003039 assert count == 2
Alex Gaynor03737182020-07-23 20:40:46 -04003040 assert client.recv(2) == b"xy"
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05003041
Abraham Martinef063482015-03-25 14:06:24 +00003042 def test_text(self):
3043 """
Alex Chanb7480992017-01-30 14:04:47 +00003044 When passed a text, `Connection.send` transmits all of it and
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04003045 returns the number of bytes sent. It also raises a DeprecationWarning.
Abraham Martinef063482015-03-25 14:06:24 +00003046 """
Alex Chanb7480992017-01-30 14:04:47 +00003047 server, client = loopback()
3048 with pytest.warns(DeprecationWarning) as w:
Abraham Martinef063482015-03-25 14:06:24 +00003049 simplefilter("always")
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04003050 count = server.send(b"xy".decode("ascii"))
Alex Gaynor03737182020-07-23 20:40:46 -04003051 assert "{0} for buf is no longer accepted, use bytes".format(
3052 WARNING_TYPE_EXPECTED
3053 ) == str(w[-1].message)
Alex Chanb7480992017-01-30 14:04:47 +00003054 assert count == 2
Alex Gaynor03737182020-07-23 20:40:46 -04003055 assert client.recv(2) == b"xy"
Abraham Martinef063482015-03-25 14:06:24 +00003056
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003057 def test_short_memoryview(self):
3058 """
3059 When passed a memoryview onto a small number of bytes,
Alex Chanb7480992017-01-30 14:04:47 +00003060 `Connection.send` transmits all of them and returns the number
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003061 of bytes sent.
3062 """
Alex Chanb7480992017-01-30 14:04:47 +00003063 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04003064 count = server.send(memoryview(b"xy"))
Alex Chanb7480992017-01-30 14:04:47 +00003065 assert count == 2
Alex Gaynor03737182020-07-23 20:40:46 -04003066 assert client.recv(2) == b"xy"
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05003067
Daniel Holth079c9632019-11-17 22:45:52 -05003068 def test_short_bytearray(self):
3069 """
3070 When passed a short bytearray, `Connection.send` transmits all of
3071 it and returns the number of bytes sent.
3072 """
3073 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04003074 count = server.send(bytearray(b"xy"))
Daniel Holth079c9632019-11-17 22:45:52 -05003075 assert count == 2
Alex Gaynor03737182020-07-23 20:40:46 -04003076 assert client.recv(2) == b"xy"
Daniel Holth079c9632019-11-17 22:45:52 -05003077
Hynek Schlawack8e94f1b2015-09-05 21:31:00 +02003078 @skip_if_py3
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003079 def test_short_buffer(self):
3080 """
3081 When passed a buffer containing a small number of bytes,
Alex Chanb7480992017-01-30 14:04:47 +00003082 `Connection.send` transmits all of them and returns the number
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003083 of bytes sent.
3084 """
Alex Chanb7480992017-01-30 14:04:47 +00003085 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04003086 count = server.send(buffer(b"xy")) # noqa: F821
Alex Chanb7480992017-01-30 14:04:47 +00003087 assert count == 2
Alex Gaynor03737182020-07-23 20:40:46 -04003088 assert client.recv(2) == b"xy"
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02003089
Maximilian Hils868dc3c2017-02-10 14:56:55 +01003090 @pytest.mark.skipif(
Alex Gaynor03737182020-07-23 20:40:46 -04003091 sys.maxsize < 2 ** 31,
3092 reason="sys.maxsize < 2**31 - test requires 64 bit",
Maximilian Hils868dc3c2017-02-10 14:56:55 +01003093 )
3094 def test_buf_too_large(self):
3095 """
3096 When passed a buffer containing >= 2**31 bytes,
3097 `Connection.send` bails out as SSL_write only
3098 accepts an int for the buffer length.
3099 """
Paul Kehrer688538c2020-08-03 19:18:15 -05003100 connection = Connection(Context(SSLv23_METHOD), None)
Maximilian Hils868dc3c2017-02-10 14:56:55 +01003101 with pytest.raises(ValueError) as exc_info:
3102 connection.send(VeryLarge())
3103 exc_info.match(r"Cannot send more than .+ bytes at once")
3104
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05003105
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003106def _make_memoryview(size):
3107 """
3108 Create a new ``memoryview`` wrapped around a ``bytearray`` of the given
3109 size.
3110 """
3111 return memoryview(bytearray(size))
3112
3113
Alex Chanb7480992017-01-30 14:04:47 +00003114class TestConnectionRecvInto(object):
Cory Benfield62d10332014-06-15 10:03:41 +01003115 """
Alex Chanb7480992017-01-30 14:04:47 +00003116 Tests for `Connection.recv_into`.
Cory Benfield62d10332014-06-15 10:03:41 +01003117 """
Alex Gaynor03737182020-07-23 20:40:46 -04003118
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003119 def _no_length_test(self, factory):
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04003120 """
Alex Chanb7480992017-01-30 14:04:47 +00003121 Assert that when the given buffer is passed to `Connection.recv_into`,
3122 whatever bytes are available to be received that fit into that buffer
3123 are written into that buffer.
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04003124 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003125 output_buffer = factory(5)
3126
Alex Chanb7480992017-01-30 14:04:47 +00003127 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04003128 server.send(b"xy")
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04003129
Alex Chanb7480992017-01-30 14:04:47 +00003130 assert client.recv_into(output_buffer) == 2
Alex Gaynor03737182020-07-23 20:40:46 -04003131 assert output_buffer == bytearray(b"xy\x00\x00\x00")
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04003132
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04003133 def test_bytearray_no_length(self):
Cory Benfield62d10332014-06-15 10:03:41 +01003134 """
Alex Chanb7480992017-01-30 14:04:47 +00003135 `Connection.recv_into` can be passed a `bytearray` instance and data
3136 in the receive buffer is written to it.
Cory Benfield62d10332014-06-15 10:03:41 +01003137 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003138 self._no_length_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01003139
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003140 def _respects_length_test(self, factory):
Cory Benfield62d10332014-06-15 10:03:41 +01003141 """
Alex Chanb7480992017-01-30 14:04:47 +00003142 Assert that when the given buffer is passed to `Connection.recv_into`
3143 along with a value for `nbytes` that is less than the size of that
3144 buffer, only `nbytes` bytes are written into the buffer.
Cory Benfield62d10332014-06-15 10:03:41 +01003145 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003146 output_buffer = factory(10)
3147
Alex Chanb7480992017-01-30 14:04:47 +00003148 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04003149 server.send(b"abcdefghij")
Cory Benfield62d10332014-06-15 10:03:41 +01003150
Alex Chanb7480992017-01-30 14:04:47 +00003151 assert client.recv_into(output_buffer, 5) == 5
Alex Gaynor03737182020-07-23 20:40:46 -04003152 assert output_buffer == bytearray(b"abcde\x00\x00\x00\x00\x00")
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04003153
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04003154 def test_bytearray_respects_length(self):
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04003155 """
Alex Chanb7480992017-01-30 14:04:47 +00003156 When called with a `bytearray` instance, `Connection.recv_into`
3157 respects the `nbytes` parameter and doesn't copy in more than that
3158 number of bytes.
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04003159 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003160 self._respects_length_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01003161
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003162 def _doesnt_overfill_test(self, factory):
Cory Benfield62d10332014-06-15 10:03:41 +01003163 """
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04003164 Assert that if there are more bytes available to be read from the
3165 receive buffer than would fit into the buffer passed to
Alex Chanb7480992017-01-30 14:04:47 +00003166 `Connection.recv_into`, only as many as fit are written into it.
Cory Benfield62d10332014-06-15 10:03:41 +01003167 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003168 output_buffer = factory(5)
3169
Alex Chanb7480992017-01-30 14:04:47 +00003170 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04003171 server.send(b"abcdefghij")
Cory Benfield62d10332014-06-15 10:03:41 +01003172
Alex Chanb7480992017-01-30 14:04:47 +00003173 assert client.recv_into(output_buffer) == 5
Alex Gaynor03737182020-07-23 20:40:46 -04003174 assert output_buffer == bytearray(b"abcde")
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04003175 rest = client.recv(5)
Alex Gaynor03737182020-07-23 20:40:46 -04003176 assert b"fghij" == rest
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04003177
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04003178 def test_bytearray_doesnt_overfill(self):
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04003179 """
Alex Chanb7480992017-01-30 14:04:47 +00003180 When called with a `bytearray` instance, `Connection.recv_into`
3181 respects the size of the array and doesn't write more bytes into it
3182 than will fit.
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04003183 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003184 self._doesnt_overfill_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01003185
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04003186 def test_bytearray_really_doesnt_overfill(self):
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003187 """
Alex Chanb7480992017-01-30 14:04:47 +00003188 When called with a `bytearray` instance and an `nbytes` value that is
3189 too large, `Connection.recv_into` respects the size of the array and
3190 not the `nbytes` value and doesn't write more bytes into the buffer
3191 than will fit.
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003192 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003193 self._doesnt_overfill_test(bytearray)
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003194
Maximilian Hils1d95dea2015-08-17 19:27:20 +02003195 def test_peek(self):
Alex Chanb7480992017-01-30 14:04:47 +00003196 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04003197 server.send(b"xy")
Maximilian Hils1d95dea2015-08-17 19:27:20 +02003198
3199 for _ in range(2):
3200 output_buffer = bytearray(5)
Alex Chanb7480992017-01-30 14:04:47 +00003201 assert client.recv_into(output_buffer, flags=MSG_PEEK) == 2
Alex Gaynor03737182020-07-23 20:40:46 -04003202 assert output_buffer == bytearray(b"xy\x00\x00\x00")
Maximilian Hils1d95dea2015-08-17 19:27:20 +02003203
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003204 def test_memoryview_no_length(self):
3205 """
Alex Chanb7480992017-01-30 14:04:47 +00003206 `Connection.recv_into` can be passed a `memoryview` instance and data
3207 in the receive buffer is written to it.
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003208 """
3209 self._no_length_test(_make_memoryview)
Maximilian Hils1d95dea2015-08-17 19:27:20 +02003210
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003211 def test_memoryview_respects_length(self):
3212 """
Alex Chanb7480992017-01-30 14:04:47 +00003213 When called with a `memoryview` instance, `Connection.recv_into`
3214 respects the ``nbytes`` parameter and doesn't copy more than that
3215 number of bytes in.
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003216 """
3217 self._respects_length_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01003218
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003219 def test_memoryview_doesnt_overfill(self):
3220 """
Alex Chanb7480992017-01-30 14:04:47 +00003221 When called with a `memoryview` instance, `Connection.recv_into`
3222 respects the size of the array and doesn't write more bytes into it
3223 than will fit.
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003224 """
3225 self._doesnt_overfill_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01003226
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003227 def test_memoryview_really_doesnt_overfill(self):
3228 """
Alex Chanb7480992017-01-30 14:04:47 +00003229 When called with a `memoryview` instance and an `nbytes` value that is
3230 too large, `Connection.recv_into` respects the size of the array and
3231 not the `nbytes` value and doesn't write more bytes into the buffer
3232 than will fit.
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003233 """
3234 self._doesnt_overfill_test(_make_memoryview)
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003235
Cory Benfield62d10332014-06-15 10:03:41 +01003236
Alex Chanb7480992017-01-30 14:04:47 +00003237class TestConnectionSendall(object):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003238 """
Alex Chanb7480992017-01-30 14:04:47 +00003239 Tests for `Connection.sendall`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003240 """
Alex Gaynor03737182020-07-23 20:40:46 -04003241
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003242 def test_wrong_args(self):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003243 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003244 When called with arguments other than a string argument for its first
Alex Chanb7480992017-01-30 14:04:47 +00003245 parameter, `Connection.sendall` raises `TypeError`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003246 """
Paul Kehrer688538c2020-08-03 19:18:15 -05003247 connection = Connection(Context(SSLv23_METHOD), None)
Alex Chanb7480992017-01-30 14:04:47 +00003248 with pytest.raises(TypeError):
3249 connection.sendall(object())
Daniel Holth079c9632019-11-17 22:45:52 -05003250 with pytest.raises(TypeError):
3251 connection.sendall([1, 2, 3])
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003252
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003253 def test_short(self):
3254 """
Alex Chanb7480992017-01-30 14:04:47 +00003255 `Connection.sendall` transmits all of the bytes in the string
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003256 passed to it.
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003257 """
Alex Chanb7480992017-01-30 14:04:47 +00003258 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04003259 server.sendall(b"x")
3260 assert client.recv(1) == b"x"
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003261
Abraham Martinef063482015-03-25 14:06:24 +00003262 def test_text(self):
3263 """
Alex Chanb7480992017-01-30 14:04:47 +00003264 `Connection.sendall` transmits all the content in the string passed
3265 to it, raising a DeprecationWarning in case of this being a text.
Abraham Martinef063482015-03-25 14:06:24 +00003266 """
Alex Chanb7480992017-01-30 14:04:47 +00003267 server, client = loopback()
3268 with pytest.warns(DeprecationWarning) as w:
Abraham Martinef063482015-03-25 14:06:24 +00003269 simplefilter("always")
Jean-Paul Calderone8dc37a12015-03-29 08:16:52 -04003270 server.sendall(b"x".decode("ascii"))
Alex Gaynor03737182020-07-23 20:40:46 -04003271 assert "{0} for buf is no longer accepted, use bytes".format(
3272 WARNING_TYPE_EXPECTED
3273 ) == str(w[-1].message)
Alex Chanb7480992017-01-30 14:04:47 +00003274 assert client.recv(1) == b"x"
Abraham Martinef063482015-03-25 14:06:24 +00003275
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003276 def test_short_memoryview(self):
3277 """
3278 When passed a memoryview onto a small number of bytes,
Alex Chanb7480992017-01-30 14:04:47 +00003279 `Connection.sendall` transmits all of them.
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003280 """
Alex Chanb7480992017-01-30 14:04:47 +00003281 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04003282 server.sendall(memoryview(b"x"))
3283 assert client.recv(1) == b"x"
Abraham Martinef063482015-03-25 14:06:24 +00003284
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003285 @skip_if_py3
3286 def test_short_buffers(self):
3287 """
3288 When passed a buffer containing a small number of bytes,
Alex Chanb7480992017-01-30 14:04:47 +00003289 `Connection.sendall` transmits all of them.
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003290 """
Alex Chanb7480992017-01-30 14:04:47 +00003291 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04003292 count = server.sendall(buffer(b"xy")) # noqa: F821
Daniel Holth079c9632019-11-17 22:45:52 -05003293 assert count == 2
Alex Gaynor03737182020-07-23 20:40:46 -04003294 assert client.recv(2) == b"xy"
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02003295
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003296 def test_long(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003297 """
Alex Chanb7480992017-01-30 14:04:47 +00003298 `Connection.sendall` transmits all the bytes in the string passed to it
3299 even if this requires multiple calls of an underlying write function.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003300 """
Alex Chanb7480992017-01-30 14:04:47 +00003301 server, client = loopback()
Jean-Paul Calderone6241c702010-09-16 19:59:24 -04003302 # Should be enough, underlying SSL_write should only do 16k at a time.
Hynek Schlawack35618382015-09-05 21:54:25 +02003303 # On Windows, after 32k of bytes the write will block (forever
3304 # - because no one is yet reading).
Alex Gaynor03737182020-07-23 20:40:46 -04003305 message = b"x" * (1024 * 32 - 1) + b"y"
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003306 server.sendall(message)
3307 accum = []
3308 received = 0
3309 while received < len(message):
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04003310 data = client.recv(1024)
3311 accum.append(data)
3312 received += len(data)
Alex Gaynor03737182020-07-23 20:40:46 -04003313 assert message == b"".join(accum)
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003314
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003315 def test_closed(self):
3316 """
Alex Chanb7480992017-01-30 14:04:47 +00003317 If the underlying socket is closed, `Connection.sendall` propagates the
3318 write error from the low level write call.
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003319 """
Alex Chanb7480992017-01-30 14:04:47 +00003320 server, client = loopback()
Jean-Paul Calderone05d43e82010-09-24 18:01:36 -04003321 server.sock_shutdown(2)
Alex Chanb7480992017-01-30 14:04:47 +00003322 with pytest.raises(SysCallError) as err:
3323 server.sendall(b"hello, world")
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +02003324 if platform == "win32":
Alex Chanb7480992017-01-30 14:04:47 +00003325 assert err.value.args[0] == ESHUTDOWN
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +02003326 else:
Alex Chanb7480992017-01-30 14:04:47 +00003327 assert err.value.args[0] == EPIPE
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003328
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003329
Alex Chanb7480992017-01-30 14:04:47 +00003330class TestConnectionRenegotiate(object):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003331 """
3332 Tests for SSL renegotiation APIs.
3333 """
Alex Gaynor03737182020-07-23 20:40:46 -04003334
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003335 def test_total_renegotiations(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003336 """
Alex Chanb7480992017-01-30 14:04:47 +00003337 `Connection.total_renegotiations` returns `0` before any renegotiations
3338 have happened.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003339 """
Paul Kehrer688538c2020-08-03 19:18:15 -05003340 connection = Connection(Context(SSLv23_METHOD), None)
Alex Chanb7480992017-01-30 14:04:47 +00003341 assert connection.total_renegotiations() == 0
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003342
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003343 def test_renegotiate(self):
3344 """
3345 Go through a complete renegotiation cycle.
3346 """
Paul Kehrer7d5a3bf2019-01-21 12:24:02 -06003347 server, client = loopback(
3348 lambda s: loopback_server_factory(s, TLSv1_2_METHOD),
3349 lambda s: loopback_client_factory(s, TLSv1_2_METHOD),
3350 )
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003351
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003352 server.send(b"hello world")
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003353
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003354 assert b"hello world" == client.recv(len(b"hello world"))
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003355
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003356 assert 0 == server.total_renegotiations()
3357 assert False is server.renegotiate_pending()
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003358
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003359 assert True is server.renegotiate()
3360
3361 assert True is server.renegotiate_pending()
3362
3363 server.setblocking(False)
3364 client.setblocking(False)
3365
3366 client.do_handshake()
3367 server.do_handshake()
3368
3369 assert 1 == server.total_renegotiations()
3370 while False is server.renegotiate_pending():
3371 pass
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003372
3373
Alex Chanb7480992017-01-30 14:04:47 +00003374class TestError(object):
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003375 """
Alex Chanb7480992017-01-30 14:04:47 +00003376 Unit tests for `OpenSSL.SSL.Error`.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003377 """
Alex Gaynor03737182020-07-23 20:40:46 -04003378
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003379 def test_type(self):
3380 """
Alex Chanb7480992017-01-30 14:04:47 +00003381 `Error` is an exception type.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003382 """
Alex Chanb7480992017-01-30 14:04:47 +00003383 assert issubclass(Error, Exception)
Alex Gaynor03737182020-07-23 20:40:46 -04003384 assert Error.__name__ == "Error"
Rick Deane15b1472009-07-09 15:53:42 -05003385
3386
Alex Chanb7480992017-01-30 14:04:47 +00003387class TestConstants(object):
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003388 """
Alex Chanb7480992017-01-30 14:04:47 +00003389 Tests for the values of constants exposed in `OpenSSL.SSL`.
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003390
3391 These are values defined by OpenSSL intended only to be used as flags to
3392 OpenSSL APIs. The only assertions it seems can be made about them is
3393 their values.
3394 """
Alex Gaynor03737182020-07-23 20:40:46 -04003395
Hynek Schlawack35618382015-09-05 21:54:25 +02003396 @pytest.mark.skipif(
3397 OP_NO_QUERY_MTU is None,
Alex Gaynor03737182020-07-23 20:40:46 -04003398 reason="OP_NO_QUERY_MTU unavailable - OpenSSL version may be too old",
Hynek Schlawack35618382015-09-05 21:54:25 +02003399 )
3400 def test_op_no_query_mtu(self):
3401 """
Alex Chanb7480992017-01-30 14:04:47 +00003402 The value of `OpenSSL.SSL.OP_NO_QUERY_MTU` is 0x1000, the value
3403 of `SSL_OP_NO_QUERY_MTU` defined by `openssl/ssl.h`.
Hynek Schlawack35618382015-09-05 21:54:25 +02003404 """
Alex Chanb7480992017-01-30 14:04:47 +00003405 assert OP_NO_QUERY_MTU == 0x1000
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003406
Hynek Schlawack35618382015-09-05 21:54:25 +02003407 @pytest.mark.skipif(
3408 OP_COOKIE_EXCHANGE is None,
3409 reason="OP_COOKIE_EXCHANGE unavailable - "
Alex Gaynor03737182020-07-23 20:40:46 -04003410 "OpenSSL version may be too old",
Hynek Schlawack35618382015-09-05 21:54:25 +02003411 )
3412 def test_op_cookie_exchange(self):
3413 """
Alex Chanb7480992017-01-30 14:04:47 +00003414 The value of `OpenSSL.SSL.OP_COOKIE_EXCHANGE` is 0x2000, the
3415 value of `SSL_OP_COOKIE_EXCHANGE` defined by `openssl/ssl.h`.
Hynek Schlawack35618382015-09-05 21:54:25 +02003416 """
Alex Chanb7480992017-01-30 14:04:47 +00003417 assert OP_COOKIE_EXCHANGE == 0x2000
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003418
Hynek Schlawack35618382015-09-05 21:54:25 +02003419 @pytest.mark.skipif(
3420 OP_NO_TICKET is None,
Alex Gaynor03737182020-07-23 20:40:46 -04003421 reason="OP_NO_TICKET unavailable - OpenSSL version may be too old",
Hynek Schlawack35618382015-09-05 21:54:25 +02003422 )
3423 def test_op_no_ticket(self):
3424 """
Alex Chanb7480992017-01-30 14:04:47 +00003425 The value of `OpenSSL.SSL.OP_NO_TICKET` is 0x4000, the value of
3426 `SSL_OP_NO_TICKET` defined by `openssl/ssl.h`.
Hynek Schlawack35618382015-09-05 21:54:25 +02003427 """
Alex Chanb7480992017-01-30 14:04:47 +00003428 assert OP_NO_TICKET == 0x4000
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003429
Hynek Schlawack35618382015-09-05 21:54:25 +02003430 @pytest.mark.skipif(
3431 OP_NO_COMPRESSION is None,
Alex Gaynor03737182020-07-23 20:40:46 -04003432 reason=(
3433 "OP_NO_COMPRESSION unavailable - OpenSSL version may be too old"
3434 ),
Hynek Schlawack35618382015-09-05 21:54:25 +02003435 )
3436 def test_op_no_compression(self):
3437 """
Alex Chanb7480992017-01-30 14:04:47 +00003438 The value of `OpenSSL.SSL.OP_NO_COMPRESSION` is 0x20000, the
3439 value of `SSL_OP_NO_COMPRESSION` defined by `openssl/ssl.h`.
Hynek Schlawack35618382015-09-05 21:54:25 +02003440 """
Alex Chanb7480992017-01-30 14:04:47 +00003441 assert OP_NO_COMPRESSION == 0x20000
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04003442
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003443 def test_sess_cache_off(self):
3444 """
Alex Chanb7480992017-01-30 14:04:47 +00003445 The value of `OpenSSL.SSL.SESS_CACHE_OFF` 0x0, the value of
3446 `SSL_SESS_CACHE_OFF` defined by `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003447 """
Alex Chanb7480992017-01-30 14:04:47 +00003448 assert 0x0 == SESS_CACHE_OFF
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003449
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003450 def test_sess_cache_client(self):
3451 """
Alex Chanb7480992017-01-30 14:04:47 +00003452 The value of `OpenSSL.SSL.SESS_CACHE_CLIENT` 0x1, the value of
3453 `SSL_SESS_CACHE_CLIENT` defined by `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003454 """
Alex Chanb7480992017-01-30 14:04:47 +00003455 assert 0x1 == SESS_CACHE_CLIENT
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003456
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003457 def test_sess_cache_server(self):
3458 """
Alex Chanb7480992017-01-30 14:04:47 +00003459 The value of `OpenSSL.SSL.SESS_CACHE_SERVER` 0x2, the value of
3460 `SSL_SESS_CACHE_SERVER` defined by `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003461 """
Alex Chanb7480992017-01-30 14:04:47 +00003462 assert 0x2 == SESS_CACHE_SERVER
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003463
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003464 def test_sess_cache_both(self):
3465 """
Alex Chanb7480992017-01-30 14:04:47 +00003466 The value of `OpenSSL.SSL.SESS_CACHE_BOTH` 0x3, the value of
3467 `SSL_SESS_CACHE_BOTH` defined by `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003468 """
Alex Chanb7480992017-01-30 14:04:47 +00003469 assert 0x3 == SESS_CACHE_BOTH
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003470
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003471 def test_sess_cache_no_auto_clear(self):
3472 """
Alex Chanb7480992017-01-30 14:04:47 +00003473 The value of `OpenSSL.SSL.SESS_CACHE_NO_AUTO_CLEAR` 0x80, the
3474 value of `SSL_SESS_CACHE_NO_AUTO_CLEAR` defined by
3475 `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003476 """
Alex Chanb7480992017-01-30 14:04:47 +00003477 assert 0x80 == SESS_CACHE_NO_AUTO_CLEAR
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003478
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003479 def test_sess_cache_no_internal_lookup(self):
3480 """
Alex Chanb7480992017-01-30 14:04:47 +00003481 The value of `OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_LOOKUP` 0x100,
3482 the value of `SSL_SESS_CACHE_NO_INTERNAL_LOOKUP` defined by
3483 `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003484 """
Alex Chanb7480992017-01-30 14:04:47 +00003485 assert 0x100 == SESS_CACHE_NO_INTERNAL_LOOKUP
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003486
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003487 def test_sess_cache_no_internal_store(self):
3488 """
Alex Chanb7480992017-01-30 14:04:47 +00003489 The value of `OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_STORE` 0x200,
3490 the value of `SSL_SESS_CACHE_NO_INTERNAL_STORE` defined by
3491 `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003492 """
Alex Chanb7480992017-01-30 14:04:47 +00003493 assert 0x200 == SESS_CACHE_NO_INTERNAL_STORE
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003494
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003495 def test_sess_cache_no_internal(self):
3496 """
Alex Chanb7480992017-01-30 14:04:47 +00003497 The value of `OpenSSL.SSL.SESS_CACHE_NO_INTERNAL` 0x300, the
3498 value of `SSL_SESS_CACHE_NO_INTERNAL` defined by
3499 `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003500 """
Alex Chanb7480992017-01-30 14:04:47 +00003501 assert 0x300 == SESS_CACHE_NO_INTERNAL
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003502
3503
Alex Chanb7480992017-01-30 14:04:47 +00003504class TestMemoryBIO(object):
Rick Deanb71c0d22009-04-01 14:09:23 -05003505 """
Alex Chanb7480992017-01-30 14:04:47 +00003506 Tests for `OpenSSL.SSL.Connection` using a memory BIO.
Rick Deanb71c0d22009-04-01 14:09:23 -05003507 """
Alex Gaynor03737182020-07-23 20:40:46 -04003508
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003509 def _server(self, sock):
3510 """
Alex Chanb7480992017-01-30 14:04:47 +00003511 Create a new server-side SSL `Connection` object wrapped around `sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003512 """
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003513 # Create the server side Connection. This is mostly setup boilerplate
3514 # - use TLSv1, use a particular certificate, etc.
Paul Kehrer688538c2020-08-03 19:18:15 -05003515 server_ctx = Context(SSLv23_METHOD)
Alex Gaynor43307782015-09-04 09:05:45 -04003516 server_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE)
Hynek Schlawack35618382015-09-05 21:54:25 +02003517 server_ctx.set_verify(
3518 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT | VERIFY_CLIENT_ONCE,
Alex Gaynor03737182020-07-23 20:40:46 -04003519 verify_cb,
Hynek Schlawack35618382015-09-05 21:54:25 +02003520 )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003521 server_store = server_ctx.get_cert_store()
Hynek Schlawack35618382015-09-05 21:54:25 +02003522 server_ctx.use_privatekey(
Alex Gaynor03737182020-07-23 20:40:46 -04003523 load_privatekey(FILETYPE_PEM, server_key_pem)
3524 )
Hynek Schlawack35618382015-09-05 21:54:25 +02003525 server_ctx.use_certificate(
Alex Gaynor03737182020-07-23 20:40:46 -04003526 load_certificate(FILETYPE_PEM, server_cert_pem)
3527 )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003528 server_ctx.check_privatekey()
3529 server_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Hynek Schlawack35618382015-09-05 21:54:25 +02003530 # Here the Connection is actually created. If None is passed as the
3531 # 2nd parameter, it indicates a memory BIO should be created.
Rick Deanb1ccd562009-07-09 23:52:39 -05003532 server_conn = Connection(server_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003533 server_conn.set_accept_state()
3534 return server_conn
3535
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003536 def _client(self, sock):
3537 """
Alex Chanb7480992017-01-30 14:04:47 +00003538 Create a new client-side SSL `Connection` object wrapped around `sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003539 """
3540 # Now create the client side Connection. Similar boilerplate to the
3541 # above.
Paul Kehrer688538c2020-08-03 19:18:15 -05003542 client_ctx = Context(SSLv23_METHOD)
Alex Gaynor43307782015-09-04 09:05:45 -04003543 client_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE)
Hynek Schlawack35618382015-09-05 21:54:25 +02003544 client_ctx.set_verify(
3545 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT | VERIFY_CLIENT_ONCE,
Alex Gaynor03737182020-07-23 20:40:46 -04003546 verify_cb,
Hynek Schlawack35618382015-09-05 21:54:25 +02003547 )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003548 client_store = client_ctx.get_cert_store()
Hynek Schlawack35618382015-09-05 21:54:25 +02003549 client_ctx.use_privatekey(
Alex Gaynor03737182020-07-23 20:40:46 -04003550 load_privatekey(FILETYPE_PEM, client_key_pem)
3551 )
Hynek Schlawack35618382015-09-05 21:54:25 +02003552 client_ctx.use_certificate(
Alex Gaynor03737182020-07-23 20:40:46 -04003553 load_certificate(FILETYPE_PEM, client_cert_pem)
3554 )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003555 client_ctx.check_privatekey()
3556 client_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05003557 client_conn = Connection(client_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003558 client_conn.set_connect_state()
3559 return client_conn
3560
Alex Chanb7480992017-01-30 14:04:47 +00003561 def test_memory_connect(self):
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003562 """
Alex Chanb7480992017-01-30 14:04:47 +00003563 Two `Connection`s which use memory BIOs can be manually connected by
3564 reading from the output of each and writing those bytes to the input of
3565 the other and in this way establish a connection and exchange
3566 application-level bytes with each other.
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003567 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003568 server_conn = self._server(None)
3569 client_conn = self._client(None)
Rick Deanb71c0d22009-04-01 14:09:23 -05003570
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003571 # There should be no key or nonces yet.
Alex Chanb7480992017-01-30 14:04:47 +00003572 assert server_conn.master_key() is None
3573 assert server_conn.client_random() is None
3574 assert server_conn.server_random() is None
Rick Deanb71c0d22009-04-01 14:09:23 -05003575
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003576 # First, the handshake needs to happen. We'll deliver bytes back and
3577 # forth between the client and server until neither of them feels like
3578 # speaking any more.
Alex Chanb7480992017-01-30 14:04:47 +00003579 assert interact_in_memory(client_conn, server_conn) is None
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003580
3581 # Now that the handshake is done, there should be a key and nonces.
Alex Chanb7480992017-01-30 14:04:47 +00003582 assert server_conn.master_key() is not None
3583 assert server_conn.client_random() is not None
3584 assert server_conn.server_random() is not None
3585 assert server_conn.client_random() == client_conn.client_random()
3586 assert server_conn.server_random() == client_conn.server_random()
3587 assert server_conn.client_random() != server_conn.server_random()
3588 assert client_conn.client_random() != client_conn.server_random()
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003589
Paul Kehrerbdb76392017-12-01 04:54:32 +08003590 # Export key material for other uses.
Alex Gaynor03737182020-07-23 20:40:46 -04003591 cekm = client_conn.export_keying_material(b"LABEL", 32)
3592 sekm = server_conn.export_keying_material(b"LABEL", 32)
Paul Kehrerbdb76392017-12-01 04:54:32 +08003593 assert cekm is not None
3594 assert sekm is not None
3595 assert cekm == sekm
3596 assert len(sekm) == 32
3597
3598 # Export key material for other uses with additional context.
Alex Gaynor03737182020-07-23 20:40:46 -04003599 cekmc = client_conn.export_keying_material(b"LABEL", 32, b"CONTEXT")
3600 sekmc = server_conn.export_keying_material(b"LABEL", 32, b"CONTEXT")
Paul Kehrerbdb76392017-12-01 04:54:32 +08003601 assert cekmc is not None
3602 assert sekmc is not None
3603 assert cekmc == sekmc
3604 assert cekmc != cekm
3605 assert sekmc != sekm
3606 # Export with alternate label
Alex Gaynor03737182020-07-23 20:40:46 -04003607 cekmt = client_conn.export_keying_material(b"test", 32, b"CONTEXT")
3608 sekmt = server_conn.export_keying_material(b"test", 32, b"CONTEXT")
Paul Kehrerbdb76392017-12-01 04:54:32 +08003609 assert cekmc != cekmt
3610 assert sekmc != sekmt
3611
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003612 # Here are the bytes we'll try to send.
Alex Gaynor03737182020-07-23 20:40:46 -04003613 important_message = b"One if by land, two if by sea."
Rick Deanb71c0d22009-04-01 14:09:23 -05003614
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003615 server_conn.write(important_message)
Alex Gaynor03737182020-07-23 20:40:46 -04003616 assert interact_in_memory(client_conn, server_conn) == (
3617 client_conn,
3618 important_message,
3619 )
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003620
3621 client_conn.write(important_message[::-1])
Alex Gaynor03737182020-07-23 20:40:46 -04003622 assert interact_in_memory(client_conn, server_conn) == (
3623 server_conn,
3624 important_message[::-1],
3625 )
Rick Deanb71c0d22009-04-01 14:09:23 -05003626
Alex Chanb7480992017-01-30 14:04:47 +00003627 def test_socket_connect(self):
Rick Deanb1ccd562009-07-09 23:52:39 -05003628 """
Alex Chanb7480992017-01-30 14:04:47 +00003629 Just like `test_memory_connect` but with an actual socket.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003630
Hynek Schlawack35618382015-09-05 21:54:25 +02003631 This is primarily to rule out the memory BIO code as the source of any
Alex Chanb7480992017-01-30 14:04:47 +00003632 problems encountered while passing data over a `Connection` (if
Hynek Schlawack35618382015-09-05 21:54:25 +02003633 this test fails, there must be a problem outside the memory BIO code,
3634 as no memory BIO is involved here). Even though this isn't a memory
3635 BIO test, it's convenient to have it here.
Rick Deanb1ccd562009-07-09 23:52:39 -05003636 """
Alex Chanb7480992017-01-30 14:04:47 +00003637 server_conn, client_conn = loopback()
Rick Deanb1ccd562009-07-09 23:52:39 -05003638
Alex Gaynore7f51982016-09-11 11:48:14 -04003639 important_message = b"Help me Obi Wan Kenobi, you're my only hope."
Rick Deanb1ccd562009-07-09 23:52:39 -05003640 client_conn.send(important_message)
3641 msg = server_conn.recv(1024)
Alex Chanb7480992017-01-30 14:04:47 +00003642 assert msg == important_message
Rick Deanb1ccd562009-07-09 23:52:39 -05003643
3644 # Again in the other direction, just for fun.
3645 important_message = important_message[::-1]
3646 server_conn.send(important_message)
3647 msg = client_conn.recv(1024)
Alex Chanb7480992017-01-30 14:04:47 +00003648 assert msg == important_message
Rick Deanb1ccd562009-07-09 23:52:39 -05003649
Alex Chanb7480992017-01-30 14:04:47 +00003650 def test_socket_overrides_memory(self):
Rick Deanb71c0d22009-04-01 14:09:23 -05003651 """
Alex Chanb7480992017-01-30 14:04:47 +00003652 Test that `OpenSSL.SSL.bio_read` and `OpenSSL.SSL.bio_write` don't
3653 work on `OpenSSL.SSL.Connection`() that use sockets.
Rick Deanb71c0d22009-04-01 14:09:23 -05003654 """
Paul Kehrer688538c2020-08-03 19:18:15 -05003655 context = Context(SSLv23_METHOD)
David Benjamin1fbe0642019-04-15 17:05:13 -05003656 client = socket_any_family()
Rick Deanb71c0d22009-04-01 14:09:23 -05003657 clientSSL = Connection(context, client)
Alex Chanb7480992017-01-30 14:04:47 +00003658 with pytest.raises(TypeError):
3659 clientSSL.bio_read(100)
3660 with pytest.raises(TypeError):
Paul Kehrerc45a6ea2020-08-03 15:54:20 -05003661 clientSSL.bio_write(b"foo")
Alex Chanb7480992017-01-30 14:04:47 +00003662 with pytest.raises(TypeError):
3663 clientSSL.bio_shutdown()
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003664
Alex Chanb7480992017-01-30 14:04:47 +00003665 def test_outgoing_overflow(self):
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003666 """
3667 If more bytes than can be written to the memory BIO are passed to
Alex Chanb7480992017-01-30 14:04:47 +00003668 `Connection.send` at once, the number of bytes which were written is
3669 returned and that many bytes from the beginning of the input can be
3670 read from the other end of the connection.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003671 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003672 server = self._server(None)
3673 client = self._client(None)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003674
Alex Chanb7480992017-01-30 14:04:47 +00003675 interact_in_memory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003676
3677 size = 2 ** 15
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003678 sent = client.send(b"x" * size)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003679 # Sanity check. We're trying to test what happens when the entire
3680 # input can't be sent. If the entire input was sent, this test is
3681 # meaningless.
Alex Chanb7480992017-01-30 14:04:47 +00003682 assert sent < size
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003683
Alex Chanb7480992017-01-30 14:04:47 +00003684 receiver, received = interact_in_memory(client, server)
3685 assert receiver is server
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003686
3687 # We can rely on all of these bytes being received at once because
Alex Chanb7480992017-01-30 14:04:47 +00003688 # loopback passes 2 ** 16 to recv - more than 2 ** 15.
3689 assert len(received) == sent
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003690
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003691 def test_shutdown(self):
3692 """
Alex Chanb7480992017-01-30 14:04:47 +00003693 `Connection.bio_shutdown` signals the end of the data stream
3694 from which the `Connection` reads.
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003695 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003696 server = self._server(None)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003697 server.bio_shutdown()
Alex Chanb7480992017-01-30 14:04:47 +00003698 with pytest.raises(Error) as err:
3699 server.recv(1024)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003700 # We don't want WantReadError or ZeroReturnError or anything - it's a
3701 # handshake failure.
Alex Chanb7480992017-01-30 14:04:47 +00003702 assert type(err.value) in [Error, SysCallError]
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003703
Alex Chanb7480992017-01-30 14:04:47 +00003704 def test_unexpected_EOF(self):
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003705 """
3706 If the connection is lost before an orderly SSL shutdown occurs,
Alex Chanb7480992017-01-30 14:04:47 +00003707 `OpenSSL.SSL.SysCallError` is raised with a message of
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003708 "Unexpected EOF".
3709 """
Alex Chanb7480992017-01-30 14:04:47 +00003710 server_conn, client_conn = loopback()
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003711 client_conn.sock_shutdown(SHUT_RDWR)
Alex Chanb7480992017-01-30 14:04:47 +00003712 with pytest.raises(SysCallError) as err:
3713 server_conn.recv(1024)
3714 assert err.value.args == (-1, "Unexpected EOF")
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003715
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003716 def _check_client_ca_list(self, func):
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003717 """
Alex Chanb7480992017-01-30 14:04:47 +00003718 Verify the return value of the `get_client_ca_list` method for
Hynek Schlawack35618382015-09-05 21:54:25 +02003719 server and client connections.
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003720
Jonathan Ballet78b92a22011-07-16 08:07:26 +09003721 :param func: A function which will be called with the server context
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003722 before the client and server are connected to each other. This
3723 function should specify a list of CAs for the server to send to the
3724 client and return that same list. The list will be used to verify
Alex Chanb7480992017-01-30 14:04:47 +00003725 that `get_client_ca_list` returns the proper value at
Hynek Schlawack35618382015-09-05 21:54:25 +02003726 various times.
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003727 """
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003728 server = self._server(None)
3729 client = self._client(None)
Alex Chanb7480992017-01-30 14:04:47 +00003730 assert client.get_client_ca_list() == []
3731 assert server.get_client_ca_list() == []
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003732 ctx = server.get_context()
3733 expected = func(ctx)
Alex Chanb7480992017-01-30 14:04:47 +00003734 assert client.get_client_ca_list() == []
3735 assert server.get_client_ca_list() == expected
3736 interact_in_memory(client, server)
3737 assert client.get_client_ca_list() == expected
3738 assert server.get_client_ca_list() == expected
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003739
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003740 def test_set_client_ca_list_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003741 """
Alex Chanb7480992017-01-30 14:04:47 +00003742 `Context.set_client_ca_list` raises a `TypeError` if called with a
3743 non-list or a list that contains objects other than X509Names.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003744 """
Paul Kehrer688538c2020-08-03 19:18:15 -05003745 ctx = Context(SSLv23_METHOD)
Alex Chanb7480992017-01-30 14:04:47 +00003746 with pytest.raises(TypeError):
3747 ctx.set_client_ca_list("spam")
3748 with pytest.raises(TypeError):
3749 ctx.set_client_ca_list(["spam"])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003750
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003751 def test_set_empty_ca_list(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003752 """
Alex Chanb7480992017-01-30 14:04:47 +00003753 If passed an empty list, `Context.set_client_ca_list` configures the
3754 context to send no CA names to the client and, on both the server and
3755 client sides, `Connection.get_client_ca_list` returns an empty list
3756 after the connection is set up.
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003757 """
Alex Gaynor03737182020-07-23 20:40:46 -04003758
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003759 def no_ca(ctx):
3760 ctx.set_client_ca_list([])
3761 return []
Alex Gaynor03737182020-07-23 20:40:46 -04003762
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003763 self._check_client_ca_list(no_ca)
3764
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003765 def test_set_one_ca_list(self):
3766 """
3767 If passed a list containing a single X509Name,
Alex Chanb7480992017-01-30 14:04:47 +00003768 `Context.set_client_ca_list` configures the context to send
Hynek Schlawack35618382015-09-05 21:54:25 +02003769 that CA name to the client and, on both the server and client sides,
Alex Chanb7480992017-01-30 14:04:47 +00003770 `Connection.get_client_ca_list` returns a list containing that
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003771 X509Name after the connection is set up.
3772 """
3773 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3774 cadesc = cacert.get_subject()
Hynek Schlawack35618382015-09-05 21:54:25 +02003775
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003776 def single_ca(ctx):
3777 ctx.set_client_ca_list([cadesc])
3778 return [cadesc]
Alex Gaynor03737182020-07-23 20:40:46 -04003779
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003780 self._check_client_ca_list(single_ca)
3781
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003782 def test_set_multiple_ca_list(self):
3783 """
3784 If passed a list containing multiple X509Name objects,
Alex Chanb7480992017-01-30 14:04:47 +00003785 `Context.set_client_ca_list` configures the context to send
Hynek Schlawack35618382015-09-05 21:54:25 +02003786 those CA names to the client and, on both the server and client sides,
Alex Chanb7480992017-01-30 14:04:47 +00003787 `Connection.get_client_ca_list` returns a list containing those
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003788 X509Names after the connection is set up.
3789 """
3790 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3791 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3792
3793 sedesc = secert.get_subject()
3794 cldesc = clcert.get_subject()
3795
3796 def multiple_ca(ctx):
3797 L = [sedesc, cldesc]
3798 ctx.set_client_ca_list(L)
3799 return L
Alex Gaynor03737182020-07-23 20:40:46 -04003800
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003801 self._check_client_ca_list(multiple_ca)
3802
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003803 def test_reset_ca_list(self):
3804 """
3805 If called multiple times, only the X509Names passed to the final call
Alex Chanb7480992017-01-30 14:04:47 +00003806 of `Context.set_client_ca_list` are used to configure the CA
Hynek Schlawack35618382015-09-05 21:54:25 +02003807 names sent to the client.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003808 """
3809 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3810 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3811 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3812
3813 cadesc = cacert.get_subject()
3814 sedesc = secert.get_subject()
3815 cldesc = clcert.get_subject()
3816
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003817 def changed_ca(ctx):
3818 ctx.set_client_ca_list([sedesc, cldesc])
3819 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003820 return [cadesc]
Alex Gaynor03737182020-07-23 20:40:46 -04003821
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003822 self._check_client_ca_list(changed_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003823
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003824 def test_mutated_ca_list(self):
3825 """
Alex Chanb7480992017-01-30 14:04:47 +00003826 If the list passed to `Context.set_client_ca_list` is mutated
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003827 afterwards, this does not affect the list of CA names sent to the
3828 client.
3829 """
3830 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3831 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3832
3833 cadesc = cacert.get_subject()
3834 sedesc = secert.get_subject()
3835
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003836 def mutated_ca(ctx):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003837 L = [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003838 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003839 L.append(sedesc)
3840 return [cadesc]
Alex Gaynor03737182020-07-23 20:40:46 -04003841
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003842 self._check_client_ca_list(mutated_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003843
Alex Chanb7480992017-01-30 14:04:47 +00003844 def test_add_client_ca_wrong_args(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003845 """
Alex Chanb7480992017-01-30 14:04:47 +00003846 `Context.add_client_ca` raises `TypeError` if called with
3847 a non-X509 object.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003848 """
Paul Kehrer688538c2020-08-03 19:18:15 -05003849 ctx = Context(SSLv23_METHOD)
Alex Chanb7480992017-01-30 14:04:47 +00003850 with pytest.raises(TypeError):
3851 ctx.add_client_ca("spam")
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003852
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003853 def test_one_add_client_ca(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003854 """
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003855 A certificate's subject can be added as a CA to be sent to the client
Alex Chanb7480992017-01-30 14:04:47 +00003856 with `Context.add_client_ca`.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003857 """
3858 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3859 cadesc = cacert.get_subject()
Hynek Schlawack35618382015-09-05 21:54:25 +02003860
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003861 def single_ca(ctx):
3862 ctx.add_client_ca(cacert)
3863 return [cadesc]
Alex Gaynor03737182020-07-23 20:40:46 -04003864
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003865 self._check_client_ca_list(single_ca)
3866
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003867 def test_multiple_add_client_ca(self):
3868 """
3869 Multiple CA names can be sent to the client by calling
Alex Chanb7480992017-01-30 14:04:47 +00003870 `Context.add_client_ca` with multiple X509 objects.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003871 """
3872 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3873 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3874
3875 cadesc = cacert.get_subject()
3876 sedesc = secert.get_subject()
3877
3878 def multiple_ca(ctx):
3879 ctx.add_client_ca(cacert)
3880 ctx.add_client_ca(secert)
3881 return [cadesc, sedesc]
Alex Gaynor03737182020-07-23 20:40:46 -04003882
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003883 self._check_client_ca_list(multiple_ca)
3884
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003885 def test_set_and_add_client_ca(self):
3886 """
Alex Chanb7480992017-01-30 14:04:47 +00003887 A call to `Context.set_client_ca_list` followed by a call to
3888 `Context.add_client_ca` results in using the CA names from the
Hynek Schlawack35618382015-09-05 21:54:25 +02003889 first call and the CA name from the second call.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003890 """
3891 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3892 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3893 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3894
3895 cadesc = cacert.get_subject()
3896 sedesc = secert.get_subject()
3897 cldesc = clcert.get_subject()
3898
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003899 def mixed_set_add_ca(ctx):
3900 ctx.set_client_ca_list([cadesc, sedesc])
3901 ctx.add_client_ca(clcert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003902 return [cadesc, sedesc, cldesc]
Alex Gaynor03737182020-07-23 20:40:46 -04003903
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003904 self._check_client_ca_list(mixed_set_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003905
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003906 def test_set_after_add_client_ca(self):
3907 """
Alex Chanb7480992017-01-30 14:04:47 +00003908 A call to `Context.set_client_ca_list` after a call to
3909 `Context.add_client_ca` replaces the CA name specified by the
Hynek Schlawack35618382015-09-05 21:54:25 +02003910 former call with the names specified by the latter call.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003911 """
3912 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3913 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3914 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3915
3916 cadesc = cacert.get_subject()
3917 sedesc = secert.get_subject()
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003918
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003919 def set_replaces_add_ca(ctx):
3920 ctx.add_client_ca(clcert)
3921 ctx.set_client_ca_list([cadesc])
3922 ctx.add_client_ca(secert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003923 return [cadesc, sedesc]
Alex Gaynor03737182020-07-23 20:40:46 -04003924
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003925 self._check_client_ca_list(set_replaces_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003926
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003927
Alex Chanb7480992017-01-30 14:04:47 +00003928class TestInfoConstants(object):
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003929 """
3930 Tests for assorted constants exposed for use in info callbacks.
3931 """
Alex Gaynor03737182020-07-23 20:40:46 -04003932
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003933 def test_integers(self):
3934 """
3935 All of the info constants are integers.
3936
3937 This is a very weak test. It would be nice to have one that actually
3938 verifies that as certain info events happen, the value passed to the
3939 info callback matches up with the constant exposed by OpenSSL.SSL.
3940 """
3941 for const in [
Alex Gaynor03737182020-07-23 20:40:46 -04003942 SSL_ST_CONNECT,
3943 SSL_ST_ACCEPT,
3944 SSL_ST_MASK,
3945 SSL_CB_LOOP,
3946 SSL_CB_EXIT,
3947 SSL_CB_READ,
3948 SSL_CB_WRITE,
3949 SSL_CB_ALERT,
3950 SSL_CB_READ_ALERT,
3951 SSL_CB_WRITE_ALERT,
3952 SSL_CB_ACCEPT_LOOP,
3953 SSL_CB_ACCEPT_EXIT,
3954 SSL_CB_CONNECT_LOOP,
3955 SSL_CB_CONNECT_EXIT,
3956 SSL_CB_HANDSHAKE_START,
3957 SSL_CB_HANDSHAKE_DONE,
Hynek Schlawack35618382015-09-05 21:54:25 +02003958 ]:
Alex Gaynor5af32d02016-09-24 01:52:21 -04003959 assert isinstance(const, int)
3960
3961 # These constants don't exist on OpenSSL 1.1.0
3962 for const in [
Alex Gaynor03737182020-07-23 20:40:46 -04003963 SSL_ST_INIT,
3964 SSL_ST_BEFORE,
3965 SSL_ST_OK,
3966 SSL_ST_RENEGOTIATE,
Alex Gaynor5af32d02016-09-24 01:52:21 -04003967 ]:
3968 assert const is None or isinstance(const, int)
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003969
Ziga Seilnacht44611bf2009-08-31 20:49:30 +02003970
Cory Benfield1d142142016-03-30 11:51:45 +01003971class TestRequires(object):
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003972 """
3973 Tests for the decorator factory used to conditionally raise
Cory Benfield1d142142016-03-30 11:51:45 +01003974 NotImplementedError when older OpenSSLs are used.
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003975 """
Alex Gaynor03737182020-07-23 20:40:46 -04003976
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003977 def test_available(self):
3978 """
3979 When the OpenSSL functionality is available the decorated functions
3980 work appropriately.
3981 """
3982 feature_guard = _make_requires(True, "Error text")
3983 results = []
3984
3985 @feature_guard
3986 def inner():
3987 results.append(True)
3988 return True
3989
Cory Benfield2333e5e2016-03-30 14:24:16 +01003990 assert inner() is True
3991 assert [True] == results
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003992
3993 def test_unavailable(self):
3994 """
3995 When the OpenSSL functionality is not available the decorated function
3996 does not execute and NotImplementedError is raised.
3997 """
3998 feature_guard = _make_requires(False, "Error text")
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003999
4000 @feature_guard
Alex Chanfb078d82017-04-20 11:16:15 +01004001 def inner(): # pragma: nocover
4002 pytest.fail("Should not be called")
Cory Benfield0ba57ec2016-03-30 09:35:05 +01004003
Cory Benfield1d142142016-03-30 11:51:45 +01004004 with pytest.raises(NotImplementedError) as e:
4005 inner()
4006
4007 assert "Error text" in str(e.value)
Cory Benfield496652a2017-01-24 11:42:56 +00004008
4009
Alex Chanb7480992017-01-30 14:04:47 +00004010class TestOCSP(object):
Cory Benfield496652a2017-01-24 11:42:56 +00004011 """
4012 Tests for PyOpenSSL's OCSP stapling support.
4013 """
Alex Gaynor03737182020-07-23 20:40:46 -04004014
Cory Benfield496652a2017-01-24 11:42:56 +00004015 sample_ocsp_data = b"this is totally ocsp data"
4016
4017 def _client_connection(self, callback, data, request_ocsp=True):
4018 """
4019 Builds a client connection suitable for using OCSP.
4020
4021 :param callback: The callback to register for OCSP.
4022 :param data: The opaque data object that will be handed to the
4023 OCSP callback.
4024 :param request_ocsp: Whether the client will actually ask for OCSP
4025 stapling. Useful for testing only.
4026 """
4027 ctx = Context(SSLv23_METHOD)
4028 ctx.set_ocsp_client_callback(callback, data)
4029 client = Connection(ctx)
4030
4031 if request_ocsp:
4032 client.request_ocsp()
4033
4034 client.set_connect_state()
4035 return client
4036
4037 def _server_connection(self, callback, data):
4038 """
4039 Builds a server connection suitable for using OCSP.
4040
4041 :param callback: The callback to register for OCSP.
4042 :param data: The opaque data object that will be handed to the
4043 OCSP callback.
4044 """
4045 ctx = Context(SSLv23_METHOD)
4046 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
4047 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
4048 ctx.set_ocsp_server_callback(callback, data)
4049 server = Connection(ctx)
4050 server.set_accept_state()
4051 return server
4052
4053 def test_callbacks_arent_called_by_default(self):
4054 """
4055 If both the client and the server have registered OCSP callbacks, but
4056 the client does not send the OCSP request, neither callback gets
4057 called.
4058 """
Alex Gaynor03737182020-07-23 20:40:46 -04004059
Alex Chanfb078d82017-04-20 11:16:15 +01004060 def ocsp_callback(*args, **kwargs): # pragma: nocover
4061 pytest.fail("Should not be called")
Cory Benfield496652a2017-01-24 11:42:56 +00004062
4063 client = self._client_connection(
4064 callback=ocsp_callback, data=None, request_ocsp=False
4065 )
4066 server = self._server_connection(callback=ocsp_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00004067 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00004068
Cory Benfield496652a2017-01-24 11:42:56 +00004069 def test_client_negotiates_without_server(self):
4070 """
4071 If the client wants to do OCSP but the server does not, the handshake
4072 succeeds, and the client callback fires with an empty byte string.
4073 """
4074 called = []
4075
4076 def ocsp_callback(conn, ocsp_data, ignored):
4077 called.append(ocsp_data)
4078 return True
4079
4080 client = self._client_connection(callback=ocsp_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00004081 server = loopback_server_factory(socket=None)
4082 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00004083
4084 assert len(called) == 1
Alex Gaynor03737182020-07-23 20:40:46 -04004085 assert called[0] == b""
Cory Benfield496652a2017-01-24 11:42:56 +00004086
4087 def test_client_receives_servers_data(self):
4088 """
4089 The data the server sends in its callback is received by the client.
4090 """
4091 calls = []
4092
4093 def server_callback(*args, **kwargs):
4094 return self.sample_ocsp_data
4095
4096 def client_callback(conn, ocsp_data, ignored):
4097 calls.append(ocsp_data)
4098 return True
4099
4100 client = self._client_connection(callback=client_callback, data=None)
4101 server = self._server_connection(callback=server_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00004102 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00004103
4104 assert len(calls) == 1
4105 assert calls[0] == self.sample_ocsp_data
4106
4107 def test_callbacks_are_invoked_with_connections(self):
4108 """
4109 The first arguments to both callbacks are their respective connections.
4110 """
4111 client_calls = []
4112 server_calls = []
4113
4114 def client_callback(conn, *args, **kwargs):
4115 client_calls.append(conn)
4116 return True
4117
4118 def server_callback(conn, *args, **kwargs):
4119 server_calls.append(conn)
4120 return self.sample_ocsp_data
4121
4122 client = self._client_connection(callback=client_callback, data=None)
4123 server = self._server_connection(callback=server_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00004124 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00004125
4126 assert len(client_calls) == 1
4127 assert len(server_calls) == 1
4128 assert client_calls[0] is client
4129 assert server_calls[0] is server
4130
4131 def test_opaque_data_is_passed_through(self):
4132 """
4133 Both callbacks receive an opaque, user-provided piece of data in their
4134 callbacks as the final argument.
4135 """
4136 calls = []
4137
4138 def server_callback(*args):
4139 calls.append(args)
4140 return self.sample_ocsp_data
4141
4142 def client_callback(*args):
4143 calls.append(args)
4144 return True
4145
4146 sentinel = object()
4147
4148 client = self._client_connection(
4149 callback=client_callback, data=sentinel
4150 )
4151 server = self._server_connection(
4152 callback=server_callback, data=sentinel
4153 )
Alex Chanb7480992017-01-30 14:04:47 +00004154 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00004155
4156 assert len(calls) == 2
4157 assert calls[0][-1] is sentinel
4158 assert calls[1][-1] is sentinel
4159
4160 def test_server_returns_empty_string(self):
4161 """
4162 If the server returns an empty bytestring from its callback, the
4163 client callback is called with the empty bytestring.
4164 """
4165 client_calls = []
4166
4167 def server_callback(*args):
Alex Gaynor03737182020-07-23 20:40:46 -04004168 return b""
Cory Benfield496652a2017-01-24 11:42:56 +00004169
4170 def client_callback(conn, ocsp_data, ignored):
4171 client_calls.append(ocsp_data)
4172 return True
4173
4174 client = self._client_connection(callback=client_callback, data=None)
4175 server = self._server_connection(callback=server_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00004176 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00004177
4178 assert len(client_calls) == 1
Alex Gaynor03737182020-07-23 20:40:46 -04004179 assert client_calls[0] == b""
Cory Benfield496652a2017-01-24 11:42:56 +00004180
4181 def test_client_returns_false_terminates_handshake(self):
4182 """
4183 If the client returns False from its callback, the handshake fails.
4184 """
Alex Gaynor03737182020-07-23 20:40:46 -04004185
Cory Benfield496652a2017-01-24 11:42:56 +00004186 def server_callback(*args):
4187 return self.sample_ocsp_data
4188
4189 def client_callback(*args):
4190 return False
4191
4192 client = self._client_connection(callback=client_callback, data=None)
4193 server = self._server_connection(callback=server_callback, data=None)
4194
4195 with pytest.raises(Error):
Alex Chanb7480992017-01-30 14:04:47 +00004196 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00004197
4198 def test_exceptions_in_client_bubble_up(self):
4199 """
4200 The callbacks thrown in the client callback bubble up to the caller.
4201 """
Alex Gaynor03737182020-07-23 20:40:46 -04004202
Cory Benfield496652a2017-01-24 11:42:56 +00004203 class SentinelException(Exception):
4204 pass
4205
4206 def server_callback(*args):
4207 return self.sample_ocsp_data
4208
4209 def client_callback(*args):
4210 raise SentinelException()
4211
4212 client = self._client_connection(callback=client_callback, data=None)
4213 server = self._server_connection(callback=server_callback, data=None)
4214
4215 with pytest.raises(SentinelException):
Alex Chanb7480992017-01-30 14:04:47 +00004216 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00004217
4218 def test_exceptions_in_server_bubble_up(self):
4219 """
4220 The callbacks thrown in the server callback bubble up to the caller.
4221 """
Alex Gaynor03737182020-07-23 20:40:46 -04004222
Cory Benfield496652a2017-01-24 11:42:56 +00004223 class SentinelException(Exception):
4224 pass
4225
4226 def server_callback(*args):
4227 raise SentinelException()
4228
Alex Chanfb078d82017-04-20 11:16:15 +01004229 def client_callback(*args): # pragma: nocover
Cory Benfield496652a2017-01-24 11:42:56 +00004230 pytest.fail("Should not be called")
4231
4232 client = self._client_connection(callback=client_callback, data=None)
4233 server = self._server_connection(callback=server_callback, data=None)
4234
4235 with pytest.raises(SentinelException):
Alex Chanb7480992017-01-30 14:04:47 +00004236 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00004237
4238 def test_server_must_return_bytes(self):
4239 """
4240 The server callback must return a bytestring, or a TypeError is thrown.
4241 """
Alex Gaynor03737182020-07-23 20:40:46 -04004242
Cory Benfield496652a2017-01-24 11:42:56 +00004243 def server_callback(*args):
Alex Gaynor03737182020-07-23 20:40:46 -04004244 return self.sample_ocsp_data.decode("ascii")
Cory Benfield496652a2017-01-24 11:42:56 +00004245
Alex Chanfb078d82017-04-20 11:16:15 +01004246 def client_callback(*args): # pragma: nocover
Cory Benfield496652a2017-01-24 11:42:56 +00004247 pytest.fail("Should not be called")
4248
4249 client = self._client_connection(callback=client_callback, data=None)
4250 server = self._server_connection(callback=server_callback, data=None)
4251
4252 with pytest.raises(TypeError):
Alex Chanb7480992017-01-30 14:04:47 +00004253 handshake_in_memory(client, server)