blob: aed2367033a72a7d3ace0d97c38be370d80234c3 [file] [log] [blame]
Jean-Paul Calderone8671c852011-03-02 19:26:20 -05001# Copyright (C) Jean-Paul Calderone
2# See LICENSE for details.
Jean-Paul Calderone8b63d452008-03-21 18:31:12 -04003
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -04004"""
Hynek Schlawackf90e3682016-03-11 11:21:13 +01005Unit tests for :mod:`OpenSSL.SSL`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -04006"""
7
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01008import datetime
Maximilian Hils868dc3c2017-02-10 14:56:55 +01009import sys
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +010010import uuid
11
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -050012from gc import collect, get_referrers
David Benjamin1fbe0642019-04-15 17:05:13 -050013from errno import (
Alex Gaynor03737182020-07-23 20:40:46 -040014 EAFNOSUPPORT,
15 ECONNREFUSED,
16 EINPROGRESS,
17 EWOULDBLOCK,
18 EPIPE,
19 ESHUTDOWN,
20)
Jeremy Lainé1ae7cb62018-03-21 14:49:42 +010021from sys import platform, getfilesystemencoding
David Benjamin1fbe0642019-04-15 17:05:13 -050022from socket import AF_INET, AF_INET6, MSG_PEEK, SHUT_RDWR, error, socket
Jean-Paul Calderonea65cf6c2009-07-19 10:26:52 -040023from os import makedirs
Jean-Paul Calderone1461c492013-10-03 16:05:00 -040024from os.path import join
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -040025from weakref import ref
Alex Chanb7480992017-01-30 14:04:47 +000026from warnings import simplefilter
Jean-Paul Calderone460cc1f2009-03-07 11:31:12 -050027
Alex Gaynor963ae032019-07-06 17:38:32 -040028import flaky
29
Hynek Schlawack734d3022015-09-05 19:19:32 +020030import pytest
31
Paul Kehrer55fb3412017-06-29 18:44:08 -050032from pretend import raiser
33
Hugo van Kemenade60827f82019-08-30 00:39:35 +030034from six import PY2, text_type
Jean-Paul Calderonec76c61c2014-01-18 13:21:52 -050035
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +010036from cryptography import x509
37from cryptography.hazmat.backends import default_backend
38from cryptography.hazmat.primitives import hashes
39from cryptography.hazmat.primitives import serialization
40from cryptography.hazmat.primitives.asymmetric import rsa
41from cryptography.x509.oid import NameOID
42
43
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040044from OpenSSL.crypto import TYPE_RSA, FILETYPE_PEM
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -080045from OpenSSL.crypto import PKey, X509, X509Extension, X509Store
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040046from OpenSSL.crypto import dump_privatekey, load_privatekey
47from OpenSSL.crypto import dump_certificate, load_certificate
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -040048from OpenSSL.crypto import get_elliptic_curves
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040049
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -040050from OpenSSL.SSL import OPENSSL_VERSION_NUMBER, SSLEAY_VERSION, SSLEAY_CFLAGS
51from OpenSSL.SSL import SSLEAY_PLATFORM, SSLEAY_DIR, SSLEAY_BUILT_ON
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -040052from OpenSSL.SSL import SENT_SHUTDOWN, RECEIVED_SHUTDOWN
Jean-Paul Calderone1461c492013-10-03 16:05:00 -040053from OpenSSL.SSL import (
Alex Gaynor03737182020-07-23 20:40:46 -040054 SSLv2_METHOD,
55 SSLv3_METHOD,
56 SSLv23_METHOD,
57 TLSv1_METHOD,
58 TLSv1_1_METHOD,
59 TLSv1_2_METHOD,
60)
Jean-Paul Calderone1461c492013-10-03 16:05:00 -040061from OpenSSL.SSL import OP_SINGLE_DH_USE, OP_NO_SSLv2, OP_NO_SSLv3
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040062from OpenSSL.SSL import (
Alex Gaynor03737182020-07-23 20:40:46 -040063 VERIFY_PEER,
64 VERIFY_FAIL_IF_NO_PEER_CERT,
65 VERIFY_CLIENT_ONCE,
66 VERIFY_NONE,
67)
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040068
Paul Kehrer55fb3412017-06-29 18:44:08 -050069from OpenSSL import SSL
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040070from OpenSSL.SSL import (
Alex Gaynor03737182020-07-23 20:40:46 -040071 SESS_CACHE_OFF,
72 SESS_CACHE_CLIENT,
73 SESS_CACHE_SERVER,
74 SESS_CACHE_BOTH,
75 SESS_CACHE_NO_AUTO_CLEAR,
76 SESS_CACHE_NO_INTERNAL_LOOKUP,
77 SESS_CACHE_NO_INTERNAL_STORE,
78 SESS_CACHE_NO_INTERNAL,
79)
Jean-Paul Calderone313bf012012-02-08 13:02:49 -050080
81from OpenSSL.SSL import (
Alex Gaynor03737182020-07-23 20:40:46 -040082 Error,
83 SysCallError,
84 WantReadError,
85 WantWriteError,
86 ZeroReturnError,
87)
88from OpenSSL.SSL import Context, Session, Connection, SSLeay_version
Cory Benfield0ba57ec2016-03-30 09:35:05 +010089from OpenSSL.SSL import _make_requires
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040090
Paul Kehrer55fb3412017-06-29 18:44:08 -050091from OpenSSL._util import ffi as _ffi, lib as _lib
Cory Benfieldba1820d2015-04-13 17:39:12 -040092
Alex Gaynord3b5d9b2016-07-31 10:54:24 -040093from OpenSSL.SSL import (
Alex Gaynor03737182020-07-23 20:40:46 -040094 OP_NO_QUERY_MTU,
95 OP_COOKIE_EXCHANGE,
96 OP_NO_TICKET,
97 OP_NO_COMPRESSION,
98 MODE_RELEASE_BUFFERS,
99 NO_OVERLAPPING_PROTOCOLS,
100)
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400101
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -0400102from OpenSSL.SSL import (
Alex Gaynor03737182020-07-23 20:40:46 -0400103 SSL_ST_CONNECT,
104 SSL_ST_ACCEPT,
105 SSL_ST_MASK,
106 SSL_CB_LOOP,
107 SSL_CB_EXIT,
108 SSL_CB_READ,
109 SSL_CB_WRITE,
110 SSL_CB_ALERT,
111 SSL_CB_READ_ALERT,
112 SSL_CB_WRITE_ALERT,
113 SSL_CB_ACCEPT_LOOP,
114 SSL_CB_ACCEPT_EXIT,
115 SSL_CB_CONNECT_LOOP,
116 SSL_CB_CONNECT_EXIT,
117 SSL_CB_HANDSHAKE_START,
118 SSL_CB_HANDSHAKE_DONE,
119)
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400120
Alex Gaynor5af32d02016-09-24 01:52:21 -0400121try:
122 from OpenSSL.SSL import (
Alex Gaynor03737182020-07-23 20:40:46 -0400123 SSL_ST_INIT,
124 SSL_ST_BEFORE,
125 SSL_ST_OK,
126 SSL_ST_RENEGOTIATE,
Alex Gaynor5af32d02016-09-24 01:52:21 -0400127 )
128except ImportError:
129 SSL_ST_INIT = SSL_ST_BEFORE = SSL_ST_OK = SSL_ST_RENEGOTIATE = None
130
Alex Chanb7480992017-01-30 14:04:47 +0000131from .util import WARNING_TYPE_EXPECTED, NON_ASCII, is_consistent_type
Hynek Schlawackf0e66852015-10-16 20:18:38 +0200132from .test_crypto import (
Alex Gaynor03737182020-07-23 20:40:46 -0400133 client_cert_pem,
134 client_key_pem,
135 server_cert_pem,
136 server_key_pem,
137 root_cert_pem,
Paul Kehrerbeaf9f52020-08-03 17:50:31 -0500138 root_key_pem,
Alex Gaynor03737182020-07-23 20:40:46 -0400139)
Hynek Schlawackf0e66852015-10-16 20:18:38 +0200140
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200141
Paul Kehrer41dc1362020-08-04 23:44:18 -0500142# openssl dhparam 2048 -out dh-2048.pem
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -0400143dhparam = """\
144-----BEGIN DH PARAMETERS-----
Paul Kehrer41dc1362020-08-04 23:44:18 -0500145MIIBCAKCAQEA2F5e976d/GjsaCdKv5RMWL/YV7fq1UUWpPAer5fDXflLMVUuYXxE
1463m3ayZob9lbpgEU0jlPAsXHfQPGxpKmvhv+xV26V/DEoukED8JeZUY/z4pigoptl
147+8+TYdNNE/rFSZQFXIp+v2D91IEgmHBnZlKFSbKR+p8i0KjExXGjU6ji3S5jkOku
148ogikc7df1Ui0hWNJCmTjExq07aXghk97PsdFSxjdawuG3+vos5bnNoUwPLYlFc/z
149ITYG0KXySiCLi4UDlXTZTz7u/+OYczPEgqa/JPUddbM/kfvaRAnjY38cfQ7qXf8Y
150i5s5yYK7a/0eWxxRr2qraYaUj8RwDpH9CwIBAg==
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -0400151-----END DH PARAMETERS-----
152"""
153
154
Hugo van Kemenade60827f82019-08-30 00:39:35 +0300155skip_if_py3 = pytest.mark.skipif(not PY2, reason="Python 2 only")
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200156
157
David Benjamin1fbe0642019-04-15 17:05:13 -0500158def socket_any_family():
159 try:
160 return socket(AF_INET)
161 except error as e:
162 if e.errno == EAFNOSUPPORT:
163 return socket(AF_INET6)
164 raise
165
166
167def loopback_address(socket):
168 if socket.family == AF_INET:
169 return "127.0.0.1"
170 else:
171 assert socket.family == AF_INET6
172 return "::1"
173
174
Jean-Paul Calderone05826732015-04-12 11:38:49 -0400175def join_bytes_or_unicode(prefix, suffix):
176 """
177 Join two path components of either ``bytes`` or ``unicode``.
178
179 The return type is the same as the type of ``prefix``.
180 """
181 # If the types are the same, nothing special is necessary.
182 if type(prefix) == type(suffix):
183 return join(prefix, suffix)
184
185 # Otherwise, coerce suffix to the type of prefix.
186 if isinstance(prefix, text_type):
187 return join(prefix, suffix.decode(getfilesystemencoding()))
188 else:
189 return join(prefix, suffix.encode(getfilesystemencoding()))
190
191
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400192def verify_cb(conn, cert, errnum, depth, ok):
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400193 return ok
194
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400195
Rick Deanb1ccd562009-07-09 23:52:39 -0500196def socket_pair():
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400197 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400198 Establish and return a pair of network sockets connected to each other.
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400199 """
200 # Connect a pair of sockets
David Benjamin1fbe0642019-04-15 17:05:13 -0500201 port = socket_any_family()
Alex Gaynor03737182020-07-23 20:40:46 -0400202 port.bind(("", 0))
Rick Deanb1ccd562009-07-09 23:52:39 -0500203 port.listen(1)
David Benjamin1fbe0642019-04-15 17:05:13 -0500204 client = socket(port.family)
Rick Deanb1ccd562009-07-09 23:52:39 -0500205 client.setblocking(False)
David Benjamin1fbe0642019-04-15 17:05:13 -0500206 client.connect_ex((loopback_address(port), port.getsockname()[1]))
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400207 client.setblocking(True)
Rick Deanb1ccd562009-07-09 23:52:39 -0500208 server = port.accept()[0]
Rick Deanb1ccd562009-07-09 23:52:39 -0500209
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400210 # Let's pass some unencrypted data to make sure our socket connection is
211 # fine. Just one byte, so we don't have to worry about buffers getting
212 # filled up or fragmentation.
Alex Gaynore7f51982016-09-11 11:48:14 -0400213 server.send(b"x")
214 assert client.recv(1024) == b"x"
215 client.send(b"y")
216 assert server.recv(1024) == b"y"
Rick Deanb1ccd562009-07-09 23:52:39 -0500217
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -0400218 # Most of our callers want non-blocking sockets, make it easy for them.
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400219 server.setblocking(False)
220 client.setblocking(False)
Jim Shaver46f28912015-05-29 19:32:16 -0400221
Rick Deanb1ccd562009-07-09 23:52:39 -0500222 return (server, client)
223
224
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400225def handshake(client, server):
226 conns = [client, server]
227 while conns:
228 for conn in conns:
229 try:
230 conn.do_handshake()
231 except WantReadError:
232 pass
233 else:
234 conns.remove(conn)
235
236
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400237def _create_certificate_chain():
238 """
239 Construct and return a chain of certificates.
240
241 1. A new self-signed certificate authority certificate (cacert)
242 2. A new intermediate certificate signed by cacert (icert)
243 3. A new server certificate signed by icert (scert)
244 """
Alex Gaynor03737182020-07-23 20:40:46 -0400245 caext = X509Extension(b"basicConstraints", False, b"CA:true")
246 not_after_date = datetime.date.today() + datetime.timedelta(days=365)
Alex Gaynor675534c2020-01-12 11:59:49 -0600247 not_after = not_after_date.strftime("%Y%m%d%H%M%SZ").encode("ascii")
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400248
249 # Step 1
250 cakey = PKey()
Alex Gaynor8cd336e2020-08-03 10:36:32 -0400251 cakey.generate_key(TYPE_RSA, 2048)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400252 cacert = X509()
David Benjamin6b799472020-06-24 17:14:16 -0400253 cacert.set_version(2)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400254 cacert.get_subject().commonName = "Authority Certificate"
255 cacert.set_issuer(cacert.get_subject())
256 cacert.set_pubkey(cakey)
Alex Gaynore7f51982016-09-11 11:48:14 -0400257 cacert.set_notBefore(b"20000101000000Z")
Alex Gaynor675534c2020-01-12 11:59:49 -0600258 cacert.set_notAfter(not_after)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400259 cacert.add_extensions([caext])
260 cacert.set_serial_number(0)
Paul Kehrerd4b60462020-08-03 18:26:03 -0500261 cacert.sign(cakey, "sha256")
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400262
263 # Step 2
264 ikey = PKey()
Alex Gaynor8cd336e2020-08-03 10:36:32 -0400265 ikey.generate_key(TYPE_RSA, 2048)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400266 icert = X509()
David Benjamin6b799472020-06-24 17:14:16 -0400267 icert.set_version(2)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400268 icert.get_subject().commonName = "Intermediate Certificate"
269 icert.set_issuer(cacert.get_subject())
270 icert.set_pubkey(ikey)
Alex Gaynore7f51982016-09-11 11:48:14 -0400271 icert.set_notBefore(b"20000101000000Z")
Alex Gaynor675534c2020-01-12 11:59:49 -0600272 icert.set_notAfter(not_after)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400273 icert.add_extensions([caext])
274 icert.set_serial_number(0)
Paul Kehrerd4b60462020-08-03 18:26:03 -0500275 icert.sign(cakey, "sha256")
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400276
277 # Step 3
278 skey = PKey()
Alex Gaynor8cd336e2020-08-03 10:36:32 -0400279 skey.generate_key(TYPE_RSA, 2048)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400280 scert = X509()
David Benjamin6b799472020-06-24 17:14:16 -0400281 scert.set_version(2)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400282 scert.get_subject().commonName = "Server Certificate"
283 scert.set_issuer(icert.get_subject())
284 scert.set_pubkey(skey)
Alex Gaynore7f51982016-09-11 11:48:14 -0400285 scert.set_notBefore(b"20000101000000Z")
Alex Gaynor675534c2020-01-12 11:59:49 -0600286 scert.set_notAfter(not_after)
Alex Gaynor03737182020-07-23 20:40:46 -0400287 scert.add_extensions(
288 [X509Extension(b"basicConstraints", True, b"CA:false")]
289 )
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400290 scert.set_serial_number(0)
Paul Kehrerd4b60462020-08-03 18:26:03 -0500291 scert.sign(ikey, "sha256")
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400292
293 return [(cakey, cacert), (ikey, icert), (skey, scert)]
294
295
Paul Kehrer7d5a3bf2019-01-21 12:24:02 -0600296def loopback_client_factory(socket, version=SSLv23_METHOD):
297 client = Connection(Context(version), socket)
Alex Chan1c0cb662017-01-30 07:13:30 +0000298 client.set_connect_state()
299 return client
300
301
Paul Kehrer7d5a3bf2019-01-21 12:24:02 -0600302def loopback_server_factory(socket, version=SSLv23_METHOD):
303 ctx = Context(version)
Alex Chan1c0cb662017-01-30 07:13:30 +0000304 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
305 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
306 server = Connection(ctx, socket)
307 server.set_accept_state()
308 return server
309
310
311def loopback(server_factory=None, client_factory=None):
312 """
313 Create a connected socket pair and force two connected SSL sockets
314 to talk to each other via memory BIOs.
315 """
316 if server_factory is None:
317 server_factory = loopback_server_factory
318 if client_factory is None:
319 client_factory = loopback_client_factory
320
321 (server, client) = socket_pair()
322 server = server_factory(server)
323 client = client_factory(client)
324
325 handshake(client, server)
326
327 server.setblocking(True)
328 client.setblocking(True)
329 return server, client
330
331
Alex Chan1ca9e3a2016-11-05 13:01:51 +0000332def interact_in_memory(client_conn, server_conn):
333 """
334 Try to read application bytes from each of the two `Connection` objects.
335 Copy bytes back and forth between their send/receive buffers for as long
336 as there is anything to copy. When there is nothing more to copy,
337 return `None`. If one of them actually manages to deliver some application
338 bytes, return a two-tuple of the connection from which the bytes were read
339 and the bytes themselves.
340 """
341 wrote = True
342 while wrote:
343 # Loop until neither side has anything to say
344 wrote = False
345
346 # Copy stuff from each side's send buffer to the other side's
347 # receive buffer.
Alex Gaynor03737182020-07-23 20:40:46 -0400348 for (read, write) in [
349 (client_conn, server_conn),
350 (server_conn, client_conn),
351 ]:
Alex Chan1ca9e3a2016-11-05 13:01:51 +0000352
353 # Give the side a chance to generate some more bytes, or succeed.
354 try:
355 data = read.recv(2 ** 16)
356 except WantReadError:
357 # It didn't succeed, so we'll hope it generated some output.
358 pass
359 else:
360 # It did succeed, so we'll stop now and let the caller deal
361 # with it.
362 return (read, data)
363
364 while True:
365 # Keep copying as long as there's more stuff there.
366 try:
367 dirty = read.bio_read(4096)
368 except WantReadError:
369 # Okay, nothing more waiting to be sent. Stop
370 # processing this send buffer.
371 break
372 else:
373 # Keep track of the fact that someone generated some
374 # output.
375 wrote = True
376 write.bio_write(dirty)
377
378
Alex Chan532b79e2017-01-24 15:14:52 +0000379def handshake_in_memory(client_conn, server_conn):
380 """
381 Perform the TLS handshake between two `Connection` instances connected to
382 each other via memory BIOs.
383 """
384 client_conn.set_connect_state()
385 server_conn.set_accept_state()
386
387 for conn in [client_conn, server_conn]:
388 try:
389 conn.do_handshake()
390 except WantReadError:
391 pass
392
393 interact_in_memory(client_conn, server_conn)
394
395
Alex Chanb7480992017-01-30 14:04:47 +0000396class TestVersion(object):
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400397 """
Alex Chanb7480992017-01-30 14:04:47 +0000398 Tests for version information exposed by `OpenSSL.SSL.SSLeay_version` and
399 `OpenSSL.SSL.OPENSSL_VERSION_NUMBER`.
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400400 """
Alex Gaynor03737182020-07-23 20:40:46 -0400401
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400402 def test_OPENSSL_VERSION_NUMBER(self):
403 """
Alex Chanb7480992017-01-30 14:04:47 +0000404 `OPENSSL_VERSION_NUMBER` is an integer with status in the low byte and
405 the patch, fix, minor, and major versions in the nibbles above that.
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400406 """
Alex Chanb7480992017-01-30 14:04:47 +0000407 assert isinstance(OPENSSL_VERSION_NUMBER, int)
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400408
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400409 def test_SSLeay_version(self):
410 """
Alex Chanb7480992017-01-30 14:04:47 +0000411 `SSLeay_version` takes a version type indicator and returns one of a
412 number of version strings based on that indicator.
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400413 """
414 versions = {}
Alex Gaynor03737182020-07-23 20:40:46 -0400415 for t in [
416 SSLEAY_VERSION,
417 SSLEAY_CFLAGS,
418 SSLEAY_BUILT_ON,
419 SSLEAY_PLATFORM,
420 SSLEAY_DIR,
421 ]:
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400422 version = SSLeay_version(t)
423 versions[version] = t
Alex Chanb7480992017-01-30 14:04:47 +0000424 assert isinstance(version, bytes)
425 assert len(versions) == 5
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400426
427
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100428@pytest.fixture
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100429def ca_file(tmpdir):
430 """
431 Create a valid PEM file with CA certificates and return the path.
432 """
433 key = rsa.generate_private_key(
Alex Gaynor03737182020-07-23 20:40:46 -0400434 public_exponent=65537, key_size=2048, backend=default_backend()
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100435 )
436 public_key = key.public_key()
437
438 builder = x509.CertificateBuilder()
Alex Gaynor03737182020-07-23 20:40:46 -0400439 builder = builder.subject_name(
440 x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, u"pyopenssl.org")])
441 )
442 builder = builder.issuer_name(
443 x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, u"pyopenssl.org")])
444 )
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100445 one_day = datetime.timedelta(1, 0, 0)
446 builder = builder.not_valid_before(datetime.datetime.today() - one_day)
447 builder = builder.not_valid_after(datetime.datetime.today() + one_day)
448 builder = builder.serial_number(int(uuid.uuid4()))
449 builder = builder.public_key(public_key)
450 builder = builder.add_extension(
Alex Gaynor04882142020-08-26 22:50:40 -0400451 x509.BasicConstraints(ca=True, path_length=None),
452 critical=True,
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100453 )
454
455 certificate = builder.sign(
Alex Gaynor03737182020-07-23 20:40:46 -0400456 private_key=key, algorithm=hashes.SHA256(), backend=default_backend()
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100457 )
458
459 ca_file = tmpdir.join("test.pem")
460 ca_file.write_binary(
Alex Gaynor04882142020-08-26 22:50:40 -0400461 certificate.public_bytes(
462 encoding=serialization.Encoding.PEM,
463 )
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100464 )
465
466 return str(ca_file).encode("ascii")
467
468
469@pytest.fixture
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100470def context():
471 """
Paul Kehrer688538c2020-08-03 19:18:15 -0500472 A simple "best TLS you can get" context. TLS 1.2+ in any reasonable OpenSSL
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100473 """
Paul Kehrer688538c2020-08-03 19:18:15 -0500474 return Context(SSLv23_METHOD)
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100475
476
477class TestContext(object):
Hynek Schlawackaa861212016-03-13 13:53:48 +0100478 """
Alex Chan532b79e2017-01-24 15:14:52 +0000479 Unit tests for `OpenSSL.SSL.Context`.
Hynek Schlawackaa861212016-03-13 13:53:48 +0100480 """
Alex Gaynor03737182020-07-23 20:40:46 -0400481
482 @pytest.mark.parametrize(
483 "cipher_string",
484 [b"hello world:AES128-SHA", u"hello world:AES128-SHA"],
485 )
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100486 def test_set_cipher_list(self, context, cipher_string):
487 """
Alex Chan532b79e2017-01-24 15:14:52 +0000488 `Context.set_cipher_list` accepts both byte and unicode strings
Hynek Schlawacka7a63af2016-03-11 12:05:26 +0100489 for naming the ciphers which connections created with the context
490 object will be able to choose from.
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100491 """
492 context.set_cipher_list(cipher_string)
493 conn = Connection(context, None)
494
495 assert "AES128-SHA" in conn.get_cipher_list()
496
Mark Williamsdf2480d2019-02-14 19:30:07 -0800497 def test_set_cipher_list_wrong_type(self, context):
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100498 """
Alex Chan532b79e2017-01-24 15:14:52 +0000499 `Context.set_cipher_list` raises `TypeError` when passed a non-string
Mark Williamsdf2480d2019-02-14 19:30:07 -0800500 argument.
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100501 """
Mark Williamsdf2480d2019-02-14 19:30:07 -0800502 with pytest.raises(TypeError):
503 context.set_cipher_list(object())
504
Alex Gaynor963ae032019-07-06 17:38:32 -0400505 @flaky.flaky
Mark Williamsdf2480d2019-02-14 19:30:07 -0800506 def test_set_cipher_list_no_cipher_match(self, context):
507 """
508 `Context.set_cipher_list` raises `OpenSSL.SSL.Error` with a
509 `"no cipher match"` reason string regardless of the TLS
510 version.
511 """
512 with pytest.raises(Error) as excinfo:
513 context.set_cipher_list(b"imaginary-cipher")
514 assert excinfo.value.args == (
Alex Gaynor04882142020-08-26 22:50:40 -0400515 [
516 (
517 "SSL routines",
518 "SSL_CTX_set_cipher_list",
519 "no cipher match",
520 )
521 ],
Alex Gaynor03737182020-07-23 20:40:46 -0400522 )
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100523
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100524 def test_load_client_ca(self, context, ca_file):
525 """
Alex Chan532b79e2017-01-24 15:14:52 +0000526 `Context.load_client_ca` works as far as we can tell.
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100527 """
528 context.load_client_ca(ca_file)
529
530 def test_load_client_ca_invalid(self, context, tmpdir):
531 """
Alex Chan532b79e2017-01-24 15:14:52 +0000532 `Context.load_client_ca` raises an Error if the ca file is invalid.
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100533 """
534 ca_file = tmpdir.join("test.pem")
535 ca_file.write("")
536
537 with pytest.raises(Error) as e:
538 context.load_client_ca(str(ca_file).encode("ascii"))
539
540 assert "PEM routines" == e.value.args[0][0][0]
541
542 def test_load_client_ca_unicode(self, context, ca_file):
543 """
544 Passing the path as unicode raises a warning but works.
545 """
Alex Gaynor03737182020-07-23 20:40:46 -0400546 pytest.deprecated_call(context.load_client_ca, ca_file.decode("ascii"))
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100547
548 def test_set_session_id(self, context):
549 """
Alex Chan532b79e2017-01-24 15:14:52 +0000550 `Context.set_session_id` works as far as we can tell.
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100551 """
552 context.set_session_id(b"abc")
553
554 def test_set_session_id_fail(self, context):
555 """
Alex Chan532b79e2017-01-24 15:14:52 +0000556 `Context.set_session_id` errors are propagated.
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100557 """
558 with pytest.raises(Error) as e:
559 context.set_session_id(b"abc" * 1000)
560
561 assert [
Alex Gaynor03737182020-07-23 20:40:46 -0400562 (
563 "SSL routines",
564 "SSL_CTX_set_session_id_context",
565 "ssl session id context too long",
566 )
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100567 ] == e.value.args[0]
568
569 def test_set_session_id_unicode(self, context):
570 """
Alex Chan532b79e2017-01-24 15:14:52 +0000571 `Context.set_session_id` raises a warning if a unicode string is
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100572 passed.
573 """
574 pytest.deprecated_call(context.set_session_id, u"abc")
575
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400576 def test_method(self):
577 """
Alex Chan532b79e2017-01-24 15:14:52 +0000578 `Context` can be instantiated with one of `SSLv2_METHOD`,
579 `SSLv3_METHOD`, `SSLv23_METHOD`, `TLSv1_METHOD`, `TLSv1_1_METHOD`,
580 or `TLSv1_2_METHOD`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400581 """
Alex Gaynor5af32d02016-09-24 01:52:21 -0400582 methods = [SSLv23_METHOD, TLSv1_METHOD]
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400583 for meth in methods:
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400584 Context(meth)
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400585
Alex Gaynor5af32d02016-09-24 01:52:21 -0400586 maybe = [SSLv2_METHOD, SSLv3_METHOD, TLSv1_1_METHOD, TLSv1_2_METHOD]
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400587 for meth in maybe:
588 try:
589 Context(meth)
590 except (Error, ValueError):
591 # Some versions of OpenSSL have SSLv2 / TLSv1.1 / TLSv1.2, some
592 # don't. Difficult to say in advance.
593 pass
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400594
Alex Chan532b79e2017-01-24 15:14:52 +0000595 with pytest.raises(TypeError):
596 Context("")
597 with pytest.raises(ValueError):
598 Context(10)
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400599
Rick Deane15b1472009-07-09 15:53:42 -0500600 def test_type(self):
601 """
Alex Gaynor01f90a12019-02-07 09:14:48 -0500602 `Context` can be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -0500603 """
Alex Gaynor03737182020-07-23 20:40:46 -0400604 assert is_consistent_type(Context, "Context", TLSv1_METHOD)
Rick Deane15b1472009-07-09 15:53:42 -0500605
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400606 def test_use_privatekey(self):
607 """
Alex Chan532b79e2017-01-24 15:14:52 +0000608 `Context.use_privatekey` takes an `OpenSSL.crypto.PKey` instance.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400609 """
610 key = PKey()
Paul Kehrerc45a6ea2020-08-03 15:54:20 -0500611 key.generate_key(TYPE_RSA, 1024)
Paul Kehrer688538c2020-08-03 19:18:15 -0500612 ctx = Context(SSLv23_METHOD)
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400613 ctx.use_privatekey(key)
Alex Chan532b79e2017-01-24 15:14:52 +0000614 with pytest.raises(TypeError):
615 ctx.use_privatekey("")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400616
Alex Chan532b79e2017-01-24 15:14:52 +0000617 def test_use_privatekey_file_missing(self, tmpfile):
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800618 """
Alex Chan532b79e2017-01-24 15:14:52 +0000619 `Context.use_privatekey_file` raises `OpenSSL.SSL.Error` when passed
620 the name of a file which does not exist.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800621 """
Paul Kehrer688538c2020-08-03 19:18:15 -0500622 ctx = Context(SSLv23_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000623 with pytest.raises(Error):
624 ctx.use_privatekey_file(tmpfile)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800625
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400626 def _use_privatekey_file_test(self, pemfile, filetype):
627 """
628 Verify that calling ``Context.use_privatekey_file`` with the given
629 arguments does not raise an exception.
630 """
631 key = PKey()
Paul Kehrerc45a6ea2020-08-03 15:54:20 -0500632 key.generate_key(TYPE_RSA, 1024)
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400633
634 with open(pemfile, "wt") as pem:
Alex Gaynor03737182020-07-23 20:40:46 -0400635 pem.write(dump_privatekey(FILETYPE_PEM, key).decode("ascii"))
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400636
Paul Kehrer688538c2020-08-03 19:18:15 -0500637 ctx = Context(SSLv23_METHOD)
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400638 ctx.use_privatekey_file(pemfile, filetype)
639
Alex Gaynor03737182020-07-23 20:40:46 -0400640 @pytest.mark.parametrize("filetype", [object(), "", None, 1.0])
Alex Chanfb078d82017-04-20 11:16:15 +0100641 def test_wrong_privatekey_file_wrong_args(self, tmpfile, filetype):
642 """
643 `Context.use_privatekey_file` raises `TypeError` when called with
644 a `filetype` which is not a valid file encoding.
645 """
Paul Kehrer688538c2020-08-03 19:18:15 -0500646 ctx = Context(SSLv23_METHOD)
Alex Chanfb078d82017-04-20 11:16:15 +0100647 with pytest.raises(TypeError):
648 ctx.use_privatekey_file(tmpfile, filetype)
649
Alex Chan532b79e2017-01-24 15:14:52 +0000650 def test_use_privatekey_file_bytes(self, tmpfile):
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400651 """
652 A private key can be specified from a file by passing a ``bytes``
653 instance giving the file name to ``Context.use_privatekey_file``.
654 """
655 self._use_privatekey_file_test(
Alex Gaynor04882142020-08-26 22:50:40 -0400656 tmpfile + NON_ASCII.encode(getfilesystemencoding()),
657 FILETYPE_PEM,
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400658 )
659
Alex Chan532b79e2017-01-24 15:14:52 +0000660 def test_use_privatekey_file_unicode(self, tmpfile):
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400661 """
662 A private key can be specified from a file by passing a ``unicode``
663 instance giving the file name to ``Context.use_privatekey_file``.
664 """
665 self._use_privatekey_file_test(
Alex Gaynor04882142020-08-26 22:50:40 -0400666 tmpfile.decode(getfilesystemencoding()) + NON_ASCII,
667 FILETYPE_PEM,
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400668 )
669
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800670 def test_use_certificate_wrong_args(self):
671 """
Alex Chan532b79e2017-01-24 15:14:52 +0000672 `Context.use_certificate_wrong_args` raises `TypeError` when not passed
673 exactly one `OpenSSL.crypto.X509` instance as an argument.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800674 """
Paul Kehrer688538c2020-08-03 19:18:15 -0500675 ctx = Context(SSLv23_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000676 with pytest.raises(TypeError):
677 ctx.use_certificate("hello, world")
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800678
679 def test_use_certificate_uninitialized(self):
680 """
Alex Chan532b79e2017-01-24 15:14:52 +0000681 `Context.use_certificate` raises `OpenSSL.SSL.Error` when passed a
682 `OpenSSL.crypto.X509` instance which has not been initialized
683 (ie, which does not actually have any certificate data).
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800684 """
Paul Kehrer688538c2020-08-03 19:18:15 -0500685 ctx = Context(SSLv23_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000686 with pytest.raises(Error):
687 ctx.use_certificate(X509())
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800688
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800689 def test_use_certificate(self):
690 """
Alex Chan532b79e2017-01-24 15:14:52 +0000691 `Context.use_certificate` sets the certificate which will be
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800692 used to identify connections created using the context.
693 """
694 # TODO
695 # Hard to assert anything. But we could set a privatekey then ask
696 # OpenSSL if the cert and key agree using check_privatekey. Then as
697 # long as check_privatekey works right we're good...
Paul Kehrer688538c2020-08-03 19:18:15 -0500698 ctx = Context(SSLv23_METHOD)
Paul Kehrerbeaf9f52020-08-03 17:50:31 -0500699 ctx.use_certificate(load_certificate(FILETYPE_PEM, root_cert_pem))
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800700
701 def test_use_certificate_file_wrong_args(self):
702 """
Alex Chan532b79e2017-01-24 15:14:52 +0000703 `Context.use_certificate_file` raises `TypeError` if the first
704 argument is not a byte string or the second argument is not an integer.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800705 """
Paul Kehrer688538c2020-08-03 19:18:15 -0500706 ctx = Context(SSLv23_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000707 with pytest.raises(TypeError):
708 ctx.use_certificate_file(object(), FILETYPE_PEM)
709 with pytest.raises(TypeError):
710 ctx.use_certificate_file(b"somefile", object())
711 with pytest.raises(TypeError):
712 ctx.use_certificate_file(object(), FILETYPE_PEM)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800713
Alex Chan532b79e2017-01-24 15:14:52 +0000714 def test_use_certificate_file_missing(self, tmpfile):
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800715 """
Alex Chan532b79e2017-01-24 15:14:52 +0000716 `Context.use_certificate_file` raises `OpenSSL.SSL.Error` if passed
717 the name of a file which does not exist.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800718 """
Paul Kehrer688538c2020-08-03 19:18:15 -0500719 ctx = Context(SSLv23_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000720 with pytest.raises(Error):
721 ctx.use_certificate_file(tmpfile)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800722
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400723 def _use_certificate_file_test(self, certificate_file):
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800724 """
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400725 Verify that calling ``Context.use_certificate_file`` with the given
726 filename doesn't raise an exception.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800727 """
728 # TODO
729 # Hard to assert anything. But we could set a privatekey then ask
730 # OpenSSL if the cert and key agree using check_privatekey. Then as
731 # long as check_privatekey works right we're good...
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400732 with open(certificate_file, "wb") as pem_file:
Paul Kehrerbeaf9f52020-08-03 17:50:31 -0500733 pem_file.write(root_cert_pem)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800734
Paul Kehrer688538c2020-08-03 19:18:15 -0500735 ctx = Context(SSLv23_METHOD)
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400736 ctx.use_certificate_file(certificate_file)
737
Alex Chan532b79e2017-01-24 15:14:52 +0000738 def test_use_certificate_file_bytes(self, tmpfile):
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400739 """
Alex Chan532b79e2017-01-24 15:14:52 +0000740 `Context.use_certificate_file` sets the certificate (given as a
741 `bytes` filename) which will be used to identify connections created
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400742 using the context.
743 """
Alex Chan532b79e2017-01-24 15:14:52 +0000744 filename = tmpfile + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400745 self._use_certificate_file_test(filename)
746
Alex Chan532b79e2017-01-24 15:14:52 +0000747 def test_use_certificate_file_unicode(self, tmpfile):
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400748 """
Alex Chan532b79e2017-01-24 15:14:52 +0000749 `Context.use_certificate_file` sets the certificate (given as a
750 `bytes` filename) which will be used to identify connections created
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400751 using the context.
752 """
Alex Chan532b79e2017-01-24 15:14:52 +0000753 filename = tmpfile.decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400754 self._use_certificate_file_test(filename)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800755
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500756 def test_check_privatekey_valid(self):
757 """
Alex Chan532b79e2017-01-24 15:14:52 +0000758 `Context.check_privatekey` returns `None` if the `Context` instance
759 has been configured to use a matched key and certificate pair.
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500760 """
761 key = load_privatekey(FILETYPE_PEM, client_key_pem)
762 cert = load_certificate(FILETYPE_PEM, client_cert_pem)
Paul Kehrer688538c2020-08-03 19:18:15 -0500763 context = Context(SSLv23_METHOD)
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500764 context.use_privatekey(key)
765 context.use_certificate(cert)
Alex Chan532b79e2017-01-24 15:14:52 +0000766 assert None is context.check_privatekey()
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500767
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500768 def test_check_privatekey_invalid(self):
769 """
Alex Chan532b79e2017-01-24 15:14:52 +0000770 `Context.check_privatekey` raises `Error` if the `Context` instance
771 has been configured to use a key and certificate pair which don't
772 relate to each other.
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500773 """
774 key = load_privatekey(FILETYPE_PEM, client_key_pem)
775 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
Paul Kehrer688538c2020-08-03 19:18:15 -0500776 context = Context(SSLv23_METHOD)
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500777 context.use_privatekey(key)
778 context.use_certificate(cert)
Alex Chan532b79e2017-01-24 15:14:52 +0000779 with pytest.raises(Error):
780 context.check_privatekey()
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400781
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400782 def test_app_data(self):
783 """
Alex Chan532b79e2017-01-24 15:14:52 +0000784 `Context.set_app_data` stores an object for later retrieval
785 using `Context.get_app_data`.
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400786 """
787 app_data = object()
Paul Kehrer688538c2020-08-03 19:18:15 -0500788 context = Context(SSLv23_METHOD)
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400789 context.set_app_data(app_data)
Alex Chan532b79e2017-01-24 15:14:52 +0000790 assert context.get_app_data() is app_data
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400791
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400792 def test_set_options_wrong_args(self):
793 """
Alex Chan532b79e2017-01-24 15:14:52 +0000794 `Context.set_options` raises `TypeError` if called with
795 a non-`int` argument.
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400796 """
Paul Kehrer688538c2020-08-03 19:18:15 -0500797 context = Context(SSLv23_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000798 with pytest.raises(TypeError):
799 context.set_options(None)
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400800
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500801 def test_set_options(self):
802 """
Alex Chan532b79e2017-01-24 15:14:52 +0000803 `Context.set_options` returns the new options value.
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500804 """
Paul Kehrer688538c2020-08-03 19:18:15 -0500805 context = Context(SSLv23_METHOD)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500806 options = context.set_options(OP_NO_SSLv2)
Alex Gaynor2310f8b2016-09-10 14:39:32 -0400807 assert options & OP_NO_SSLv2 == OP_NO_SSLv2
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500808
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300809 def test_set_mode_wrong_args(self):
810 """
Alex Chan532b79e2017-01-24 15:14:52 +0000811 `Context.set_mode` raises `TypeError` if called with
812 a non-`int` argument.
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300813 """
Paul Kehrer688538c2020-08-03 19:18:15 -0500814 context = Context(SSLv23_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000815 with pytest.raises(TypeError):
816 context.set_mode(None)
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300817
Alex Gaynord3b5d9b2016-07-31 10:54:24 -0400818 def test_set_mode(self):
819 """
Alex Chan532b79e2017-01-24 15:14:52 +0000820 `Context.set_mode` accepts a mode bitvector and returns the
Alex Gaynord3b5d9b2016-07-31 10:54:24 -0400821 newly set mode.
822 """
Paul Kehrer688538c2020-08-03 19:18:15 -0500823 context = Context(SSLv23_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000824 assert MODE_RELEASE_BUFFERS & context.set_mode(MODE_RELEASE_BUFFERS)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500825
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400826 def test_set_timeout_wrong_args(self):
827 """
Alex Chan532b79e2017-01-24 15:14:52 +0000828 `Context.set_timeout` raises `TypeError` if called with
829 a non-`int` argument.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400830 """
Paul Kehrer688538c2020-08-03 19:18:15 -0500831 context = Context(SSLv23_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000832 with pytest.raises(TypeError):
833 context.set_timeout(None)
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400834
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400835 def test_timeout(self):
836 """
Alex Chan532b79e2017-01-24 15:14:52 +0000837 `Context.set_timeout` sets the session timeout for all connections
838 created using the context object. `Context.get_timeout` retrieves
839 this value.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400840 """
Paul Kehrer688538c2020-08-03 19:18:15 -0500841 context = Context(SSLv23_METHOD)
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400842 context.set_timeout(1234)
Alex Chan532b79e2017-01-24 15:14:52 +0000843 assert context.get_timeout() == 1234
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400844
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400845 def test_set_verify_depth_wrong_args(self):
846 """
Alex Chan532b79e2017-01-24 15:14:52 +0000847 `Context.set_verify_depth` raises `TypeError` if called with a
848 non-`int` argument.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400849 """
Paul Kehrer688538c2020-08-03 19:18:15 -0500850 context = Context(SSLv23_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000851 with pytest.raises(TypeError):
852 context.set_verify_depth(None)
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400853
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400854 def test_verify_depth(self):
855 """
Alex Chan532b79e2017-01-24 15:14:52 +0000856 `Context.set_verify_depth` sets the number of certificates in
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200857 a chain to follow before giving up. The value can be retrieved with
Alex Chan532b79e2017-01-24 15:14:52 +0000858 `Context.get_verify_depth`.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400859 """
Paul Kehrer688538c2020-08-03 19:18:15 -0500860 context = Context(SSLv23_METHOD)
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400861 context.set_verify_depth(11)
Alex Chan532b79e2017-01-24 15:14:52 +0000862 assert context.get_verify_depth() == 11
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400863
Alex Chan532b79e2017-01-24 15:14:52 +0000864 def _write_encrypted_pem(self, passphrase, tmpfile):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400865 """
866 Write a new private key out to a new file, encrypted using the given
867 passphrase. Return the path to the new file.
868 """
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400869 key = PKey()
Paul Kehrerc45a6ea2020-08-03 15:54:20 -0500870 key.generate_key(TYPE_RSA, 1024)
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400871 pem = dump_privatekey(FILETYPE_PEM, key, "blowfish", passphrase)
Alex Gaynor03737182020-07-23 20:40:46 -0400872 with open(tmpfile, "w") as fObj:
873 fObj.write(pem.decode("ascii"))
Alex Chan532b79e2017-01-24 15:14:52 +0000874 return tmpfile
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400875
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400876 def test_set_passwd_cb_wrong_args(self):
877 """
Alex Chan532b79e2017-01-24 15:14:52 +0000878 `Context.set_passwd_cb` raises `TypeError` if called with a
879 non-callable first argument.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400880 """
Paul Kehrer688538c2020-08-03 19:18:15 -0500881 context = Context(SSLv23_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000882 with pytest.raises(TypeError):
883 context.set_passwd_cb(None)
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400884
Alex Chan532b79e2017-01-24 15:14:52 +0000885 def test_set_passwd_cb(self, tmpfile):
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400886 """
Alex Chan532b79e2017-01-24 15:14:52 +0000887 `Context.set_passwd_cb` accepts a callable which will be invoked when
888 a private key is loaded from an encrypted PEM.
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400889 """
Alex Gaynore7f51982016-09-11 11:48:14 -0400890 passphrase = b"foobar"
Alex Chan532b79e2017-01-24 15:14:52 +0000891 pemFile = self._write_encrypted_pem(passphrase, tmpfile)
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400892 calledWith = []
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200893
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400894 def passphraseCallback(maxlen, verify, extra):
895 calledWith.append((maxlen, verify, extra))
896 return passphrase
Alex Gaynor03737182020-07-23 20:40:46 -0400897
Paul Kehrer688538c2020-08-03 19:18:15 -0500898 context = Context(SSLv23_METHOD)
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400899 context.set_passwd_cb(passphraseCallback)
900 context.use_privatekey_file(pemFile)
Alex Chan532b79e2017-01-24 15:14:52 +0000901 assert len(calledWith) == 1
902 assert isinstance(calledWith[0][0], int)
903 assert isinstance(calledWith[0][1], int)
904 assert calledWith[0][2] is None
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400905
Alex Chan532b79e2017-01-24 15:14:52 +0000906 def test_passwd_callback_exception(self, tmpfile):
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400907 """
Alex Chan532b79e2017-01-24 15:14:52 +0000908 `Context.use_privatekey_file` propagates any exception raised
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200909 by the passphrase callback.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400910 """
Alex Chan532b79e2017-01-24 15:14:52 +0000911 pemFile = self._write_encrypted_pem(b"monkeys are nice", tmpfile)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200912
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400913 def passphraseCallback(maxlen, verify, extra):
914 raise RuntimeError("Sorry, I am a fail.")
915
Paul Kehrer688538c2020-08-03 19:18:15 -0500916 context = Context(SSLv23_METHOD)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400917 context.set_passwd_cb(passphraseCallback)
Alex Chan532b79e2017-01-24 15:14:52 +0000918 with pytest.raises(RuntimeError):
919 context.use_privatekey_file(pemFile)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400920
Alex Chan532b79e2017-01-24 15:14:52 +0000921 def test_passwd_callback_false(self, tmpfile):
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400922 """
Alex Chan532b79e2017-01-24 15:14:52 +0000923 `Context.use_privatekey_file` raises `OpenSSL.SSL.Error` if the
924 passphrase callback returns a false value.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400925 """
Alex Chan532b79e2017-01-24 15:14:52 +0000926 pemFile = self._write_encrypted_pem(b"monkeys are nice", tmpfile)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200927
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400928 def passphraseCallback(maxlen, verify, extra):
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500929 return b""
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400930
Paul Kehrer688538c2020-08-03 19:18:15 -0500931 context = Context(SSLv23_METHOD)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400932 context.set_passwd_cb(passphraseCallback)
Alex Chan532b79e2017-01-24 15:14:52 +0000933 with pytest.raises(Error):
934 context.use_privatekey_file(pemFile)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400935
Alex Chan532b79e2017-01-24 15:14:52 +0000936 def test_passwd_callback_non_string(self, tmpfile):
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400937 """
Alex Chan532b79e2017-01-24 15:14:52 +0000938 `Context.use_privatekey_file` raises `OpenSSL.SSL.Error` if the
939 passphrase callback returns a true non-string value.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400940 """
Alex Chan532b79e2017-01-24 15:14:52 +0000941 pemFile = self._write_encrypted_pem(b"monkeys are nice", tmpfile)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200942
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400943 def passphraseCallback(maxlen, verify, extra):
944 return 10
945
Paul Kehrer688538c2020-08-03 19:18:15 -0500946 context = Context(SSLv23_METHOD)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400947 context.set_passwd_cb(passphraseCallback)
Alex Chan532b79e2017-01-24 15:14:52 +0000948 # TODO: Surely this is the wrong error?
949 with pytest.raises(ValueError):
950 context.use_privatekey_file(pemFile)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400951
Alex Chan532b79e2017-01-24 15:14:52 +0000952 def test_passwd_callback_too_long(self, tmpfile):
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400953 """
954 If the passphrase returned by the passphrase callback returns a string
955 longer than the indicated maximum length, it is truncated.
956 """
957 # A priori knowledge!
Alex Gaynore7f51982016-09-11 11:48:14 -0400958 passphrase = b"x" * 1024
Alex Chan532b79e2017-01-24 15:14:52 +0000959 pemFile = self._write_encrypted_pem(passphrase, tmpfile)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200960
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400961 def passphraseCallback(maxlen, verify, extra):
962 assert maxlen == 1024
Alex Gaynore7f51982016-09-11 11:48:14 -0400963 return passphrase + b"y"
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400964
Paul Kehrer688538c2020-08-03 19:18:15 -0500965 context = Context(SSLv23_METHOD)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400966 context.set_passwd_cb(passphraseCallback)
967 # This shall succeed because the truncated result is the correct
968 # passphrase.
969 context.use_privatekey_file(pemFile)
970
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400971 def test_set_info_callback(self):
972 """
Alex Chan532b79e2017-01-24 15:14:52 +0000973 `Context.set_info_callback` accepts a callable which will be
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200974 invoked when certain information about an SSL connection is available.
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400975 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500976 (server, client) = socket_pair()
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400977
Paul Kehrer688538c2020-08-03 19:18:15 -0500978 clientSSL = Connection(Context(SSLv23_METHOD), client)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400979 clientSSL.set_connect_state()
980
981 called = []
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200982
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400983 def info(conn, where, ret):
984 called.append((conn, where, ret))
Alex Gaynor03737182020-07-23 20:40:46 -0400985
Paul Kehrer688538c2020-08-03 19:18:15 -0500986 context = Context(SSLv23_METHOD)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400987 context.set_info_callback(info)
Paul Kehrerbeaf9f52020-08-03 17:50:31 -0500988 context.use_certificate(load_certificate(FILETYPE_PEM, root_cert_pem))
989 context.use_privatekey(load_privatekey(FILETYPE_PEM, root_key_pem))
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400990
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400991 serverSSL = Connection(context, server)
992 serverSSL.set_accept_state()
993
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -0500994 handshake(clientSSL, serverSSL)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400995
Jean-Paul Calderone3835e522014-02-02 11:12:30 -0500996 # The callback must always be called with a Connection instance as the
997 # first argument. It would probably be better to split this into
998 # separate tests for client and server side info callbacks so we could
999 # assert it is called with the right Connection instance. It would
1000 # also be good to assert *something* about `where` and `ret`.
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -05001001 notConnections = [
Alex Gaynor03737182020-07-23 20:40:46 -04001002 conn
1003 for (conn, where, ret) in called
1004 if not isinstance(conn, Connection)
1005 ]
1006 assert (
1007 [] == notConnections
1008 ), "Some info callback arguments were not Connection instances."
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001009
Maximilian Hilsb2bca412020-07-28 16:31:22 +02001010 @pytest.mark.skipif(
1011 not getattr(_lib, "Cryptography_HAS_KEYLOG", None),
1012 reason="SSL_CTX_set_keylog_callback unavailable",
1013 )
1014 def test_set_keylog_callback(self):
1015 """
1016 `Context.set_keylog_callback` accepts a callable which will be
1017 invoked when key material is generated or received.
1018 """
1019 called = []
1020
1021 def keylog(conn, line):
1022 called.append((conn, line))
1023
Paul Kehrer688538c2020-08-03 19:18:15 -05001024 server_context = Context(TLSv1_2_METHOD)
Maximilian Hilsb2bca412020-07-28 16:31:22 +02001025 server_context.set_keylog_callback(keylog)
1026 server_context.use_certificate(
Paul Kehrerbeaf9f52020-08-03 17:50:31 -05001027 load_certificate(FILETYPE_PEM, root_cert_pem)
Maximilian Hilsb2bca412020-07-28 16:31:22 +02001028 )
1029 server_context.use_privatekey(
Paul Kehrerbeaf9f52020-08-03 17:50:31 -05001030 load_privatekey(FILETYPE_PEM, root_key_pem)
Maximilian Hilsb2bca412020-07-28 16:31:22 +02001031 )
1032
Paul Kehrer688538c2020-08-03 19:18:15 -05001033 client_context = Context(SSLv23_METHOD)
Maximilian Hilsb2bca412020-07-28 16:31:22 +02001034
1035 self._handshake_test(server_context, client_context)
1036
1037 assert called
1038 assert all(isinstance(conn, Connection) for conn, line in called)
1039 assert all(b"CLIENT_RANDOM" in line for conn, line in called)
1040
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001041 def _load_verify_locations_test(self, *args):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001042 """
1043 Create a client context which will verify the peer certificate and call
Alex Chan532b79e2017-01-24 15:14:52 +00001044 its `load_verify_locations` method with the given arguments.
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04001045 Then connect it to a server and ensure that the handshake succeeds.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001046 """
Rick Deanb1ccd562009-07-09 23:52:39 -05001047 (server, client) = socket_pair()
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001048
Paul Kehrer688538c2020-08-03 19:18:15 -05001049 clientContext = Context(SSLv23_METHOD)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001050 clientContext.load_verify_locations(*args)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001051 # Require that the server certificate verify properly or the
1052 # connection will fail.
1053 clientContext.set_verify(
1054 VERIFY_PEER,
Alex Gaynor03737182020-07-23 20:40:46 -04001055 lambda conn, cert, errno, depth, preverify_ok: preverify_ok,
1056 )
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001057
1058 clientSSL = Connection(clientContext, client)
1059 clientSSL.set_connect_state()
1060
Paul Kehrer688538c2020-08-03 19:18:15 -05001061 serverContext = Context(SSLv23_METHOD)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001062 serverContext.use_certificate(
Paul Kehrerbeaf9f52020-08-03 17:50:31 -05001063 load_certificate(FILETYPE_PEM, root_cert_pem)
Alex Gaynor03737182020-07-23 20:40:46 -04001064 )
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001065 serverContext.use_privatekey(
Paul Kehrerbeaf9f52020-08-03 17:50:31 -05001066 load_privatekey(FILETYPE_PEM, root_key_pem)
Alex Gaynor03737182020-07-23 20:40:46 -04001067 )
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001068
1069 serverSSL = Connection(serverContext, server)
1070 serverSSL.set_accept_state()
1071
Jean-Paul Calderonef8742032010-09-25 00:00:32 -04001072 # Without load_verify_locations above, the handshake
1073 # will fail:
1074 # Error: [('SSL routines', 'SSL3_GET_SERVER_CERTIFICATE',
1075 # 'certificate verify failed')]
1076 handshake(clientSSL, serverSSL)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001077
1078 cert = clientSSL.get_peer_certificate()
Alex Gaynor03737182020-07-23 20:40:46 -04001079 assert cert.get_subject().CN == "Testing Root CA"
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -04001080
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001081 def _load_verify_cafile(self, cafile):
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001082 """
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001083 Verify that if path to a file containing a certificate is passed to
Alex Chan532b79e2017-01-24 15:14:52 +00001084 `Context.load_verify_locations` for the ``cafile`` parameter, that
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001085 certificate is used as a trust root for the purposes of verifying
Alex Chan532b79e2017-01-24 15:14:52 +00001086 connections created using that `Context`.
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001087 """
Alex Gaynor03737182020-07-23 20:40:46 -04001088 with open(cafile, "w") as fObj:
Paul Kehrerbeaf9f52020-08-03 17:50:31 -05001089 fObj.write(root_cert_pem.decode("ascii"))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001090
1091 self._load_verify_locations_test(cafile)
1092
Alex Chan532b79e2017-01-24 15:14:52 +00001093 def test_load_verify_bytes_cafile(self, tmpfile):
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001094 """
Alex Chan532b79e2017-01-24 15:14:52 +00001095 `Context.load_verify_locations` accepts a file name as a `bytes`
1096 instance and uses the certificates within for verification purposes.
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001097 """
Alex Chan532b79e2017-01-24 15:14:52 +00001098 cafile = tmpfile + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001099 self._load_verify_cafile(cafile)
1100
Alex Chan532b79e2017-01-24 15:14:52 +00001101 def test_load_verify_unicode_cafile(self, tmpfile):
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001102 """
Alex Chan532b79e2017-01-24 15:14:52 +00001103 `Context.load_verify_locations` accepts a file name as a `unicode`
1104 instance and uses the certificates within for verification purposes.
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001105 """
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001106 self._load_verify_cafile(
Alex Chan532b79e2017-01-24 15:14:52 +00001107 tmpfile.decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001108 )
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001109
Alex Chan532b79e2017-01-24 15:14:52 +00001110 def test_load_verify_invalid_file(self, tmpfile):
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -04001111 """
Alex Chan532b79e2017-01-24 15:14:52 +00001112 `Context.load_verify_locations` raises `Error` when passed a
1113 non-existent cafile.
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -04001114 """
Paul Kehrer688538c2020-08-03 19:18:15 -05001115 clientContext = Context(SSLv23_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001116 with pytest.raises(Error):
1117 clientContext.load_verify_locations(tmpfile)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001118
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001119 def _load_verify_directory_locations_capath(self, capath):
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001120 """
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001121 Verify that if path to a directory containing certificate files is
1122 passed to ``Context.load_verify_locations`` for the ``capath``
1123 parameter, those certificates are used as trust roots for the purposes
1124 of verifying connections created using that ``Context``.
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001125 """
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001126 makedirs(capath)
Jean-Paul Calderone24dfb332011-05-04 18:10:26 -04001127 # Hash values computed manually with c_rehash to avoid depending on
1128 # c_rehash in the test suite. One is from OpenSSL 0.9.8, the other
1129 # from OpenSSL 1.0.0.
Alex Gaynor03737182020-07-23 20:40:46 -04001130 for name in [b"c7adac82.0", b"c3705638.0"]:
Jean-Paul Calderone05826732015-04-12 11:38:49 -04001131 cafile = join_bytes_or_unicode(capath, name)
Alex Gaynor03737182020-07-23 20:40:46 -04001132 with open(cafile, "w") as fObj:
Paul Kehrerbeaf9f52020-08-03 17:50:31 -05001133 fObj.write(root_cert_pem.decode("ascii"))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001134
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001135 self._load_verify_locations_test(None, capath)
1136
Alex Chan532b79e2017-01-24 15:14:52 +00001137 def test_load_verify_directory_bytes_capath(self, tmpfile):
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001138 """
Alex Chan532b79e2017-01-24 15:14:52 +00001139 `Context.load_verify_locations` accepts a directory name as a `bytes`
1140 instance and uses the certificates within for verification purposes.
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001141 """
1142 self._load_verify_directory_locations_capath(
Alex Chan532b79e2017-01-24 15:14:52 +00001143 tmpfile + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001144 )
1145
Alex Chan532b79e2017-01-24 15:14:52 +00001146 def test_load_verify_directory_unicode_capath(self, tmpfile):
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001147 """
Alex Chan532b79e2017-01-24 15:14:52 +00001148 `Context.load_verify_locations` accepts a directory name as a `unicode`
1149 instance and uses the certificates within for verification purposes.
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001150 """
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001151 self._load_verify_directory_locations_capath(
Alex Chan532b79e2017-01-24 15:14:52 +00001152 tmpfile.decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001153 )
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001154
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001155 def test_load_verify_locations_wrong_args(self):
1156 """
Alex Chan532b79e2017-01-24 15:14:52 +00001157 `Context.load_verify_locations` raises `TypeError` if with non-`str`
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001158 arguments.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001159 """
Paul Kehrer688538c2020-08-03 19:18:15 -05001160 context = Context(SSLv23_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001161 with pytest.raises(TypeError):
1162 context.load_verify_locations(object())
1163 with pytest.raises(TypeError):
1164 context.load_verify_locations(object(), object())
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001165
Hynek Schlawack734d3022015-09-05 19:19:32 +02001166 @pytest.mark.skipif(
Paul Kehrer55fb3412017-06-29 18:44:08 -05001167 not platform.startswith("linux"),
1168 reason="Loading fallback paths is a linux-specific behavior to "
Alex Gaynor03737182020-07-23 20:40:46 -04001169 "accommodate pyca/cryptography manylinux1 wheels",
Paul Kehrer55fb3412017-06-29 18:44:08 -05001170 )
1171 def test_fallback_default_verify_paths(self, monkeypatch):
1172 """
1173 Test that we load certificates successfully on linux from the fallback
1174 path. To do this we set the _CRYPTOGRAPHY_MANYLINUX1_CA_FILE and
1175 _CRYPTOGRAPHY_MANYLINUX1_CA_DIR vars to be equal to whatever the
1176 current OpenSSL default is and we disable
1177 SSL_CTX_SET_default_verify_paths so that it can't find certs unless
1178 it loads via fallback.
1179 """
Paul Kehrer688538c2020-08-03 19:18:15 -05001180 context = Context(SSLv23_METHOD)
Paul Kehrer55fb3412017-06-29 18:44:08 -05001181 monkeypatch.setattr(
1182 _lib, "SSL_CTX_set_default_verify_paths", lambda x: 1
1183 )
1184 monkeypatch.setattr(
1185 SSL,
1186 "_CRYPTOGRAPHY_MANYLINUX1_CA_FILE",
Alex Gaynor03737182020-07-23 20:40:46 -04001187 _ffi.string(_lib.X509_get_default_cert_file()),
Paul Kehrer55fb3412017-06-29 18:44:08 -05001188 )
1189 monkeypatch.setattr(
1190 SSL,
1191 "_CRYPTOGRAPHY_MANYLINUX1_CA_DIR",
Alex Gaynor03737182020-07-23 20:40:46 -04001192 _ffi.string(_lib.X509_get_default_cert_dir()),
Paul Kehrer55fb3412017-06-29 18:44:08 -05001193 )
1194 context.set_default_verify_paths()
1195 store = context.get_cert_store()
1196 sk_obj = _lib.X509_STORE_get0_objects(store._store)
1197 assert sk_obj != _ffi.NULL
1198 num = _lib.sk_X509_OBJECT_num(sk_obj)
1199 assert num != 0
1200
1201 def test_check_env_vars(self, monkeypatch):
1202 """
1203 Test that we return True/False appropriately if the env vars are set.
1204 """
Paul Kehrer688538c2020-08-03 19:18:15 -05001205 context = Context(SSLv23_METHOD)
Paul Kehrer55fb3412017-06-29 18:44:08 -05001206 dir_var = "CUSTOM_DIR_VAR"
1207 file_var = "CUSTOM_FILE_VAR"
1208 assert context._check_env_vars_set(dir_var, file_var) is False
1209 monkeypatch.setenv(dir_var, "value")
1210 monkeypatch.setenv(file_var, "value")
1211 assert context._check_env_vars_set(dir_var, file_var) is True
1212 assert context._check_env_vars_set(dir_var, file_var) is True
1213
1214 def test_verify_no_fallback_if_env_vars_set(self, monkeypatch):
1215 """
1216 Test that we don't use the fallback path if env vars are set.
1217 """
Paul Kehrer688538c2020-08-03 19:18:15 -05001218 context = Context(SSLv23_METHOD)
Paul Kehrer55fb3412017-06-29 18:44:08 -05001219 monkeypatch.setattr(
1220 _lib, "SSL_CTX_set_default_verify_paths", lambda x: 1
1221 )
Alex Gaynor03737182020-07-23 20:40:46 -04001222 dir_env_var = _ffi.string(_lib.X509_get_default_cert_dir_env()).decode(
1223 "ascii"
1224 )
Paul Kehrer55fb3412017-06-29 18:44:08 -05001225 file_env_var = _ffi.string(
1226 _lib.X509_get_default_cert_file_env()
1227 ).decode("ascii")
1228 monkeypatch.setenv(dir_env_var, "value")
1229 monkeypatch.setenv(file_env_var, "value")
1230 context.set_default_verify_paths()
1231
1232 monkeypatch.setattr(
Alex Gaynor03737182020-07-23 20:40:46 -04001233 context, "_fallback_default_verify_paths", raiser(SystemError)
Paul Kehrer55fb3412017-06-29 18:44:08 -05001234 )
1235 context.set_default_verify_paths()
1236
1237 @pytest.mark.skipif(
Hynek Schlawack734d3022015-09-05 19:19:32 +02001238 platform == "win32",
1239 reason="set_default_verify_paths appears not to work on Windows. "
Alex Gaynor03737182020-07-23 20:40:46 -04001240 "See LP#404343 and LP#404344.",
Hynek Schlawack734d3022015-09-05 19:19:32 +02001241 )
1242 def test_set_default_verify_paths(self):
1243 """
Alex Chan532b79e2017-01-24 15:14:52 +00001244 `Context.set_default_verify_paths` causes the platform-specific CA
1245 certificate locations to be used for verification purposes.
Hynek Schlawack734d3022015-09-05 19:19:32 +02001246 """
1247 # Testing this requires a server with a certificate signed by one
1248 # of the CAs in the platform CA location. Getting one of those
1249 # costs money. Fortunately (or unfortunately, depending on your
1250 # perspective), it's easy to think of a public server on the
1251 # internet which has such a certificate. Connecting to the network
1252 # in a unit test is bad, but it's the only way I can think of to
1253 # really test this. -exarkun
Hynek Schlawackbf887932015-10-21 17:13:47 +02001254 context = Context(SSLv23_METHOD)
Hynek Schlawack734d3022015-09-05 19:19:32 +02001255 context.set_default_verify_paths()
1256 context.set_verify(
1257 VERIFY_PEER,
Alex Gaynor03737182020-07-23 20:40:46 -04001258 lambda conn, cert, errno, depth, preverify_ok: preverify_ok,
1259 )
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001260
David Benjamin1fbe0642019-04-15 17:05:13 -05001261 client = socket_any_family()
Hynek Schlawackbf887932015-10-21 17:13:47 +02001262 client.connect(("encrypted.google.com", 443))
Hynek Schlawack734d3022015-09-05 19:19:32 +02001263 clientSSL = Connection(context, client)
1264 clientSSL.set_connect_state()
Alex Gaynor373926c2018-05-12 07:43:07 -04001265 clientSSL.set_tlsext_host_name(b"encrypted.google.com")
Hynek Schlawack734d3022015-09-05 19:19:32 +02001266 clientSSL.do_handshake()
1267 clientSSL.send(b"GET / HTTP/1.0\r\n\r\n")
Alex Chan532b79e2017-01-24 15:14:52 +00001268 assert clientSSL.recv(1024)
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05001269
Paul Kehrer55fb3412017-06-29 18:44:08 -05001270 def test_fallback_path_is_not_file_or_dir(self):
1271 """
1272 Test that when passed empty arrays or paths that do not exist no
1273 errors are raised.
1274 """
Paul Kehrer688538c2020-08-03 19:18:15 -05001275 context = Context(SSLv23_METHOD)
Paul Kehrer55fb3412017-06-29 18:44:08 -05001276 context._fallback_default_verify_paths([], [])
Alex Gaynor03737182020-07-23 20:40:46 -04001277 context._fallback_default_verify_paths(["/not/a/file"], ["/not/a/dir"])
Paul Kehrer55fb3412017-06-29 18:44:08 -05001278
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001279 def test_add_extra_chain_cert_invalid_cert(self):
1280 """
Alex Chan532b79e2017-01-24 15:14:52 +00001281 `Context.add_extra_chain_cert` raises `TypeError` if called with an
1282 object which is not an instance of `X509`.
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001283 """
Paul Kehrer688538c2020-08-03 19:18:15 -05001284 context = Context(SSLv23_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001285 with pytest.raises(TypeError):
1286 context.add_extra_chain_cert(object())
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001287
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001288 def _handshake_test(self, serverContext, clientContext):
1289 """
1290 Verify that a client and server created with the given contexts can
1291 successfully handshake and communicate.
1292 """
1293 serverSocket, clientSocket = socket_pair()
1294
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001295 server = Connection(serverContext, serverSocket)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001296 server.set_accept_state()
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001297
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001298 client = Connection(clientContext, clientSocket)
1299 client.set_connect_state()
1300
1301 # Make them talk to each other.
Alex Chan532b79e2017-01-24 15:14:52 +00001302 # interact_in_memory(client, server)
1303 for _ in range(3):
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001304 for s in [client, server]:
1305 try:
1306 s.do_handshake()
1307 except WantReadError:
1308 pass
1309
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001310 def test_set_verify_callback_connection_argument(self):
1311 """
1312 The first argument passed to the verify callback is the
Alex Chan532b79e2017-01-24 15:14:52 +00001313 `Connection` instance for which verification is taking place.
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001314 """
Paul Kehrer688538c2020-08-03 19:18:15 -05001315 serverContext = Context(SSLv23_METHOD)
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001316 serverContext.use_privatekey(
Paul Kehrerbeaf9f52020-08-03 17:50:31 -05001317 load_privatekey(FILETYPE_PEM, root_key_pem)
Alex Gaynor03737182020-07-23 20:40:46 -04001318 )
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001319 serverContext.use_certificate(
Paul Kehrerbeaf9f52020-08-03 17:50:31 -05001320 load_certificate(FILETYPE_PEM, root_cert_pem)
Alex Gaynor03737182020-07-23 20:40:46 -04001321 )
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001322 serverConnection = Connection(serverContext, None)
1323
1324 class VerifyCallback(object):
1325 def callback(self, connection, *args):
1326 self.connection = connection
1327 return 1
1328
1329 verify = VerifyCallback()
Paul Kehrer688538c2020-08-03 19:18:15 -05001330 clientContext = Context(SSLv23_METHOD)
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001331 clientContext.set_verify(VERIFY_PEER, verify.callback)
1332 clientConnection = Connection(clientContext, None)
1333 clientConnection.set_connect_state()
1334
Alex Chan532b79e2017-01-24 15:14:52 +00001335 handshake_in_memory(clientConnection, serverConnection)
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001336
Alex Chan532b79e2017-01-24 15:14:52 +00001337 assert verify.connection is clientConnection
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001338
Paul Kehrere7381862017-11-30 20:55:25 +08001339 def test_x509_in_verify_works(self):
1340 """
1341 We had a bug where the X509 cert instantiated in the callback wrapper
1342 didn't __init__ so it was missing objects needed when calling
1343 get_subject. This test sets up a handshake where we call get_subject
1344 on the cert provided to the verify callback.
1345 """
Paul Kehrer688538c2020-08-03 19:18:15 -05001346 serverContext = Context(SSLv23_METHOD)
Paul Kehrere7381862017-11-30 20:55:25 +08001347 serverContext.use_privatekey(
Paul Kehrerbeaf9f52020-08-03 17:50:31 -05001348 load_privatekey(FILETYPE_PEM, root_key_pem)
Alex Gaynor03737182020-07-23 20:40:46 -04001349 )
Paul Kehrere7381862017-11-30 20:55:25 +08001350 serverContext.use_certificate(
Paul Kehrerbeaf9f52020-08-03 17:50:31 -05001351 load_certificate(FILETYPE_PEM, root_cert_pem)
Alex Gaynor03737182020-07-23 20:40:46 -04001352 )
Paul Kehrere7381862017-11-30 20:55:25 +08001353 serverConnection = Connection(serverContext, None)
1354
1355 def verify_cb_get_subject(conn, cert, errnum, depth, ok):
1356 assert cert.get_subject()
1357 return 1
1358
Paul Kehrer688538c2020-08-03 19:18:15 -05001359 clientContext = Context(SSLv23_METHOD)
Paul Kehrere7381862017-11-30 20:55:25 +08001360 clientContext.set_verify(VERIFY_PEER, verify_cb_get_subject)
1361 clientConnection = Connection(clientContext, None)
1362 clientConnection.set_connect_state()
1363
1364 handshake_in_memory(clientConnection, serverConnection)
1365
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001366 def test_set_verify_callback_exception(self):
1367 """
Alex Chan532b79e2017-01-24 15:14:52 +00001368 If the verify callback passed to `Context.set_verify` raises an
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001369 exception, verification fails and the exception is propagated to the
Alex Chan532b79e2017-01-24 15:14:52 +00001370 caller of `Connection.do_handshake`.
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001371 """
Paul Kehrer7d5a3bf2019-01-21 12:24:02 -06001372 serverContext = Context(TLSv1_2_METHOD)
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001373 serverContext.use_privatekey(
Paul Kehrerbeaf9f52020-08-03 17:50:31 -05001374 load_privatekey(FILETYPE_PEM, root_key_pem)
Alex Gaynor03737182020-07-23 20:40:46 -04001375 )
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001376 serverContext.use_certificate(
Paul Kehrerbeaf9f52020-08-03 17:50:31 -05001377 load_certificate(FILETYPE_PEM, root_cert_pem)
Alex Gaynor03737182020-07-23 20:40:46 -04001378 )
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001379
Paul Kehrer7d5a3bf2019-01-21 12:24:02 -06001380 clientContext = Context(TLSv1_2_METHOD)
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001381
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001382 def verify_callback(*args):
1383 raise Exception("silly verify failure")
Alex Gaynor03737182020-07-23 20:40:46 -04001384
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001385 clientContext.set_verify(VERIFY_PEER, verify_callback)
1386
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01001387 with pytest.raises(Exception) as exc:
1388 self._handshake_test(serverContext, clientContext)
1389
Alex Chan532b79e2017-01-24 15:14:52 +00001390 assert "silly verify failure" == str(exc.value)
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001391
Maximilian Hils79b9c792020-08-08 03:08:17 +02001392 @pytest.mark.parametrize("mode", [SSL.VERIFY_PEER, SSL.VERIFY_NONE])
1393 def test_set_verify_default_callback(self, mode):
1394 """
1395 If the verify callback is omitted, the preverify value is used.
1396 """
1397 serverContext = Context(TLSv1_2_METHOD)
1398 serverContext.use_privatekey(
1399 load_privatekey(FILETYPE_PEM, root_key_pem)
1400 )
1401 serverContext.use_certificate(
1402 load_certificate(FILETYPE_PEM, root_cert_pem)
1403 )
1404
1405 clientContext = Context(TLSv1_2_METHOD)
1406 clientContext.set_verify(mode, None)
1407
1408 if mode == SSL.VERIFY_PEER:
1409 with pytest.raises(Exception) as exc:
1410 self._handshake_test(serverContext, clientContext)
1411 assert "certificate verify failed" in str(exc.value)
1412 else:
1413 self._handshake_test(serverContext, clientContext)
1414
Alex Chan532b79e2017-01-24 15:14:52 +00001415 def test_add_extra_chain_cert(self, tmpdir):
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001416 """
Alex Chan532b79e2017-01-24 15:14:52 +00001417 `Context.add_extra_chain_cert` accepts an `X509`
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001418 instance to add to the certificate chain.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001419
Alex Chan532b79e2017-01-24 15:14:52 +00001420 See `_create_certificate_chain` for the details of the
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001421 certificate chain tested.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001422
1423 The chain is tested by starting a server with scert and connecting
1424 to it with a client which trusts cacert and requires verification to
1425 succeed.
1426 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001427 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001428 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1429
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001430 # Dump the CA certificate to a file because that's the only way to load
1431 # it as a trusted CA in the client context.
Alex Gaynor03737182020-07-23 20:40:46 -04001432 for cert, name in [
1433 (cacert, "ca.pem"),
1434 (icert, "i.pem"),
1435 (scert, "s.pem"),
1436 ]:
1437 with tmpdir.join(name).open("w") as f:
1438 f.write(dump_certificate(FILETYPE_PEM, cert).decode("ascii"))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001439
Alex Gaynor03737182020-07-23 20:40:46 -04001440 for key, name in [(cakey, "ca.key"), (ikey, "i.key"), (skey, "s.key")]:
1441 with tmpdir.join(name).open("w") as f:
1442 f.write(dump_privatekey(FILETYPE_PEM, key).decode("ascii"))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001443
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001444 # Create the server context
Paul Kehrer688538c2020-08-03 19:18:15 -05001445 serverContext = Context(SSLv23_METHOD)
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001446 serverContext.use_privatekey(skey)
1447 serverContext.use_certificate(scert)
Jean-Paul Calderone16cf03d2010-09-08 18:53:39 -04001448 # The client already has cacert, we only need to give them icert.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001449 serverContext.add_extra_chain_cert(icert)
1450
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001451 # Create the client
Paul Kehrer688538c2020-08-03 19:18:15 -05001452 clientContext = Context(SSLv23_METHOD)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001453 clientContext.set_verify(
Alex Gaynor03737182020-07-23 20:40:46 -04001454 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb
1455 )
Alex Chan532b79e2017-01-24 15:14:52 +00001456 clientContext.load_verify_locations(str(tmpdir.join("ca.pem")))
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001457
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001458 # Try it out.
1459 self._handshake_test(serverContext, clientContext)
1460
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001461 def _use_certificate_chain_file_test(self, certdir):
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001462 """
Alex Chan532b79e2017-01-24 15:14:52 +00001463 Verify that `Context.use_certificate_chain_file` reads a
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001464 certificate chain from a specified file.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001465
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001466 The chain is tested by starting a server with scert and connecting to
1467 it with a client which trusts cacert and requires verification to
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001468 succeed.
1469 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001470 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001471 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1472
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001473 makedirs(certdir)
1474
Jean-Paul Calderone05826732015-04-12 11:38:49 -04001475 chainFile = join_bytes_or_unicode(certdir, "chain.pem")
1476 caFile = join_bytes_or_unicode(certdir, "ca.pem")
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001477
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001478 # Write out the chain file.
Alex Gaynor03737182020-07-23 20:40:46 -04001479 with open(chainFile, "wb") as fObj:
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001480 # Most specific to least general.
1481 fObj.write(dump_certificate(FILETYPE_PEM, scert))
1482 fObj.write(dump_certificate(FILETYPE_PEM, icert))
1483 fObj.write(dump_certificate(FILETYPE_PEM, cacert))
1484
Alex Gaynor03737182020-07-23 20:40:46 -04001485 with open(caFile, "w") as fObj:
1486 fObj.write(dump_certificate(FILETYPE_PEM, cacert).decode("ascii"))
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001487
Paul Kehrer688538c2020-08-03 19:18:15 -05001488 serverContext = Context(SSLv23_METHOD)
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001489 serverContext.use_certificate_chain_file(chainFile)
1490 serverContext.use_privatekey(skey)
1491
Paul Kehrer688538c2020-08-03 19:18:15 -05001492 clientContext = Context(SSLv23_METHOD)
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001493 clientContext.set_verify(
Alex Gaynor03737182020-07-23 20:40:46 -04001494 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb
1495 )
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001496 clientContext.load_verify_locations(caFile)
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001497
1498 self._handshake_test(serverContext, clientContext)
1499
Alex Chan532b79e2017-01-24 15:14:52 +00001500 def test_use_certificate_chain_file_bytes(self, tmpfile):
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001501 """
1502 ``Context.use_certificate_chain_file`` accepts the name of a file (as
1503 an instance of ``bytes``) to specify additional certificates to use to
1504 construct and verify a trust chain.
1505 """
1506 self._use_certificate_chain_file_test(
Alex Chan532b79e2017-01-24 15:14:52 +00001507 tmpfile + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001508 )
1509
Alex Chan532b79e2017-01-24 15:14:52 +00001510 def test_use_certificate_chain_file_unicode(self, tmpfile):
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001511 """
1512 ``Context.use_certificate_chain_file`` accepts the name of a file (as
1513 an instance of ``unicode``) to specify additional certificates to use
1514 to construct and verify a trust chain.
1515 """
1516 self._use_certificate_chain_file_test(
Alex Chan532b79e2017-01-24 15:14:52 +00001517 tmpfile.decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001518 )
1519
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001520 def test_use_certificate_chain_file_wrong_args(self):
1521 """
Alex Chan532b79e2017-01-24 15:14:52 +00001522 `Context.use_certificate_chain_file` raises `TypeError` if passed a
1523 non-byte string single argument.
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001524 """
Paul Kehrer688538c2020-08-03 19:18:15 -05001525 context = Context(SSLv23_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001526 with pytest.raises(TypeError):
1527 context.use_certificate_chain_file(object())
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001528
Alex Chan532b79e2017-01-24 15:14:52 +00001529 def test_use_certificate_chain_file_missing_file(self, tmpfile):
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001530 """
Alex Chan532b79e2017-01-24 15:14:52 +00001531 `Context.use_certificate_chain_file` raises `OpenSSL.SSL.Error` when
1532 passed a bad chain file name (for example, the name of a file which
1533 does not exist).
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001534 """
Paul Kehrer688538c2020-08-03 19:18:15 -05001535 context = Context(SSLv23_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001536 with pytest.raises(Error):
1537 context.use_certificate_chain_file(tmpfile)
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001538
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001539 def test_set_verify_mode(self):
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001540 """
Alex Chan532b79e2017-01-24 15:14:52 +00001541 `Context.get_verify_mode` returns the verify mode flags previously
1542 passed to `Context.set_verify`.
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001543 """
Paul Kehrer688538c2020-08-03 19:18:15 -05001544 context = Context(SSLv23_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001545 assert context.get_verify_mode() == 0
Maximilian Hils79b9c792020-08-08 03:08:17 +02001546 context.set_verify(VERIFY_PEER | VERIFY_CLIENT_ONCE)
Alex Chan532b79e2017-01-24 15:14:52 +00001547 assert context.get_verify_mode() == (VERIFY_PEER | VERIFY_CLIENT_ONCE)
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001548
Alex Gaynor03737182020-07-23 20:40:46 -04001549 @pytest.mark.parametrize("mode", [None, 1.0, object(), "mode"])
Alex Chanfb078d82017-04-20 11:16:15 +01001550 def test_set_verify_wrong_mode_arg(self, mode):
1551 """
1552 `Context.set_verify` raises `TypeError` if the first argument is
1553 not an integer.
1554 """
Paul Kehrer688538c2020-08-03 19:18:15 -05001555 context = Context(SSLv23_METHOD)
Alex Chanfb078d82017-04-20 11:16:15 +01001556 with pytest.raises(TypeError):
Maximilian Hils79b9c792020-08-08 03:08:17 +02001557 context.set_verify(mode=mode)
Alex Chanfb078d82017-04-20 11:16:15 +01001558
Maximilian Hils79b9c792020-08-08 03:08:17 +02001559 @pytest.mark.parametrize("callback", [1.0, "mode", ("foo", "bar")])
Alex Chanfb078d82017-04-20 11:16:15 +01001560 def test_set_verify_wrong_callable_arg(self, callback):
1561 """
Alex Gaynor40bc0f12018-05-14 14:06:16 -04001562 `Context.set_verify` raises `TypeError` if the second argument
Alex Chanfb078d82017-04-20 11:16:15 +01001563 is not callable.
1564 """
Paul Kehrer688538c2020-08-03 19:18:15 -05001565 context = Context(SSLv23_METHOD)
Alex Chanfb078d82017-04-20 11:16:15 +01001566 with pytest.raises(TypeError):
1567 context.set_verify(mode=VERIFY_PEER, callback=callback)
1568
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001569 def test_load_tmp_dh_wrong_args(self):
1570 """
Alex Chan532b79e2017-01-24 15:14:52 +00001571 `Context.load_tmp_dh` raises `TypeError` if called with a
1572 non-`str` argument.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001573 """
Paul Kehrer688538c2020-08-03 19:18:15 -05001574 context = Context(SSLv23_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001575 with pytest.raises(TypeError):
1576 context.load_tmp_dh(object())
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001577
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001578 def test_load_tmp_dh_missing_file(self):
1579 """
Alex Chan532b79e2017-01-24 15:14:52 +00001580 `Context.load_tmp_dh` raises `OpenSSL.SSL.Error` if the
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001581 specified file does not exist.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001582 """
Paul Kehrer688538c2020-08-03 19:18:15 -05001583 context = Context(SSLv23_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001584 with pytest.raises(Error):
1585 context.load_tmp_dh(b"hello")
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001586
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001587 def _load_tmp_dh_test(self, dhfilename):
Jean-Paul Calderone4e0c43f2015-04-13 10:15:17 -04001588 """
1589 Verify that calling ``Context.load_tmp_dh`` with the given filename
1590 does not raise an exception.
1591 """
Paul Kehrer688538c2020-08-03 19:18:15 -05001592 context = Context(SSLv23_METHOD)
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001593 with open(dhfilename, "w") as dhfile:
1594 dhfile.write(dhparam)
1595
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001596 context.load_tmp_dh(dhfilename)
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001597
Alex Chan532b79e2017-01-24 15:14:52 +00001598 def test_load_tmp_dh_bytes(self, tmpfile):
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001599 """
Alex Chan532b79e2017-01-24 15:14:52 +00001600 `Context.load_tmp_dh` loads Diffie-Hellman parameters from the
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001601 specified file (given as ``bytes``).
1602 """
1603 self._load_tmp_dh_test(
Alex Chan532b79e2017-01-24 15:14:52 +00001604 tmpfile + NON_ASCII.encode(getfilesystemencoding()),
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001605 )
1606
Alex Chan532b79e2017-01-24 15:14:52 +00001607 def test_load_tmp_dh_unicode(self, tmpfile):
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001608 """
Alex Chan532b79e2017-01-24 15:14:52 +00001609 `Context.load_tmp_dh` loads Diffie-Hellman parameters from the
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001610 specified file (given as ``unicode``).
1611 """
1612 self._load_tmp_dh_test(
Alex Chan532b79e2017-01-24 15:14:52 +00001613 tmpfile.decode(getfilesystemencoding()) + NON_ASCII,
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001614 )
1615
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001616 def test_set_tmp_ecdh(self):
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001617 """
Alex Chan532b79e2017-01-24 15:14:52 +00001618 `Context.set_tmp_ecdh` sets the elliptic curve for Diffie-Hellman to
1619 the specified curve.
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001620 """
Paul Kehrer688538c2020-08-03 19:18:15 -05001621 context = Context(SSLv23_METHOD)
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001622 for curve in get_elliptic_curves():
Hynek Schlawacka07fa8c2015-10-17 10:15:28 +02001623 if curve.name.startswith(u"Oakley-"):
Hynek Schlawack7408aff2015-10-17 09:51:16 +02001624 # Setting Oakley-EC2N-4 and Oakley-EC2N-3 adds
1625 # ('bignum routines', 'BN_mod_inverse', 'no inverse') to the
1626 # error queue on OpenSSL 1.0.2.
1627 continue
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001628 # The only easily "assertable" thing is that it does not raise an
1629 # exception.
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001630 context.set_tmp_ecdh(curve)
Alex Gaynor12dc0842014-01-17 12:51:31 -06001631
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001632 def test_set_session_cache_mode_wrong_args(self):
1633 """
Alex Chan532b79e2017-01-24 15:14:52 +00001634 `Context.set_session_cache_mode` raises `TypeError` if called with
1635 a non-integer argument.
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001636 called with other than one integer argument.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001637 """
Paul Kehrer688538c2020-08-03 19:18:15 -05001638 context = Context(SSLv23_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001639 with pytest.raises(TypeError):
1640 context.set_session_cache_mode(object())
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001641
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001642 def test_session_cache_mode(self):
1643 """
Alex Chan532b79e2017-01-24 15:14:52 +00001644 `Context.set_session_cache_mode` specifies how sessions are cached.
1645 The setting can be retrieved via `Context.get_session_cache_mode`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001646 """
Paul Kehrer688538c2020-08-03 19:18:15 -05001647 context = Context(SSLv23_METHOD)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001648 context.set_session_cache_mode(SESS_CACHE_OFF)
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001649 off = context.set_session_cache_mode(SESS_CACHE_BOTH)
Alex Chan532b79e2017-01-24 15:14:52 +00001650 assert SESS_CACHE_OFF == off
1651 assert SESS_CACHE_BOTH == context.get_session_cache_mode()
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001652
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001653 def test_get_cert_store(self):
1654 """
Alex Chan532b79e2017-01-24 15:14:52 +00001655 `Context.get_cert_store` returns a `X509Store` instance.
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001656 """
Paul Kehrer688538c2020-08-03 19:18:15 -05001657 context = Context(SSLv23_METHOD)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001658 store = context.get_cert_store()
Alex Chan532b79e2017-01-24 15:14:52 +00001659 assert isinstance(store, X509Store)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001660
Jeremy Lainé02261ad2018-05-16 18:33:25 +02001661 def test_set_tlsext_use_srtp_not_bytes(self):
1662 """
1663 `Context.set_tlsext_use_srtp' enables negotiating SRTP keying material.
1664
1665 It raises a TypeError if the list of profiles is not a byte string.
1666 """
Paul Kehrer688538c2020-08-03 19:18:15 -05001667 context = Context(SSLv23_METHOD)
Jeremy Lainé02261ad2018-05-16 18:33:25 +02001668 with pytest.raises(TypeError):
Alex Gaynor03737182020-07-23 20:40:46 -04001669 context.set_tlsext_use_srtp(text_type("SRTP_AES128_CM_SHA1_80"))
Jeremy Lainé02261ad2018-05-16 18:33:25 +02001670
1671 def test_set_tlsext_use_srtp_invalid_profile(self):
1672 """
1673 `Context.set_tlsext_use_srtp' enables negotiating SRTP keying material.
1674
1675 It raises an Error if the call to OpenSSL fails.
1676 """
Paul Kehrer688538c2020-08-03 19:18:15 -05001677 context = Context(SSLv23_METHOD)
Jeremy Lainé02261ad2018-05-16 18:33:25 +02001678 with pytest.raises(Error):
Alex Gaynor03737182020-07-23 20:40:46 -04001679 context.set_tlsext_use_srtp(b"SRTP_BOGUS")
Jeremy Lainé02261ad2018-05-16 18:33:25 +02001680
1681 def test_set_tlsext_use_srtp_valid(self):
1682 """
1683 `Context.set_tlsext_use_srtp' enables negotiating SRTP keying material.
1684
1685 It does not return anything.
1686 """
Paul Kehrer688538c2020-08-03 19:18:15 -05001687 context = Context(SSLv23_METHOD)
Alex Gaynor03737182020-07-23 20:40:46 -04001688 assert context.set_tlsext_use_srtp(b"SRTP_AES128_CM_SHA1_80") is None
Jeremy Lainé02261ad2018-05-16 18:33:25 +02001689
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001690
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001691class TestServerNameCallback(object):
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001692 """
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001693 Tests for `Context.set_tlsext_servername_callback` and its
1694 interaction with `Connection`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001695 """
Alex Gaynor03737182020-07-23 20:40:46 -04001696
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001697 def test_old_callback_forgotten(self):
1698 """
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001699 If `Context.set_tlsext_servername_callback` is used to specify
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001700 a new callback, the one it replaces is dereferenced.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001701 """
Alex Gaynor03737182020-07-23 20:40:46 -04001702
Alex Chanfb078d82017-04-20 11:16:15 +01001703 def callback(connection): # pragma: no cover
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001704 pass
1705
Alex Chanfb078d82017-04-20 11:16:15 +01001706 def replacement(connection): # pragma: no cover
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001707 pass
1708
Paul Kehrer688538c2020-08-03 19:18:15 -05001709 context = Context(SSLv23_METHOD)
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001710 context.set_tlsext_servername_callback(callback)
1711
1712 tracker = ref(callback)
1713 del callback
1714
1715 context.set_tlsext_servername_callback(replacement)
Jean-Paul Calderoned4033eb2014-01-11 08:21:46 -05001716
1717 # One run of the garbage collector happens to work on CPython. PyPy
1718 # doesn't collect the underlying object until a second run for whatever
1719 # reason. That's fine, it still demonstrates our code has properly
1720 # dropped the reference.
1721 collect()
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001722 collect()
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001723
1724 callback = tracker()
1725 if callback is not None:
1726 referrers = get_referrers(callback)
Alex Chanfb078d82017-04-20 11:16:15 +01001727 if len(referrers) > 1: # pragma: nocover
1728 pytest.fail("Some references remain: %r" % (referrers,))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001729
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001730 def test_no_servername(self):
1731 """
1732 When a client specifies no server name, the callback passed to
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001733 `Context.set_tlsext_servername_callback` is invoked and the
1734 result of `Connection.get_servername` is `None`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001735 """
1736 args = []
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001737
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001738 def servername(conn):
1739 args.append((conn, conn.get_servername()))
Alex Gaynor03737182020-07-23 20:40:46 -04001740
Paul Kehrer688538c2020-08-03 19:18:15 -05001741 context = Context(SSLv23_METHOD)
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001742 context.set_tlsext_servername_callback(servername)
1743
1744 # Lose our reference to it. The Context is responsible for keeping it
1745 # alive now.
1746 del servername
1747 collect()
1748
1749 # Necessary to actually accept the connection
1750 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001751 context.use_certificate(
Alex Gaynor03737182020-07-23 20:40:46 -04001752 load_certificate(FILETYPE_PEM, server_cert_pem)
1753 )
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001754
1755 # Do a little connection to trigger the logic
1756 server = Connection(context, None)
1757 server.set_accept_state()
1758
Paul Kehrer688538c2020-08-03 19:18:15 -05001759 client = Connection(Context(SSLv23_METHOD), None)
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001760 client.set_connect_state()
1761
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001762 interact_in_memory(server, client)
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001763
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001764 assert args == [(server, None)]
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001765
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001766 def test_servername(self):
1767 """
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001768 When a client specifies a server name in its hello message, the
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001769 callback passed to `Contexts.set_tlsext_servername_callback` is
1770 invoked and the result of `Connection.get_servername` is that
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001771 server name.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001772 """
1773 args = []
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001774
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001775 def servername(conn):
1776 args.append((conn, conn.get_servername()))
Alex Gaynor03737182020-07-23 20:40:46 -04001777
Paul Kehrer688538c2020-08-03 19:18:15 -05001778 context = Context(SSLv23_METHOD)
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001779 context.set_tlsext_servername_callback(servername)
1780
1781 # Necessary to actually accept the connection
1782 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001783 context.use_certificate(
Alex Gaynor03737182020-07-23 20:40:46 -04001784 load_certificate(FILETYPE_PEM, server_cert_pem)
1785 )
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001786
1787 # Do a little connection to trigger the logic
1788 server = Connection(context, None)
1789 server.set_accept_state()
1790
Paul Kehrer688538c2020-08-03 19:18:15 -05001791 client = Connection(Context(SSLv23_METHOD), None)
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001792 client.set_connect_state()
Alex Gaynore7f51982016-09-11 11:48:14 -04001793 client.set_tlsext_host_name(b"foo1.example.com")
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001794
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001795 interact_in_memory(server, client)
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001796
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001797 assert args == [(server, b"foo1.example.com")]
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001798
1799
Alex Chanec1e32d2016-11-10 14:11:45 +00001800class TestApplicationLayerProtoNegotiation(object):
Cory Benfield12eae892014-06-07 15:42:56 +01001801 """
1802 Tests for ALPN in PyOpenSSL.
1803 """
Alex Gaynor03737182020-07-23 20:40:46 -04001804
Alex Gaynor77debda2020-04-07 13:40:59 -04001805 def test_alpn_success(self):
1806 """
1807 Clients and servers that agree on the negotiated ALPN protocol can
1808 correct establish a connection, and the agreed protocol is reported
1809 by the connections.
1810 """
1811 select_args = []
Cory Benfield12eae892014-06-07 15:42:56 +01001812
Alex Gaynor77debda2020-04-07 13:40:59 -04001813 def select(conn, options):
1814 select_args.append((conn, options))
Alex Gaynor03737182020-07-23 20:40:46 -04001815 return b"spdy/2"
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001816
Paul Kehrer688538c2020-08-03 19:18:15 -05001817 client_context = Context(SSLv23_METHOD)
Alex Gaynor03737182020-07-23 20:40:46 -04001818 client_context.set_alpn_protos([b"http/1.1", b"spdy/2"])
Cory Benfield12eae892014-06-07 15:42:56 +01001819
Paul Kehrer688538c2020-08-03 19:18:15 -05001820 server_context = Context(SSLv23_METHOD)
Alex Gaynor77debda2020-04-07 13:40:59 -04001821 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01001822
Alex Gaynor77debda2020-04-07 13:40:59 -04001823 # Necessary to actually accept the connection
1824 server_context.use_privatekey(
Alex Gaynor03737182020-07-23 20:40:46 -04001825 load_privatekey(FILETYPE_PEM, server_key_pem)
1826 )
Alex Gaynor77debda2020-04-07 13:40:59 -04001827 server_context.use_certificate(
Alex Gaynor03737182020-07-23 20:40:46 -04001828 load_certificate(FILETYPE_PEM, server_cert_pem)
1829 )
Cory Benfield12eae892014-06-07 15:42:56 +01001830
Alex Gaynor77debda2020-04-07 13:40:59 -04001831 # Do a little connection to trigger the logic
1832 server = Connection(server_context, None)
1833 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001834
Alex Gaynor77debda2020-04-07 13:40:59 -04001835 client = Connection(client_context, None)
1836 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001837
Alex Gaynor77debda2020-04-07 13:40:59 -04001838 interact_in_memory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001839
Alex Gaynor03737182020-07-23 20:40:46 -04001840 assert select_args == [(server, [b"http/1.1", b"spdy/2"])]
Alex Gaynor77debda2020-04-07 13:40:59 -04001841
Alex Gaynor03737182020-07-23 20:40:46 -04001842 assert server.get_alpn_proto_negotiated() == b"spdy/2"
1843 assert client.get_alpn_proto_negotiated() == b"spdy/2"
Alex Gaynor77debda2020-04-07 13:40:59 -04001844
1845 def test_alpn_set_on_connection(self):
1846 """
1847 The same as test_alpn_success, but setting the ALPN protocols on
1848 the connection rather than the context.
1849 """
1850 select_args = []
1851
1852 def select(conn, options):
1853 select_args.append((conn, options))
Alex Gaynor03737182020-07-23 20:40:46 -04001854 return b"spdy/2"
Alex Gaynor77debda2020-04-07 13:40:59 -04001855
1856 # Setup the client context but don't set any ALPN protocols.
Paul Kehrer688538c2020-08-03 19:18:15 -05001857 client_context = Context(SSLv23_METHOD)
Alex Gaynor77debda2020-04-07 13:40:59 -04001858
Paul Kehrer688538c2020-08-03 19:18:15 -05001859 server_context = Context(SSLv23_METHOD)
Alex Gaynor77debda2020-04-07 13:40:59 -04001860 server_context.set_alpn_select_callback(select)
1861
1862 # Necessary to actually accept the connection
1863 server_context.use_privatekey(
Alex Gaynor03737182020-07-23 20:40:46 -04001864 load_privatekey(FILETYPE_PEM, server_key_pem)
1865 )
Alex Gaynor77debda2020-04-07 13:40:59 -04001866 server_context.use_certificate(
Alex Gaynor03737182020-07-23 20:40:46 -04001867 load_certificate(FILETYPE_PEM, server_cert_pem)
1868 )
Alex Gaynor77debda2020-04-07 13:40:59 -04001869
1870 # Do a little connection to trigger the logic
1871 server = Connection(server_context, None)
1872 server.set_accept_state()
1873
1874 # Set the ALPN protocols on the client connection.
1875 client = Connection(client_context, None)
Alex Gaynor03737182020-07-23 20:40:46 -04001876 client.set_alpn_protos([b"http/1.1", b"spdy/2"])
Alex Gaynor77debda2020-04-07 13:40:59 -04001877 client.set_connect_state()
1878
1879 interact_in_memory(server, client)
1880
Alex Gaynor03737182020-07-23 20:40:46 -04001881 assert select_args == [(server, [b"http/1.1", b"spdy/2"])]
Alex Gaynor77debda2020-04-07 13:40:59 -04001882
Alex Gaynor03737182020-07-23 20:40:46 -04001883 assert server.get_alpn_proto_negotiated() == b"spdy/2"
1884 assert client.get_alpn_proto_negotiated() == b"spdy/2"
Alex Gaynor77debda2020-04-07 13:40:59 -04001885
1886 def test_alpn_server_fail(self):
1887 """
1888 When clients and servers cannot agree on what protocol to use next
1889 the TLS connection does not get established.
1890 """
1891 select_args = []
1892
1893 def select(conn, options):
1894 select_args.append((conn, options))
Alex Gaynor03737182020-07-23 20:40:46 -04001895 return b""
Alex Gaynor77debda2020-04-07 13:40:59 -04001896
Paul Kehrer688538c2020-08-03 19:18:15 -05001897 client_context = Context(SSLv23_METHOD)
Alex Gaynor03737182020-07-23 20:40:46 -04001898 client_context.set_alpn_protos([b"http/1.1", b"spdy/2"])
Alex Gaynor77debda2020-04-07 13:40:59 -04001899
Paul Kehrer688538c2020-08-03 19:18:15 -05001900 server_context = Context(SSLv23_METHOD)
Alex Gaynor77debda2020-04-07 13:40:59 -04001901 server_context.set_alpn_select_callback(select)
1902
1903 # Necessary to actually accept the connection
1904 server_context.use_privatekey(
Alex Gaynor03737182020-07-23 20:40:46 -04001905 load_privatekey(FILETYPE_PEM, server_key_pem)
1906 )
Alex Gaynor77debda2020-04-07 13:40:59 -04001907 server_context.use_certificate(
Alex Gaynor03737182020-07-23 20:40:46 -04001908 load_certificate(FILETYPE_PEM, server_cert_pem)
1909 )
Alex Gaynor77debda2020-04-07 13:40:59 -04001910
1911 # Do a little connection to trigger the logic
1912 server = Connection(server_context, None)
1913 server.set_accept_state()
1914
1915 client = Connection(client_context, None)
1916 client.set_connect_state()
1917
1918 # If the client doesn't return anything, the connection will fail.
1919 with pytest.raises(Error):
Alex Chanec1e32d2016-11-10 14:11:45 +00001920 interact_in_memory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001921
Alex Gaynor03737182020-07-23 20:40:46 -04001922 assert select_args == [(server, [b"http/1.1", b"spdy/2"])]
Cory Benfielde46fa842015-04-13 16:50:49 -04001923
Alex Gaynor77debda2020-04-07 13:40:59 -04001924 def test_alpn_no_server_overlap(self):
1925 """
1926 A server can allow a TLS handshake to complete without
1927 agreeing to an application protocol by returning
1928 ``NO_OVERLAPPING_PROTOCOLS``.
1929 """
1930 refusal_args = []
Cory Benfield12eae892014-06-07 15:42:56 +01001931
Alex Gaynor77debda2020-04-07 13:40:59 -04001932 def refusal(conn, options):
1933 refusal_args.append((conn, options))
1934 return NO_OVERLAPPING_PROTOCOLS
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001935
Alex Gaynor77debda2020-04-07 13:40:59 -04001936 client_context = Context(SSLv23_METHOD)
Alex Gaynor03737182020-07-23 20:40:46 -04001937 client_context.set_alpn_protos([b"http/1.1", b"spdy/2"])
Cory Benfield12eae892014-06-07 15:42:56 +01001938
Alex Gaynor77debda2020-04-07 13:40:59 -04001939 server_context = Context(SSLv23_METHOD)
1940 server_context.set_alpn_select_callback(refusal)
Cory Benfield12eae892014-06-07 15:42:56 +01001941
Alex Gaynor77debda2020-04-07 13:40:59 -04001942 # Necessary to actually accept the connection
1943 server_context.use_privatekey(
Alex Gaynor03737182020-07-23 20:40:46 -04001944 load_privatekey(FILETYPE_PEM, server_key_pem)
1945 )
Alex Gaynor77debda2020-04-07 13:40:59 -04001946 server_context.use_certificate(
Alex Gaynor03737182020-07-23 20:40:46 -04001947 load_certificate(FILETYPE_PEM, server_cert_pem)
1948 )
Cory Benfield12eae892014-06-07 15:42:56 +01001949
Alex Gaynor77debda2020-04-07 13:40:59 -04001950 # Do a little connection to trigger the logic
1951 server = Connection(server_context, None)
1952 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001953
Alex Gaynor77debda2020-04-07 13:40:59 -04001954 client = Connection(client_context, None)
1955 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001956
Alex Gaynor77debda2020-04-07 13:40:59 -04001957 # Do the dance.
1958 interact_in_memory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001959
Alex Gaynor03737182020-07-23 20:40:46 -04001960 assert refusal_args == [(server, [b"http/1.1", b"spdy/2"])]
Alex Gaynor77debda2020-04-07 13:40:59 -04001961
Alex Gaynor03737182020-07-23 20:40:46 -04001962 assert client.get_alpn_proto_negotiated() == b""
Alex Gaynor77debda2020-04-07 13:40:59 -04001963
1964 def test_alpn_select_cb_returns_invalid_value(self):
1965 """
1966 If the ALPN selection callback returns anything other than
1967 a bytestring or ``NO_OVERLAPPING_PROTOCOLS``, a
1968 :py:exc:`TypeError` is raised.
1969 """
1970 invalid_cb_args = []
1971
1972 def invalid_cb(conn, options):
1973 invalid_cb_args.append((conn, options))
1974 return u"can't return unicode"
1975
1976 client_context = Context(SSLv23_METHOD)
Alex Gaynor03737182020-07-23 20:40:46 -04001977 client_context.set_alpn_protos([b"http/1.1", b"spdy/2"])
Alex Gaynor77debda2020-04-07 13:40:59 -04001978
1979 server_context = Context(SSLv23_METHOD)
1980 server_context.set_alpn_select_callback(invalid_cb)
1981
1982 # Necessary to actually accept the connection
1983 server_context.use_privatekey(
Alex Gaynor03737182020-07-23 20:40:46 -04001984 load_privatekey(FILETYPE_PEM, server_key_pem)
1985 )
Alex Gaynor77debda2020-04-07 13:40:59 -04001986 server_context.use_certificate(
Alex Gaynor03737182020-07-23 20:40:46 -04001987 load_certificate(FILETYPE_PEM, server_cert_pem)
1988 )
Alex Gaynor77debda2020-04-07 13:40:59 -04001989
1990 # Do a little connection to trigger the logic
1991 server = Connection(server_context, None)
1992 server.set_accept_state()
1993
1994 client = Connection(client_context, None)
1995 client.set_connect_state()
1996
1997 # Do the dance.
1998 with pytest.raises(TypeError):
Alex Chanec1e32d2016-11-10 14:11:45 +00001999 interact_in_memory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01002000
Alex Gaynor03737182020-07-23 20:40:46 -04002001 assert invalid_cb_args == [(server, [b"http/1.1", b"spdy/2"])]
Cory Benfield12eae892014-06-07 15:42:56 +01002002
Alex Gaynor03737182020-07-23 20:40:46 -04002003 assert client.get_alpn_proto_negotiated() == b""
Cory Benfield12eae892014-06-07 15:42:56 +01002004
Alex Gaynor77debda2020-04-07 13:40:59 -04002005 def test_alpn_no_server(self):
2006 """
2007 When clients and servers cannot agree on what protocol to use next
2008 because the server doesn't offer ALPN, no protocol is negotiated.
2009 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002010 client_context = Context(SSLv23_METHOD)
Alex Gaynor03737182020-07-23 20:40:46 -04002011 client_context.set_alpn_protos([b"http/1.1", b"spdy/2"])
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002012
Paul Kehrer688538c2020-08-03 19:18:15 -05002013 server_context = Context(SSLv23_METHOD)
Cory Benfield12eae892014-06-07 15:42:56 +01002014
Alex Gaynor77debda2020-04-07 13:40:59 -04002015 # Necessary to actually accept the connection
2016 server_context.use_privatekey(
Alex Gaynor03737182020-07-23 20:40:46 -04002017 load_privatekey(FILETYPE_PEM, server_key_pem)
2018 )
Alex Gaynor77debda2020-04-07 13:40:59 -04002019 server_context.use_certificate(
Alex Gaynor03737182020-07-23 20:40:46 -04002020 load_certificate(FILETYPE_PEM, server_cert_pem)
2021 )
Cory Benfield12eae892014-06-07 15:42:56 +01002022
Alex Gaynor77debda2020-04-07 13:40:59 -04002023 # Do a little connection to trigger the logic
2024 server = Connection(server_context, None)
2025 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01002026
Alex Gaynor77debda2020-04-07 13:40:59 -04002027 client = Connection(client_context, None)
2028 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01002029
Alex Gaynor77debda2020-04-07 13:40:59 -04002030 # Do the dance.
2031 interact_in_memory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01002032
Alex Gaynor03737182020-07-23 20:40:46 -04002033 assert client.get_alpn_proto_negotiated() == b""
Cory Benfield12eae892014-06-07 15:42:56 +01002034
Alex Gaynor77debda2020-04-07 13:40:59 -04002035 def test_alpn_callback_exception(self):
2036 """
2037 We can handle exceptions in the ALPN select callback.
2038 """
2039 select_args = []
Cory Benfield12eae892014-06-07 15:42:56 +01002040
Alex Gaynor77debda2020-04-07 13:40:59 -04002041 def select(conn, options):
2042 select_args.append((conn, options))
2043 raise TypeError()
Cory Benfield12eae892014-06-07 15:42:56 +01002044
Paul Kehrer688538c2020-08-03 19:18:15 -05002045 client_context = Context(SSLv23_METHOD)
Alex Gaynor03737182020-07-23 20:40:46 -04002046 client_context.set_alpn_protos([b"http/1.1", b"spdy/2"])
Mark Williams5d890a02019-11-17 19:56:26 -08002047
Paul Kehrer688538c2020-08-03 19:18:15 -05002048 server_context = Context(SSLv23_METHOD)
Alex Gaynor77debda2020-04-07 13:40:59 -04002049 server_context.set_alpn_select_callback(select)
Mark Williams5d890a02019-11-17 19:56:26 -08002050
Alex Gaynor77debda2020-04-07 13:40:59 -04002051 # Necessary to actually accept the connection
2052 server_context.use_privatekey(
Alex Gaynor03737182020-07-23 20:40:46 -04002053 load_privatekey(FILETYPE_PEM, server_key_pem)
2054 )
Alex Gaynor77debda2020-04-07 13:40:59 -04002055 server_context.use_certificate(
Alex Gaynor03737182020-07-23 20:40:46 -04002056 load_certificate(FILETYPE_PEM, server_cert_pem)
2057 )
Mark Williams5d890a02019-11-17 19:56:26 -08002058
Alex Gaynor77debda2020-04-07 13:40:59 -04002059 # Do a little connection to trigger the logic
2060 server = Connection(server_context, None)
2061 server.set_accept_state()
Mark Williams5d890a02019-11-17 19:56:26 -08002062
Alex Gaynor77debda2020-04-07 13:40:59 -04002063 client = Connection(client_context, None)
2064 client.set_connect_state()
Mark Williams5d890a02019-11-17 19:56:26 -08002065
Alex Gaynor77debda2020-04-07 13:40:59 -04002066 with pytest.raises(TypeError):
Mark Williams5d890a02019-11-17 19:56:26 -08002067 interact_in_memory(server, client)
Alex Gaynor03737182020-07-23 20:40:46 -04002068 assert select_args == [(server, [b"http/1.1", b"spdy/2"])]
Cory Benfield0f7b04c2015-04-13 17:51:12 -04002069
Cory Benfieldf1177e72015-04-12 09:11:49 -04002070
Alex Chanec1e32d2016-11-10 14:11:45 +00002071class TestSession(object):
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05002072 """
2073 Unit tests for :py:obj:`OpenSSL.SSL.Session`.
2074 """
Alex Gaynor03737182020-07-23 20:40:46 -04002075
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05002076 def test_construction(self):
2077 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002078 :py:class:`Session` can be constructed with no arguments, creating
2079 a new instance of that type.
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05002080 """
2081 new_session = Session()
Alex Chanec1e32d2016-11-10 14:11:45 +00002082 assert isinstance(new_session, Session)
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05002083
2084
Alex Chan1c0cb662017-01-30 07:13:30 +00002085class TestConnection(object):
Rick Deane15b1472009-07-09 15:53:42 -05002086 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002087 Unit tests for `OpenSSL.SSL.Connection`.
Rick Deane15b1472009-07-09 15:53:42 -05002088 """
Alex Gaynor03737182020-07-23 20:40:46 -04002089
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04002090 # XXX get_peer_certificate -> None
2091 # XXX sock_shutdown
2092 # XXX master_key -> TypeError
2093 # XXX server_random -> TypeError
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04002094 # XXX connect -> TypeError
2095 # XXX connect_ex -> TypeError
2096 # XXX set_connect_state -> TypeError
2097 # XXX set_accept_state -> TypeError
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04002098 # XXX do_handshake -> TypeError
2099 # XXX bio_read -> TypeError
2100 # XXX recv -> TypeError
2101 # XXX send -> TypeError
2102 # XXX bio_write -> TypeError
2103
Rick Deane15b1472009-07-09 15:53:42 -05002104 def test_type(self):
2105 """
Alex Gaynor01f90a12019-02-07 09:14:48 -05002106 `Connection` can be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -05002107 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002108 ctx = Context(SSLv23_METHOD)
Alex Gaynor03737182020-07-23 20:40:46 -04002109 assert is_consistent_type(Connection, "Connection", ctx, None)
Rick Deane15b1472009-07-09 15:53:42 -05002110
Alex Gaynor03737182020-07-23 20:40:46 -04002111 @pytest.mark.parametrize("bad_context", [object(), "context", None, 1])
Alex Chanfb078d82017-04-20 11:16:15 +01002112 def test_wrong_args(self, bad_context):
2113 """
2114 `Connection.__init__` raises `TypeError` if called with a non-`Context`
2115 instance argument.
2116 """
2117 with pytest.raises(TypeError):
2118 Connection(bad_context)
2119
Alex Gaynor03737182020-07-23 20:40:46 -04002120 @pytest.mark.parametrize("bad_bio", [object(), None, 1, [1, 2, 3]])
Daniel Holth079c9632019-11-17 22:45:52 -05002121 def test_bio_write_wrong_args(self, bad_bio):
2122 """
2123 `Connection.bio_write` raises `TypeError` if called with a non-bytes
2124 (or text) argument.
2125 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002126 context = Context(SSLv23_METHOD)
Daniel Holth079c9632019-11-17 22:45:52 -05002127 connection = Connection(context, None)
2128 with pytest.raises(TypeError):
2129 connection.bio_write(bad_bio)
2130
2131 def test_bio_write(self):
2132 """
2133 `Connection.bio_write` does not raise if called with bytes or
2134 bytearray, warns if called with text.
2135 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002136 context = Context(SSLv23_METHOD)
Daniel Holth079c9632019-11-17 22:45:52 -05002137 connection = Connection(context, None)
Alex Gaynor03737182020-07-23 20:40:46 -04002138 connection.bio_write(b"xy")
2139 connection.bio_write(bytearray(b"za"))
Daniel Holth079c9632019-11-17 22:45:52 -05002140 with pytest.warns(DeprecationWarning):
Alex Gaynor03737182020-07-23 20:40:46 -04002141 connection.bio_write(u"deprecated")
Daniel Holth079c9632019-11-17 22:45:52 -05002142
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002143 def test_get_context(self):
2144 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002145 `Connection.get_context` returns the `Context` instance used to
2146 construct the `Connection` instance.
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002147 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002148 context = Context(SSLv23_METHOD)
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002149 connection = Connection(context, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002150 assert connection.get_context() is context
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002151
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002152 def test_set_context_wrong_args(self):
2153 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002154 `Connection.set_context` raises `TypeError` if called with a
Alex Chanfb078d82017-04-20 11:16:15 +01002155 non-`Context` instance argument.
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002156 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002157 ctx = Context(SSLv23_METHOD)
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002158 connection = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002159 with pytest.raises(TypeError):
2160 connection.set_context(object())
2161 with pytest.raises(TypeError):
2162 connection.set_context("hello")
2163 with pytest.raises(TypeError):
2164 connection.set_context(1)
2165 assert ctx is connection.get_context()
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002166
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002167 def test_set_context(self):
2168 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002169 `Connection.set_context` specifies a new `Context` instance to be
2170 used for the connection.
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002171 """
2172 original = Context(SSLv23_METHOD)
Paul Kehrer688538c2020-08-03 19:18:15 -05002173 replacement = Context(SSLv23_METHOD)
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002174 connection = Connection(original, None)
2175 connection.set_context(replacement)
Alex Chan1c0cb662017-01-30 07:13:30 +00002176 assert replacement is connection.get_context()
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002177 # Lose our references to the contexts, just in case the Connection
2178 # isn't properly managing its own contributions to their reference
2179 # counts.
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002180 del original, replacement
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002181 collect()
2182
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002183 def test_set_tlsext_host_name_wrong_args(self):
2184 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002185 If `Connection.set_tlsext_host_name` is called with a non-byte string
2186 argument or a byte string with an embedded NUL, `TypeError` is raised.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002187 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002188 conn = Connection(Context(SSLv23_METHOD), None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002189 with pytest.raises(TypeError):
2190 conn.set_tlsext_host_name(object())
2191 with pytest.raises(TypeError):
2192 conn.set_tlsext_host_name(b"with\0null")
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002193
Hugo van Kemenade60827f82019-08-30 00:39:35 +03002194 if not PY2:
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002195 # On Python 3.x, don't accidentally implicitly convert from text.
Alex Chan1c0cb662017-01-30 07:13:30 +00002196 with pytest.raises(TypeError):
2197 conn.set_tlsext_host_name(b"example.com".decode("ascii"))
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04002198
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002199 def test_pending(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002200 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002201 `Connection.pending` returns the number of bytes available for
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002202 immediate read.
2203 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002204 connection = Connection(Context(SSLv23_METHOD), None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002205 assert connection.pending() == 0
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002206
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002207 def test_peek(self):
2208 """
Hynek Schlawack3bcf3152017-02-18 08:25:34 +01002209 `Connection.recv` peeks into the connection if `socket.MSG_PEEK` is
2210 passed.
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002211 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002212 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04002213 server.send(b"xy")
2214 assert client.recv(2, MSG_PEEK) == b"xy"
2215 assert client.recv(2, MSG_PEEK) == b"xy"
2216 assert client.recv(2) == b"xy"
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002217
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002218 def test_connect_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002219 """
Hynek Schlawack3bcf3152017-02-18 08:25:34 +01002220 `Connection.connect` raises `TypeError` if called with a non-address
2221 argument.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002222 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002223 connection = Connection(Context(SSLv23_METHOD), socket_any_family())
Alex Chan1c0cb662017-01-30 07:13:30 +00002224 with pytest.raises(TypeError):
2225 connection.connect(None)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002226
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002227 def test_connect_refused(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002228 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002229 `Connection.connect` raises `socket.error` if the underlying socket
2230 connect method raises it.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002231 """
David Benjamin1fbe0642019-04-15 17:05:13 -05002232 client = socket_any_family()
Paul Kehrer688538c2020-08-03 19:18:15 -05002233 context = Context(SSLv23_METHOD)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002234 clientSSL = Connection(context, client)
Alex Gaynor122717b2015-09-05 14:14:18 -04002235 # pytest.raises here doesn't work because of a bug in py.test on Python
2236 # 2.6: https://github.com/pytest-dev/pytest/issues/988
Alex Gaynore69c2782015-09-05 14:07:48 -04002237 try:
David Benjamin1fbe0642019-04-15 17:05:13 -05002238 clientSSL.connect((loopback_address(client), 1))
Alex Gaynore69c2782015-09-05 14:07:48 -04002239 except error as e:
Alex Gaynor20a4c082015-09-05 14:24:15 -04002240 exc = e
2241 assert exc.args[0] == ECONNREFUSED
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002242
2243 def test_connect(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002244 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002245 `Connection.connect` establishes a connection to the specified address.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002246 """
David Benjamin1fbe0642019-04-15 17:05:13 -05002247 port = socket_any_family()
Alex Gaynor03737182020-07-23 20:40:46 -04002248 port.bind(("", 0))
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002249 port.listen(3)
2250
Paul Kehrer688538c2020-08-03 19:18:15 -05002251 clientSSL = Connection(Context(SSLv23_METHOD), socket(port.family))
David Benjamin1fbe0642019-04-15 17:05:13 -05002252 clientSSL.connect((loopback_address(port), port.getsockname()[1]))
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002253 # XXX An assertion? Or something?
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002254
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002255 @pytest.mark.skipif(
2256 platform == "darwin",
Alex Gaynor03737182020-07-23 20:40:46 -04002257 reason="connect_ex sometimes causes a kernel panic on OS X 10.6.4",
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002258 )
2259 def test_connect_ex(self):
2260 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002261 If there is a connection error, `Connection.connect_ex` returns the
2262 errno instead of raising an exception.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002263 """
David Benjamin1fbe0642019-04-15 17:05:13 -05002264 port = socket_any_family()
Alex Gaynor03737182020-07-23 20:40:46 -04002265 port.bind(("", 0))
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002266 port.listen(3)
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002267
Paul Kehrer688538c2020-08-03 19:18:15 -05002268 clientSSL = Connection(Context(SSLv23_METHOD), socket(port.family))
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002269 clientSSL.setblocking(False)
2270 result = clientSSL.connect_ex(port.getsockname())
2271 expected = (EINPROGRESS, EWOULDBLOCK)
Alex Chan1c0cb662017-01-30 07:13:30 +00002272 assert result in expected
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002273
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002274 def test_accept(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002275 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002276 `Connection.accept` accepts a pending connection attempt and returns a
2277 tuple of a new `Connection` (the accepted client) and the address the
2278 connection originated from.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002279 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002280 ctx = Context(SSLv23_METHOD)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002281 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2282 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
David Benjamin1fbe0642019-04-15 17:05:13 -05002283 port = socket_any_family()
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002284 portSSL = Connection(ctx, port)
Alex Gaynor03737182020-07-23 20:40:46 -04002285 portSSL.bind(("", 0))
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002286 portSSL.listen(3)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002287
Paul Kehrer688538c2020-08-03 19:18:15 -05002288 clientSSL = Connection(Context(SSLv23_METHOD), socket(port.family))
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002289
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002290 # Calling portSSL.getsockname() here to get the server IP address
2291 # sounds great, but frequently fails on Windows.
David Benjamin1fbe0642019-04-15 17:05:13 -05002292 clientSSL.connect((loopback_address(port), portSSL.getsockname()[1]))
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002293
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002294 serverSSL, address = portSSL.accept()
2295
Alex Chan1c0cb662017-01-30 07:13:30 +00002296 assert isinstance(serverSSL, Connection)
2297 assert serverSSL.get_context() is ctx
2298 assert address == clientSSL.getsockname()
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002299
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002300 def test_shutdown_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002301 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002302 `Connection.set_shutdown` raises `TypeError` if called with arguments
2303 other than integers.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002304 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002305 connection = Connection(Context(SSLv23_METHOD), None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002306 with pytest.raises(TypeError):
2307 connection.set_shutdown(None)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002308
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002309 def test_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002310 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002311 `Connection.shutdown` performs an SSL-level connection shutdown.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002312 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002313 server, client = loopback()
2314 assert not server.shutdown()
2315 assert server.get_shutdown() == SENT_SHUTDOWN
2316 with pytest.raises(ZeroReturnError):
2317 client.recv(1024)
2318 assert client.get_shutdown() == RECEIVED_SHUTDOWN
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04002319 client.shutdown()
Alex Chan1c0cb662017-01-30 07:13:30 +00002320 assert client.get_shutdown() == (SENT_SHUTDOWN | RECEIVED_SHUTDOWN)
2321 with pytest.raises(ZeroReturnError):
2322 server.recv(1024)
2323 assert server.get_shutdown() == (SENT_SHUTDOWN | RECEIVED_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002324
Paul Aurichc85e0862015-01-08 08:34:33 -08002325 def test_shutdown_closed(self):
2326 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002327 If the underlying socket is closed, `Connection.shutdown` propagates
2328 the write error from the low level write call.
Paul Aurichc85e0862015-01-08 08:34:33 -08002329 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002330 server, client = loopback()
Paul Aurichc85e0862015-01-08 08:34:33 -08002331 server.sock_shutdown(2)
Alex Chan1c0cb662017-01-30 07:13:30 +00002332 with pytest.raises(SysCallError) as exc:
2333 server.shutdown()
Alex Chanfb078d82017-04-20 11:16:15 +01002334 if platform == "win32":
2335 assert exc.value.args[0] == ESHUTDOWN
2336 else:
2337 assert exc.value.args[0] == EPIPE
Paul Aurichc85e0862015-01-08 08:34:33 -08002338
Glyph89389472015-04-14 17:29:26 -04002339 def test_shutdown_truncated(self):
Glyph6064ec32015-04-14 16:38:22 -04002340 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002341 If the underlying connection is truncated, `Connection.shutdown`
2342 raises an `Error`.
Glyph6064ec32015-04-14 16:38:22 -04002343 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002344 server_ctx = Context(SSLv23_METHOD)
2345 client_ctx = Context(SSLv23_METHOD)
Glyph89389472015-04-14 17:29:26 -04002346 server_ctx.use_privatekey(
Alex Gaynor03737182020-07-23 20:40:46 -04002347 load_privatekey(FILETYPE_PEM, server_key_pem)
2348 )
Glyph89389472015-04-14 17:29:26 -04002349 server_ctx.use_certificate(
Alex Gaynor03737182020-07-23 20:40:46 -04002350 load_certificate(FILETYPE_PEM, server_cert_pem)
2351 )
Glyph89389472015-04-14 17:29:26 -04002352 server = Connection(server_ctx, None)
2353 client = Connection(client_ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002354 handshake_in_memory(client, server)
2355 assert not server.shutdown()
2356 with pytest.raises(WantReadError):
2357 server.shutdown()
Glyph89389472015-04-14 17:29:26 -04002358 server.bio_shutdown()
Alex Chan1c0cb662017-01-30 07:13:30 +00002359 with pytest.raises(Error):
2360 server.shutdown()
Glyph6064ec32015-04-14 16:38:22 -04002361
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002362 def test_set_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002363 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002364 `Connection.set_shutdown` sets the state of the SSL connection
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002365 shutdown process.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002366 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002367 connection = Connection(Context(SSLv23_METHOD), socket_any_family())
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002368 connection.set_shutdown(RECEIVED_SHUTDOWN)
Alex Chan1c0cb662017-01-30 07:13:30 +00002369 assert connection.get_shutdown() == RECEIVED_SHUTDOWN
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002370
kjavaf248592015-09-07 12:14:01 +01002371 def test_state_string(self):
2372 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002373 `Connection.state_string` verbosely describes the current state of
2374 the `Connection`.
kjavaf248592015-09-07 12:14:01 +01002375 """
Hynek Schlawackb0274ce2015-10-16 19:56:26 +02002376 server, client = socket_pair()
Alex Chan1c0cb662017-01-30 07:13:30 +00002377 server = loopback_server_factory(server)
2378 client = loopback_client_factory(client)
kjavaf248592015-09-07 12:14:01 +01002379
Alex Gaynor5af32d02016-09-24 01:52:21 -04002380 assert server.get_state_string() in [
Alex Gaynor03737182020-07-23 20:40:46 -04002381 b"before/accept initialization",
2382 b"before SSL initialization",
Alex Gaynor5af32d02016-09-24 01:52:21 -04002383 ]
2384 assert client.get_state_string() in [
Alex Gaynor03737182020-07-23 20:40:46 -04002385 b"before/connect initialization",
2386 b"before SSL initialization",
Alex Gaynor5af32d02016-09-24 01:52:21 -04002387 ]
kjavaf248592015-09-07 12:14:01 +01002388
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002389 def test_app_data(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002390 """
2391 Any object can be set as app data by passing it to
Alex Chan1c0cb662017-01-30 07:13:30 +00002392 `Connection.set_app_data` and later retrieved with
2393 `Connection.get_app_data`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002394 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002395 conn = Connection(Context(SSLv23_METHOD), None)
Todd Chapman4f73e4f2015-08-27 11:26:43 -04002396 assert None is conn.get_app_data()
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002397 app_data = object()
2398 conn.set_app_data(app_data)
Todd Chapman4f73e4f2015-08-27 11:26:43 -04002399 assert conn.get_app_data() is app_data
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002400
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002401 def test_makefile(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002402 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002403 `Connection.makefile` is not implemented and calling that
2404 method raises `NotImplementedError`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002405 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002406 conn = Connection(Context(SSLv23_METHOD), None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002407 with pytest.raises(NotImplementedError):
2408 conn.makefile()
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002409
Jeremy Lainé460a19d2018-05-16 19:44:19 +02002410 def test_get_certificate(self):
2411 """
2412 `Connection.get_certificate` returns the local certificate.
2413 """
2414 chain = _create_certificate_chain()
2415 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
2416
Paul Kehrer688538c2020-08-03 19:18:15 -05002417 context = Context(SSLv23_METHOD)
Jeremy Lainé460a19d2018-05-16 19:44:19 +02002418 context.use_certificate(scert)
2419 client = Connection(context, None)
2420 cert = client.get_certificate()
2421 assert cert is not None
2422 assert "Server Certificate" == cert.get_subject().CN
2423
2424 def test_get_certificate_none(self):
2425 """
2426 `Connection.get_certificate` returns the local certificate.
2427
2428 If there is no certificate, it returns None.
2429 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002430 context = Context(SSLv23_METHOD)
Jeremy Lainé460a19d2018-05-16 19:44:19 +02002431 client = Connection(context, None)
2432 cert = client.get_certificate()
2433 assert cert is None
2434
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002435 def test_get_peer_cert_chain(self):
2436 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002437 `Connection.get_peer_cert_chain` returns a list of certificates
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002438 which the connected server returned for the certification verification.
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002439 """
2440 chain = _create_certificate_chain()
2441 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
2442
Paul Kehrer688538c2020-08-03 19:18:15 -05002443 serverContext = Context(SSLv23_METHOD)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002444 serverContext.use_privatekey(skey)
2445 serverContext.use_certificate(scert)
2446 serverContext.add_extra_chain_cert(icert)
2447 serverContext.add_extra_chain_cert(cacert)
2448 server = Connection(serverContext, None)
2449 server.set_accept_state()
2450
2451 # Create the client
Paul Kehrer688538c2020-08-03 19:18:15 -05002452 clientContext = Context(SSLv23_METHOD)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002453 clientContext.set_verify(VERIFY_NONE, verify_cb)
2454 client = Connection(clientContext, None)
2455 client.set_connect_state()
2456
Alex Chan1c0cb662017-01-30 07:13:30 +00002457 interact_in_memory(client, server)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002458
2459 chain = client.get_peer_cert_chain()
Alex Chan1c0cb662017-01-30 07:13:30 +00002460 assert len(chain) == 3
2461 assert "Server Certificate" == chain[0].get_subject().CN
2462 assert "Intermediate Certificate" == chain[1].get_subject().CN
2463 assert "Authority Certificate" == chain[2].get_subject().CN
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002464
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002465 def test_get_peer_cert_chain_none(self):
2466 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002467 `Connection.get_peer_cert_chain` returns `None` if the peer sends
2468 no certificate chain.
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002469 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002470 ctx = Context(SSLv23_METHOD)
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002471 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2472 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
2473 server = Connection(ctx, None)
2474 server.set_accept_state()
Paul Kehrer688538c2020-08-03 19:18:15 -05002475 client = Connection(Context(SSLv23_METHOD), None)
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002476 client.set_connect_state()
Alex Chan1c0cb662017-01-30 07:13:30 +00002477 interact_in_memory(client, server)
2478 assert None is server.get_peer_cert_chain()
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002479
Shane Harvey33c54992020-08-05 16:48:51 -07002480 def test_get_verified_chain(self):
2481 """
2482 `Connection.get_verified_chain` returns a list of certificates
2483 which the connected server returned for the certification verification.
2484 """
2485 chain = _create_certificate_chain()
2486 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
2487
2488 serverContext = Context(SSLv23_METHOD)
2489 serverContext.use_privatekey(skey)
2490 serverContext.use_certificate(scert)
2491 serverContext.add_extra_chain_cert(icert)
2492 serverContext.add_extra_chain_cert(cacert)
2493 server = Connection(serverContext, None)
2494 server.set_accept_state()
2495
2496 # Create the client
2497 clientContext = Context(SSLv23_METHOD)
2498 # cacert is self-signed so the client must trust it for verification
2499 # to succeed.
2500 clientContext.get_cert_store().add_cert(cacert)
2501 clientContext.set_verify(VERIFY_PEER, verify_cb)
2502 client = Connection(clientContext, None)
2503 client.set_connect_state()
2504
2505 interact_in_memory(client, server)
2506
2507 chain = client.get_verified_chain()
2508 assert len(chain) == 3
2509 assert "Server Certificate" == chain[0].get_subject().CN
2510 assert "Intermediate Certificate" == chain[1].get_subject().CN
2511 assert "Authority Certificate" == chain[2].get_subject().CN
2512
2513 def test_get_verified_chain_none(self):
2514 """
2515 `Connection.get_verified_chain` returns `None` if the peer sends
2516 no certificate chain.
2517 """
2518 ctx = Context(SSLv23_METHOD)
2519 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2520 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
2521 server = Connection(ctx, None)
2522 server.set_accept_state()
2523 client = Connection(Context(SSLv23_METHOD), None)
2524 client.set_connect_state()
2525 interact_in_memory(client, server)
2526 assert None is server.get_verified_chain()
2527
2528 def test_get_verified_chain_unconnected(self):
2529 """
2530 `Connection.get_verified_chain` returns `None` when used with an object
2531 which has not been connected.
2532 """
2533 ctx = Context(SSLv23_METHOD)
2534 server = Connection(ctx, None)
2535 assert None is server.get_verified_chain()
2536
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002537 def test_get_session_unconnected(self):
2538 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002539 `Connection.get_session` returns `None` when used with an object
2540 which has not been connected.
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002541 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002542 ctx = Context(SSLv23_METHOD)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002543 server = Connection(ctx, None)
2544 session = server.get_session()
Alex Chan1c0cb662017-01-30 07:13:30 +00002545 assert None is session
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002546
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002547 def test_server_get_session(self):
2548 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002549 On the server side of a connection, `Connection.get_session` returns a
2550 `Session` instance representing the SSL session for that connection.
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002551 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002552 server, client = loopback()
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002553 session = server.get_session()
Alex Chan1c0cb662017-01-30 07:13:30 +00002554 assert isinstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002555
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002556 def test_client_get_session(self):
2557 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002558 On the client side of a connection, `Connection.get_session`
2559 returns a `Session` instance representing the SSL session for
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002560 that connection.
2561 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002562 server, client = loopback()
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002563 session = client.get_session()
Alex Chan1c0cb662017-01-30 07:13:30 +00002564 assert isinstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002565
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002566 def test_set_session_wrong_args(self):
2567 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002568 `Connection.set_session` raises `TypeError` if called with an object
2569 that is not an instance of `Session`.
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002570 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002571 ctx = Context(SSLv23_METHOD)
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002572 connection = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002573 with pytest.raises(TypeError):
2574 connection.set_session(123)
2575 with pytest.raises(TypeError):
2576 connection.set_session("hello")
2577 with pytest.raises(TypeError):
2578 connection.set_session(object())
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002579
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002580 def test_client_set_session(self):
2581 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002582 `Connection.set_session`, when used prior to a connection being
2583 established, accepts a `Session` instance and causes an attempt to
2584 re-use the session it represents when the SSL handshake is performed.
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002585 """
2586 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2587 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
Paul Kehrer7d5a3bf2019-01-21 12:24:02 -06002588 ctx = Context(TLSv1_2_METHOD)
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002589 ctx.use_privatekey(key)
2590 ctx.use_certificate(cert)
2591 ctx.set_session_id("unity-test")
2592
2593 def makeServer(socket):
2594 server = Connection(ctx, socket)
2595 server.set_accept_state()
2596 return server
2597
Alex Gaynor03737182020-07-23 20:40:46 -04002598 originalServer, originalClient = loopback(server_factory=makeServer)
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002599 originalSession = originalClient.get_session()
2600
2601 def makeClient(socket):
Alex Chan1c0cb662017-01-30 07:13:30 +00002602 client = loopback_client_factory(socket)
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002603 client.set_session(originalSession)
2604 return client
Alex Gaynor03737182020-07-23 20:40:46 -04002605
Alex Chan1c0cb662017-01-30 07:13:30 +00002606 resumedServer, resumedClient = loopback(
Alex Gaynor03737182020-07-23 20:40:46 -04002607 server_factory=makeServer, client_factory=makeClient
2608 )
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002609
2610 # This is a proxy: in general, we have no access to any unique
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002611 # identifier for the session (new enough versions of OpenSSL expose
2612 # a hash which could be usable, but "new enough" is very, very new).
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002613 # Instead, exploit the fact that the master key is re-used if the
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002614 # session is re-used. As long as the master key for the two
2615 # connections is the same, the session was re-used!
Alex Chan1c0cb662017-01-30 07:13:30 +00002616 assert originalServer.master_key() == resumedServer.master_key()
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002617
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002618 def test_set_session_wrong_method(self):
2619 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002620 If `Connection.set_session` is passed a `Session` instance associated
2621 with a context using a different SSL method than the `Connection`
2622 is using, a `OpenSSL.SSL.Error` is raised.
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002623 """
Alex Gaynor124a0132020-10-27 00:15:17 -04002624 v1 = TLSv1_2_METHOD
2625 v2 = TLSv1_METHOD
Alex Gaynor5af32d02016-09-24 01:52:21 -04002626
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002627 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2628 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
Alex Gaynor5af32d02016-09-24 01:52:21 -04002629 ctx = Context(v1)
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002630 ctx.use_privatekey(key)
2631 ctx.use_certificate(cert)
Paul Kehrerc45a6ea2020-08-03 15:54:20 -05002632 ctx.set_session_id(b"unity-test")
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002633
2634 def makeServer(socket):
2635 server = Connection(ctx, socket)
2636 server.set_accept_state()
2637 return server
2638
Alex Gaynor5af32d02016-09-24 01:52:21 -04002639 def makeOriginalClient(socket):
2640 client = Connection(Context(v1), socket)
2641 client.set_connect_state()
2642 return client
2643
Alex Chan1c0cb662017-01-30 07:13:30 +00002644 originalServer, originalClient = loopback(
Alex Gaynor03737182020-07-23 20:40:46 -04002645 server_factory=makeServer, client_factory=makeOriginalClient
2646 )
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002647 originalSession = originalClient.get_session()
2648
2649 def makeClient(socket):
2650 # Intentionally use a different, incompatible method here.
Alex Gaynor5af32d02016-09-24 01:52:21 -04002651 client = Connection(Context(v2), socket)
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002652 client.set_connect_state()
2653 client.set_session(originalSession)
2654 return client
2655
Alex Chan1c0cb662017-01-30 07:13:30 +00002656 with pytest.raises(Error):
2657 loopback(client_factory=makeClient, server_factory=makeServer)
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002658
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002659 def test_wantWriteError(self):
2660 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002661 `Connection` methods which generate output raise
2662 `OpenSSL.SSL.WantWriteError` if writing to the connection's BIO
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002663 fail indicating a should-write state.
2664 """
2665 client_socket, server_socket = socket_pair()
2666 # Fill up the client's send buffer so Connection won't be able to write
Jean-Paul Calderonebbff8b92014-03-22 14:20:30 -04002667 # anything. Only write a single byte at a time so we can be sure we
2668 # completely fill the buffer. Even though the socket API is allowed to
2669 # signal a short write via its return value it seems this doesn't
2670 # always happen on all platforms (FreeBSD and OS X particular) for the
2671 # very last bit of available buffer space.
2672 msg = b"x"
caternb2777a42018-08-09 15:38:13 -04002673 for i in range(1024 * 1024 * 64):
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002674 try:
2675 client_socket.send(msg)
2676 except error as e:
2677 if e.errno == EWOULDBLOCK:
2678 break
2679 raise
2680 else:
Alex Chan1c0cb662017-01-30 07:13:30 +00002681 pytest.fail(
Alex Gaynor03737182020-07-23 20:40:46 -04002682 "Failed to fill socket buffer, cannot test BIO want write"
2683 )
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002684
Paul Kehrer688538c2020-08-03 19:18:15 -05002685 ctx = Context(SSLv23_METHOD)
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002686 conn = Connection(ctx, client_socket)
2687 # Client's speak first, so make it an SSL client
2688 conn.set_connect_state()
Alex Chan1c0cb662017-01-30 07:13:30 +00002689 with pytest.raises(WantWriteError):
2690 conn.do_handshake()
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002691
2692 # XXX want_read
2693
Fedor Brunner416f4a12014-03-28 13:18:38 +01002694 def test_get_finished_before_connect(self):
Fedor Brunner5747b932014-03-05 14:22:34 +01002695 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002696 `Connection.get_finished` returns `None` before TLS handshake
2697 is completed.
Fedor Brunner5747b932014-03-05 14:22:34 +01002698 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002699 ctx = Context(SSLv23_METHOD)
Fedor Brunner5747b932014-03-05 14:22:34 +01002700 connection = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002701 assert connection.get_finished() is None
Fedor Brunner416f4a12014-03-28 13:18:38 +01002702
2703 def test_get_peer_finished_before_connect(self):
2704 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002705 `Connection.get_peer_finished` returns `None` before TLS handshake
2706 is completed.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002707 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002708 ctx = Context(SSLv23_METHOD)
Fedor Brunner416f4a12014-03-28 13:18:38 +01002709 connection = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002710 assert connection.get_peer_finished() is None
Fedor Brunner5747b932014-03-05 14:22:34 +01002711
Fedor Brunner416f4a12014-03-28 13:18:38 +01002712 def test_get_finished(self):
2713 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002714 `Connection.get_finished` method returns the TLS Finished message send
2715 from client, or server. Finished messages are send during
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002716 TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002717 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002718 server, client = loopback()
Fedor Brunner416f4a12014-03-28 13:18:38 +01002719
Alex Chan1c0cb662017-01-30 07:13:30 +00002720 assert server.get_finished() is not None
2721 assert len(server.get_finished()) > 0
Fedor Brunner416f4a12014-03-28 13:18:38 +01002722
2723 def test_get_peer_finished(self):
2724 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002725 `Connection.get_peer_finished` method returns the TLS Finished
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002726 message received from client, or server. Finished messages are send
2727 during TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002728 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002729 server, client = loopback()
Fedor Brunner416f4a12014-03-28 13:18:38 +01002730
Alex Chan1c0cb662017-01-30 07:13:30 +00002731 assert server.get_peer_finished() is not None
2732 assert len(server.get_peer_finished()) > 0
Fedor Brunner5747b932014-03-05 14:22:34 +01002733
Fedor Brunner416f4a12014-03-28 13:18:38 +01002734 def test_tls_finished_message_symmetry(self):
2735 """
Hynek Schlawackdddd1112015-09-05 21:12:30 +02002736 The TLS Finished message send by server must be the TLS Finished
2737 message received by client.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002738
Hynek Schlawackdddd1112015-09-05 21:12:30 +02002739 The TLS Finished message send by client must be the TLS Finished
2740 message received by server.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002741 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002742 server, client = loopback()
Fedor Brunner416f4a12014-03-28 13:18:38 +01002743
Alex Chan1c0cb662017-01-30 07:13:30 +00002744 assert server.get_finished() == client.get_peer_finished()
2745 assert client.get_finished() == server.get_peer_finished()
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002746
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002747 def test_get_cipher_name_before_connect(self):
2748 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002749 `Connection.get_cipher_name` returns `None` if no connection
2750 has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002751 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002752 ctx = Context(SSLv23_METHOD)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002753 conn = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002754 assert conn.get_cipher_name() is None
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002755
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002756 def test_get_cipher_name(self):
2757 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002758 `Connection.get_cipher_name` returns a `unicode` string giving the
2759 name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002760 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002761 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04002762 server_cipher_name, client_cipher_name = (
2763 server.get_cipher_name(),
2764 client.get_cipher_name(),
2765 )
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002766
Alex Chan1c0cb662017-01-30 07:13:30 +00002767 assert isinstance(server_cipher_name, text_type)
2768 assert isinstance(client_cipher_name, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002769
Alex Chan1c0cb662017-01-30 07:13:30 +00002770 assert server_cipher_name == client_cipher_name
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002771
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002772 def test_get_cipher_version_before_connect(self):
2773 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002774 `Connection.get_cipher_version` returns `None` if no connection
2775 has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002776 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002777 ctx = Context(SSLv23_METHOD)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002778 conn = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002779 assert conn.get_cipher_version() is None
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002780
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002781 def test_get_cipher_version(self):
2782 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002783 `Connection.get_cipher_version` returns a `unicode` string giving
2784 the protocol name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002785 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002786 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04002787 server_cipher_version, client_cipher_version = (
2788 server.get_cipher_version(),
2789 client.get_cipher_version(),
2790 )
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002791
Alex Chan1c0cb662017-01-30 07:13:30 +00002792 assert isinstance(server_cipher_version, text_type)
2793 assert isinstance(client_cipher_version, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002794
Alex Chan1c0cb662017-01-30 07:13:30 +00002795 assert server_cipher_version == client_cipher_version
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002796
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002797 def test_get_cipher_bits_before_connect(self):
2798 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002799 `Connection.get_cipher_bits` returns `None` if no connection has
2800 been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002801 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002802 ctx = Context(SSLv23_METHOD)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002803 conn = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002804 assert conn.get_cipher_bits() is None
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002805
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002806 def test_get_cipher_bits(self):
2807 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002808 `Connection.get_cipher_bits` returns the number of secret bits
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002809 of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002810 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002811 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04002812 server_cipher_bits, client_cipher_bits = (
2813 server.get_cipher_bits(),
2814 client.get_cipher_bits(),
2815 )
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002816
Alex Chan1c0cb662017-01-30 07:13:30 +00002817 assert isinstance(server_cipher_bits, int)
2818 assert isinstance(client_cipher_bits, int)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002819
Alex Chan1c0cb662017-01-30 07:13:30 +00002820 assert server_cipher_bits == client_cipher_bits
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002821
Jim Shaverabff1882015-05-27 09:15:55 -04002822 def test_get_protocol_version_name(self):
2823 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002824 `Connection.get_protocol_version_name()` returns a string giving the
2825 protocol version of the current connection.
Jim Shaverabff1882015-05-27 09:15:55 -04002826 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002827 server, client = loopback()
Jim Shaverabff1882015-05-27 09:15:55 -04002828 client_protocol_version_name = client.get_protocol_version_name()
2829 server_protocol_version_name = server.get_protocol_version_name()
2830
Alex Chan1c0cb662017-01-30 07:13:30 +00002831 assert isinstance(server_protocol_version_name, text_type)
2832 assert isinstance(client_protocol_version_name, text_type)
Jim Shaverabff1882015-05-27 09:15:55 -04002833
Alex Chan1c0cb662017-01-30 07:13:30 +00002834 assert server_protocol_version_name == client_protocol_version_name
Jim Shaverabff1882015-05-27 09:15:55 -04002835
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002836 def test_get_protocol_version(self):
2837 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002838 `Connection.get_protocol_version()` returns an integer
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002839 giving the protocol version of the current connection.
2840 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002841 server, client = loopback()
Jim Shaver85a4dff2015-04-27 17:42:46 -04002842 client_protocol_version = client.get_protocol_version()
2843 server_protocol_version = server.get_protocol_version()
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002844
Alex Chan1c0cb662017-01-30 07:13:30 +00002845 assert isinstance(server_protocol_version, int)
2846 assert isinstance(client_protocol_version, int)
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002847
Alex Chan1c0cb662017-01-30 07:13:30 +00002848 assert server_protocol_version == client_protocol_version
2849
2850 def test_wantReadError(self):
2851 """
2852 `Connection.bio_read` raises `OpenSSL.SSL.WantReadError` if there are
2853 no bytes available to be read from the BIO.
2854 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002855 ctx = Context(SSLv23_METHOD)
Alex Chan1c0cb662017-01-30 07:13:30 +00002856 conn = Connection(ctx, None)
2857 with pytest.raises(WantReadError):
2858 conn.bio_read(1024)
2859
Alex Gaynor03737182020-07-23 20:40:46 -04002860 @pytest.mark.parametrize("bufsize", [1.0, None, object(), "bufsize"])
Alex Chanfb078d82017-04-20 11:16:15 +01002861 def test_bio_read_wrong_args(self, bufsize):
2862 """
2863 `Connection.bio_read` raises `TypeError` if passed a non-integer
2864 argument.
2865 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002866 ctx = Context(SSLv23_METHOD)
Alex Chanfb078d82017-04-20 11:16:15 +01002867 conn = Connection(ctx, None)
2868 with pytest.raises(TypeError):
2869 conn.bio_read(bufsize)
2870
Alex Chan1c0cb662017-01-30 07:13:30 +00002871 def test_buffer_size(self):
2872 """
2873 `Connection.bio_read` accepts an integer giving the maximum number
2874 of bytes to read and return.
2875 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002876 ctx = Context(SSLv23_METHOD)
Alex Chan1c0cb662017-01-30 07:13:30 +00002877 conn = Connection(ctx, None)
2878 conn.set_connect_state()
2879 try:
2880 conn.do_handshake()
2881 except WantReadError:
2882 pass
2883 data = conn.bio_read(2)
2884 assert 2 == len(data)
2885
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002886
Alex Chanb7480992017-01-30 14:04:47 +00002887class TestConnectionGetCipherList(object):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002888 """
Alex Chanb7480992017-01-30 14:04:47 +00002889 Tests for `Connection.get_cipher_list`.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002890 """
Alex Gaynor03737182020-07-23 20:40:46 -04002891
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002892 def test_result(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002893 """
Alex Chanb7480992017-01-30 14:04:47 +00002894 `Connection.get_cipher_list` returns a list of `bytes` giving the
2895 names of the ciphers which might be used.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002896 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002897 connection = Connection(Context(SSLv23_METHOD), None)
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002898 ciphers = connection.get_cipher_list()
Alex Chanb7480992017-01-30 14:04:47 +00002899 assert isinstance(ciphers, list)
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002900 for cipher in ciphers:
Alex Chanb7480992017-01-30 14:04:47 +00002901 assert isinstance(cipher, str)
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002902
2903
Maximilian Hils868dc3c2017-02-10 14:56:55 +01002904class VeryLarge(bytes):
2905 """
2906 Mock object so that we don't have to allocate 2**31 bytes
2907 """
Alex Gaynor03737182020-07-23 20:40:46 -04002908
Maximilian Hils868dc3c2017-02-10 14:56:55 +01002909 def __len__(self):
Alex Gaynor03737182020-07-23 20:40:46 -04002910 return 2 ** 31
Maximilian Hils868dc3c2017-02-10 14:56:55 +01002911
2912
Alex Chanb7480992017-01-30 14:04:47 +00002913class TestConnectionSend(object):
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002914 """
Alex Chanb7480992017-01-30 14:04:47 +00002915 Tests for `Connection.send`.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002916 """
Alex Gaynor03737182020-07-23 20:40:46 -04002917
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002918 def test_wrong_args(self):
2919 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002920 When called with arguments other than string argument for its first
Alex Chanb7480992017-01-30 14:04:47 +00002921 parameter, `Connection.send` raises `TypeError`.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002922 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002923 connection = Connection(Context(SSLv23_METHOD), None)
Alex Chanb7480992017-01-30 14:04:47 +00002924 with pytest.raises(TypeError):
2925 connection.send(object())
Daniel Holth079c9632019-11-17 22:45:52 -05002926 with pytest.raises(TypeError):
2927 connection.send([1, 2, 3])
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002928
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002929 def test_short_bytes(self):
2930 """
Alex Chanb7480992017-01-30 14:04:47 +00002931 When passed a short byte string, `Connection.send` transmits all of it
2932 and returns the number of bytes sent.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002933 """
Alex Chanb7480992017-01-30 14:04:47 +00002934 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04002935 count = server.send(b"xy")
Alex Chanb7480992017-01-30 14:04:47 +00002936 assert count == 2
Alex Gaynor03737182020-07-23 20:40:46 -04002937 assert client.recv(2) == b"xy"
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002938
Abraham Martinef063482015-03-25 14:06:24 +00002939 def test_text(self):
2940 """
Alex Chanb7480992017-01-30 14:04:47 +00002941 When passed a text, `Connection.send` transmits all of it and
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002942 returns the number of bytes sent. It also raises a DeprecationWarning.
Abraham Martinef063482015-03-25 14:06:24 +00002943 """
Alex Chanb7480992017-01-30 14:04:47 +00002944 server, client = loopback()
2945 with pytest.warns(DeprecationWarning) as w:
Abraham Martinef063482015-03-25 14:06:24 +00002946 simplefilter("always")
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002947 count = server.send(b"xy".decode("ascii"))
Alex Gaynor03737182020-07-23 20:40:46 -04002948 assert "{0} for buf is no longer accepted, use bytes".format(
2949 WARNING_TYPE_EXPECTED
2950 ) == str(w[-1].message)
Alex Chanb7480992017-01-30 14:04:47 +00002951 assert count == 2
Alex Gaynor03737182020-07-23 20:40:46 -04002952 assert client.recv(2) == b"xy"
Abraham Martinef063482015-03-25 14:06:24 +00002953
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002954 def test_short_memoryview(self):
2955 """
2956 When passed a memoryview onto a small number of bytes,
Alex Chanb7480992017-01-30 14:04:47 +00002957 `Connection.send` transmits all of them and returns the number
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002958 of bytes sent.
2959 """
Alex Chanb7480992017-01-30 14:04:47 +00002960 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04002961 count = server.send(memoryview(b"xy"))
Alex Chanb7480992017-01-30 14:04:47 +00002962 assert count == 2
Alex Gaynor03737182020-07-23 20:40:46 -04002963 assert client.recv(2) == b"xy"
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002964
Daniel Holth079c9632019-11-17 22:45:52 -05002965 def test_short_bytearray(self):
2966 """
2967 When passed a short bytearray, `Connection.send` transmits all of
2968 it and returns the number of bytes sent.
2969 """
2970 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04002971 count = server.send(bytearray(b"xy"))
Daniel Holth079c9632019-11-17 22:45:52 -05002972 assert count == 2
Alex Gaynor03737182020-07-23 20:40:46 -04002973 assert client.recv(2) == b"xy"
Daniel Holth079c9632019-11-17 22:45:52 -05002974
Hynek Schlawack8e94f1b2015-09-05 21:31:00 +02002975 @skip_if_py3
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002976 def test_short_buffer(self):
2977 """
2978 When passed a buffer containing a small number of bytes,
Alex Chanb7480992017-01-30 14:04:47 +00002979 `Connection.send` transmits all of them and returns the number
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002980 of bytes sent.
2981 """
Alex Chanb7480992017-01-30 14:04:47 +00002982 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04002983 count = server.send(buffer(b"xy")) # noqa: F821
Alex Chanb7480992017-01-30 14:04:47 +00002984 assert count == 2
Alex Gaynor03737182020-07-23 20:40:46 -04002985 assert client.recv(2) == b"xy"
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02002986
Maximilian Hils868dc3c2017-02-10 14:56:55 +01002987 @pytest.mark.skipif(
Alex Gaynor03737182020-07-23 20:40:46 -04002988 sys.maxsize < 2 ** 31,
2989 reason="sys.maxsize < 2**31 - test requires 64 bit",
Maximilian Hils868dc3c2017-02-10 14:56:55 +01002990 )
2991 def test_buf_too_large(self):
2992 """
2993 When passed a buffer containing >= 2**31 bytes,
2994 `Connection.send` bails out as SSL_write only
2995 accepts an int for the buffer length.
2996 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002997 connection = Connection(Context(SSLv23_METHOD), None)
Maximilian Hils868dc3c2017-02-10 14:56:55 +01002998 with pytest.raises(ValueError) as exc_info:
2999 connection.send(VeryLarge())
3000 exc_info.match(r"Cannot send more than .+ bytes at once")
3001
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05003002
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003003def _make_memoryview(size):
3004 """
3005 Create a new ``memoryview`` wrapped around a ``bytearray`` of the given
3006 size.
3007 """
3008 return memoryview(bytearray(size))
3009
3010
Alex Chanb7480992017-01-30 14:04:47 +00003011class TestConnectionRecvInto(object):
Cory Benfield62d10332014-06-15 10:03:41 +01003012 """
Alex Chanb7480992017-01-30 14:04:47 +00003013 Tests for `Connection.recv_into`.
Cory Benfield62d10332014-06-15 10:03:41 +01003014 """
Alex Gaynor03737182020-07-23 20:40:46 -04003015
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003016 def _no_length_test(self, factory):
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04003017 """
Alex Chanb7480992017-01-30 14:04:47 +00003018 Assert that when the given buffer is passed to `Connection.recv_into`,
3019 whatever bytes are available to be received that fit into that buffer
3020 are written into that buffer.
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04003021 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003022 output_buffer = factory(5)
3023
Alex Chanb7480992017-01-30 14:04:47 +00003024 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04003025 server.send(b"xy")
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04003026
Alex Chanb7480992017-01-30 14:04:47 +00003027 assert client.recv_into(output_buffer) == 2
Alex Gaynor03737182020-07-23 20:40:46 -04003028 assert output_buffer == bytearray(b"xy\x00\x00\x00")
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04003029
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04003030 def test_bytearray_no_length(self):
Cory Benfield62d10332014-06-15 10:03:41 +01003031 """
Alex Chanb7480992017-01-30 14:04:47 +00003032 `Connection.recv_into` can be passed a `bytearray` instance and data
3033 in the receive buffer is written to it.
Cory Benfield62d10332014-06-15 10:03:41 +01003034 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003035 self._no_length_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01003036
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003037 def _respects_length_test(self, factory):
Cory Benfield62d10332014-06-15 10:03:41 +01003038 """
Alex Chanb7480992017-01-30 14:04:47 +00003039 Assert that when the given buffer is passed to `Connection.recv_into`
3040 along with a value for `nbytes` that is less than the size of that
3041 buffer, only `nbytes` bytes are written into the buffer.
Cory Benfield62d10332014-06-15 10:03:41 +01003042 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003043 output_buffer = factory(10)
3044
Alex Chanb7480992017-01-30 14:04:47 +00003045 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04003046 server.send(b"abcdefghij")
Cory Benfield62d10332014-06-15 10:03:41 +01003047
Alex Chanb7480992017-01-30 14:04:47 +00003048 assert client.recv_into(output_buffer, 5) == 5
Alex Gaynor03737182020-07-23 20:40:46 -04003049 assert output_buffer == bytearray(b"abcde\x00\x00\x00\x00\x00")
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04003050
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04003051 def test_bytearray_respects_length(self):
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04003052 """
Alex Chanb7480992017-01-30 14:04:47 +00003053 When called with a `bytearray` instance, `Connection.recv_into`
3054 respects the `nbytes` parameter and doesn't copy in more than that
3055 number of bytes.
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04003056 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003057 self._respects_length_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01003058
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003059 def _doesnt_overfill_test(self, factory):
Cory Benfield62d10332014-06-15 10:03:41 +01003060 """
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04003061 Assert that if there are more bytes available to be read from the
3062 receive buffer than would fit into the buffer passed to
Alex Chanb7480992017-01-30 14:04:47 +00003063 `Connection.recv_into`, only as many as fit are written into it.
Cory Benfield62d10332014-06-15 10:03:41 +01003064 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003065 output_buffer = factory(5)
3066
Alex Chanb7480992017-01-30 14:04:47 +00003067 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04003068 server.send(b"abcdefghij")
Cory Benfield62d10332014-06-15 10:03:41 +01003069
Alex Chanb7480992017-01-30 14:04:47 +00003070 assert client.recv_into(output_buffer) == 5
Alex Gaynor03737182020-07-23 20:40:46 -04003071 assert output_buffer == bytearray(b"abcde")
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04003072 rest = client.recv(5)
Alex Gaynor03737182020-07-23 20:40:46 -04003073 assert b"fghij" == rest
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04003074
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04003075 def test_bytearray_doesnt_overfill(self):
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04003076 """
Alex Chanb7480992017-01-30 14:04:47 +00003077 When called with a `bytearray` instance, `Connection.recv_into`
3078 respects the size of the array and doesn't write more bytes into it
3079 than will fit.
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04003080 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003081 self._doesnt_overfill_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01003082
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04003083 def test_bytearray_really_doesnt_overfill(self):
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003084 """
Alex Chanb7480992017-01-30 14:04:47 +00003085 When called with a `bytearray` instance and an `nbytes` value that is
3086 too large, `Connection.recv_into` respects the size of the array and
3087 not the `nbytes` value and doesn't write more bytes into the buffer
3088 than will fit.
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003089 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003090 self._doesnt_overfill_test(bytearray)
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003091
Maximilian Hils1d95dea2015-08-17 19:27:20 +02003092 def test_peek(self):
Alex Chanb7480992017-01-30 14:04:47 +00003093 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04003094 server.send(b"xy")
Maximilian Hils1d95dea2015-08-17 19:27:20 +02003095
3096 for _ in range(2):
3097 output_buffer = bytearray(5)
Alex Chanb7480992017-01-30 14:04:47 +00003098 assert client.recv_into(output_buffer, flags=MSG_PEEK) == 2
Alex Gaynor03737182020-07-23 20:40:46 -04003099 assert output_buffer == bytearray(b"xy\x00\x00\x00")
Maximilian Hils1d95dea2015-08-17 19:27:20 +02003100
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003101 def test_memoryview_no_length(self):
3102 """
Alex Chanb7480992017-01-30 14:04:47 +00003103 `Connection.recv_into` can be passed a `memoryview` instance and data
3104 in the receive buffer is written to it.
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003105 """
3106 self._no_length_test(_make_memoryview)
Maximilian Hils1d95dea2015-08-17 19:27:20 +02003107
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003108 def test_memoryview_respects_length(self):
3109 """
Alex Chanb7480992017-01-30 14:04:47 +00003110 When called with a `memoryview` instance, `Connection.recv_into`
3111 respects the ``nbytes`` parameter and doesn't copy more than that
3112 number of bytes in.
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003113 """
3114 self._respects_length_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01003115
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003116 def test_memoryview_doesnt_overfill(self):
3117 """
Alex Chanb7480992017-01-30 14:04:47 +00003118 When called with a `memoryview` instance, `Connection.recv_into`
3119 respects the size of the array and doesn't write more bytes into it
3120 than will fit.
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003121 """
3122 self._doesnt_overfill_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01003123
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003124 def test_memoryview_really_doesnt_overfill(self):
3125 """
Alex Chanb7480992017-01-30 14:04:47 +00003126 When called with a `memoryview` instance and an `nbytes` value that is
3127 too large, `Connection.recv_into` respects the size of the array and
3128 not the `nbytes` value and doesn't write more bytes into the buffer
3129 than will fit.
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003130 """
3131 self._doesnt_overfill_test(_make_memoryview)
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003132
Cory Benfield62d10332014-06-15 10:03:41 +01003133
Alex Chanb7480992017-01-30 14:04:47 +00003134class TestConnectionSendall(object):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003135 """
Alex Chanb7480992017-01-30 14:04:47 +00003136 Tests for `Connection.sendall`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003137 """
Alex Gaynor03737182020-07-23 20:40:46 -04003138
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003139 def test_wrong_args(self):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003140 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003141 When called with arguments other than a string argument for its first
Alex Chanb7480992017-01-30 14:04:47 +00003142 parameter, `Connection.sendall` raises `TypeError`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003143 """
Paul Kehrer688538c2020-08-03 19:18:15 -05003144 connection = Connection(Context(SSLv23_METHOD), None)
Alex Chanb7480992017-01-30 14:04:47 +00003145 with pytest.raises(TypeError):
3146 connection.sendall(object())
Daniel Holth079c9632019-11-17 22:45:52 -05003147 with pytest.raises(TypeError):
3148 connection.sendall([1, 2, 3])
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003149
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003150 def test_short(self):
3151 """
Alex Chanb7480992017-01-30 14:04:47 +00003152 `Connection.sendall` transmits all of the bytes in the string
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003153 passed to it.
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003154 """
Alex Chanb7480992017-01-30 14:04:47 +00003155 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04003156 server.sendall(b"x")
3157 assert client.recv(1) == b"x"
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003158
Abraham Martinef063482015-03-25 14:06:24 +00003159 def test_text(self):
3160 """
Alex Chanb7480992017-01-30 14:04:47 +00003161 `Connection.sendall` transmits all the content in the string passed
3162 to it, raising a DeprecationWarning in case of this being a text.
Abraham Martinef063482015-03-25 14:06:24 +00003163 """
Alex Chanb7480992017-01-30 14:04:47 +00003164 server, client = loopback()
3165 with pytest.warns(DeprecationWarning) as w:
Abraham Martinef063482015-03-25 14:06:24 +00003166 simplefilter("always")
Jean-Paul Calderone8dc37a12015-03-29 08:16:52 -04003167 server.sendall(b"x".decode("ascii"))
Alex Gaynor03737182020-07-23 20:40:46 -04003168 assert "{0} for buf is no longer accepted, use bytes".format(
3169 WARNING_TYPE_EXPECTED
3170 ) == str(w[-1].message)
Alex Chanb7480992017-01-30 14:04:47 +00003171 assert client.recv(1) == b"x"
Abraham Martinef063482015-03-25 14:06:24 +00003172
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003173 def test_short_memoryview(self):
3174 """
3175 When passed a memoryview onto a small number of bytes,
Alex Chanb7480992017-01-30 14:04:47 +00003176 `Connection.sendall` transmits all of them.
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003177 """
Alex Chanb7480992017-01-30 14:04:47 +00003178 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04003179 server.sendall(memoryview(b"x"))
3180 assert client.recv(1) == b"x"
Abraham Martinef063482015-03-25 14:06:24 +00003181
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003182 @skip_if_py3
3183 def test_short_buffers(self):
3184 """
3185 When passed a buffer containing a small number of bytes,
Alex Chanb7480992017-01-30 14:04:47 +00003186 `Connection.sendall` transmits all of them.
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003187 """
Alex Chanb7480992017-01-30 14:04:47 +00003188 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04003189 count = server.sendall(buffer(b"xy")) # noqa: F821
Daniel Holth079c9632019-11-17 22:45:52 -05003190 assert count == 2
Alex Gaynor03737182020-07-23 20:40:46 -04003191 assert client.recv(2) == b"xy"
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02003192
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003193 def test_long(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003194 """
Alex Chanb7480992017-01-30 14:04:47 +00003195 `Connection.sendall` transmits all the bytes in the string passed to it
3196 even if this requires multiple calls of an underlying write function.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003197 """
Alex Chanb7480992017-01-30 14:04:47 +00003198 server, client = loopback()
Jean-Paul Calderone6241c702010-09-16 19:59:24 -04003199 # Should be enough, underlying SSL_write should only do 16k at a time.
Hynek Schlawack35618382015-09-05 21:54:25 +02003200 # On Windows, after 32k of bytes the write will block (forever
3201 # - because no one is yet reading).
Alex Gaynor03737182020-07-23 20:40:46 -04003202 message = b"x" * (1024 * 32 - 1) + b"y"
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003203 server.sendall(message)
3204 accum = []
3205 received = 0
3206 while received < len(message):
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04003207 data = client.recv(1024)
3208 accum.append(data)
3209 received += len(data)
Alex Gaynor03737182020-07-23 20:40:46 -04003210 assert message == b"".join(accum)
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003211
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003212 def test_closed(self):
3213 """
Alex Chanb7480992017-01-30 14:04:47 +00003214 If the underlying socket is closed, `Connection.sendall` propagates the
3215 write error from the low level write call.
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003216 """
Alex Chanb7480992017-01-30 14:04:47 +00003217 server, client = loopback()
Jean-Paul Calderone05d43e82010-09-24 18:01:36 -04003218 server.sock_shutdown(2)
Alex Chanb7480992017-01-30 14:04:47 +00003219 with pytest.raises(SysCallError) as err:
3220 server.sendall(b"hello, world")
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +02003221 if platform == "win32":
Alex Chanb7480992017-01-30 14:04:47 +00003222 assert err.value.args[0] == ESHUTDOWN
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +02003223 else:
Alex Chanb7480992017-01-30 14:04:47 +00003224 assert err.value.args[0] == EPIPE
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003225
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003226
Alex Chanb7480992017-01-30 14:04:47 +00003227class TestConnectionRenegotiate(object):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003228 """
3229 Tests for SSL renegotiation APIs.
3230 """
Alex Gaynor03737182020-07-23 20:40:46 -04003231
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003232 def test_total_renegotiations(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003233 """
Alex Chanb7480992017-01-30 14:04:47 +00003234 `Connection.total_renegotiations` returns `0` before any renegotiations
3235 have happened.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003236 """
Paul Kehrer688538c2020-08-03 19:18:15 -05003237 connection = Connection(Context(SSLv23_METHOD), None)
Alex Chanb7480992017-01-30 14:04:47 +00003238 assert connection.total_renegotiations() == 0
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003239
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003240 def test_renegotiate(self):
3241 """
3242 Go through a complete renegotiation cycle.
3243 """
Paul Kehrer7d5a3bf2019-01-21 12:24:02 -06003244 server, client = loopback(
3245 lambda s: loopback_server_factory(s, TLSv1_2_METHOD),
3246 lambda s: loopback_client_factory(s, TLSv1_2_METHOD),
3247 )
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003248
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003249 server.send(b"hello world")
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003250
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003251 assert b"hello world" == client.recv(len(b"hello world"))
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003252
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003253 assert 0 == server.total_renegotiations()
3254 assert False is server.renegotiate_pending()
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003255
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003256 assert True is server.renegotiate()
3257
3258 assert True is server.renegotiate_pending()
3259
3260 server.setblocking(False)
3261 client.setblocking(False)
3262
3263 client.do_handshake()
3264 server.do_handshake()
3265
3266 assert 1 == server.total_renegotiations()
3267 while False is server.renegotiate_pending():
3268 pass
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003269
3270
Alex Chanb7480992017-01-30 14:04:47 +00003271class TestError(object):
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003272 """
Alex Chanb7480992017-01-30 14:04:47 +00003273 Unit tests for `OpenSSL.SSL.Error`.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003274 """
Alex Gaynor03737182020-07-23 20:40:46 -04003275
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003276 def test_type(self):
3277 """
Alex Chanb7480992017-01-30 14:04:47 +00003278 `Error` is an exception type.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003279 """
Alex Chanb7480992017-01-30 14:04:47 +00003280 assert issubclass(Error, Exception)
Alex Gaynor03737182020-07-23 20:40:46 -04003281 assert Error.__name__ == "Error"
Rick Deane15b1472009-07-09 15:53:42 -05003282
3283
Alex Chanb7480992017-01-30 14:04:47 +00003284class TestConstants(object):
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003285 """
Alex Chanb7480992017-01-30 14:04:47 +00003286 Tests for the values of constants exposed in `OpenSSL.SSL`.
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003287
3288 These are values defined by OpenSSL intended only to be used as flags to
3289 OpenSSL APIs. The only assertions it seems can be made about them is
3290 their values.
3291 """
Alex Gaynor03737182020-07-23 20:40:46 -04003292
Hynek Schlawack35618382015-09-05 21:54:25 +02003293 @pytest.mark.skipif(
3294 OP_NO_QUERY_MTU is None,
Alex Gaynor03737182020-07-23 20:40:46 -04003295 reason="OP_NO_QUERY_MTU unavailable - OpenSSL version may be too old",
Hynek Schlawack35618382015-09-05 21:54:25 +02003296 )
3297 def test_op_no_query_mtu(self):
3298 """
Alex Chanb7480992017-01-30 14:04:47 +00003299 The value of `OpenSSL.SSL.OP_NO_QUERY_MTU` is 0x1000, the value
3300 of `SSL_OP_NO_QUERY_MTU` defined by `openssl/ssl.h`.
Hynek Schlawack35618382015-09-05 21:54:25 +02003301 """
Alex Chanb7480992017-01-30 14:04:47 +00003302 assert OP_NO_QUERY_MTU == 0x1000
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003303
Hynek Schlawack35618382015-09-05 21:54:25 +02003304 @pytest.mark.skipif(
3305 OP_COOKIE_EXCHANGE is None,
3306 reason="OP_COOKIE_EXCHANGE unavailable - "
Alex Gaynor03737182020-07-23 20:40:46 -04003307 "OpenSSL version may be too old",
Hynek Schlawack35618382015-09-05 21:54:25 +02003308 )
3309 def test_op_cookie_exchange(self):
3310 """
Alex Chanb7480992017-01-30 14:04:47 +00003311 The value of `OpenSSL.SSL.OP_COOKIE_EXCHANGE` is 0x2000, the
3312 value of `SSL_OP_COOKIE_EXCHANGE` defined by `openssl/ssl.h`.
Hynek Schlawack35618382015-09-05 21:54:25 +02003313 """
Alex Chanb7480992017-01-30 14:04:47 +00003314 assert OP_COOKIE_EXCHANGE == 0x2000
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003315
Hynek Schlawack35618382015-09-05 21:54:25 +02003316 @pytest.mark.skipif(
3317 OP_NO_TICKET is None,
Alex Gaynor03737182020-07-23 20:40:46 -04003318 reason="OP_NO_TICKET unavailable - OpenSSL version may be too old",
Hynek Schlawack35618382015-09-05 21:54:25 +02003319 )
3320 def test_op_no_ticket(self):
3321 """
Alex Chanb7480992017-01-30 14:04:47 +00003322 The value of `OpenSSL.SSL.OP_NO_TICKET` is 0x4000, the value of
3323 `SSL_OP_NO_TICKET` defined by `openssl/ssl.h`.
Hynek Schlawack35618382015-09-05 21:54:25 +02003324 """
Alex Chanb7480992017-01-30 14:04:47 +00003325 assert OP_NO_TICKET == 0x4000
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003326
Hynek Schlawack35618382015-09-05 21:54:25 +02003327 @pytest.mark.skipif(
3328 OP_NO_COMPRESSION is None,
Alex Gaynor03737182020-07-23 20:40:46 -04003329 reason=(
3330 "OP_NO_COMPRESSION unavailable - OpenSSL version may be too old"
3331 ),
Hynek Schlawack35618382015-09-05 21:54:25 +02003332 )
3333 def test_op_no_compression(self):
3334 """
Alex Chanb7480992017-01-30 14:04:47 +00003335 The value of `OpenSSL.SSL.OP_NO_COMPRESSION` is 0x20000, the
3336 value of `SSL_OP_NO_COMPRESSION` defined by `openssl/ssl.h`.
Hynek Schlawack35618382015-09-05 21:54:25 +02003337 """
Alex Chanb7480992017-01-30 14:04:47 +00003338 assert OP_NO_COMPRESSION == 0x20000
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04003339
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003340 def test_sess_cache_off(self):
3341 """
Alex Chanb7480992017-01-30 14:04:47 +00003342 The value of `OpenSSL.SSL.SESS_CACHE_OFF` 0x0, the value of
3343 `SSL_SESS_CACHE_OFF` defined by `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003344 """
Alex Chanb7480992017-01-30 14:04:47 +00003345 assert 0x0 == SESS_CACHE_OFF
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003346
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003347 def test_sess_cache_client(self):
3348 """
Alex Chanb7480992017-01-30 14:04:47 +00003349 The value of `OpenSSL.SSL.SESS_CACHE_CLIENT` 0x1, the value of
3350 `SSL_SESS_CACHE_CLIENT` defined by `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003351 """
Alex Chanb7480992017-01-30 14:04:47 +00003352 assert 0x1 == SESS_CACHE_CLIENT
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003353
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003354 def test_sess_cache_server(self):
3355 """
Alex Chanb7480992017-01-30 14:04:47 +00003356 The value of `OpenSSL.SSL.SESS_CACHE_SERVER` 0x2, the value of
3357 `SSL_SESS_CACHE_SERVER` defined by `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003358 """
Alex Chanb7480992017-01-30 14:04:47 +00003359 assert 0x2 == SESS_CACHE_SERVER
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003360
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003361 def test_sess_cache_both(self):
3362 """
Alex Chanb7480992017-01-30 14:04:47 +00003363 The value of `OpenSSL.SSL.SESS_CACHE_BOTH` 0x3, the value of
3364 `SSL_SESS_CACHE_BOTH` defined by `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003365 """
Alex Chanb7480992017-01-30 14:04:47 +00003366 assert 0x3 == SESS_CACHE_BOTH
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003367
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003368 def test_sess_cache_no_auto_clear(self):
3369 """
Alex Chanb7480992017-01-30 14:04:47 +00003370 The value of `OpenSSL.SSL.SESS_CACHE_NO_AUTO_CLEAR` 0x80, the
3371 value of `SSL_SESS_CACHE_NO_AUTO_CLEAR` defined by
3372 `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003373 """
Alex Chanb7480992017-01-30 14:04:47 +00003374 assert 0x80 == SESS_CACHE_NO_AUTO_CLEAR
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003375
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003376 def test_sess_cache_no_internal_lookup(self):
3377 """
Alex Chanb7480992017-01-30 14:04:47 +00003378 The value of `OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_LOOKUP` 0x100,
3379 the value of `SSL_SESS_CACHE_NO_INTERNAL_LOOKUP` defined by
3380 `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003381 """
Alex Chanb7480992017-01-30 14:04:47 +00003382 assert 0x100 == SESS_CACHE_NO_INTERNAL_LOOKUP
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003383
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003384 def test_sess_cache_no_internal_store(self):
3385 """
Alex Chanb7480992017-01-30 14:04:47 +00003386 The value of `OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_STORE` 0x200,
3387 the value of `SSL_SESS_CACHE_NO_INTERNAL_STORE` defined by
3388 `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003389 """
Alex Chanb7480992017-01-30 14:04:47 +00003390 assert 0x200 == SESS_CACHE_NO_INTERNAL_STORE
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003391
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003392 def test_sess_cache_no_internal(self):
3393 """
Alex Chanb7480992017-01-30 14:04:47 +00003394 The value of `OpenSSL.SSL.SESS_CACHE_NO_INTERNAL` 0x300, the
3395 value of `SSL_SESS_CACHE_NO_INTERNAL` defined by
3396 `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003397 """
Alex Chanb7480992017-01-30 14:04:47 +00003398 assert 0x300 == SESS_CACHE_NO_INTERNAL
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003399
3400
Alex Chanb7480992017-01-30 14:04:47 +00003401class TestMemoryBIO(object):
Rick Deanb71c0d22009-04-01 14:09:23 -05003402 """
Alex Chanb7480992017-01-30 14:04:47 +00003403 Tests for `OpenSSL.SSL.Connection` using a memory BIO.
Rick Deanb71c0d22009-04-01 14:09:23 -05003404 """
Alex Gaynor03737182020-07-23 20:40:46 -04003405
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003406 def _server(self, sock):
3407 """
Alex Chanb7480992017-01-30 14:04:47 +00003408 Create a new server-side SSL `Connection` object wrapped around `sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003409 """
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003410 # Create the server side Connection. This is mostly setup boilerplate
3411 # - use TLSv1, use a particular certificate, etc.
Paul Kehrer688538c2020-08-03 19:18:15 -05003412 server_ctx = Context(SSLv23_METHOD)
Alex Gaynor43307782015-09-04 09:05:45 -04003413 server_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE)
Hynek Schlawack35618382015-09-05 21:54:25 +02003414 server_ctx.set_verify(
3415 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT | VERIFY_CLIENT_ONCE,
Alex Gaynor03737182020-07-23 20:40:46 -04003416 verify_cb,
Hynek Schlawack35618382015-09-05 21:54:25 +02003417 )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003418 server_store = server_ctx.get_cert_store()
Hynek Schlawack35618382015-09-05 21:54:25 +02003419 server_ctx.use_privatekey(
Alex Gaynor03737182020-07-23 20:40:46 -04003420 load_privatekey(FILETYPE_PEM, server_key_pem)
3421 )
Hynek Schlawack35618382015-09-05 21:54:25 +02003422 server_ctx.use_certificate(
Alex Gaynor03737182020-07-23 20:40:46 -04003423 load_certificate(FILETYPE_PEM, server_cert_pem)
3424 )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003425 server_ctx.check_privatekey()
3426 server_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Hynek Schlawack35618382015-09-05 21:54:25 +02003427 # Here the Connection is actually created. If None is passed as the
3428 # 2nd parameter, it indicates a memory BIO should be created.
Rick Deanb1ccd562009-07-09 23:52:39 -05003429 server_conn = Connection(server_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003430 server_conn.set_accept_state()
3431 return server_conn
3432
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003433 def _client(self, sock):
3434 """
Alex Chanb7480992017-01-30 14:04:47 +00003435 Create a new client-side SSL `Connection` object wrapped around `sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003436 """
3437 # Now create the client side Connection. Similar boilerplate to the
3438 # above.
Paul Kehrer688538c2020-08-03 19:18:15 -05003439 client_ctx = Context(SSLv23_METHOD)
Alex Gaynor43307782015-09-04 09:05:45 -04003440 client_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE)
Hynek Schlawack35618382015-09-05 21:54:25 +02003441 client_ctx.set_verify(
3442 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT | VERIFY_CLIENT_ONCE,
Alex Gaynor03737182020-07-23 20:40:46 -04003443 verify_cb,
Hynek Schlawack35618382015-09-05 21:54:25 +02003444 )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003445 client_store = client_ctx.get_cert_store()
Hynek Schlawack35618382015-09-05 21:54:25 +02003446 client_ctx.use_privatekey(
Alex Gaynor03737182020-07-23 20:40:46 -04003447 load_privatekey(FILETYPE_PEM, client_key_pem)
3448 )
Hynek Schlawack35618382015-09-05 21:54:25 +02003449 client_ctx.use_certificate(
Alex Gaynor03737182020-07-23 20:40:46 -04003450 load_certificate(FILETYPE_PEM, client_cert_pem)
3451 )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003452 client_ctx.check_privatekey()
3453 client_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05003454 client_conn = Connection(client_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003455 client_conn.set_connect_state()
3456 return client_conn
3457
Alex Chanb7480992017-01-30 14:04:47 +00003458 def test_memory_connect(self):
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003459 """
Alex Chanb7480992017-01-30 14:04:47 +00003460 Two `Connection`s which use memory BIOs can be manually connected by
3461 reading from the output of each and writing those bytes to the input of
3462 the other and in this way establish a connection and exchange
3463 application-level bytes with each other.
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003464 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003465 server_conn = self._server(None)
3466 client_conn = self._client(None)
Rick Deanb71c0d22009-04-01 14:09:23 -05003467
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003468 # There should be no key or nonces yet.
Alex Chanb7480992017-01-30 14:04:47 +00003469 assert server_conn.master_key() is None
3470 assert server_conn.client_random() is None
3471 assert server_conn.server_random() is None
Rick Deanb71c0d22009-04-01 14:09:23 -05003472
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003473 # First, the handshake needs to happen. We'll deliver bytes back and
3474 # forth between the client and server until neither of them feels like
3475 # speaking any more.
Alex Chanb7480992017-01-30 14:04:47 +00003476 assert interact_in_memory(client_conn, server_conn) is None
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003477
3478 # Now that the handshake is done, there should be a key and nonces.
Alex Chanb7480992017-01-30 14:04:47 +00003479 assert server_conn.master_key() is not None
3480 assert server_conn.client_random() is not None
3481 assert server_conn.server_random() is not None
3482 assert server_conn.client_random() == client_conn.client_random()
3483 assert server_conn.server_random() == client_conn.server_random()
3484 assert server_conn.client_random() != server_conn.server_random()
3485 assert client_conn.client_random() != client_conn.server_random()
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003486
Paul Kehrerbdb76392017-12-01 04:54:32 +08003487 # Export key material for other uses.
Alex Gaynor03737182020-07-23 20:40:46 -04003488 cekm = client_conn.export_keying_material(b"LABEL", 32)
3489 sekm = server_conn.export_keying_material(b"LABEL", 32)
Paul Kehrerbdb76392017-12-01 04:54:32 +08003490 assert cekm is not None
3491 assert sekm is not None
3492 assert cekm == sekm
3493 assert len(sekm) == 32
3494
3495 # Export key material for other uses with additional context.
Alex Gaynor03737182020-07-23 20:40:46 -04003496 cekmc = client_conn.export_keying_material(b"LABEL", 32, b"CONTEXT")
3497 sekmc = server_conn.export_keying_material(b"LABEL", 32, b"CONTEXT")
Paul Kehrerbdb76392017-12-01 04:54:32 +08003498 assert cekmc is not None
3499 assert sekmc is not None
3500 assert cekmc == sekmc
3501 assert cekmc != cekm
3502 assert sekmc != sekm
3503 # Export with alternate label
Alex Gaynor03737182020-07-23 20:40:46 -04003504 cekmt = client_conn.export_keying_material(b"test", 32, b"CONTEXT")
3505 sekmt = server_conn.export_keying_material(b"test", 32, b"CONTEXT")
Paul Kehrerbdb76392017-12-01 04:54:32 +08003506 assert cekmc != cekmt
3507 assert sekmc != sekmt
3508
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003509 # Here are the bytes we'll try to send.
Alex Gaynor03737182020-07-23 20:40:46 -04003510 important_message = b"One if by land, two if by sea."
Rick Deanb71c0d22009-04-01 14:09:23 -05003511
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003512 server_conn.write(important_message)
Alex Gaynor03737182020-07-23 20:40:46 -04003513 assert interact_in_memory(client_conn, server_conn) == (
3514 client_conn,
3515 important_message,
3516 )
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003517
3518 client_conn.write(important_message[::-1])
Alex Gaynor03737182020-07-23 20:40:46 -04003519 assert interact_in_memory(client_conn, server_conn) == (
3520 server_conn,
3521 important_message[::-1],
3522 )
Rick Deanb71c0d22009-04-01 14:09:23 -05003523
Alex Chanb7480992017-01-30 14:04:47 +00003524 def test_socket_connect(self):
Rick Deanb1ccd562009-07-09 23:52:39 -05003525 """
Alex Chanb7480992017-01-30 14:04:47 +00003526 Just like `test_memory_connect` but with an actual socket.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003527
Hynek Schlawack35618382015-09-05 21:54:25 +02003528 This is primarily to rule out the memory BIO code as the source of any
Alex Chanb7480992017-01-30 14:04:47 +00003529 problems encountered while passing data over a `Connection` (if
Hynek Schlawack35618382015-09-05 21:54:25 +02003530 this test fails, there must be a problem outside the memory BIO code,
3531 as no memory BIO is involved here). Even though this isn't a memory
3532 BIO test, it's convenient to have it here.
Rick Deanb1ccd562009-07-09 23:52:39 -05003533 """
Alex Chanb7480992017-01-30 14:04:47 +00003534 server_conn, client_conn = loopback()
Rick Deanb1ccd562009-07-09 23:52:39 -05003535
Alex Gaynore7f51982016-09-11 11:48:14 -04003536 important_message = b"Help me Obi Wan Kenobi, you're my only hope."
Rick Deanb1ccd562009-07-09 23:52:39 -05003537 client_conn.send(important_message)
3538 msg = server_conn.recv(1024)
Alex Chanb7480992017-01-30 14:04:47 +00003539 assert msg == important_message
Rick Deanb1ccd562009-07-09 23:52:39 -05003540
3541 # Again in the other direction, just for fun.
3542 important_message = important_message[::-1]
3543 server_conn.send(important_message)
3544 msg = client_conn.recv(1024)
Alex Chanb7480992017-01-30 14:04:47 +00003545 assert msg == important_message
Rick Deanb1ccd562009-07-09 23:52:39 -05003546
Alex Chanb7480992017-01-30 14:04:47 +00003547 def test_socket_overrides_memory(self):
Rick Deanb71c0d22009-04-01 14:09:23 -05003548 """
Alex Chanb7480992017-01-30 14:04:47 +00003549 Test that `OpenSSL.SSL.bio_read` and `OpenSSL.SSL.bio_write` don't
3550 work on `OpenSSL.SSL.Connection`() that use sockets.
Rick Deanb71c0d22009-04-01 14:09:23 -05003551 """
Paul Kehrer688538c2020-08-03 19:18:15 -05003552 context = Context(SSLv23_METHOD)
David Benjamin1fbe0642019-04-15 17:05:13 -05003553 client = socket_any_family()
Rick Deanb71c0d22009-04-01 14:09:23 -05003554 clientSSL = Connection(context, client)
Alex Chanb7480992017-01-30 14:04:47 +00003555 with pytest.raises(TypeError):
3556 clientSSL.bio_read(100)
3557 with pytest.raises(TypeError):
Paul Kehrerc45a6ea2020-08-03 15:54:20 -05003558 clientSSL.bio_write(b"foo")
Alex Chanb7480992017-01-30 14:04:47 +00003559 with pytest.raises(TypeError):
3560 clientSSL.bio_shutdown()
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003561
Alex Chanb7480992017-01-30 14:04:47 +00003562 def test_outgoing_overflow(self):
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003563 """
3564 If more bytes than can be written to the memory BIO are passed to
Alex Chanb7480992017-01-30 14:04:47 +00003565 `Connection.send` at once, the number of bytes which were written is
3566 returned and that many bytes from the beginning of the input can be
3567 read from the other end of the connection.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003568 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003569 server = self._server(None)
3570 client = self._client(None)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003571
Alex Chanb7480992017-01-30 14:04:47 +00003572 interact_in_memory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003573
3574 size = 2 ** 15
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003575 sent = client.send(b"x" * size)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003576 # Sanity check. We're trying to test what happens when the entire
3577 # input can't be sent. If the entire input was sent, this test is
3578 # meaningless.
Alex Chanb7480992017-01-30 14:04:47 +00003579 assert sent < size
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003580
Alex Chanb7480992017-01-30 14:04:47 +00003581 receiver, received = interact_in_memory(client, server)
3582 assert receiver is server
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003583
3584 # We can rely on all of these bytes being received at once because
Alex Chanb7480992017-01-30 14:04:47 +00003585 # loopback passes 2 ** 16 to recv - more than 2 ** 15.
3586 assert len(received) == sent
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003587
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003588 def test_shutdown(self):
3589 """
Alex Chanb7480992017-01-30 14:04:47 +00003590 `Connection.bio_shutdown` signals the end of the data stream
3591 from which the `Connection` reads.
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003592 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003593 server = self._server(None)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003594 server.bio_shutdown()
Alex Chanb7480992017-01-30 14:04:47 +00003595 with pytest.raises(Error) as err:
3596 server.recv(1024)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003597 # We don't want WantReadError or ZeroReturnError or anything - it's a
3598 # handshake failure.
Alex Chanb7480992017-01-30 14:04:47 +00003599 assert type(err.value) in [Error, SysCallError]
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003600
Alex Chanb7480992017-01-30 14:04:47 +00003601 def test_unexpected_EOF(self):
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003602 """
3603 If the connection is lost before an orderly SSL shutdown occurs,
Alex Chanb7480992017-01-30 14:04:47 +00003604 `OpenSSL.SSL.SysCallError` is raised with a message of
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003605 "Unexpected EOF".
3606 """
Alex Chanb7480992017-01-30 14:04:47 +00003607 server_conn, client_conn = loopback()
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003608 client_conn.sock_shutdown(SHUT_RDWR)
Alex Chanb7480992017-01-30 14:04:47 +00003609 with pytest.raises(SysCallError) as err:
3610 server_conn.recv(1024)
3611 assert err.value.args == (-1, "Unexpected EOF")
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003612
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003613 def _check_client_ca_list(self, func):
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003614 """
Alex Chanb7480992017-01-30 14:04:47 +00003615 Verify the return value of the `get_client_ca_list` method for
Hynek Schlawack35618382015-09-05 21:54:25 +02003616 server and client connections.
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003617
Jonathan Ballet78b92a22011-07-16 08:07:26 +09003618 :param func: A function which will be called with the server context
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003619 before the client and server are connected to each other. This
3620 function should specify a list of CAs for the server to send to the
3621 client and return that same list. The list will be used to verify
Alex Chanb7480992017-01-30 14:04:47 +00003622 that `get_client_ca_list` returns the proper value at
Hynek Schlawack35618382015-09-05 21:54:25 +02003623 various times.
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003624 """
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003625 server = self._server(None)
3626 client = self._client(None)
Alex Chanb7480992017-01-30 14:04:47 +00003627 assert client.get_client_ca_list() == []
3628 assert server.get_client_ca_list() == []
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003629 ctx = server.get_context()
3630 expected = func(ctx)
Alex Chanb7480992017-01-30 14:04:47 +00003631 assert client.get_client_ca_list() == []
3632 assert server.get_client_ca_list() == expected
3633 interact_in_memory(client, server)
3634 assert client.get_client_ca_list() == expected
3635 assert server.get_client_ca_list() == expected
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003636
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003637 def test_set_client_ca_list_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003638 """
Alex Chanb7480992017-01-30 14:04:47 +00003639 `Context.set_client_ca_list` raises a `TypeError` if called with a
3640 non-list or a list that contains objects other than X509Names.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003641 """
Paul Kehrer688538c2020-08-03 19:18:15 -05003642 ctx = Context(SSLv23_METHOD)
Alex Chanb7480992017-01-30 14:04:47 +00003643 with pytest.raises(TypeError):
3644 ctx.set_client_ca_list("spam")
3645 with pytest.raises(TypeError):
3646 ctx.set_client_ca_list(["spam"])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003647
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003648 def test_set_empty_ca_list(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003649 """
Alex Chanb7480992017-01-30 14:04:47 +00003650 If passed an empty list, `Context.set_client_ca_list` configures the
3651 context to send no CA names to the client and, on both the server and
3652 client sides, `Connection.get_client_ca_list` returns an empty list
3653 after the connection is set up.
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003654 """
Alex Gaynor03737182020-07-23 20:40:46 -04003655
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003656 def no_ca(ctx):
3657 ctx.set_client_ca_list([])
3658 return []
Alex Gaynor03737182020-07-23 20:40:46 -04003659
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003660 self._check_client_ca_list(no_ca)
3661
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003662 def test_set_one_ca_list(self):
3663 """
3664 If passed a list containing a single X509Name,
Alex Chanb7480992017-01-30 14:04:47 +00003665 `Context.set_client_ca_list` configures the context to send
Hynek Schlawack35618382015-09-05 21:54:25 +02003666 that CA name to the client and, on both the server and client sides,
Alex Chanb7480992017-01-30 14:04:47 +00003667 `Connection.get_client_ca_list` returns a list containing that
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003668 X509Name after the connection is set up.
3669 """
3670 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3671 cadesc = cacert.get_subject()
Hynek Schlawack35618382015-09-05 21:54:25 +02003672
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003673 def single_ca(ctx):
3674 ctx.set_client_ca_list([cadesc])
3675 return [cadesc]
Alex Gaynor03737182020-07-23 20:40:46 -04003676
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003677 self._check_client_ca_list(single_ca)
3678
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003679 def test_set_multiple_ca_list(self):
3680 """
3681 If passed a list containing multiple X509Name objects,
Alex Chanb7480992017-01-30 14:04:47 +00003682 `Context.set_client_ca_list` configures the context to send
Hynek Schlawack35618382015-09-05 21:54:25 +02003683 those CA names to the client and, on both the server and client sides,
Alex Chanb7480992017-01-30 14:04:47 +00003684 `Connection.get_client_ca_list` returns a list containing those
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003685 X509Names after the connection is set up.
3686 """
3687 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3688 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3689
3690 sedesc = secert.get_subject()
3691 cldesc = clcert.get_subject()
3692
3693 def multiple_ca(ctx):
3694 L = [sedesc, cldesc]
3695 ctx.set_client_ca_list(L)
3696 return L
Alex Gaynor03737182020-07-23 20:40:46 -04003697
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003698 self._check_client_ca_list(multiple_ca)
3699
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003700 def test_reset_ca_list(self):
3701 """
3702 If called multiple times, only the X509Names passed to the final call
Alex Chanb7480992017-01-30 14:04:47 +00003703 of `Context.set_client_ca_list` are used to configure the CA
Hynek Schlawack35618382015-09-05 21:54:25 +02003704 names sent to the client.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003705 """
3706 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3707 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3708 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3709
3710 cadesc = cacert.get_subject()
3711 sedesc = secert.get_subject()
3712 cldesc = clcert.get_subject()
3713
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003714 def changed_ca(ctx):
3715 ctx.set_client_ca_list([sedesc, cldesc])
3716 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003717 return [cadesc]
Alex Gaynor03737182020-07-23 20:40:46 -04003718
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003719 self._check_client_ca_list(changed_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003720
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003721 def test_mutated_ca_list(self):
3722 """
Alex Chanb7480992017-01-30 14:04:47 +00003723 If the list passed to `Context.set_client_ca_list` is mutated
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003724 afterwards, this does not affect the list of CA names sent to the
3725 client.
3726 """
3727 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3728 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3729
3730 cadesc = cacert.get_subject()
3731 sedesc = secert.get_subject()
3732
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003733 def mutated_ca(ctx):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003734 L = [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003735 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003736 L.append(sedesc)
3737 return [cadesc]
Alex Gaynor03737182020-07-23 20:40:46 -04003738
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003739 self._check_client_ca_list(mutated_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003740
Alex Chanb7480992017-01-30 14:04:47 +00003741 def test_add_client_ca_wrong_args(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003742 """
Alex Chanb7480992017-01-30 14:04:47 +00003743 `Context.add_client_ca` raises `TypeError` if called with
3744 a non-X509 object.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003745 """
Paul Kehrer688538c2020-08-03 19:18:15 -05003746 ctx = Context(SSLv23_METHOD)
Alex Chanb7480992017-01-30 14:04:47 +00003747 with pytest.raises(TypeError):
3748 ctx.add_client_ca("spam")
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003749
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003750 def test_one_add_client_ca(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003751 """
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003752 A certificate's subject can be added as a CA to be sent to the client
Alex Chanb7480992017-01-30 14:04:47 +00003753 with `Context.add_client_ca`.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003754 """
3755 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3756 cadesc = cacert.get_subject()
Hynek Schlawack35618382015-09-05 21:54:25 +02003757
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003758 def single_ca(ctx):
3759 ctx.add_client_ca(cacert)
3760 return [cadesc]
Alex Gaynor03737182020-07-23 20:40:46 -04003761
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003762 self._check_client_ca_list(single_ca)
3763
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003764 def test_multiple_add_client_ca(self):
3765 """
3766 Multiple CA names can be sent to the client by calling
Alex Chanb7480992017-01-30 14:04:47 +00003767 `Context.add_client_ca` with multiple X509 objects.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003768 """
3769 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3770 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3771
3772 cadesc = cacert.get_subject()
3773 sedesc = secert.get_subject()
3774
3775 def multiple_ca(ctx):
3776 ctx.add_client_ca(cacert)
3777 ctx.add_client_ca(secert)
3778 return [cadesc, sedesc]
Alex Gaynor03737182020-07-23 20:40:46 -04003779
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003780 self._check_client_ca_list(multiple_ca)
3781
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003782 def test_set_and_add_client_ca(self):
3783 """
Alex Chanb7480992017-01-30 14:04:47 +00003784 A call to `Context.set_client_ca_list` followed by a call to
3785 `Context.add_client_ca` results in using the CA names from the
Hynek Schlawack35618382015-09-05 21:54:25 +02003786 first call and the CA name from the second call.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003787 """
3788 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3789 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3790 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3791
3792 cadesc = cacert.get_subject()
3793 sedesc = secert.get_subject()
3794 cldesc = clcert.get_subject()
3795
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003796 def mixed_set_add_ca(ctx):
3797 ctx.set_client_ca_list([cadesc, sedesc])
3798 ctx.add_client_ca(clcert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003799 return [cadesc, sedesc, cldesc]
Alex Gaynor03737182020-07-23 20:40:46 -04003800
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003801 self._check_client_ca_list(mixed_set_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003802
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003803 def test_set_after_add_client_ca(self):
3804 """
Alex Chanb7480992017-01-30 14:04:47 +00003805 A call to `Context.set_client_ca_list` after a call to
3806 `Context.add_client_ca` replaces the CA name specified by the
Hynek Schlawack35618382015-09-05 21:54:25 +02003807 former call with the names specified by the latter call.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003808 """
3809 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3810 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3811 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3812
3813 cadesc = cacert.get_subject()
3814 sedesc = secert.get_subject()
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003815
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003816 def set_replaces_add_ca(ctx):
3817 ctx.add_client_ca(clcert)
3818 ctx.set_client_ca_list([cadesc])
3819 ctx.add_client_ca(secert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003820 return [cadesc, sedesc]
Alex Gaynor03737182020-07-23 20:40:46 -04003821
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003822 self._check_client_ca_list(set_replaces_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003823
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003824
Alex Chanb7480992017-01-30 14:04:47 +00003825class TestInfoConstants(object):
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003826 """
3827 Tests for assorted constants exposed for use in info callbacks.
3828 """
Alex Gaynor03737182020-07-23 20:40:46 -04003829
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003830 def test_integers(self):
3831 """
3832 All of the info constants are integers.
3833
3834 This is a very weak test. It would be nice to have one that actually
3835 verifies that as certain info events happen, the value passed to the
3836 info callback matches up with the constant exposed by OpenSSL.SSL.
3837 """
3838 for const in [
Alex Gaynor03737182020-07-23 20:40:46 -04003839 SSL_ST_CONNECT,
3840 SSL_ST_ACCEPT,
3841 SSL_ST_MASK,
3842 SSL_CB_LOOP,
3843 SSL_CB_EXIT,
3844 SSL_CB_READ,
3845 SSL_CB_WRITE,
3846 SSL_CB_ALERT,
3847 SSL_CB_READ_ALERT,
3848 SSL_CB_WRITE_ALERT,
3849 SSL_CB_ACCEPT_LOOP,
3850 SSL_CB_ACCEPT_EXIT,
3851 SSL_CB_CONNECT_LOOP,
3852 SSL_CB_CONNECT_EXIT,
3853 SSL_CB_HANDSHAKE_START,
3854 SSL_CB_HANDSHAKE_DONE,
Hynek Schlawack35618382015-09-05 21:54:25 +02003855 ]:
Alex Gaynor5af32d02016-09-24 01:52:21 -04003856 assert isinstance(const, int)
3857
3858 # These constants don't exist on OpenSSL 1.1.0
3859 for const in [
Alex Gaynor03737182020-07-23 20:40:46 -04003860 SSL_ST_INIT,
3861 SSL_ST_BEFORE,
3862 SSL_ST_OK,
3863 SSL_ST_RENEGOTIATE,
Alex Gaynor5af32d02016-09-24 01:52:21 -04003864 ]:
3865 assert const is None or isinstance(const, int)
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003866
Ziga Seilnacht44611bf2009-08-31 20:49:30 +02003867
Cory Benfield1d142142016-03-30 11:51:45 +01003868class TestRequires(object):
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003869 """
3870 Tests for the decorator factory used to conditionally raise
Cory Benfield1d142142016-03-30 11:51:45 +01003871 NotImplementedError when older OpenSSLs are used.
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003872 """
Alex Gaynor03737182020-07-23 20:40:46 -04003873
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003874 def test_available(self):
3875 """
3876 When the OpenSSL functionality is available the decorated functions
3877 work appropriately.
3878 """
3879 feature_guard = _make_requires(True, "Error text")
3880 results = []
3881
3882 @feature_guard
3883 def inner():
3884 results.append(True)
3885 return True
3886
Cory Benfield2333e5e2016-03-30 14:24:16 +01003887 assert inner() is True
3888 assert [True] == results
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003889
3890 def test_unavailable(self):
3891 """
3892 When the OpenSSL functionality is not available the decorated function
3893 does not execute and NotImplementedError is raised.
3894 """
3895 feature_guard = _make_requires(False, "Error text")
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003896
3897 @feature_guard
Alex Chanfb078d82017-04-20 11:16:15 +01003898 def inner(): # pragma: nocover
3899 pytest.fail("Should not be called")
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003900
Cory Benfield1d142142016-03-30 11:51:45 +01003901 with pytest.raises(NotImplementedError) as e:
3902 inner()
3903
3904 assert "Error text" in str(e.value)
Cory Benfield496652a2017-01-24 11:42:56 +00003905
3906
Alex Chanb7480992017-01-30 14:04:47 +00003907class TestOCSP(object):
Cory Benfield496652a2017-01-24 11:42:56 +00003908 """
3909 Tests for PyOpenSSL's OCSP stapling support.
3910 """
Alex Gaynor03737182020-07-23 20:40:46 -04003911
Cory Benfield496652a2017-01-24 11:42:56 +00003912 sample_ocsp_data = b"this is totally ocsp data"
3913
3914 def _client_connection(self, callback, data, request_ocsp=True):
3915 """
3916 Builds a client connection suitable for using OCSP.
3917
3918 :param callback: The callback to register for OCSP.
3919 :param data: The opaque data object that will be handed to the
3920 OCSP callback.
3921 :param request_ocsp: Whether the client will actually ask for OCSP
3922 stapling. Useful for testing only.
3923 """
3924 ctx = Context(SSLv23_METHOD)
3925 ctx.set_ocsp_client_callback(callback, data)
3926 client = Connection(ctx)
3927
3928 if request_ocsp:
3929 client.request_ocsp()
3930
3931 client.set_connect_state()
3932 return client
3933
3934 def _server_connection(self, callback, data):
3935 """
3936 Builds a server connection suitable for using OCSP.
3937
3938 :param callback: The callback to register for OCSP.
3939 :param data: The opaque data object that will be handed to the
3940 OCSP callback.
3941 """
3942 ctx = Context(SSLv23_METHOD)
3943 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
3944 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
3945 ctx.set_ocsp_server_callback(callback, data)
3946 server = Connection(ctx)
3947 server.set_accept_state()
3948 return server
3949
3950 def test_callbacks_arent_called_by_default(self):
3951 """
3952 If both the client and the server have registered OCSP callbacks, but
3953 the client does not send the OCSP request, neither callback gets
3954 called.
3955 """
Alex Gaynor03737182020-07-23 20:40:46 -04003956
Alex Chanfb078d82017-04-20 11:16:15 +01003957 def ocsp_callback(*args, **kwargs): # pragma: nocover
3958 pytest.fail("Should not be called")
Cory Benfield496652a2017-01-24 11:42:56 +00003959
3960 client = self._client_connection(
3961 callback=ocsp_callback, data=None, request_ocsp=False
3962 )
3963 server = self._server_connection(callback=ocsp_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00003964 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003965
Cory Benfield496652a2017-01-24 11:42:56 +00003966 def test_client_negotiates_without_server(self):
3967 """
3968 If the client wants to do OCSP but the server does not, the handshake
3969 succeeds, and the client callback fires with an empty byte string.
3970 """
3971 called = []
3972
3973 def ocsp_callback(conn, ocsp_data, ignored):
3974 called.append(ocsp_data)
3975 return True
3976
3977 client = self._client_connection(callback=ocsp_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00003978 server = loopback_server_factory(socket=None)
3979 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003980
3981 assert len(called) == 1
Alex Gaynor03737182020-07-23 20:40:46 -04003982 assert called[0] == b""
Cory Benfield496652a2017-01-24 11:42:56 +00003983
3984 def test_client_receives_servers_data(self):
3985 """
3986 The data the server sends in its callback is received by the client.
3987 """
3988 calls = []
3989
3990 def server_callback(*args, **kwargs):
3991 return self.sample_ocsp_data
3992
3993 def client_callback(conn, ocsp_data, ignored):
3994 calls.append(ocsp_data)
3995 return True
3996
3997 client = self._client_connection(callback=client_callback, data=None)
3998 server = self._server_connection(callback=server_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00003999 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00004000
4001 assert len(calls) == 1
4002 assert calls[0] == self.sample_ocsp_data
4003
4004 def test_callbacks_are_invoked_with_connections(self):
4005 """
4006 The first arguments to both callbacks are their respective connections.
4007 """
4008 client_calls = []
4009 server_calls = []
4010
4011 def client_callback(conn, *args, **kwargs):
4012 client_calls.append(conn)
4013 return True
4014
4015 def server_callback(conn, *args, **kwargs):
4016 server_calls.append(conn)
4017 return self.sample_ocsp_data
4018
4019 client = self._client_connection(callback=client_callback, data=None)
4020 server = self._server_connection(callback=server_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00004021 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00004022
4023 assert len(client_calls) == 1
4024 assert len(server_calls) == 1
4025 assert client_calls[0] is client
4026 assert server_calls[0] is server
4027
4028 def test_opaque_data_is_passed_through(self):
4029 """
4030 Both callbacks receive an opaque, user-provided piece of data in their
4031 callbacks as the final argument.
4032 """
4033 calls = []
4034
4035 def server_callback(*args):
4036 calls.append(args)
4037 return self.sample_ocsp_data
4038
4039 def client_callback(*args):
4040 calls.append(args)
4041 return True
4042
4043 sentinel = object()
4044
4045 client = self._client_connection(
4046 callback=client_callback, data=sentinel
4047 )
4048 server = self._server_connection(
4049 callback=server_callback, data=sentinel
4050 )
Alex Chanb7480992017-01-30 14:04:47 +00004051 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00004052
4053 assert len(calls) == 2
4054 assert calls[0][-1] is sentinel
4055 assert calls[1][-1] is sentinel
4056
4057 def test_server_returns_empty_string(self):
4058 """
4059 If the server returns an empty bytestring from its callback, the
4060 client callback is called with the empty bytestring.
4061 """
4062 client_calls = []
4063
4064 def server_callback(*args):
Alex Gaynor03737182020-07-23 20:40:46 -04004065 return b""
Cory Benfield496652a2017-01-24 11:42:56 +00004066
4067 def client_callback(conn, ocsp_data, ignored):
4068 client_calls.append(ocsp_data)
4069 return True
4070
4071 client = self._client_connection(callback=client_callback, data=None)
4072 server = self._server_connection(callback=server_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00004073 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00004074
4075 assert len(client_calls) == 1
Alex Gaynor03737182020-07-23 20:40:46 -04004076 assert client_calls[0] == b""
Cory Benfield496652a2017-01-24 11:42:56 +00004077
4078 def test_client_returns_false_terminates_handshake(self):
4079 """
4080 If the client returns False from its callback, the handshake fails.
4081 """
Alex Gaynor03737182020-07-23 20:40:46 -04004082
Cory Benfield496652a2017-01-24 11:42:56 +00004083 def server_callback(*args):
4084 return self.sample_ocsp_data
4085
4086 def client_callback(*args):
4087 return False
4088
4089 client = self._client_connection(callback=client_callback, data=None)
4090 server = self._server_connection(callback=server_callback, data=None)
4091
4092 with pytest.raises(Error):
Alex Chanb7480992017-01-30 14:04:47 +00004093 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00004094
4095 def test_exceptions_in_client_bubble_up(self):
4096 """
4097 The callbacks thrown in the client callback bubble up to the caller.
4098 """
Alex Gaynor03737182020-07-23 20:40:46 -04004099
Cory Benfield496652a2017-01-24 11:42:56 +00004100 class SentinelException(Exception):
4101 pass
4102
4103 def server_callback(*args):
4104 return self.sample_ocsp_data
4105
4106 def client_callback(*args):
4107 raise SentinelException()
4108
4109 client = self._client_connection(callback=client_callback, data=None)
4110 server = self._server_connection(callback=server_callback, data=None)
4111
4112 with pytest.raises(SentinelException):
Alex Chanb7480992017-01-30 14:04:47 +00004113 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00004114
4115 def test_exceptions_in_server_bubble_up(self):
4116 """
4117 The callbacks thrown in the server callback bubble up to the caller.
4118 """
Alex Gaynor03737182020-07-23 20:40:46 -04004119
Cory Benfield496652a2017-01-24 11:42:56 +00004120 class SentinelException(Exception):
4121 pass
4122
4123 def server_callback(*args):
4124 raise SentinelException()
4125
Alex Chanfb078d82017-04-20 11:16:15 +01004126 def client_callback(*args): # pragma: nocover
Cory Benfield496652a2017-01-24 11:42:56 +00004127 pytest.fail("Should not be called")
4128
4129 client = self._client_connection(callback=client_callback, data=None)
4130 server = self._server_connection(callback=server_callback, data=None)
4131
4132 with pytest.raises(SentinelException):
Alex Chanb7480992017-01-30 14:04:47 +00004133 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00004134
4135 def test_server_must_return_bytes(self):
4136 """
4137 The server callback must return a bytestring, or a TypeError is thrown.
4138 """
Alex Gaynor03737182020-07-23 20:40:46 -04004139
Cory Benfield496652a2017-01-24 11:42:56 +00004140 def server_callback(*args):
Alex Gaynor03737182020-07-23 20:40:46 -04004141 return self.sample_ocsp_data.decode("ascii")
Cory Benfield496652a2017-01-24 11:42:56 +00004142
Alex Chanfb078d82017-04-20 11:16:15 +01004143 def client_callback(*args): # pragma: nocover
Cory Benfield496652a2017-01-24 11:42:56 +00004144 pytest.fail("Should not be called")
4145
4146 client = self._client_connection(callback=client_callback, data=None)
4147 server = self._server_connection(callback=server_callback, data=None)
4148
4149 with pytest.raises(TypeError):
Alex Chanb7480992017-01-30 14:04:47 +00004150 handshake_in_memory(client, server)