blob: e405b1a12fbc9d664a375b306c3d8b2f9fd7c1a7 [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 Gaynor5af32d02016-09-24 01:52:21 -04002624 # Make this work on both OpenSSL 1.0.0, which doesn't support TLSv1.2
2625 # and also on OpenSSL 1.1.0 which doesn't support SSLv3. (SSL_ST_INIT
2626 # is a way to check for 1.1.0)
Alex Gaynoraa32e712017-06-29 20:56:12 -07002627 if SSL_ST_INIT is None:
2628 v1 = TLSv1_2_METHOD
2629 v2 = TLSv1_METHOD
2630 elif hasattr(_lib, "SSLv3_method"):
Alex Gaynor5af32d02016-09-24 01:52:21 -04002631 v1 = TLSv1_METHOD
2632 v2 = SSLv3_METHOD
2633 else:
Alex Gaynoraa32e712017-06-29 20:56:12 -07002634 pytest.skip("Test requires either OpenSSL 1.1.0 or SSLv3")
Alex Gaynor5af32d02016-09-24 01:52:21 -04002635
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002636 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2637 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
Alex Gaynor5af32d02016-09-24 01:52:21 -04002638 ctx = Context(v1)
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002639 ctx.use_privatekey(key)
2640 ctx.use_certificate(cert)
Paul Kehrerc45a6ea2020-08-03 15:54:20 -05002641 ctx.set_session_id(b"unity-test")
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002642
2643 def makeServer(socket):
2644 server = Connection(ctx, socket)
2645 server.set_accept_state()
2646 return server
2647
Alex Gaynor5af32d02016-09-24 01:52:21 -04002648 def makeOriginalClient(socket):
2649 client = Connection(Context(v1), socket)
2650 client.set_connect_state()
2651 return client
2652
Alex Chan1c0cb662017-01-30 07:13:30 +00002653 originalServer, originalClient = loopback(
Alex Gaynor03737182020-07-23 20:40:46 -04002654 server_factory=makeServer, client_factory=makeOriginalClient
2655 )
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002656 originalSession = originalClient.get_session()
2657
2658 def makeClient(socket):
2659 # Intentionally use a different, incompatible method here.
Alex Gaynor5af32d02016-09-24 01:52:21 -04002660 client = Connection(Context(v2), socket)
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002661 client.set_connect_state()
2662 client.set_session(originalSession)
2663 return client
2664
Alex Chan1c0cb662017-01-30 07:13:30 +00002665 with pytest.raises(Error):
2666 loopback(client_factory=makeClient, server_factory=makeServer)
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002667
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002668 def test_wantWriteError(self):
2669 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002670 `Connection` methods which generate output raise
2671 `OpenSSL.SSL.WantWriteError` if writing to the connection's BIO
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002672 fail indicating a should-write state.
2673 """
2674 client_socket, server_socket = socket_pair()
2675 # Fill up the client's send buffer so Connection won't be able to write
Jean-Paul Calderonebbff8b92014-03-22 14:20:30 -04002676 # anything. Only write a single byte at a time so we can be sure we
2677 # completely fill the buffer. Even though the socket API is allowed to
2678 # signal a short write via its return value it seems this doesn't
2679 # always happen on all platforms (FreeBSD and OS X particular) for the
2680 # very last bit of available buffer space.
2681 msg = b"x"
caternb2777a42018-08-09 15:38:13 -04002682 for i in range(1024 * 1024 * 64):
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002683 try:
2684 client_socket.send(msg)
2685 except error as e:
2686 if e.errno == EWOULDBLOCK:
2687 break
2688 raise
2689 else:
Alex Chan1c0cb662017-01-30 07:13:30 +00002690 pytest.fail(
Alex Gaynor03737182020-07-23 20:40:46 -04002691 "Failed to fill socket buffer, cannot test BIO want write"
2692 )
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002693
Paul Kehrer688538c2020-08-03 19:18:15 -05002694 ctx = Context(SSLv23_METHOD)
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002695 conn = Connection(ctx, client_socket)
2696 # Client's speak first, so make it an SSL client
2697 conn.set_connect_state()
Alex Chan1c0cb662017-01-30 07:13:30 +00002698 with pytest.raises(WantWriteError):
2699 conn.do_handshake()
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002700
2701 # XXX want_read
2702
Fedor Brunner416f4a12014-03-28 13:18:38 +01002703 def test_get_finished_before_connect(self):
Fedor Brunner5747b932014-03-05 14:22:34 +01002704 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002705 `Connection.get_finished` returns `None` before TLS handshake
2706 is completed.
Fedor Brunner5747b932014-03-05 14:22:34 +01002707 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002708 ctx = Context(SSLv23_METHOD)
Fedor Brunner5747b932014-03-05 14:22:34 +01002709 connection = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002710 assert connection.get_finished() is None
Fedor Brunner416f4a12014-03-28 13:18:38 +01002711
2712 def test_get_peer_finished_before_connect(self):
2713 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002714 `Connection.get_peer_finished` returns `None` before TLS handshake
2715 is completed.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002716 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002717 ctx = Context(SSLv23_METHOD)
Fedor Brunner416f4a12014-03-28 13:18:38 +01002718 connection = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002719 assert connection.get_peer_finished() is None
Fedor Brunner5747b932014-03-05 14:22:34 +01002720
Fedor Brunner416f4a12014-03-28 13:18:38 +01002721 def test_get_finished(self):
2722 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002723 `Connection.get_finished` method returns the TLS Finished message send
2724 from client, or server. Finished messages are send during
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002725 TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002726 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002727 server, client = loopback()
Fedor Brunner416f4a12014-03-28 13:18:38 +01002728
Alex Chan1c0cb662017-01-30 07:13:30 +00002729 assert server.get_finished() is not None
2730 assert len(server.get_finished()) > 0
Fedor Brunner416f4a12014-03-28 13:18:38 +01002731
2732 def test_get_peer_finished(self):
2733 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002734 `Connection.get_peer_finished` method returns the TLS Finished
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002735 message received from client, or server. Finished messages are send
2736 during TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002737 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002738 server, client = loopback()
Fedor Brunner416f4a12014-03-28 13:18:38 +01002739
Alex Chan1c0cb662017-01-30 07:13:30 +00002740 assert server.get_peer_finished() is not None
2741 assert len(server.get_peer_finished()) > 0
Fedor Brunner5747b932014-03-05 14:22:34 +01002742
Fedor Brunner416f4a12014-03-28 13:18:38 +01002743 def test_tls_finished_message_symmetry(self):
2744 """
Hynek Schlawackdddd1112015-09-05 21:12:30 +02002745 The TLS Finished message send by server must be the TLS Finished
2746 message received by client.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002747
Hynek Schlawackdddd1112015-09-05 21:12:30 +02002748 The TLS Finished message send by client must be the TLS Finished
2749 message received by server.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002750 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002751 server, client = loopback()
Fedor Brunner416f4a12014-03-28 13:18:38 +01002752
Alex Chan1c0cb662017-01-30 07:13:30 +00002753 assert server.get_finished() == client.get_peer_finished()
2754 assert client.get_finished() == server.get_peer_finished()
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002755
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002756 def test_get_cipher_name_before_connect(self):
2757 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002758 `Connection.get_cipher_name` returns `None` if no connection
2759 has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002760 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002761 ctx = Context(SSLv23_METHOD)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002762 conn = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002763 assert conn.get_cipher_name() is None
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002764
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002765 def test_get_cipher_name(self):
2766 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002767 `Connection.get_cipher_name` returns a `unicode` string giving the
2768 name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002769 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002770 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04002771 server_cipher_name, client_cipher_name = (
2772 server.get_cipher_name(),
2773 client.get_cipher_name(),
2774 )
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002775
Alex Chan1c0cb662017-01-30 07:13:30 +00002776 assert isinstance(server_cipher_name, text_type)
2777 assert isinstance(client_cipher_name, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002778
Alex Chan1c0cb662017-01-30 07:13:30 +00002779 assert server_cipher_name == client_cipher_name
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002780
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002781 def test_get_cipher_version_before_connect(self):
2782 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002783 `Connection.get_cipher_version` returns `None` if no connection
2784 has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002785 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002786 ctx = Context(SSLv23_METHOD)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002787 conn = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002788 assert conn.get_cipher_version() is None
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002789
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002790 def test_get_cipher_version(self):
2791 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002792 `Connection.get_cipher_version` returns a `unicode` string giving
2793 the protocol name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002794 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002795 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04002796 server_cipher_version, client_cipher_version = (
2797 server.get_cipher_version(),
2798 client.get_cipher_version(),
2799 )
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002800
Alex Chan1c0cb662017-01-30 07:13:30 +00002801 assert isinstance(server_cipher_version, text_type)
2802 assert isinstance(client_cipher_version, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002803
Alex Chan1c0cb662017-01-30 07:13:30 +00002804 assert server_cipher_version == client_cipher_version
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002805
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002806 def test_get_cipher_bits_before_connect(self):
2807 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002808 `Connection.get_cipher_bits` returns `None` if no connection has
2809 been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002810 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002811 ctx = Context(SSLv23_METHOD)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002812 conn = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002813 assert conn.get_cipher_bits() is None
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002814
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002815 def test_get_cipher_bits(self):
2816 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002817 `Connection.get_cipher_bits` returns the number of secret bits
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002818 of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002819 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002820 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04002821 server_cipher_bits, client_cipher_bits = (
2822 server.get_cipher_bits(),
2823 client.get_cipher_bits(),
2824 )
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002825
Alex Chan1c0cb662017-01-30 07:13:30 +00002826 assert isinstance(server_cipher_bits, int)
2827 assert isinstance(client_cipher_bits, int)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002828
Alex Chan1c0cb662017-01-30 07:13:30 +00002829 assert server_cipher_bits == client_cipher_bits
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002830
Jim Shaverabff1882015-05-27 09:15:55 -04002831 def test_get_protocol_version_name(self):
2832 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002833 `Connection.get_protocol_version_name()` returns a string giving the
2834 protocol version of the current connection.
Jim Shaverabff1882015-05-27 09:15:55 -04002835 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002836 server, client = loopback()
Jim Shaverabff1882015-05-27 09:15:55 -04002837 client_protocol_version_name = client.get_protocol_version_name()
2838 server_protocol_version_name = server.get_protocol_version_name()
2839
Alex Chan1c0cb662017-01-30 07:13:30 +00002840 assert isinstance(server_protocol_version_name, text_type)
2841 assert isinstance(client_protocol_version_name, text_type)
Jim Shaverabff1882015-05-27 09:15:55 -04002842
Alex Chan1c0cb662017-01-30 07:13:30 +00002843 assert server_protocol_version_name == client_protocol_version_name
Jim Shaverabff1882015-05-27 09:15:55 -04002844
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002845 def test_get_protocol_version(self):
2846 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002847 `Connection.get_protocol_version()` returns an integer
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002848 giving the protocol version of the current connection.
2849 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002850 server, client = loopback()
Jim Shaver85a4dff2015-04-27 17:42:46 -04002851 client_protocol_version = client.get_protocol_version()
2852 server_protocol_version = server.get_protocol_version()
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002853
Alex Chan1c0cb662017-01-30 07:13:30 +00002854 assert isinstance(server_protocol_version, int)
2855 assert isinstance(client_protocol_version, int)
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002856
Alex Chan1c0cb662017-01-30 07:13:30 +00002857 assert server_protocol_version == client_protocol_version
2858
2859 def test_wantReadError(self):
2860 """
2861 `Connection.bio_read` raises `OpenSSL.SSL.WantReadError` if there are
2862 no bytes available to be read from the BIO.
2863 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002864 ctx = Context(SSLv23_METHOD)
Alex Chan1c0cb662017-01-30 07:13:30 +00002865 conn = Connection(ctx, None)
2866 with pytest.raises(WantReadError):
2867 conn.bio_read(1024)
2868
Alex Gaynor03737182020-07-23 20:40:46 -04002869 @pytest.mark.parametrize("bufsize", [1.0, None, object(), "bufsize"])
Alex Chanfb078d82017-04-20 11:16:15 +01002870 def test_bio_read_wrong_args(self, bufsize):
2871 """
2872 `Connection.bio_read` raises `TypeError` if passed a non-integer
2873 argument.
2874 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002875 ctx = Context(SSLv23_METHOD)
Alex Chanfb078d82017-04-20 11:16:15 +01002876 conn = Connection(ctx, None)
2877 with pytest.raises(TypeError):
2878 conn.bio_read(bufsize)
2879
Alex Chan1c0cb662017-01-30 07:13:30 +00002880 def test_buffer_size(self):
2881 """
2882 `Connection.bio_read` accepts an integer giving the maximum number
2883 of bytes to read and return.
2884 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002885 ctx = Context(SSLv23_METHOD)
Alex Chan1c0cb662017-01-30 07:13:30 +00002886 conn = Connection(ctx, None)
2887 conn.set_connect_state()
2888 try:
2889 conn.do_handshake()
2890 except WantReadError:
2891 pass
2892 data = conn.bio_read(2)
2893 assert 2 == len(data)
2894
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002895
Alex Chanb7480992017-01-30 14:04:47 +00002896class TestConnectionGetCipherList(object):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002897 """
Alex Chanb7480992017-01-30 14:04:47 +00002898 Tests for `Connection.get_cipher_list`.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002899 """
Alex Gaynor03737182020-07-23 20:40:46 -04002900
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002901 def test_result(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002902 """
Alex Chanb7480992017-01-30 14:04:47 +00002903 `Connection.get_cipher_list` returns a list of `bytes` giving the
2904 names of the ciphers which might be used.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002905 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002906 connection = Connection(Context(SSLv23_METHOD), None)
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002907 ciphers = connection.get_cipher_list()
Alex Chanb7480992017-01-30 14:04:47 +00002908 assert isinstance(ciphers, list)
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002909 for cipher in ciphers:
Alex Chanb7480992017-01-30 14:04:47 +00002910 assert isinstance(cipher, str)
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002911
2912
Maximilian Hils868dc3c2017-02-10 14:56:55 +01002913class VeryLarge(bytes):
2914 """
2915 Mock object so that we don't have to allocate 2**31 bytes
2916 """
Alex Gaynor03737182020-07-23 20:40:46 -04002917
Maximilian Hils868dc3c2017-02-10 14:56:55 +01002918 def __len__(self):
Alex Gaynor03737182020-07-23 20:40:46 -04002919 return 2 ** 31
Maximilian Hils868dc3c2017-02-10 14:56:55 +01002920
2921
Alex Chanb7480992017-01-30 14:04:47 +00002922class TestConnectionSend(object):
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002923 """
Alex Chanb7480992017-01-30 14:04:47 +00002924 Tests for `Connection.send`.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002925 """
Alex Gaynor03737182020-07-23 20:40:46 -04002926
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002927 def test_wrong_args(self):
2928 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002929 When called with arguments other than string argument for its first
Alex Chanb7480992017-01-30 14:04:47 +00002930 parameter, `Connection.send` raises `TypeError`.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002931 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002932 connection = Connection(Context(SSLv23_METHOD), None)
Alex Chanb7480992017-01-30 14:04:47 +00002933 with pytest.raises(TypeError):
2934 connection.send(object())
Daniel Holth079c9632019-11-17 22:45:52 -05002935 with pytest.raises(TypeError):
2936 connection.send([1, 2, 3])
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002937
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002938 def test_short_bytes(self):
2939 """
Alex Chanb7480992017-01-30 14:04:47 +00002940 When passed a short byte string, `Connection.send` transmits all of it
2941 and returns the number of bytes sent.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002942 """
Alex Chanb7480992017-01-30 14:04:47 +00002943 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04002944 count = server.send(b"xy")
Alex Chanb7480992017-01-30 14:04:47 +00002945 assert count == 2
Alex Gaynor03737182020-07-23 20:40:46 -04002946 assert client.recv(2) == b"xy"
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002947
Abraham Martinef063482015-03-25 14:06:24 +00002948 def test_text(self):
2949 """
Alex Chanb7480992017-01-30 14:04:47 +00002950 When passed a text, `Connection.send` transmits all of it and
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002951 returns the number of bytes sent. It also raises a DeprecationWarning.
Abraham Martinef063482015-03-25 14:06:24 +00002952 """
Alex Chanb7480992017-01-30 14:04:47 +00002953 server, client = loopback()
2954 with pytest.warns(DeprecationWarning) as w:
Abraham Martinef063482015-03-25 14:06:24 +00002955 simplefilter("always")
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002956 count = server.send(b"xy".decode("ascii"))
Alex Gaynor03737182020-07-23 20:40:46 -04002957 assert "{0} for buf is no longer accepted, use bytes".format(
2958 WARNING_TYPE_EXPECTED
2959 ) == str(w[-1].message)
Alex Chanb7480992017-01-30 14:04:47 +00002960 assert count == 2
Alex Gaynor03737182020-07-23 20:40:46 -04002961 assert client.recv(2) == b"xy"
Abraham Martinef063482015-03-25 14:06:24 +00002962
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002963 def test_short_memoryview(self):
2964 """
2965 When passed a memoryview onto a small number of bytes,
Alex Chanb7480992017-01-30 14:04:47 +00002966 `Connection.send` transmits all of them and returns the number
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002967 of bytes sent.
2968 """
Alex Chanb7480992017-01-30 14:04:47 +00002969 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04002970 count = server.send(memoryview(b"xy"))
Alex Chanb7480992017-01-30 14:04:47 +00002971 assert count == 2
Alex Gaynor03737182020-07-23 20:40:46 -04002972 assert client.recv(2) == b"xy"
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002973
Daniel Holth079c9632019-11-17 22:45:52 -05002974 def test_short_bytearray(self):
2975 """
2976 When passed a short bytearray, `Connection.send` transmits all of
2977 it and returns the number of bytes sent.
2978 """
2979 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04002980 count = server.send(bytearray(b"xy"))
Daniel Holth079c9632019-11-17 22:45:52 -05002981 assert count == 2
Alex Gaynor03737182020-07-23 20:40:46 -04002982 assert client.recv(2) == b"xy"
Daniel Holth079c9632019-11-17 22:45:52 -05002983
Hynek Schlawack8e94f1b2015-09-05 21:31:00 +02002984 @skip_if_py3
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002985 def test_short_buffer(self):
2986 """
2987 When passed a buffer containing a small number of bytes,
Alex Chanb7480992017-01-30 14:04:47 +00002988 `Connection.send` transmits all of them and returns the number
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002989 of bytes sent.
2990 """
Alex Chanb7480992017-01-30 14:04:47 +00002991 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04002992 count = server.send(buffer(b"xy")) # noqa: F821
Alex Chanb7480992017-01-30 14:04:47 +00002993 assert count == 2
Alex Gaynor03737182020-07-23 20:40:46 -04002994 assert client.recv(2) == b"xy"
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02002995
Maximilian Hils868dc3c2017-02-10 14:56:55 +01002996 @pytest.mark.skipif(
Alex Gaynor03737182020-07-23 20:40:46 -04002997 sys.maxsize < 2 ** 31,
2998 reason="sys.maxsize < 2**31 - test requires 64 bit",
Maximilian Hils868dc3c2017-02-10 14:56:55 +01002999 )
3000 def test_buf_too_large(self):
3001 """
3002 When passed a buffer containing >= 2**31 bytes,
3003 `Connection.send` bails out as SSL_write only
3004 accepts an int for the buffer length.
3005 """
Paul Kehrer688538c2020-08-03 19:18:15 -05003006 connection = Connection(Context(SSLv23_METHOD), None)
Maximilian Hils868dc3c2017-02-10 14:56:55 +01003007 with pytest.raises(ValueError) as exc_info:
3008 connection.send(VeryLarge())
3009 exc_info.match(r"Cannot send more than .+ bytes at once")
3010
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05003011
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003012def _make_memoryview(size):
3013 """
3014 Create a new ``memoryview`` wrapped around a ``bytearray`` of the given
3015 size.
3016 """
3017 return memoryview(bytearray(size))
3018
3019
Alex Chanb7480992017-01-30 14:04:47 +00003020class TestConnectionRecvInto(object):
Cory Benfield62d10332014-06-15 10:03:41 +01003021 """
Alex Chanb7480992017-01-30 14:04:47 +00003022 Tests for `Connection.recv_into`.
Cory Benfield62d10332014-06-15 10:03:41 +01003023 """
Alex Gaynor03737182020-07-23 20:40:46 -04003024
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003025 def _no_length_test(self, factory):
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04003026 """
Alex Chanb7480992017-01-30 14:04:47 +00003027 Assert that when the given buffer is passed to `Connection.recv_into`,
3028 whatever bytes are available to be received that fit into that buffer
3029 are written into that buffer.
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04003030 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003031 output_buffer = factory(5)
3032
Alex Chanb7480992017-01-30 14:04:47 +00003033 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04003034 server.send(b"xy")
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04003035
Alex Chanb7480992017-01-30 14:04:47 +00003036 assert client.recv_into(output_buffer) == 2
Alex Gaynor03737182020-07-23 20:40:46 -04003037 assert output_buffer == bytearray(b"xy\x00\x00\x00")
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04003038
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04003039 def test_bytearray_no_length(self):
Cory Benfield62d10332014-06-15 10:03:41 +01003040 """
Alex Chanb7480992017-01-30 14:04:47 +00003041 `Connection.recv_into` can be passed a `bytearray` instance and data
3042 in the receive buffer is written to it.
Cory Benfield62d10332014-06-15 10:03:41 +01003043 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003044 self._no_length_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01003045
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003046 def _respects_length_test(self, factory):
Cory Benfield62d10332014-06-15 10:03:41 +01003047 """
Alex Chanb7480992017-01-30 14:04:47 +00003048 Assert that when the given buffer is passed to `Connection.recv_into`
3049 along with a value for `nbytes` that is less than the size of that
3050 buffer, only `nbytes` bytes are written into the buffer.
Cory Benfield62d10332014-06-15 10:03:41 +01003051 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003052 output_buffer = factory(10)
3053
Alex Chanb7480992017-01-30 14:04:47 +00003054 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04003055 server.send(b"abcdefghij")
Cory Benfield62d10332014-06-15 10:03:41 +01003056
Alex Chanb7480992017-01-30 14:04:47 +00003057 assert client.recv_into(output_buffer, 5) == 5
Alex Gaynor03737182020-07-23 20:40:46 -04003058 assert output_buffer == bytearray(b"abcde\x00\x00\x00\x00\x00")
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04003059
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04003060 def test_bytearray_respects_length(self):
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04003061 """
Alex Chanb7480992017-01-30 14:04:47 +00003062 When called with a `bytearray` instance, `Connection.recv_into`
3063 respects the `nbytes` parameter and doesn't copy in more than that
3064 number of bytes.
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04003065 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003066 self._respects_length_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01003067
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003068 def _doesnt_overfill_test(self, factory):
Cory Benfield62d10332014-06-15 10:03:41 +01003069 """
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04003070 Assert that if there are more bytes available to be read from the
3071 receive buffer than would fit into the buffer passed to
Alex Chanb7480992017-01-30 14:04:47 +00003072 `Connection.recv_into`, only as many as fit are written into it.
Cory Benfield62d10332014-06-15 10:03:41 +01003073 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003074 output_buffer = factory(5)
3075
Alex Chanb7480992017-01-30 14:04:47 +00003076 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04003077 server.send(b"abcdefghij")
Cory Benfield62d10332014-06-15 10:03:41 +01003078
Alex Chanb7480992017-01-30 14:04:47 +00003079 assert client.recv_into(output_buffer) == 5
Alex Gaynor03737182020-07-23 20:40:46 -04003080 assert output_buffer == bytearray(b"abcde")
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04003081 rest = client.recv(5)
Alex Gaynor03737182020-07-23 20:40:46 -04003082 assert b"fghij" == rest
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04003083
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04003084 def test_bytearray_doesnt_overfill(self):
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04003085 """
Alex Chanb7480992017-01-30 14:04:47 +00003086 When called with a `bytearray` instance, `Connection.recv_into`
3087 respects the size of the array and doesn't write more bytes into it
3088 than will fit.
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04003089 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003090 self._doesnt_overfill_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01003091
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04003092 def test_bytearray_really_doesnt_overfill(self):
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003093 """
Alex Chanb7480992017-01-30 14:04:47 +00003094 When called with a `bytearray` instance and an `nbytes` value that is
3095 too large, `Connection.recv_into` respects the size of the array and
3096 not the `nbytes` value and doesn't write more bytes into the buffer
3097 than will fit.
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003098 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003099 self._doesnt_overfill_test(bytearray)
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003100
Maximilian Hils1d95dea2015-08-17 19:27:20 +02003101 def test_peek(self):
Alex Chanb7480992017-01-30 14:04:47 +00003102 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04003103 server.send(b"xy")
Maximilian Hils1d95dea2015-08-17 19:27:20 +02003104
3105 for _ in range(2):
3106 output_buffer = bytearray(5)
Alex Chanb7480992017-01-30 14:04:47 +00003107 assert client.recv_into(output_buffer, flags=MSG_PEEK) == 2
Alex Gaynor03737182020-07-23 20:40:46 -04003108 assert output_buffer == bytearray(b"xy\x00\x00\x00")
Maximilian Hils1d95dea2015-08-17 19:27:20 +02003109
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003110 def test_memoryview_no_length(self):
3111 """
Alex Chanb7480992017-01-30 14:04:47 +00003112 `Connection.recv_into` can be passed a `memoryview` instance and data
3113 in the receive buffer is written to it.
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003114 """
3115 self._no_length_test(_make_memoryview)
Maximilian Hils1d95dea2015-08-17 19:27:20 +02003116
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003117 def test_memoryview_respects_length(self):
3118 """
Alex Chanb7480992017-01-30 14:04:47 +00003119 When called with a `memoryview` instance, `Connection.recv_into`
3120 respects the ``nbytes`` parameter and doesn't copy more than that
3121 number of bytes in.
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003122 """
3123 self._respects_length_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01003124
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003125 def test_memoryview_doesnt_overfill(self):
3126 """
Alex Chanb7480992017-01-30 14:04:47 +00003127 When called with a `memoryview` instance, `Connection.recv_into`
3128 respects the size of the array and doesn't write more bytes into it
3129 than will fit.
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003130 """
3131 self._doesnt_overfill_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01003132
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003133 def test_memoryview_really_doesnt_overfill(self):
3134 """
Alex Chanb7480992017-01-30 14:04:47 +00003135 When called with a `memoryview` instance and an `nbytes` value that is
3136 too large, `Connection.recv_into` respects the size of the array and
3137 not the `nbytes` value and doesn't write more bytes into the buffer
3138 than will fit.
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003139 """
3140 self._doesnt_overfill_test(_make_memoryview)
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003141
Cory Benfield62d10332014-06-15 10:03:41 +01003142
Alex Chanb7480992017-01-30 14:04:47 +00003143class TestConnectionSendall(object):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003144 """
Alex Chanb7480992017-01-30 14:04:47 +00003145 Tests for `Connection.sendall`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003146 """
Alex Gaynor03737182020-07-23 20:40:46 -04003147
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003148 def test_wrong_args(self):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003149 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003150 When called with arguments other than a string argument for its first
Alex Chanb7480992017-01-30 14:04:47 +00003151 parameter, `Connection.sendall` raises `TypeError`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003152 """
Paul Kehrer688538c2020-08-03 19:18:15 -05003153 connection = Connection(Context(SSLv23_METHOD), None)
Alex Chanb7480992017-01-30 14:04:47 +00003154 with pytest.raises(TypeError):
3155 connection.sendall(object())
Daniel Holth079c9632019-11-17 22:45:52 -05003156 with pytest.raises(TypeError):
3157 connection.sendall([1, 2, 3])
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003158
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003159 def test_short(self):
3160 """
Alex Chanb7480992017-01-30 14:04:47 +00003161 `Connection.sendall` transmits all of the bytes in the string
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003162 passed to it.
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003163 """
Alex Chanb7480992017-01-30 14:04:47 +00003164 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04003165 server.sendall(b"x")
3166 assert client.recv(1) == b"x"
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003167
Abraham Martinef063482015-03-25 14:06:24 +00003168 def test_text(self):
3169 """
Alex Chanb7480992017-01-30 14:04:47 +00003170 `Connection.sendall` transmits all the content in the string passed
3171 to it, raising a DeprecationWarning in case of this being a text.
Abraham Martinef063482015-03-25 14:06:24 +00003172 """
Alex Chanb7480992017-01-30 14:04:47 +00003173 server, client = loopback()
3174 with pytest.warns(DeprecationWarning) as w:
Abraham Martinef063482015-03-25 14:06:24 +00003175 simplefilter("always")
Jean-Paul Calderone8dc37a12015-03-29 08:16:52 -04003176 server.sendall(b"x".decode("ascii"))
Alex Gaynor03737182020-07-23 20:40:46 -04003177 assert "{0} for buf is no longer accepted, use bytes".format(
3178 WARNING_TYPE_EXPECTED
3179 ) == str(w[-1].message)
Alex Chanb7480992017-01-30 14:04:47 +00003180 assert client.recv(1) == b"x"
Abraham Martinef063482015-03-25 14:06:24 +00003181
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003182 def test_short_memoryview(self):
3183 """
3184 When passed a memoryview onto a small number of bytes,
Alex Chanb7480992017-01-30 14:04:47 +00003185 `Connection.sendall` transmits all of them.
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003186 """
Alex Chanb7480992017-01-30 14:04:47 +00003187 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04003188 server.sendall(memoryview(b"x"))
3189 assert client.recv(1) == b"x"
Abraham Martinef063482015-03-25 14:06:24 +00003190
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003191 @skip_if_py3
3192 def test_short_buffers(self):
3193 """
3194 When passed a buffer containing a small number of bytes,
Alex Chanb7480992017-01-30 14:04:47 +00003195 `Connection.sendall` transmits all of them.
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003196 """
Alex Chanb7480992017-01-30 14:04:47 +00003197 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04003198 count = server.sendall(buffer(b"xy")) # noqa: F821
Daniel Holth079c9632019-11-17 22:45:52 -05003199 assert count == 2
Alex Gaynor03737182020-07-23 20:40:46 -04003200 assert client.recv(2) == b"xy"
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02003201
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003202 def test_long(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003203 """
Alex Chanb7480992017-01-30 14:04:47 +00003204 `Connection.sendall` transmits all the bytes in the string passed to it
3205 even if this requires multiple calls of an underlying write function.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003206 """
Alex Chanb7480992017-01-30 14:04:47 +00003207 server, client = loopback()
Jean-Paul Calderone6241c702010-09-16 19:59:24 -04003208 # Should be enough, underlying SSL_write should only do 16k at a time.
Hynek Schlawack35618382015-09-05 21:54:25 +02003209 # On Windows, after 32k of bytes the write will block (forever
3210 # - because no one is yet reading).
Alex Gaynor03737182020-07-23 20:40:46 -04003211 message = b"x" * (1024 * 32 - 1) + b"y"
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003212 server.sendall(message)
3213 accum = []
3214 received = 0
3215 while received < len(message):
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04003216 data = client.recv(1024)
3217 accum.append(data)
3218 received += len(data)
Alex Gaynor03737182020-07-23 20:40:46 -04003219 assert message == b"".join(accum)
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003220
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003221 def test_closed(self):
3222 """
Alex Chanb7480992017-01-30 14:04:47 +00003223 If the underlying socket is closed, `Connection.sendall` propagates the
3224 write error from the low level write call.
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003225 """
Alex Chanb7480992017-01-30 14:04:47 +00003226 server, client = loopback()
Jean-Paul Calderone05d43e82010-09-24 18:01:36 -04003227 server.sock_shutdown(2)
Alex Chanb7480992017-01-30 14:04:47 +00003228 with pytest.raises(SysCallError) as err:
3229 server.sendall(b"hello, world")
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +02003230 if platform == "win32":
Alex Chanb7480992017-01-30 14:04:47 +00003231 assert err.value.args[0] == ESHUTDOWN
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +02003232 else:
Alex Chanb7480992017-01-30 14:04:47 +00003233 assert err.value.args[0] == EPIPE
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003234
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003235
Alex Chanb7480992017-01-30 14:04:47 +00003236class TestConnectionRenegotiate(object):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003237 """
3238 Tests for SSL renegotiation APIs.
3239 """
Alex Gaynor03737182020-07-23 20:40:46 -04003240
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003241 def test_total_renegotiations(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003242 """
Alex Chanb7480992017-01-30 14:04:47 +00003243 `Connection.total_renegotiations` returns `0` before any renegotiations
3244 have happened.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003245 """
Paul Kehrer688538c2020-08-03 19:18:15 -05003246 connection = Connection(Context(SSLv23_METHOD), None)
Alex Chanb7480992017-01-30 14:04:47 +00003247 assert connection.total_renegotiations() == 0
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003248
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003249 def test_renegotiate(self):
3250 """
3251 Go through a complete renegotiation cycle.
3252 """
Paul Kehrer7d5a3bf2019-01-21 12:24:02 -06003253 server, client = loopback(
3254 lambda s: loopback_server_factory(s, TLSv1_2_METHOD),
3255 lambda s: loopback_client_factory(s, TLSv1_2_METHOD),
3256 )
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003257
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003258 server.send(b"hello world")
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003259
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003260 assert b"hello world" == client.recv(len(b"hello world"))
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003261
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003262 assert 0 == server.total_renegotiations()
3263 assert False is server.renegotiate_pending()
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003264
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003265 assert True is server.renegotiate()
3266
3267 assert True is server.renegotiate_pending()
3268
3269 server.setblocking(False)
3270 client.setblocking(False)
3271
3272 client.do_handshake()
3273 server.do_handshake()
3274
3275 assert 1 == server.total_renegotiations()
3276 while False is server.renegotiate_pending():
3277 pass
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003278
3279
Alex Chanb7480992017-01-30 14:04:47 +00003280class TestError(object):
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003281 """
Alex Chanb7480992017-01-30 14:04:47 +00003282 Unit tests for `OpenSSL.SSL.Error`.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003283 """
Alex Gaynor03737182020-07-23 20:40:46 -04003284
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003285 def test_type(self):
3286 """
Alex Chanb7480992017-01-30 14:04:47 +00003287 `Error` is an exception type.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003288 """
Alex Chanb7480992017-01-30 14:04:47 +00003289 assert issubclass(Error, Exception)
Alex Gaynor03737182020-07-23 20:40:46 -04003290 assert Error.__name__ == "Error"
Rick Deane15b1472009-07-09 15:53:42 -05003291
3292
Alex Chanb7480992017-01-30 14:04:47 +00003293class TestConstants(object):
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003294 """
Alex Chanb7480992017-01-30 14:04:47 +00003295 Tests for the values of constants exposed in `OpenSSL.SSL`.
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003296
3297 These are values defined by OpenSSL intended only to be used as flags to
3298 OpenSSL APIs. The only assertions it seems can be made about them is
3299 their values.
3300 """
Alex Gaynor03737182020-07-23 20:40:46 -04003301
Hynek Schlawack35618382015-09-05 21:54:25 +02003302 @pytest.mark.skipif(
3303 OP_NO_QUERY_MTU is None,
Alex Gaynor03737182020-07-23 20:40:46 -04003304 reason="OP_NO_QUERY_MTU unavailable - OpenSSL version may be too old",
Hynek Schlawack35618382015-09-05 21:54:25 +02003305 )
3306 def test_op_no_query_mtu(self):
3307 """
Alex Chanb7480992017-01-30 14:04:47 +00003308 The value of `OpenSSL.SSL.OP_NO_QUERY_MTU` is 0x1000, the value
3309 of `SSL_OP_NO_QUERY_MTU` defined by `openssl/ssl.h`.
Hynek Schlawack35618382015-09-05 21:54:25 +02003310 """
Alex Chanb7480992017-01-30 14:04:47 +00003311 assert OP_NO_QUERY_MTU == 0x1000
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003312
Hynek Schlawack35618382015-09-05 21:54:25 +02003313 @pytest.mark.skipif(
3314 OP_COOKIE_EXCHANGE is None,
3315 reason="OP_COOKIE_EXCHANGE unavailable - "
Alex Gaynor03737182020-07-23 20:40:46 -04003316 "OpenSSL version may be too old",
Hynek Schlawack35618382015-09-05 21:54:25 +02003317 )
3318 def test_op_cookie_exchange(self):
3319 """
Alex Chanb7480992017-01-30 14:04:47 +00003320 The value of `OpenSSL.SSL.OP_COOKIE_EXCHANGE` is 0x2000, the
3321 value of `SSL_OP_COOKIE_EXCHANGE` defined by `openssl/ssl.h`.
Hynek Schlawack35618382015-09-05 21:54:25 +02003322 """
Alex Chanb7480992017-01-30 14:04:47 +00003323 assert OP_COOKIE_EXCHANGE == 0x2000
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003324
Hynek Schlawack35618382015-09-05 21:54:25 +02003325 @pytest.mark.skipif(
3326 OP_NO_TICKET is None,
Alex Gaynor03737182020-07-23 20:40:46 -04003327 reason="OP_NO_TICKET unavailable - OpenSSL version may be too old",
Hynek Schlawack35618382015-09-05 21:54:25 +02003328 )
3329 def test_op_no_ticket(self):
3330 """
Alex Chanb7480992017-01-30 14:04:47 +00003331 The value of `OpenSSL.SSL.OP_NO_TICKET` is 0x4000, the value of
3332 `SSL_OP_NO_TICKET` defined by `openssl/ssl.h`.
Hynek Schlawack35618382015-09-05 21:54:25 +02003333 """
Alex Chanb7480992017-01-30 14:04:47 +00003334 assert OP_NO_TICKET == 0x4000
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003335
Hynek Schlawack35618382015-09-05 21:54:25 +02003336 @pytest.mark.skipif(
3337 OP_NO_COMPRESSION is None,
Alex Gaynor03737182020-07-23 20:40:46 -04003338 reason=(
3339 "OP_NO_COMPRESSION unavailable - OpenSSL version may be too old"
3340 ),
Hynek Schlawack35618382015-09-05 21:54:25 +02003341 )
3342 def test_op_no_compression(self):
3343 """
Alex Chanb7480992017-01-30 14:04:47 +00003344 The value of `OpenSSL.SSL.OP_NO_COMPRESSION` is 0x20000, the
3345 value of `SSL_OP_NO_COMPRESSION` defined by `openssl/ssl.h`.
Hynek Schlawack35618382015-09-05 21:54:25 +02003346 """
Alex Chanb7480992017-01-30 14:04:47 +00003347 assert OP_NO_COMPRESSION == 0x20000
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04003348
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003349 def test_sess_cache_off(self):
3350 """
Alex Chanb7480992017-01-30 14:04:47 +00003351 The value of `OpenSSL.SSL.SESS_CACHE_OFF` 0x0, the value of
3352 `SSL_SESS_CACHE_OFF` defined by `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003353 """
Alex Chanb7480992017-01-30 14:04:47 +00003354 assert 0x0 == SESS_CACHE_OFF
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003355
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003356 def test_sess_cache_client(self):
3357 """
Alex Chanb7480992017-01-30 14:04:47 +00003358 The value of `OpenSSL.SSL.SESS_CACHE_CLIENT` 0x1, the value of
3359 `SSL_SESS_CACHE_CLIENT` defined by `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003360 """
Alex Chanb7480992017-01-30 14:04:47 +00003361 assert 0x1 == SESS_CACHE_CLIENT
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003362
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003363 def test_sess_cache_server(self):
3364 """
Alex Chanb7480992017-01-30 14:04:47 +00003365 The value of `OpenSSL.SSL.SESS_CACHE_SERVER` 0x2, the value of
3366 `SSL_SESS_CACHE_SERVER` defined by `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003367 """
Alex Chanb7480992017-01-30 14:04:47 +00003368 assert 0x2 == SESS_CACHE_SERVER
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003369
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003370 def test_sess_cache_both(self):
3371 """
Alex Chanb7480992017-01-30 14:04:47 +00003372 The value of `OpenSSL.SSL.SESS_CACHE_BOTH` 0x3, the value of
3373 `SSL_SESS_CACHE_BOTH` defined by `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003374 """
Alex Chanb7480992017-01-30 14:04:47 +00003375 assert 0x3 == SESS_CACHE_BOTH
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003376
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003377 def test_sess_cache_no_auto_clear(self):
3378 """
Alex Chanb7480992017-01-30 14:04:47 +00003379 The value of `OpenSSL.SSL.SESS_CACHE_NO_AUTO_CLEAR` 0x80, the
3380 value of `SSL_SESS_CACHE_NO_AUTO_CLEAR` defined by
3381 `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003382 """
Alex Chanb7480992017-01-30 14:04:47 +00003383 assert 0x80 == SESS_CACHE_NO_AUTO_CLEAR
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003384
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003385 def test_sess_cache_no_internal_lookup(self):
3386 """
Alex Chanb7480992017-01-30 14:04:47 +00003387 The value of `OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_LOOKUP` 0x100,
3388 the value of `SSL_SESS_CACHE_NO_INTERNAL_LOOKUP` defined by
3389 `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003390 """
Alex Chanb7480992017-01-30 14:04:47 +00003391 assert 0x100 == SESS_CACHE_NO_INTERNAL_LOOKUP
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003392
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003393 def test_sess_cache_no_internal_store(self):
3394 """
Alex Chanb7480992017-01-30 14:04:47 +00003395 The value of `OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_STORE` 0x200,
3396 the value of `SSL_SESS_CACHE_NO_INTERNAL_STORE` defined by
3397 `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003398 """
Alex Chanb7480992017-01-30 14:04:47 +00003399 assert 0x200 == SESS_CACHE_NO_INTERNAL_STORE
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003400
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003401 def test_sess_cache_no_internal(self):
3402 """
Alex Chanb7480992017-01-30 14:04:47 +00003403 The value of `OpenSSL.SSL.SESS_CACHE_NO_INTERNAL` 0x300, the
3404 value of `SSL_SESS_CACHE_NO_INTERNAL` defined by
3405 `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003406 """
Alex Chanb7480992017-01-30 14:04:47 +00003407 assert 0x300 == SESS_CACHE_NO_INTERNAL
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003408
3409
Alex Chanb7480992017-01-30 14:04:47 +00003410class TestMemoryBIO(object):
Rick Deanb71c0d22009-04-01 14:09:23 -05003411 """
Alex Chanb7480992017-01-30 14:04:47 +00003412 Tests for `OpenSSL.SSL.Connection` using a memory BIO.
Rick Deanb71c0d22009-04-01 14:09:23 -05003413 """
Alex Gaynor03737182020-07-23 20:40:46 -04003414
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003415 def _server(self, sock):
3416 """
Alex Chanb7480992017-01-30 14:04:47 +00003417 Create a new server-side SSL `Connection` object wrapped around `sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003418 """
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003419 # Create the server side Connection. This is mostly setup boilerplate
3420 # - use TLSv1, use a particular certificate, etc.
Paul Kehrer688538c2020-08-03 19:18:15 -05003421 server_ctx = Context(SSLv23_METHOD)
Alex Gaynor43307782015-09-04 09:05:45 -04003422 server_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE)
Hynek Schlawack35618382015-09-05 21:54:25 +02003423 server_ctx.set_verify(
3424 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT | VERIFY_CLIENT_ONCE,
Alex Gaynor03737182020-07-23 20:40:46 -04003425 verify_cb,
Hynek Schlawack35618382015-09-05 21:54:25 +02003426 )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003427 server_store = server_ctx.get_cert_store()
Hynek Schlawack35618382015-09-05 21:54:25 +02003428 server_ctx.use_privatekey(
Alex Gaynor03737182020-07-23 20:40:46 -04003429 load_privatekey(FILETYPE_PEM, server_key_pem)
3430 )
Hynek Schlawack35618382015-09-05 21:54:25 +02003431 server_ctx.use_certificate(
Alex Gaynor03737182020-07-23 20:40:46 -04003432 load_certificate(FILETYPE_PEM, server_cert_pem)
3433 )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003434 server_ctx.check_privatekey()
3435 server_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Hynek Schlawack35618382015-09-05 21:54:25 +02003436 # Here the Connection is actually created. If None is passed as the
3437 # 2nd parameter, it indicates a memory BIO should be created.
Rick Deanb1ccd562009-07-09 23:52:39 -05003438 server_conn = Connection(server_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003439 server_conn.set_accept_state()
3440 return server_conn
3441
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003442 def _client(self, sock):
3443 """
Alex Chanb7480992017-01-30 14:04:47 +00003444 Create a new client-side SSL `Connection` object wrapped around `sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003445 """
3446 # Now create the client side Connection. Similar boilerplate to the
3447 # above.
Paul Kehrer688538c2020-08-03 19:18:15 -05003448 client_ctx = Context(SSLv23_METHOD)
Alex Gaynor43307782015-09-04 09:05:45 -04003449 client_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE)
Hynek Schlawack35618382015-09-05 21:54:25 +02003450 client_ctx.set_verify(
3451 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT | VERIFY_CLIENT_ONCE,
Alex Gaynor03737182020-07-23 20:40:46 -04003452 verify_cb,
Hynek Schlawack35618382015-09-05 21:54:25 +02003453 )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003454 client_store = client_ctx.get_cert_store()
Hynek Schlawack35618382015-09-05 21:54:25 +02003455 client_ctx.use_privatekey(
Alex Gaynor03737182020-07-23 20:40:46 -04003456 load_privatekey(FILETYPE_PEM, client_key_pem)
3457 )
Hynek Schlawack35618382015-09-05 21:54:25 +02003458 client_ctx.use_certificate(
Alex Gaynor03737182020-07-23 20:40:46 -04003459 load_certificate(FILETYPE_PEM, client_cert_pem)
3460 )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003461 client_ctx.check_privatekey()
3462 client_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05003463 client_conn = Connection(client_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003464 client_conn.set_connect_state()
3465 return client_conn
3466
Alex Chanb7480992017-01-30 14:04:47 +00003467 def test_memory_connect(self):
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003468 """
Alex Chanb7480992017-01-30 14:04:47 +00003469 Two `Connection`s which use memory BIOs can be manually connected by
3470 reading from the output of each and writing those bytes to the input of
3471 the other and in this way establish a connection and exchange
3472 application-level bytes with each other.
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003473 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003474 server_conn = self._server(None)
3475 client_conn = self._client(None)
Rick Deanb71c0d22009-04-01 14:09:23 -05003476
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003477 # There should be no key or nonces yet.
Alex Chanb7480992017-01-30 14:04:47 +00003478 assert server_conn.master_key() is None
3479 assert server_conn.client_random() is None
3480 assert server_conn.server_random() is None
Rick Deanb71c0d22009-04-01 14:09:23 -05003481
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003482 # First, the handshake needs to happen. We'll deliver bytes back and
3483 # forth between the client and server until neither of them feels like
3484 # speaking any more.
Alex Chanb7480992017-01-30 14:04:47 +00003485 assert interact_in_memory(client_conn, server_conn) is None
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003486
3487 # Now that the handshake is done, there should be a key and nonces.
Alex Chanb7480992017-01-30 14:04:47 +00003488 assert server_conn.master_key() is not None
3489 assert server_conn.client_random() is not None
3490 assert server_conn.server_random() is not None
3491 assert server_conn.client_random() == client_conn.client_random()
3492 assert server_conn.server_random() == client_conn.server_random()
3493 assert server_conn.client_random() != server_conn.server_random()
3494 assert client_conn.client_random() != client_conn.server_random()
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003495
Paul Kehrerbdb76392017-12-01 04:54:32 +08003496 # Export key material for other uses.
Alex Gaynor03737182020-07-23 20:40:46 -04003497 cekm = client_conn.export_keying_material(b"LABEL", 32)
3498 sekm = server_conn.export_keying_material(b"LABEL", 32)
Paul Kehrerbdb76392017-12-01 04:54:32 +08003499 assert cekm is not None
3500 assert sekm is not None
3501 assert cekm == sekm
3502 assert len(sekm) == 32
3503
3504 # Export key material for other uses with additional context.
Alex Gaynor03737182020-07-23 20:40:46 -04003505 cekmc = client_conn.export_keying_material(b"LABEL", 32, b"CONTEXT")
3506 sekmc = server_conn.export_keying_material(b"LABEL", 32, b"CONTEXT")
Paul Kehrerbdb76392017-12-01 04:54:32 +08003507 assert cekmc is not None
3508 assert sekmc is not None
3509 assert cekmc == sekmc
3510 assert cekmc != cekm
3511 assert sekmc != sekm
3512 # Export with alternate label
Alex Gaynor03737182020-07-23 20:40:46 -04003513 cekmt = client_conn.export_keying_material(b"test", 32, b"CONTEXT")
3514 sekmt = server_conn.export_keying_material(b"test", 32, b"CONTEXT")
Paul Kehrerbdb76392017-12-01 04:54:32 +08003515 assert cekmc != cekmt
3516 assert sekmc != sekmt
3517
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003518 # Here are the bytes we'll try to send.
Alex Gaynor03737182020-07-23 20:40:46 -04003519 important_message = b"One if by land, two if by sea."
Rick Deanb71c0d22009-04-01 14:09:23 -05003520
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003521 server_conn.write(important_message)
Alex Gaynor03737182020-07-23 20:40:46 -04003522 assert interact_in_memory(client_conn, server_conn) == (
3523 client_conn,
3524 important_message,
3525 )
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003526
3527 client_conn.write(important_message[::-1])
Alex Gaynor03737182020-07-23 20:40:46 -04003528 assert interact_in_memory(client_conn, server_conn) == (
3529 server_conn,
3530 important_message[::-1],
3531 )
Rick Deanb71c0d22009-04-01 14:09:23 -05003532
Alex Chanb7480992017-01-30 14:04:47 +00003533 def test_socket_connect(self):
Rick Deanb1ccd562009-07-09 23:52:39 -05003534 """
Alex Chanb7480992017-01-30 14:04:47 +00003535 Just like `test_memory_connect` but with an actual socket.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003536
Hynek Schlawack35618382015-09-05 21:54:25 +02003537 This is primarily to rule out the memory BIO code as the source of any
Alex Chanb7480992017-01-30 14:04:47 +00003538 problems encountered while passing data over a `Connection` (if
Hynek Schlawack35618382015-09-05 21:54:25 +02003539 this test fails, there must be a problem outside the memory BIO code,
3540 as no memory BIO is involved here). Even though this isn't a memory
3541 BIO test, it's convenient to have it here.
Rick Deanb1ccd562009-07-09 23:52:39 -05003542 """
Alex Chanb7480992017-01-30 14:04:47 +00003543 server_conn, client_conn = loopback()
Rick Deanb1ccd562009-07-09 23:52:39 -05003544
Alex Gaynore7f51982016-09-11 11:48:14 -04003545 important_message = b"Help me Obi Wan Kenobi, you're my only hope."
Rick Deanb1ccd562009-07-09 23:52:39 -05003546 client_conn.send(important_message)
3547 msg = server_conn.recv(1024)
Alex Chanb7480992017-01-30 14:04:47 +00003548 assert msg == important_message
Rick Deanb1ccd562009-07-09 23:52:39 -05003549
3550 # Again in the other direction, just for fun.
3551 important_message = important_message[::-1]
3552 server_conn.send(important_message)
3553 msg = client_conn.recv(1024)
Alex Chanb7480992017-01-30 14:04:47 +00003554 assert msg == important_message
Rick Deanb1ccd562009-07-09 23:52:39 -05003555
Alex Chanb7480992017-01-30 14:04:47 +00003556 def test_socket_overrides_memory(self):
Rick Deanb71c0d22009-04-01 14:09:23 -05003557 """
Alex Chanb7480992017-01-30 14:04:47 +00003558 Test that `OpenSSL.SSL.bio_read` and `OpenSSL.SSL.bio_write` don't
3559 work on `OpenSSL.SSL.Connection`() that use sockets.
Rick Deanb71c0d22009-04-01 14:09:23 -05003560 """
Paul Kehrer688538c2020-08-03 19:18:15 -05003561 context = Context(SSLv23_METHOD)
David Benjamin1fbe0642019-04-15 17:05:13 -05003562 client = socket_any_family()
Rick Deanb71c0d22009-04-01 14:09:23 -05003563 clientSSL = Connection(context, client)
Alex Chanb7480992017-01-30 14:04:47 +00003564 with pytest.raises(TypeError):
3565 clientSSL.bio_read(100)
3566 with pytest.raises(TypeError):
Paul Kehrerc45a6ea2020-08-03 15:54:20 -05003567 clientSSL.bio_write(b"foo")
Alex Chanb7480992017-01-30 14:04:47 +00003568 with pytest.raises(TypeError):
3569 clientSSL.bio_shutdown()
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003570
Alex Chanb7480992017-01-30 14:04:47 +00003571 def test_outgoing_overflow(self):
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003572 """
3573 If more bytes than can be written to the memory BIO are passed to
Alex Chanb7480992017-01-30 14:04:47 +00003574 `Connection.send` at once, the number of bytes which were written is
3575 returned and that many bytes from the beginning of the input can be
3576 read from the other end of the connection.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003577 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003578 server = self._server(None)
3579 client = self._client(None)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003580
Alex Chanb7480992017-01-30 14:04:47 +00003581 interact_in_memory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003582
3583 size = 2 ** 15
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003584 sent = client.send(b"x" * size)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003585 # Sanity check. We're trying to test what happens when the entire
3586 # input can't be sent. If the entire input was sent, this test is
3587 # meaningless.
Alex Chanb7480992017-01-30 14:04:47 +00003588 assert sent < size
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003589
Alex Chanb7480992017-01-30 14:04:47 +00003590 receiver, received = interact_in_memory(client, server)
3591 assert receiver is server
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003592
3593 # We can rely on all of these bytes being received at once because
Alex Chanb7480992017-01-30 14:04:47 +00003594 # loopback passes 2 ** 16 to recv - more than 2 ** 15.
3595 assert len(received) == sent
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003596
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003597 def test_shutdown(self):
3598 """
Alex Chanb7480992017-01-30 14:04:47 +00003599 `Connection.bio_shutdown` signals the end of the data stream
3600 from which the `Connection` reads.
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003601 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003602 server = self._server(None)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003603 server.bio_shutdown()
Alex Chanb7480992017-01-30 14:04:47 +00003604 with pytest.raises(Error) as err:
3605 server.recv(1024)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003606 # We don't want WantReadError or ZeroReturnError or anything - it's a
3607 # handshake failure.
Alex Chanb7480992017-01-30 14:04:47 +00003608 assert type(err.value) in [Error, SysCallError]
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003609
Alex Chanb7480992017-01-30 14:04:47 +00003610 def test_unexpected_EOF(self):
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003611 """
3612 If the connection is lost before an orderly SSL shutdown occurs,
Alex Chanb7480992017-01-30 14:04:47 +00003613 `OpenSSL.SSL.SysCallError` is raised with a message of
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003614 "Unexpected EOF".
3615 """
Alex Chanb7480992017-01-30 14:04:47 +00003616 server_conn, client_conn = loopback()
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003617 client_conn.sock_shutdown(SHUT_RDWR)
Alex Chanb7480992017-01-30 14:04:47 +00003618 with pytest.raises(SysCallError) as err:
3619 server_conn.recv(1024)
3620 assert err.value.args == (-1, "Unexpected EOF")
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003621
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003622 def _check_client_ca_list(self, func):
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003623 """
Alex Chanb7480992017-01-30 14:04:47 +00003624 Verify the return value of the `get_client_ca_list` method for
Hynek Schlawack35618382015-09-05 21:54:25 +02003625 server and client connections.
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003626
Jonathan Ballet78b92a22011-07-16 08:07:26 +09003627 :param func: A function which will be called with the server context
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003628 before the client and server are connected to each other. This
3629 function should specify a list of CAs for the server to send to the
3630 client and return that same list. The list will be used to verify
Alex Chanb7480992017-01-30 14:04:47 +00003631 that `get_client_ca_list` returns the proper value at
Hynek Schlawack35618382015-09-05 21:54:25 +02003632 various times.
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003633 """
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003634 server = self._server(None)
3635 client = self._client(None)
Alex Chanb7480992017-01-30 14:04:47 +00003636 assert client.get_client_ca_list() == []
3637 assert server.get_client_ca_list() == []
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003638 ctx = server.get_context()
3639 expected = func(ctx)
Alex Chanb7480992017-01-30 14:04:47 +00003640 assert client.get_client_ca_list() == []
3641 assert server.get_client_ca_list() == expected
3642 interact_in_memory(client, server)
3643 assert client.get_client_ca_list() == expected
3644 assert server.get_client_ca_list() == expected
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003645
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003646 def test_set_client_ca_list_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003647 """
Alex Chanb7480992017-01-30 14:04:47 +00003648 `Context.set_client_ca_list` raises a `TypeError` if called with a
3649 non-list or a list that contains objects other than X509Names.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003650 """
Paul Kehrer688538c2020-08-03 19:18:15 -05003651 ctx = Context(SSLv23_METHOD)
Alex Chanb7480992017-01-30 14:04:47 +00003652 with pytest.raises(TypeError):
3653 ctx.set_client_ca_list("spam")
3654 with pytest.raises(TypeError):
3655 ctx.set_client_ca_list(["spam"])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003656
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003657 def test_set_empty_ca_list(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003658 """
Alex Chanb7480992017-01-30 14:04:47 +00003659 If passed an empty list, `Context.set_client_ca_list` configures the
3660 context to send no CA names to the client and, on both the server and
3661 client sides, `Connection.get_client_ca_list` returns an empty list
3662 after the connection is set up.
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003663 """
Alex Gaynor03737182020-07-23 20:40:46 -04003664
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003665 def no_ca(ctx):
3666 ctx.set_client_ca_list([])
3667 return []
Alex Gaynor03737182020-07-23 20:40:46 -04003668
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003669 self._check_client_ca_list(no_ca)
3670
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003671 def test_set_one_ca_list(self):
3672 """
3673 If passed a list containing a single X509Name,
Alex Chanb7480992017-01-30 14:04:47 +00003674 `Context.set_client_ca_list` configures the context to send
Hynek Schlawack35618382015-09-05 21:54:25 +02003675 that CA name to the client and, on both the server and client sides,
Alex Chanb7480992017-01-30 14:04:47 +00003676 `Connection.get_client_ca_list` returns a list containing that
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003677 X509Name after the connection is set up.
3678 """
3679 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3680 cadesc = cacert.get_subject()
Hynek Schlawack35618382015-09-05 21:54:25 +02003681
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003682 def single_ca(ctx):
3683 ctx.set_client_ca_list([cadesc])
3684 return [cadesc]
Alex Gaynor03737182020-07-23 20:40:46 -04003685
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003686 self._check_client_ca_list(single_ca)
3687
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003688 def test_set_multiple_ca_list(self):
3689 """
3690 If passed a list containing multiple X509Name objects,
Alex Chanb7480992017-01-30 14:04:47 +00003691 `Context.set_client_ca_list` configures the context to send
Hynek Schlawack35618382015-09-05 21:54:25 +02003692 those CA names to the client and, on both the server and client sides,
Alex Chanb7480992017-01-30 14:04:47 +00003693 `Connection.get_client_ca_list` returns a list containing those
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003694 X509Names after the connection is set up.
3695 """
3696 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3697 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3698
3699 sedesc = secert.get_subject()
3700 cldesc = clcert.get_subject()
3701
3702 def multiple_ca(ctx):
3703 L = [sedesc, cldesc]
3704 ctx.set_client_ca_list(L)
3705 return L
Alex Gaynor03737182020-07-23 20:40:46 -04003706
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003707 self._check_client_ca_list(multiple_ca)
3708
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003709 def test_reset_ca_list(self):
3710 """
3711 If called multiple times, only the X509Names passed to the final call
Alex Chanb7480992017-01-30 14:04:47 +00003712 of `Context.set_client_ca_list` are used to configure the CA
Hynek Schlawack35618382015-09-05 21:54:25 +02003713 names sent to the client.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003714 """
3715 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3716 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3717 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3718
3719 cadesc = cacert.get_subject()
3720 sedesc = secert.get_subject()
3721 cldesc = clcert.get_subject()
3722
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003723 def changed_ca(ctx):
3724 ctx.set_client_ca_list([sedesc, cldesc])
3725 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003726 return [cadesc]
Alex Gaynor03737182020-07-23 20:40:46 -04003727
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003728 self._check_client_ca_list(changed_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003729
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003730 def test_mutated_ca_list(self):
3731 """
Alex Chanb7480992017-01-30 14:04:47 +00003732 If the list passed to `Context.set_client_ca_list` is mutated
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003733 afterwards, this does not affect the list of CA names sent to the
3734 client.
3735 """
3736 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3737 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3738
3739 cadesc = cacert.get_subject()
3740 sedesc = secert.get_subject()
3741
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003742 def mutated_ca(ctx):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003743 L = [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003744 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003745 L.append(sedesc)
3746 return [cadesc]
Alex Gaynor03737182020-07-23 20:40:46 -04003747
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003748 self._check_client_ca_list(mutated_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003749
Alex Chanb7480992017-01-30 14:04:47 +00003750 def test_add_client_ca_wrong_args(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003751 """
Alex Chanb7480992017-01-30 14:04:47 +00003752 `Context.add_client_ca` raises `TypeError` if called with
3753 a non-X509 object.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003754 """
Paul Kehrer688538c2020-08-03 19:18:15 -05003755 ctx = Context(SSLv23_METHOD)
Alex Chanb7480992017-01-30 14:04:47 +00003756 with pytest.raises(TypeError):
3757 ctx.add_client_ca("spam")
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003758
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003759 def test_one_add_client_ca(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003760 """
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003761 A certificate's subject can be added as a CA to be sent to the client
Alex Chanb7480992017-01-30 14:04:47 +00003762 with `Context.add_client_ca`.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003763 """
3764 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3765 cadesc = cacert.get_subject()
Hynek Schlawack35618382015-09-05 21:54:25 +02003766
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003767 def single_ca(ctx):
3768 ctx.add_client_ca(cacert)
3769 return [cadesc]
Alex Gaynor03737182020-07-23 20:40:46 -04003770
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003771 self._check_client_ca_list(single_ca)
3772
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003773 def test_multiple_add_client_ca(self):
3774 """
3775 Multiple CA names can be sent to the client by calling
Alex Chanb7480992017-01-30 14:04:47 +00003776 `Context.add_client_ca` with multiple X509 objects.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003777 """
3778 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3779 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3780
3781 cadesc = cacert.get_subject()
3782 sedesc = secert.get_subject()
3783
3784 def multiple_ca(ctx):
3785 ctx.add_client_ca(cacert)
3786 ctx.add_client_ca(secert)
3787 return [cadesc, sedesc]
Alex Gaynor03737182020-07-23 20:40:46 -04003788
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003789 self._check_client_ca_list(multiple_ca)
3790
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003791 def test_set_and_add_client_ca(self):
3792 """
Alex Chanb7480992017-01-30 14:04:47 +00003793 A call to `Context.set_client_ca_list` followed by a call to
3794 `Context.add_client_ca` results in using the CA names from the
Hynek Schlawack35618382015-09-05 21:54:25 +02003795 first call and the CA name from the second call.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003796 """
3797 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3798 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3799 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3800
3801 cadesc = cacert.get_subject()
3802 sedesc = secert.get_subject()
3803 cldesc = clcert.get_subject()
3804
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003805 def mixed_set_add_ca(ctx):
3806 ctx.set_client_ca_list([cadesc, sedesc])
3807 ctx.add_client_ca(clcert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003808 return [cadesc, sedesc, cldesc]
Alex Gaynor03737182020-07-23 20:40:46 -04003809
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003810 self._check_client_ca_list(mixed_set_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003811
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003812 def test_set_after_add_client_ca(self):
3813 """
Alex Chanb7480992017-01-30 14:04:47 +00003814 A call to `Context.set_client_ca_list` after a call to
3815 `Context.add_client_ca` replaces the CA name specified by the
Hynek Schlawack35618382015-09-05 21:54:25 +02003816 former call with the names specified by the latter call.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003817 """
3818 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3819 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3820 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3821
3822 cadesc = cacert.get_subject()
3823 sedesc = secert.get_subject()
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003824
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003825 def set_replaces_add_ca(ctx):
3826 ctx.add_client_ca(clcert)
3827 ctx.set_client_ca_list([cadesc])
3828 ctx.add_client_ca(secert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003829 return [cadesc, sedesc]
Alex Gaynor03737182020-07-23 20:40:46 -04003830
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003831 self._check_client_ca_list(set_replaces_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003832
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003833
Alex Chanb7480992017-01-30 14:04:47 +00003834class TestInfoConstants(object):
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003835 """
3836 Tests for assorted constants exposed for use in info callbacks.
3837 """
Alex Gaynor03737182020-07-23 20:40:46 -04003838
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003839 def test_integers(self):
3840 """
3841 All of the info constants are integers.
3842
3843 This is a very weak test. It would be nice to have one that actually
3844 verifies that as certain info events happen, the value passed to the
3845 info callback matches up with the constant exposed by OpenSSL.SSL.
3846 """
3847 for const in [
Alex Gaynor03737182020-07-23 20:40:46 -04003848 SSL_ST_CONNECT,
3849 SSL_ST_ACCEPT,
3850 SSL_ST_MASK,
3851 SSL_CB_LOOP,
3852 SSL_CB_EXIT,
3853 SSL_CB_READ,
3854 SSL_CB_WRITE,
3855 SSL_CB_ALERT,
3856 SSL_CB_READ_ALERT,
3857 SSL_CB_WRITE_ALERT,
3858 SSL_CB_ACCEPT_LOOP,
3859 SSL_CB_ACCEPT_EXIT,
3860 SSL_CB_CONNECT_LOOP,
3861 SSL_CB_CONNECT_EXIT,
3862 SSL_CB_HANDSHAKE_START,
3863 SSL_CB_HANDSHAKE_DONE,
Hynek Schlawack35618382015-09-05 21:54:25 +02003864 ]:
Alex Gaynor5af32d02016-09-24 01:52:21 -04003865 assert isinstance(const, int)
3866
3867 # These constants don't exist on OpenSSL 1.1.0
3868 for const in [
Alex Gaynor03737182020-07-23 20:40:46 -04003869 SSL_ST_INIT,
3870 SSL_ST_BEFORE,
3871 SSL_ST_OK,
3872 SSL_ST_RENEGOTIATE,
Alex Gaynor5af32d02016-09-24 01:52:21 -04003873 ]:
3874 assert const is None or isinstance(const, int)
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003875
Ziga Seilnacht44611bf2009-08-31 20:49:30 +02003876
Cory Benfield1d142142016-03-30 11:51:45 +01003877class TestRequires(object):
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003878 """
3879 Tests for the decorator factory used to conditionally raise
Cory Benfield1d142142016-03-30 11:51:45 +01003880 NotImplementedError when older OpenSSLs are used.
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003881 """
Alex Gaynor03737182020-07-23 20:40:46 -04003882
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003883 def test_available(self):
3884 """
3885 When the OpenSSL functionality is available the decorated functions
3886 work appropriately.
3887 """
3888 feature_guard = _make_requires(True, "Error text")
3889 results = []
3890
3891 @feature_guard
3892 def inner():
3893 results.append(True)
3894 return True
3895
Cory Benfield2333e5e2016-03-30 14:24:16 +01003896 assert inner() is True
3897 assert [True] == results
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003898
3899 def test_unavailable(self):
3900 """
3901 When the OpenSSL functionality is not available the decorated function
3902 does not execute and NotImplementedError is raised.
3903 """
3904 feature_guard = _make_requires(False, "Error text")
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003905
3906 @feature_guard
Alex Chanfb078d82017-04-20 11:16:15 +01003907 def inner(): # pragma: nocover
3908 pytest.fail("Should not be called")
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003909
Cory Benfield1d142142016-03-30 11:51:45 +01003910 with pytest.raises(NotImplementedError) as e:
3911 inner()
3912
3913 assert "Error text" in str(e.value)
Cory Benfield496652a2017-01-24 11:42:56 +00003914
3915
Alex Chanb7480992017-01-30 14:04:47 +00003916class TestOCSP(object):
Cory Benfield496652a2017-01-24 11:42:56 +00003917 """
3918 Tests for PyOpenSSL's OCSP stapling support.
3919 """
Alex Gaynor03737182020-07-23 20:40:46 -04003920
Cory Benfield496652a2017-01-24 11:42:56 +00003921 sample_ocsp_data = b"this is totally ocsp data"
3922
3923 def _client_connection(self, callback, data, request_ocsp=True):
3924 """
3925 Builds a client connection suitable for using OCSP.
3926
3927 :param callback: The callback to register for OCSP.
3928 :param data: The opaque data object that will be handed to the
3929 OCSP callback.
3930 :param request_ocsp: Whether the client will actually ask for OCSP
3931 stapling. Useful for testing only.
3932 """
3933 ctx = Context(SSLv23_METHOD)
3934 ctx.set_ocsp_client_callback(callback, data)
3935 client = Connection(ctx)
3936
3937 if request_ocsp:
3938 client.request_ocsp()
3939
3940 client.set_connect_state()
3941 return client
3942
3943 def _server_connection(self, callback, data):
3944 """
3945 Builds a server connection suitable for using OCSP.
3946
3947 :param callback: The callback to register for OCSP.
3948 :param data: The opaque data object that will be handed to the
3949 OCSP callback.
3950 """
3951 ctx = Context(SSLv23_METHOD)
3952 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
3953 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
3954 ctx.set_ocsp_server_callback(callback, data)
3955 server = Connection(ctx)
3956 server.set_accept_state()
3957 return server
3958
3959 def test_callbacks_arent_called_by_default(self):
3960 """
3961 If both the client and the server have registered OCSP callbacks, but
3962 the client does not send the OCSP request, neither callback gets
3963 called.
3964 """
Alex Gaynor03737182020-07-23 20:40:46 -04003965
Alex Chanfb078d82017-04-20 11:16:15 +01003966 def ocsp_callback(*args, **kwargs): # pragma: nocover
3967 pytest.fail("Should not be called")
Cory Benfield496652a2017-01-24 11:42:56 +00003968
3969 client = self._client_connection(
3970 callback=ocsp_callback, data=None, request_ocsp=False
3971 )
3972 server = self._server_connection(callback=ocsp_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00003973 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003974
Cory Benfield496652a2017-01-24 11:42:56 +00003975 def test_client_negotiates_without_server(self):
3976 """
3977 If the client wants to do OCSP but the server does not, the handshake
3978 succeeds, and the client callback fires with an empty byte string.
3979 """
3980 called = []
3981
3982 def ocsp_callback(conn, ocsp_data, ignored):
3983 called.append(ocsp_data)
3984 return True
3985
3986 client = self._client_connection(callback=ocsp_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00003987 server = loopback_server_factory(socket=None)
3988 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003989
3990 assert len(called) == 1
Alex Gaynor03737182020-07-23 20:40:46 -04003991 assert called[0] == b""
Cory Benfield496652a2017-01-24 11:42:56 +00003992
3993 def test_client_receives_servers_data(self):
3994 """
3995 The data the server sends in its callback is received by the client.
3996 """
3997 calls = []
3998
3999 def server_callback(*args, **kwargs):
4000 return self.sample_ocsp_data
4001
4002 def client_callback(conn, ocsp_data, ignored):
4003 calls.append(ocsp_data)
4004 return True
4005
4006 client = self._client_connection(callback=client_callback, data=None)
4007 server = self._server_connection(callback=server_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00004008 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00004009
4010 assert len(calls) == 1
4011 assert calls[0] == self.sample_ocsp_data
4012
4013 def test_callbacks_are_invoked_with_connections(self):
4014 """
4015 The first arguments to both callbacks are their respective connections.
4016 """
4017 client_calls = []
4018 server_calls = []
4019
4020 def client_callback(conn, *args, **kwargs):
4021 client_calls.append(conn)
4022 return True
4023
4024 def server_callback(conn, *args, **kwargs):
4025 server_calls.append(conn)
4026 return self.sample_ocsp_data
4027
4028 client = self._client_connection(callback=client_callback, data=None)
4029 server = self._server_connection(callback=server_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00004030 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00004031
4032 assert len(client_calls) == 1
4033 assert len(server_calls) == 1
4034 assert client_calls[0] is client
4035 assert server_calls[0] is server
4036
4037 def test_opaque_data_is_passed_through(self):
4038 """
4039 Both callbacks receive an opaque, user-provided piece of data in their
4040 callbacks as the final argument.
4041 """
4042 calls = []
4043
4044 def server_callback(*args):
4045 calls.append(args)
4046 return self.sample_ocsp_data
4047
4048 def client_callback(*args):
4049 calls.append(args)
4050 return True
4051
4052 sentinel = object()
4053
4054 client = self._client_connection(
4055 callback=client_callback, data=sentinel
4056 )
4057 server = self._server_connection(
4058 callback=server_callback, data=sentinel
4059 )
Alex Chanb7480992017-01-30 14:04:47 +00004060 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00004061
4062 assert len(calls) == 2
4063 assert calls[0][-1] is sentinel
4064 assert calls[1][-1] is sentinel
4065
4066 def test_server_returns_empty_string(self):
4067 """
4068 If the server returns an empty bytestring from its callback, the
4069 client callback is called with the empty bytestring.
4070 """
4071 client_calls = []
4072
4073 def server_callback(*args):
Alex Gaynor03737182020-07-23 20:40:46 -04004074 return b""
Cory Benfield496652a2017-01-24 11:42:56 +00004075
4076 def client_callback(conn, ocsp_data, ignored):
4077 client_calls.append(ocsp_data)
4078 return True
4079
4080 client = self._client_connection(callback=client_callback, data=None)
4081 server = self._server_connection(callback=server_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00004082 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00004083
4084 assert len(client_calls) == 1
Alex Gaynor03737182020-07-23 20:40:46 -04004085 assert client_calls[0] == b""
Cory Benfield496652a2017-01-24 11:42:56 +00004086
4087 def test_client_returns_false_terminates_handshake(self):
4088 """
4089 If the client returns False from its callback, the handshake fails.
4090 """
Alex Gaynor03737182020-07-23 20:40:46 -04004091
Cory Benfield496652a2017-01-24 11:42:56 +00004092 def server_callback(*args):
4093 return self.sample_ocsp_data
4094
4095 def client_callback(*args):
4096 return False
4097
4098 client = self._client_connection(callback=client_callback, data=None)
4099 server = self._server_connection(callback=server_callback, data=None)
4100
4101 with pytest.raises(Error):
Alex Chanb7480992017-01-30 14:04:47 +00004102 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00004103
4104 def test_exceptions_in_client_bubble_up(self):
4105 """
4106 The callbacks thrown in the client callback bubble up to the caller.
4107 """
Alex Gaynor03737182020-07-23 20:40:46 -04004108
Cory Benfield496652a2017-01-24 11:42:56 +00004109 class SentinelException(Exception):
4110 pass
4111
4112 def server_callback(*args):
4113 return self.sample_ocsp_data
4114
4115 def client_callback(*args):
4116 raise SentinelException()
4117
4118 client = self._client_connection(callback=client_callback, data=None)
4119 server = self._server_connection(callback=server_callback, data=None)
4120
4121 with pytest.raises(SentinelException):
Alex Chanb7480992017-01-30 14:04:47 +00004122 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00004123
4124 def test_exceptions_in_server_bubble_up(self):
4125 """
4126 The callbacks thrown in the server callback bubble up to the caller.
4127 """
Alex Gaynor03737182020-07-23 20:40:46 -04004128
Cory Benfield496652a2017-01-24 11:42:56 +00004129 class SentinelException(Exception):
4130 pass
4131
4132 def server_callback(*args):
4133 raise SentinelException()
4134
Alex Chanfb078d82017-04-20 11:16:15 +01004135 def client_callback(*args): # pragma: nocover
Cory Benfield496652a2017-01-24 11:42:56 +00004136 pytest.fail("Should not be called")
4137
4138 client = self._client_connection(callback=client_callback, data=None)
4139 server = self._server_connection(callback=server_callback, data=None)
4140
4141 with pytest.raises(SentinelException):
Alex Chanb7480992017-01-30 14:04:47 +00004142 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00004143
4144 def test_server_must_return_bytes(self):
4145 """
4146 The server callback must return a bytestring, or a TypeError is thrown.
4147 """
Alex Gaynor03737182020-07-23 20:40:46 -04004148
Cory Benfield496652a2017-01-24 11:42:56 +00004149 def server_callback(*args):
Alex Gaynor03737182020-07-23 20:40:46 -04004150 return self.sample_ocsp_data.decode("ascii")
Cory Benfield496652a2017-01-24 11:42:56 +00004151
Alex Chanfb078d82017-04-20 11:16:15 +01004152 def client_callback(*args): # pragma: nocover
Cory Benfield496652a2017-01-24 11:42:56 +00004153 pytest.fail("Should not be called")
4154
4155 client = self._client_connection(callback=client_callback, data=None)
4156 server = self._server_connection(callback=server_callback, data=None)
4157
4158 with pytest.raises(TypeError):
Alex Chanb7480992017-01-30 14:04:47 +00004159 handshake_in_memory(client, server)