blob: a08759fa98e30f1b0698d4ea9331b8a4ad0aabe9 [file] [log] [blame]
Jean-Paul Calderone8671c852011-03-02 19:26:20 -05001# Copyright (C) Jean-Paul Calderone
2# See LICENSE for details.
Jean-Paul Calderone8b63d452008-03-21 18:31:12 -04003
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -04004"""
Hynek Schlawackf90e3682016-03-11 11:21:13 +01005Unit tests for :mod:`OpenSSL.SSL`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -04006"""
7
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01008import datetime
Maximilian Hils868dc3c2017-02-10 14:56:55 +01009import sys
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +010010import uuid
11
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -050012from gc import collect, get_referrers
David Benjamin1fbe0642019-04-15 17:05:13 -050013from errno import (
Alex Gaynor03737182020-07-23 20:40:46 -040014 EAFNOSUPPORT,
15 ECONNREFUSED,
16 EINPROGRESS,
17 EWOULDBLOCK,
18 EPIPE,
19 ESHUTDOWN,
20)
Jeremy Lainé1ae7cb62018-03-21 14:49:42 +010021from sys import platform, getfilesystemencoding
David Benjamin1fbe0642019-04-15 17:05:13 -050022from socket import AF_INET, AF_INET6, MSG_PEEK, SHUT_RDWR, error, socket
Jean-Paul Calderonea65cf6c2009-07-19 10:26:52 -040023from os import makedirs
Jean-Paul Calderone1461c492013-10-03 16:05:00 -040024from os.path import join
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -040025from weakref import ref
Alex Chanb7480992017-01-30 14:04:47 +000026from warnings import simplefilter
Jean-Paul Calderone460cc1f2009-03-07 11:31:12 -050027
Alex Gaynor963ae032019-07-06 17:38:32 -040028import flaky
29
Hynek Schlawack734d3022015-09-05 19:19:32 +020030import pytest
31
Paul Kehrer55fb3412017-06-29 18:44:08 -050032from pretend import raiser
33
Hugo van Kemenade60827f82019-08-30 00:39:35 +030034from six import PY2, text_type
Jean-Paul Calderonec76c61c2014-01-18 13:21:52 -050035
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +010036from cryptography import x509
37from cryptography.hazmat.backends import default_backend
38from cryptography.hazmat.primitives import hashes
39from cryptography.hazmat.primitives import serialization
40from cryptography.hazmat.primitives.asymmetric import rsa
41from cryptography.x509.oid import NameOID
42
43
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040044from OpenSSL.crypto import TYPE_RSA, FILETYPE_PEM
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -080045from OpenSSL.crypto import PKey, X509, X509Extension, X509Store
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040046from OpenSSL.crypto import dump_privatekey, load_privatekey
47from OpenSSL.crypto import dump_certificate, load_certificate
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -040048from OpenSSL.crypto import get_elliptic_curves
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040049
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -040050from OpenSSL.SSL import OPENSSL_VERSION_NUMBER, SSLEAY_VERSION, SSLEAY_CFLAGS
51from OpenSSL.SSL import SSLEAY_PLATFORM, SSLEAY_DIR, SSLEAY_BUILT_ON
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -040052from OpenSSL.SSL import SENT_SHUTDOWN, RECEIVED_SHUTDOWN
Jean-Paul Calderone1461c492013-10-03 16:05:00 -040053from OpenSSL.SSL import (
Alex Gaynor03737182020-07-23 20:40:46 -040054 SSLv2_METHOD,
55 SSLv3_METHOD,
56 SSLv23_METHOD,
57 TLSv1_METHOD,
58 TLSv1_1_METHOD,
59 TLSv1_2_METHOD,
60)
Jean-Paul Calderone1461c492013-10-03 16:05:00 -040061from OpenSSL.SSL import OP_SINGLE_DH_USE, OP_NO_SSLv2, OP_NO_SSLv3
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040062from OpenSSL.SSL import (
Alex Gaynor03737182020-07-23 20:40:46 -040063 VERIFY_PEER,
64 VERIFY_FAIL_IF_NO_PEER_CERT,
65 VERIFY_CLIENT_ONCE,
66 VERIFY_NONE,
67)
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040068
Paul Kehrer55fb3412017-06-29 18:44:08 -050069from OpenSSL import SSL
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040070from OpenSSL.SSL import (
Alex Gaynor03737182020-07-23 20:40:46 -040071 SESS_CACHE_OFF,
72 SESS_CACHE_CLIENT,
73 SESS_CACHE_SERVER,
74 SESS_CACHE_BOTH,
75 SESS_CACHE_NO_AUTO_CLEAR,
76 SESS_CACHE_NO_INTERNAL_LOOKUP,
77 SESS_CACHE_NO_INTERNAL_STORE,
78 SESS_CACHE_NO_INTERNAL,
79)
Jean-Paul Calderone313bf012012-02-08 13:02:49 -050080
81from OpenSSL.SSL import (
Alex Gaynor03737182020-07-23 20:40:46 -040082 Error,
83 SysCallError,
84 WantReadError,
85 WantWriteError,
86 ZeroReturnError,
87)
88from OpenSSL.SSL import Context, Session, Connection, SSLeay_version
Cory Benfield0ba57ec2016-03-30 09:35:05 +010089from OpenSSL.SSL import _make_requires
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040090
Paul Kehrer55fb3412017-06-29 18:44:08 -050091from OpenSSL._util import ffi as _ffi, lib as _lib
Cory Benfieldba1820d2015-04-13 17:39:12 -040092
Alex Gaynord3b5d9b2016-07-31 10:54:24 -040093from OpenSSL.SSL import (
Alex Gaynor03737182020-07-23 20:40:46 -040094 OP_NO_QUERY_MTU,
95 OP_COOKIE_EXCHANGE,
96 OP_NO_TICKET,
97 OP_NO_COMPRESSION,
98 MODE_RELEASE_BUFFERS,
99 NO_OVERLAPPING_PROTOCOLS,
100)
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400101
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -0400102from OpenSSL.SSL import (
Alex Gaynor03737182020-07-23 20:40:46 -0400103 SSL_ST_CONNECT,
104 SSL_ST_ACCEPT,
105 SSL_ST_MASK,
106 SSL_CB_LOOP,
107 SSL_CB_EXIT,
108 SSL_CB_READ,
109 SSL_CB_WRITE,
110 SSL_CB_ALERT,
111 SSL_CB_READ_ALERT,
112 SSL_CB_WRITE_ALERT,
113 SSL_CB_ACCEPT_LOOP,
114 SSL_CB_ACCEPT_EXIT,
115 SSL_CB_CONNECT_LOOP,
116 SSL_CB_CONNECT_EXIT,
117 SSL_CB_HANDSHAKE_START,
118 SSL_CB_HANDSHAKE_DONE,
119)
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400120
Alex Gaynor5af32d02016-09-24 01:52:21 -0400121try:
122 from OpenSSL.SSL import (
Alex Gaynor03737182020-07-23 20:40:46 -0400123 SSL_ST_INIT,
124 SSL_ST_BEFORE,
125 SSL_ST_OK,
126 SSL_ST_RENEGOTIATE,
Alex Gaynor5af32d02016-09-24 01:52:21 -0400127 )
128except ImportError:
129 SSL_ST_INIT = SSL_ST_BEFORE = SSL_ST_OK = SSL_ST_RENEGOTIATE = None
130
Alex Chanb7480992017-01-30 14:04:47 +0000131from .util import WARNING_TYPE_EXPECTED, NON_ASCII, is_consistent_type
Hynek Schlawackf0e66852015-10-16 20:18:38 +0200132from .test_crypto import (
Alex Gaynor03737182020-07-23 20:40:46 -0400133 cleartextCertificatePEM,
134 cleartextPrivateKeyPEM,
135 client_cert_pem,
136 client_key_pem,
137 server_cert_pem,
138 server_key_pem,
139 root_cert_pem,
140)
Hynek Schlawackf0e66852015-10-16 20:18:38 +0200141
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200142
Alex Gaynord0bdd2d2016-09-10 14:23:46 -0400143# openssl dhparam 1024 -out dh-1024.pem (note that 1024 is a small number of
144# bits to use)
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -0400145dhparam = """\
146-----BEGIN DH PARAMETERS-----
Alex Gaynord0bdd2d2016-09-10 14:23:46 -0400147MIGHAoGBALdUMvn+C9MM+y5BWZs11mSeH6HHoEq0UVbzVq7UojC1hbsZUuGukQ3a
148Qh2/pwqb18BZFykrWB0zv/OkLa0kx4cuUgNrUVq1EFheBiX6YqryJ7t2sO09NQiO
149V7H54LmltOT/hEh6QWsJqb6BQgH65bswvV/XkYGja8/T0GzvbaVzAgEC
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -0400150-----END DH PARAMETERS-----
151"""
152
153
Hugo van Kemenade60827f82019-08-30 00:39:35 +0300154skip_if_py3 = pytest.mark.skipif(not PY2, reason="Python 2 only")
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200155
156
David Benjamin1fbe0642019-04-15 17:05:13 -0500157def socket_any_family():
158 try:
159 return socket(AF_INET)
160 except error as e:
161 if e.errno == EAFNOSUPPORT:
162 return socket(AF_INET6)
163 raise
164
165
166def loopback_address(socket):
167 if socket.family == AF_INET:
168 return "127.0.0.1"
169 else:
170 assert socket.family == AF_INET6
171 return "::1"
172
173
Jean-Paul Calderone05826732015-04-12 11:38:49 -0400174def join_bytes_or_unicode(prefix, suffix):
175 """
176 Join two path components of either ``bytes`` or ``unicode``.
177
178 The return type is the same as the type of ``prefix``.
179 """
180 # If the types are the same, nothing special is necessary.
181 if type(prefix) == type(suffix):
182 return join(prefix, suffix)
183
184 # Otherwise, coerce suffix to the type of prefix.
185 if isinstance(prefix, text_type):
186 return join(prefix, suffix.decode(getfilesystemencoding()))
187 else:
188 return join(prefix, suffix.encode(getfilesystemencoding()))
189
190
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400191def verify_cb(conn, cert, errnum, depth, ok):
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400192 return ok
193
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400194
Rick Deanb1ccd562009-07-09 23:52:39 -0500195def socket_pair():
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400196 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400197 Establish and return a pair of network sockets connected to each other.
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400198 """
199 # Connect a pair of sockets
David Benjamin1fbe0642019-04-15 17:05:13 -0500200 port = socket_any_family()
Alex Gaynor03737182020-07-23 20:40:46 -0400201 port.bind(("", 0))
Rick Deanb1ccd562009-07-09 23:52:39 -0500202 port.listen(1)
David Benjamin1fbe0642019-04-15 17:05:13 -0500203 client = socket(port.family)
Rick Deanb1ccd562009-07-09 23:52:39 -0500204 client.setblocking(False)
David Benjamin1fbe0642019-04-15 17:05:13 -0500205 client.connect_ex((loopback_address(port), port.getsockname()[1]))
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400206 client.setblocking(True)
Rick Deanb1ccd562009-07-09 23:52:39 -0500207 server = port.accept()[0]
Rick Deanb1ccd562009-07-09 23:52:39 -0500208
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400209 # Let's pass some unencrypted data to make sure our socket connection is
210 # fine. Just one byte, so we don't have to worry about buffers getting
211 # filled up or fragmentation.
Alex Gaynore7f51982016-09-11 11:48:14 -0400212 server.send(b"x")
213 assert client.recv(1024) == b"x"
214 client.send(b"y")
215 assert server.recv(1024) == b"y"
Rick Deanb1ccd562009-07-09 23:52:39 -0500216
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -0400217 # Most of our callers want non-blocking sockets, make it easy for them.
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400218 server.setblocking(False)
219 client.setblocking(False)
Jim Shaver46f28912015-05-29 19:32:16 -0400220
Rick Deanb1ccd562009-07-09 23:52:39 -0500221 return (server, client)
222
223
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400224def handshake(client, server):
225 conns = [client, server]
226 while conns:
227 for conn in conns:
228 try:
229 conn.do_handshake()
230 except WantReadError:
231 pass
232 else:
233 conns.remove(conn)
234
235
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400236def _create_certificate_chain():
237 """
238 Construct and return a chain of certificates.
239
240 1. A new self-signed certificate authority certificate (cacert)
241 2. A new intermediate certificate signed by cacert (icert)
242 3. A new server certificate signed by icert (scert)
243 """
Alex Gaynor03737182020-07-23 20:40:46 -0400244 caext = X509Extension(b"basicConstraints", False, b"CA:true")
245 not_after_date = datetime.date.today() + datetime.timedelta(days=365)
Alex Gaynor675534c2020-01-12 11:59:49 -0600246 not_after = not_after_date.strftime("%Y%m%d%H%M%SZ").encode("ascii")
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400247
248 # Step 1
249 cakey = PKey()
Alex Gaynor0737a5e2016-09-10 14:35:09 -0400250 cakey.generate_key(TYPE_RSA, 1024)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400251 cacert = X509()
David Benjamin6b799472020-06-24 17:14:16 -0400252 cacert.set_version(2)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400253 cacert.get_subject().commonName = "Authority Certificate"
254 cacert.set_issuer(cacert.get_subject())
255 cacert.set_pubkey(cakey)
Alex Gaynore7f51982016-09-11 11:48:14 -0400256 cacert.set_notBefore(b"20000101000000Z")
Alex Gaynor675534c2020-01-12 11:59:49 -0600257 cacert.set_notAfter(not_after)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400258 cacert.add_extensions([caext])
259 cacert.set_serial_number(0)
260 cacert.sign(cakey, "sha1")
261
262 # Step 2
263 ikey = PKey()
Alex Gaynor0737a5e2016-09-10 14:35:09 -0400264 ikey.generate_key(TYPE_RSA, 1024)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400265 icert = X509()
David Benjamin6b799472020-06-24 17:14:16 -0400266 icert.set_version(2)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400267 icert.get_subject().commonName = "Intermediate Certificate"
268 icert.set_issuer(cacert.get_subject())
269 icert.set_pubkey(ikey)
Alex Gaynore7f51982016-09-11 11:48:14 -0400270 icert.set_notBefore(b"20000101000000Z")
Alex Gaynor675534c2020-01-12 11:59:49 -0600271 icert.set_notAfter(not_after)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400272 icert.add_extensions([caext])
273 icert.set_serial_number(0)
274 icert.sign(cakey, "sha1")
275
276 # Step 3
277 skey = PKey()
Alex Gaynor0737a5e2016-09-10 14:35:09 -0400278 skey.generate_key(TYPE_RSA, 1024)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400279 scert = X509()
David Benjamin6b799472020-06-24 17:14:16 -0400280 scert.set_version(2)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400281 scert.get_subject().commonName = "Server Certificate"
282 scert.set_issuer(icert.get_subject())
283 scert.set_pubkey(skey)
Alex Gaynore7f51982016-09-11 11:48:14 -0400284 scert.set_notBefore(b"20000101000000Z")
Alex Gaynor675534c2020-01-12 11:59:49 -0600285 scert.set_notAfter(not_after)
Alex Gaynor03737182020-07-23 20:40:46 -0400286 scert.add_extensions(
287 [X509Extension(b"basicConstraints", True, b"CA:false")]
288 )
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400289 scert.set_serial_number(0)
290 scert.sign(ikey, "sha1")
291
292 return [(cakey, cacert), (ikey, icert), (skey, scert)]
293
294
Paul Kehrer7d5a3bf2019-01-21 12:24:02 -0600295def loopback_client_factory(socket, version=SSLv23_METHOD):
296 client = Connection(Context(version), socket)
Alex Chan1c0cb662017-01-30 07:13:30 +0000297 client.set_connect_state()
298 return client
299
300
Paul Kehrer7d5a3bf2019-01-21 12:24:02 -0600301def loopback_server_factory(socket, version=SSLv23_METHOD):
302 ctx = Context(version)
Alex Chan1c0cb662017-01-30 07:13:30 +0000303 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
304 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
305 server = Connection(ctx, socket)
306 server.set_accept_state()
307 return server
308
309
310def loopback(server_factory=None, client_factory=None):
311 """
312 Create a connected socket pair and force two connected SSL sockets
313 to talk to each other via memory BIOs.
314 """
315 if server_factory is None:
316 server_factory = loopback_server_factory
317 if client_factory is None:
318 client_factory = loopback_client_factory
319
320 (server, client) = socket_pair()
321 server = server_factory(server)
322 client = client_factory(client)
323
324 handshake(client, server)
325
326 server.setblocking(True)
327 client.setblocking(True)
328 return server, client
329
330
Alex Chan1ca9e3a2016-11-05 13:01:51 +0000331def interact_in_memory(client_conn, server_conn):
332 """
333 Try to read application bytes from each of the two `Connection` objects.
334 Copy bytes back and forth between their send/receive buffers for as long
335 as there is anything to copy. When there is nothing more to copy,
336 return `None`. If one of them actually manages to deliver some application
337 bytes, return a two-tuple of the connection from which the bytes were read
338 and the bytes themselves.
339 """
340 wrote = True
341 while wrote:
342 # Loop until neither side has anything to say
343 wrote = False
344
345 # Copy stuff from each side's send buffer to the other side's
346 # receive buffer.
Alex Gaynor03737182020-07-23 20:40:46 -0400347 for (read, write) in [
348 (client_conn, server_conn),
349 (server_conn, client_conn),
350 ]:
Alex Chan1ca9e3a2016-11-05 13:01:51 +0000351
352 # Give the side a chance to generate some more bytes, or succeed.
353 try:
354 data = read.recv(2 ** 16)
355 except WantReadError:
356 # It didn't succeed, so we'll hope it generated some output.
357 pass
358 else:
359 # It did succeed, so we'll stop now and let the caller deal
360 # with it.
361 return (read, data)
362
363 while True:
364 # Keep copying as long as there's more stuff there.
365 try:
366 dirty = read.bio_read(4096)
367 except WantReadError:
368 # Okay, nothing more waiting to be sent. Stop
369 # processing this send buffer.
370 break
371 else:
372 # Keep track of the fact that someone generated some
373 # output.
374 wrote = True
375 write.bio_write(dirty)
376
377
Alex Chan532b79e2017-01-24 15:14:52 +0000378def handshake_in_memory(client_conn, server_conn):
379 """
380 Perform the TLS handshake between two `Connection` instances connected to
381 each other via memory BIOs.
382 """
383 client_conn.set_connect_state()
384 server_conn.set_accept_state()
385
386 for conn in [client_conn, server_conn]:
387 try:
388 conn.do_handshake()
389 except WantReadError:
390 pass
391
392 interact_in_memory(client_conn, server_conn)
393
394
Alex Chanb7480992017-01-30 14:04:47 +0000395class TestVersion(object):
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400396 """
Alex Chanb7480992017-01-30 14:04:47 +0000397 Tests for version information exposed by `OpenSSL.SSL.SSLeay_version` and
398 `OpenSSL.SSL.OPENSSL_VERSION_NUMBER`.
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400399 """
Alex Gaynor03737182020-07-23 20:40:46 -0400400
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400401 def test_OPENSSL_VERSION_NUMBER(self):
402 """
Alex Chanb7480992017-01-30 14:04:47 +0000403 `OPENSSL_VERSION_NUMBER` is an integer with status in the low byte and
404 the patch, fix, minor, and major versions in the nibbles above that.
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400405 """
Alex Chanb7480992017-01-30 14:04:47 +0000406 assert isinstance(OPENSSL_VERSION_NUMBER, int)
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400407
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400408 def test_SSLeay_version(self):
409 """
Alex Chanb7480992017-01-30 14:04:47 +0000410 `SSLeay_version` takes a version type indicator and returns one of a
411 number of version strings based on that indicator.
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400412 """
413 versions = {}
Alex Gaynor03737182020-07-23 20:40:46 -0400414 for t in [
415 SSLEAY_VERSION,
416 SSLEAY_CFLAGS,
417 SSLEAY_BUILT_ON,
418 SSLEAY_PLATFORM,
419 SSLEAY_DIR,
420 ]:
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400421 version = SSLeay_version(t)
422 versions[version] = t
Alex Chanb7480992017-01-30 14:04:47 +0000423 assert isinstance(version, bytes)
424 assert len(versions) == 5
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400425
426
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100427@pytest.fixture
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100428def ca_file(tmpdir):
429 """
430 Create a valid PEM file with CA certificates and return the path.
431 """
432 key = rsa.generate_private_key(
Alex Gaynor03737182020-07-23 20:40:46 -0400433 public_exponent=65537, key_size=2048, backend=default_backend()
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100434 )
435 public_key = key.public_key()
436
437 builder = x509.CertificateBuilder()
Alex Gaynor03737182020-07-23 20:40:46 -0400438 builder = builder.subject_name(
439 x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, u"pyopenssl.org")])
440 )
441 builder = builder.issuer_name(
442 x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, u"pyopenssl.org")])
443 )
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100444 one_day = datetime.timedelta(1, 0, 0)
445 builder = builder.not_valid_before(datetime.datetime.today() - one_day)
446 builder = builder.not_valid_after(datetime.datetime.today() + one_day)
447 builder = builder.serial_number(int(uuid.uuid4()))
448 builder = builder.public_key(public_key)
449 builder = builder.add_extension(
450 x509.BasicConstraints(ca=True, path_length=None), critical=True,
451 )
452
453 certificate = builder.sign(
Alex Gaynor03737182020-07-23 20:40:46 -0400454 private_key=key, algorithm=hashes.SHA256(), backend=default_backend()
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100455 )
456
457 ca_file = tmpdir.join("test.pem")
458 ca_file.write_binary(
Alex Gaynor03737182020-07-23 20:40:46 -0400459 certificate.public_bytes(encoding=serialization.Encoding.PEM,)
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100460 )
461
462 return str(ca_file).encode("ascii")
463
464
465@pytest.fixture
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100466def context():
467 """
468 A simple TLS 1.0 context.
469 """
470 return Context(TLSv1_METHOD)
471
472
473class TestContext(object):
Hynek Schlawackaa861212016-03-13 13:53:48 +0100474 """
Alex Chan532b79e2017-01-24 15:14:52 +0000475 Unit tests for `OpenSSL.SSL.Context`.
Hynek Schlawackaa861212016-03-13 13:53:48 +0100476 """
Alex Gaynor03737182020-07-23 20:40:46 -0400477
478 @pytest.mark.parametrize(
479 "cipher_string",
480 [b"hello world:AES128-SHA", u"hello world:AES128-SHA"],
481 )
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100482 def test_set_cipher_list(self, context, cipher_string):
483 """
Alex Chan532b79e2017-01-24 15:14:52 +0000484 `Context.set_cipher_list` accepts both byte and unicode strings
Hynek Schlawacka7a63af2016-03-11 12:05:26 +0100485 for naming the ciphers which connections created with the context
486 object will be able to choose from.
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100487 """
488 context.set_cipher_list(cipher_string)
489 conn = Connection(context, None)
490
491 assert "AES128-SHA" in conn.get_cipher_list()
492
Mark Williamsdf2480d2019-02-14 19:30:07 -0800493 def test_set_cipher_list_wrong_type(self, context):
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100494 """
Alex Chan532b79e2017-01-24 15:14:52 +0000495 `Context.set_cipher_list` raises `TypeError` when passed a non-string
Mark Williamsdf2480d2019-02-14 19:30:07 -0800496 argument.
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100497 """
Mark Williamsdf2480d2019-02-14 19:30:07 -0800498 with pytest.raises(TypeError):
499 context.set_cipher_list(object())
500
Alex Gaynor963ae032019-07-06 17:38:32 -0400501 @flaky.flaky
Mark Williamsdf2480d2019-02-14 19:30:07 -0800502 def test_set_cipher_list_no_cipher_match(self, context):
503 """
504 `Context.set_cipher_list` raises `OpenSSL.SSL.Error` with a
505 `"no cipher match"` reason string regardless of the TLS
506 version.
507 """
508 with pytest.raises(Error) as excinfo:
509 context.set_cipher_list(b"imaginary-cipher")
510 assert excinfo.value.args == (
Alex Gaynor03737182020-07-23 20:40:46 -0400511 [("SSL routines", "SSL_CTX_set_cipher_list", "no cipher match",)],
512 )
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100513
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100514 def test_load_client_ca(self, context, ca_file):
515 """
Alex Chan532b79e2017-01-24 15:14:52 +0000516 `Context.load_client_ca` works as far as we can tell.
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100517 """
518 context.load_client_ca(ca_file)
519
520 def test_load_client_ca_invalid(self, context, tmpdir):
521 """
Alex Chan532b79e2017-01-24 15:14:52 +0000522 `Context.load_client_ca` raises an Error if the ca file is invalid.
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100523 """
524 ca_file = tmpdir.join("test.pem")
525 ca_file.write("")
526
527 with pytest.raises(Error) as e:
528 context.load_client_ca(str(ca_file).encode("ascii"))
529
530 assert "PEM routines" == e.value.args[0][0][0]
531
532 def test_load_client_ca_unicode(self, context, ca_file):
533 """
534 Passing the path as unicode raises a warning but works.
535 """
Alex Gaynor03737182020-07-23 20:40:46 -0400536 pytest.deprecated_call(context.load_client_ca, ca_file.decode("ascii"))
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100537
538 def test_set_session_id(self, context):
539 """
Alex Chan532b79e2017-01-24 15:14:52 +0000540 `Context.set_session_id` works as far as we can tell.
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100541 """
542 context.set_session_id(b"abc")
543
544 def test_set_session_id_fail(self, context):
545 """
Alex Chan532b79e2017-01-24 15:14:52 +0000546 `Context.set_session_id` errors are propagated.
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100547 """
548 with pytest.raises(Error) as e:
549 context.set_session_id(b"abc" * 1000)
550
551 assert [
Alex Gaynor03737182020-07-23 20:40:46 -0400552 (
553 "SSL routines",
554 "SSL_CTX_set_session_id_context",
555 "ssl session id context too long",
556 )
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100557 ] == e.value.args[0]
558
559 def test_set_session_id_unicode(self, context):
560 """
Alex Chan532b79e2017-01-24 15:14:52 +0000561 `Context.set_session_id` raises a warning if a unicode string is
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100562 passed.
563 """
564 pytest.deprecated_call(context.set_session_id, u"abc")
565
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400566 def test_method(self):
567 """
Alex Chan532b79e2017-01-24 15:14:52 +0000568 `Context` can be instantiated with one of `SSLv2_METHOD`,
569 `SSLv3_METHOD`, `SSLv23_METHOD`, `TLSv1_METHOD`, `TLSv1_1_METHOD`,
570 or `TLSv1_2_METHOD`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400571 """
Alex Gaynor5af32d02016-09-24 01:52:21 -0400572 methods = [SSLv23_METHOD, TLSv1_METHOD]
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400573 for meth in methods:
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400574 Context(meth)
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400575
Alex Gaynor5af32d02016-09-24 01:52:21 -0400576 maybe = [SSLv2_METHOD, SSLv3_METHOD, TLSv1_1_METHOD, TLSv1_2_METHOD]
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400577 for meth in maybe:
578 try:
579 Context(meth)
580 except (Error, ValueError):
581 # Some versions of OpenSSL have SSLv2 / TLSv1.1 / TLSv1.2, some
582 # don't. Difficult to say in advance.
583 pass
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400584
Alex Chan532b79e2017-01-24 15:14:52 +0000585 with pytest.raises(TypeError):
586 Context("")
587 with pytest.raises(ValueError):
588 Context(10)
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400589
Rick Deane15b1472009-07-09 15:53:42 -0500590 def test_type(self):
591 """
Alex Gaynor01f90a12019-02-07 09:14:48 -0500592 `Context` can be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -0500593 """
Alex Gaynor03737182020-07-23 20:40:46 -0400594 assert is_consistent_type(Context, "Context", TLSv1_METHOD)
Rick Deane15b1472009-07-09 15:53:42 -0500595
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400596 def test_use_privatekey(self):
597 """
Alex Chan532b79e2017-01-24 15:14:52 +0000598 `Context.use_privatekey` takes an `OpenSSL.crypto.PKey` instance.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400599 """
600 key = PKey()
Alex Gaynor6e9f9762018-05-12 07:44:37 -0400601 key.generate_key(TYPE_RSA, 512)
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400602 ctx = Context(TLSv1_METHOD)
603 ctx.use_privatekey(key)
Alex Chan532b79e2017-01-24 15:14:52 +0000604 with pytest.raises(TypeError):
605 ctx.use_privatekey("")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400606
Alex Chan532b79e2017-01-24 15:14:52 +0000607 def test_use_privatekey_file_missing(self, tmpfile):
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800608 """
Alex Chan532b79e2017-01-24 15:14:52 +0000609 `Context.use_privatekey_file` raises `OpenSSL.SSL.Error` when passed
610 the name of a file which does not exist.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800611 """
612 ctx = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000613 with pytest.raises(Error):
614 ctx.use_privatekey_file(tmpfile)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800615
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400616 def _use_privatekey_file_test(self, pemfile, filetype):
617 """
618 Verify that calling ``Context.use_privatekey_file`` with the given
619 arguments does not raise an exception.
620 """
621 key = PKey()
Alex Gaynor6e9f9762018-05-12 07:44:37 -0400622 key.generate_key(TYPE_RSA, 512)
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400623
624 with open(pemfile, "wt") as pem:
Alex Gaynor03737182020-07-23 20:40:46 -0400625 pem.write(dump_privatekey(FILETYPE_PEM, key).decode("ascii"))
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400626
627 ctx = Context(TLSv1_METHOD)
628 ctx.use_privatekey_file(pemfile, filetype)
629
Alex Gaynor03737182020-07-23 20:40:46 -0400630 @pytest.mark.parametrize("filetype", [object(), "", None, 1.0])
Alex Chanfb078d82017-04-20 11:16:15 +0100631 def test_wrong_privatekey_file_wrong_args(self, tmpfile, filetype):
632 """
633 `Context.use_privatekey_file` raises `TypeError` when called with
634 a `filetype` which is not a valid file encoding.
635 """
636 ctx = Context(TLSv1_METHOD)
637 with pytest.raises(TypeError):
638 ctx.use_privatekey_file(tmpfile, filetype)
639
Alex Chan532b79e2017-01-24 15:14:52 +0000640 def test_use_privatekey_file_bytes(self, tmpfile):
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400641 """
642 A private key can be specified from a file by passing a ``bytes``
643 instance giving the file name to ``Context.use_privatekey_file``.
644 """
645 self._use_privatekey_file_test(
Alex Gaynor03737182020-07-23 20:40:46 -0400646 tmpfile + NON_ASCII.encode(getfilesystemencoding()), FILETYPE_PEM,
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400647 )
648
Alex Chan532b79e2017-01-24 15:14:52 +0000649 def test_use_privatekey_file_unicode(self, tmpfile):
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400650 """
651 A private key can be specified from a file by passing a ``unicode``
652 instance giving the file name to ``Context.use_privatekey_file``.
653 """
654 self._use_privatekey_file_test(
Alex Gaynor03737182020-07-23 20:40:46 -0400655 tmpfile.decode(getfilesystemencoding()) + NON_ASCII, FILETYPE_PEM,
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400656 )
657
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800658 def test_use_certificate_wrong_args(self):
659 """
Alex Chan532b79e2017-01-24 15:14:52 +0000660 `Context.use_certificate_wrong_args` raises `TypeError` when not passed
661 exactly one `OpenSSL.crypto.X509` instance as an argument.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800662 """
663 ctx = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000664 with pytest.raises(TypeError):
665 ctx.use_certificate("hello, world")
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800666
667 def test_use_certificate_uninitialized(self):
668 """
Alex Chan532b79e2017-01-24 15:14:52 +0000669 `Context.use_certificate` raises `OpenSSL.SSL.Error` when passed a
670 `OpenSSL.crypto.X509` instance which has not been initialized
671 (ie, which does not actually have any certificate data).
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800672 """
673 ctx = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000674 with pytest.raises(Error):
675 ctx.use_certificate(X509())
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800676
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800677 def test_use_certificate(self):
678 """
Alex Chan532b79e2017-01-24 15:14:52 +0000679 `Context.use_certificate` sets the certificate which will be
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800680 used to identify connections created using the context.
681 """
682 # TODO
683 # Hard to assert anything. But we could set a privatekey then ask
684 # OpenSSL if the cert and key agree using check_privatekey. Then as
685 # long as check_privatekey works right we're good...
686 ctx = Context(TLSv1_METHOD)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200687 ctx.use_certificate(
688 load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
689 )
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800690
691 def test_use_certificate_file_wrong_args(self):
692 """
Alex Chan532b79e2017-01-24 15:14:52 +0000693 `Context.use_certificate_file` raises `TypeError` if the first
694 argument is not a byte string or the second argument is not an integer.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800695 """
696 ctx = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000697 with pytest.raises(TypeError):
698 ctx.use_certificate_file(object(), FILETYPE_PEM)
699 with pytest.raises(TypeError):
700 ctx.use_certificate_file(b"somefile", object())
701 with pytest.raises(TypeError):
702 ctx.use_certificate_file(object(), FILETYPE_PEM)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800703
Alex Chan532b79e2017-01-24 15:14:52 +0000704 def test_use_certificate_file_missing(self, tmpfile):
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800705 """
Alex Chan532b79e2017-01-24 15:14:52 +0000706 `Context.use_certificate_file` raises `OpenSSL.SSL.Error` if passed
707 the name of a file which does not exist.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800708 """
709 ctx = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000710 with pytest.raises(Error):
711 ctx.use_certificate_file(tmpfile)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800712
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400713 def _use_certificate_file_test(self, certificate_file):
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800714 """
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400715 Verify that calling ``Context.use_certificate_file`` with the given
716 filename doesn't raise an exception.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800717 """
718 # TODO
719 # Hard to assert anything. But we could set a privatekey then ask
720 # OpenSSL if the cert and key agree using check_privatekey. Then as
721 # long as check_privatekey works right we're good...
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400722 with open(certificate_file, "wb") as pem_file:
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800723 pem_file.write(cleartextCertificatePEM)
724
725 ctx = Context(TLSv1_METHOD)
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400726 ctx.use_certificate_file(certificate_file)
727
Alex Chan532b79e2017-01-24 15:14:52 +0000728 def test_use_certificate_file_bytes(self, tmpfile):
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400729 """
Alex Chan532b79e2017-01-24 15:14:52 +0000730 `Context.use_certificate_file` sets the certificate (given as a
731 `bytes` filename) which will be used to identify connections created
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400732 using the context.
733 """
Alex Chan532b79e2017-01-24 15:14:52 +0000734 filename = tmpfile + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400735 self._use_certificate_file_test(filename)
736
Alex Chan532b79e2017-01-24 15:14:52 +0000737 def test_use_certificate_file_unicode(self, tmpfile):
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400738 """
Alex Chan532b79e2017-01-24 15:14:52 +0000739 `Context.use_certificate_file` sets the certificate (given as a
740 `bytes` filename) which will be used to identify connections created
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400741 using the context.
742 """
Alex Chan532b79e2017-01-24 15:14:52 +0000743 filename = tmpfile.decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400744 self._use_certificate_file_test(filename)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800745
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500746 def test_check_privatekey_valid(self):
747 """
Alex Chan532b79e2017-01-24 15:14:52 +0000748 `Context.check_privatekey` returns `None` if the `Context` instance
749 has been configured to use a matched key and certificate pair.
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500750 """
751 key = load_privatekey(FILETYPE_PEM, client_key_pem)
752 cert = load_certificate(FILETYPE_PEM, client_cert_pem)
753 context = Context(TLSv1_METHOD)
754 context.use_privatekey(key)
755 context.use_certificate(cert)
Alex Chan532b79e2017-01-24 15:14:52 +0000756 assert None is context.check_privatekey()
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500757
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500758 def test_check_privatekey_invalid(self):
759 """
Alex Chan532b79e2017-01-24 15:14:52 +0000760 `Context.check_privatekey` raises `Error` if the `Context` instance
761 has been configured to use a key and certificate pair which don't
762 relate to each other.
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500763 """
764 key = load_privatekey(FILETYPE_PEM, client_key_pem)
765 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
766 context = Context(TLSv1_METHOD)
767 context.use_privatekey(key)
768 context.use_certificate(cert)
Alex Chan532b79e2017-01-24 15:14:52 +0000769 with pytest.raises(Error):
770 context.check_privatekey()
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400771
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400772 def test_app_data(self):
773 """
Alex Chan532b79e2017-01-24 15:14:52 +0000774 `Context.set_app_data` stores an object for later retrieval
775 using `Context.get_app_data`.
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400776 """
777 app_data = object()
778 context = Context(TLSv1_METHOD)
779 context.set_app_data(app_data)
Alex Chan532b79e2017-01-24 15:14:52 +0000780 assert context.get_app_data() is app_data
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400781
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400782 def test_set_options_wrong_args(self):
783 """
Alex Chan532b79e2017-01-24 15:14:52 +0000784 `Context.set_options` raises `TypeError` if called with
785 a non-`int` argument.
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400786 """
787 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000788 with pytest.raises(TypeError):
789 context.set_options(None)
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400790
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500791 def test_set_options(self):
792 """
Alex Chan532b79e2017-01-24 15:14:52 +0000793 `Context.set_options` returns the new options value.
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500794 """
795 context = Context(TLSv1_METHOD)
796 options = context.set_options(OP_NO_SSLv2)
Alex Gaynor2310f8b2016-09-10 14:39:32 -0400797 assert options & OP_NO_SSLv2 == OP_NO_SSLv2
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500798
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300799 def test_set_mode_wrong_args(self):
800 """
Alex Chan532b79e2017-01-24 15:14:52 +0000801 `Context.set_mode` raises `TypeError` if called with
802 a non-`int` argument.
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300803 """
804 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000805 with pytest.raises(TypeError):
806 context.set_mode(None)
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300807
Alex Gaynord3b5d9b2016-07-31 10:54:24 -0400808 def test_set_mode(self):
809 """
Alex Chan532b79e2017-01-24 15:14:52 +0000810 `Context.set_mode` accepts a mode bitvector and returns the
Alex Gaynord3b5d9b2016-07-31 10:54:24 -0400811 newly set mode.
812 """
813 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000814 assert MODE_RELEASE_BUFFERS & context.set_mode(MODE_RELEASE_BUFFERS)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500815
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400816 def test_set_timeout_wrong_args(self):
817 """
Alex Chan532b79e2017-01-24 15:14:52 +0000818 `Context.set_timeout` raises `TypeError` if called with
819 a non-`int` argument.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400820 """
821 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000822 with pytest.raises(TypeError):
823 context.set_timeout(None)
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400824
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400825 def test_timeout(self):
826 """
Alex Chan532b79e2017-01-24 15:14:52 +0000827 `Context.set_timeout` sets the session timeout for all connections
828 created using the context object. `Context.get_timeout` retrieves
829 this value.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400830 """
831 context = Context(TLSv1_METHOD)
832 context.set_timeout(1234)
Alex Chan532b79e2017-01-24 15:14:52 +0000833 assert context.get_timeout() == 1234
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400834
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400835 def test_set_verify_depth_wrong_args(self):
836 """
Alex Chan532b79e2017-01-24 15:14:52 +0000837 `Context.set_verify_depth` raises `TypeError` if called with a
838 non-`int` argument.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400839 """
840 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000841 with pytest.raises(TypeError):
842 context.set_verify_depth(None)
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400843
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400844 def test_verify_depth(self):
845 """
Alex Chan532b79e2017-01-24 15:14:52 +0000846 `Context.set_verify_depth` sets the number of certificates in
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200847 a chain to follow before giving up. The value can be retrieved with
Alex Chan532b79e2017-01-24 15:14:52 +0000848 `Context.get_verify_depth`.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400849 """
850 context = Context(TLSv1_METHOD)
851 context.set_verify_depth(11)
Alex Chan532b79e2017-01-24 15:14:52 +0000852 assert context.get_verify_depth() == 11
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400853
Alex Chan532b79e2017-01-24 15:14:52 +0000854 def _write_encrypted_pem(self, passphrase, tmpfile):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400855 """
856 Write a new private key out to a new file, encrypted using the given
857 passphrase. Return the path to the new file.
858 """
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400859 key = PKey()
Alex Gaynor6e9f9762018-05-12 07:44:37 -0400860 key.generate_key(TYPE_RSA, 512)
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400861 pem = dump_privatekey(FILETYPE_PEM, key, "blowfish", passphrase)
Alex Gaynor03737182020-07-23 20:40:46 -0400862 with open(tmpfile, "w") as fObj:
863 fObj.write(pem.decode("ascii"))
Alex Chan532b79e2017-01-24 15:14:52 +0000864 return tmpfile
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400865
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400866 def test_set_passwd_cb_wrong_args(self):
867 """
Alex Chan532b79e2017-01-24 15:14:52 +0000868 `Context.set_passwd_cb` raises `TypeError` if called with a
869 non-callable first argument.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400870 """
871 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000872 with pytest.raises(TypeError):
873 context.set_passwd_cb(None)
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400874
Alex Chan532b79e2017-01-24 15:14:52 +0000875 def test_set_passwd_cb(self, tmpfile):
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400876 """
Alex Chan532b79e2017-01-24 15:14:52 +0000877 `Context.set_passwd_cb` accepts a callable which will be invoked when
878 a private key is loaded from an encrypted PEM.
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400879 """
Alex Gaynore7f51982016-09-11 11:48:14 -0400880 passphrase = b"foobar"
Alex Chan532b79e2017-01-24 15:14:52 +0000881 pemFile = self._write_encrypted_pem(passphrase, tmpfile)
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400882 calledWith = []
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200883
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400884 def passphraseCallback(maxlen, verify, extra):
885 calledWith.append((maxlen, verify, extra))
886 return passphrase
Alex Gaynor03737182020-07-23 20:40:46 -0400887
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400888 context = Context(TLSv1_METHOD)
889 context.set_passwd_cb(passphraseCallback)
890 context.use_privatekey_file(pemFile)
Alex Chan532b79e2017-01-24 15:14:52 +0000891 assert len(calledWith) == 1
892 assert isinstance(calledWith[0][0], int)
893 assert isinstance(calledWith[0][1], int)
894 assert calledWith[0][2] is None
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400895
Alex Chan532b79e2017-01-24 15:14:52 +0000896 def test_passwd_callback_exception(self, tmpfile):
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400897 """
Alex Chan532b79e2017-01-24 15:14:52 +0000898 `Context.use_privatekey_file` propagates any exception raised
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200899 by the passphrase callback.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400900 """
Alex Chan532b79e2017-01-24 15:14:52 +0000901 pemFile = self._write_encrypted_pem(b"monkeys are nice", tmpfile)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200902
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400903 def passphraseCallback(maxlen, verify, extra):
904 raise RuntimeError("Sorry, I am a fail.")
905
906 context = Context(TLSv1_METHOD)
907 context.set_passwd_cb(passphraseCallback)
Alex Chan532b79e2017-01-24 15:14:52 +0000908 with pytest.raises(RuntimeError):
909 context.use_privatekey_file(pemFile)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400910
Alex Chan532b79e2017-01-24 15:14:52 +0000911 def test_passwd_callback_false(self, tmpfile):
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400912 """
Alex Chan532b79e2017-01-24 15:14:52 +0000913 `Context.use_privatekey_file` raises `OpenSSL.SSL.Error` if the
914 passphrase callback returns a false value.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400915 """
Alex Chan532b79e2017-01-24 15:14:52 +0000916 pemFile = self._write_encrypted_pem(b"monkeys are nice", tmpfile)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200917
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400918 def passphraseCallback(maxlen, verify, extra):
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500919 return b""
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400920
921 context = Context(TLSv1_METHOD)
922 context.set_passwd_cb(passphraseCallback)
Alex Chan532b79e2017-01-24 15:14:52 +0000923 with pytest.raises(Error):
924 context.use_privatekey_file(pemFile)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400925
Alex Chan532b79e2017-01-24 15:14:52 +0000926 def test_passwd_callback_non_string(self, tmpfile):
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400927 """
Alex Chan532b79e2017-01-24 15:14:52 +0000928 `Context.use_privatekey_file` raises `OpenSSL.SSL.Error` if the
929 passphrase callback returns a true non-string value.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400930 """
Alex Chan532b79e2017-01-24 15:14:52 +0000931 pemFile = self._write_encrypted_pem(b"monkeys are nice", tmpfile)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200932
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400933 def passphraseCallback(maxlen, verify, extra):
934 return 10
935
936 context = Context(TLSv1_METHOD)
937 context.set_passwd_cb(passphraseCallback)
Alex Chan532b79e2017-01-24 15:14:52 +0000938 # TODO: Surely this is the wrong error?
939 with pytest.raises(ValueError):
940 context.use_privatekey_file(pemFile)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400941
Alex Chan532b79e2017-01-24 15:14:52 +0000942 def test_passwd_callback_too_long(self, tmpfile):
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400943 """
944 If the passphrase returned by the passphrase callback returns a string
945 longer than the indicated maximum length, it is truncated.
946 """
947 # A priori knowledge!
Alex Gaynore7f51982016-09-11 11:48:14 -0400948 passphrase = b"x" * 1024
Alex Chan532b79e2017-01-24 15:14:52 +0000949 pemFile = self._write_encrypted_pem(passphrase, tmpfile)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200950
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400951 def passphraseCallback(maxlen, verify, extra):
952 assert maxlen == 1024
Alex Gaynore7f51982016-09-11 11:48:14 -0400953 return passphrase + b"y"
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400954
955 context = Context(TLSv1_METHOD)
956 context.set_passwd_cb(passphraseCallback)
957 # This shall succeed because the truncated result is the correct
958 # passphrase.
959 context.use_privatekey_file(pemFile)
960
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400961 def test_set_info_callback(self):
962 """
Alex Chan532b79e2017-01-24 15:14:52 +0000963 `Context.set_info_callback` accepts a callable which will be
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200964 invoked when certain information about an SSL connection is available.
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400965 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500966 (server, client) = socket_pair()
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400967
968 clientSSL = Connection(Context(TLSv1_METHOD), client)
969 clientSSL.set_connect_state()
970
971 called = []
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200972
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400973 def info(conn, where, ret):
974 called.append((conn, where, ret))
Alex Gaynor03737182020-07-23 20:40:46 -0400975
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400976 context = Context(TLSv1_METHOD)
977 context.set_info_callback(info)
978 context.use_certificate(
Alex Gaynor03737182020-07-23 20:40:46 -0400979 load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
980 )
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400981 context.use_privatekey(
Alex Gaynor03737182020-07-23 20:40:46 -0400982 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
983 )
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400984
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400985 serverSSL = Connection(context, server)
986 serverSSL.set_accept_state()
987
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -0500988 handshake(clientSSL, serverSSL)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400989
Jean-Paul Calderone3835e522014-02-02 11:12:30 -0500990 # The callback must always be called with a Connection instance as the
991 # first argument. It would probably be better to split this into
992 # separate tests for client and server side info callbacks so we could
993 # assert it is called with the right Connection instance. It would
994 # also be good to assert *something* about `where` and `ret`.
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -0500995 notConnections = [
Alex Gaynor03737182020-07-23 20:40:46 -0400996 conn
997 for (conn, where, ret) in called
998 if not isinstance(conn, Connection)
999 ]
1000 assert (
1001 [] == notConnections
1002 ), "Some info callback arguments were not Connection instances."
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001003
Maximilian Hilsb2bca412020-07-28 16:31:22 +02001004 @pytest.mark.skipif(
1005 not getattr(_lib, "Cryptography_HAS_KEYLOG", None),
1006 reason="SSL_CTX_set_keylog_callback unavailable",
1007 )
1008 def test_set_keylog_callback(self):
1009 """
1010 `Context.set_keylog_callback` accepts a callable which will be
1011 invoked when key material is generated or received.
1012 """
1013 called = []
1014
1015 def keylog(conn, line):
1016 called.append((conn, line))
1017
1018 server_context = Context(TLSv1_METHOD)
1019 server_context.set_keylog_callback(keylog)
1020 server_context.use_certificate(
1021 load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
1022 )
1023 server_context.use_privatekey(
1024 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
1025 )
1026
1027 client_context = Context(TLSv1_METHOD)
1028
1029 self._handshake_test(server_context, client_context)
1030
1031 assert called
1032 assert all(isinstance(conn, Connection) for conn, line in called)
1033 assert all(b"CLIENT_RANDOM" in line for conn, line in called)
1034
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001035 def _load_verify_locations_test(self, *args):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001036 """
1037 Create a client context which will verify the peer certificate and call
Alex Chan532b79e2017-01-24 15:14:52 +00001038 its `load_verify_locations` method with the given arguments.
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04001039 Then connect it to a server and ensure that the handshake succeeds.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001040 """
Rick Deanb1ccd562009-07-09 23:52:39 -05001041 (server, client) = socket_pair()
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001042
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001043 clientContext = Context(TLSv1_METHOD)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001044 clientContext.load_verify_locations(*args)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001045 # Require that the server certificate verify properly or the
1046 # connection will fail.
1047 clientContext.set_verify(
1048 VERIFY_PEER,
Alex Gaynor03737182020-07-23 20:40:46 -04001049 lambda conn, cert, errno, depth, preverify_ok: preverify_ok,
1050 )
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001051
1052 clientSSL = Connection(clientContext, client)
1053 clientSSL.set_connect_state()
1054
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001055 serverContext = Context(TLSv1_METHOD)
1056 serverContext.use_certificate(
Alex Gaynor03737182020-07-23 20:40:46 -04001057 load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
1058 )
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001059 serverContext.use_privatekey(
Alex Gaynor03737182020-07-23 20:40:46 -04001060 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
1061 )
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001062
1063 serverSSL = Connection(serverContext, server)
1064 serverSSL.set_accept_state()
1065
Jean-Paul Calderonef8742032010-09-25 00:00:32 -04001066 # Without load_verify_locations above, the handshake
1067 # will fail:
1068 # Error: [('SSL routines', 'SSL3_GET_SERVER_CERTIFICATE',
1069 # 'certificate verify failed')]
1070 handshake(clientSSL, serverSSL)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001071
1072 cert = clientSSL.get_peer_certificate()
Alex Gaynor03737182020-07-23 20:40:46 -04001073 assert cert.get_subject().CN == "Testing Root CA"
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -04001074
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001075 def _load_verify_cafile(self, cafile):
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001076 """
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001077 Verify that if path to a file containing a certificate is passed to
Alex Chan532b79e2017-01-24 15:14:52 +00001078 `Context.load_verify_locations` for the ``cafile`` parameter, that
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001079 certificate is used as a trust root for the purposes of verifying
Alex Chan532b79e2017-01-24 15:14:52 +00001080 connections created using that `Context`.
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001081 """
Alex Gaynor03737182020-07-23 20:40:46 -04001082 with open(cafile, "w") as fObj:
1083 fObj.write(cleartextCertificatePEM.decode("ascii"))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001084
1085 self._load_verify_locations_test(cafile)
1086
Alex Chan532b79e2017-01-24 15:14:52 +00001087 def test_load_verify_bytes_cafile(self, tmpfile):
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001088 """
Alex Chan532b79e2017-01-24 15:14:52 +00001089 `Context.load_verify_locations` accepts a file name as a `bytes`
1090 instance and uses the certificates within for verification purposes.
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001091 """
Alex Chan532b79e2017-01-24 15:14:52 +00001092 cafile = tmpfile + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001093 self._load_verify_cafile(cafile)
1094
Alex Chan532b79e2017-01-24 15:14:52 +00001095 def test_load_verify_unicode_cafile(self, tmpfile):
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001096 """
Alex Chan532b79e2017-01-24 15:14:52 +00001097 `Context.load_verify_locations` accepts a file name as a `unicode`
1098 instance and uses the certificates within for verification purposes.
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001099 """
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001100 self._load_verify_cafile(
Alex Chan532b79e2017-01-24 15:14:52 +00001101 tmpfile.decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001102 )
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001103
Alex Chan532b79e2017-01-24 15:14:52 +00001104 def test_load_verify_invalid_file(self, tmpfile):
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -04001105 """
Alex Chan532b79e2017-01-24 15:14:52 +00001106 `Context.load_verify_locations` raises `Error` when passed a
1107 non-existent cafile.
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -04001108 """
1109 clientContext = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001110 with pytest.raises(Error):
1111 clientContext.load_verify_locations(tmpfile)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001112
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001113 def _load_verify_directory_locations_capath(self, capath):
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001114 """
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001115 Verify that if path to a directory containing certificate files is
1116 passed to ``Context.load_verify_locations`` for the ``capath``
1117 parameter, those certificates are used as trust roots for the purposes
1118 of verifying connections created using that ``Context``.
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001119 """
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001120 makedirs(capath)
Jean-Paul Calderone24dfb332011-05-04 18:10:26 -04001121 # Hash values computed manually with c_rehash to avoid depending on
1122 # c_rehash in the test suite. One is from OpenSSL 0.9.8, the other
1123 # from OpenSSL 1.0.0.
Alex Gaynor03737182020-07-23 20:40:46 -04001124 for name in [b"c7adac82.0", b"c3705638.0"]:
Jean-Paul Calderone05826732015-04-12 11:38:49 -04001125 cafile = join_bytes_or_unicode(capath, name)
Alex Gaynor03737182020-07-23 20:40:46 -04001126 with open(cafile, "w") as fObj:
1127 fObj.write(cleartextCertificatePEM.decode("ascii"))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001128
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001129 self._load_verify_locations_test(None, capath)
1130
Alex Chan532b79e2017-01-24 15:14:52 +00001131 def test_load_verify_directory_bytes_capath(self, tmpfile):
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001132 """
Alex Chan532b79e2017-01-24 15:14:52 +00001133 `Context.load_verify_locations` accepts a directory name as a `bytes`
1134 instance and uses the certificates within for verification purposes.
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001135 """
1136 self._load_verify_directory_locations_capath(
Alex Chan532b79e2017-01-24 15:14:52 +00001137 tmpfile + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001138 )
1139
Alex Chan532b79e2017-01-24 15:14:52 +00001140 def test_load_verify_directory_unicode_capath(self, tmpfile):
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001141 """
Alex Chan532b79e2017-01-24 15:14:52 +00001142 `Context.load_verify_locations` accepts a directory name as a `unicode`
1143 instance and uses the certificates within for verification purposes.
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001144 """
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001145 self._load_verify_directory_locations_capath(
Alex Chan532b79e2017-01-24 15:14:52 +00001146 tmpfile.decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001147 )
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001148
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001149 def test_load_verify_locations_wrong_args(self):
1150 """
Alex Chan532b79e2017-01-24 15:14:52 +00001151 `Context.load_verify_locations` raises `TypeError` if with non-`str`
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001152 arguments.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001153 """
1154 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001155 with pytest.raises(TypeError):
1156 context.load_verify_locations(object())
1157 with pytest.raises(TypeError):
1158 context.load_verify_locations(object(), object())
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001159
Hynek Schlawack734d3022015-09-05 19:19:32 +02001160 @pytest.mark.skipif(
Paul Kehrer55fb3412017-06-29 18:44:08 -05001161 not platform.startswith("linux"),
1162 reason="Loading fallback paths is a linux-specific behavior to "
Alex Gaynor03737182020-07-23 20:40:46 -04001163 "accommodate pyca/cryptography manylinux1 wheels",
Paul Kehrer55fb3412017-06-29 18:44:08 -05001164 )
1165 def test_fallback_default_verify_paths(self, monkeypatch):
1166 """
1167 Test that we load certificates successfully on linux from the fallback
1168 path. To do this we set the _CRYPTOGRAPHY_MANYLINUX1_CA_FILE and
1169 _CRYPTOGRAPHY_MANYLINUX1_CA_DIR vars to be equal to whatever the
1170 current OpenSSL default is and we disable
1171 SSL_CTX_SET_default_verify_paths so that it can't find certs unless
1172 it loads via fallback.
1173 """
1174 context = Context(TLSv1_METHOD)
1175 monkeypatch.setattr(
1176 _lib, "SSL_CTX_set_default_verify_paths", lambda x: 1
1177 )
1178 monkeypatch.setattr(
1179 SSL,
1180 "_CRYPTOGRAPHY_MANYLINUX1_CA_FILE",
Alex Gaynor03737182020-07-23 20:40:46 -04001181 _ffi.string(_lib.X509_get_default_cert_file()),
Paul Kehrer55fb3412017-06-29 18:44:08 -05001182 )
1183 monkeypatch.setattr(
1184 SSL,
1185 "_CRYPTOGRAPHY_MANYLINUX1_CA_DIR",
Alex Gaynor03737182020-07-23 20:40:46 -04001186 _ffi.string(_lib.X509_get_default_cert_dir()),
Paul Kehrer55fb3412017-06-29 18:44:08 -05001187 )
1188 context.set_default_verify_paths()
1189 store = context.get_cert_store()
1190 sk_obj = _lib.X509_STORE_get0_objects(store._store)
1191 assert sk_obj != _ffi.NULL
1192 num = _lib.sk_X509_OBJECT_num(sk_obj)
1193 assert num != 0
1194
1195 def test_check_env_vars(self, monkeypatch):
1196 """
1197 Test that we return True/False appropriately if the env vars are set.
1198 """
1199 context = Context(TLSv1_METHOD)
1200 dir_var = "CUSTOM_DIR_VAR"
1201 file_var = "CUSTOM_FILE_VAR"
1202 assert context._check_env_vars_set(dir_var, file_var) is False
1203 monkeypatch.setenv(dir_var, "value")
1204 monkeypatch.setenv(file_var, "value")
1205 assert context._check_env_vars_set(dir_var, file_var) is True
1206 assert context._check_env_vars_set(dir_var, file_var) is True
1207
1208 def test_verify_no_fallback_if_env_vars_set(self, monkeypatch):
1209 """
1210 Test that we don't use the fallback path if env vars are set.
1211 """
1212 context = Context(TLSv1_METHOD)
1213 monkeypatch.setattr(
1214 _lib, "SSL_CTX_set_default_verify_paths", lambda x: 1
1215 )
Alex Gaynor03737182020-07-23 20:40:46 -04001216 dir_env_var = _ffi.string(_lib.X509_get_default_cert_dir_env()).decode(
1217 "ascii"
1218 )
Paul Kehrer55fb3412017-06-29 18:44:08 -05001219 file_env_var = _ffi.string(
1220 _lib.X509_get_default_cert_file_env()
1221 ).decode("ascii")
1222 monkeypatch.setenv(dir_env_var, "value")
1223 monkeypatch.setenv(file_env_var, "value")
1224 context.set_default_verify_paths()
1225
1226 monkeypatch.setattr(
Alex Gaynor03737182020-07-23 20:40:46 -04001227 context, "_fallback_default_verify_paths", raiser(SystemError)
Paul Kehrer55fb3412017-06-29 18:44:08 -05001228 )
1229 context.set_default_verify_paths()
1230
1231 @pytest.mark.skipif(
Hynek Schlawack734d3022015-09-05 19:19:32 +02001232 platform == "win32",
1233 reason="set_default_verify_paths appears not to work on Windows. "
Alex Gaynor03737182020-07-23 20:40:46 -04001234 "See LP#404343 and LP#404344.",
Hynek Schlawack734d3022015-09-05 19:19:32 +02001235 )
1236 def test_set_default_verify_paths(self):
1237 """
Alex Chan532b79e2017-01-24 15:14:52 +00001238 `Context.set_default_verify_paths` causes the platform-specific CA
1239 certificate locations to be used for verification purposes.
Hynek Schlawack734d3022015-09-05 19:19:32 +02001240 """
1241 # Testing this requires a server with a certificate signed by one
1242 # of the CAs in the platform CA location. Getting one of those
1243 # costs money. Fortunately (or unfortunately, depending on your
1244 # perspective), it's easy to think of a public server on the
1245 # internet which has such a certificate. Connecting to the network
1246 # in a unit test is bad, but it's the only way I can think of to
1247 # really test this. -exarkun
Hynek Schlawackbf887932015-10-21 17:13:47 +02001248 context = Context(SSLv23_METHOD)
Hynek Schlawack734d3022015-09-05 19:19:32 +02001249 context.set_default_verify_paths()
1250 context.set_verify(
1251 VERIFY_PEER,
Alex Gaynor03737182020-07-23 20:40:46 -04001252 lambda conn, cert, errno, depth, preverify_ok: preverify_ok,
1253 )
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001254
David Benjamin1fbe0642019-04-15 17:05:13 -05001255 client = socket_any_family()
Hynek Schlawackbf887932015-10-21 17:13:47 +02001256 client.connect(("encrypted.google.com", 443))
Hynek Schlawack734d3022015-09-05 19:19:32 +02001257 clientSSL = Connection(context, client)
1258 clientSSL.set_connect_state()
Alex Gaynor373926c2018-05-12 07:43:07 -04001259 clientSSL.set_tlsext_host_name(b"encrypted.google.com")
Hynek Schlawack734d3022015-09-05 19:19:32 +02001260 clientSSL.do_handshake()
1261 clientSSL.send(b"GET / HTTP/1.0\r\n\r\n")
Alex Chan532b79e2017-01-24 15:14:52 +00001262 assert clientSSL.recv(1024)
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05001263
Paul Kehrer55fb3412017-06-29 18:44:08 -05001264 def test_fallback_path_is_not_file_or_dir(self):
1265 """
1266 Test that when passed empty arrays or paths that do not exist no
1267 errors are raised.
1268 """
1269 context = Context(TLSv1_METHOD)
1270 context._fallback_default_verify_paths([], [])
Alex Gaynor03737182020-07-23 20:40:46 -04001271 context._fallback_default_verify_paths(["/not/a/file"], ["/not/a/dir"])
Paul Kehrer55fb3412017-06-29 18:44:08 -05001272
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001273 def test_add_extra_chain_cert_invalid_cert(self):
1274 """
Alex Chan532b79e2017-01-24 15:14:52 +00001275 `Context.add_extra_chain_cert` raises `TypeError` if called with an
1276 object which is not an instance of `X509`.
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001277 """
1278 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001279 with pytest.raises(TypeError):
1280 context.add_extra_chain_cert(object())
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001281
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001282 def _handshake_test(self, serverContext, clientContext):
1283 """
1284 Verify that a client and server created with the given contexts can
1285 successfully handshake and communicate.
1286 """
1287 serverSocket, clientSocket = socket_pair()
1288
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001289 server = Connection(serverContext, serverSocket)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001290 server.set_accept_state()
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001291
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001292 client = Connection(clientContext, clientSocket)
1293 client.set_connect_state()
1294
1295 # Make them talk to each other.
Alex Chan532b79e2017-01-24 15:14:52 +00001296 # interact_in_memory(client, server)
1297 for _ in range(3):
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001298 for s in [client, server]:
1299 try:
1300 s.do_handshake()
1301 except WantReadError:
1302 pass
1303
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001304 def test_set_verify_callback_connection_argument(self):
1305 """
1306 The first argument passed to the verify callback is the
Alex Chan532b79e2017-01-24 15:14:52 +00001307 `Connection` instance for which verification is taking place.
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001308 """
1309 serverContext = Context(TLSv1_METHOD)
1310 serverContext.use_privatekey(
Alex Gaynor03737182020-07-23 20:40:46 -04001311 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
1312 )
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001313 serverContext.use_certificate(
Alex Gaynor03737182020-07-23 20:40:46 -04001314 load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
1315 )
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001316 serverConnection = Connection(serverContext, None)
1317
1318 class VerifyCallback(object):
1319 def callback(self, connection, *args):
1320 self.connection = connection
1321 return 1
1322
1323 verify = VerifyCallback()
1324 clientContext = Context(TLSv1_METHOD)
1325 clientContext.set_verify(VERIFY_PEER, verify.callback)
1326 clientConnection = Connection(clientContext, None)
1327 clientConnection.set_connect_state()
1328
Alex Chan532b79e2017-01-24 15:14:52 +00001329 handshake_in_memory(clientConnection, serverConnection)
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001330
Alex Chan532b79e2017-01-24 15:14:52 +00001331 assert verify.connection is clientConnection
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001332
Paul Kehrere7381862017-11-30 20:55:25 +08001333 def test_x509_in_verify_works(self):
1334 """
1335 We had a bug where the X509 cert instantiated in the callback wrapper
1336 didn't __init__ so it was missing objects needed when calling
1337 get_subject. This test sets up a handshake where we call get_subject
1338 on the cert provided to the verify callback.
1339 """
1340 serverContext = Context(TLSv1_METHOD)
1341 serverContext.use_privatekey(
Alex Gaynor03737182020-07-23 20:40:46 -04001342 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
1343 )
Paul Kehrere7381862017-11-30 20:55:25 +08001344 serverContext.use_certificate(
Alex Gaynor03737182020-07-23 20:40:46 -04001345 load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
1346 )
Paul Kehrere7381862017-11-30 20:55:25 +08001347 serverConnection = Connection(serverContext, None)
1348
1349 def verify_cb_get_subject(conn, cert, errnum, depth, ok):
1350 assert cert.get_subject()
1351 return 1
1352
1353 clientContext = Context(TLSv1_METHOD)
1354 clientContext.set_verify(VERIFY_PEER, verify_cb_get_subject)
1355 clientConnection = Connection(clientContext, None)
1356 clientConnection.set_connect_state()
1357
1358 handshake_in_memory(clientConnection, serverConnection)
1359
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001360 def test_set_verify_callback_exception(self):
1361 """
Alex Chan532b79e2017-01-24 15:14:52 +00001362 If the verify callback passed to `Context.set_verify` raises an
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001363 exception, verification fails and the exception is propagated to the
Alex Chan532b79e2017-01-24 15:14:52 +00001364 caller of `Connection.do_handshake`.
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001365 """
Paul Kehrer7d5a3bf2019-01-21 12:24:02 -06001366 serverContext = Context(TLSv1_2_METHOD)
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001367 serverContext.use_privatekey(
Alex Gaynor03737182020-07-23 20:40:46 -04001368 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM)
1369 )
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001370 serverContext.use_certificate(
Alex Gaynor03737182020-07-23 20:40:46 -04001371 load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
1372 )
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001373
Paul Kehrer7d5a3bf2019-01-21 12:24:02 -06001374 clientContext = Context(TLSv1_2_METHOD)
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001375
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001376 def verify_callback(*args):
1377 raise Exception("silly verify failure")
Alex Gaynor03737182020-07-23 20:40:46 -04001378
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001379 clientContext.set_verify(VERIFY_PEER, verify_callback)
1380
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01001381 with pytest.raises(Exception) as exc:
1382 self._handshake_test(serverContext, clientContext)
1383
Alex Chan532b79e2017-01-24 15:14:52 +00001384 assert "silly verify failure" == str(exc.value)
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001385
Alex Chan532b79e2017-01-24 15:14:52 +00001386 def test_add_extra_chain_cert(self, tmpdir):
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001387 """
Alex Chan532b79e2017-01-24 15:14:52 +00001388 `Context.add_extra_chain_cert` accepts an `X509`
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001389 instance to add to the certificate chain.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001390
Alex Chan532b79e2017-01-24 15:14:52 +00001391 See `_create_certificate_chain` for the details of the
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001392 certificate chain tested.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001393
1394 The chain is tested by starting a server with scert and connecting
1395 to it with a client which trusts cacert and requires verification to
1396 succeed.
1397 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001398 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001399 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1400
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001401 # Dump the CA certificate to a file because that's the only way to load
1402 # it as a trusted CA in the client context.
Alex Gaynor03737182020-07-23 20:40:46 -04001403 for cert, name in [
1404 (cacert, "ca.pem"),
1405 (icert, "i.pem"),
1406 (scert, "s.pem"),
1407 ]:
1408 with tmpdir.join(name).open("w") as f:
1409 f.write(dump_certificate(FILETYPE_PEM, cert).decode("ascii"))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001410
Alex Gaynor03737182020-07-23 20:40:46 -04001411 for key, name in [(cakey, "ca.key"), (ikey, "i.key"), (skey, "s.key")]:
1412 with tmpdir.join(name).open("w") as f:
1413 f.write(dump_privatekey(FILETYPE_PEM, key).decode("ascii"))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001414
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001415 # Create the server context
1416 serverContext = Context(TLSv1_METHOD)
1417 serverContext.use_privatekey(skey)
1418 serverContext.use_certificate(scert)
Jean-Paul Calderone16cf03d2010-09-08 18:53:39 -04001419 # The client already has cacert, we only need to give them icert.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001420 serverContext.add_extra_chain_cert(icert)
1421
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001422 # Create the client
1423 clientContext = Context(TLSv1_METHOD)
1424 clientContext.set_verify(
Alex Gaynor03737182020-07-23 20:40:46 -04001425 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb
1426 )
Alex Chan532b79e2017-01-24 15:14:52 +00001427 clientContext.load_verify_locations(str(tmpdir.join("ca.pem")))
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001428
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001429 # Try it out.
1430 self._handshake_test(serverContext, clientContext)
1431
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001432 def _use_certificate_chain_file_test(self, certdir):
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001433 """
Alex Chan532b79e2017-01-24 15:14:52 +00001434 Verify that `Context.use_certificate_chain_file` reads a
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001435 certificate chain from a specified file.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001436
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001437 The chain is tested by starting a server with scert and connecting to
1438 it with a client which trusts cacert and requires verification to
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001439 succeed.
1440 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001441 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001442 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1443
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001444 makedirs(certdir)
1445
Jean-Paul Calderone05826732015-04-12 11:38:49 -04001446 chainFile = join_bytes_or_unicode(certdir, "chain.pem")
1447 caFile = join_bytes_or_unicode(certdir, "ca.pem")
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001448
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001449 # Write out the chain file.
Alex Gaynor03737182020-07-23 20:40:46 -04001450 with open(chainFile, "wb") as fObj:
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001451 # Most specific to least general.
1452 fObj.write(dump_certificate(FILETYPE_PEM, scert))
1453 fObj.write(dump_certificate(FILETYPE_PEM, icert))
1454 fObj.write(dump_certificate(FILETYPE_PEM, cacert))
1455
Alex Gaynor03737182020-07-23 20:40:46 -04001456 with open(caFile, "w") as fObj:
1457 fObj.write(dump_certificate(FILETYPE_PEM, cacert).decode("ascii"))
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001458
1459 serverContext = Context(TLSv1_METHOD)
1460 serverContext.use_certificate_chain_file(chainFile)
1461 serverContext.use_privatekey(skey)
1462
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001463 clientContext = Context(TLSv1_METHOD)
1464 clientContext.set_verify(
Alex Gaynor03737182020-07-23 20:40:46 -04001465 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb
1466 )
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001467 clientContext.load_verify_locations(caFile)
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001468
1469 self._handshake_test(serverContext, clientContext)
1470
Alex Chan532b79e2017-01-24 15:14:52 +00001471 def test_use_certificate_chain_file_bytes(self, tmpfile):
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001472 """
1473 ``Context.use_certificate_chain_file`` accepts the name of a file (as
1474 an instance of ``bytes``) to specify additional certificates to use to
1475 construct and verify a trust chain.
1476 """
1477 self._use_certificate_chain_file_test(
Alex Chan532b79e2017-01-24 15:14:52 +00001478 tmpfile + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001479 )
1480
Alex Chan532b79e2017-01-24 15:14:52 +00001481 def test_use_certificate_chain_file_unicode(self, tmpfile):
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001482 """
1483 ``Context.use_certificate_chain_file`` accepts the name of a file (as
1484 an instance of ``unicode``) to specify additional certificates to use
1485 to construct and verify a trust chain.
1486 """
1487 self._use_certificate_chain_file_test(
Alex Chan532b79e2017-01-24 15:14:52 +00001488 tmpfile.decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001489 )
1490
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001491 def test_use_certificate_chain_file_wrong_args(self):
1492 """
Alex Chan532b79e2017-01-24 15:14:52 +00001493 `Context.use_certificate_chain_file` raises `TypeError` if passed a
1494 non-byte string single argument.
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001495 """
1496 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001497 with pytest.raises(TypeError):
1498 context.use_certificate_chain_file(object())
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001499
Alex Chan532b79e2017-01-24 15:14:52 +00001500 def test_use_certificate_chain_file_missing_file(self, tmpfile):
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001501 """
Alex Chan532b79e2017-01-24 15:14:52 +00001502 `Context.use_certificate_chain_file` raises `OpenSSL.SSL.Error` when
1503 passed a bad chain file name (for example, the name of a file which
1504 does not exist).
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001505 """
1506 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001507 with pytest.raises(Error):
1508 context.use_certificate_chain_file(tmpfile)
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001509
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001510 def test_set_verify_mode(self):
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001511 """
Alex Chan532b79e2017-01-24 15:14:52 +00001512 `Context.get_verify_mode` returns the verify mode flags previously
1513 passed to `Context.set_verify`.
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001514 """
1515 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001516 assert context.get_verify_mode() == 0
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001517 context.set_verify(
Alex Gaynor03737182020-07-23 20:40:46 -04001518 VERIFY_PEER | VERIFY_CLIENT_ONCE, lambda *args: None
1519 )
Alex Chan532b79e2017-01-24 15:14:52 +00001520 assert context.get_verify_mode() == (VERIFY_PEER | VERIFY_CLIENT_ONCE)
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001521
Alex Gaynor03737182020-07-23 20:40:46 -04001522 @pytest.mark.parametrize("mode", [None, 1.0, object(), "mode"])
Alex Chanfb078d82017-04-20 11:16:15 +01001523 def test_set_verify_wrong_mode_arg(self, mode):
1524 """
1525 `Context.set_verify` raises `TypeError` if the first argument is
1526 not an integer.
1527 """
1528 context = Context(TLSv1_METHOD)
1529 with pytest.raises(TypeError):
1530 context.set_verify(mode=mode, callback=lambda *args: None)
1531
Alex Gaynor03737182020-07-23 20:40:46 -04001532 @pytest.mark.parametrize("callback", [None, 1.0, "mode", ("foo", "bar")])
Alex Chanfb078d82017-04-20 11:16:15 +01001533 def test_set_verify_wrong_callable_arg(self, callback):
1534 """
Alex Gaynor40bc0f12018-05-14 14:06:16 -04001535 `Context.set_verify` raises `TypeError` if the second argument
Alex Chanfb078d82017-04-20 11:16:15 +01001536 is not callable.
1537 """
1538 context = Context(TLSv1_METHOD)
1539 with pytest.raises(TypeError):
1540 context.set_verify(mode=VERIFY_PEER, callback=callback)
1541
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001542 def test_load_tmp_dh_wrong_args(self):
1543 """
Alex Chan532b79e2017-01-24 15:14:52 +00001544 `Context.load_tmp_dh` raises `TypeError` if called with a
1545 non-`str` argument.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001546 """
1547 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001548 with pytest.raises(TypeError):
1549 context.load_tmp_dh(object())
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001550
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001551 def test_load_tmp_dh_missing_file(self):
1552 """
Alex Chan532b79e2017-01-24 15:14:52 +00001553 `Context.load_tmp_dh` raises `OpenSSL.SSL.Error` if the
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001554 specified file does not exist.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001555 """
1556 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001557 with pytest.raises(Error):
1558 context.load_tmp_dh(b"hello")
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001559
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001560 def _load_tmp_dh_test(self, dhfilename):
Jean-Paul Calderone4e0c43f2015-04-13 10:15:17 -04001561 """
1562 Verify that calling ``Context.load_tmp_dh`` with the given filename
1563 does not raise an exception.
1564 """
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001565 context = Context(TLSv1_METHOD)
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001566 with open(dhfilename, "w") as dhfile:
1567 dhfile.write(dhparam)
1568
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001569 context.load_tmp_dh(dhfilename)
1570 # XXX What should I assert here? -exarkun
1571
Alex Chan532b79e2017-01-24 15:14:52 +00001572 def test_load_tmp_dh_bytes(self, tmpfile):
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001573 """
Alex Chan532b79e2017-01-24 15:14:52 +00001574 `Context.load_tmp_dh` loads Diffie-Hellman parameters from the
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001575 specified file (given as ``bytes``).
1576 """
1577 self._load_tmp_dh_test(
Alex Chan532b79e2017-01-24 15:14:52 +00001578 tmpfile + NON_ASCII.encode(getfilesystemencoding()),
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001579 )
1580
Alex Chan532b79e2017-01-24 15:14:52 +00001581 def test_load_tmp_dh_unicode(self, tmpfile):
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001582 """
Alex Chan532b79e2017-01-24 15:14:52 +00001583 `Context.load_tmp_dh` loads Diffie-Hellman parameters from the
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001584 specified file (given as ``unicode``).
1585 """
1586 self._load_tmp_dh_test(
Alex Chan532b79e2017-01-24 15:14:52 +00001587 tmpfile.decode(getfilesystemencoding()) + NON_ASCII,
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001588 )
1589
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001590 def test_set_tmp_ecdh(self):
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001591 """
Alex Chan532b79e2017-01-24 15:14:52 +00001592 `Context.set_tmp_ecdh` sets the elliptic curve for Diffie-Hellman to
1593 the specified curve.
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001594 """
1595 context = Context(TLSv1_METHOD)
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001596 for curve in get_elliptic_curves():
Hynek Schlawacka07fa8c2015-10-17 10:15:28 +02001597 if curve.name.startswith(u"Oakley-"):
Hynek Schlawack7408aff2015-10-17 09:51:16 +02001598 # Setting Oakley-EC2N-4 and Oakley-EC2N-3 adds
1599 # ('bignum routines', 'BN_mod_inverse', 'no inverse') to the
1600 # error queue on OpenSSL 1.0.2.
1601 continue
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001602 # The only easily "assertable" thing is that it does not raise an
1603 # exception.
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001604 context.set_tmp_ecdh(curve)
Alex Gaynor12dc0842014-01-17 12:51:31 -06001605
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001606 def test_set_session_cache_mode_wrong_args(self):
1607 """
Alex Chan532b79e2017-01-24 15:14:52 +00001608 `Context.set_session_cache_mode` raises `TypeError` if called with
1609 a non-integer argument.
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001610 called with other than one integer argument.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001611 """
1612 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001613 with pytest.raises(TypeError):
1614 context.set_session_cache_mode(object())
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001615
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001616 def test_session_cache_mode(self):
1617 """
Alex Chan532b79e2017-01-24 15:14:52 +00001618 `Context.set_session_cache_mode` specifies how sessions are cached.
1619 The setting can be retrieved via `Context.get_session_cache_mode`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001620 """
1621 context = Context(TLSv1_METHOD)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001622 context.set_session_cache_mode(SESS_CACHE_OFF)
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001623 off = context.set_session_cache_mode(SESS_CACHE_BOTH)
Alex Chan532b79e2017-01-24 15:14:52 +00001624 assert SESS_CACHE_OFF == off
1625 assert SESS_CACHE_BOTH == context.get_session_cache_mode()
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001626
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001627 def test_get_cert_store(self):
1628 """
Alex Chan532b79e2017-01-24 15:14:52 +00001629 `Context.get_cert_store` returns a `X509Store` instance.
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001630 """
1631 context = Context(TLSv1_METHOD)
1632 store = context.get_cert_store()
Alex Chan532b79e2017-01-24 15:14:52 +00001633 assert isinstance(store, X509Store)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001634
Jeremy Lainé02261ad2018-05-16 18:33:25 +02001635 def test_set_tlsext_use_srtp_not_bytes(self):
1636 """
1637 `Context.set_tlsext_use_srtp' enables negotiating SRTP keying material.
1638
1639 It raises a TypeError if the list of profiles is not a byte string.
1640 """
1641 context = Context(TLSv1_METHOD)
1642 with pytest.raises(TypeError):
Alex Gaynor03737182020-07-23 20:40:46 -04001643 context.set_tlsext_use_srtp(text_type("SRTP_AES128_CM_SHA1_80"))
Jeremy Lainé02261ad2018-05-16 18:33:25 +02001644
1645 def test_set_tlsext_use_srtp_invalid_profile(self):
1646 """
1647 `Context.set_tlsext_use_srtp' enables negotiating SRTP keying material.
1648
1649 It raises an Error if the call to OpenSSL fails.
1650 """
1651 context = Context(TLSv1_METHOD)
1652 with pytest.raises(Error):
Alex Gaynor03737182020-07-23 20:40:46 -04001653 context.set_tlsext_use_srtp(b"SRTP_BOGUS")
Jeremy Lainé02261ad2018-05-16 18:33:25 +02001654
1655 def test_set_tlsext_use_srtp_valid(self):
1656 """
1657 `Context.set_tlsext_use_srtp' enables negotiating SRTP keying material.
1658
1659 It does not return anything.
1660 """
1661 context = Context(TLSv1_METHOD)
Alex Gaynor03737182020-07-23 20:40:46 -04001662 assert context.set_tlsext_use_srtp(b"SRTP_AES128_CM_SHA1_80") is None
Jeremy Lainé02261ad2018-05-16 18:33:25 +02001663
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001664
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001665class TestServerNameCallback(object):
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001666 """
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001667 Tests for `Context.set_tlsext_servername_callback` and its
1668 interaction with `Connection`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001669 """
Alex Gaynor03737182020-07-23 20:40:46 -04001670
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001671 def test_old_callback_forgotten(self):
1672 """
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001673 If `Context.set_tlsext_servername_callback` is used to specify
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001674 a new callback, the one it replaces is dereferenced.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001675 """
Alex Gaynor03737182020-07-23 20:40:46 -04001676
Alex Chanfb078d82017-04-20 11:16:15 +01001677 def callback(connection): # pragma: no cover
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001678 pass
1679
Alex Chanfb078d82017-04-20 11:16:15 +01001680 def replacement(connection): # pragma: no cover
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001681 pass
1682
1683 context = Context(TLSv1_METHOD)
1684 context.set_tlsext_servername_callback(callback)
1685
1686 tracker = ref(callback)
1687 del callback
1688
1689 context.set_tlsext_servername_callback(replacement)
Jean-Paul Calderoned4033eb2014-01-11 08:21:46 -05001690
1691 # One run of the garbage collector happens to work on CPython. PyPy
1692 # doesn't collect the underlying object until a second run for whatever
1693 # reason. That's fine, it still demonstrates our code has properly
1694 # dropped the reference.
1695 collect()
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001696 collect()
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001697
1698 callback = tracker()
1699 if callback is not None:
1700 referrers = get_referrers(callback)
Alex Chanfb078d82017-04-20 11:16:15 +01001701 if len(referrers) > 1: # pragma: nocover
1702 pytest.fail("Some references remain: %r" % (referrers,))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001703
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001704 def test_no_servername(self):
1705 """
1706 When a client specifies no server name, the callback passed to
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001707 `Context.set_tlsext_servername_callback` is invoked and the
1708 result of `Connection.get_servername` is `None`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001709 """
1710 args = []
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001711
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001712 def servername(conn):
1713 args.append((conn, conn.get_servername()))
Alex Gaynor03737182020-07-23 20:40:46 -04001714
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001715 context = Context(TLSv1_METHOD)
1716 context.set_tlsext_servername_callback(servername)
1717
1718 # Lose our reference to it. The Context is responsible for keeping it
1719 # alive now.
1720 del servername
1721 collect()
1722
1723 # Necessary to actually accept the connection
1724 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001725 context.use_certificate(
Alex Gaynor03737182020-07-23 20:40:46 -04001726 load_certificate(FILETYPE_PEM, server_cert_pem)
1727 )
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001728
1729 # Do a little connection to trigger the logic
1730 server = Connection(context, None)
1731 server.set_accept_state()
1732
1733 client = Connection(Context(TLSv1_METHOD), None)
1734 client.set_connect_state()
1735
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001736 interact_in_memory(server, client)
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001737
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001738 assert args == [(server, None)]
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001739
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001740 def test_servername(self):
1741 """
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001742 When a client specifies a server name in its hello message, the
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001743 callback passed to `Contexts.set_tlsext_servername_callback` is
1744 invoked and the result of `Connection.get_servername` is that
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001745 server name.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001746 """
1747 args = []
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001748
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001749 def servername(conn):
1750 args.append((conn, conn.get_servername()))
Alex Gaynor03737182020-07-23 20:40:46 -04001751
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001752 context = Context(TLSv1_METHOD)
1753 context.set_tlsext_servername_callback(servername)
1754
1755 # Necessary to actually accept the connection
1756 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001757 context.use_certificate(
Alex Gaynor03737182020-07-23 20:40:46 -04001758 load_certificate(FILETYPE_PEM, server_cert_pem)
1759 )
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001760
1761 # Do a little connection to trigger the logic
1762 server = Connection(context, None)
1763 server.set_accept_state()
1764
1765 client = Connection(Context(TLSv1_METHOD), None)
1766 client.set_connect_state()
Alex Gaynore7f51982016-09-11 11:48:14 -04001767 client.set_tlsext_host_name(b"foo1.example.com")
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001768
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001769 interact_in_memory(server, client)
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001770
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001771 assert args == [(server, b"foo1.example.com")]
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001772
1773
Paul Kehrer4d575902019-02-26 21:42:12 +08001774@pytest.mark.skipif(
1775 not _lib.Cryptography_HAS_NEXTPROTONEG, reason="NPN is not available"
1776)
Alex Chan9e08b3e2016-11-10 12:18:54 +00001777class TestNextProtoNegotiation(object):
Cory Benfield84a121e2014-03-31 20:30:25 +01001778 """
1779 Test for Next Protocol Negotiation in PyOpenSSL.
1780 """
Alex Gaynor03737182020-07-23 20:40:46 -04001781
Alex Chan9e08b3e2016-11-10 12:18:54 +00001782 def test_npn_success(self):
1783 """
1784 Tests that clients and servers that agree on the negotiated next
1785 protocol can correct establish a connection, and that the agreed
1786 protocol is reported by the connections.
1787 """
1788 advertise_args = []
1789 select_args = []
1790
1791 def advertise(conn):
1792 advertise_args.append((conn,))
Alex Gaynor03737182020-07-23 20:40:46 -04001793 return [b"http/1.1", b"spdy/2"]
Alex Chan9e08b3e2016-11-10 12:18:54 +00001794
1795 def select(conn, options):
1796 select_args.append((conn, options))
Alex Gaynor03737182020-07-23 20:40:46 -04001797 return b"spdy/2"
Alex Chan9e08b3e2016-11-10 12:18:54 +00001798
1799 server_context = Context(TLSv1_METHOD)
1800 server_context.set_npn_advertise_callback(advertise)
1801
1802 client_context = Context(TLSv1_METHOD)
1803 client_context.set_npn_select_callback(select)
1804
1805 # Necessary to actually accept the connection
1806 server_context.use_privatekey(
Alex Gaynor03737182020-07-23 20:40:46 -04001807 load_privatekey(FILETYPE_PEM, server_key_pem)
1808 )
Alex Chan9e08b3e2016-11-10 12:18:54 +00001809 server_context.use_certificate(
Alex Gaynor03737182020-07-23 20:40:46 -04001810 load_certificate(FILETYPE_PEM, server_cert_pem)
1811 )
Alex Chan9e08b3e2016-11-10 12:18:54 +00001812
1813 # Do a little connection to trigger the logic
1814 server = Connection(server_context, None)
1815 server.set_accept_state()
1816
1817 client = Connection(client_context, None)
1818 client.set_connect_state()
1819
1820 interact_in_memory(server, client)
1821
1822 assert advertise_args == [(server,)]
Alex Gaynor03737182020-07-23 20:40:46 -04001823 assert select_args == [(client, [b"http/1.1", b"spdy/2"])]
Alex Chan9e08b3e2016-11-10 12:18:54 +00001824
Alex Gaynor03737182020-07-23 20:40:46 -04001825 assert server.get_next_proto_negotiated() == b"spdy/2"
1826 assert client.get_next_proto_negotiated() == b"spdy/2"
Alex Chan9e08b3e2016-11-10 12:18:54 +00001827
1828 def test_npn_client_fail(self):
1829 """
1830 Tests that when clients and servers cannot agree on what protocol
1831 to use next that the TLS connection does not get established.
1832 """
1833 advertise_args = []
1834 select_args = []
1835
1836 def advertise(conn):
1837 advertise_args.append((conn,))
Alex Gaynor03737182020-07-23 20:40:46 -04001838 return [b"http/1.1", b"spdy/2"]
Alex Chan9e08b3e2016-11-10 12:18:54 +00001839
1840 def select(conn, options):
1841 select_args.append((conn, options))
Alex Gaynor03737182020-07-23 20:40:46 -04001842 return b""
Alex Chan9e08b3e2016-11-10 12:18:54 +00001843
1844 server_context = Context(TLSv1_METHOD)
1845 server_context.set_npn_advertise_callback(advertise)
1846
1847 client_context = Context(TLSv1_METHOD)
1848 client_context.set_npn_select_callback(select)
1849
1850 # Necessary to actually accept the connection
1851 server_context.use_privatekey(
Alex Gaynor03737182020-07-23 20:40:46 -04001852 load_privatekey(FILETYPE_PEM, server_key_pem)
1853 )
Alex Chan9e08b3e2016-11-10 12:18:54 +00001854 server_context.use_certificate(
Alex Gaynor03737182020-07-23 20:40:46 -04001855 load_certificate(FILETYPE_PEM, server_cert_pem)
1856 )
Alex Chan9e08b3e2016-11-10 12:18:54 +00001857
1858 # Do a little connection to trigger the logic
1859 server = Connection(server_context, None)
1860 server.set_accept_state()
1861
1862 client = Connection(client_context, None)
1863 client.set_connect_state()
1864
1865 # If the client doesn't return anything, the connection will fail.
1866 with pytest.raises(Error):
1867 interact_in_memory(server, client)
1868
1869 assert advertise_args == [(server,)]
Alex Gaynor03737182020-07-23 20:40:46 -04001870 assert select_args == [(client, [b"http/1.1", b"spdy/2"])]
Alex Chan9e08b3e2016-11-10 12:18:54 +00001871
1872 def test_npn_select_error(self):
1873 """
1874 Test that we can handle exceptions in the select callback. If
1875 select fails it should be fatal to the connection.
1876 """
1877 advertise_args = []
1878
1879 def advertise(conn):
1880 advertise_args.append((conn,))
Alex Gaynor03737182020-07-23 20:40:46 -04001881 return [b"http/1.1", b"spdy/2"]
Alex Chan9e08b3e2016-11-10 12:18:54 +00001882
1883 def select(conn, options):
1884 raise TypeError
1885
1886 server_context = Context(TLSv1_METHOD)
1887 server_context.set_npn_advertise_callback(advertise)
1888
1889 client_context = Context(TLSv1_METHOD)
1890 client_context.set_npn_select_callback(select)
1891
1892 # Necessary to actually accept the connection
1893 server_context.use_privatekey(
Alex Gaynor03737182020-07-23 20:40:46 -04001894 load_privatekey(FILETYPE_PEM, server_key_pem)
1895 )
Alex Chan9e08b3e2016-11-10 12:18:54 +00001896 server_context.use_certificate(
Alex Gaynor03737182020-07-23 20:40:46 -04001897 load_certificate(FILETYPE_PEM, server_cert_pem)
1898 )
Alex Chan9e08b3e2016-11-10 12:18:54 +00001899
1900 # Do a little connection to trigger the logic
1901 server = Connection(server_context, None)
1902 server.set_accept_state()
1903
1904 client = Connection(client_context, None)
1905 client.set_connect_state()
1906
1907 # If the callback throws an exception it should be raised here.
1908 with pytest.raises(TypeError):
1909 interact_in_memory(server, client)
Alex Gaynor03737182020-07-23 20:40:46 -04001910 assert advertise_args == [
1911 (server,),
1912 ]
Alex Chan9e08b3e2016-11-10 12:18:54 +00001913
1914 def test_npn_advertise_error(self):
1915 """
1916 Test that we can handle exceptions in the advertise callback. If
1917 advertise fails no NPN is advertised to the client.
1918 """
1919 select_args = []
1920
1921 def advertise(conn):
1922 raise TypeError
1923
1924 def select(conn, options): # pragma: nocover
Cory Benfieldba1820d2015-04-13 17:39:12 -04001925 """
Alex Chan9e08b3e2016-11-10 12:18:54 +00001926 Assert later that no args are actually appended.
Cory Benfieldba1820d2015-04-13 17:39:12 -04001927 """
Alex Chan9e08b3e2016-11-10 12:18:54 +00001928 select_args.append((conn, options))
Alex Gaynor03737182020-07-23 20:40:46 -04001929 return b""
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001930
Alex Chan9e08b3e2016-11-10 12:18:54 +00001931 server_context = Context(TLSv1_METHOD)
1932 server_context.set_npn_advertise_callback(advertise)
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001933
Alex Chan9e08b3e2016-11-10 12:18:54 +00001934 client_context = Context(TLSv1_METHOD)
1935 client_context.set_npn_select_callback(select)
Cory Benfield84a121e2014-03-31 20:30:25 +01001936
Alex Chan9e08b3e2016-11-10 12:18:54 +00001937 # Necessary to actually accept the connection
1938 server_context.use_privatekey(
Alex Gaynor03737182020-07-23 20:40:46 -04001939 load_privatekey(FILETYPE_PEM, server_key_pem)
1940 )
Alex Chan9e08b3e2016-11-10 12:18:54 +00001941 server_context.use_certificate(
Alex Gaynor03737182020-07-23 20:40:46 -04001942 load_certificate(FILETYPE_PEM, server_cert_pem)
1943 )
Cory Benfield84a121e2014-03-31 20:30:25 +01001944
Alex Chan9e08b3e2016-11-10 12:18:54 +00001945 # Do a little connection to trigger the logic
1946 server = Connection(server_context, None)
1947 server.set_accept_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001948
Alex Chan9e08b3e2016-11-10 12:18:54 +00001949 client = Connection(client_context, None)
1950 client.set_connect_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001951
Alex Chan9e08b3e2016-11-10 12:18:54 +00001952 # If the client doesn't return anything, the connection will fail.
1953 with pytest.raises(TypeError):
1954 interact_in_memory(server, client)
1955 assert select_args == []
Cory Benfield0ea76e72015-03-22 09:05:28 +00001956
1957
Alex Chanec1e32d2016-11-10 14:11:45 +00001958class TestApplicationLayerProtoNegotiation(object):
Cory Benfield12eae892014-06-07 15:42:56 +01001959 """
1960 Tests for ALPN in PyOpenSSL.
1961 """
Alex Gaynor03737182020-07-23 20:40:46 -04001962
Alex Gaynor77debda2020-04-07 13:40:59 -04001963 def test_alpn_success(self):
1964 """
1965 Clients and servers that agree on the negotiated ALPN protocol can
1966 correct establish a connection, and the agreed protocol is reported
1967 by the connections.
1968 """
1969 select_args = []
Cory Benfield12eae892014-06-07 15:42:56 +01001970
Alex Gaynor77debda2020-04-07 13:40:59 -04001971 def select(conn, options):
1972 select_args.append((conn, options))
Alex Gaynor03737182020-07-23 20:40:46 -04001973 return b"spdy/2"
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001974
Alex Gaynor77debda2020-04-07 13:40:59 -04001975 client_context = Context(TLSv1_METHOD)
Alex Gaynor03737182020-07-23 20:40:46 -04001976 client_context.set_alpn_protos([b"http/1.1", b"spdy/2"])
Cory Benfield12eae892014-06-07 15:42:56 +01001977
Alex Gaynor77debda2020-04-07 13:40:59 -04001978 server_context = Context(TLSv1_METHOD)
1979 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01001980
Alex Gaynor77debda2020-04-07 13:40:59 -04001981 # Necessary to actually accept the connection
1982 server_context.use_privatekey(
Alex Gaynor03737182020-07-23 20:40:46 -04001983 load_privatekey(FILETYPE_PEM, server_key_pem)
1984 )
Alex Gaynor77debda2020-04-07 13:40:59 -04001985 server_context.use_certificate(
Alex Gaynor03737182020-07-23 20:40:46 -04001986 load_certificate(FILETYPE_PEM, server_cert_pem)
1987 )
Cory Benfield12eae892014-06-07 15:42:56 +01001988
Alex Gaynor77debda2020-04-07 13:40:59 -04001989 # Do a little connection to trigger the logic
1990 server = Connection(server_context, None)
1991 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001992
Alex Gaynor77debda2020-04-07 13:40:59 -04001993 client = Connection(client_context, None)
1994 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001995
Alex Gaynor77debda2020-04-07 13:40:59 -04001996 interact_in_memory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001997
Alex Gaynor03737182020-07-23 20:40:46 -04001998 assert select_args == [(server, [b"http/1.1", b"spdy/2"])]
Alex Gaynor77debda2020-04-07 13:40:59 -04001999
Alex Gaynor03737182020-07-23 20:40:46 -04002000 assert server.get_alpn_proto_negotiated() == b"spdy/2"
2001 assert client.get_alpn_proto_negotiated() == b"spdy/2"
Alex Gaynor77debda2020-04-07 13:40:59 -04002002
2003 def test_alpn_set_on_connection(self):
2004 """
2005 The same as test_alpn_success, but setting the ALPN protocols on
2006 the connection rather than the context.
2007 """
2008 select_args = []
2009
2010 def select(conn, options):
2011 select_args.append((conn, options))
Alex Gaynor03737182020-07-23 20:40:46 -04002012 return b"spdy/2"
Alex Gaynor77debda2020-04-07 13:40:59 -04002013
2014 # Setup the client context but don't set any ALPN protocols.
2015 client_context = Context(TLSv1_METHOD)
2016
2017 server_context = Context(TLSv1_METHOD)
2018 server_context.set_alpn_select_callback(select)
2019
2020 # Necessary to actually accept the connection
2021 server_context.use_privatekey(
Alex Gaynor03737182020-07-23 20:40:46 -04002022 load_privatekey(FILETYPE_PEM, server_key_pem)
2023 )
Alex Gaynor77debda2020-04-07 13:40:59 -04002024 server_context.use_certificate(
Alex Gaynor03737182020-07-23 20:40:46 -04002025 load_certificate(FILETYPE_PEM, server_cert_pem)
2026 )
Alex Gaynor77debda2020-04-07 13:40:59 -04002027
2028 # Do a little connection to trigger the logic
2029 server = Connection(server_context, None)
2030 server.set_accept_state()
2031
2032 # Set the ALPN protocols on the client connection.
2033 client = Connection(client_context, None)
Alex Gaynor03737182020-07-23 20:40:46 -04002034 client.set_alpn_protos([b"http/1.1", b"spdy/2"])
Alex Gaynor77debda2020-04-07 13:40:59 -04002035 client.set_connect_state()
2036
2037 interact_in_memory(server, client)
2038
Alex Gaynor03737182020-07-23 20:40:46 -04002039 assert select_args == [(server, [b"http/1.1", b"spdy/2"])]
Alex Gaynor77debda2020-04-07 13:40:59 -04002040
Alex Gaynor03737182020-07-23 20:40:46 -04002041 assert server.get_alpn_proto_negotiated() == b"spdy/2"
2042 assert client.get_alpn_proto_negotiated() == b"spdy/2"
Alex Gaynor77debda2020-04-07 13:40:59 -04002043
2044 def test_alpn_server_fail(self):
2045 """
2046 When clients and servers cannot agree on what protocol to use next
2047 the TLS connection does not get established.
2048 """
2049 select_args = []
2050
2051 def select(conn, options):
2052 select_args.append((conn, options))
Alex Gaynor03737182020-07-23 20:40:46 -04002053 return b""
Alex Gaynor77debda2020-04-07 13:40:59 -04002054
2055 client_context = Context(TLSv1_METHOD)
Alex Gaynor03737182020-07-23 20:40:46 -04002056 client_context.set_alpn_protos([b"http/1.1", b"spdy/2"])
Alex Gaynor77debda2020-04-07 13:40:59 -04002057
2058 server_context = Context(TLSv1_METHOD)
2059 server_context.set_alpn_select_callback(select)
2060
2061 # Necessary to actually accept the connection
2062 server_context.use_privatekey(
Alex Gaynor03737182020-07-23 20:40:46 -04002063 load_privatekey(FILETYPE_PEM, server_key_pem)
2064 )
Alex Gaynor77debda2020-04-07 13:40:59 -04002065 server_context.use_certificate(
Alex Gaynor03737182020-07-23 20:40:46 -04002066 load_certificate(FILETYPE_PEM, server_cert_pem)
2067 )
Alex Gaynor77debda2020-04-07 13:40:59 -04002068
2069 # Do a little connection to trigger the logic
2070 server = Connection(server_context, None)
2071 server.set_accept_state()
2072
2073 client = Connection(client_context, None)
2074 client.set_connect_state()
2075
2076 # If the client doesn't return anything, the connection will fail.
2077 with pytest.raises(Error):
Alex Chanec1e32d2016-11-10 14:11:45 +00002078 interact_in_memory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01002079
Alex Gaynor03737182020-07-23 20:40:46 -04002080 assert select_args == [(server, [b"http/1.1", b"spdy/2"])]
Cory Benfielde46fa842015-04-13 16:50:49 -04002081
Alex Gaynor77debda2020-04-07 13:40:59 -04002082 def test_alpn_no_server_overlap(self):
2083 """
2084 A server can allow a TLS handshake to complete without
2085 agreeing to an application protocol by returning
2086 ``NO_OVERLAPPING_PROTOCOLS``.
2087 """
2088 refusal_args = []
Cory Benfield12eae892014-06-07 15:42:56 +01002089
Alex Gaynor77debda2020-04-07 13:40:59 -04002090 def refusal(conn, options):
2091 refusal_args.append((conn, options))
2092 return NO_OVERLAPPING_PROTOCOLS
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002093
Alex Gaynor77debda2020-04-07 13:40:59 -04002094 client_context = Context(SSLv23_METHOD)
Alex Gaynor03737182020-07-23 20:40:46 -04002095 client_context.set_alpn_protos([b"http/1.1", b"spdy/2"])
Cory Benfield12eae892014-06-07 15:42:56 +01002096
Alex Gaynor77debda2020-04-07 13:40:59 -04002097 server_context = Context(SSLv23_METHOD)
2098 server_context.set_alpn_select_callback(refusal)
Cory Benfield12eae892014-06-07 15:42:56 +01002099
Alex Gaynor77debda2020-04-07 13:40:59 -04002100 # Necessary to actually accept the connection
2101 server_context.use_privatekey(
Alex Gaynor03737182020-07-23 20:40:46 -04002102 load_privatekey(FILETYPE_PEM, server_key_pem)
2103 )
Alex Gaynor77debda2020-04-07 13:40:59 -04002104 server_context.use_certificate(
Alex Gaynor03737182020-07-23 20:40:46 -04002105 load_certificate(FILETYPE_PEM, server_cert_pem)
2106 )
Cory Benfield12eae892014-06-07 15:42:56 +01002107
Alex Gaynor77debda2020-04-07 13:40:59 -04002108 # Do a little connection to trigger the logic
2109 server = Connection(server_context, None)
2110 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01002111
Alex Gaynor77debda2020-04-07 13:40:59 -04002112 client = Connection(client_context, None)
2113 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01002114
Alex Gaynor77debda2020-04-07 13:40:59 -04002115 # Do the dance.
2116 interact_in_memory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01002117
Alex Gaynor03737182020-07-23 20:40:46 -04002118 assert refusal_args == [(server, [b"http/1.1", b"spdy/2"])]
Alex Gaynor77debda2020-04-07 13:40:59 -04002119
Alex Gaynor03737182020-07-23 20:40:46 -04002120 assert client.get_alpn_proto_negotiated() == b""
Alex Gaynor77debda2020-04-07 13:40:59 -04002121
2122 def test_alpn_select_cb_returns_invalid_value(self):
2123 """
2124 If the ALPN selection callback returns anything other than
2125 a bytestring or ``NO_OVERLAPPING_PROTOCOLS``, a
2126 :py:exc:`TypeError` is raised.
2127 """
2128 invalid_cb_args = []
2129
2130 def invalid_cb(conn, options):
2131 invalid_cb_args.append((conn, options))
2132 return u"can't return unicode"
2133
2134 client_context = Context(SSLv23_METHOD)
Alex Gaynor03737182020-07-23 20:40:46 -04002135 client_context.set_alpn_protos([b"http/1.1", b"spdy/2"])
Alex Gaynor77debda2020-04-07 13:40:59 -04002136
2137 server_context = Context(SSLv23_METHOD)
2138 server_context.set_alpn_select_callback(invalid_cb)
2139
2140 # Necessary to actually accept the connection
2141 server_context.use_privatekey(
Alex Gaynor03737182020-07-23 20:40:46 -04002142 load_privatekey(FILETYPE_PEM, server_key_pem)
2143 )
Alex Gaynor77debda2020-04-07 13:40:59 -04002144 server_context.use_certificate(
Alex Gaynor03737182020-07-23 20:40:46 -04002145 load_certificate(FILETYPE_PEM, server_cert_pem)
2146 )
Alex Gaynor77debda2020-04-07 13:40:59 -04002147
2148 # Do a little connection to trigger the logic
2149 server = Connection(server_context, None)
2150 server.set_accept_state()
2151
2152 client = Connection(client_context, None)
2153 client.set_connect_state()
2154
2155 # Do the dance.
2156 with pytest.raises(TypeError):
Alex Chanec1e32d2016-11-10 14:11:45 +00002157 interact_in_memory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01002158
Alex Gaynor03737182020-07-23 20:40:46 -04002159 assert invalid_cb_args == [(server, [b"http/1.1", b"spdy/2"])]
Cory Benfield12eae892014-06-07 15:42:56 +01002160
Alex Gaynor03737182020-07-23 20:40:46 -04002161 assert client.get_alpn_proto_negotiated() == b""
Cory Benfield12eae892014-06-07 15:42:56 +01002162
Alex Gaynor77debda2020-04-07 13:40:59 -04002163 def test_alpn_no_server(self):
2164 """
2165 When clients and servers cannot agree on what protocol to use next
2166 because the server doesn't offer ALPN, no protocol is negotiated.
2167 """
2168 client_context = Context(TLSv1_METHOD)
Alex Gaynor03737182020-07-23 20:40:46 -04002169 client_context.set_alpn_protos([b"http/1.1", b"spdy/2"])
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002170
Alex Gaynor77debda2020-04-07 13:40:59 -04002171 server_context = Context(TLSv1_METHOD)
Cory Benfield12eae892014-06-07 15:42:56 +01002172
Alex Gaynor77debda2020-04-07 13:40:59 -04002173 # Necessary to actually accept the connection
2174 server_context.use_privatekey(
Alex Gaynor03737182020-07-23 20:40:46 -04002175 load_privatekey(FILETYPE_PEM, server_key_pem)
2176 )
Alex Gaynor77debda2020-04-07 13:40:59 -04002177 server_context.use_certificate(
Alex Gaynor03737182020-07-23 20:40:46 -04002178 load_certificate(FILETYPE_PEM, server_cert_pem)
2179 )
Cory Benfield12eae892014-06-07 15:42:56 +01002180
Alex Gaynor77debda2020-04-07 13:40:59 -04002181 # Do a little connection to trigger the logic
2182 server = Connection(server_context, None)
2183 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01002184
Alex Gaynor77debda2020-04-07 13:40:59 -04002185 client = Connection(client_context, None)
2186 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01002187
Alex Gaynor77debda2020-04-07 13:40:59 -04002188 # Do the dance.
2189 interact_in_memory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01002190
Alex Gaynor03737182020-07-23 20:40:46 -04002191 assert client.get_alpn_proto_negotiated() == b""
Cory Benfield12eae892014-06-07 15:42:56 +01002192
Alex Gaynor77debda2020-04-07 13:40:59 -04002193 def test_alpn_callback_exception(self):
2194 """
2195 We can handle exceptions in the ALPN select callback.
2196 """
2197 select_args = []
Cory Benfield12eae892014-06-07 15:42:56 +01002198
Alex Gaynor77debda2020-04-07 13:40:59 -04002199 def select(conn, options):
2200 select_args.append((conn, options))
2201 raise TypeError()
Cory Benfield12eae892014-06-07 15:42:56 +01002202
Alex Gaynor77debda2020-04-07 13:40:59 -04002203 client_context = Context(TLSv1_METHOD)
Alex Gaynor03737182020-07-23 20:40:46 -04002204 client_context.set_alpn_protos([b"http/1.1", b"spdy/2"])
Mark Williams5d890a02019-11-17 19:56:26 -08002205
Alex Gaynor77debda2020-04-07 13:40:59 -04002206 server_context = Context(TLSv1_METHOD)
2207 server_context.set_alpn_select_callback(select)
Mark Williams5d890a02019-11-17 19:56:26 -08002208
Alex Gaynor77debda2020-04-07 13:40:59 -04002209 # Necessary to actually accept the connection
2210 server_context.use_privatekey(
Alex Gaynor03737182020-07-23 20:40:46 -04002211 load_privatekey(FILETYPE_PEM, server_key_pem)
2212 )
Alex Gaynor77debda2020-04-07 13:40:59 -04002213 server_context.use_certificate(
Alex Gaynor03737182020-07-23 20:40:46 -04002214 load_certificate(FILETYPE_PEM, server_cert_pem)
2215 )
Mark Williams5d890a02019-11-17 19:56:26 -08002216
Alex Gaynor77debda2020-04-07 13:40:59 -04002217 # Do a little connection to trigger the logic
2218 server = Connection(server_context, None)
2219 server.set_accept_state()
Mark Williams5d890a02019-11-17 19:56:26 -08002220
Alex Gaynor77debda2020-04-07 13:40:59 -04002221 client = Connection(client_context, None)
2222 client.set_connect_state()
Mark Williams5d890a02019-11-17 19:56:26 -08002223
Alex Gaynor77debda2020-04-07 13:40:59 -04002224 with pytest.raises(TypeError):
Mark Williams5d890a02019-11-17 19:56:26 -08002225 interact_in_memory(server, client)
Alex Gaynor03737182020-07-23 20:40:46 -04002226 assert select_args == [(server, [b"http/1.1", b"spdy/2"])]
Cory Benfield0f7b04c2015-04-13 17:51:12 -04002227
Cory Benfieldf1177e72015-04-12 09:11:49 -04002228
Alex Chanec1e32d2016-11-10 14:11:45 +00002229class TestSession(object):
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05002230 """
2231 Unit tests for :py:obj:`OpenSSL.SSL.Session`.
2232 """
Alex Gaynor03737182020-07-23 20:40:46 -04002233
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05002234 def test_construction(self):
2235 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002236 :py:class:`Session` can be constructed with no arguments, creating
2237 a new instance of that type.
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05002238 """
2239 new_session = Session()
Alex Chanec1e32d2016-11-10 14:11:45 +00002240 assert isinstance(new_session, Session)
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05002241
2242
Alex Chan1c0cb662017-01-30 07:13:30 +00002243class TestConnection(object):
Rick Deane15b1472009-07-09 15:53:42 -05002244 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002245 Unit tests for `OpenSSL.SSL.Connection`.
Rick Deane15b1472009-07-09 15:53:42 -05002246 """
Alex Gaynor03737182020-07-23 20:40:46 -04002247
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04002248 # XXX get_peer_certificate -> None
2249 # XXX sock_shutdown
2250 # XXX master_key -> TypeError
2251 # XXX server_random -> TypeError
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04002252 # XXX connect -> TypeError
2253 # XXX connect_ex -> TypeError
2254 # XXX set_connect_state -> TypeError
2255 # XXX set_accept_state -> TypeError
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04002256 # XXX do_handshake -> TypeError
2257 # XXX bio_read -> TypeError
2258 # XXX recv -> TypeError
2259 # XXX send -> TypeError
2260 # XXX bio_write -> TypeError
2261
Rick Deane15b1472009-07-09 15:53:42 -05002262 def test_type(self):
2263 """
Alex Gaynor01f90a12019-02-07 09:14:48 -05002264 `Connection` can be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -05002265 """
2266 ctx = Context(TLSv1_METHOD)
Alex Gaynor03737182020-07-23 20:40:46 -04002267 assert is_consistent_type(Connection, "Connection", ctx, None)
Rick Deane15b1472009-07-09 15:53:42 -05002268
Alex Gaynor03737182020-07-23 20:40:46 -04002269 @pytest.mark.parametrize("bad_context", [object(), "context", None, 1])
Alex Chanfb078d82017-04-20 11:16:15 +01002270 def test_wrong_args(self, bad_context):
2271 """
2272 `Connection.__init__` raises `TypeError` if called with a non-`Context`
2273 instance argument.
2274 """
2275 with pytest.raises(TypeError):
2276 Connection(bad_context)
2277
Alex Gaynor03737182020-07-23 20:40:46 -04002278 @pytest.mark.parametrize("bad_bio", [object(), None, 1, [1, 2, 3]])
Daniel Holth079c9632019-11-17 22:45:52 -05002279 def test_bio_write_wrong_args(self, bad_bio):
2280 """
2281 `Connection.bio_write` raises `TypeError` if called with a non-bytes
2282 (or text) argument.
2283 """
2284 context = Context(TLSv1_METHOD)
2285 connection = Connection(context, None)
2286 with pytest.raises(TypeError):
2287 connection.bio_write(bad_bio)
2288
2289 def test_bio_write(self):
2290 """
2291 `Connection.bio_write` does not raise if called with bytes or
2292 bytearray, warns if called with text.
2293 """
2294 context = Context(TLSv1_METHOD)
2295 connection = Connection(context, None)
Alex Gaynor03737182020-07-23 20:40:46 -04002296 connection.bio_write(b"xy")
2297 connection.bio_write(bytearray(b"za"))
Daniel Holth079c9632019-11-17 22:45:52 -05002298 with pytest.warns(DeprecationWarning):
Alex Gaynor03737182020-07-23 20:40:46 -04002299 connection.bio_write(u"deprecated")
Daniel Holth079c9632019-11-17 22:45:52 -05002300
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002301 def test_get_context(self):
2302 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002303 `Connection.get_context` returns the `Context` instance used to
2304 construct the `Connection` instance.
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002305 """
2306 context = Context(TLSv1_METHOD)
2307 connection = Connection(context, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002308 assert connection.get_context() is context
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002309
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002310 def test_set_context_wrong_args(self):
2311 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002312 `Connection.set_context` raises `TypeError` if called with a
Alex Chanfb078d82017-04-20 11:16:15 +01002313 non-`Context` instance argument.
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002314 """
2315 ctx = Context(TLSv1_METHOD)
2316 connection = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002317 with pytest.raises(TypeError):
2318 connection.set_context(object())
2319 with pytest.raises(TypeError):
2320 connection.set_context("hello")
2321 with pytest.raises(TypeError):
2322 connection.set_context(1)
2323 assert ctx is connection.get_context()
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002324
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002325 def test_set_context(self):
2326 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002327 `Connection.set_context` specifies a new `Context` instance to be
2328 used for the connection.
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002329 """
2330 original = Context(SSLv23_METHOD)
2331 replacement = Context(TLSv1_METHOD)
2332 connection = Connection(original, None)
2333 connection.set_context(replacement)
Alex Chan1c0cb662017-01-30 07:13:30 +00002334 assert replacement is connection.get_context()
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002335 # Lose our references to the contexts, just in case the Connection
2336 # isn't properly managing its own contributions to their reference
2337 # counts.
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002338 del original, replacement
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002339 collect()
2340
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002341 def test_set_tlsext_host_name_wrong_args(self):
2342 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002343 If `Connection.set_tlsext_host_name` is called with a non-byte string
2344 argument or a byte string with an embedded NUL, `TypeError` is raised.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002345 """
2346 conn = Connection(Context(TLSv1_METHOD), None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002347 with pytest.raises(TypeError):
2348 conn.set_tlsext_host_name(object())
2349 with pytest.raises(TypeError):
2350 conn.set_tlsext_host_name(b"with\0null")
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002351
Hugo van Kemenade60827f82019-08-30 00:39:35 +03002352 if not PY2:
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002353 # On Python 3.x, don't accidentally implicitly convert from text.
Alex Chan1c0cb662017-01-30 07:13:30 +00002354 with pytest.raises(TypeError):
2355 conn.set_tlsext_host_name(b"example.com".decode("ascii"))
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04002356
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002357 def test_pending(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002358 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002359 `Connection.pending` returns the number of bytes available for
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002360 immediate read.
2361 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002362 connection = Connection(Context(TLSv1_METHOD), None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002363 assert connection.pending() == 0
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002364
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002365 def test_peek(self):
2366 """
Hynek Schlawack3bcf3152017-02-18 08:25:34 +01002367 `Connection.recv` peeks into the connection if `socket.MSG_PEEK` is
2368 passed.
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002369 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002370 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04002371 server.send(b"xy")
2372 assert client.recv(2, MSG_PEEK) == b"xy"
2373 assert client.recv(2, MSG_PEEK) == b"xy"
2374 assert client.recv(2) == b"xy"
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002375
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002376 def test_connect_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002377 """
Hynek Schlawack3bcf3152017-02-18 08:25:34 +01002378 `Connection.connect` raises `TypeError` if called with a non-address
2379 argument.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002380 """
David Benjamin1fbe0642019-04-15 17:05:13 -05002381 connection = Connection(Context(TLSv1_METHOD), socket_any_family())
Alex Chan1c0cb662017-01-30 07:13:30 +00002382 with pytest.raises(TypeError):
2383 connection.connect(None)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002384
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002385 def test_connect_refused(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002386 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002387 `Connection.connect` raises `socket.error` if the underlying socket
2388 connect method raises it.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002389 """
David Benjamin1fbe0642019-04-15 17:05:13 -05002390 client = socket_any_family()
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002391 context = Context(TLSv1_METHOD)
2392 clientSSL = Connection(context, client)
Alex Gaynor122717b2015-09-05 14:14:18 -04002393 # pytest.raises here doesn't work because of a bug in py.test on Python
2394 # 2.6: https://github.com/pytest-dev/pytest/issues/988
Alex Gaynore69c2782015-09-05 14:07:48 -04002395 try:
David Benjamin1fbe0642019-04-15 17:05:13 -05002396 clientSSL.connect((loopback_address(client), 1))
Alex Gaynore69c2782015-09-05 14:07:48 -04002397 except error as e:
Alex Gaynor20a4c082015-09-05 14:24:15 -04002398 exc = e
2399 assert exc.args[0] == ECONNREFUSED
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002400
2401 def test_connect(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002402 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002403 `Connection.connect` establishes a connection to the specified address.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002404 """
David Benjamin1fbe0642019-04-15 17:05:13 -05002405 port = socket_any_family()
Alex Gaynor03737182020-07-23 20:40:46 -04002406 port.bind(("", 0))
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002407 port.listen(3)
2408
David Benjamin1fbe0642019-04-15 17:05:13 -05002409 clientSSL = Connection(Context(TLSv1_METHOD), socket(port.family))
2410 clientSSL.connect((loopback_address(port), port.getsockname()[1]))
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002411 # XXX An assertion? Or something?
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002412
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002413 @pytest.mark.skipif(
2414 platform == "darwin",
Alex Gaynor03737182020-07-23 20:40:46 -04002415 reason="connect_ex sometimes causes a kernel panic on OS X 10.6.4",
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002416 )
2417 def test_connect_ex(self):
2418 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002419 If there is a connection error, `Connection.connect_ex` returns the
2420 errno instead of raising an exception.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002421 """
David Benjamin1fbe0642019-04-15 17:05:13 -05002422 port = socket_any_family()
Alex Gaynor03737182020-07-23 20:40:46 -04002423 port.bind(("", 0))
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002424 port.listen(3)
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002425
David Benjamin1fbe0642019-04-15 17:05:13 -05002426 clientSSL = Connection(Context(TLSv1_METHOD), socket(port.family))
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002427 clientSSL.setblocking(False)
2428 result = clientSSL.connect_ex(port.getsockname())
2429 expected = (EINPROGRESS, EWOULDBLOCK)
Alex Chan1c0cb662017-01-30 07:13:30 +00002430 assert result in expected
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002431
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002432 def test_accept(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002433 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002434 `Connection.accept` accepts a pending connection attempt and returns a
2435 tuple of a new `Connection` (the accepted client) and the address the
2436 connection originated from.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002437 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002438 ctx = Context(TLSv1_METHOD)
2439 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2440 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
David Benjamin1fbe0642019-04-15 17:05:13 -05002441 port = socket_any_family()
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002442 portSSL = Connection(ctx, port)
Alex Gaynor03737182020-07-23 20:40:46 -04002443 portSSL.bind(("", 0))
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002444 portSSL.listen(3)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002445
David Benjamin1fbe0642019-04-15 17:05:13 -05002446 clientSSL = Connection(Context(TLSv1_METHOD), socket(port.family))
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002447
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002448 # Calling portSSL.getsockname() here to get the server IP address
2449 # sounds great, but frequently fails on Windows.
David Benjamin1fbe0642019-04-15 17:05:13 -05002450 clientSSL.connect((loopback_address(port), portSSL.getsockname()[1]))
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002451
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002452 serverSSL, address = portSSL.accept()
2453
Alex Chan1c0cb662017-01-30 07:13:30 +00002454 assert isinstance(serverSSL, Connection)
2455 assert serverSSL.get_context() is ctx
2456 assert address == clientSSL.getsockname()
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002457
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002458 def test_shutdown_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002459 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002460 `Connection.set_shutdown` raises `TypeError` if called with arguments
2461 other than integers.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002462 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002463 connection = Connection(Context(TLSv1_METHOD), None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002464 with pytest.raises(TypeError):
2465 connection.set_shutdown(None)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002466
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002467 def test_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002468 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002469 `Connection.shutdown` performs an SSL-level connection shutdown.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002470 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002471 server, client = loopback()
2472 assert not server.shutdown()
2473 assert server.get_shutdown() == SENT_SHUTDOWN
2474 with pytest.raises(ZeroReturnError):
2475 client.recv(1024)
2476 assert client.get_shutdown() == RECEIVED_SHUTDOWN
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04002477 client.shutdown()
Alex Chan1c0cb662017-01-30 07:13:30 +00002478 assert client.get_shutdown() == (SENT_SHUTDOWN | RECEIVED_SHUTDOWN)
2479 with pytest.raises(ZeroReturnError):
2480 server.recv(1024)
2481 assert server.get_shutdown() == (SENT_SHUTDOWN | RECEIVED_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002482
Paul Aurichc85e0862015-01-08 08:34:33 -08002483 def test_shutdown_closed(self):
2484 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002485 If the underlying socket is closed, `Connection.shutdown` propagates
2486 the write error from the low level write call.
Paul Aurichc85e0862015-01-08 08:34:33 -08002487 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002488 server, client = loopback()
Paul Aurichc85e0862015-01-08 08:34:33 -08002489 server.sock_shutdown(2)
Alex Chan1c0cb662017-01-30 07:13:30 +00002490 with pytest.raises(SysCallError) as exc:
2491 server.shutdown()
Alex Chanfb078d82017-04-20 11:16:15 +01002492 if platform == "win32":
2493 assert exc.value.args[0] == ESHUTDOWN
2494 else:
2495 assert exc.value.args[0] == EPIPE
Paul Aurichc85e0862015-01-08 08:34:33 -08002496
Glyph89389472015-04-14 17:29:26 -04002497 def test_shutdown_truncated(self):
Glyph6064ec32015-04-14 16:38:22 -04002498 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002499 If the underlying connection is truncated, `Connection.shutdown`
2500 raises an `Error`.
Glyph6064ec32015-04-14 16:38:22 -04002501 """
Glyph89389472015-04-14 17:29:26 -04002502 server_ctx = Context(TLSv1_METHOD)
2503 client_ctx = Context(TLSv1_METHOD)
2504 server_ctx.use_privatekey(
Alex Gaynor03737182020-07-23 20:40:46 -04002505 load_privatekey(FILETYPE_PEM, server_key_pem)
2506 )
Glyph89389472015-04-14 17:29:26 -04002507 server_ctx.use_certificate(
Alex Gaynor03737182020-07-23 20:40:46 -04002508 load_certificate(FILETYPE_PEM, server_cert_pem)
2509 )
Glyph89389472015-04-14 17:29:26 -04002510 server = Connection(server_ctx, None)
2511 client = Connection(client_ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002512 handshake_in_memory(client, server)
2513 assert not server.shutdown()
2514 with pytest.raises(WantReadError):
2515 server.shutdown()
Glyph89389472015-04-14 17:29:26 -04002516 server.bio_shutdown()
Alex Chan1c0cb662017-01-30 07:13:30 +00002517 with pytest.raises(Error):
2518 server.shutdown()
Glyph6064ec32015-04-14 16:38:22 -04002519
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002520 def test_set_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002521 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002522 `Connection.set_shutdown` sets the state of the SSL connection
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002523 shutdown process.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002524 """
David Benjamin1fbe0642019-04-15 17:05:13 -05002525 connection = Connection(Context(TLSv1_METHOD), socket_any_family())
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002526 connection.set_shutdown(RECEIVED_SHUTDOWN)
Alex Chan1c0cb662017-01-30 07:13:30 +00002527 assert connection.get_shutdown() == RECEIVED_SHUTDOWN
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002528
kjavaf248592015-09-07 12:14:01 +01002529 def test_state_string(self):
2530 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002531 `Connection.state_string` verbosely describes the current state of
2532 the `Connection`.
kjavaf248592015-09-07 12:14:01 +01002533 """
Hynek Schlawackb0274ce2015-10-16 19:56:26 +02002534 server, client = socket_pair()
Alex Chan1c0cb662017-01-30 07:13:30 +00002535 server = loopback_server_factory(server)
2536 client = loopback_client_factory(client)
kjavaf248592015-09-07 12:14:01 +01002537
Alex Gaynor5af32d02016-09-24 01:52:21 -04002538 assert server.get_state_string() in [
Alex Gaynor03737182020-07-23 20:40:46 -04002539 b"before/accept initialization",
2540 b"before SSL initialization",
Alex Gaynor5af32d02016-09-24 01:52:21 -04002541 ]
2542 assert client.get_state_string() in [
Alex Gaynor03737182020-07-23 20:40:46 -04002543 b"before/connect initialization",
2544 b"before SSL initialization",
Alex Gaynor5af32d02016-09-24 01:52:21 -04002545 ]
kjavaf248592015-09-07 12:14:01 +01002546
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002547 def test_app_data(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002548 """
2549 Any object can be set as app data by passing it to
Alex Chan1c0cb662017-01-30 07:13:30 +00002550 `Connection.set_app_data` and later retrieved with
2551 `Connection.get_app_data`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002552 """
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002553 conn = Connection(Context(TLSv1_METHOD), None)
Todd Chapman4f73e4f2015-08-27 11:26:43 -04002554 assert None is conn.get_app_data()
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002555 app_data = object()
2556 conn.set_app_data(app_data)
Todd Chapman4f73e4f2015-08-27 11:26:43 -04002557 assert conn.get_app_data() is app_data
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002558
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002559 def test_makefile(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002560 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002561 `Connection.makefile` is not implemented and calling that
2562 method raises `NotImplementedError`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002563 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002564 conn = Connection(Context(TLSv1_METHOD), None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002565 with pytest.raises(NotImplementedError):
2566 conn.makefile()
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002567
Jeremy Lainé460a19d2018-05-16 19:44:19 +02002568 def test_get_certificate(self):
2569 """
2570 `Connection.get_certificate` returns the local certificate.
2571 """
2572 chain = _create_certificate_chain()
2573 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
2574
2575 context = Context(TLSv1_METHOD)
2576 context.use_certificate(scert)
2577 client = Connection(context, None)
2578 cert = client.get_certificate()
2579 assert cert is not None
2580 assert "Server Certificate" == cert.get_subject().CN
2581
2582 def test_get_certificate_none(self):
2583 """
2584 `Connection.get_certificate` returns the local certificate.
2585
2586 If there is no certificate, it returns None.
2587 """
2588 context = Context(TLSv1_METHOD)
2589 client = Connection(context, None)
2590 cert = client.get_certificate()
2591 assert cert is None
2592
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002593 def test_get_peer_cert_chain(self):
2594 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002595 `Connection.get_peer_cert_chain` returns a list of certificates
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002596 which the connected server returned for the certification verification.
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002597 """
2598 chain = _create_certificate_chain()
2599 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
2600
2601 serverContext = Context(TLSv1_METHOD)
2602 serverContext.use_privatekey(skey)
2603 serverContext.use_certificate(scert)
2604 serverContext.add_extra_chain_cert(icert)
2605 serverContext.add_extra_chain_cert(cacert)
2606 server = Connection(serverContext, None)
2607 server.set_accept_state()
2608
2609 # Create the client
2610 clientContext = Context(TLSv1_METHOD)
2611 clientContext.set_verify(VERIFY_NONE, verify_cb)
2612 client = Connection(clientContext, None)
2613 client.set_connect_state()
2614
Alex Chan1c0cb662017-01-30 07:13:30 +00002615 interact_in_memory(client, server)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002616
2617 chain = client.get_peer_cert_chain()
Alex Chan1c0cb662017-01-30 07:13:30 +00002618 assert len(chain) == 3
2619 assert "Server Certificate" == chain[0].get_subject().CN
2620 assert "Intermediate Certificate" == chain[1].get_subject().CN
2621 assert "Authority Certificate" == chain[2].get_subject().CN
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002622
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002623 def test_get_peer_cert_chain_none(self):
2624 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002625 `Connection.get_peer_cert_chain` returns `None` if the peer sends
2626 no certificate chain.
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002627 """
2628 ctx = Context(TLSv1_METHOD)
2629 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2630 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
2631 server = Connection(ctx, None)
2632 server.set_accept_state()
2633 client = Connection(Context(TLSv1_METHOD), None)
2634 client.set_connect_state()
Alex Chan1c0cb662017-01-30 07:13:30 +00002635 interact_in_memory(client, server)
2636 assert None is server.get_peer_cert_chain()
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002637
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002638 def test_get_session_unconnected(self):
2639 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002640 `Connection.get_session` returns `None` when used with an object
2641 which has not been connected.
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002642 """
2643 ctx = Context(TLSv1_METHOD)
2644 server = Connection(ctx, None)
2645 session = server.get_session()
Alex Chan1c0cb662017-01-30 07:13:30 +00002646 assert None is session
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002647
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002648 def test_server_get_session(self):
2649 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002650 On the server side of a connection, `Connection.get_session` returns a
2651 `Session` instance representing the SSL session for that connection.
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002652 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002653 server, client = loopback()
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002654 session = server.get_session()
Alex Chan1c0cb662017-01-30 07:13:30 +00002655 assert isinstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002656
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002657 def test_client_get_session(self):
2658 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002659 On the client side of a connection, `Connection.get_session`
2660 returns a `Session` instance representing the SSL session for
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002661 that connection.
2662 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002663 server, client = loopback()
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002664 session = client.get_session()
Alex Chan1c0cb662017-01-30 07:13:30 +00002665 assert isinstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002666
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002667 def test_set_session_wrong_args(self):
2668 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002669 `Connection.set_session` raises `TypeError` if called with an object
2670 that is not an instance of `Session`.
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002671 """
2672 ctx = Context(TLSv1_METHOD)
2673 connection = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002674 with pytest.raises(TypeError):
2675 connection.set_session(123)
2676 with pytest.raises(TypeError):
2677 connection.set_session("hello")
2678 with pytest.raises(TypeError):
2679 connection.set_session(object())
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002680
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002681 def test_client_set_session(self):
2682 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002683 `Connection.set_session`, when used prior to a connection being
2684 established, accepts a `Session` instance and causes an attempt to
2685 re-use the session it represents when the SSL handshake is performed.
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002686 """
2687 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2688 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
Paul Kehrer7d5a3bf2019-01-21 12:24:02 -06002689 ctx = Context(TLSv1_2_METHOD)
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002690 ctx.use_privatekey(key)
2691 ctx.use_certificate(cert)
2692 ctx.set_session_id("unity-test")
2693
2694 def makeServer(socket):
2695 server = Connection(ctx, socket)
2696 server.set_accept_state()
2697 return server
2698
Alex Gaynor03737182020-07-23 20:40:46 -04002699 originalServer, originalClient = loopback(server_factory=makeServer)
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002700 originalSession = originalClient.get_session()
2701
2702 def makeClient(socket):
Alex Chan1c0cb662017-01-30 07:13:30 +00002703 client = loopback_client_factory(socket)
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002704 client.set_session(originalSession)
2705 return client
Alex Gaynor03737182020-07-23 20:40:46 -04002706
Alex Chan1c0cb662017-01-30 07:13:30 +00002707 resumedServer, resumedClient = loopback(
Alex Gaynor03737182020-07-23 20:40:46 -04002708 server_factory=makeServer, client_factory=makeClient
2709 )
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002710
2711 # This is a proxy: in general, we have no access to any unique
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002712 # identifier for the session (new enough versions of OpenSSL expose
2713 # a hash which could be usable, but "new enough" is very, very new).
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002714 # Instead, exploit the fact that the master key is re-used if the
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002715 # session is re-used. As long as the master key for the two
2716 # connections is the same, the session was re-used!
Alex Chan1c0cb662017-01-30 07:13:30 +00002717 assert originalServer.master_key() == resumedServer.master_key()
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002718
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002719 def test_set_session_wrong_method(self):
2720 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002721 If `Connection.set_session` is passed a `Session` instance associated
2722 with a context using a different SSL method than the `Connection`
2723 is using, a `OpenSSL.SSL.Error` is raised.
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002724 """
Alex Gaynor5af32d02016-09-24 01:52:21 -04002725 # Make this work on both OpenSSL 1.0.0, which doesn't support TLSv1.2
2726 # and also on OpenSSL 1.1.0 which doesn't support SSLv3. (SSL_ST_INIT
2727 # is a way to check for 1.1.0)
Alex Gaynoraa32e712017-06-29 20:56:12 -07002728 if SSL_ST_INIT is None:
2729 v1 = TLSv1_2_METHOD
2730 v2 = TLSv1_METHOD
2731 elif hasattr(_lib, "SSLv3_method"):
Alex Gaynor5af32d02016-09-24 01:52:21 -04002732 v1 = TLSv1_METHOD
2733 v2 = SSLv3_METHOD
2734 else:
Alex Gaynoraa32e712017-06-29 20:56:12 -07002735 pytest.skip("Test requires either OpenSSL 1.1.0 or SSLv3")
Alex Gaynor5af32d02016-09-24 01:52:21 -04002736
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002737 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2738 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
Alex Gaynor5af32d02016-09-24 01:52:21 -04002739 ctx = Context(v1)
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002740 ctx.use_privatekey(key)
2741 ctx.use_certificate(cert)
2742 ctx.set_session_id("unity-test")
2743
2744 def makeServer(socket):
2745 server = Connection(ctx, socket)
2746 server.set_accept_state()
2747 return server
2748
Alex Gaynor5af32d02016-09-24 01:52:21 -04002749 def makeOriginalClient(socket):
2750 client = Connection(Context(v1), socket)
2751 client.set_connect_state()
2752 return client
2753
Alex Chan1c0cb662017-01-30 07:13:30 +00002754 originalServer, originalClient = loopback(
Alex Gaynor03737182020-07-23 20:40:46 -04002755 server_factory=makeServer, client_factory=makeOriginalClient
2756 )
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002757 originalSession = originalClient.get_session()
2758
2759 def makeClient(socket):
2760 # Intentionally use a different, incompatible method here.
Alex Gaynor5af32d02016-09-24 01:52:21 -04002761 client = Connection(Context(v2), socket)
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002762 client.set_connect_state()
2763 client.set_session(originalSession)
2764 return client
2765
Alex Chan1c0cb662017-01-30 07:13:30 +00002766 with pytest.raises(Error):
2767 loopback(client_factory=makeClient, server_factory=makeServer)
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002768
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002769 def test_wantWriteError(self):
2770 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002771 `Connection` methods which generate output raise
2772 `OpenSSL.SSL.WantWriteError` if writing to the connection's BIO
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002773 fail indicating a should-write state.
2774 """
2775 client_socket, server_socket = socket_pair()
2776 # Fill up the client's send buffer so Connection won't be able to write
Jean-Paul Calderonebbff8b92014-03-22 14:20:30 -04002777 # anything. Only write a single byte at a time so we can be sure we
2778 # completely fill the buffer. Even though the socket API is allowed to
2779 # signal a short write via its return value it seems this doesn't
2780 # always happen on all platforms (FreeBSD and OS X particular) for the
2781 # very last bit of available buffer space.
2782 msg = b"x"
caternb2777a42018-08-09 15:38:13 -04002783 for i in range(1024 * 1024 * 64):
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002784 try:
2785 client_socket.send(msg)
2786 except error as e:
2787 if e.errno == EWOULDBLOCK:
2788 break
2789 raise
2790 else:
Alex Chan1c0cb662017-01-30 07:13:30 +00002791 pytest.fail(
Alex Gaynor03737182020-07-23 20:40:46 -04002792 "Failed to fill socket buffer, cannot test BIO want write"
2793 )
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002794
2795 ctx = Context(TLSv1_METHOD)
2796 conn = Connection(ctx, client_socket)
2797 # Client's speak first, so make it an SSL client
2798 conn.set_connect_state()
Alex Chan1c0cb662017-01-30 07:13:30 +00002799 with pytest.raises(WantWriteError):
2800 conn.do_handshake()
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002801
2802 # XXX want_read
2803
Fedor Brunner416f4a12014-03-28 13:18:38 +01002804 def test_get_finished_before_connect(self):
Fedor Brunner5747b932014-03-05 14:22:34 +01002805 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002806 `Connection.get_finished` returns `None` before TLS handshake
2807 is completed.
Fedor Brunner5747b932014-03-05 14:22:34 +01002808 """
Fedor Brunner5747b932014-03-05 14:22:34 +01002809 ctx = Context(TLSv1_METHOD)
2810 connection = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002811 assert connection.get_finished() is None
Fedor Brunner416f4a12014-03-28 13:18:38 +01002812
2813 def test_get_peer_finished_before_connect(self):
2814 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002815 `Connection.get_peer_finished` returns `None` before TLS handshake
2816 is completed.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002817 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002818 ctx = Context(TLSv1_METHOD)
2819 connection = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002820 assert connection.get_peer_finished() is None
Fedor Brunner5747b932014-03-05 14:22:34 +01002821
Fedor Brunner416f4a12014-03-28 13:18:38 +01002822 def test_get_finished(self):
2823 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002824 `Connection.get_finished` method returns the TLS Finished message send
2825 from client, or server. Finished messages are send during
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002826 TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002827 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002828 server, client = loopback()
Fedor Brunner416f4a12014-03-28 13:18:38 +01002829
Alex Chan1c0cb662017-01-30 07:13:30 +00002830 assert server.get_finished() is not None
2831 assert len(server.get_finished()) > 0
Fedor Brunner416f4a12014-03-28 13:18:38 +01002832
2833 def test_get_peer_finished(self):
2834 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002835 `Connection.get_peer_finished` method returns the TLS Finished
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002836 message received from client, or server. Finished messages are send
2837 during TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002838 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002839 server, client = loopback()
Fedor Brunner416f4a12014-03-28 13:18:38 +01002840
Alex Chan1c0cb662017-01-30 07:13:30 +00002841 assert server.get_peer_finished() is not None
2842 assert len(server.get_peer_finished()) > 0
Fedor Brunner5747b932014-03-05 14:22:34 +01002843
Fedor Brunner416f4a12014-03-28 13:18:38 +01002844 def test_tls_finished_message_symmetry(self):
2845 """
Hynek Schlawackdddd1112015-09-05 21:12:30 +02002846 The TLS Finished message send by server must be the TLS Finished
2847 message received by client.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002848
Hynek Schlawackdddd1112015-09-05 21:12:30 +02002849 The TLS Finished message send by client must be the TLS Finished
2850 message received by server.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002851 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002852 server, client = loopback()
Fedor Brunner416f4a12014-03-28 13:18:38 +01002853
Alex Chan1c0cb662017-01-30 07:13:30 +00002854 assert server.get_finished() == client.get_peer_finished()
2855 assert client.get_finished() == server.get_peer_finished()
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002856
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002857 def test_get_cipher_name_before_connect(self):
2858 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002859 `Connection.get_cipher_name` returns `None` if no connection
2860 has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002861 """
2862 ctx = Context(TLSv1_METHOD)
2863 conn = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002864 assert conn.get_cipher_name() is None
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002865
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002866 def test_get_cipher_name(self):
2867 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002868 `Connection.get_cipher_name` returns a `unicode` string giving the
2869 name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002870 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002871 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04002872 server_cipher_name, client_cipher_name = (
2873 server.get_cipher_name(),
2874 client.get_cipher_name(),
2875 )
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002876
Alex Chan1c0cb662017-01-30 07:13:30 +00002877 assert isinstance(server_cipher_name, text_type)
2878 assert isinstance(client_cipher_name, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002879
Alex Chan1c0cb662017-01-30 07:13:30 +00002880 assert server_cipher_name == client_cipher_name
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002881
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002882 def test_get_cipher_version_before_connect(self):
2883 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002884 `Connection.get_cipher_version` returns `None` if no connection
2885 has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002886 """
2887 ctx = Context(TLSv1_METHOD)
2888 conn = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002889 assert conn.get_cipher_version() is None
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002890
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002891 def test_get_cipher_version(self):
2892 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002893 `Connection.get_cipher_version` returns a `unicode` string giving
2894 the protocol name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002895 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002896 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04002897 server_cipher_version, client_cipher_version = (
2898 server.get_cipher_version(),
2899 client.get_cipher_version(),
2900 )
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002901
Alex Chan1c0cb662017-01-30 07:13:30 +00002902 assert isinstance(server_cipher_version, text_type)
2903 assert isinstance(client_cipher_version, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002904
Alex Chan1c0cb662017-01-30 07:13:30 +00002905 assert server_cipher_version == client_cipher_version
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002906
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002907 def test_get_cipher_bits_before_connect(self):
2908 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002909 `Connection.get_cipher_bits` returns `None` if no connection has
2910 been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002911 """
2912 ctx = Context(TLSv1_METHOD)
2913 conn = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002914 assert conn.get_cipher_bits() is None
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002915
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002916 def test_get_cipher_bits(self):
2917 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002918 `Connection.get_cipher_bits` returns the number of secret bits
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002919 of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002920 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002921 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04002922 server_cipher_bits, client_cipher_bits = (
2923 server.get_cipher_bits(),
2924 client.get_cipher_bits(),
2925 )
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002926
Alex Chan1c0cb662017-01-30 07:13:30 +00002927 assert isinstance(server_cipher_bits, int)
2928 assert isinstance(client_cipher_bits, int)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002929
Alex Chan1c0cb662017-01-30 07:13:30 +00002930 assert server_cipher_bits == client_cipher_bits
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002931
Jim Shaverabff1882015-05-27 09:15:55 -04002932 def test_get_protocol_version_name(self):
2933 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002934 `Connection.get_protocol_version_name()` returns a string giving the
2935 protocol version of the current connection.
Jim Shaverabff1882015-05-27 09:15:55 -04002936 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002937 server, client = loopback()
Jim Shaverabff1882015-05-27 09:15:55 -04002938 client_protocol_version_name = client.get_protocol_version_name()
2939 server_protocol_version_name = server.get_protocol_version_name()
2940
Alex Chan1c0cb662017-01-30 07:13:30 +00002941 assert isinstance(server_protocol_version_name, text_type)
2942 assert isinstance(client_protocol_version_name, text_type)
Jim Shaverabff1882015-05-27 09:15:55 -04002943
Alex Chan1c0cb662017-01-30 07:13:30 +00002944 assert server_protocol_version_name == client_protocol_version_name
Jim Shaverabff1882015-05-27 09:15:55 -04002945
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002946 def test_get_protocol_version(self):
2947 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002948 `Connection.get_protocol_version()` returns an integer
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002949 giving the protocol version of the current connection.
2950 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002951 server, client = loopback()
Jim Shaver85a4dff2015-04-27 17:42:46 -04002952 client_protocol_version = client.get_protocol_version()
2953 server_protocol_version = server.get_protocol_version()
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002954
Alex Chan1c0cb662017-01-30 07:13:30 +00002955 assert isinstance(server_protocol_version, int)
2956 assert isinstance(client_protocol_version, int)
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002957
Alex Chan1c0cb662017-01-30 07:13:30 +00002958 assert server_protocol_version == client_protocol_version
2959
2960 def test_wantReadError(self):
2961 """
2962 `Connection.bio_read` raises `OpenSSL.SSL.WantReadError` if there are
2963 no bytes available to be read from the BIO.
2964 """
2965 ctx = Context(TLSv1_METHOD)
2966 conn = Connection(ctx, None)
2967 with pytest.raises(WantReadError):
2968 conn.bio_read(1024)
2969
Alex Gaynor03737182020-07-23 20:40:46 -04002970 @pytest.mark.parametrize("bufsize", [1.0, None, object(), "bufsize"])
Alex Chanfb078d82017-04-20 11:16:15 +01002971 def test_bio_read_wrong_args(self, bufsize):
2972 """
2973 `Connection.bio_read` raises `TypeError` if passed a non-integer
2974 argument.
2975 """
2976 ctx = Context(TLSv1_METHOD)
2977 conn = Connection(ctx, None)
2978 with pytest.raises(TypeError):
2979 conn.bio_read(bufsize)
2980
Alex Chan1c0cb662017-01-30 07:13:30 +00002981 def test_buffer_size(self):
2982 """
2983 `Connection.bio_read` accepts an integer giving the maximum number
2984 of bytes to read and return.
2985 """
2986 ctx = Context(TLSv1_METHOD)
2987 conn = Connection(ctx, None)
2988 conn.set_connect_state()
2989 try:
2990 conn.do_handshake()
2991 except WantReadError:
2992 pass
2993 data = conn.bio_read(2)
2994 assert 2 == len(data)
2995
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002996
Alex Chanb7480992017-01-30 14:04:47 +00002997class TestConnectionGetCipherList(object):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002998 """
Alex Chanb7480992017-01-30 14:04:47 +00002999 Tests for `Connection.get_cipher_list`.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003000 """
Alex Gaynor03737182020-07-23 20:40:46 -04003001
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04003002 def test_result(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003003 """
Alex Chanb7480992017-01-30 14:04:47 +00003004 `Connection.get_cipher_list` returns a list of `bytes` giving the
3005 names of the ciphers which might be used.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003006 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04003007 connection = Connection(Context(TLSv1_METHOD), None)
3008 ciphers = connection.get_cipher_list()
Alex Chanb7480992017-01-30 14:04:47 +00003009 assert isinstance(ciphers, list)
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04003010 for cipher in ciphers:
Alex Chanb7480992017-01-30 14:04:47 +00003011 assert isinstance(cipher, str)
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04003012
3013
Maximilian Hils868dc3c2017-02-10 14:56:55 +01003014class VeryLarge(bytes):
3015 """
3016 Mock object so that we don't have to allocate 2**31 bytes
3017 """
Alex Gaynor03737182020-07-23 20:40:46 -04003018
Maximilian Hils868dc3c2017-02-10 14:56:55 +01003019 def __len__(self):
Alex Gaynor03737182020-07-23 20:40:46 -04003020 return 2 ** 31
Maximilian Hils868dc3c2017-02-10 14:56:55 +01003021
3022
Alex Chanb7480992017-01-30 14:04:47 +00003023class TestConnectionSend(object):
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05003024 """
Alex Chanb7480992017-01-30 14:04:47 +00003025 Tests for `Connection.send`.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05003026 """
Alex Gaynor03737182020-07-23 20:40:46 -04003027
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05003028 def test_wrong_args(self):
3029 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003030 When called with arguments other than string argument for its first
Alex Chanb7480992017-01-30 14:04:47 +00003031 parameter, `Connection.send` raises `TypeError`.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05003032 """
3033 connection = Connection(Context(TLSv1_METHOD), None)
Alex Chanb7480992017-01-30 14:04:47 +00003034 with pytest.raises(TypeError):
3035 connection.send(object())
Daniel Holth079c9632019-11-17 22:45:52 -05003036 with pytest.raises(TypeError):
3037 connection.send([1, 2, 3])
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05003038
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05003039 def test_short_bytes(self):
3040 """
Alex Chanb7480992017-01-30 14:04:47 +00003041 When passed a short byte string, `Connection.send` transmits all of it
3042 and returns the number of bytes sent.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05003043 """
Alex Chanb7480992017-01-30 14:04:47 +00003044 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04003045 count = server.send(b"xy")
Alex Chanb7480992017-01-30 14:04:47 +00003046 assert count == 2
Alex Gaynor03737182020-07-23 20:40:46 -04003047 assert client.recv(2) == b"xy"
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05003048
Abraham Martinef063482015-03-25 14:06:24 +00003049 def test_text(self):
3050 """
Alex Chanb7480992017-01-30 14:04:47 +00003051 When passed a text, `Connection.send` transmits all of it and
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04003052 returns the number of bytes sent. It also raises a DeprecationWarning.
Abraham Martinef063482015-03-25 14:06:24 +00003053 """
Alex Chanb7480992017-01-30 14:04:47 +00003054 server, client = loopback()
3055 with pytest.warns(DeprecationWarning) as w:
Abraham Martinef063482015-03-25 14:06:24 +00003056 simplefilter("always")
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04003057 count = server.send(b"xy".decode("ascii"))
Alex Gaynor03737182020-07-23 20:40:46 -04003058 assert "{0} for buf is no longer accepted, use bytes".format(
3059 WARNING_TYPE_EXPECTED
3060 ) == str(w[-1].message)
Alex Chanb7480992017-01-30 14:04:47 +00003061 assert count == 2
Alex Gaynor03737182020-07-23 20:40:46 -04003062 assert client.recv(2) == b"xy"
Abraham Martinef063482015-03-25 14:06:24 +00003063
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003064 def test_short_memoryview(self):
3065 """
3066 When passed a memoryview onto a small number of bytes,
Alex Chanb7480992017-01-30 14:04:47 +00003067 `Connection.send` transmits all of them and returns the number
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003068 of bytes sent.
3069 """
Alex Chanb7480992017-01-30 14:04:47 +00003070 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04003071 count = server.send(memoryview(b"xy"))
Alex Chanb7480992017-01-30 14:04:47 +00003072 assert count == 2
Alex Gaynor03737182020-07-23 20:40:46 -04003073 assert client.recv(2) == b"xy"
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05003074
Daniel Holth079c9632019-11-17 22:45:52 -05003075 def test_short_bytearray(self):
3076 """
3077 When passed a short bytearray, `Connection.send` transmits all of
3078 it and returns the number of bytes sent.
3079 """
3080 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04003081 count = server.send(bytearray(b"xy"))
Daniel Holth079c9632019-11-17 22:45:52 -05003082 assert count == 2
Alex Gaynor03737182020-07-23 20:40:46 -04003083 assert client.recv(2) == b"xy"
Daniel Holth079c9632019-11-17 22:45:52 -05003084
Hynek Schlawack8e94f1b2015-09-05 21:31:00 +02003085 @skip_if_py3
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003086 def test_short_buffer(self):
3087 """
3088 When passed a buffer containing a small number of bytes,
Alex Chanb7480992017-01-30 14:04:47 +00003089 `Connection.send` transmits all of them and returns the number
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003090 of bytes sent.
3091 """
Alex Chanb7480992017-01-30 14:04:47 +00003092 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04003093 count = server.send(buffer(b"xy")) # noqa: F821
Alex Chanb7480992017-01-30 14:04:47 +00003094 assert count == 2
Alex Gaynor03737182020-07-23 20:40:46 -04003095 assert client.recv(2) == b"xy"
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02003096
Maximilian Hils868dc3c2017-02-10 14:56:55 +01003097 @pytest.mark.skipif(
Alex Gaynor03737182020-07-23 20:40:46 -04003098 sys.maxsize < 2 ** 31,
3099 reason="sys.maxsize < 2**31 - test requires 64 bit",
Maximilian Hils868dc3c2017-02-10 14:56:55 +01003100 )
3101 def test_buf_too_large(self):
3102 """
3103 When passed a buffer containing >= 2**31 bytes,
3104 `Connection.send` bails out as SSL_write only
3105 accepts an int for the buffer length.
3106 """
3107 connection = Connection(Context(TLSv1_METHOD), None)
3108 with pytest.raises(ValueError) as exc_info:
3109 connection.send(VeryLarge())
3110 exc_info.match(r"Cannot send more than .+ bytes at once")
3111
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05003112
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003113def _make_memoryview(size):
3114 """
3115 Create a new ``memoryview`` wrapped around a ``bytearray`` of the given
3116 size.
3117 """
3118 return memoryview(bytearray(size))
3119
3120
Alex Chanb7480992017-01-30 14:04:47 +00003121class TestConnectionRecvInto(object):
Cory Benfield62d10332014-06-15 10:03:41 +01003122 """
Alex Chanb7480992017-01-30 14:04:47 +00003123 Tests for `Connection.recv_into`.
Cory Benfield62d10332014-06-15 10:03:41 +01003124 """
Alex Gaynor03737182020-07-23 20:40:46 -04003125
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003126 def _no_length_test(self, factory):
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04003127 """
Alex Chanb7480992017-01-30 14:04:47 +00003128 Assert that when the given buffer is passed to `Connection.recv_into`,
3129 whatever bytes are available to be received that fit into that buffer
3130 are written into that buffer.
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04003131 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003132 output_buffer = factory(5)
3133
Alex Chanb7480992017-01-30 14:04:47 +00003134 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04003135 server.send(b"xy")
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04003136
Alex Chanb7480992017-01-30 14:04:47 +00003137 assert client.recv_into(output_buffer) == 2
Alex Gaynor03737182020-07-23 20:40:46 -04003138 assert output_buffer == bytearray(b"xy\x00\x00\x00")
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04003139
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04003140 def test_bytearray_no_length(self):
Cory Benfield62d10332014-06-15 10:03:41 +01003141 """
Alex Chanb7480992017-01-30 14:04:47 +00003142 `Connection.recv_into` can be passed a `bytearray` instance and data
3143 in the receive buffer is written to it.
Cory Benfield62d10332014-06-15 10:03:41 +01003144 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003145 self._no_length_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01003146
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003147 def _respects_length_test(self, factory):
Cory Benfield62d10332014-06-15 10:03:41 +01003148 """
Alex Chanb7480992017-01-30 14:04:47 +00003149 Assert that when the given buffer is passed to `Connection.recv_into`
3150 along with a value for `nbytes` that is less than the size of that
3151 buffer, only `nbytes` bytes are written into the buffer.
Cory Benfield62d10332014-06-15 10:03:41 +01003152 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003153 output_buffer = factory(10)
3154
Alex Chanb7480992017-01-30 14:04:47 +00003155 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04003156 server.send(b"abcdefghij")
Cory Benfield62d10332014-06-15 10:03:41 +01003157
Alex Chanb7480992017-01-30 14:04:47 +00003158 assert client.recv_into(output_buffer, 5) == 5
Alex Gaynor03737182020-07-23 20:40:46 -04003159 assert output_buffer == bytearray(b"abcde\x00\x00\x00\x00\x00")
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04003160
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04003161 def test_bytearray_respects_length(self):
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04003162 """
Alex Chanb7480992017-01-30 14:04:47 +00003163 When called with a `bytearray` instance, `Connection.recv_into`
3164 respects the `nbytes` parameter and doesn't copy in more than that
3165 number of bytes.
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04003166 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003167 self._respects_length_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01003168
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003169 def _doesnt_overfill_test(self, factory):
Cory Benfield62d10332014-06-15 10:03:41 +01003170 """
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04003171 Assert that if there are more bytes available to be read from the
3172 receive buffer than would fit into the buffer passed to
Alex Chanb7480992017-01-30 14:04:47 +00003173 `Connection.recv_into`, only as many as fit are written into it.
Cory Benfield62d10332014-06-15 10:03:41 +01003174 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003175 output_buffer = factory(5)
3176
Alex Chanb7480992017-01-30 14:04:47 +00003177 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04003178 server.send(b"abcdefghij")
Cory Benfield62d10332014-06-15 10:03:41 +01003179
Alex Chanb7480992017-01-30 14:04:47 +00003180 assert client.recv_into(output_buffer) == 5
Alex Gaynor03737182020-07-23 20:40:46 -04003181 assert output_buffer == bytearray(b"abcde")
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04003182 rest = client.recv(5)
Alex Gaynor03737182020-07-23 20:40:46 -04003183 assert b"fghij" == rest
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04003184
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04003185 def test_bytearray_doesnt_overfill(self):
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04003186 """
Alex Chanb7480992017-01-30 14:04:47 +00003187 When called with a `bytearray` instance, `Connection.recv_into`
3188 respects the size of the array and doesn't write more bytes into it
3189 than will fit.
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04003190 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003191 self._doesnt_overfill_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01003192
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04003193 def test_bytearray_really_doesnt_overfill(self):
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003194 """
Alex Chanb7480992017-01-30 14:04:47 +00003195 When called with a `bytearray` instance and an `nbytes` value that is
3196 too large, `Connection.recv_into` respects the size of the array and
3197 not the `nbytes` value and doesn't write more bytes into the buffer
3198 than will fit.
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003199 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003200 self._doesnt_overfill_test(bytearray)
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003201
Maximilian Hils1d95dea2015-08-17 19:27:20 +02003202 def test_peek(self):
Alex Chanb7480992017-01-30 14:04:47 +00003203 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04003204 server.send(b"xy")
Maximilian Hils1d95dea2015-08-17 19:27:20 +02003205
3206 for _ in range(2):
3207 output_buffer = bytearray(5)
Alex Chanb7480992017-01-30 14:04:47 +00003208 assert client.recv_into(output_buffer, flags=MSG_PEEK) == 2
Alex Gaynor03737182020-07-23 20:40:46 -04003209 assert output_buffer == bytearray(b"xy\x00\x00\x00")
Maximilian Hils1d95dea2015-08-17 19:27:20 +02003210
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003211 def test_memoryview_no_length(self):
3212 """
Alex Chanb7480992017-01-30 14:04:47 +00003213 `Connection.recv_into` can be passed a `memoryview` instance and data
3214 in the receive buffer is written to it.
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003215 """
3216 self._no_length_test(_make_memoryview)
Maximilian Hils1d95dea2015-08-17 19:27:20 +02003217
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003218 def test_memoryview_respects_length(self):
3219 """
Alex Chanb7480992017-01-30 14:04:47 +00003220 When called with a `memoryview` instance, `Connection.recv_into`
3221 respects the ``nbytes`` parameter and doesn't copy more than that
3222 number of bytes in.
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003223 """
3224 self._respects_length_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01003225
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003226 def test_memoryview_doesnt_overfill(self):
3227 """
Alex Chanb7480992017-01-30 14:04:47 +00003228 When called with a `memoryview` instance, `Connection.recv_into`
3229 respects the size of the array and doesn't write more bytes into it
3230 than will fit.
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003231 """
3232 self._doesnt_overfill_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01003233
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003234 def test_memoryview_really_doesnt_overfill(self):
3235 """
Alex Chanb7480992017-01-30 14:04:47 +00003236 When called with a `memoryview` instance and an `nbytes` value that is
3237 too large, `Connection.recv_into` respects the size of the array and
3238 not the `nbytes` value and doesn't write more bytes into the buffer
3239 than will fit.
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003240 """
3241 self._doesnt_overfill_test(_make_memoryview)
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003242
Cory Benfield62d10332014-06-15 10:03:41 +01003243
Alex Chanb7480992017-01-30 14:04:47 +00003244class TestConnectionSendall(object):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003245 """
Alex Chanb7480992017-01-30 14:04:47 +00003246 Tests for `Connection.sendall`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003247 """
Alex Gaynor03737182020-07-23 20:40:46 -04003248
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003249 def test_wrong_args(self):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003250 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003251 When called with arguments other than a string argument for its first
Alex Chanb7480992017-01-30 14:04:47 +00003252 parameter, `Connection.sendall` raises `TypeError`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003253 """
3254 connection = Connection(Context(TLSv1_METHOD), None)
Alex Chanb7480992017-01-30 14:04:47 +00003255 with pytest.raises(TypeError):
3256 connection.sendall(object())
Daniel Holth079c9632019-11-17 22:45:52 -05003257 with pytest.raises(TypeError):
3258 connection.sendall([1, 2, 3])
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003259
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003260 def test_short(self):
3261 """
Alex Chanb7480992017-01-30 14:04:47 +00003262 `Connection.sendall` transmits all of the bytes in the string
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003263 passed to it.
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003264 """
Alex Chanb7480992017-01-30 14:04:47 +00003265 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04003266 server.sendall(b"x")
3267 assert client.recv(1) == b"x"
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003268
Abraham Martinef063482015-03-25 14:06:24 +00003269 def test_text(self):
3270 """
Alex Chanb7480992017-01-30 14:04:47 +00003271 `Connection.sendall` transmits all the content in the string passed
3272 to it, raising a DeprecationWarning in case of this being a text.
Abraham Martinef063482015-03-25 14:06:24 +00003273 """
Alex Chanb7480992017-01-30 14:04:47 +00003274 server, client = loopback()
3275 with pytest.warns(DeprecationWarning) as w:
Abraham Martinef063482015-03-25 14:06:24 +00003276 simplefilter("always")
Jean-Paul Calderone8dc37a12015-03-29 08:16:52 -04003277 server.sendall(b"x".decode("ascii"))
Alex Gaynor03737182020-07-23 20:40:46 -04003278 assert "{0} for buf is no longer accepted, use bytes".format(
3279 WARNING_TYPE_EXPECTED
3280 ) == str(w[-1].message)
Alex Chanb7480992017-01-30 14:04:47 +00003281 assert client.recv(1) == b"x"
Abraham Martinef063482015-03-25 14:06:24 +00003282
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003283 def test_short_memoryview(self):
3284 """
3285 When passed a memoryview onto a small number of bytes,
Alex Chanb7480992017-01-30 14:04:47 +00003286 `Connection.sendall` transmits all of them.
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003287 """
Alex Chanb7480992017-01-30 14:04:47 +00003288 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04003289 server.sendall(memoryview(b"x"))
3290 assert client.recv(1) == b"x"
Abraham Martinef063482015-03-25 14:06:24 +00003291
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003292 @skip_if_py3
3293 def test_short_buffers(self):
3294 """
3295 When passed a buffer containing a small number of bytes,
Alex Chanb7480992017-01-30 14:04:47 +00003296 `Connection.sendall` transmits all of them.
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003297 """
Alex Chanb7480992017-01-30 14:04:47 +00003298 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04003299 count = server.sendall(buffer(b"xy")) # noqa: F821
Daniel Holth079c9632019-11-17 22:45:52 -05003300 assert count == 2
Alex Gaynor03737182020-07-23 20:40:46 -04003301 assert client.recv(2) == b"xy"
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02003302
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003303 def test_long(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003304 """
Alex Chanb7480992017-01-30 14:04:47 +00003305 `Connection.sendall` transmits all the bytes in the string passed to it
3306 even if this requires multiple calls of an underlying write function.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003307 """
Alex Chanb7480992017-01-30 14:04:47 +00003308 server, client = loopback()
Jean-Paul Calderone6241c702010-09-16 19:59:24 -04003309 # Should be enough, underlying SSL_write should only do 16k at a time.
Hynek Schlawack35618382015-09-05 21:54:25 +02003310 # On Windows, after 32k of bytes the write will block (forever
3311 # - because no one is yet reading).
Alex Gaynor03737182020-07-23 20:40:46 -04003312 message = b"x" * (1024 * 32 - 1) + b"y"
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003313 server.sendall(message)
3314 accum = []
3315 received = 0
3316 while received < len(message):
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04003317 data = client.recv(1024)
3318 accum.append(data)
3319 received += len(data)
Alex Gaynor03737182020-07-23 20:40:46 -04003320 assert message == b"".join(accum)
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003321
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003322 def test_closed(self):
3323 """
Alex Chanb7480992017-01-30 14:04:47 +00003324 If the underlying socket is closed, `Connection.sendall` propagates the
3325 write error from the low level write call.
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003326 """
Alex Chanb7480992017-01-30 14:04:47 +00003327 server, client = loopback()
Jean-Paul Calderone05d43e82010-09-24 18:01:36 -04003328 server.sock_shutdown(2)
Alex Chanb7480992017-01-30 14:04:47 +00003329 with pytest.raises(SysCallError) as err:
3330 server.sendall(b"hello, world")
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +02003331 if platform == "win32":
Alex Chanb7480992017-01-30 14:04:47 +00003332 assert err.value.args[0] == ESHUTDOWN
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +02003333 else:
Alex Chanb7480992017-01-30 14:04:47 +00003334 assert err.value.args[0] == EPIPE
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003335
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003336
Alex Chanb7480992017-01-30 14:04:47 +00003337class TestConnectionRenegotiate(object):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003338 """
3339 Tests for SSL renegotiation APIs.
3340 """
Alex Gaynor03737182020-07-23 20:40:46 -04003341
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003342 def test_total_renegotiations(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003343 """
Alex Chanb7480992017-01-30 14:04:47 +00003344 `Connection.total_renegotiations` returns `0` before any renegotiations
3345 have happened.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003346 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003347 connection = Connection(Context(TLSv1_METHOD), None)
Alex Chanb7480992017-01-30 14:04:47 +00003348 assert connection.total_renegotiations() == 0
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003349
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003350 def test_renegotiate(self):
3351 """
3352 Go through a complete renegotiation cycle.
3353 """
Paul Kehrer7d5a3bf2019-01-21 12:24:02 -06003354 server, client = loopback(
3355 lambda s: loopback_server_factory(s, TLSv1_2_METHOD),
3356 lambda s: loopback_client_factory(s, TLSv1_2_METHOD),
3357 )
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003358
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003359 server.send(b"hello world")
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003360
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003361 assert b"hello world" == client.recv(len(b"hello world"))
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003362
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003363 assert 0 == server.total_renegotiations()
3364 assert False is server.renegotiate_pending()
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003365
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003366 assert True is server.renegotiate()
3367
3368 assert True is server.renegotiate_pending()
3369
3370 server.setblocking(False)
3371 client.setblocking(False)
3372
3373 client.do_handshake()
3374 server.do_handshake()
3375
3376 assert 1 == server.total_renegotiations()
3377 while False is server.renegotiate_pending():
3378 pass
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003379
3380
Alex Chanb7480992017-01-30 14:04:47 +00003381class TestError(object):
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003382 """
Alex Chanb7480992017-01-30 14:04:47 +00003383 Unit tests for `OpenSSL.SSL.Error`.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003384 """
Alex Gaynor03737182020-07-23 20:40:46 -04003385
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003386 def test_type(self):
3387 """
Alex Chanb7480992017-01-30 14:04:47 +00003388 `Error` is an exception type.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003389 """
Alex Chanb7480992017-01-30 14:04:47 +00003390 assert issubclass(Error, Exception)
Alex Gaynor03737182020-07-23 20:40:46 -04003391 assert Error.__name__ == "Error"
Rick Deane15b1472009-07-09 15:53:42 -05003392
3393
Alex Chanb7480992017-01-30 14:04:47 +00003394class TestConstants(object):
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003395 """
Alex Chanb7480992017-01-30 14:04:47 +00003396 Tests for the values of constants exposed in `OpenSSL.SSL`.
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003397
3398 These are values defined by OpenSSL intended only to be used as flags to
3399 OpenSSL APIs. The only assertions it seems can be made about them is
3400 their values.
3401 """
Alex Gaynor03737182020-07-23 20:40:46 -04003402
Hynek Schlawack35618382015-09-05 21:54:25 +02003403 @pytest.mark.skipif(
3404 OP_NO_QUERY_MTU is None,
Alex Gaynor03737182020-07-23 20:40:46 -04003405 reason="OP_NO_QUERY_MTU unavailable - OpenSSL version may be too old",
Hynek Schlawack35618382015-09-05 21:54:25 +02003406 )
3407 def test_op_no_query_mtu(self):
3408 """
Alex Chanb7480992017-01-30 14:04:47 +00003409 The value of `OpenSSL.SSL.OP_NO_QUERY_MTU` is 0x1000, the value
3410 of `SSL_OP_NO_QUERY_MTU` defined by `openssl/ssl.h`.
Hynek Schlawack35618382015-09-05 21:54:25 +02003411 """
Alex Chanb7480992017-01-30 14:04:47 +00003412 assert OP_NO_QUERY_MTU == 0x1000
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003413
Hynek Schlawack35618382015-09-05 21:54:25 +02003414 @pytest.mark.skipif(
3415 OP_COOKIE_EXCHANGE is None,
3416 reason="OP_COOKIE_EXCHANGE unavailable - "
Alex Gaynor03737182020-07-23 20:40:46 -04003417 "OpenSSL version may be too old",
Hynek Schlawack35618382015-09-05 21:54:25 +02003418 )
3419 def test_op_cookie_exchange(self):
3420 """
Alex Chanb7480992017-01-30 14:04:47 +00003421 The value of `OpenSSL.SSL.OP_COOKIE_EXCHANGE` is 0x2000, the
3422 value of `SSL_OP_COOKIE_EXCHANGE` defined by `openssl/ssl.h`.
Hynek Schlawack35618382015-09-05 21:54:25 +02003423 """
Alex Chanb7480992017-01-30 14:04:47 +00003424 assert OP_COOKIE_EXCHANGE == 0x2000
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003425
Hynek Schlawack35618382015-09-05 21:54:25 +02003426 @pytest.mark.skipif(
3427 OP_NO_TICKET is None,
Alex Gaynor03737182020-07-23 20:40:46 -04003428 reason="OP_NO_TICKET unavailable - OpenSSL version may be too old",
Hynek Schlawack35618382015-09-05 21:54:25 +02003429 )
3430 def test_op_no_ticket(self):
3431 """
Alex Chanb7480992017-01-30 14:04:47 +00003432 The value of `OpenSSL.SSL.OP_NO_TICKET` is 0x4000, the value of
3433 `SSL_OP_NO_TICKET` defined by `openssl/ssl.h`.
Hynek Schlawack35618382015-09-05 21:54:25 +02003434 """
Alex Chanb7480992017-01-30 14:04:47 +00003435 assert OP_NO_TICKET == 0x4000
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003436
Hynek Schlawack35618382015-09-05 21:54:25 +02003437 @pytest.mark.skipif(
3438 OP_NO_COMPRESSION is None,
Alex Gaynor03737182020-07-23 20:40:46 -04003439 reason=(
3440 "OP_NO_COMPRESSION unavailable - OpenSSL version may be too old"
3441 ),
Hynek Schlawack35618382015-09-05 21:54:25 +02003442 )
3443 def test_op_no_compression(self):
3444 """
Alex Chanb7480992017-01-30 14:04:47 +00003445 The value of `OpenSSL.SSL.OP_NO_COMPRESSION` is 0x20000, the
3446 value of `SSL_OP_NO_COMPRESSION` defined by `openssl/ssl.h`.
Hynek Schlawack35618382015-09-05 21:54:25 +02003447 """
Alex Chanb7480992017-01-30 14:04:47 +00003448 assert OP_NO_COMPRESSION == 0x20000
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04003449
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003450 def test_sess_cache_off(self):
3451 """
Alex Chanb7480992017-01-30 14:04:47 +00003452 The value of `OpenSSL.SSL.SESS_CACHE_OFF` 0x0, the value of
3453 `SSL_SESS_CACHE_OFF` defined by `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003454 """
Alex Chanb7480992017-01-30 14:04:47 +00003455 assert 0x0 == SESS_CACHE_OFF
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003456
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003457 def test_sess_cache_client(self):
3458 """
Alex Chanb7480992017-01-30 14:04:47 +00003459 The value of `OpenSSL.SSL.SESS_CACHE_CLIENT` 0x1, the value of
3460 `SSL_SESS_CACHE_CLIENT` defined by `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003461 """
Alex Chanb7480992017-01-30 14:04:47 +00003462 assert 0x1 == SESS_CACHE_CLIENT
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003463
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003464 def test_sess_cache_server(self):
3465 """
Alex Chanb7480992017-01-30 14:04:47 +00003466 The value of `OpenSSL.SSL.SESS_CACHE_SERVER` 0x2, the value of
3467 `SSL_SESS_CACHE_SERVER` defined by `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003468 """
Alex Chanb7480992017-01-30 14:04:47 +00003469 assert 0x2 == SESS_CACHE_SERVER
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003470
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003471 def test_sess_cache_both(self):
3472 """
Alex Chanb7480992017-01-30 14:04:47 +00003473 The value of `OpenSSL.SSL.SESS_CACHE_BOTH` 0x3, the value of
3474 `SSL_SESS_CACHE_BOTH` defined by `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003475 """
Alex Chanb7480992017-01-30 14:04:47 +00003476 assert 0x3 == SESS_CACHE_BOTH
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003477
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003478 def test_sess_cache_no_auto_clear(self):
3479 """
Alex Chanb7480992017-01-30 14:04:47 +00003480 The value of `OpenSSL.SSL.SESS_CACHE_NO_AUTO_CLEAR` 0x80, the
3481 value of `SSL_SESS_CACHE_NO_AUTO_CLEAR` defined by
3482 `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003483 """
Alex Chanb7480992017-01-30 14:04:47 +00003484 assert 0x80 == SESS_CACHE_NO_AUTO_CLEAR
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003485
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003486 def test_sess_cache_no_internal_lookup(self):
3487 """
Alex Chanb7480992017-01-30 14:04:47 +00003488 The value of `OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_LOOKUP` 0x100,
3489 the value of `SSL_SESS_CACHE_NO_INTERNAL_LOOKUP` defined by
3490 `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003491 """
Alex Chanb7480992017-01-30 14:04:47 +00003492 assert 0x100 == SESS_CACHE_NO_INTERNAL_LOOKUP
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003493
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003494 def test_sess_cache_no_internal_store(self):
3495 """
Alex Chanb7480992017-01-30 14:04:47 +00003496 The value of `OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_STORE` 0x200,
3497 the value of `SSL_SESS_CACHE_NO_INTERNAL_STORE` defined by
3498 `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003499 """
Alex Chanb7480992017-01-30 14:04:47 +00003500 assert 0x200 == SESS_CACHE_NO_INTERNAL_STORE
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003501
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003502 def test_sess_cache_no_internal(self):
3503 """
Alex Chanb7480992017-01-30 14:04:47 +00003504 The value of `OpenSSL.SSL.SESS_CACHE_NO_INTERNAL` 0x300, the
3505 value of `SSL_SESS_CACHE_NO_INTERNAL` defined by
3506 `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003507 """
Alex Chanb7480992017-01-30 14:04:47 +00003508 assert 0x300 == SESS_CACHE_NO_INTERNAL
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003509
3510
Alex Chanb7480992017-01-30 14:04:47 +00003511class TestMemoryBIO(object):
Rick Deanb71c0d22009-04-01 14:09:23 -05003512 """
Alex Chanb7480992017-01-30 14:04:47 +00003513 Tests for `OpenSSL.SSL.Connection` using a memory BIO.
Rick Deanb71c0d22009-04-01 14:09:23 -05003514 """
Alex Gaynor03737182020-07-23 20:40:46 -04003515
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003516 def _server(self, sock):
3517 """
Alex Chanb7480992017-01-30 14:04:47 +00003518 Create a new server-side SSL `Connection` object wrapped around `sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003519 """
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003520 # Create the server side Connection. This is mostly setup boilerplate
3521 # - use TLSv1, use a particular certificate, etc.
3522 server_ctx = Context(TLSv1_METHOD)
Alex Gaynor43307782015-09-04 09:05:45 -04003523 server_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE)
Hynek Schlawack35618382015-09-05 21:54:25 +02003524 server_ctx.set_verify(
3525 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT | VERIFY_CLIENT_ONCE,
Alex Gaynor03737182020-07-23 20:40:46 -04003526 verify_cb,
Hynek Schlawack35618382015-09-05 21:54:25 +02003527 )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003528 server_store = server_ctx.get_cert_store()
Hynek Schlawack35618382015-09-05 21:54:25 +02003529 server_ctx.use_privatekey(
Alex Gaynor03737182020-07-23 20:40:46 -04003530 load_privatekey(FILETYPE_PEM, server_key_pem)
3531 )
Hynek Schlawack35618382015-09-05 21:54:25 +02003532 server_ctx.use_certificate(
Alex Gaynor03737182020-07-23 20:40:46 -04003533 load_certificate(FILETYPE_PEM, server_cert_pem)
3534 )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003535 server_ctx.check_privatekey()
3536 server_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Hynek Schlawack35618382015-09-05 21:54:25 +02003537 # Here the Connection is actually created. If None is passed as the
3538 # 2nd parameter, it indicates a memory BIO should be created.
Rick Deanb1ccd562009-07-09 23:52:39 -05003539 server_conn = Connection(server_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003540 server_conn.set_accept_state()
3541 return server_conn
3542
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003543 def _client(self, sock):
3544 """
Alex Chanb7480992017-01-30 14:04:47 +00003545 Create a new client-side SSL `Connection` object wrapped around `sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003546 """
3547 # Now create the client side Connection. Similar boilerplate to the
3548 # above.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003549 client_ctx = Context(TLSv1_METHOD)
Alex Gaynor43307782015-09-04 09:05:45 -04003550 client_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE)
Hynek Schlawack35618382015-09-05 21:54:25 +02003551 client_ctx.set_verify(
3552 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT | VERIFY_CLIENT_ONCE,
Alex Gaynor03737182020-07-23 20:40:46 -04003553 verify_cb,
Hynek Schlawack35618382015-09-05 21:54:25 +02003554 )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003555 client_store = client_ctx.get_cert_store()
Hynek Schlawack35618382015-09-05 21:54:25 +02003556 client_ctx.use_privatekey(
Alex Gaynor03737182020-07-23 20:40:46 -04003557 load_privatekey(FILETYPE_PEM, client_key_pem)
3558 )
Hynek Schlawack35618382015-09-05 21:54:25 +02003559 client_ctx.use_certificate(
Alex Gaynor03737182020-07-23 20:40:46 -04003560 load_certificate(FILETYPE_PEM, client_cert_pem)
3561 )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003562 client_ctx.check_privatekey()
3563 client_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05003564 client_conn = Connection(client_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003565 client_conn.set_connect_state()
3566 return client_conn
3567
Alex Chanb7480992017-01-30 14:04:47 +00003568 def test_memory_connect(self):
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003569 """
Alex Chanb7480992017-01-30 14:04:47 +00003570 Two `Connection`s which use memory BIOs can be manually connected by
3571 reading from the output of each and writing those bytes to the input of
3572 the other and in this way establish a connection and exchange
3573 application-level bytes with each other.
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003574 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003575 server_conn = self._server(None)
3576 client_conn = self._client(None)
Rick Deanb71c0d22009-04-01 14:09:23 -05003577
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003578 # There should be no key or nonces yet.
Alex Chanb7480992017-01-30 14:04:47 +00003579 assert server_conn.master_key() is None
3580 assert server_conn.client_random() is None
3581 assert server_conn.server_random() is None
Rick Deanb71c0d22009-04-01 14:09:23 -05003582
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003583 # First, the handshake needs to happen. We'll deliver bytes back and
3584 # forth between the client and server until neither of them feels like
3585 # speaking any more.
Alex Chanb7480992017-01-30 14:04:47 +00003586 assert interact_in_memory(client_conn, server_conn) is None
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003587
3588 # Now that the handshake is done, there should be a key and nonces.
Alex Chanb7480992017-01-30 14:04:47 +00003589 assert server_conn.master_key() is not None
3590 assert server_conn.client_random() is not None
3591 assert server_conn.server_random() is not None
3592 assert server_conn.client_random() == client_conn.client_random()
3593 assert server_conn.server_random() == client_conn.server_random()
3594 assert server_conn.client_random() != server_conn.server_random()
3595 assert client_conn.client_random() != client_conn.server_random()
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003596
Paul Kehrerbdb76392017-12-01 04:54:32 +08003597 # Export key material for other uses.
Alex Gaynor03737182020-07-23 20:40:46 -04003598 cekm = client_conn.export_keying_material(b"LABEL", 32)
3599 sekm = server_conn.export_keying_material(b"LABEL", 32)
Paul Kehrerbdb76392017-12-01 04:54:32 +08003600 assert cekm is not None
3601 assert sekm is not None
3602 assert cekm == sekm
3603 assert len(sekm) == 32
3604
3605 # Export key material for other uses with additional context.
Alex Gaynor03737182020-07-23 20:40:46 -04003606 cekmc = client_conn.export_keying_material(b"LABEL", 32, b"CONTEXT")
3607 sekmc = server_conn.export_keying_material(b"LABEL", 32, b"CONTEXT")
Paul Kehrerbdb76392017-12-01 04:54:32 +08003608 assert cekmc is not None
3609 assert sekmc is not None
3610 assert cekmc == sekmc
3611 assert cekmc != cekm
3612 assert sekmc != sekm
3613 # Export with alternate label
Alex Gaynor03737182020-07-23 20:40:46 -04003614 cekmt = client_conn.export_keying_material(b"test", 32, b"CONTEXT")
3615 sekmt = server_conn.export_keying_material(b"test", 32, b"CONTEXT")
Paul Kehrerbdb76392017-12-01 04:54:32 +08003616 assert cekmc != cekmt
3617 assert sekmc != sekmt
3618
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003619 # Here are the bytes we'll try to send.
Alex Gaynor03737182020-07-23 20:40:46 -04003620 important_message = b"One if by land, two if by sea."
Rick Deanb71c0d22009-04-01 14:09:23 -05003621
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003622 server_conn.write(important_message)
Alex Gaynor03737182020-07-23 20:40:46 -04003623 assert interact_in_memory(client_conn, server_conn) == (
3624 client_conn,
3625 important_message,
3626 )
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003627
3628 client_conn.write(important_message[::-1])
Alex Gaynor03737182020-07-23 20:40:46 -04003629 assert interact_in_memory(client_conn, server_conn) == (
3630 server_conn,
3631 important_message[::-1],
3632 )
Rick Deanb71c0d22009-04-01 14:09:23 -05003633
Alex Chanb7480992017-01-30 14:04:47 +00003634 def test_socket_connect(self):
Rick Deanb1ccd562009-07-09 23:52:39 -05003635 """
Alex Chanb7480992017-01-30 14:04:47 +00003636 Just like `test_memory_connect` but with an actual socket.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003637
Hynek Schlawack35618382015-09-05 21:54:25 +02003638 This is primarily to rule out the memory BIO code as the source of any
Alex Chanb7480992017-01-30 14:04:47 +00003639 problems encountered while passing data over a `Connection` (if
Hynek Schlawack35618382015-09-05 21:54:25 +02003640 this test fails, there must be a problem outside the memory BIO code,
3641 as no memory BIO is involved here). Even though this isn't a memory
3642 BIO test, it's convenient to have it here.
Rick Deanb1ccd562009-07-09 23:52:39 -05003643 """
Alex Chanb7480992017-01-30 14:04:47 +00003644 server_conn, client_conn = loopback()
Rick Deanb1ccd562009-07-09 23:52:39 -05003645
Alex Gaynore7f51982016-09-11 11:48:14 -04003646 important_message = b"Help me Obi Wan Kenobi, you're my only hope."
Rick Deanb1ccd562009-07-09 23:52:39 -05003647 client_conn.send(important_message)
3648 msg = server_conn.recv(1024)
Alex Chanb7480992017-01-30 14:04:47 +00003649 assert msg == important_message
Rick Deanb1ccd562009-07-09 23:52:39 -05003650
3651 # Again in the other direction, just for fun.
3652 important_message = important_message[::-1]
3653 server_conn.send(important_message)
3654 msg = client_conn.recv(1024)
Alex Chanb7480992017-01-30 14:04:47 +00003655 assert msg == important_message
Rick Deanb1ccd562009-07-09 23:52:39 -05003656
Alex Chanb7480992017-01-30 14:04:47 +00003657 def test_socket_overrides_memory(self):
Rick Deanb71c0d22009-04-01 14:09:23 -05003658 """
Alex Chanb7480992017-01-30 14:04:47 +00003659 Test that `OpenSSL.SSL.bio_read` and `OpenSSL.SSL.bio_write` don't
3660 work on `OpenSSL.SSL.Connection`() that use sockets.
Rick Deanb71c0d22009-04-01 14:09:23 -05003661 """
Alex Gaynor51d424c2016-09-10 14:50:11 -04003662 context = Context(TLSv1_METHOD)
David Benjamin1fbe0642019-04-15 17:05:13 -05003663 client = socket_any_family()
Rick Deanb71c0d22009-04-01 14:09:23 -05003664 clientSSL = Connection(context, client)
Alex Chanb7480992017-01-30 14:04:47 +00003665 with pytest.raises(TypeError):
3666 clientSSL.bio_read(100)
3667 with pytest.raises(TypeError):
3668 clientSSL.bio_write("foo")
3669 with pytest.raises(TypeError):
3670 clientSSL.bio_shutdown()
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003671
Alex Chanb7480992017-01-30 14:04:47 +00003672 def test_outgoing_overflow(self):
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003673 """
3674 If more bytes than can be written to the memory BIO are passed to
Alex Chanb7480992017-01-30 14:04:47 +00003675 `Connection.send` at once, the number of bytes which were written is
3676 returned and that many bytes from the beginning of the input can be
3677 read from the other end of the connection.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003678 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003679 server = self._server(None)
3680 client = self._client(None)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003681
Alex Chanb7480992017-01-30 14:04:47 +00003682 interact_in_memory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003683
3684 size = 2 ** 15
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003685 sent = client.send(b"x" * size)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003686 # Sanity check. We're trying to test what happens when the entire
3687 # input can't be sent. If the entire input was sent, this test is
3688 # meaningless.
Alex Chanb7480992017-01-30 14:04:47 +00003689 assert sent < size
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003690
Alex Chanb7480992017-01-30 14:04:47 +00003691 receiver, received = interact_in_memory(client, server)
3692 assert receiver is server
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003693
3694 # We can rely on all of these bytes being received at once because
Alex Chanb7480992017-01-30 14:04:47 +00003695 # loopback passes 2 ** 16 to recv - more than 2 ** 15.
3696 assert len(received) == sent
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003697
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003698 def test_shutdown(self):
3699 """
Alex Chanb7480992017-01-30 14:04:47 +00003700 `Connection.bio_shutdown` signals the end of the data stream
3701 from which the `Connection` reads.
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003702 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003703 server = self._server(None)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003704 server.bio_shutdown()
Alex Chanb7480992017-01-30 14:04:47 +00003705 with pytest.raises(Error) as err:
3706 server.recv(1024)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003707 # We don't want WantReadError or ZeroReturnError or anything - it's a
3708 # handshake failure.
Alex Chanb7480992017-01-30 14:04:47 +00003709 assert type(err.value) in [Error, SysCallError]
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003710
Alex Chanb7480992017-01-30 14:04:47 +00003711 def test_unexpected_EOF(self):
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003712 """
3713 If the connection is lost before an orderly SSL shutdown occurs,
Alex Chanb7480992017-01-30 14:04:47 +00003714 `OpenSSL.SSL.SysCallError` is raised with a message of
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003715 "Unexpected EOF".
3716 """
Alex Chanb7480992017-01-30 14:04:47 +00003717 server_conn, client_conn = loopback()
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003718 client_conn.sock_shutdown(SHUT_RDWR)
Alex Chanb7480992017-01-30 14:04:47 +00003719 with pytest.raises(SysCallError) as err:
3720 server_conn.recv(1024)
3721 assert err.value.args == (-1, "Unexpected EOF")
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003722
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003723 def _check_client_ca_list(self, func):
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003724 """
Alex Chanb7480992017-01-30 14:04:47 +00003725 Verify the return value of the `get_client_ca_list` method for
Hynek Schlawack35618382015-09-05 21:54:25 +02003726 server and client connections.
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003727
Jonathan Ballet78b92a22011-07-16 08:07:26 +09003728 :param func: A function which will be called with the server context
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003729 before the client and server are connected to each other. This
3730 function should specify a list of CAs for the server to send to the
3731 client and return that same list. The list will be used to verify
Alex Chanb7480992017-01-30 14:04:47 +00003732 that `get_client_ca_list` returns the proper value at
Hynek Schlawack35618382015-09-05 21:54:25 +02003733 various times.
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003734 """
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003735 server = self._server(None)
3736 client = self._client(None)
Alex Chanb7480992017-01-30 14:04:47 +00003737 assert client.get_client_ca_list() == []
3738 assert server.get_client_ca_list() == []
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003739 ctx = server.get_context()
3740 expected = func(ctx)
Alex Chanb7480992017-01-30 14:04:47 +00003741 assert client.get_client_ca_list() == []
3742 assert server.get_client_ca_list() == expected
3743 interact_in_memory(client, server)
3744 assert client.get_client_ca_list() == expected
3745 assert server.get_client_ca_list() == expected
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003746
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003747 def test_set_client_ca_list_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003748 """
Alex Chanb7480992017-01-30 14:04:47 +00003749 `Context.set_client_ca_list` raises a `TypeError` if called with a
3750 non-list or a list that contains objects other than X509Names.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003751 """
3752 ctx = Context(TLSv1_METHOD)
Alex Chanb7480992017-01-30 14:04:47 +00003753 with pytest.raises(TypeError):
3754 ctx.set_client_ca_list("spam")
3755 with pytest.raises(TypeError):
3756 ctx.set_client_ca_list(["spam"])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003757
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003758 def test_set_empty_ca_list(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003759 """
Alex Chanb7480992017-01-30 14:04:47 +00003760 If passed an empty list, `Context.set_client_ca_list` configures the
3761 context to send no CA names to the client and, on both the server and
3762 client sides, `Connection.get_client_ca_list` returns an empty list
3763 after the connection is set up.
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003764 """
Alex Gaynor03737182020-07-23 20:40:46 -04003765
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003766 def no_ca(ctx):
3767 ctx.set_client_ca_list([])
3768 return []
Alex Gaynor03737182020-07-23 20:40:46 -04003769
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003770 self._check_client_ca_list(no_ca)
3771
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003772 def test_set_one_ca_list(self):
3773 """
3774 If passed a list containing a single X509Name,
Alex Chanb7480992017-01-30 14:04:47 +00003775 `Context.set_client_ca_list` configures the context to send
Hynek Schlawack35618382015-09-05 21:54:25 +02003776 that CA name to the client and, on both the server and client sides,
Alex Chanb7480992017-01-30 14:04:47 +00003777 `Connection.get_client_ca_list` returns a list containing that
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003778 X509Name after the connection is set up.
3779 """
3780 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3781 cadesc = cacert.get_subject()
Hynek Schlawack35618382015-09-05 21:54:25 +02003782
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003783 def single_ca(ctx):
3784 ctx.set_client_ca_list([cadesc])
3785 return [cadesc]
Alex Gaynor03737182020-07-23 20:40:46 -04003786
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003787 self._check_client_ca_list(single_ca)
3788
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003789 def test_set_multiple_ca_list(self):
3790 """
3791 If passed a list containing multiple X509Name objects,
Alex Chanb7480992017-01-30 14:04:47 +00003792 `Context.set_client_ca_list` configures the context to send
Hynek Schlawack35618382015-09-05 21:54:25 +02003793 those CA names to the client and, on both the server and client sides,
Alex Chanb7480992017-01-30 14:04:47 +00003794 `Connection.get_client_ca_list` returns a list containing those
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003795 X509Names after the connection is set up.
3796 """
3797 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3798 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3799
3800 sedesc = secert.get_subject()
3801 cldesc = clcert.get_subject()
3802
3803 def multiple_ca(ctx):
3804 L = [sedesc, cldesc]
3805 ctx.set_client_ca_list(L)
3806 return L
Alex Gaynor03737182020-07-23 20:40:46 -04003807
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003808 self._check_client_ca_list(multiple_ca)
3809
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003810 def test_reset_ca_list(self):
3811 """
3812 If called multiple times, only the X509Names passed to the final call
Alex Chanb7480992017-01-30 14:04:47 +00003813 of `Context.set_client_ca_list` are used to configure the CA
Hynek Schlawack35618382015-09-05 21:54:25 +02003814 names sent to the client.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003815 """
3816 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3817 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3818 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3819
3820 cadesc = cacert.get_subject()
3821 sedesc = secert.get_subject()
3822 cldesc = clcert.get_subject()
3823
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003824 def changed_ca(ctx):
3825 ctx.set_client_ca_list([sedesc, cldesc])
3826 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003827 return [cadesc]
Alex Gaynor03737182020-07-23 20:40:46 -04003828
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003829 self._check_client_ca_list(changed_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003830
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003831 def test_mutated_ca_list(self):
3832 """
Alex Chanb7480992017-01-30 14:04:47 +00003833 If the list passed to `Context.set_client_ca_list` is mutated
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003834 afterwards, this does not affect the list of CA names sent to the
3835 client.
3836 """
3837 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3838 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3839
3840 cadesc = cacert.get_subject()
3841 sedesc = secert.get_subject()
3842
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003843 def mutated_ca(ctx):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003844 L = [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003845 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003846 L.append(sedesc)
3847 return [cadesc]
Alex Gaynor03737182020-07-23 20:40:46 -04003848
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003849 self._check_client_ca_list(mutated_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003850
Alex Chanb7480992017-01-30 14:04:47 +00003851 def test_add_client_ca_wrong_args(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003852 """
Alex Chanb7480992017-01-30 14:04:47 +00003853 `Context.add_client_ca` raises `TypeError` if called with
3854 a non-X509 object.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003855 """
3856 ctx = Context(TLSv1_METHOD)
Alex Chanb7480992017-01-30 14:04:47 +00003857 with pytest.raises(TypeError):
3858 ctx.add_client_ca("spam")
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003859
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003860 def test_one_add_client_ca(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003861 """
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003862 A certificate's subject can be added as a CA to be sent to the client
Alex Chanb7480992017-01-30 14:04:47 +00003863 with `Context.add_client_ca`.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003864 """
3865 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3866 cadesc = cacert.get_subject()
Hynek Schlawack35618382015-09-05 21:54:25 +02003867
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003868 def single_ca(ctx):
3869 ctx.add_client_ca(cacert)
3870 return [cadesc]
Alex Gaynor03737182020-07-23 20:40:46 -04003871
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003872 self._check_client_ca_list(single_ca)
3873
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003874 def test_multiple_add_client_ca(self):
3875 """
3876 Multiple CA names can be sent to the client by calling
Alex Chanb7480992017-01-30 14:04:47 +00003877 `Context.add_client_ca` with multiple X509 objects.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003878 """
3879 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3880 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3881
3882 cadesc = cacert.get_subject()
3883 sedesc = secert.get_subject()
3884
3885 def multiple_ca(ctx):
3886 ctx.add_client_ca(cacert)
3887 ctx.add_client_ca(secert)
3888 return [cadesc, sedesc]
Alex Gaynor03737182020-07-23 20:40:46 -04003889
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003890 self._check_client_ca_list(multiple_ca)
3891
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003892 def test_set_and_add_client_ca(self):
3893 """
Alex Chanb7480992017-01-30 14:04:47 +00003894 A call to `Context.set_client_ca_list` followed by a call to
3895 `Context.add_client_ca` results in using the CA names from the
Hynek Schlawack35618382015-09-05 21:54:25 +02003896 first call and the CA name from the second call.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003897 """
3898 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3899 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3900 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3901
3902 cadesc = cacert.get_subject()
3903 sedesc = secert.get_subject()
3904 cldesc = clcert.get_subject()
3905
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003906 def mixed_set_add_ca(ctx):
3907 ctx.set_client_ca_list([cadesc, sedesc])
3908 ctx.add_client_ca(clcert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003909 return [cadesc, sedesc, cldesc]
Alex Gaynor03737182020-07-23 20:40:46 -04003910
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003911 self._check_client_ca_list(mixed_set_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003912
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003913 def test_set_after_add_client_ca(self):
3914 """
Alex Chanb7480992017-01-30 14:04:47 +00003915 A call to `Context.set_client_ca_list` after a call to
3916 `Context.add_client_ca` replaces the CA name specified by the
Hynek Schlawack35618382015-09-05 21:54:25 +02003917 former call with the names specified by the latter call.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003918 """
3919 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3920 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3921 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3922
3923 cadesc = cacert.get_subject()
3924 sedesc = secert.get_subject()
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003925
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003926 def set_replaces_add_ca(ctx):
3927 ctx.add_client_ca(clcert)
3928 ctx.set_client_ca_list([cadesc])
3929 ctx.add_client_ca(secert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003930 return [cadesc, sedesc]
Alex Gaynor03737182020-07-23 20:40:46 -04003931
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003932 self._check_client_ca_list(set_replaces_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003933
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003934
Alex Chanb7480992017-01-30 14:04:47 +00003935class TestInfoConstants(object):
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003936 """
3937 Tests for assorted constants exposed for use in info callbacks.
3938 """
Alex Gaynor03737182020-07-23 20:40:46 -04003939
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003940 def test_integers(self):
3941 """
3942 All of the info constants are integers.
3943
3944 This is a very weak test. It would be nice to have one that actually
3945 verifies that as certain info events happen, the value passed to the
3946 info callback matches up with the constant exposed by OpenSSL.SSL.
3947 """
3948 for const in [
Alex Gaynor03737182020-07-23 20:40:46 -04003949 SSL_ST_CONNECT,
3950 SSL_ST_ACCEPT,
3951 SSL_ST_MASK,
3952 SSL_CB_LOOP,
3953 SSL_CB_EXIT,
3954 SSL_CB_READ,
3955 SSL_CB_WRITE,
3956 SSL_CB_ALERT,
3957 SSL_CB_READ_ALERT,
3958 SSL_CB_WRITE_ALERT,
3959 SSL_CB_ACCEPT_LOOP,
3960 SSL_CB_ACCEPT_EXIT,
3961 SSL_CB_CONNECT_LOOP,
3962 SSL_CB_CONNECT_EXIT,
3963 SSL_CB_HANDSHAKE_START,
3964 SSL_CB_HANDSHAKE_DONE,
Hynek Schlawack35618382015-09-05 21:54:25 +02003965 ]:
Alex Gaynor5af32d02016-09-24 01:52:21 -04003966 assert isinstance(const, int)
3967
3968 # These constants don't exist on OpenSSL 1.1.0
3969 for const in [
Alex Gaynor03737182020-07-23 20:40:46 -04003970 SSL_ST_INIT,
3971 SSL_ST_BEFORE,
3972 SSL_ST_OK,
3973 SSL_ST_RENEGOTIATE,
Alex Gaynor5af32d02016-09-24 01:52:21 -04003974 ]:
3975 assert const is None or isinstance(const, int)
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003976
Ziga Seilnacht44611bf2009-08-31 20:49:30 +02003977
Cory Benfield1d142142016-03-30 11:51:45 +01003978class TestRequires(object):
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003979 """
3980 Tests for the decorator factory used to conditionally raise
Cory Benfield1d142142016-03-30 11:51:45 +01003981 NotImplementedError when older OpenSSLs are used.
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003982 """
Alex Gaynor03737182020-07-23 20:40:46 -04003983
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003984 def test_available(self):
3985 """
3986 When the OpenSSL functionality is available the decorated functions
3987 work appropriately.
3988 """
3989 feature_guard = _make_requires(True, "Error text")
3990 results = []
3991
3992 @feature_guard
3993 def inner():
3994 results.append(True)
3995 return True
3996
Cory Benfield2333e5e2016-03-30 14:24:16 +01003997 assert inner() is True
3998 assert [True] == results
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003999
4000 def test_unavailable(self):
4001 """
4002 When the OpenSSL functionality is not available the decorated function
4003 does not execute and NotImplementedError is raised.
4004 """
4005 feature_guard = _make_requires(False, "Error text")
Cory Benfield0ba57ec2016-03-30 09:35:05 +01004006
4007 @feature_guard
Alex Chanfb078d82017-04-20 11:16:15 +01004008 def inner(): # pragma: nocover
4009 pytest.fail("Should not be called")
Cory Benfield0ba57ec2016-03-30 09:35:05 +01004010
Cory Benfield1d142142016-03-30 11:51:45 +01004011 with pytest.raises(NotImplementedError) as e:
4012 inner()
4013
4014 assert "Error text" in str(e.value)
Cory Benfield496652a2017-01-24 11:42:56 +00004015
4016
Alex Chanb7480992017-01-30 14:04:47 +00004017class TestOCSP(object):
Cory Benfield496652a2017-01-24 11:42:56 +00004018 """
4019 Tests for PyOpenSSL's OCSP stapling support.
4020 """
Alex Gaynor03737182020-07-23 20:40:46 -04004021
Cory Benfield496652a2017-01-24 11:42:56 +00004022 sample_ocsp_data = b"this is totally ocsp data"
4023
4024 def _client_connection(self, callback, data, request_ocsp=True):
4025 """
4026 Builds a client connection suitable for using OCSP.
4027
4028 :param callback: The callback to register for OCSP.
4029 :param data: The opaque data object that will be handed to the
4030 OCSP callback.
4031 :param request_ocsp: Whether the client will actually ask for OCSP
4032 stapling. Useful for testing only.
4033 """
4034 ctx = Context(SSLv23_METHOD)
4035 ctx.set_ocsp_client_callback(callback, data)
4036 client = Connection(ctx)
4037
4038 if request_ocsp:
4039 client.request_ocsp()
4040
4041 client.set_connect_state()
4042 return client
4043
4044 def _server_connection(self, callback, data):
4045 """
4046 Builds a server connection suitable for using OCSP.
4047
4048 :param callback: The callback to register for OCSP.
4049 :param data: The opaque data object that will be handed to the
4050 OCSP callback.
4051 """
4052 ctx = Context(SSLv23_METHOD)
4053 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
4054 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
4055 ctx.set_ocsp_server_callback(callback, data)
4056 server = Connection(ctx)
4057 server.set_accept_state()
4058 return server
4059
4060 def test_callbacks_arent_called_by_default(self):
4061 """
4062 If both the client and the server have registered OCSP callbacks, but
4063 the client does not send the OCSP request, neither callback gets
4064 called.
4065 """
Alex Gaynor03737182020-07-23 20:40:46 -04004066
Alex Chanfb078d82017-04-20 11:16:15 +01004067 def ocsp_callback(*args, **kwargs): # pragma: nocover
4068 pytest.fail("Should not be called")
Cory Benfield496652a2017-01-24 11:42:56 +00004069
4070 client = self._client_connection(
4071 callback=ocsp_callback, data=None, request_ocsp=False
4072 )
4073 server = self._server_connection(callback=ocsp_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00004074 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00004075
Cory Benfield496652a2017-01-24 11:42:56 +00004076 def test_client_negotiates_without_server(self):
4077 """
4078 If the client wants to do OCSP but the server does not, the handshake
4079 succeeds, and the client callback fires with an empty byte string.
4080 """
4081 called = []
4082
4083 def ocsp_callback(conn, ocsp_data, ignored):
4084 called.append(ocsp_data)
4085 return True
4086
4087 client = self._client_connection(callback=ocsp_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00004088 server = loopback_server_factory(socket=None)
4089 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00004090
4091 assert len(called) == 1
Alex Gaynor03737182020-07-23 20:40:46 -04004092 assert called[0] == b""
Cory Benfield496652a2017-01-24 11:42:56 +00004093
4094 def test_client_receives_servers_data(self):
4095 """
4096 The data the server sends in its callback is received by the client.
4097 """
4098 calls = []
4099
4100 def server_callback(*args, **kwargs):
4101 return self.sample_ocsp_data
4102
4103 def client_callback(conn, ocsp_data, ignored):
4104 calls.append(ocsp_data)
4105 return True
4106
4107 client = self._client_connection(callback=client_callback, data=None)
4108 server = self._server_connection(callback=server_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00004109 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00004110
4111 assert len(calls) == 1
4112 assert calls[0] == self.sample_ocsp_data
4113
4114 def test_callbacks_are_invoked_with_connections(self):
4115 """
4116 The first arguments to both callbacks are their respective connections.
4117 """
4118 client_calls = []
4119 server_calls = []
4120
4121 def client_callback(conn, *args, **kwargs):
4122 client_calls.append(conn)
4123 return True
4124
4125 def server_callback(conn, *args, **kwargs):
4126 server_calls.append(conn)
4127 return self.sample_ocsp_data
4128
4129 client = self._client_connection(callback=client_callback, data=None)
4130 server = self._server_connection(callback=server_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00004131 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00004132
4133 assert len(client_calls) == 1
4134 assert len(server_calls) == 1
4135 assert client_calls[0] is client
4136 assert server_calls[0] is server
4137
4138 def test_opaque_data_is_passed_through(self):
4139 """
4140 Both callbacks receive an opaque, user-provided piece of data in their
4141 callbacks as the final argument.
4142 """
4143 calls = []
4144
4145 def server_callback(*args):
4146 calls.append(args)
4147 return self.sample_ocsp_data
4148
4149 def client_callback(*args):
4150 calls.append(args)
4151 return True
4152
4153 sentinel = object()
4154
4155 client = self._client_connection(
4156 callback=client_callback, data=sentinel
4157 )
4158 server = self._server_connection(
4159 callback=server_callback, data=sentinel
4160 )
Alex Chanb7480992017-01-30 14:04:47 +00004161 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00004162
4163 assert len(calls) == 2
4164 assert calls[0][-1] is sentinel
4165 assert calls[1][-1] is sentinel
4166
4167 def test_server_returns_empty_string(self):
4168 """
4169 If the server returns an empty bytestring from its callback, the
4170 client callback is called with the empty bytestring.
4171 """
4172 client_calls = []
4173
4174 def server_callback(*args):
Alex Gaynor03737182020-07-23 20:40:46 -04004175 return b""
Cory Benfield496652a2017-01-24 11:42:56 +00004176
4177 def client_callback(conn, ocsp_data, ignored):
4178 client_calls.append(ocsp_data)
4179 return True
4180
4181 client = self._client_connection(callback=client_callback, data=None)
4182 server = self._server_connection(callback=server_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00004183 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00004184
4185 assert len(client_calls) == 1
Alex Gaynor03737182020-07-23 20:40:46 -04004186 assert client_calls[0] == b""
Cory Benfield496652a2017-01-24 11:42:56 +00004187
4188 def test_client_returns_false_terminates_handshake(self):
4189 """
4190 If the client returns False from its callback, the handshake fails.
4191 """
Alex Gaynor03737182020-07-23 20:40:46 -04004192
Cory Benfield496652a2017-01-24 11:42:56 +00004193 def server_callback(*args):
4194 return self.sample_ocsp_data
4195
4196 def client_callback(*args):
4197 return False
4198
4199 client = self._client_connection(callback=client_callback, data=None)
4200 server = self._server_connection(callback=server_callback, data=None)
4201
4202 with pytest.raises(Error):
Alex Chanb7480992017-01-30 14:04:47 +00004203 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00004204
4205 def test_exceptions_in_client_bubble_up(self):
4206 """
4207 The callbacks thrown in the client callback bubble up to the caller.
4208 """
Alex Gaynor03737182020-07-23 20:40:46 -04004209
Cory Benfield496652a2017-01-24 11:42:56 +00004210 class SentinelException(Exception):
4211 pass
4212
4213 def server_callback(*args):
4214 return self.sample_ocsp_data
4215
4216 def client_callback(*args):
4217 raise SentinelException()
4218
4219 client = self._client_connection(callback=client_callback, data=None)
4220 server = self._server_connection(callback=server_callback, data=None)
4221
4222 with pytest.raises(SentinelException):
Alex Chanb7480992017-01-30 14:04:47 +00004223 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00004224
4225 def test_exceptions_in_server_bubble_up(self):
4226 """
4227 The callbacks thrown in the server callback bubble up to the caller.
4228 """
Alex Gaynor03737182020-07-23 20:40:46 -04004229
Cory Benfield496652a2017-01-24 11:42:56 +00004230 class SentinelException(Exception):
4231 pass
4232
4233 def server_callback(*args):
4234 raise SentinelException()
4235
Alex Chanfb078d82017-04-20 11:16:15 +01004236 def client_callback(*args): # pragma: nocover
Cory Benfield496652a2017-01-24 11:42:56 +00004237 pytest.fail("Should not be called")
4238
4239 client = self._client_connection(callback=client_callback, data=None)
4240 server = self._server_connection(callback=server_callback, data=None)
4241
4242 with pytest.raises(SentinelException):
Alex Chanb7480992017-01-30 14:04:47 +00004243 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00004244
4245 def test_server_must_return_bytes(self):
4246 """
4247 The server callback must return a bytestring, or a TypeError is thrown.
4248 """
Alex Gaynor03737182020-07-23 20:40:46 -04004249
Cory Benfield496652a2017-01-24 11:42:56 +00004250 def server_callback(*args):
Alex Gaynor03737182020-07-23 20:40:46 -04004251 return self.sample_ocsp_data.decode("ascii")
Cory Benfield496652a2017-01-24 11:42:56 +00004252
Alex Chanfb078d82017-04-20 11:16:15 +01004253 def client_callback(*args): # pragma: nocover
Cory Benfield496652a2017-01-24 11:42:56 +00004254 pytest.fail("Should not be called")
4255
4256 client = self._client_connection(callback=client_callback, data=None)
4257 server = self._server_connection(callback=server_callback, data=None)
4258
4259 with pytest.raises(TypeError):
Alex Chanb7480992017-01-30 14:04:47 +00004260 handshake_in_memory(client, server)