blob: 0860eb81fa101a7a80da04aaebcb17573c09c568 [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(
451 x509.BasicConstraints(ca=True, path_length=None), critical=True,
452 )
453
454 certificate = builder.sign(
Alex Gaynor03737182020-07-23 20:40:46 -0400455 private_key=key, algorithm=hashes.SHA256(), backend=default_backend()
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100456 )
457
458 ca_file = tmpdir.join("test.pem")
459 ca_file.write_binary(
Alex Gaynor03737182020-07-23 20:40:46 -0400460 certificate.public_bytes(encoding=serialization.Encoding.PEM,)
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100461 )
462
463 return str(ca_file).encode("ascii")
464
465
466@pytest.fixture
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100467def context():
468 """
Paul Kehrer688538c2020-08-03 19:18:15 -0500469 A simple "best TLS you can get" context. TLS 1.2+ in any reasonable OpenSSL
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100470 """
Paul Kehrer688538c2020-08-03 19:18:15 -0500471 return Context(SSLv23_METHOD)
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100472
473
474class TestContext(object):
Hynek Schlawackaa861212016-03-13 13:53:48 +0100475 """
Alex Chan532b79e2017-01-24 15:14:52 +0000476 Unit tests for `OpenSSL.SSL.Context`.
Hynek Schlawackaa861212016-03-13 13:53:48 +0100477 """
Alex Gaynor03737182020-07-23 20:40:46 -0400478
479 @pytest.mark.parametrize(
480 "cipher_string",
481 [b"hello world:AES128-SHA", u"hello world:AES128-SHA"],
482 )
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100483 def test_set_cipher_list(self, context, cipher_string):
484 """
Alex Chan532b79e2017-01-24 15:14:52 +0000485 `Context.set_cipher_list` accepts both byte and unicode strings
Hynek Schlawacka7a63af2016-03-11 12:05:26 +0100486 for naming the ciphers which connections created with the context
487 object will be able to choose from.
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100488 """
489 context.set_cipher_list(cipher_string)
490 conn = Connection(context, None)
491
492 assert "AES128-SHA" in conn.get_cipher_list()
493
Mark Williamsdf2480d2019-02-14 19:30:07 -0800494 def test_set_cipher_list_wrong_type(self, context):
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100495 """
Alex Chan532b79e2017-01-24 15:14:52 +0000496 `Context.set_cipher_list` raises `TypeError` when passed a non-string
Mark Williamsdf2480d2019-02-14 19:30:07 -0800497 argument.
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100498 """
Mark Williamsdf2480d2019-02-14 19:30:07 -0800499 with pytest.raises(TypeError):
500 context.set_cipher_list(object())
501
Alex Gaynor963ae032019-07-06 17:38:32 -0400502 @flaky.flaky
Mark Williamsdf2480d2019-02-14 19:30:07 -0800503 def test_set_cipher_list_no_cipher_match(self, context):
504 """
505 `Context.set_cipher_list` raises `OpenSSL.SSL.Error` with a
506 `"no cipher match"` reason string regardless of the TLS
507 version.
508 """
509 with pytest.raises(Error) as excinfo:
510 context.set_cipher_list(b"imaginary-cipher")
511 assert excinfo.value.args == (
Alex Gaynor03737182020-07-23 20:40:46 -0400512 [("SSL routines", "SSL_CTX_set_cipher_list", "no cipher match",)],
513 )
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100514
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100515 def test_load_client_ca(self, context, ca_file):
516 """
Alex Chan532b79e2017-01-24 15:14:52 +0000517 `Context.load_client_ca` works as far as we can tell.
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100518 """
519 context.load_client_ca(ca_file)
520
521 def test_load_client_ca_invalid(self, context, tmpdir):
522 """
Alex Chan532b79e2017-01-24 15:14:52 +0000523 `Context.load_client_ca` raises an Error if the ca file is invalid.
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100524 """
525 ca_file = tmpdir.join("test.pem")
526 ca_file.write("")
527
528 with pytest.raises(Error) as e:
529 context.load_client_ca(str(ca_file).encode("ascii"))
530
531 assert "PEM routines" == e.value.args[0][0][0]
532
533 def test_load_client_ca_unicode(self, context, ca_file):
534 """
535 Passing the path as unicode raises a warning but works.
536 """
Alex Gaynor03737182020-07-23 20:40:46 -0400537 pytest.deprecated_call(context.load_client_ca, ca_file.decode("ascii"))
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100538
539 def test_set_session_id(self, context):
540 """
Alex Chan532b79e2017-01-24 15:14:52 +0000541 `Context.set_session_id` works as far as we can tell.
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100542 """
543 context.set_session_id(b"abc")
544
545 def test_set_session_id_fail(self, context):
546 """
Alex Chan532b79e2017-01-24 15:14:52 +0000547 `Context.set_session_id` errors are propagated.
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100548 """
549 with pytest.raises(Error) as e:
550 context.set_session_id(b"abc" * 1000)
551
552 assert [
Alex Gaynor03737182020-07-23 20:40:46 -0400553 (
554 "SSL routines",
555 "SSL_CTX_set_session_id_context",
556 "ssl session id context too long",
557 )
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100558 ] == e.value.args[0]
559
560 def test_set_session_id_unicode(self, context):
561 """
Alex Chan532b79e2017-01-24 15:14:52 +0000562 `Context.set_session_id` raises a warning if a unicode string is
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100563 passed.
564 """
565 pytest.deprecated_call(context.set_session_id, u"abc")
566
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400567 def test_method(self):
568 """
Alex Chan532b79e2017-01-24 15:14:52 +0000569 `Context` can be instantiated with one of `SSLv2_METHOD`,
570 `SSLv3_METHOD`, `SSLv23_METHOD`, `TLSv1_METHOD`, `TLSv1_1_METHOD`,
571 or `TLSv1_2_METHOD`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400572 """
Alex Gaynor5af32d02016-09-24 01:52:21 -0400573 methods = [SSLv23_METHOD, TLSv1_METHOD]
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400574 for meth in methods:
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400575 Context(meth)
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400576
Alex Gaynor5af32d02016-09-24 01:52:21 -0400577 maybe = [SSLv2_METHOD, SSLv3_METHOD, TLSv1_1_METHOD, TLSv1_2_METHOD]
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400578 for meth in maybe:
579 try:
580 Context(meth)
581 except (Error, ValueError):
582 # Some versions of OpenSSL have SSLv2 / TLSv1.1 / TLSv1.2, some
583 # don't. Difficult to say in advance.
584 pass
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400585
Alex Chan532b79e2017-01-24 15:14:52 +0000586 with pytest.raises(TypeError):
587 Context("")
588 with pytest.raises(ValueError):
589 Context(10)
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400590
Rick Deane15b1472009-07-09 15:53:42 -0500591 def test_type(self):
592 """
Alex Gaynor01f90a12019-02-07 09:14:48 -0500593 `Context` can be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -0500594 """
Alex Gaynor03737182020-07-23 20:40:46 -0400595 assert is_consistent_type(Context, "Context", TLSv1_METHOD)
Rick Deane15b1472009-07-09 15:53:42 -0500596
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400597 def test_use_privatekey(self):
598 """
Alex Chan532b79e2017-01-24 15:14:52 +0000599 `Context.use_privatekey` takes an `OpenSSL.crypto.PKey` instance.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400600 """
601 key = PKey()
Paul Kehrerc45a6ea2020-08-03 15:54:20 -0500602 key.generate_key(TYPE_RSA, 1024)
Paul Kehrer688538c2020-08-03 19:18:15 -0500603 ctx = Context(SSLv23_METHOD)
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400604 ctx.use_privatekey(key)
Alex Chan532b79e2017-01-24 15:14:52 +0000605 with pytest.raises(TypeError):
606 ctx.use_privatekey("")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400607
Alex Chan532b79e2017-01-24 15:14:52 +0000608 def test_use_privatekey_file_missing(self, tmpfile):
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800609 """
Alex Chan532b79e2017-01-24 15:14:52 +0000610 `Context.use_privatekey_file` raises `OpenSSL.SSL.Error` when passed
611 the name of a file which does not exist.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800612 """
Paul Kehrer688538c2020-08-03 19:18:15 -0500613 ctx = Context(SSLv23_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000614 with pytest.raises(Error):
615 ctx.use_privatekey_file(tmpfile)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800616
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400617 def _use_privatekey_file_test(self, pemfile, filetype):
618 """
619 Verify that calling ``Context.use_privatekey_file`` with the given
620 arguments does not raise an exception.
621 """
622 key = PKey()
Paul Kehrerc45a6ea2020-08-03 15:54:20 -0500623 key.generate_key(TYPE_RSA, 1024)
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400624
625 with open(pemfile, "wt") as pem:
Alex Gaynor03737182020-07-23 20:40:46 -0400626 pem.write(dump_privatekey(FILETYPE_PEM, key).decode("ascii"))
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400627
Paul Kehrer688538c2020-08-03 19:18:15 -0500628 ctx = Context(SSLv23_METHOD)
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400629 ctx.use_privatekey_file(pemfile, filetype)
630
Alex Gaynor03737182020-07-23 20:40:46 -0400631 @pytest.mark.parametrize("filetype", [object(), "", None, 1.0])
Alex Chanfb078d82017-04-20 11:16:15 +0100632 def test_wrong_privatekey_file_wrong_args(self, tmpfile, filetype):
633 """
634 `Context.use_privatekey_file` raises `TypeError` when called with
635 a `filetype` which is not a valid file encoding.
636 """
Paul Kehrer688538c2020-08-03 19:18:15 -0500637 ctx = Context(SSLv23_METHOD)
Alex Chanfb078d82017-04-20 11:16:15 +0100638 with pytest.raises(TypeError):
639 ctx.use_privatekey_file(tmpfile, filetype)
640
Alex Chan532b79e2017-01-24 15:14:52 +0000641 def test_use_privatekey_file_bytes(self, tmpfile):
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400642 """
643 A private key can be specified from a file by passing a ``bytes``
644 instance giving the file name to ``Context.use_privatekey_file``.
645 """
646 self._use_privatekey_file_test(
Alex Gaynor03737182020-07-23 20:40:46 -0400647 tmpfile + NON_ASCII.encode(getfilesystemencoding()), FILETYPE_PEM,
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400648 )
649
Alex Chan532b79e2017-01-24 15:14:52 +0000650 def test_use_privatekey_file_unicode(self, tmpfile):
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400651 """
652 A private key can be specified from a file by passing a ``unicode``
653 instance giving the file name to ``Context.use_privatekey_file``.
654 """
655 self._use_privatekey_file_test(
Alex Gaynor03737182020-07-23 20:40:46 -0400656 tmpfile.decode(getfilesystemencoding()) + NON_ASCII, FILETYPE_PEM,
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400657 )
658
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800659 def test_use_certificate_wrong_args(self):
660 """
Alex Chan532b79e2017-01-24 15:14:52 +0000661 `Context.use_certificate_wrong_args` raises `TypeError` when not passed
662 exactly one `OpenSSL.crypto.X509` instance as an argument.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800663 """
Paul Kehrer688538c2020-08-03 19:18:15 -0500664 ctx = Context(SSLv23_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000665 with pytest.raises(TypeError):
666 ctx.use_certificate("hello, world")
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800667
668 def test_use_certificate_uninitialized(self):
669 """
Alex Chan532b79e2017-01-24 15:14:52 +0000670 `Context.use_certificate` raises `OpenSSL.SSL.Error` when passed a
671 `OpenSSL.crypto.X509` instance which has not been initialized
672 (ie, which does not actually have any certificate data).
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800673 """
Paul Kehrer688538c2020-08-03 19:18:15 -0500674 ctx = Context(SSLv23_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000675 with pytest.raises(Error):
676 ctx.use_certificate(X509())
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800677
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800678 def test_use_certificate(self):
679 """
Alex Chan532b79e2017-01-24 15:14:52 +0000680 `Context.use_certificate` sets the certificate which will be
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800681 used to identify connections created using the context.
682 """
683 # TODO
684 # Hard to assert anything. But we could set a privatekey then ask
685 # OpenSSL if the cert and key agree using check_privatekey. Then as
686 # long as check_privatekey works right we're good...
Paul Kehrer688538c2020-08-03 19:18:15 -0500687 ctx = Context(SSLv23_METHOD)
Paul Kehrerbeaf9f52020-08-03 17:50:31 -0500688 ctx.use_certificate(load_certificate(FILETYPE_PEM, root_cert_pem))
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800689
690 def test_use_certificate_file_wrong_args(self):
691 """
Alex Chan532b79e2017-01-24 15:14:52 +0000692 `Context.use_certificate_file` raises `TypeError` if the first
693 argument is not a byte string or the second argument is not an integer.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800694 """
Paul Kehrer688538c2020-08-03 19:18:15 -0500695 ctx = Context(SSLv23_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000696 with pytest.raises(TypeError):
697 ctx.use_certificate_file(object(), FILETYPE_PEM)
698 with pytest.raises(TypeError):
699 ctx.use_certificate_file(b"somefile", object())
700 with pytest.raises(TypeError):
701 ctx.use_certificate_file(object(), FILETYPE_PEM)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800702
Alex Chan532b79e2017-01-24 15:14:52 +0000703 def test_use_certificate_file_missing(self, tmpfile):
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800704 """
Alex Chan532b79e2017-01-24 15:14:52 +0000705 `Context.use_certificate_file` raises `OpenSSL.SSL.Error` if passed
706 the name of a file which does not exist.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800707 """
Paul Kehrer688538c2020-08-03 19:18:15 -0500708 ctx = Context(SSLv23_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000709 with pytest.raises(Error):
710 ctx.use_certificate_file(tmpfile)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800711
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400712 def _use_certificate_file_test(self, certificate_file):
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800713 """
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400714 Verify that calling ``Context.use_certificate_file`` with the given
715 filename doesn't raise an exception.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800716 """
717 # TODO
718 # Hard to assert anything. But we could set a privatekey then ask
719 # OpenSSL if the cert and key agree using check_privatekey. Then as
720 # long as check_privatekey works right we're good...
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400721 with open(certificate_file, "wb") as pem_file:
Paul Kehrerbeaf9f52020-08-03 17:50:31 -0500722 pem_file.write(root_cert_pem)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800723
Paul Kehrer688538c2020-08-03 19:18:15 -0500724 ctx = Context(SSLv23_METHOD)
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400725 ctx.use_certificate_file(certificate_file)
726
Alex Chan532b79e2017-01-24 15:14:52 +0000727 def test_use_certificate_file_bytes(self, tmpfile):
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400728 """
Alex Chan532b79e2017-01-24 15:14:52 +0000729 `Context.use_certificate_file` sets the certificate (given as a
730 `bytes` filename) which will be used to identify connections created
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400731 using the context.
732 """
Alex Chan532b79e2017-01-24 15:14:52 +0000733 filename = tmpfile + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400734 self._use_certificate_file_test(filename)
735
Alex Chan532b79e2017-01-24 15:14:52 +0000736 def test_use_certificate_file_unicode(self, tmpfile):
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400737 """
Alex Chan532b79e2017-01-24 15:14:52 +0000738 `Context.use_certificate_file` sets the certificate (given as a
739 `bytes` filename) which will be used to identify connections created
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400740 using the context.
741 """
Alex Chan532b79e2017-01-24 15:14:52 +0000742 filename = tmpfile.decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400743 self._use_certificate_file_test(filename)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800744
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500745 def test_check_privatekey_valid(self):
746 """
Alex Chan532b79e2017-01-24 15:14:52 +0000747 `Context.check_privatekey` returns `None` if the `Context` instance
748 has been configured to use a matched key and certificate pair.
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500749 """
750 key = load_privatekey(FILETYPE_PEM, client_key_pem)
751 cert = load_certificate(FILETYPE_PEM, client_cert_pem)
Paul Kehrer688538c2020-08-03 19:18:15 -0500752 context = Context(SSLv23_METHOD)
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500753 context.use_privatekey(key)
754 context.use_certificate(cert)
Alex Chan532b79e2017-01-24 15:14:52 +0000755 assert None is context.check_privatekey()
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500756
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500757 def test_check_privatekey_invalid(self):
758 """
Alex Chan532b79e2017-01-24 15:14:52 +0000759 `Context.check_privatekey` raises `Error` if the `Context` instance
760 has been configured to use a key and certificate pair which don't
761 relate to each other.
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500762 """
763 key = load_privatekey(FILETYPE_PEM, client_key_pem)
764 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
Paul Kehrer688538c2020-08-03 19:18:15 -0500765 context = Context(SSLv23_METHOD)
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500766 context.use_privatekey(key)
767 context.use_certificate(cert)
Alex Chan532b79e2017-01-24 15:14:52 +0000768 with pytest.raises(Error):
769 context.check_privatekey()
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400770
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400771 def test_app_data(self):
772 """
Alex Chan532b79e2017-01-24 15:14:52 +0000773 `Context.set_app_data` stores an object for later retrieval
774 using `Context.get_app_data`.
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400775 """
776 app_data = object()
Paul Kehrer688538c2020-08-03 19:18:15 -0500777 context = Context(SSLv23_METHOD)
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400778 context.set_app_data(app_data)
Alex Chan532b79e2017-01-24 15:14:52 +0000779 assert context.get_app_data() is app_data
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400780
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400781 def test_set_options_wrong_args(self):
782 """
Alex Chan532b79e2017-01-24 15:14:52 +0000783 `Context.set_options` raises `TypeError` if called with
784 a non-`int` argument.
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400785 """
Paul Kehrer688538c2020-08-03 19:18:15 -0500786 context = Context(SSLv23_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000787 with pytest.raises(TypeError):
788 context.set_options(None)
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400789
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500790 def test_set_options(self):
791 """
Alex Chan532b79e2017-01-24 15:14:52 +0000792 `Context.set_options` returns the new options value.
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500793 """
Paul Kehrer688538c2020-08-03 19:18:15 -0500794 context = Context(SSLv23_METHOD)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500795 options = context.set_options(OP_NO_SSLv2)
Alex Gaynor2310f8b2016-09-10 14:39:32 -0400796 assert options & OP_NO_SSLv2 == OP_NO_SSLv2
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500797
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300798 def test_set_mode_wrong_args(self):
799 """
Alex Chan532b79e2017-01-24 15:14:52 +0000800 `Context.set_mode` raises `TypeError` if called with
801 a non-`int` argument.
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300802 """
Paul Kehrer688538c2020-08-03 19:18:15 -0500803 context = Context(SSLv23_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000804 with pytest.raises(TypeError):
805 context.set_mode(None)
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300806
Alex Gaynord3b5d9b2016-07-31 10:54:24 -0400807 def test_set_mode(self):
808 """
Alex Chan532b79e2017-01-24 15:14:52 +0000809 `Context.set_mode` accepts a mode bitvector and returns the
Alex Gaynord3b5d9b2016-07-31 10:54:24 -0400810 newly set mode.
811 """
Paul Kehrer688538c2020-08-03 19:18:15 -0500812 context = Context(SSLv23_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000813 assert MODE_RELEASE_BUFFERS & context.set_mode(MODE_RELEASE_BUFFERS)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500814
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400815 def test_set_timeout_wrong_args(self):
816 """
Alex Chan532b79e2017-01-24 15:14:52 +0000817 `Context.set_timeout` raises `TypeError` if called with
818 a non-`int` argument.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400819 """
Paul Kehrer688538c2020-08-03 19:18:15 -0500820 context = Context(SSLv23_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000821 with pytest.raises(TypeError):
822 context.set_timeout(None)
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400823
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400824 def test_timeout(self):
825 """
Alex Chan532b79e2017-01-24 15:14:52 +0000826 `Context.set_timeout` sets the session timeout for all connections
827 created using the context object. `Context.get_timeout` retrieves
828 this value.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400829 """
Paul Kehrer688538c2020-08-03 19:18:15 -0500830 context = Context(SSLv23_METHOD)
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400831 context.set_timeout(1234)
Alex Chan532b79e2017-01-24 15:14:52 +0000832 assert context.get_timeout() == 1234
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400833
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400834 def test_set_verify_depth_wrong_args(self):
835 """
Alex Chan532b79e2017-01-24 15:14:52 +0000836 `Context.set_verify_depth` raises `TypeError` if called with a
837 non-`int` argument.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400838 """
Paul Kehrer688538c2020-08-03 19:18:15 -0500839 context = Context(SSLv23_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000840 with pytest.raises(TypeError):
841 context.set_verify_depth(None)
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400842
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400843 def test_verify_depth(self):
844 """
Alex Chan532b79e2017-01-24 15:14:52 +0000845 `Context.set_verify_depth` sets the number of certificates in
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200846 a chain to follow before giving up. The value can be retrieved with
Alex Chan532b79e2017-01-24 15:14:52 +0000847 `Context.get_verify_depth`.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400848 """
Paul Kehrer688538c2020-08-03 19:18:15 -0500849 context = Context(SSLv23_METHOD)
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400850 context.set_verify_depth(11)
Alex Chan532b79e2017-01-24 15:14:52 +0000851 assert context.get_verify_depth() == 11
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400852
Alex Chan532b79e2017-01-24 15:14:52 +0000853 def _write_encrypted_pem(self, passphrase, tmpfile):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400854 """
855 Write a new private key out to a new file, encrypted using the given
856 passphrase. Return the path to the new file.
857 """
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400858 key = PKey()
Paul Kehrerc45a6ea2020-08-03 15:54:20 -0500859 key.generate_key(TYPE_RSA, 1024)
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400860 pem = dump_privatekey(FILETYPE_PEM, key, "blowfish", passphrase)
Alex Gaynor03737182020-07-23 20:40:46 -0400861 with open(tmpfile, "w") as fObj:
862 fObj.write(pem.decode("ascii"))
Alex Chan532b79e2017-01-24 15:14:52 +0000863 return tmpfile
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400864
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400865 def test_set_passwd_cb_wrong_args(self):
866 """
Alex Chan532b79e2017-01-24 15:14:52 +0000867 `Context.set_passwd_cb` raises `TypeError` if called with a
868 non-callable first argument.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400869 """
Paul Kehrer688538c2020-08-03 19:18:15 -0500870 context = Context(SSLv23_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000871 with pytest.raises(TypeError):
872 context.set_passwd_cb(None)
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400873
Alex Chan532b79e2017-01-24 15:14:52 +0000874 def test_set_passwd_cb(self, tmpfile):
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400875 """
Alex Chan532b79e2017-01-24 15:14:52 +0000876 `Context.set_passwd_cb` accepts a callable which will be invoked when
877 a private key is loaded from an encrypted PEM.
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400878 """
Alex Gaynore7f51982016-09-11 11:48:14 -0400879 passphrase = b"foobar"
Alex Chan532b79e2017-01-24 15:14:52 +0000880 pemFile = self._write_encrypted_pem(passphrase, tmpfile)
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400881 calledWith = []
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200882
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400883 def passphraseCallback(maxlen, verify, extra):
884 calledWith.append((maxlen, verify, extra))
885 return passphrase
Alex Gaynor03737182020-07-23 20:40:46 -0400886
Paul Kehrer688538c2020-08-03 19:18:15 -0500887 context = Context(SSLv23_METHOD)
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400888 context.set_passwd_cb(passphraseCallback)
889 context.use_privatekey_file(pemFile)
Alex Chan532b79e2017-01-24 15:14:52 +0000890 assert len(calledWith) == 1
891 assert isinstance(calledWith[0][0], int)
892 assert isinstance(calledWith[0][1], int)
893 assert calledWith[0][2] is None
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400894
Alex Chan532b79e2017-01-24 15:14:52 +0000895 def test_passwd_callback_exception(self, tmpfile):
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400896 """
Alex Chan532b79e2017-01-24 15:14:52 +0000897 `Context.use_privatekey_file` propagates any exception raised
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200898 by the passphrase callback.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400899 """
Alex Chan532b79e2017-01-24 15:14:52 +0000900 pemFile = self._write_encrypted_pem(b"monkeys are nice", tmpfile)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200901
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400902 def passphraseCallback(maxlen, verify, extra):
903 raise RuntimeError("Sorry, I am a fail.")
904
Paul Kehrer688538c2020-08-03 19:18:15 -0500905 context = Context(SSLv23_METHOD)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400906 context.set_passwd_cb(passphraseCallback)
Alex Chan532b79e2017-01-24 15:14:52 +0000907 with pytest.raises(RuntimeError):
908 context.use_privatekey_file(pemFile)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400909
Alex Chan532b79e2017-01-24 15:14:52 +0000910 def test_passwd_callback_false(self, tmpfile):
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400911 """
Alex Chan532b79e2017-01-24 15:14:52 +0000912 `Context.use_privatekey_file` raises `OpenSSL.SSL.Error` if the
913 passphrase callback returns a false value.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400914 """
Alex Chan532b79e2017-01-24 15:14:52 +0000915 pemFile = self._write_encrypted_pem(b"monkeys are nice", tmpfile)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200916
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400917 def passphraseCallback(maxlen, verify, extra):
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500918 return b""
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400919
Paul Kehrer688538c2020-08-03 19:18:15 -0500920 context = Context(SSLv23_METHOD)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400921 context.set_passwd_cb(passphraseCallback)
Alex Chan532b79e2017-01-24 15:14:52 +0000922 with pytest.raises(Error):
923 context.use_privatekey_file(pemFile)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400924
Alex Chan532b79e2017-01-24 15:14:52 +0000925 def test_passwd_callback_non_string(self, tmpfile):
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400926 """
Alex Chan532b79e2017-01-24 15:14:52 +0000927 `Context.use_privatekey_file` raises `OpenSSL.SSL.Error` if the
928 passphrase callback returns a true non-string value.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400929 """
Alex Chan532b79e2017-01-24 15:14:52 +0000930 pemFile = self._write_encrypted_pem(b"monkeys are nice", tmpfile)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200931
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400932 def passphraseCallback(maxlen, verify, extra):
933 return 10
934
Paul Kehrer688538c2020-08-03 19:18:15 -0500935 context = Context(SSLv23_METHOD)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400936 context.set_passwd_cb(passphraseCallback)
Alex Chan532b79e2017-01-24 15:14:52 +0000937 # TODO: Surely this is the wrong error?
938 with pytest.raises(ValueError):
939 context.use_privatekey_file(pemFile)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400940
Alex Chan532b79e2017-01-24 15:14:52 +0000941 def test_passwd_callback_too_long(self, tmpfile):
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400942 """
943 If the passphrase returned by the passphrase callback returns a string
944 longer than the indicated maximum length, it is truncated.
945 """
946 # A priori knowledge!
Alex Gaynore7f51982016-09-11 11:48:14 -0400947 passphrase = b"x" * 1024
Alex Chan532b79e2017-01-24 15:14:52 +0000948 pemFile = self._write_encrypted_pem(passphrase, tmpfile)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200949
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400950 def passphraseCallback(maxlen, verify, extra):
951 assert maxlen == 1024
Alex Gaynore7f51982016-09-11 11:48:14 -0400952 return passphrase + b"y"
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400953
Paul Kehrer688538c2020-08-03 19:18:15 -0500954 context = Context(SSLv23_METHOD)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400955 context.set_passwd_cb(passphraseCallback)
956 # This shall succeed because the truncated result is the correct
957 # passphrase.
958 context.use_privatekey_file(pemFile)
959
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400960 def test_set_info_callback(self):
961 """
Alex Chan532b79e2017-01-24 15:14:52 +0000962 `Context.set_info_callback` accepts a callable which will be
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200963 invoked when certain information about an SSL connection is available.
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400964 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500965 (server, client) = socket_pair()
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400966
Paul Kehrer688538c2020-08-03 19:18:15 -0500967 clientSSL = Connection(Context(SSLv23_METHOD), client)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400968 clientSSL.set_connect_state()
969
970 called = []
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200971
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400972 def info(conn, where, ret):
973 called.append((conn, where, ret))
Alex Gaynor03737182020-07-23 20:40:46 -0400974
Paul Kehrer688538c2020-08-03 19:18:15 -0500975 context = Context(SSLv23_METHOD)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400976 context.set_info_callback(info)
Paul Kehrerbeaf9f52020-08-03 17:50:31 -0500977 context.use_certificate(load_certificate(FILETYPE_PEM, root_cert_pem))
978 context.use_privatekey(load_privatekey(FILETYPE_PEM, root_key_pem))
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400979
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400980 serverSSL = Connection(context, server)
981 serverSSL.set_accept_state()
982
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -0500983 handshake(clientSSL, serverSSL)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400984
Jean-Paul Calderone3835e522014-02-02 11:12:30 -0500985 # The callback must always be called with a Connection instance as the
986 # first argument. It would probably be better to split this into
987 # separate tests for client and server side info callbacks so we could
988 # assert it is called with the right Connection instance. It would
989 # also be good to assert *something* about `where` and `ret`.
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -0500990 notConnections = [
Alex Gaynor03737182020-07-23 20:40:46 -0400991 conn
992 for (conn, where, ret) in called
993 if not isinstance(conn, Connection)
994 ]
995 assert (
996 [] == notConnections
997 ), "Some info callback arguments were not Connection instances."
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400998
Maximilian Hilsb2bca412020-07-28 16:31:22 +0200999 @pytest.mark.skipif(
1000 not getattr(_lib, "Cryptography_HAS_KEYLOG", None),
1001 reason="SSL_CTX_set_keylog_callback unavailable",
1002 )
1003 def test_set_keylog_callback(self):
1004 """
1005 `Context.set_keylog_callback` accepts a callable which will be
1006 invoked when key material is generated or received.
1007 """
1008 called = []
1009
1010 def keylog(conn, line):
1011 called.append((conn, line))
1012
Paul Kehrer688538c2020-08-03 19:18:15 -05001013 server_context = Context(TLSv1_2_METHOD)
Maximilian Hilsb2bca412020-07-28 16:31:22 +02001014 server_context.set_keylog_callback(keylog)
1015 server_context.use_certificate(
Paul Kehrerbeaf9f52020-08-03 17:50:31 -05001016 load_certificate(FILETYPE_PEM, root_cert_pem)
Maximilian Hilsb2bca412020-07-28 16:31:22 +02001017 )
1018 server_context.use_privatekey(
Paul Kehrerbeaf9f52020-08-03 17:50:31 -05001019 load_privatekey(FILETYPE_PEM, root_key_pem)
Maximilian Hilsb2bca412020-07-28 16:31:22 +02001020 )
1021
Paul Kehrer688538c2020-08-03 19:18:15 -05001022 client_context = Context(SSLv23_METHOD)
Maximilian Hilsb2bca412020-07-28 16:31:22 +02001023
1024 self._handshake_test(server_context, client_context)
1025
1026 assert called
1027 assert all(isinstance(conn, Connection) for conn, line in called)
1028 assert all(b"CLIENT_RANDOM" in line for conn, line in called)
1029
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001030 def _load_verify_locations_test(self, *args):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001031 """
1032 Create a client context which will verify the peer certificate and call
Alex Chan532b79e2017-01-24 15:14:52 +00001033 its `load_verify_locations` method with the given arguments.
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04001034 Then connect it to a server and ensure that the handshake succeeds.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001035 """
Rick Deanb1ccd562009-07-09 23:52:39 -05001036 (server, client) = socket_pair()
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001037
Paul Kehrer688538c2020-08-03 19:18:15 -05001038 clientContext = Context(SSLv23_METHOD)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001039 clientContext.load_verify_locations(*args)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001040 # Require that the server certificate verify properly or the
1041 # connection will fail.
1042 clientContext.set_verify(
1043 VERIFY_PEER,
Alex Gaynor03737182020-07-23 20:40:46 -04001044 lambda conn, cert, errno, depth, preverify_ok: preverify_ok,
1045 )
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001046
1047 clientSSL = Connection(clientContext, client)
1048 clientSSL.set_connect_state()
1049
Paul Kehrer688538c2020-08-03 19:18:15 -05001050 serverContext = Context(SSLv23_METHOD)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001051 serverContext.use_certificate(
Paul Kehrerbeaf9f52020-08-03 17:50:31 -05001052 load_certificate(FILETYPE_PEM, root_cert_pem)
Alex Gaynor03737182020-07-23 20:40:46 -04001053 )
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001054 serverContext.use_privatekey(
Paul Kehrerbeaf9f52020-08-03 17:50:31 -05001055 load_privatekey(FILETYPE_PEM, root_key_pem)
Alex Gaynor03737182020-07-23 20:40:46 -04001056 )
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001057
1058 serverSSL = Connection(serverContext, server)
1059 serverSSL.set_accept_state()
1060
Jean-Paul Calderonef8742032010-09-25 00:00:32 -04001061 # Without load_verify_locations above, the handshake
1062 # will fail:
1063 # Error: [('SSL routines', 'SSL3_GET_SERVER_CERTIFICATE',
1064 # 'certificate verify failed')]
1065 handshake(clientSSL, serverSSL)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001066
1067 cert = clientSSL.get_peer_certificate()
Alex Gaynor03737182020-07-23 20:40:46 -04001068 assert cert.get_subject().CN == "Testing Root CA"
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -04001069
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001070 def _load_verify_cafile(self, cafile):
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001071 """
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001072 Verify that if path to a file containing a certificate is passed to
Alex Chan532b79e2017-01-24 15:14:52 +00001073 `Context.load_verify_locations` for the ``cafile`` parameter, that
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001074 certificate is used as a trust root for the purposes of verifying
Alex Chan532b79e2017-01-24 15:14:52 +00001075 connections created using that `Context`.
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001076 """
Alex Gaynor03737182020-07-23 20:40:46 -04001077 with open(cafile, "w") as fObj:
Paul Kehrerbeaf9f52020-08-03 17:50:31 -05001078 fObj.write(root_cert_pem.decode("ascii"))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001079
1080 self._load_verify_locations_test(cafile)
1081
Alex Chan532b79e2017-01-24 15:14:52 +00001082 def test_load_verify_bytes_cafile(self, tmpfile):
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001083 """
Alex Chan532b79e2017-01-24 15:14:52 +00001084 `Context.load_verify_locations` accepts a file name as a `bytes`
1085 instance and uses the certificates within for verification purposes.
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001086 """
Alex Chan532b79e2017-01-24 15:14:52 +00001087 cafile = tmpfile + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001088 self._load_verify_cafile(cafile)
1089
Alex Chan532b79e2017-01-24 15:14:52 +00001090 def test_load_verify_unicode_cafile(self, tmpfile):
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001091 """
Alex Chan532b79e2017-01-24 15:14:52 +00001092 `Context.load_verify_locations` accepts a file name as a `unicode`
1093 instance and uses the certificates within for verification purposes.
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001094 """
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001095 self._load_verify_cafile(
Alex Chan532b79e2017-01-24 15:14:52 +00001096 tmpfile.decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001097 )
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001098
Alex Chan532b79e2017-01-24 15:14:52 +00001099 def test_load_verify_invalid_file(self, tmpfile):
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -04001100 """
Alex Chan532b79e2017-01-24 15:14:52 +00001101 `Context.load_verify_locations` raises `Error` when passed a
1102 non-existent cafile.
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -04001103 """
Paul Kehrer688538c2020-08-03 19:18:15 -05001104 clientContext = Context(SSLv23_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001105 with pytest.raises(Error):
1106 clientContext.load_verify_locations(tmpfile)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001107
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001108 def _load_verify_directory_locations_capath(self, capath):
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001109 """
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001110 Verify that if path to a directory containing certificate files is
1111 passed to ``Context.load_verify_locations`` for the ``capath``
1112 parameter, those certificates are used as trust roots for the purposes
1113 of verifying connections created using that ``Context``.
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001114 """
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001115 makedirs(capath)
Jean-Paul Calderone24dfb332011-05-04 18:10:26 -04001116 # Hash values computed manually with c_rehash to avoid depending on
1117 # c_rehash in the test suite. One is from OpenSSL 0.9.8, the other
1118 # from OpenSSL 1.0.0.
Alex Gaynor03737182020-07-23 20:40:46 -04001119 for name in [b"c7adac82.0", b"c3705638.0"]:
Jean-Paul Calderone05826732015-04-12 11:38:49 -04001120 cafile = join_bytes_or_unicode(capath, name)
Alex Gaynor03737182020-07-23 20:40:46 -04001121 with open(cafile, "w") as fObj:
Paul Kehrerbeaf9f52020-08-03 17:50:31 -05001122 fObj.write(root_cert_pem.decode("ascii"))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001123
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001124 self._load_verify_locations_test(None, capath)
1125
Alex Chan532b79e2017-01-24 15:14:52 +00001126 def test_load_verify_directory_bytes_capath(self, tmpfile):
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001127 """
Alex Chan532b79e2017-01-24 15:14:52 +00001128 `Context.load_verify_locations` accepts a directory name as a `bytes`
1129 instance and uses the certificates within for verification purposes.
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001130 """
1131 self._load_verify_directory_locations_capath(
Alex Chan532b79e2017-01-24 15:14:52 +00001132 tmpfile + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001133 )
1134
Alex Chan532b79e2017-01-24 15:14:52 +00001135 def test_load_verify_directory_unicode_capath(self, tmpfile):
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001136 """
Alex Chan532b79e2017-01-24 15:14:52 +00001137 `Context.load_verify_locations` accepts a directory name as a `unicode`
1138 instance and uses the certificates within for verification purposes.
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001139 """
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001140 self._load_verify_directory_locations_capath(
Alex Chan532b79e2017-01-24 15:14:52 +00001141 tmpfile.decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001142 )
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001143
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001144 def test_load_verify_locations_wrong_args(self):
1145 """
Alex Chan532b79e2017-01-24 15:14:52 +00001146 `Context.load_verify_locations` raises `TypeError` if with non-`str`
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001147 arguments.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001148 """
Paul Kehrer688538c2020-08-03 19:18:15 -05001149 context = Context(SSLv23_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001150 with pytest.raises(TypeError):
1151 context.load_verify_locations(object())
1152 with pytest.raises(TypeError):
1153 context.load_verify_locations(object(), object())
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001154
Hynek Schlawack734d3022015-09-05 19:19:32 +02001155 @pytest.mark.skipif(
Paul Kehrer55fb3412017-06-29 18:44:08 -05001156 not platform.startswith("linux"),
1157 reason="Loading fallback paths is a linux-specific behavior to "
Alex Gaynor03737182020-07-23 20:40:46 -04001158 "accommodate pyca/cryptography manylinux1 wheels",
Paul Kehrer55fb3412017-06-29 18:44:08 -05001159 )
1160 def test_fallback_default_verify_paths(self, monkeypatch):
1161 """
1162 Test that we load certificates successfully on linux from the fallback
1163 path. To do this we set the _CRYPTOGRAPHY_MANYLINUX1_CA_FILE and
1164 _CRYPTOGRAPHY_MANYLINUX1_CA_DIR vars to be equal to whatever the
1165 current OpenSSL default is and we disable
1166 SSL_CTX_SET_default_verify_paths so that it can't find certs unless
1167 it loads via fallback.
1168 """
Paul Kehrer688538c2020-08-03 19:18:15 -05001169 context = Context(SSLv23_METHOD)
Paul Kehrer55fb3412017-06-29 18:44:08 -05001170 monkeypatch.setattr(
1171 _lib, "SSL_CTX_set_default_verify_paths", lambda x: 1
1172 )
1173 monkeypatch.setattr(
1174 SSL,
1175 "_CRYPTOGRAPHY_MANYLINUX1_CA_FILE",
Alex Gaynor03737182020-07-23 20:40:46 -04001176 _ffi.string(_lib.X509_get_default_cert_file()),
Paul Kehrer55fb3412017-06-29 18:44:08 -05001177 )
1178 monkeypatch.setattr(
1179 SSL,
1180 "_CRYPTOGRAPHY_MANYLINUX1_CA_DIR",
Alex Gaynor03737182020-07-23 20:40:46 -04001181 _ffi.string(_lib.X509_get_default_cert_dir()),
Paul Kehrer55fb3412017-06-29 18:44:08 -05001182 )
1183 context.set_default_verify_paths()
1184 store = context.get_cert_store()
1185 sk_obj = _lib.X509_STORE_get0_objects(store._store)
1186 assert sk_obj != _ffi.NULL
1187 num = _lib.sk_X509_OBJECT_num(sk_obj)
1188 assert num != 0
1189
1190 def test_check_env_vars(self, monkeypatch):
1191 """
1192 Test that we return True/False appropriately if the env vars are set.
1193 """
Paul Kehrer688538c2020-08-03 19:18:15 -05001194 context = Context(SSLv23_METHOD)
Paul Kehrer55fb3412017-06-29 18:44:08 -05001195 dir_var = "CUSTOM_DIR_VAR"
1196 file_var = "CUSTOM_FILE_VAR"
1197 assert context._check_env_vars_set(dir_var, file_var) is False
1198 monkeypatch.setenv(dir_var, "value")
1199 monkeypatch.setenv(file_var, "value")
1200 assert context._check_env_vars_set(dir_var, file_var) is True
1201 assert context._check_env_vars_set(dir_var, file_var) is True
1202
1203 def test_verify_no_fallback_if_env_vars_set(self, monkeypatch):
1204 """
1205 Test that we don't use the fallback path if env vars are set.
1206 """
Paul Kehrer688538c2020-08-03 19:18:15 -05001207 context = Context(SSLv23_METHOD)
Paul Kehrer55fb3412017-06-29 18:44:08 -05001208 monkeypatch.setattr(
1209 _lib, "SSL_CTX_set_default_verify_paths", lambda x: 1
1210 )
Alex Gaynor03737182020-07-23 20:40:46 -04001211 dir_env_var = _ffi.string(_lib.X509_get_default_cert_dir_env()).decode(
1212 "ascii"
1213 )
Paul Kehrer55fb3412017-06-29 18:44:08 -05001214 file_env_var = _ffi.string(
1215 _lib.X509_get_default_cert_file_env()
1216 ).decode("ascii")
1217 monkeypatch.setenv(dir_env_var, "value")
1218 monkeypatch.setenv(file_env_var, "value")
1219 context.set_default_verify_paths()
1220
1221 monkeypatch.setattr(
Alex Gaynor03737182020-07-23 20:40:46 -04001222 context, "_fallback_default_verify_paths", raiser(SystemError)
Paul Kehrer55fb3412017-06-29 18:44:08 -05001223 )
1224 context.set_default_verify_paths()
1225
1226 @pytest.mark.skipif(
Hynek Schlawack734d3022015-09-05 19:19:32 +02001227 platform == "win32",
1228 reason="set_default_verify_paths appears not to work on Windows. "
Alex Gaynor03737182020-07-23 20:40:46 -04001229 "See LP#404343 and LP#404344.",
Hynek Schlawack734d3022015-09-05 19:19:32 +02001230 )
1231 def test_set_default_verify_paths(self):
1232 """
Alex Chan532b79e2017-01-24 15:14:52 +00001233 `Context.set_default_verify_paths` causes the platform-specific CA
1234 certificate locations to be used for verification purposes.
Hynek Schlawack734d3022015-09-05 19:19:32 +02001235 """
1236 # Testing this requires a server with a certificate signed by one
1237 # of the CAs in the platform CA location. Getting one of those
1238 # costs money. Fortunately (or unfortunately, depending on your
1239 # perspective), it's easy to think of a public server on the
1240 # internet which has such a certificate. Connecting to the network
1241 # in a unit test is bad, but it's the only way I can think of to
1242 # really test this. -exarkun
Hynek Schlawackbf887932015-10-21 17:13:47 +02001243 context = Context(SSLv23_METHOD)
Hynek Schlawack734d3022015-09-05 19:19:32 +02001244 context.set_default_verify_paths()
1245 context.set_verify(
1246 VERIFY_PEER,
Alex Gaynor03737182020-07-23 20:40:46 -04001247 lambda conn, cert, errno, depth, preverify_ok: preverify_ok,
1248 )
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001249
David Benjamin1fbe0642019-04-15 17:05:13 -05001250 client = socket_any_family()
Hynek Schlawackbf887932015-10-21 17:13:47 +02001251 client.connect(("encrypted.google.com", 443))
Hynek Schlawack734d3022015-09-05 19:19:32 +02001252 clientSSL = Connection(context, client)
1253 clientSSL.set_connect_state()
Alex Gaynor373926c2018-05-12 07:43:07 -04001254 clientSSL.set_tlsext_host_name(b"encrypted.google.com")
Hynek Schlawack734d3022015-09-05 19:19:32 +02001255 clientSSL.do_handshake()
1256 clientSSL.send(b"GET / HTTP/1.0\r\n\r\n")
Alex Chan532b79e2017-01-24 15:14:52 +00001257 assert clientSSL.recv(1024)
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05001258
Paul Kehrer55fb3412017-06-29 18:44:08 -05001259 def test_fallback_path_is_not_file_or_dir(self):
1260 """
1261 Test that when passed empty arrays or paths that do not exist no
1262 errors are raised.
1263 """
Paul Kehrer688538c2020-08-03 19:18:15 -05001264 context = Context(SSLv23_METHOD)
Paul Kehrer55fb3412017-06-29 18:44:08 -05001265 context._fallback_default_verify_paths([], [])
Alex Gaynor03737182020-07-23 20:40:46 -04001266 context._fallback_default_verify_paths(["/not/a/file"], ["/not/a/dir"])
Paul Kehrer55fb3412017-06-29 18:44:08 -05001267
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001268 def test_add_extra_chain_cert_invalid_cert(self):
1269 """
Alex Chan532b79e2017-01-24 15:14:52 +00001270 `Context.add_extra_chain_cert` raises `TypeError` if called with an
1271 object which is not an instance of `X509`.
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001272 """
Paul Kehrer688538c2020-08-03 19:18:15 -05001273 context = Context(SSLv23_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001274 with pytest.raises(TypeError):
1275 context.add_extra_chain_cert(object())
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001276
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001277 def _handshake_test(self, serverContext, clientContext):
1278 """
1279 Verify that a client and server created with the given contexts can
1280 successfully handshake and communicate.
1281 """
1282 serverSocket, clientSocket = socket_pair()
1283
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001284 server = Connection(serverContext, serverSocket)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001285 server.set_accept_state()
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001286
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001287 client = Connection(clientContext, clientSocket)
1288 client.set_connect_state()
1289
1290 # Make them talk to each other.
Alex Chan532b79e2017-01-24 15:14:52 +00001291 # interact_in_memory(client, server)
1292 for _ in range(3):
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001293 for s in [client, server]:
1294 try:
1295 s.do_handshake()
1296 except WantReadError:
1297 pass
1298
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001299 def test_set_verify_callback_connection_argument(self):
1300 """
1301 The first argument passed to the verify callback is the
Alex Chan532b79e2017-01-24 15:14:52 +00001302 `Connection` instance for which verification is taking place.
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001303 """
Paul Kehrer688538c2020-08-03 19:18:15 -05001304 serverContext = Context(SSLv23_METHOD)
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001305 serverContext.use_privatekey(
Paul Kehrerbeaf9f52020-08-03 17:50:31 -05001306 load_privatekey(FILETYPE_PEM, root_key_pem)
Alex Gaynor03737182020-07-23 20:40:46 -04001307 )
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001308 serverContext.use_certificate(
Paul Kehrerbeaf9f52020-08-03 17:50:31 -05001309 load_certificate(FILETYPE_PEM, root_cert_pem)
Alex Gaynor03737182020-07-23 20:40:46 -04001310 )
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001311 serverConnection = Connection(serverContext, None)
1312
1313 class VerifyCallback(object):
1314 def callback(self, connection, *args):
1315 self.connection = connection
1316 return 1
1317
1318 verify = VerifyCallback()
Paul Kehrer688538c2020-08-03 19:18:15 -05001319 clientContext = Context(SSLv23_METHOD)
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001320 clientContext.set_verify(VERIFY_PEER, verify.callback)
1321 clientConnection = Connection(clientContext, None)
1322 clientConnection.set_connect_state()
1323
Alex Chan532b79e2017-01-24 15:14:52 +00001324 handshake_in_memory(clientConnection, serverConnection)
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001325
Alex Chan532b79e2017-01-24 15:14:52 +00001326 assert verify.connection is clientConnection
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001327
Paul Kehrere7381862017-11-30 20:55:25 +08001328 def test_x509_in_verify_works(self):
1329 """
1330 We had a bug where the X509 cert instantiated in the callback wrapper
1331 didn't __init__ so it was missing objects needed when calling
1332 get_subject. This test sets up a handshake where we call get_subject
1333 on the cert provided to the verify callback.
1334 """
Paul Kehrer688538c2020-08-03 19:18:15 -05001335 serverContext = Context(SSLv23_METHOD)
Paul Kehrere7381862017-11-30 20:55:25 +08001336 serverContext.use_privatekey(
Paul Kehrerbeaf9f52020-08-03 17:50:31 -05001337 load_privatekey(FILETYPE_PEM, root_key_pem)
Alex Gaynor03737182020-07-23 20:40:46 -04001338 )
Paul Kehrere7381862017-11-30 20:55:25 +08001339 serverContext.use_certificate(
Paul Kehrerbeaf9f52020-08-03 17:50:31 -05001340 load_certificate(FILETYPE_PEM, root_cert_pem)
Alex Gaynor03737182020-07-23 20:40:46 -04001341 )
Paul Kehrere7381862017-11-30 20:55:25 +08001342 serverConnection = Connection(serverContext, None)
1343
1344 def verify_cb_get_subject(conn, cert, errnum, depth, ok):
1345 assert cert.get_subject()
1346 return 1
1347
Paul Kehrer688538c2020-08-03 19:18:15 -05001348 clientContext = Context(SSLv23_METHOD)
Paul Kehrere7381862017-11-30 20:55:25 +08001349 clientContext.set_verify(VERIFY_PEER, verify_cb_get_subject)
1350 clientConnection = Connection(clientContext, None)
1351 clientConnection.set_connect_state()
1352
1353 handshake_in_memory(clientConnection, serverConnection)
1354
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001355 def test_set_verify_callback_exception(self):
1356 """
Alex Chan532b79e2017-01-24 15:14:52 +00001357 If the verify callback passed to `Context.set_verify` raises an
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001358 exception, verification fails and the exception is propagated to the
Alex Chan532b79e2017-01-24 15:14:52 +00001359 caller of `Connection.do_handshake`.
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001360 """
Paul Kehrer7d5a3bf2019-01-21 12:24:02 -06001361 serverContext = Context(TLSv1_2_METHOD)
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001362 serverContext.use_privatekey(
Paul Kehrerbeaf9f52020-08-03 17:50:31 -05001363 load_privatekey(FILETYPE_PEM, root_key_pem)
Alex Gaynor03737182020-07-23 20:40:46 -04001364 )
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001365 serverContext.use_certificate(
Paul Kehrerbeaf9f52020-08-03 17:50:31 -05001366 load_certificate(FILETYPE_PEM, root_cert_pem)
Alex Gaynor03737182020-07-23 20:40:46 -04001367 )
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001368
Paul Kehrer7d5a3bf2019-01-21 12:24:02 -06001369 clientContext = Context(TLSv1_2_METHOD)
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001370
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001371 def verify_callback(*args):
1372 raise Exception("silly verify failure")
Alex Gaynor03737182020-07-23 20:40:46 -04001373
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001374 clientContext.set_verify(VERIFY_PEER, verify_callback)
1375
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01001376 with pytest.raises(Exception) as exc:
1377 self._handshake_test(serverContext, clientContext)
1378
Alex Chan532b79e2017-01-24 15:14:52 +00001379 assert "silly verify failure" == str(exc.value)
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001380
Maximilian Hils79b9c792020-08-08 03:08:17 +02001381 @pytest.mark.parametrize("mode", [SSL.VERIFY_PEER, SSL.VERIFY_NONE])
1382 def test_set_verify_default_callback(self, mode):
1383 """
1384 If the verify callback is omitted, the preverify value is used.
1385 """
1386 serverContext = Context(TLSv1_2_METHOD)
1387 serverContext.use_privatekey(
1388 load_privatekey(FILETYPE_PEM, root_key_pem)
1389 )
1390 serverContext.use_certificate(
1391 load_certificate(FILETYPE_PEM, root_cert_pem)
1392 )
1393
1394 clientContext = Context(TLSv1_2_METHOD)
1395 clientContext.set_verify(mode, None)
1396
1397 if mode == SSL.VERIFY_PEER:
1398 with pytest.raises(Exception) as exc:
1399 self._handshake_test(serverContext, clientContext)
1400 assert "certificate verify failed" in str(exc.value)
1401 else:
1402 self._handshake_test(serverContext, clientContext)
1403
Alex Chan532b79e2017-01-24 15:14:52 +00001404 def test_add_extra_chain_cert(self, tmpdir):
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001405 """
Alex Chan532b79e2017-01-24 15:14:52 +00001406 `Context.add_extra_chain_cert` accepts an `X509`
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001407 instance to add to the certificate chain.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001408
Alex Chan532b79e2017-01-24 15:14:52 +00001409 See `_create_certificate_chain` for the details of the
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001410 certificate chain tested.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001411
1412 The chain is tested by starting a server with scert and connecting
1413 to it with a client which trusts cacert and requires verification to
1414 succeed.
1415 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001416 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001417 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1418
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001419 # Dump the CA certificate to a file because that's the only way to load
1420 # it as a trusted CA in the client context.
Alex Gaynor03737182020-07-23 20:40:46 -04001421 for cert, name in [
1422 (cacert, "ca.pem"),
1423 (icert, "i.pem"),
1424 (scert, "s.pem"),
1425 ]:
1426 with tmpdir.join(name).open("w") as f:
1427 f.write(dump_certificate(FILETYPE_PEM, cert).decode("ascii"))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001428
Alex Gaynor03737182020-07-23 20:40:46 -04001429 for key, name in [(cakey, "ca.key"), (ikey, "i.key"), (skey, "s.key")]:
1430 with tmpdir.join(name).open("w") as f:
1431 f.write(dump_privatekey(FILETYPE_PEM, key).decode("ascii"))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001432
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001433 # Create the server context
Paul Kehrer688538c2020-08-03 19:18:15 -05001434 serverContext = Context(SSLv23_METHOD)
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001435 serverContext.use_privatekey(skey)
1436 serverContext.use_certificate(scert)
Jean-Paul Calderone16cf03d2010-09-08 18:53:39 -04001437 # The client already has cacert, we only need to give them icert.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001438 serverContext.add_extra_chain_cert(icert)
1439
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001440 # Create the client
Paul Kehrer688538c2020-08-03 19:18:15 -05001441 clientContext = Context(SSLv23_METHOD)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001442 clientContext.set_verify(
Alex Gaynor03737182020-07-23 20:40:46 -04001443 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb
1444 )
Alex Chan532b79e2017-01-24 15:14:52 +00001445 clientContext.load_verify_locations(str(tmpdir.join("ca.pem")))
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001446
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001447 # Try it out.
1448 self._handshake_test(serverContext, clientContext)
1449
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001450 def _use_certificate_chain_file_test(self, certdir):
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001451 """
Alex Chan532b79e2017-01-24 15:14:52 +00001452 Verify that `Context.use_certificate_chain_file` reads a
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001453 certificate chain from a specified file.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001454
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001455 The chain is tested by starting a server with scert and connecting to
1456 it with a client which trusts cacert and requires verification to
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001457 succeed.
1458 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001459 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001460 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1461
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001462 makedirs(certdir)
1463
Jean-Paul Calderone05826732015-04-12 11:38:49 -04001464 chainFile = join_bytes_or_unicode(certdir, "chain.pem")
1465 caFile = join_bytes_or_unicode(certdir, "ca.pem")
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001466
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001467 # Write out the chain file.
Alex Gaynor03737182020-07-23 20:40:46 -04001468 with open(chainFile, "wb") as fObj:
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001469 # Most specific to least general.
1470 fObj.write(dump_certificate(FILETYPE_PEM, scert))
1471 fObj.write(dump_certificate(FILETYPE_PEM, icert))
1472 fObj.write(dump_certificate(FILETYPE_PEM, cacert))
1473
Alex Gaynor03737182020-07-23 20:40:46 -04001474 with open(caFile, "w") as fObj:
1475 fObj.write(dump_certificate(FILETYPE_PEM, cacert).decode("ascii"))
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001476
Paul Kehrer688538c2020-08-03 19:18:15 -05001477 serverContext = Context(SSLv23_METHOD)
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001478 serverContext.use_certificate_chain_file(chainFile)
1479 serverContext.use_privatekey(skey)
1480
Paul Kehrer688538c2020-08-03 19:18:15 -05001481 clientContext = Context(SSLv23_METHOD)
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001482 clientContext.set_verify(
Alex Gaynor03737182020-07-23 20:40:46 -04001483 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb
1484 )
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001485 clientContext.load_verify_locations(caFile)
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001486
1487 self._handshake_test(serverContext, clientContext)
1488
Alex Chan532b79e2017-01-24 15:14:52 +00001489 def test_use_certificate_chain_file_bytes(self, tmpfile):
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001490 """
1491 ``Context.use_certificate_chain_file`` accepts the name of a file (as
1492 an instance of ``bytes``) to specify additional certificates to use to
1493 construct and verify a trust chain.
1494 """
1495 self._use_certificate_chain_file_test(
Alex Chan532b79e2017-01-24 15:14:52 +00001496 tmpfile + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001497 )
1498
Alex Chan532b79e2017-01-24 15:14:52 +00001499 def test_use_certificate_chain_file_unicode(self, tmpfile):
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001500 """
1501 ``Context.use_certificate_chain_file`` accepts the name of a file (as
1502 an instance of ``unicode``) to specify additional certificates to use
1503 to construct and verify a trust chain.
1504 """
1505 self._use_certificate_chain_file_test(
Alex Chan532b79e2017-01-24 15:14:52 +00001506 tmpfile.decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001507 )
1508
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001509 def test_use_certificate_chain_file_wrong_args(self):
1510 """
Alex Chan532b79e2017-01-24 15:14:52 +00001511 `Context.use_certificate_chain_file` raises `TypeError` if passed a
1512 non-byte string single argument.
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001513 """
Paul Kehrer688538c2020-08-03 19:18:15 -05001514 context = Context(SSLv23_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001515 with pytest.raises(TypeError):
1516 context.use_certificate_chain_file(object())
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001517
Alex Chan532b79e2017-01-24 15:14:52 +00001518 def test_use_certificate_chain_file_missing_file(self, tmpfile):
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001519 """
Alex Chan532b79e2017-01-24 15:14:52 +00001520 `Context.use_certificate_chain_file` raises `OpenSSL.SSL.Error` when
1521 passed a bad chain file name (for example, the name of a file which
1522 does not exist).
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001523 """
Paul Kehrer688538c2020-08-03 19:18:15 -05001524 context = Context(SSLv23_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001525 with pytest.raises(Error):
1526 context.use_certificate_chain_file(tmpfile)
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001527
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001528 def test_set_verify_mode(self):
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001529 """
Alex Chan532b79e2017-01-24 15:14:52 +00001530 `Context.get_verify_mode` returns the verify mode flags previously
1531 passed to `Context.set_verify`.
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001532 """
Paul Kehrer688538c2020-08-03 19:18:15 -05001533 context = Context(SSLv23_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001534 assert context.get_verify_mode() == 0
Maximilian Hils79b9c792020-08-08 03:08:17 +02001535 context.set_verify(VERIFY_PEER | VERIFY_CLIENT_ONCE)
Alex Chan532b79e2017-01-24 15:14:52 +00001536 assert context.get_verify_mode() == (VERIFY_PEER | VERIFY_CLIENT_ONCE)
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001537
Alex Gaynor03737182020-07-23 20:40:46 -04001538 @pytest.mark.parametrize("mode", [None, 1.0, object(), "mode"])
Alex Chanfb078d82017-04-20 11:16:15 +01001539 def test_set_verify_wrong_mode_arg(self, mode):
1540 """
1541 `Context.set_verify` raises `TypeError` if the first argument is
1542 not an integer.
1543 """
Paul Kehrer688538c2020-08-03 19:18:15 -05001544 context = Context(SSLv23_METHOD)
Alex Chanfb078d82017-04-20 11:16:15 +01001545 with pytest.raises(TypeError):
Maximilian Hils79b9c792020-08-08 03:08:17 +02001546 context.set_verify(mode=mode)
Alex Chanfb078d82017-04-20 11:16:15 +01001547
Maximilian Hils79b9c792020-08-08 03:08:17 +02001548 @pytest.mark.parametrize("callback", [1.0, "mode", ("foo", "bar")])
Alex Chanfb078d82017-04-20 11:16:15 +01001549 def test_set_verify_wrong_callable_arg(self, callback):
1550 """
Alex Gaynor40bc0f12018-05-14 14:06:16 -04001551 `Context.set_verify` raises `TypeError` if the second argument
Alex Chanfb078d82017-04-20 11:16:15 +01001552 is not callable.
1553 """
Paul Kehrer688538c2020-08-03 19:18:15 -05001554 context = Context(SSLv23_METHOD)
Alex Chanfb078d82017-04-20 11:16:15 +01001555 with pytest.raises(TypeError):
1556 context.set_verify(mode=VERIFY_PEER, callback=callback)
1557
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001558 def test_load_tmp_dh_wrong_args(self):
1559 """
Alex Chan532b79e2017-01-24 15:14:52 +00001560 `Context.load_tmp_dh` raises `TypeError` if called with a
1561 non-`str` argument.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001562 """
Paul Kehrer688538c2020-08-03 19:18:15 -05001563 context = Context(SSLv23_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001564 with pytest.raises(TypeError):
1565 context.load_tmp_dh(object())
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001566
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001567 def test_load_tmp_dh_missing_file(self):
1568 """
Alex Chan532b79e2017-01-24 15:14:52 +00001569 `Context.load_tmp_dh` raises `OpenSSL.SSL.Error` if the
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001570 specified file does not exist.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001571 """
Paul Kehrer688538c2020-08-03 19:18:15 -05001572 context = Context(SSLv23_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001573 with pytest.raises(Error):
1574 context.load_tmp_dh(b"hello")
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001575
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001576 def _load_tmp_dh_test(self, dhfilename):
Jean-Paul Calderone4e0c43f2015-04-13 10:15:17 -04001577 """
1578 Verify that calling ``Context.load_tmp_dh`` with the given filename
1579 does not raise an exception.
1580 """
Paul Kehrer688538c2020-08-03 19:18:15 -05001581 context = Context(SSLv23_METHOD)
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001582 with open(dhfilename, "w") as dhfile:
1583 dhfile.write(dhparam)
1584
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001585 context.load_tmp_dh(dhfilename)
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001586
Alex Chan532b79e2017-01-24 15:14:52 +00001587 def test_load_tmp_dh_bytes(self, tmpfile):
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001588 """
Alex Chan532b79e2017-01-24 15:14:52 +00001589 `Context.load_tmp_dh` loads Diffie-Hellman parameters from the
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001590 specified file (given as ``bytes``).
1591 """
1592 self._load_tmp_dh_test(
Alex Chan532b79e2017-01-24 15:14:52 +00001593 tmpfile + NON_ASCII.encode(getfilesystemencoding()),
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001594 )
1595
Alex Chan532b79e2017-01-24 15:14:52 +00001596 def test_load_tmp_dh_unicode(self, tmpfile):
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001597 """
Alex Chan532b79e2017-01-24 15:14:52 +00001598 `Context.load_tmp_dh` loads Diffie-Hellman parameters from the
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001599 specified file (given as ``unicode``).
1600 """
1601 self._load_tmp_dh_test(
Alex Chan532b79e2017-01-24 15:14:52 +00001602 tmpfile.decode(getfilesystemencoding()) + NON_ASCII,
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001603 )
1604
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001605 def test_set_tmp_ecdh(self):
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001606 """
Alex Chan532b79e2017-01-24 15:14:52 +00001607 `Context.set_tmp_ecdh` sets the elliptic curve for Diffie-Hellman to
1608 the specified curve.
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001609 """
Paul Kehrer688538c2020-08-03 19:18:15 -05001610 context = Context(SSLv23_METHOD)
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001611 for curve in get_elliptic_curves():
Hynek Schlawacka07fa8c2015-10-17 10:15:28 +02001612 if curve.name.startswith(u"Oakley-"):
Hynek Schlawack7408aff2015-10-17 09:51:16 +02001613 # Setting Oakley-EC2N-4 and Oakley-EC2N-3 adds
1614 # ('bignum routines', 'BN_mod_inverse', 'no inverse') to the
1615 # error queue on OpenSSL 1.0.2.
1616 continue
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001617 # The only easily "assertable" thing is that it does not raise an
1618 # exception.
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001619 context.set_tmp_ecdh(curve)
Alex Gaynor12dc0842014-01-17 12:51:31 -06001620
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001621 def test_set_session_cache_mode_wrong_args(self):
1622 """
Alex Chan532b79e2017-01-24 15:14:52 +00001623 `Context.set_session_cache_mode` raises `TypeError` if called with
1624 a non-integer argument.
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001625 called with other than one integer argument.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001626 """
Paul Kehrer688538c2020-08-03 19:18:15 -05001627 context = Context(SSLv23_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001628 with pytest.raises(TypeError):
1629 context.set_session_cache_mode(object())
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001630
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001631 def test_session_cache_mode(self):
1632 """
Alex Chan532b79e2017-01-24 15:14:52 +00001633 `Context.set_session_cache_mode` specifies how sessions are cached.
1634 The setting can be retrieved via `Context.get_session_cache_mode`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001635 """
Paul Kehrer688538c2020-08-03 19:18:15 -05001636 context = Context(SSLv23_METHOD)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001637 context.set_session_cache_mode(SESS_CACHE_OFF)
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001638 off = context.set_session_cache_mode(SESS_CACHE_BOTH)
Alex Chan532b79e2017-01-24 15:14:52 +00001639 assert SESS_CACHE_OFF == off
1640 assert SESS_CACHE_BOTH == context.get_session_cache_mode()
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001641
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001642 def test_get_cert_store(self):
1643 """
Alex Chan532b79e2017-01-24 15:14:52 +00001644 `Context.get_cert_store` returns a `X509Store` instance.
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001645 """
Paul Kehrer688538c2020-08-03 19:18:15 -05001646 context = Context(SSLv23_METHOD)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001647 store = context.get_cert_store()
Alex Chan532b79e2017-01-24 15:14:52 +00001648 assert isinstance(store, X509Store)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001649
Jeremy Lainé02261ad2018-05-16 18:33:25 +02001650 def test_set_tlsext_use_srtp_not_bytes(self):
1651 """
1652 `Context.set_tlsext_use_srtp' enables negotiating SRTP keying material.
1653
1654 It raises a TypeError if the list of profiles is not a byte string.
1655 """
Paul Kehrer688538c2020-08-03 19:18:15 -05001656 context = Context(SSLv23_METHOD)
Jeremy Lainé02261ad2018-05-16 18:33:25 +02001657 with pytest.raises(TypeError):
Alex Gaynor03737182020-07-23 20:40:46 -04001658 context.set_tlsext_use_srtp(text_type("SRTP_AES128_CM_SHA1_80"))
Jeremy Lainé02261ad2018-05-16 18:33:25 +02001659
1660 def test_set_tlsext_use_srtp_invalid_profile(self):
1661 """
1662 `Context.set_tlsext_use_srtp' enables negotiating SRTP keying material.
1663
1664 It raises an Error if the call to OpenSSL fails.
1665 """
Paul Kehrer688538c2020-08-03 19:18:15 -05001666 context = Context(SSLv23_METHOD)
Jeremy Lainé02261ad2018-05-16 18:33:25 +02001667 with pytest.raises(Error):
Alex Gaynor03737182020-07-23 20:40:46 -04001668 context.set_tlsext_use_srtp(b"SRTP_BOGUS")
Jeremy Lainé02261ad2018-05-16 18:33:25 +02001669
1670 def test_set_tlsext_use_srtp_valid(self):
1671 """
1672 `Context.set_tlsext_use_srtp' enables negotiating SRTP keying material.
1673
1674 It does not return anything.
1675 """
Paul Kehrer688538c2020-08-03 19:18:15 -05001676 context = Context(SSLv23_METHOD)
Alex Gaynor03737182020-07-23 20:40:46 -04001677 assert context.set_tlsext_use_srtp(b"SRTP_AES128_CM_SHA1_80") is None
Jeremy Lainé02261ad2018-05-16 18:33:25 +02001678
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001679
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001680class TestServerNameCallback(object):
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001681 """
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001682 Tests for `Context.set_tlsext_servername_callback` and its
1683 interaction with `Connection`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001684 """
Alex Gaynor03737182020-07-23 20:40:46 -04001685
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001686 def test_old_callback_forgotten(self):
1687 """
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001688 If `Context.set_tlsext_servername_callback` is used to specify
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001689 a new callback, the one it replaces is dereferenced.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001690 """
Alex Gaynor03737182020-07-23 20:40:46 -04001691
Alex Chanfb078d82017-04-20 11:16:15 +01001692 def callback(connection): # pragma: no cover
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001693 pass
1694
Alex Chanfb078d82017-04-20 11:16:15 +01001695 def replacement(connection): # pragma: no cover
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001696 pass
1697
Paul Kehrer688538c2020-08-03 19:18:15 -05001698 context = Context(SSLv23_METHOD)
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001699 context.set_tlsext_servername_callback(callback)
1700
1701 tracker = ref(callback)
1702 del callback
1703
1704 context.set_tlsext_servername_callback(replacement)
Jean-Paul Calderoned4033eb2014-01-11 08:21:46 -05001705
1706 # One run of the garbage collector happens to work on CPython. PyPy
1707 # doesn't collect the underlying object until a second run for whatever
1708 # reason. That's fine, it still demonstrates our code has properly
1709 # dropped the reference.
1710 collect()
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001711 collect()
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001712
1713 callback = tracker()
1714 if callback is not None:
1715 referrers = get_referrers(callback)
Alex Chanfb078d82017-04-20 11:16:15 +01001716 if len(referrers) > 1: # pragma: nocover
1717 pytest.fail("Some references remain: %r" % (referrers,))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001718
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001719 def test_no_servername(self):
1720 """
1721 When a client specifies no server name, the callback passed to
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001722 `Context.set_tlsext_servername_callback` is invoked and the
1723 result of `Connection.get_servername` is `None`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001724 """
1725 args = []
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001726
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001727 def servername(conn):
1728 args.append((conn, conn.get_servername()))
Alex Gaynor03737182020-07-23 20:40:46 -04001729
Paul Kehrer688538c2020-08-03 19:18:15 -05001730 context = Context(SSLv23_METHOD)
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001731 context.set_tlsext_servername_callback(servername)
1732
1733 # Lose our reference to it. The Context is responsible for keeping it
1734 # alive now.
1735 del servername
1736 collect()
1737
1738 # Necessary to actually accept the connection
1739 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001740 context.use_certificate(
Alex Gaynor03737182020-07-23 20:40:46 -04001741 load_certificate(FILETYPE_PEM, server_cert_pem)
1742 )
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001743
1744 # Do a little connection to trigger the logic
1745 server = Connection(context, None)
1746 server.set_accept_state()
1747
Paul Kehrer688538c2020-08-03 19:18:15 -05001748 client = Connection(Context(SSLv23_METHOD), None)
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001749 client.set_connect_state()
1750
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001751 interact_in_memory(server, client)
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001752
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001753 assert args == [(server, None)]
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001754
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001755 def test_servername(self):
1756 """
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001757 When a client specifies a server name in its hello message, the
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001758 callback passed to `Contexts.set_tlsext_servername_callback` is
1759 invoked and the result of `Connection.get_servername` is that
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001760 server name.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001761 """
1762 args = []
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001763
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001764 def servername(conn):
1765 args.append((conn, conn.get_servername()))
Alex Gaynor03737182020-07-23 20:40:46 -04001766
Paul Kehrer688538c2020-08-03 19:18:15 -05001767 context = Context(SSLv23_METHOD)
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001768 context.set_tlsext_servername_callback(servername)
1769
1770 # Necessary to actually accept the connection
1771 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001772 context.use_certificate(
Alex Gaynor03737182020-07-23 20:40:46 -04001773 load_certificate(FILETYPE_PEM, server_cert_pem)
1774 )
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001775
1776 # Do a little connection to trigger the logic
1777 server = Connection(context, None)
1778 server.set_accept_state()
1779
Paul Kehrer688538c2020-08-03 19:18:15 -05001780 client = Connection(Context(SSLv23_METHOD), None)
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001781 client.set_connect_state()
Alex Gaynore7f51982016-09-11 11:48:14 -04001782 client.set_tlsext_host_name(b"foo1.example.com")
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001783
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001784 interact_in_memory(server, client)
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001785
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001786 assert args == [(server, b"foo1.example.com")]
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001787
1788
Alex Chanec1e32d2016-11-10 14:11:45 +00001789class TestApplicationLayerProtoNegotiation(object):
Cory Benfield12eae892014-06-07 15:42:56 +01001790 """
1791 Tests for ALPN in PyOpenSSL.
1792 """
Alex Gaynor03737182020-07-23 20:40:46 -04001793
Alex Gaynor77debda2020-04-07 13:40:59 -04001794 def test_alpn_success(self):
1795 """
1796 Clients and servers that agree on the negotiated ALPN protocol can
1797 correct establish a connection, and the agreed protocol is reported
1798 by the connections.
1799 """
1800 select_args = []
Cory Benfield12eae892014-06-07 15:42:56 +01001801
Alex Gaynor77debda2020-04-07 13:40:59 -04001802 def select(conn, options):
1803 select_args.append((conn, options))
Alex Gaynor03737182020-07-23 20:40:46 -04001804 return b"spdy/2"
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001805
Paul Kehrer688538c2020-08-03 19:18:15 -05001806 client_context = Context(SSLv23_METHOD)
Alex Gaynor03737182020-07-23 20:40:46 -04001807 client_context.set_alpn_protos([b"http/1.1", b"spdy/2"])
Cory Benfield12eae892014-06-07 15:42:56 +01001808
Paul Kehrer688538c2020-08-03 19:18:15 -05001809 server_context = Context(SSLv23_METHOD)
Alex Gaynor77debda2020-04-07 13:40:59 -04001810 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01001811
Alex Gaynor77debda2020-04-07 13:40:59 -04001812 # Necessary to actually accept the connection
1813 server_context.use_privatekey(
Alex Gaynor03737182020-07-23 20:40:46 -04001814 load_privatekey(FILETYPE_PEM, server_key_pem)
1815 )
Alex Gaynor77debda2020-04-07 13:40:59 -04001816 server_context.use_certificate(
Alex Gaynor03737182020-07-23 20:40:46 -04001817 load_certificate(FILETYPE_PEM, server_cert_pem)
1818 )
Cory Benfield12eae892014-06-07 15:42:56 +01001819
Alex Gaynor77debda2020-04-07 13:40:59 -04001820 # Do a little connection to trigger the logic
1821 server = Connection(server_context, None)
1822 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001823
Alex Gaynor77debda2020-04-07 13:40:59 -04001824 client = Connection(client_context, None)
1825 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001826
Alex Gaynor77debda2020-04-07 13:40:59 -04001827 interact_in_memory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001828
Alex Gaynor03737182020-07-23 20:40:46 -04001829 assert select_args == [(server, [b"http/1.1", b"spdy/2"])]
Alex Gaynor77debda2020-04-07 13:40:59 -04001830
Alex Gaynor03737182020-07-23 20:40:46 -04001831 assert server.get_alpn_proto_negotiated() == b"spdy/2"
1832 assert client.get_alpn_proto_negotiated() == b"spdy/2"
Alex Gaynor77debda2020-04-07 13:40:59 -04001833
1834 def test_alpn_set_on_connection(self):
1835 """
1836 The same as test_alpn_success, but setting the ALPN protocols on
1837 the connection rather than the context.
1838 """
1839 select_args = []
1840
1841 def select(conn, options):
1842 select_args.append((conn, options))
Alex Gaynor03737182020-07-23 20:40:46 -04001843 return b"spdy/2"
Alex Gaynor77debda2020-04-07 13:40:59 -04001844
1845 # Setup the client context but don't set any ALPN protocols.
Paul Kehrer688538c2020-08-03 19:18:15 -05001846 client_context = Context(SSLv23_METHOD)
Alex Gaynor77debda2020-04-07 13:40:59 -04001847
Paul Kehrer688538c2020-08-03 19:18:15 -05001848 server_context = Context(SSLv23_METHOD)
Alex Gaynor77debda2020-04-07 13:40:59 -04001849 server_context.set_alpn_select_callback(select)
1850
1851 # Necessary to actually accept the connection
1852 server_context.use_privatekey(
Alex Gaynor03737182020-07-23 20:40:46 -04001853 load_privatekey(FILETYPE_PEM, server_key_pem)
1854 )
Alex Gaynor77debda2020-04-07 13:40:59 -04001855 server_context.use_certificate(
Alex Gaynor03737182020-07-23 20:40:46 -04001856 load_certificate(FILETYPE_PEM, server_cert_pem)
1857 )
Alex Gaynor77debda2020-04-07 13:40:59 -04001858
1859 # Do a little connection to trigger the logic
1860 server = Connection(server_context, None)
1861 server.set_accept_state()
1862
1863 # Set the ALPN protocols on the client connection.
1864 client = Connection(client_context, None)
Alex Gaynor03737182020-07-23 20:40:46 -04001865 client.set_alpn_protos([b"http/1.1", b"spdy/2"])
Alex Gaynor77debda2020-04-07 13:40:59 -04001866 client.set_connect_state()
1867
1868 interact_in_memory(server, client)
1869
Alex Gaynor03737182020-07-23 20:40:46 -04001870 assert select_args == [(server, [b"http/1.1", b"spdy/2"])]
Alex Gaynor77debda2020-04-07 13:40:59 -04001871
Alex Gaynor03737182020-07-23 20:40:46 -04001872 assert server.get_alpn_proto_negotiated() == b"spdy/2"
1873 assert client.get_alpn_proto_negotiated() == b"spdy/2"
Alex Gaynor77debda2020-04-07 13:40:59 -04001874
1875 def test_alpn_server_fail(self):
1876 """
1877 When clients and servers cannot agree on what protocol to use next
1878 the TLS connection does not get established.
1879 """
1880 select_args = []
1881
1882 def select(conn, options):
1883 select_args.append((conn, options))
Alex Gaynor03737182020-07-23 20:40:46 -04001884 return b""
Alex Gaynor77debda2020-04-07 13:40:59 -04001885
Paul Kehrer688538c2020-08-03 19:18:15 -05001886 client_context = Context(SSLv23_METHOD)
Alex Gaynor03737182020-07-23 20:40:46 -04001887 client_context.set_alpn_protos([b"http/1.1", b"spdy/2"])
Alex Gaynor77debda2020-04-07 13:40:59 -04001888
Paul Kehrer688538c2020-08-03 19:18:15 -05001889 server_context = Context(SSLv23_METHOD)
Alex Gaynor77debda2020-04-07 13:40:59 -04001890 server_context.set_alpn_select_callback(select)
1891
1892 # Necessary to actually accept the connection
1893 server_context.use_privatekey(
Alex Gaynor03737182020-07-23 20:40:46 -04001894 load_privatekey(FILETYPE_PEM, server_key_pem)
1895 )
Alex Gaynor77debda2020-04-07 13:40:59 -04001896 server_context.use_certificate(
Alex Gaynor03737182020-07-23 20:40:46 -04001897 load_certificate(FILETYPE_PEM, server_cert_pem)
1898 )
Alex Gaynor77debda2020-04-07 13:40:59 -04001899
1900 # Do a little connection to trigger the logic
1901 server = Connection(server_context, None)
1902 server.set_accept_state()
1903
1904 client = Connection(client_context, None)
1905 client.set_connect_state()
1906
1907 # If the client doesn't return anything, the connection will fail.
1908 with pytest.raises(Error):
Alex Chanec1e32d2016-11-10 14:11:45 +00001909 interact_in_memory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001910
Alex Gaynor03737182020-07-23 20:40:46 -04001911 assert select_args == [(server, [b"http/1.1", b"spdy/2"])]
Cory Benfielde46fa842015-04-13 16:50:49 -04001912
Alex Gaynor77debda2020-04-07 13:40:59 -04001913 def test_alpn_no_server_overlap(self):
1914 """
1915 A server can allow a TLS handshake to complete without
1916 agreeing to an application protocol by returning
1917 ``NO_OVERLAPPING_PROTOCOLS``.
1918 """
1919 refusal_args = []
Cory Benfield12eae892014-06-07 15:42:56 +01001920
Alex Gaynor77debda2020-04-07 13:40:59 -04001921 def refusal(conn, options):
1922 refusal_args.append((conn, options))
1923 return NO_OVERLAPPING_PROTOCOLS
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001924
Alex Gaynor77debda2020-04-07 13:40:59 -04001925 client_context = Context(SSLv23_METHOD)
Alex Gaynor03737182020-07-23 20:40:46 -04001926 client_context.set_alpn_protos([b"http/1.1", b"spdy/2"])
Cory Benfield12eae892014-06-07 15:42:56 +01001927
Alex Gaynor77debda2020-04-07 13:40:59 -04001928 server_context = Context(SSLv23_METHOD)
1929 server_context.set_alpn_select_callback(refusal)
Cory Benfield12eae892014-06-07 15:42:56 +01001930
Alex Gaynor77debda2020-04-07 13:40:59 -04001931 # Necessary to actually accept the connection
1932 server_context.use_privatekey(
Alex Gaynor03737182020-07-23 20:40:46 -04001933 load_privatekey(FILETYPE_PEM, server_key_pem)
1934 )
Alex Gaynor77debda2020-04-07 13:40:59 -04001935 server_context.use_certificate(
Alex Gaynor03737182020-07-23 20:40:46 -04001936 load_certificate(FILETYPE_PEM, server_cert_pem)
1937 )
Cory Benfield12eae892014-06-07 15:42:56 +01001938
Alex Gaynor77debda2020-04-07 13:40:59 -04001939 # Do a little connection to trigger the logic
1940 server = Connection(server_context, None)
1941 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001942
Alex Gaynor77debda2020-04-07 13:40:59 -04001943 client = Connection(client_context, None)
1944 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001945
Alex Gaynor77debda2020-04-07 13:40:59 -04001946 # Do the dance.
1947 interact_in_memory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001948
Alex Gaynor03737182020-07-23 20:40:46 -04001949 assert refusal_args == [(server, [b"http/1.1", b"spdy/2"])]
Alex Gaynor77debda2020-04-07 13:40:59 -04001950
Alex Gaynor03737182020-07-23 20:40:46 -04001951 assert client.get_alpn_proto_negotiated() == b""
Alex Gaynor77debda2020-04-07 13:40:59 -04001952
1953 def test_alpn_select_cb_returns_invalid_value(self):
1954 """
1955 If the ALPN selection callback returns anything other than
1956 a bytestring or ``NO_OVERLAPPING_PROTOCOLS``, a
1957 :py:exc:`TypeError` is raised.
1958 """
1959 invalid_cb_args = []
1960
1961 def invalid_cb(conn, options):
1962 invalid_cb_args.append((conn, options))
1963 return u"can't return unicode"
1964
1965 client_context = Context(SSLv23_METHOD)
Alex Gaynor03737182020-07-23 20:40:46 -04001966 client_context.set_alpn_protos([b"http/1.1", b"spdy/2"])
Alex Gaynor77debda2020-04-07 13:40:59 -04001967
1968 server_context = Context(SSLv23_METHOD)
1969 server_context.set_alpn_select_callback(invalid_cb)
1970
1971 # Necessary to actually accept the connection
1972 server_context.use_privatekey(
Alex Gaynor03737182020-07-23 20:40:46 -04001973 load_privatekey(FILETYPE_PEM, server_key_pem)
1974 )
Alex Gaynor77debda2020-04-07 13:40:59 -04001975 server_context.use_certificate(
Alex Gaynor03737182020-07-23 20:40:46 -04001976 load_certificate(FILETYPE_PEM, server_cert_pem)
1977 )
Alex Gaynor77debda2020-04-07 13:40:59 -04001978
1979 # Do a little connection to trigger the logic
1980 server = Connection(server_context, None)
1981 server.set_accept_state()
1982
1983 client = Connection(client_context, None)
1984 client.set_connect_state()
1985
1986 # Do the dance.
1987 with pytest.raises(TypeError):
Alex Chanec1e32d2016-11-10 14:11:45 +00001988 interact_in_memory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001989
Alex Gaynor03737182020-07-23 20:40:46 -04001990 assert invalid_cb_args == [(server, [b"http/1.1", b"spdy/2"])]
Cory Benfield12eae892014-06-07 15:42:56 +01001991
Alex Gaynor03737182020-07-23 20:40:46 -04001992 assert client.get_alpn_proto_negotiated() == b""
Cory Benfield12eae892014-06-07 15:42:56 +01001993
Alex Gaynor77debda2020-04-07 13:40:59 -04001994 def test_alpn_no_server(self):
1995 """
1996 When clients and servers cannot agree on what protocol to use next
1997 because the server doesn't offer ALPN, no protocol is negotiated.
1998 """
Paul Kehrer688538c2020-08-03 19:18:15 -05001999 client_context = Context(SSLv23_METHOD)
Alex Gaynor03737182020-07-23 20:40:46 -04002000 client_context.set_alpn_protos([b"http/1.1", b"spdy/2"])
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002001
Paul Kehrer688538c2020-08-03 19:18:15 -05002002 server_context = Context(SSLv23_METHOD)
Cory Benfield12eae892014-06-07 15:42:56 +01002003
Alex Gaynor77debda2020-04-07 13:40:59 -04002004 # Necessary to actually accept the connection
2005 server_context.use_privatekey(
Alex Gaynor03737182020-07-23 20:40:46 -04002006 load_privatekey(FILETYPE_PEM, server_key_pem)
2007 )
Alex Gaynor77debda2020-04-07 13:40:59 -04002008 server_context.use_certificate(
Alex Gaynor03737182020-07-23 20:40:46 -04002009 load_certificate(FILETYPE_PEM, server_cert_pem)
2010 )
Cory Benfield12eae892014-06-07 15:42:56 +01002011
Alex Gaynor77debda2020-04-07 13:40:59 -04002012 # Do a little connection to trigger the logic
2013 server = Connection(server_context, None)
2014 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01002015
Alex Gaynor77debda2020-04-07 13:40:59 -04002016 client = Connection(client_context, None)
2017 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01002018
Alex Gaynor77debda2020-04-07 13:40:59 -04002019 # Do the dance.
2020 interact_in_memory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01002021
Alex Gaynor03737182020-07-23 20:40:46 -04002022 assert client.get_alpn_proto_negotiated() == b""
Cory Benfield12eae892014-06-07 15:42:56 +01002023
Alex Gaynor77debda2020-04-07 13:40:59 -04002024 def test_alpn_callback_exception(self):
2025 """
2026 We can handle exceptions in the ALPN select callback.
2027 """
2028 select_args = []
Cory Benfield12eae892014-06-07 15:42:56 +01002029
Alex Gaynor77debda2020-04-07 13:40:59 -04002030 def select(conn, options):
2031 select_args.append((conn, options))
2032 raise TypeError()
Cory Benfield12eae892014-06-07 15:42:56 +01002033
Paul Kehrer688538c2020-08-03 19:18:15 -05002034 client_context = Context(SSLv23_METHOD)
Alex Gaynor03737182020-07-23 20:40:46 -04002035 client_context.set_alpn_protos([b"http/1.1", b"spdy/2"])
Mark Williams5d890a02019-11-17 19:56:26 -08002036
Paul Kehrer688538c2020-08-03 19:18:15 -05002037 server_context = Context(SSLv23_METHOD)
Alex Gaynor77debda2020-04-07 13:40:59 -04002038 server_context.set_alpn_select_callback(select)
Mark Williams5d890a02019-11-17 19:56:26 -08002039
Alex Gaynor77debda2020-04-07 13:40:59 -04002040 # Necessary to actually accept the connection
2041 server_context.use_privatekey(
Alex Gaynor03737182020-07-23 20:40:46 -04002042 load_privatekey(FILETYPE_PEM, server_key_pem)
2043 )
Alex Gaynor77debda2020-04-07 13:40:59 -04002044 server_context.use_certificate(
Alex Gaynor03737182020-07-23 20:40:46 -04002045 load_certificate(FILETYPE_PEM, server_cert_pem)
2046 )
Mark Williams5d890a02019-11-17 19:56:26 -08002047
Alex Gaynor77debda2020-04-07 13:40:59 -04002048 # Do a little connection to trigger the logic
2049 server = Connection(server_context, None)
2050 server.set_accept_state()
Mark Williams5d890a02019-11-17 19:56:26 -08002051
Alex Gaynor77debda2020-04-07 13:40:59 -04002052 client = Connection(client_context, None)
2053 client.set_connect_state()
Mark Williams5d890a02019-11-17 19:56:26 -08002054
Alex Gaynor77debda2020-04-07 13:40:59 -04002055 with pytest.raises(TypeError):
Mark Williams5d890a02019-11-17 19:56:26 -08002056 interact_in_memory(server, client)
Alex Gaynor03737182020-07-23 20:40:46 -04002057 assert select_args == [(server, [b"http/1.1", b"spdy/2"])]
Cory Benfield0f7b04c2015-04-13 17:51:12 -04002058
Cory Benfieldf1177e72015-04-12 09:11:49 -04002059
Alex Chanec1e32d2016-11-10 14:11:45 +00002060class TestSession(object):
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05002061 """
2062 Unit tests for :py:obj:`OpenSSL.SSL.Session`.
2063 """
Alex Gaynor03737182020-07-23 20:40:46 -04002064
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05002065 def test_construction(self):
2066 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002067 :py:class:`Session` can be constructed with no arguments, creating
2068 a new instance of that type.
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05002069 """
2070 new_session = Session()
Alex Chanec1e32d2016-11-10 14:11:45 +00002071 assert isinstance(new_session, Session)
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05002072
2073
Alex Chan1c0cb662017-01-30 07:13:30 +00002074class TestConnection(object):
Rick Deane15b1472009-07-09 15:53:42 -05002075 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002076 Unit tests for `OpenSSL.SSL.Connection`.
Rick Deane15b1472009-07-09 15:53:42 -05002077 """
Alex Gaynor03737182020-07-23 20:40:46 -04002078
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04002079 # XXX get_peer_certificate -> None
2080 # XXX sock_shutdown
2081 # XXX master_key -> TypeError
2082 # XXX server_random -> TypeError
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04002083 # XXX connect -> TypeError
2084 # XXX connect_ex -> TypeError
2085 # XXX set_connect_state -> TypeError
2086 # XXX set_accept_state -> TypeError
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04002087 # XXX do_handshake -> TypeError
2088 # XXX bio_read -> TypeError
2089 # XXX recv -> TypeError
2090 # XXX send -> TypeError
2091 # XXX bio_write -> TypeError
2092
Rick Deane15b1472009-07-09 15:53:42 -05002093 def test_type(self):
2094 """
Alex Gaynor01f90a12019-02-07 09:14:48 -05002095 `Connection` can be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -05002096 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002097 ctx = Context(SSLv23_METHOD)
Alex Gaynor03737182020-07-23 20:40:46 -04002098 assert is_consistent_type(Connection, "Connection", ctx, None)
Rick Deane15b1472009-07-09 15:53:42 -05002099
Alex Gaynor03737182020-07-23 20:40:46 -04002100 @pytest.mark.parametrize("bad_context", [object(), "context", None, 1])
Alex Chanfb078d82017-04-20 11:16:15 +01002101 def test_wrong_args(self, bad_context):
2102 """
2103 `Connection.__init__` raises `TypeError` if called with a non-`Context`
2104 instance argument.
2105 """
2106 with pytest.raises(TypeError):
2107 Connection(bad_context)
2108
Alex Gaynor03737182020-07-23 20:40:46 -04002109 @pytest.mark.parametrize("bad_bio", [object(), None, 1, [1, 2, 3]])
Daniel Holth079c9632019-11-17 22:45:52 -05002110 def test_bio_write_wrong_args(self, bad_bio):
2111 """
2112 `Connection.bio_write` raises `TypeError` if called with a non-bytes
2113 (or text) argument.
2114 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002115 context = Context(SSLv23_METHOD)
Daniel Holth079c9632019-11-17 22:45:52 -05002116 connection = Connection(context, None)
2117 with pytest.raises(TypeError):
2118 connection.bio_write(bad_bio)
2119
2120 def test_bio_write(self):
2121 """
2122 `Connection.bio_write` does not raise if called with bytes or
2123 bytearray, warns if called with text.
2124 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002125 context = Context(SSLv23_METHOD)
Daniel Holth079c9632019-11-17 22:45:52 -05002126 connection = Connection(context, None)
Alex Gaynor03737182020-07-23 20:40:46 -04002127 connection.bio_write(b"xy")
2128 connection.bio_write(bytearray(b"za"))
Daniel Holth079c9632019-11-17 22:45:52 -05002129 with pytest.warns(DeprecationWarning):
Alex Gaynor03737182020-07-23 20:40:46 -04002130 connection.bio_write(u"deprecated")
Daniel Holth079c9632019-11-17 22:45:52 -05002131
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002132 def test_get_context(self):
2133 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002134 `Connection.get_context` returns the `Context` instance used to
2135 construct the `Connection` instance.
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002136 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002137 context = Context(SSLv23_METHOD)
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002138 connection = Connection(context, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002139 assert connection.get_context() is context
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002140
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002141 def test_set_context_wrong_args(self):
2142 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002143 `Connection.set_context` raises `TypeError` if called with a
Alex Chanfb078d82017-04-20 11:16:15 +01002144 non-`Context` instance argument.
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002145 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002146 ctx = Context(SSLv23_METHOD)
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002147 connection = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002148 with pytest.raises(TypeError):
2149 connection.set_context(object())
2150 with pytest.raises(TypeError):
2151 connection.set_context("hello")
2152 with pytest.raises(TypeError):
2153 connection.set_context(1)
2154 assert ctx is connection.get_context()
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002155
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002156 def test_set_context(self):
2157 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002158 `Connection.set_context` specifies a new `Context` instance to be
2159 used for the connection.
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002160 """
2161 original = Context(SSLv23_METHOD)
Paul Kehrer688538c2020-08-03 19:18:15 -05002162 replacement = Context(SSLv23_METHOD)
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002163 connection = Connection(original, None)
2164 connection.set_context(replacement)
Alex Chan1c0cb662017-01-30 07:13:30 +00002165 assert replacement is connection.get_context()
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002166 # Lose our references to the contexts, just in case the Connection
2167 # isn't properly managing its own contributions to their reference
2168 # counts.
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002169 del original, replacement
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002170 collect()
2171
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002172 def test_set_tlsext_host_name_wrong_args(self):
2173 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002174 If `Connection.set_tlsext_host_name` is called with a non-byte string
2175 argument or a byte string with an embedded NUL, `TypeError` is raised.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002176 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002177 conn = Connection(Context(SSLv23_METHOD), None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002178 with pytest.raises(TypeError):
2179 conn.set_tlsext_host_name(object())
2180 with pytest.raises(TypeError):
2181 conn.set_tlsext_host_name(b"with\0null")
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002182
Hugo van Kemenade60827f82019-08-30 00:39:35 +03002183 if not PY2:
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002184 # On Python 3.x, don't accidentally implicitly convert from text.
Alex Chan1c0cb662017-01-30 07:13:30 +00002185 with pytest.raises(TypeError):
2186 conn.set_tlsext_host_name(b"example.com".decode("ascii"))
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04002187
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002188 def test_pending(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002189 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002190 `Connection.pending` returns the number of bytes available for
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002191 immediate read.
2192 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002193 connection = Connection(Context(SSLv23_METHOD), None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002194 assert connection.pending() == 0
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002195
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002196 def test_peek(self):
2197 """
Hynek Schlawack3bcf3152017-02-18 08:25:34 +01002198 `Connection.recv` peeks into the connection if `socket.MSG_PEEK` is
2199 passed.
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002200 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002201 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04002202 server.send(b"xy")
2203 assert client.recv(2, MSG_PEEK) == b"xy"
2204 assert client.recv(2, MSG_PEEK) == b"xy"
2205 assert client.recv(2) == b"xy"
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002206
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002207 def test_connect_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002208 """
Hynek Schlawack3bcf3152017-02-18 08:25:34 +01002209 `Connection.connect` raises `TypeError` if called with a non-address
2210 argument.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002211 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002212 connection = Connection(Context(SSLv23_METHOD), socket_any_family())
Alex Chan1c0cb662017-01-30 07:13:30 +00002213 with pytest.raises(TypeError):
2214 connection.connect(None)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002215
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002216 def test_connect_refused(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002217 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002218 `Connection.connect` raises `socket.error` if the underlying socket
2219 connect method raises it.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002220 """
David Benjamin1fbe0642019-04-15 17:05:13 -05002221 client = socket_any_family()
Paul Kehrer688538c2020-08-03 19:18:15 -05002222 context = Context(SSLv23_METHOD)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002223 clientSSL = Connection(context, client)
Alex Gaynor122717b2015-09-05 14:14:18 -04002224 # pytest.raises here doesn't work because of a bug in py.test on Python
2225 # 2.6: https://github.com/pytest-dev/pytest/issues/988
Alex Gaynore69c2782015-09-05 14:07:48 -04002226 try:
David Benjamin1fbe0642019-04-15 17:05:13 -05002227 clientSSL.connect((loopback_address(client), 1))
Alex Gaynore69c2782015-09-05 14:07:48 -04002228 except error as e:
Alex Gaynor20a4c082015-09-05 14:24:15 -04002229 exc = e
2230 assert exc.args[0] == ECONNREFUSED
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002231
2232 def test_connect(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002233 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002234 `Connection.connect` establishes a connection to the specified address.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002235 """
David Benjamin1fbe0642019-04-15 17:05:13 -05002236 port = socket_any_family()
Alex Gaynor03737182020-07-23 20:40:46 -04002237 port.bind(("", 0))
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002238 port.listen(3)
2239
Paul Kehrer688538c2020-08-03 19:18:15 -05002240 clientSSL = Connection(Context(SSLv23_METHOD), socket(port.family))
David Benjamin1fbe0642019-04-15 17:05:13 -05002241 clientSSL.connect((loopback_address(port), port.getsockname()[1]))
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002242 # XXX An assertion? Or something?
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002243
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002244 @pytest.mark.skipif(
2245 platform == "darwin",
Alex Gaynor03737182020-07-23 20:40:46 -04002246 reason="connect_ex sometimes causes a kernel panic on OS X 10.6.4",
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002247 )
2248 def test_connect_ex(self):
2249 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002250 If there is a connection error, `Connection.connect_ex` returns the
2251 errno instead of raising an exception.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002252 """
David Benjamin1fbe0642019-04-15 17:05:13 -05002253 port = socket_any_family()
Alex Gaynor03737182020-07-23 20:40:46 -04002254 port.bind(("", 0))
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002255 port.listen(3)
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002256
Paul Kehrer688538c2020-08-03 19:18:15 -05002257 clientSSL = Connection(Context(SSLv23_METHOD), socket(port.family))
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002258 clientSSL.setblocking(False)
2259 result = clientSSL.connect_ex(port.getsockname())
2260 expected = (EINPROGRESS, EWOULDBLOCK)
Alex Chan1c0cb662017-01-30 07:13:30 +00002261 assert result in expected
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002262
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002263 def test_accept(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002264 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002265 `Connection.accept` accepts a pending connection attempt and returns a
2266 tuple of a new `Connection` (the accepted client) and the address the
2267 connection originated from.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002268 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002269 ctx = Context(SSLv23_METHOD)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002270 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2271 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
David Benjamin1fbe0642019-04-15 17:05:13 -05002272 port = socket_any_family()
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002273 portSSL = Connection(ctx, port)
Alex Gaynor03737182020-07-23 20:40:46 -04002274 portSSL.bind(("", 0))
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002275 portSSL.listen(3)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002276
Paul Kehrer688538c2020-08-03 19:18:15 -05002277 clientSSL = Connection(Context(SSLv23_METHOD), socket(port.family))
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002278
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002279 # Calling portSSL.getsockname() here to get the server IP address
2280 # sounds great, but frequently fails on Windows.
David Benjamin1fbe0642019-04-15 17:05:13 -05002281 clientSSL.connect((loopback_address(port), portSSL.getsockname()[1]))
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002282
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002283 serverSSL, address = portSSL.accept()
2284
Alex Chan1c0cb662017-01-30 07:13:30 +00002285 assert isinstance(serverSSL, Connection)
2286 assert serverSSL.get_context() is ctx
2287 assert address == clientSSL.getsockname()
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002288
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002289 def test_shutdown_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002290 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002291 `Connection.set_shutdown` raises `TypeError` if called with arguments
2292 other than integers.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002293 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002294 connection = Connection(Context(SSLv23_METHOD), None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002295 with pytest.raises(TypeError):
2296 connection.set_shutdown(None)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002297
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002298 def test_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002299 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002300 `Connection.shutdown` performs an SSL-level connection shutdown.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002301 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002302 server, client = loopback()
2303 assert not server.shutdown()
2304 assert server.get_shutdown() == SENT_SHUTDOWN
2305 with pytest.raises(ZeroReturnError):
2306 client.recv(1024)
2307 assert client.get_shutdown() == RECEIVED_SHUTDOWN
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04002308 client.shutdown()
Alex Chan1c0cb662017-01-30 07:13:30 +00002309 assert client.get_shutdown() == (SENT_SHUTDOWN | RECEIVED_SHUTDOWN)
2310 with pytest.raises(ZeroReturnError):
2311 server.recv(1024)
2312 assert server.get_shutdown() == (SENT_SHUTDOWN | RECEIVED_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002313
Paul Aurichc85e0862015-01-08 08:34:33 -08002314 def test_shutdown_closed(self):
2315 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002316 If the underlying socket is closed, `Connection.shutdown` propagates
2317 the write error from the low level write call.
Paul Aurichc85e0862015-01-08 08:34:33 -08002318 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002319 server, client = loopback()
Paul Aurichc85e0862015-01-08 08:34:33 -08002320 server.sock_shutdown(2)
Alex Chan1c0cb662017-01-30 07:13:30 +00002321 with pytest.raises(SysCallError) as exc:
2322 server.shutdown()
Alex Chanfb078d82017-04-20 11:16:15 +01002323 if platform == "win32":
2324 assert exc.value.args[0] == ESHUTDOWN
2325 else:
2326 assert exc.value.args[0] == EPIPE
Paul Aurichc85e0862015-01-08 08:34:33 -08002327
Glyph89389472015-04-14 17:29:26 -04002328 def test_shutdown_truncated(self):
Glyph6064ec32015-04-14 16:38:22 -04002329 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002330 If the underlying connection is truncated, `Connection.shutdown`
2331 raises an `Error`.
Glyph6064ec32015-04-14 16:38:22 -04002332 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002333 server_ctx = Context(SSLv23_METHOD)
2334 client_ctx = Context(SSLv23_METHOD)
Glyph89389472015-04-14 17:29:26 -04002335 server_ctx.use_privatekey(
Alex Gaynor03737182020-07-23 20:40:46 -04002336 load_privatekey(FILETYPE_PEM, server_key_pem)
2337 )
Glyph89389472015-04-14 17:29:26 -04002338 server_ctx.use_certificate(
Alex Gaynor03737182020-07-23 20:40:46 -04002339 load_certificate(FILETYPE_PEM, server_cert_pem)
2340 )
Glyph89389472015-04-14 17:29:26 -04002341 server = Connection(server_ctx, None)
2342 client = Connection(client_ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002343 handshake_in_memory(client, server)
2344 assert not server.shutdown()
2345 with pytest.raises(WantReadError):
2346 server.shutdown()
Glyph89389472015-04-14 17:29:26 -04002347 server.bio_shutdown()
Alex Chan1c0cb662017-01-30 07:13:30 +00002348 with pytest.raises(Error):
2349 server.shutdown()
Glyph6064ec32015-04-14 16:38:22 -04002350
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002351 def test_set_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002352 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002353 `Connection.set_shutdown` sets the state of the SSL connection
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002354 shutdown process.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002355 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002356 connection = Connection(Context(SSLv23_METHOD), socket_any_family())
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002357 connection.set_shutdown(RECEIVED_SHUTDOWN)
Alex Chan1c0cb662017-01-30 07:13:30 +00002358 assert connection.get_shutdown() == RECEIVED_SHUTDOWN
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002359
kjavaf248592015-09-07 12:14:01 +01002360 def test_state_string(self):
2361 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002362 `Connection.state_string` verbosely describes the current state of
2363 the `Connection`.
kjavaf248592015-09-07 12:14:01 +01002364 """
Hynek Schlawackb0274ce2015-10-16 19:56:26 +02002365 server, client = socket_pair()
Alex Chan1c0cb662017-01-30 07:13:30 +00002366 server = loopback_server_factory(server)
2367 client = loopback_client_factory(client)
kjavaf248592015-09-07 12:14:01 +01002368
Alex Gaynor5af32d02016-09-24 01:52:21 -04002369 assert server.get_state_string() in [
Alex Gaynor03737182020-07-23 20:40:46 -04002370 b"before/accept initialization",
2371 b"before SSL initialization",
Alex Gaynor5af32d02016-09-24 01:52:21 -04002372 ]
2373 assert client.get_state_string() in [
Alex Gaynor03737182020-07-23 20:40:46 -04002374 b"before/connect initialization",
2375 b"before SSL initialization",
Alex Gaynor5af32d02016-09-24 01:52:21 -04002376 ]
kjavaf248592015-09-07 12:14:01 +01002377
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002378 def test_app_data(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002379 """
2380 Any object can be set as app data by passing it to
Alex Chan1c0cb662017-01-30 07:13:30 +00002381 `Connection.set_app_data` and later retrieved with
2382 `Connection.get_app_data`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002383 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002384 conn = Connection(Context(SSLv23_METHOD), None)
Todd Chapman4f73e4f2015-08-27 11:26:43 -04002385 assert None is conn.get_app_data()
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002386 app_data = object()
2387 conn.set_app_data(app_data)
Todd Chapman4f73e4f2015-08-27 11:26:43 -04002388 assert conn.get_app_data() is app_data
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002389
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002390 def test_makefile(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002391 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002392 `Connection.makefile` is not implemented and calling that
2393 method raises `NotImplementedError`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002394 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002395 conn = Connection(Context(SSLv23_METHOD), None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002396 with pytest.raises(NotImplementedError):
2397 conn.makefile()
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002398
Jeremy Lainé460a19d2018-05-16 19:44:19 +02002399 def test_get_certificate(self):
2400 """
2401 `Connection.get_certificate` returns the local certificate.
2402 """
2403 chain = _create_certificate_chain()
2404 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
2405
Paul Kehrer688538c2020-08-03 19:18:15 -05002406 context = Context(SSLv23_METHOD)
Jeremy Lainé460a19d2018-05-16 19:44:19 +02002407 context.use_certificate(scert)
2408 client = Connection(context, None)
2409 cert = client.get_certificate()
2410 assert cert is not None
2411 assert "Server Certificate" == cert.get_subject().CN
2412
2413 def test_get_certificate_none(self):
2414 """
2415 `Connection.get_certificate` returns the local certificate.
2416
2417 If there is no certificate, it returns None.
2418 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002419 context = Context(SSLv23_METHOD)
Jeremy Lainé460a19d2018-05-16 19:44:19 +02002420 client = Connection(context, None)
2421 cert = client.get_certificate()
2422 assert cert is None
2423
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002424 def test_get_peer_cert_chain(self):
2425 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002426 `Connection.get_peer_cert_chain` returns a list of certificates
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002427 which the connected server returned for the certification verification.
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002428 """
2429 chain = _create_certificate_chain()
2430 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
2431
Paul Kehrer688538c2020-08-03 19:18:15 -05002432 serverContext = Context(SSLv23_METHOD)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002433 serverContext.use_privatekey(skey)
2434 serverContext.use_certificate(scert)
2435 serverContext.add_extra_chain_cert(icert)
2436 serverContext.add_extra_chain_cert(cacert)
2437 server = Connection(serverContext, None)
2438 server.set_accept_state()
2439
2440 # Create the client
Paul Kehrer688538c2020-08-03 19:18:15 -05002441 clientContext = Context(SSLv23_METHOD)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002442 clientContext.set_verify(VERIFY_NONE, verify_cb)
2443 client = Connection(clientContext, None)
2444 client.set_connect_state()
2445
Alex Chan1c0cb662017-01-30 07:13:30 +00002446 interact_in_memory(client, server)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002447
2448 chain = client.get_peer_cert_chain()
Alex Chan1c0cb662017-01-30 07:13:30 +00002449 assert len(chain) == 3
2450 assert "Server Certificate" == chain[0].get_subject().CN
2451 assert "Intermediate Certificate" == chain[1].get_subject().CN
2452 assert "Authority Certificate" == chain[2].get_subject().CN
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002453
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002454 def test_get_peer_cert_chain_none(self):
2455 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002456 `Connection.get_peer_cert_chain` returns `None` if the peer sends
2457 no certificate chain.
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002458 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002459 ctx = Context(SSLv23_METHOD)
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002460 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2461 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
2462 server = Connection(ctx, None)
2463 server.set_accept_state()
Paul Kehrer688538c2020-08-03 19:18:15 -05002464 client = Connection(Context(SSLv23_METHOD), None)
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002465 client.set_connect_state()
Alex Chan1c0cb662017-01-30 07:13:30 +00002466 interact_in_memory(client, server)
2467 assert None is server.get_peer_cert_chain()
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002468
Shane Harvey33c54992020-08-05 16:48:51 -07002469 def test_get_verified_chain(self):
2470 """
2471 `Connection.get_verified_chain` returns a list of certificates
2472 which the connected server returned for the certification verification.
2473 """
2474 chain = _create_certificate_chain()
2475 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
2476
2477 serverContext = Context(SSLv23_METHOD)
2478 serverContext.use_privatekey(skey)
2479 serverContext.use_certificate(scert)
2480 serverContext.add_extra_chain_cert(icert)
2481 serverContext.add_extra_chain_cert(cacert)
2482 server = Connection(serverContext, None)
2483 server.set_accept_state()
2484
2485 # Create the client
2486 clientContext = Context(SSLv23_METHOD)
2487 # cacert is self-signed so the client must trust it for verification
2488 # to succeed.
2489 clientContext.get_cert_store().add_cert(cacert)
2490 clientContext.set_verify(VERIFY_PEER, verify_cb)
2491 client = Connection(clientContext, None)
2492 client.set_connect_state()
2493
2494 interact_in_memory(client, server)
2495
2496 chain = client.get_verified_chain()
2497 assert len(chain) == 3
2498 assert "Server Certificate" == chain[0].get_subject().CN
2499 assert "Intermediate Certificate" == chain[1].get_subject().CN
2500 assert "Authority Certificate" == chain[2].get_subject().CN
2501
2502 def test_get_verified_chain_none(self):
2503 """
2504 `Connection.get_verified_chain` returns `None` if the peer sends
2505 no certificate chain.
2506 """
2507 ctx = Context(SSLv23_METHOD)
2508 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2509 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
2510 server = Connection(ctx, None)
2511 server.set_accept_state()
2512 client = Connection(Context(SSLv23_METHOD), None)
2513 client.set_connect_state()
2514 interact_in_memory(client, server)
2515 assert None is server.get_verified_chain()
2516
2517 def test_get_verified_chain_unconnected(self):
2518 """
2519 `Connection.get_verified_chain` returns `None` when used with an object
2520 which has not been connected.
2521 """
2522 ctx = Context(SSLv23_METHOD)
2523 server = Connection(ctx, None)
2524 assert None is server.get_verified_chain()
2525
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002526 def test_get_session_unconnected(self):
2527 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002528 `Connection.get_session` returns `None` when used with an object
2529 which has not been connected.
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002530 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002531 ctx = Context(SSLv23_METHOD)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002532 server = Connection(ctx, None)
2533 session = server.get_session()
Alex Chan1c0cb662017-01-30 07:13:30 +00002534 assert None is session
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002535
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002536 def test_server_get_session(self):
2537 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002538 On the server side of a connection, `Connection.get_session` returns a
2539 `Session` instance representing the SSL session for that connection.
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002540 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002541 server, client = loopback()
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002542 session = server.get_session()
Alex Chan1c0cb662017-01-30 07:13:30 +00002543 assert isinstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002544
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002545 def test_client_get_session(self):
2546 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002547 On the client side of a connection, `Connection.get_session`
2548 returns a `Session` instance representing the SSL session for
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002549 that connection.
2550 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002551 server, client = loopback()
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002552 session = client.get_session()
Alex Chan1c0cb662017-01-30 07:13:30 +00002553 assert isinstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002554
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002555 def test_set_session_wrong_args(self):
2556 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002557 `Connection.set_session` raises `TypeError` if called with an object
2558 that is not an instance of `Session`.
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002559 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002560 ctx = Context(SSLv23_METHOD)
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002561 connection = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002562 with pytest.raises(TypeError):
2563 connection.set_session(123)
2564 with pytest.raises(TypeError):
2565 connection.set_session("hello")
2566 with pytest.raises(TypeError):
2567 connection.set_session(object())
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002568
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002569 def test_client_set_session(self):
2570 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002571 `Connection.set_session`, when used prior to a connection being
2572 established, accepts a `Session` instance and causes an attempt to
2573 re-use the session it represents when the SSL handshake is performed.
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002574 """
2575 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2576 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
Paul Kehrer7d5a3bf2019-01-21 12:24:02 -06002577 ctx = Context(TLSv1_2_METHOD)
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002578 ctx.use_privatekey(key)
2579 ctx.use_certificate(cert)
2580 ctx.set_session_id("unity-test")
2581
2582 def makeServer(socket):
2583 server = Connection(ctx, socket)
2584 server.set_accept_state()
2585 return server
2586
Alex Gaynor03737182020-07-23 20:40:46 -04002587 originalServer, originalClient = loopback(server_factory=makeServer)
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002588 originalSession = originalClient.get_session()
2589
2590 def makeClient(socket):
Alex Chan1c0cb662017-01-30 07:13:30 +00002591 client = loopback_client_factory(socket)
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002592 client.set_session(originalSession)
2593 return client
Alex Gaynor03737182020-07-23 20:40:46 -04002594
Alex Chan1c0cb662017-01-30 07:13:30 +00002595 resumedServer, resumedClient = loopback(
Alex Gaynor03737182020-07-23 20:40:46 -04002596 server_factory=makeServer, client_factory=makeClient
2597 )
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002598
2599 # This is a proxy: in general, we have no access to any unique
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002600 # identifier for the session (new enough versions of OpenSSL expose
2601 # a hash which could be usable, but "new enough" is very, very new).
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002602 # Instead, exploit the fact that the master key is re-used if the
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002603 # session is re-used. As long as the master key for the two
2604 # connections is the same, the session was re-used!
Alex Chan1c0cb662017-01-30 07:13:30 +00002605 assert originalServer.master_key() == resumedServer.master_key()
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002606
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002607 def test_set_session_wrong_method(self):
2608 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002609 If `Connection.set_session` is passed a `Session` instance associated
2610 with a context using a different SSL method than the `Connection`
2611 is using, a `OpenSSL.SSL.Error` is raised.
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002612 """
Alex Gaynor5af32d02016-09-24 01:52:21 -04002613 # Make this work on both OpenSSL 1.0.0, which doesn't support TLSv1.2
2614 # and also on OpenSSL 1.1.0 which doesn't support SSLv3. (SSL_ST_INIT
2615 # is a way to check for 1.1.0)
Alex Gaynoraa32e712017-06-29 20:56:12 -07002616 if SSL_ST_INIT is None:
2617 v1 = TLSv1_2_METHOD
2618 v2 = TLSv1_METHOD
2619 elif hasattr(_lib, "SSLv3_method"):
Alex Gaynor5af32d02016-09-24 01:52:21 -04002620 v1 = TLSv1_METHOD
2621 v2 = SSLv3_METHOD
2622 else:
Alex Gaynoraa32e712017-06-29 20:56:12 -07002623 pytest.skip("Test requires either OpenSSL 1.1.0 or SSLv3")
Alex Gaynor5af32d02016-09-24 01:52:21 -04002624
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002625 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2626 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
Alex Gaynor5af32d02016-09-24 01:52:21 -04002627 ctx = Context(v1)
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002628 ctx.use_privatekey(key)
2629 ctx.use_certificate(cert)
Paul Kehrerc45a6ea2020-08-03 15:54:20 -05002630 ctx.set_session_id(b"unity-test")
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002631
2632 def makeServer(socket):
2633 server = Connection(ctx, socket)
2634 server.set_accept_state()
2635 return server
2636
Alex Gaynor5af32d02016-09-24 01:52:21 -04002637 def makeOriginalClient(socket):
2638 client = Connection(Context(v1), socket)
2639 client.set_connect_state()
2640 return client
2641
Alex Chan1c0cb662017-01-30 07:13:30 +00002642 originalServer, originalClient = loopback(
Alex Gaynor03737182020-07-23 20:40:46 -04002643 server_factory=makeServer, client_factory=makeOriginalClient
2644 )
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002645 originalSession = originalClient.get_session()
2646
2647 def makeClient(socket):
2648 # Intentionally use a different, incompatible method here.
Alex Gaynor5af32d02016-09-24 01:52:21 -04002649 client = Connection(Context(v2), socket)
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002650 client.set_connect_state()
2651 client.set_session(originalSession)
2652 return client
2653
Alex Chan1c0cb662017-01-30 07:13:30 +00002654 with pytest.raises(Error):
2655 loopback(client_factory=makeClient, server_factory=makeServer)
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002656
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002657 def test_wantWriteError(self):
2658 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002659 `Connection` methods which generate output raise
2660 `OpenSSL.SSL.WantWriteError` if writing to the connection's BIO
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002661 fail indicating a should-write state.
2662 """
2663 client_socket, server_socket = socket_pair()
2664 # Fill up the client's send buffer so Connection won't be able to write
Jean-Paul Calderonebbff8b92014-03-22 14:20:30 -04002665 # anything. Only write a single byte at a time so we can be sure we
2666 # completely fill the buffer. Even though the socket API is allowed to
2667 # signal a short write via its return value it seems this doesn't
2668 # always happen on all platforms (FreeBSD and OS X particular) for the
2669 # very last bit of available buffer space.
2670 msg = b"x"
caternb2777a42018-08-09 15:38:13 -04002671 for i in range(1024 * 1024 * 64):
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002672 try:
2673 client_socket.send(msg)
2674 except error as e:
2675 if e.errno == EWOULDBLOCK:
2676 break
2677 raise
2678 else:
Alex Chan1c0cb662017-01-30 07:13:30 +00002679 pytest.fail(
Alex Gaynor03737182020-07-23 20:40:46 -04002680 "Failed to fill socket buffer, cannot test BIO want write"
2681 )
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002682
Paul Kehrer688538c2020-08-03 19:18:15 -05002683 ctx = Context(SSLv23_METHOD)
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002684 conn = Connection(ctx, client_socket)
2685 # Client's speak first, so make it an SSL client
2686 conn.set_connect_state()
Alex Chan1c0cb662017-01-30 07:13:30 +00002687 with pytest.raises(WantWriteError):
2688 conn.do_handshake()
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002689
2690 # XXX want_read
2691
Fedor Brunner416f4a12014-03-28 13:18:38 +01002692 def test_get_finished_before_connect(self):
Fedor Brunner5747b932014-03-05 14:22:34 +01002693 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002694 `Connection.get_finished` returns `None` before TLS handshake
2695 is completed.
Fedor Brunner5747b932014-03-05 14:22:34 +01002696 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002697 ctx = Context(SSLv23_METHOD)
Fedor Brunner5747b932014-03-05 14:22:34 +01002698 connection = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002699 assert connection.get_finished() is None
Fedor Brunner416f4a12014-03-28 13:18:38 +01002700
2701 def test_get_peer_finished_before_connect(self):
2702 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002703 `Connection.get_peer_finished` returns `None` before TLS handshake
2704 is completed.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002705 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002706 ctx = Context(SSLv23_METHOD)
Fedor Brunner416f4a12014-03-28 13:18:38 +01002707 connection = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002708 assert connection.get_peer_finished() is None
Fedor Brunner5747b932014-03-05 14:22:34 +01002709
Fedor Brunner416f4a12014-03-28 13:18:38 +01002710 def test_get_finished(self):
2711 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002712 `Connection.get_finished` method returns the TLS Finished message send
2713 from client, or server. Finished messages are send during
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002714 TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002715 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002716 server, client = loopback()
Fedor Brunner416f4a12014-03-28 13:18:38 +01002717
Alex Chan1c0cb662017-01-30 07:13:30 +00002718 assert server.get_finished() is not None
2719 assert len(server.get_finished()) > 0
Fedor Brunner416f4a12014-03-28 13:18:38 +01002720
2721 def test_get_peer_finished(self):
2722 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002723 `Connection.get_peer_finished` method returns the TLS Finished
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002724 message received from client, or server. Finished messages are send
2725 during 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_peer_finished() is not None
2730 assert len(server.get_peer_finished()) > 0
Fedor Brunner5747b932014-03-05 14:22:34 +01002731
Fedor Brunner416f4a12014-03-28 13:18:38 +01002732 def test_tls_finished_message_symmetry(self):
2733 """
Hynek Schlawackdddd1112015-09-05 21:12:30 +02002734 The TLS Finished message send by server must be the TLS Finished
2735 message received by client.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002736
Hynek Schlawackdddd1112015-09-05 21:12:30 +02002737 The TLS Finished message send by client must be the TLS Finished
2738 message received by server.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002739 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002740 server, client = loopback()
Fedor Brunner416f4a12014-03-28 13:18:38 +01002741
Alex Chan1c0cb662017-01-30 07:13:30 +00002742 assert server.get_finished() == client.get_peer_finished()
2743 assert client.get_finished() == server.get_peer_finished()
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002744
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002745 def test_get_cipher_name_before_connect(self):
2746 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002747 `Connection.get_cipher_name` returns `None` if no connection
2748 has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002749 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002750 ctx = Context(SSLv23_METHOD)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002751 conn = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002752 assert conn.get_cipher_name() is None
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002753
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002754 def test_get_cipher_name(self):
2755 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002756 `Connection.get_cipher_name` returns a `unicode` string giving the
2757 name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002758 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002759 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04002760 server_cipher_name, client_cipher_name = (
2761 server.get_cipher_name(),
2762 client.get_cipher_name(),
2763 )
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002764
Alex Chan1c0cb662017-01-30 07:13:30 +00002765 assert isinstance(server_cipher_name, text_type)
2766 assert isinstance(client_cipher_name, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002767
Alex Chan1c0cb662017-01-30 07:13:30 +00002768 assert server_cipher_name == client_cipher_name
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002769
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002770 def test_get_cipher_version_before_connect(self):
2771 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002772 `Connection.get_cipher_version` returns `None` if no connection
2773 has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002774 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002775 ctx = Context(SSLv23_METHOD)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002776 conn = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002777 assert conn.get_cipher_version() is None
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002778
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002779 def test_get_cipher_version(self):
2780 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002781 `Connection.get_cipher_version` returns a `unicode` string giving
2782 the protocol name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002783 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002784 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04002785 server_cipher_version, client_cipher_version = (
2786 server.get_cipher_version(),
2787 client.get_cipher_version(),
2788 )
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002789
Alex Chan1c0cb662017-01-30 07:13:30 +00002790 assert isinstance(server_cipher_version, text_type)
2791 assert isinstance(client_cipher_version, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002792
Alex Chan1c0cb662017-01-30 07:13:30 +00002793 assert server_cipher_version == client_cipher_version
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002794
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002795 def test_get_cipher_bits_before_connect(self):
2796 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002797 `Connection.get_cipher_bits` returns `None` if no connection has
2798 been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002799 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002800 ctx = Context(SSLv23_METHOD)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002801 conn = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002802 assert conn.get_cipher_bits() is None
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002803
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002804 def test_get_cipher_bits(self):
2805 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002806 `Connection.get_cipher_bits` returns the number of secret bits
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002807 of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002808 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002809 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04002810 server_cipher_bits, client_cipher_bits = (
2811 server.get_cipher_bits(),
2812 client.get_cipher_bits(),
2813 )
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002814
Alex Chan1c0cb662017-01-30 07:13:30 +00002815 assert isinstance(server_cipher_bits, int)
2816 assert isinstance(client_cipher_bits, int)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002817
Alex Chan1c0cb662017-01-30 07:13:30 +00002818 assert server_cipher_bits == client_cipher_bits
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002819
Jim Shaverabff1882015-05-27 09:15:55 -04002820 def test_get_protocol_version_name(self):
2821 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002822 `Connection.get_protocol_version_name()` returns a string giving the
2823 protocol version of the current connection.
Jim Shaverabff1882015-05-27 09:15:55 -04002824 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002825 server, client = loopback()
Jim Shaverabff1882015-05-27 09:15:55 -04002826 client_protocol_version_name = client.get_protocol_version_name()
2827 server_protocol_version_name = server.get_protocol_version_name()
2828
Alex Chan1c0cb662017-01-30 07:13:30 +00002829 assert isinstance(server_protocol_version_name, text_type)
2830 assert isinstance(client_protocol_version_name, text_type)
Jim Shaverabff1882015-05-27 09:15:55 -04002831
Alex Chan1c0cb662017-01-30 07:13:30 +00002832 assert server_protocol_version_name == client_protocol_version_name
Jim Shaverabff1882015-05-27 09:15:55 -04002833
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002834 def test_get_protocol_version(self):
2835 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002836 `Connection.get_protocol_version()` returns an integer
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002837 giving the protocol version of the current connection.
2838 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002839 server, client = loopback()
Jim Shaver85a4dff2015-04-27 17:42:46 -04002840 client_protocol_version = client.get_protocol_version()
2841 server_protocol_version = server.get_protocol_version()
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002842
Alex Chan1c0cb662017-01-30 07:13:30 +00002843 assert isinstance(server_protocol_version, int)
2844 assert isinstance(client_protocol_version, int)
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002845
Alex Chan1c0cb662017-01-30 07:13:30 +00002846 assert server_protocol_version == client_protocol_version
2847
2848 def test_wantReadError(self):
2849 """
2850 `Connection.bio_read` raises `OpenSSL.SSL.WantReadError` if there are
2851 no bytes available to be read from the BIO.
2852 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002853 ctx = Context(SSLv23_METHOD)
Alex Chan1c0cb662017-01-30 07:13:30 +00002854 conn = Connection(ctx, None)
2855 with pytest.raises(WantReadError):
2856 conn.bio_read(1024)
2857
Alex Gaynor03737182020-07-23 20:40:46 -04002858 @pytest.mark.parametrize("bufsize", [1.0, None, object(), "bufsize"])
Alex Chanfb078d82017-04-20 11:16:15 +01002859 def test_bio_read_wrong_args(self, bufsize):
2860 """
2861 `Connection.bio_read` raises `TypeError` if passed a non-integer
2862 argument.
2863 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002864 ctx = Context(SSLv23_METHOD)
Alex Chanfb078d82017-04-20 11:16:15 +01002865 conn = Connection(ctx, None)
2866 with pytest.raises(TypeError):
2867 conn.bio_read(bufsize)
2868
Alex Chan1c0cb662017-01-30 07:13:30 +00002869 def test_buffer_size(self):
2870 """
2871 `Connection.bio_read` accepts an integer giving the maximum number
2872 of bytes to read and return.
2873 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002874 ctx = Context(SSLv23_METHOD)
Alex Chan1c0cb662017-01-30 07:13:30 +00002875 conn = Connection(ctx, None)
2876 conn.set_connect_state()
2877 try:
2878 conn.do_handshake()
2879 except WantReadError:
2880 pass
2881 data = conn.bio_read(2)
2882 assert 2 == len(data)
2883
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002884
Alex Chanb7480992017-01-30 14:04:47 +00002885class TestConnectionGetCipherList(object):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002886 """
Alex Chanb7480992017-01-30 14:04:47 +00002887 Tests for `Connection.get_cipher_list`.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002888 """
Alex Gaynor03737182020-07-23 20:40:46 -04002889
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002890 def test_result(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002891 """
Alex Chanb7480992017-01-30 14:04:47 +00002892 `Connection.get_cipher_list` returns a list of `bytes` giving the
2893 names of the ciphers which might be used.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002894 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002895 connection = Connection(Context(SSLv23_METHOD), None)
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002896 ciphers = connection.get_cipher_list()
Alex Chanb7480992017-01-30 14:04:47 +00002897 assert isinstance(ciphers, list)
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002898 for cipher in ciphers:
Alex Chanb7480992017-01-30 14:04:47 +00002899 assert isinstance(cipher, str)
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002900
2901
Maximilian Hils868dc3c2017-02-10 14:56:55 +01002902class VeryLarge(bytes):
2903 """
2904 Mock object so that we don't have to allocate 2**31 bytes
2905 """
Alex Gaynor03737182020-07-23 20:40:46 -04002906
Maximilian Hils868dc3c2017-02-10 14:56:55 +01002907 def __len__(self):
Alex Gaynor03737182020-07-23 20:40:46 -04002908 return 2 ** 31
Maximilian Hils868dc3c2017-02-10 14:56:55 +01002909
2910
Alex Chanb7480992017-01-30 14:04:47 +00002911class TestConnectionSend(object):
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002912 """
Alex Chanb7480992017-01-30 14:04:47 +00002913 Tests for `Connection.send`.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002914 """
Alex Gaynor03737182020-07-23 20:40:46 -04002915
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002916 def test_wrong_args(self):
2917 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002918 When called with arguments other than string argument for its first
Alex Chanb7480992017-01-30 14:04:47 +00002919 parameter, `Connection.send` raises `TypeError`.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002920 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002921 connection = Connection(Context(SSLv23_METHOD), None)
Alex Chanb7480992017-01-30 14:04:47 +00002922 with pytest.raises(TypeError):
2923 connection.send(object())
Daniel Holth079c9632019-11-17 22:45:52 -05002924 with pytest.raises(TypeError):
2925 connection.send([1, 2, 3])
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002926
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002927 def test_short_bytes(self):
2928 """
Alex Chanb7480992017-01-30 14:04:47 +00002929 When passed a short byte string, `Connection.send` transmits all of it
2930 and returns the number of bytes sent.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002931 """
Alex Chanb7480992017-01-30 14:04:47 +00002932 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04002933 count = server.send(b"xy")
Alex Chanb7480992017-01-30 14:04:47 +00002934 assert count == 2
Alex Gaynor03737182020-07-23 20:40:46 -04002935 assert client.recv(2) == b"xy"
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002936
Abraham Martinef063482015-03-25 14:06:24 +00002937 def test_text(self):
2938 """
Alex Chanb7480992017-01-30 14:04:47 +00002939 When passed a text, `Connection.send` transmits all of it and
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002940 returns the number of bytes sent. It also raises a DeprecationWarning.
Abraham Martinef063482015-03-25 14:06:24 +00002941 """
Alex Chanb7480992017-01-30 14:04:47 +00002942 server, client = loopback()
2943 with pytest.warns(DeprecationWarning) as w:
Abraham Martinef063482015-03-25 14:06:24 +00002944 simplefilter("always")
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002945 count = server.send(b"xy".decode("ascii"))
Alex Gaynor03737182020-07-23 20:40:46 -04002946 assert "{0} for buf is no longer accepted, use bytes".format(
2947 WARNING_TYPE_EXPECTED
2948 ) == str(w[-1].message)
Alex Chanb7480992017-01-30 14:04:47 +00002949 assert count == 2
Alex Gaynor03737182020-07-23 20:40:46 -04002950 assert client.recv(2) == b"xy"
Abraham Martinef063482015-03-25 14:06:24 +00002951
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002952 def test_short_memoryview(self):
2953 """
2954 When passed a memoryview onto a small number of bytes,
Alex Chanb7480992017-01-30 14:04:47 +00002955 `Connection.send` transmits all of them and returns the number
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002956 of bytes sent.
2957 """
Alex Chanb7480992017-01-30 14:04:47 +00002958 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04002959 count = server.send(memoryview(b"xy"))
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"
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002962
Daniel Holth079c9632019-11-17 22:45:52 -05002963 def test_short_bytearray(self):
2964 """
2965 When passed a short bytearray, `Connection.send` transmits all of
2966 it and returns the number of bytes sent.
2967 """
2968 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04002969 count = server.send(bytearray(b"xy"))
Daniel Holth079c9632019-11-17 22:45:52 -05002970 assert count == 2
Alex Gaynor03737182020-07-23 20:40:46 -04002971 assert client.recv(2) == b"xy"
Daniel Holth079c9632019-11-17 22:45:52 -05002972
Hynek Schlawack8e94f1b2015-09-05 21:31:00 +02002973 @skip_if_py3
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002974 def test_short_buffer(self):
2975 """
2976 When passed a buffer containing a small number of bytes,
Alex Chanb7480992017-01-30 14:04:47 +00002977 `Connection.send` transmits all of them and returns the number
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002978 of bytes sent.
2979 """
Alex Chanb7480992017-01-30 14:04:47 +00002980 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04002981 count = server.send(buffer(b"xy")) # noqa: F821
Alex Chanb7480992017-01-30 14:04:47 +00002982 assert count == 2
Alex Gaynor03737182020-07-23 20:40:46 -04002983 assert client.recv(2) == b"xy"
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02002984
Maximilian Hils868dc3c2017-02-10 14:56:55 +01002985 @pytest.mark.skipif(
Alex Gaynor03737182020-07-23 20:40:46 -04002986 sys.maxsize < 2 ** 31,
2987 reason="sys.maxsize < 2**31 - test requires 64 bit",
Maximilian Hils868dc3c2017-02-10 14:56:55 +01002988 )
2989 def test_buf_too_large(self):
2990 """
2991 When passed a buffer containing >= 2**31 bytes,
2992 `Connection.send` bails out as SSL_write only
2993 accepts an int for the buffer length.
2994 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002995 connection = Connection(Context(SSLv23_METHOD), None)
Maximilian Hils868dc3c2017-02-10 14:56:55 +01002996 with pytest.raises(ValueError) as exc_info:
2997 connection.send(VeryLarge())
2998 exc_info.match(r"Cannot send more than .+ bytes at once")
2999
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05003000
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003001def _make_memoryview(size):
3002 """
3003 Create a new ``memoryview`` wrapped around a ``bytearray`` of the given
3004 size.
3005 """
3006 return memoryview(bytearray(size))
3007
3008
Alex Chanb7480992017-01-30 14:04:47 +00003009class TestConnectionRecvInto(object):
Cory Benfield62d10332014-06-15 10:03:41 +01003010 """
Alex Chanb7480992017-01-30 14:04:47 +00003011 Tests for `Connection.recv_into`.
Cory Benfield62d10332014-06-15 10:03:41 +01003012 """
Alex Gaynor03737182020-07-23 20:40:46 -04003013
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003014 def _no_length_test(self, factory):
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04003015 """
Alex Chanb7480992017-01-30 14:04:47 +00003016 Assert that when the given buffer is passed to `Connection.recv_into`,
3017 whatever bytes are available to be received that fit into that buffer
3018 are written into that buffer.
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04003019 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003020 output_buffer = factory(5)
3021
Alex Chanb7480992017-01-30 14:04:47 +00003022 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04003023 server.send(b"xy")
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04003024
Alex Chanb7480992017-01-30 14:04:47 +00003025 assert client.recv_into(output_buffer) == 2
Alex Gaynor03737182020-07-23 20:40:46 -04003026 assert output_buffer == bytearray(b"xy\x00\x00\x00")
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04003027
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04003028 def test_bytearray_no_length(self):
Cory Benfield62d10332014-06-15 10:03:41 +01003029 """
Alex Chanb7480992017-01-30 14:04:47 +00003030 `Connection.recv_into` can be passed a `bytearray` instance and data
3031 in the receive buffer is written to it.
Cory Benfield62d10332014-06-15 10:03:41 +01003032 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003033 self._no_length_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01003034
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003035 def _respects_length_test(self, factory):
Cory Benfield62d10332014-06-15 10:03:41 +01003036 """
Alex Chanb7480992017-01-30 14:04:47 +00003037 Assert that when the given buffer is passed to `Connection.recv_into`
3038 along with a value for `nbytes` that is less than the size of that
3039 buffer, only `nbytes` bytes are written into the buffer.
Cory Benfield62d10332014-06-15 10:03:41 +01003040 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003041 output_buffer = factory(10)
3042
Alex Chanb7480992017-01-30 14:04:47 +00003043 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04003044 server.send(b"abcdefghij")
Cory Benfield62d10332014-06-15 10:03:41 +01003045
Alex Chanb7480992017-01-30 14:04:47 +00003046 assert client.recv_into(output_buffer, 5) == 5
Alex Gaynor03737182020-07-23 20:40:46 -04003047 assert output_buffer == bytearray(b"abcde\x00\x00\x00\x00\x00")
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04003048
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04003049 def test_bytearray_respects_length(self):
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04003050 """
Alex Chanb7480992017-01-30 14:04:47 +00003051 When called with a `bytearray` instance, `Connection.recv_into`
3052 respects the `nbytes` parameter and doesn't copy in more than that
3053 number of bytes.
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04003054 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003055 self._respects_length_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01003056
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003057 def _doesnt_overfill_test(self, factory):
Cory Benfield62d10332014-06-15 10:03:41 +01003058 """
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04003059 Assert that if there are more bytes available to be read from the
3060 receive buffer than would fit into the buffer passed to
Alex Chanb7480992017-01-30 14:04:47 +00003061 `Connection.recv_into`, only as many as fit are written into it.
Cory Benfield62d10332014-06-15 10:03:41 +01003062 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003063 output_buffer = factory(5)
3064
Alex Chanb7480992017-01-30 14:04:47 +00003065 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04003066 server.send(b"abcdefghij")
Cory Benfield62d10332014-06-15 10:03:41 +01003067
Alex Chanb7480992017-01-30 14:04:47 +00003068 assert client.recv_into(output_buffer) == 5
Alex Gaynor03737182020-07-23 20:40:46 -04003069 assert output_buffer == bytearray(b"abcde")
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04003070 rest = client.recv(5)
Alex Gaynor03737182020-07-23 20:40:46 -04003071 assert b"fghij" == rest
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04003072
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04003073 def test_bytearray_doesnt_overfill(self):
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04003074 """
Alex Chanb7480992017-01-30 14:04:47 +00003075 When called with a `bytearray` instance, `Connection.recv_into`
3076 respects the size of the array and doesn't write more bytes into it
3077 than will fit.
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04003078 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003079 self._doesnt_overfill_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01003080
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04003081 def test_bytearray_really_doesnt_overfill(self):
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003082 """
Alex Chanb7480992017-01-30 14:04:47 +00003083 When called with a `bytearray` instance and an `nbytes` value that is
3084 too large, `Connection.recv_into` respects the size of the array and
3085 not the `nbytes` value and doesn't write more bytes into the buffer
3086 than will fit.
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003087 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003088 self._doesnt_overfill_test(bytearray)
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003089
Maximilian Hils1d95dea2015-08-17 19:27:20 +02003090 def test_peek(self):
Alex Chanb7480992017-01-30 14:04:47 +00003091 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04003092 server.send(b"xy")
Maximilian Hils1d95dea2015-08-17 19:27:20 +02003093
3094 for _ in range(2):
3095 output_buffer = bytearray(5)
Alex Chanb7480992017-01-30 14:04:47 +00003096 assert client.recv_into(output_buffer, flags=MSG_PEEK) == 2
Alex Gaynor03737182020-07-23 20:40:46 -04003097 assert output_buffer == bytearray(b"xy\x00\x00\x00")
Maximilian Hils1d95dea2015-08-17 19:27:20 +02003098
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003099 def test_memoryview_no_length(self):
3100 """
Alex Chanb7480992017-01-30 14:04:47 +00003101 `Connection.recv_into` can be passed a `memoryview` instance and data
3102 in the receive buffer is written to it.
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003103 """
3104 self._no_length_test(_make_memoryview)
Maximilian Hils1d95dea2015-08-17 19:27:20 +02003105
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003106 def test_memoryview_respects_length(self):
3107 """
Alex Chanb7480992017-01-30 14:04:47 +00003108 When called with a `memoryview` instance, `Connection.recv_into`
3109 respects the ``nbytes`` parameter and doesn't copy more than that
3110 number of bytes in.
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003111 """
3112 self._respects_length_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01003113
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003114 def test_memoryview_doesnt_overfill(self):
3115 """
Alex Chanb7480992017-01-30 14:04:47 +00003116 When called with a `memoryview` instance, `Connection.recv_into`
3117 respects the size of the array and doesn't write more bytes into it
3118 than will fit.
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003119 """
3120 self._doesnt_overfill_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01003121
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003122 def test_memoryview_really_doesnt_overfill(self):
3123 """
Alex Chanb7480992017-01-30 14:04:47 +00003124 When called with a `memoryview` instance and an `nbytes` value that is
3125 too large, `Connection.recv_into` respects the size of the array and
3126 not the `nbytes` value and doesn't write more bytes into the buffer
3127 than will fit.
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003128 """
3129 self._doesnt_overfill_test(_make_memoryview)
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003130
Cory Benfield62d10332014-06-15 10:03:41 +01003131
Alex Chanb7480992017-01-30 14:04:47 +00003132class TestConnectionSendall(object):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003133 """
Alex Chanb7480992017-01-30 14:04:47 +00003134 Tests for `Connection.sendall`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003135 """
Alex Gaynor03737182020-07-23 20:40:46 -04003136
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003137 def test_wrong_args(self):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003138 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003139 When called with arguments other than a string argument for its first
Alex Chanb7480992017-01-30 14:04:47 +00003140 parameter, `Connection.sendall` raises `TypeError`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003141 """
Paul Kehrer688538c2020-08-03 19:18:15 -05003142 connection = Connection(Context(SSLv23_METHOD), None)
Alex Chanb7480992017-01-30 14:04:47 +00003143 with pytest.raises(TypeError):
3144 connection.sendall(object())
Daniel Holth079c9632019-11-17 22:45:52 -05003145 with pytest.raises(TypeError):
3146 connection.sendall([1, 2, 3])
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003147
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003148 def test_short(self):
3149 """
Alex Chanb7480992017-01-30 14:04:47 +00003150 `Connection.sendall` transmits all of the bytes in the string
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003151 passed to it.
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003152 """
Alex Chanb7480992017-01-30 14:04:47 +00003153 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04003154 server.sendall(b"x")
3155 assert client.recv(1) == b"x"
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003156
Abraham Martinef063482015-03-25 14:06:24 +00003157 def test_text(self):
3158 """
Alex Chanb7480992017-01-30 14:04:47 +00003159 `Connection.sendall` transmits all the content in the string passed
3160 to it, raising a DeprecationWarning in case of this being a text.
Abraham Martinef063482015-03-25 14:06:24 +00003161 """
Alex Chanb7480992017-01-30 14:04:47 +00003162 server, client = loopback()
3163 with pytest.warns(DeprecationWarning) as w:
Abraham Martinef063482015-03-25 14:06:24 +00003164 simplefilter("always")
Jean-Paul Calderone8dc37a12015-03-29 08:16:52 -04003165 server.sendall(b"x".decode("ascii"))
Alex Gaynor03737182020-07-23 20:40:46 -04003166 assert "{0} for buf is no longer accepted, use bytes".format(
3167 WARNING_TYPE_EXPECTED
3168 ) == str(w[-1].message)
Alex Chanb7480992017-01-30 14:04:47 +00003169 assert client.recv(1) == b"x"
Abraham Martinef063482015-03-25 14:06:24 +00003170
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003171 def test_short_memoryview(self):
3172 """
3173 When passed a memoryview onto a small number of bytes,
Alex Chanb7480992017-01-30 14:04:47 +00003174 `Connection.sendall` transmits all of them.
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003175 """
Alex Chanb7480992017-01-30 14:04:47 +00003176 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04003177 server.sendall(memoryview(b"x"))
3178 assert client.recv(1) == b"x"
Abraham Martinef063482015-03-25 14:06:24 +00003179
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003180 @skip_if_py3
3181 def test_short_buffers(self):
3182 """
3183 When passed a buffer containing a small number of bytes,
Alex Chanb7480992017-01-30 14:04:47 +00003184 `Connection.sendall` transmits all of them.
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003185 """
Alex Chanb7480992017-01-30 14:04:47 +00003186 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04003187 count = server.sendall(buffer(b"xy")) # noqa: F821
Daniel Holth079c9632019-11-17 22:45:52 -05003188 assert count == 2
Alex Gaynor03737182020-07-23 20:40:46 -04003189 assert client.recv(2) == b"xy"
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02003190
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003191 def test_long(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003192 """
Alex Chanb7480992017-01-30 14:04:47 +00003193 `Connection.sendall` transmits all the bytes in the string passed to it
3194 even if this requires multiple calls of an underlying write function.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003195 """
Alex Chanb7480992017-01-30 14:04:47 +00003196 server, client = loopback()
Jean-Paul Calderone6241c702010-09-16 19:59:24 -04003197 # Should be enough, underlying SSL_write should only do 16k at a time.
Hynek Schlawack35618382015-09-05 21:54:25 +02003198 # On Windows, after 32k of bytes the write will block (forever
3199 # - because no one is yet reading).
Alex Gaynor03737182020-07-23 20:40:46 -04003200 message = b"x" * (1024 * 32 - 1) + b"y"
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003201 server.sendall(message)
3202 accum = []
3203 received = 0
3204 while received < len(message):
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04003205 data = client.recv(1024)
3206 accum.append(data)
3207 received += len(data)
Alex Gaynor03737182020-07-23 20:40:46 -04003208 assert message == b"".join(accum)
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003209
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003210 def test_closed(self):
3211 """
Alex Chanb7480992017-01-30 14:04:47 +00003212 If the underlying socket is closed, `Connection.sendall` propagates the
3213 write error from the low level write call.
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003214 """
Alex Chanb7480992017-01-30 14:04:47 +00003215 server, client = loopback()
Jean-Paul Calderone05d43e82010-09-24 18:01:36 -04003216 server.sock_shutdown(2)
Alex Chanb7480992017-01-30 14:04:47 +00003217 with pytest.raises(SysCallError) as err:
3218 server.sendall(b"hello, world")
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +02003219 if platform == "win32":
Alex Chanb7480992017-01-30 14:04:47 +00003220 assert err.value.args[0] == ESHUTDOWN
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +02003221 else:
Alex Chanb7480992017-01-30 14:04:47 +00003222 assert err.value.args[0] == EPIPE
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003223
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003224
Alex Chanb7480992017-01-30 14:04:47 +00003225class TestConnectionRenegotiate(object):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003226 """
3227 Tests for SSL renegotiation APIs.
3228 """
Alex Gaynor03737182020-07-23 20:40:46 -04003229
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003230 def test_total_renegotiations(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003231 """
Alex Chanb7480992017-01-30 14:04:47 +00003232 `Connection.total_renegotiations` returns `0` before any renegotiations
3233 have happened.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003234 """
Paul Kehrer688538c2020-08-03 19:18:15 -05003235 connection = Connection(Context(SSLv23_METHOD), None)
Alex Chanb7480992017-01-30 14:04:47 +00003236 assert connection.total_renegotiations() == 0
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003237
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003238 def test_renegotiate(self):
3239 """
3240 Go through a complete renegotiation cycle.
3241 """
Paul Kehrer7d5a3bf2019-01-21 12:24:02 -06003242 server, client = loopback(
3243 lambda s: loopback_server_factory(s, TLSv1_2_METHOD),
3244 lambda s: loopback_client_factory(s, TLSv1_2_METHOD),
3245 )
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003246
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003247 server.send(b"hello world")
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003248
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003249 assert b"hello world" == client.recv(len(b"hello world"))
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003250
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003251 assert 0 == server.total_renegotiations()
3252 assert False is server.renegotiate_pending()
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003253
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003254 assert True is server.renegotiate()
3255
3256 assert True is server.renegotiate_pending()
3257
3258 server.setblocking(False)
3259 client.setblocking(False)
3260
3261 client.do_handshake()
3262 server.do_handshake()
3263
3264 assert 1 == server.total_renegotiations()
3265 while False is server.renegotiate_pending():
3266 pass
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003267
3268
Alex Chanb7480992017-01-30 14:04:47 +00003269class TestError(object):
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003270 """
Alex Chanb7480992017-01-30 14:04:47 +00003271 Unit tests for `OpenSSL.SSL.Error`.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003272 """
Alex Gaynor03737182020-07-23 20:40:46 -04003273
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003274 def test_type(self):
3275 """
Alex Chanb7480992017-01-30 14:04:47 +00003276 `Error` is an exception type.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003277 """
Alex Chanb7480992017-01-30 14:04:47 +00003278 assert issubclass(Error, Exception)
Alex Gaynor03737182020-07-23 20:40:46 -04003279 assert Error.__name__ == "Error"
Rick Deane15b1472009-07-09 15:53:42 -05003280
3281
Alex Chanb7480992017-01-30 14:04:47 +00003282class TestConstants(object):
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003283 """
Alex Chanb7480992017-01-30 14:04:47 +00003284 Tests for the values of constants exposed in `OpenSSL.SSL`.
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003285
3286 These are values defined by OpenSSL intended only to be used as flags to
3287 OpenSSL APIs. The only assertions it seems can be made about them is
3288 their values.
3289 """
Alex Gaynor03737182020-07-23 20:40:46 -04003290
Hynek Schlawack35618382015-09-05 21:54:25 +02003291 @pytest.mark.skipif(
3292 OP_NO_QUERY_MTU is None,
Alex Gaynor03737182020-07-23 20:40:46 -04003293 reason="OP_NO_QUERY_MTU unavailable - OpenSSL version may be too old",
Hynek Schlawack35618382015-09-05 21:54:25 +02003294 )
3295 def test_op_no_query_mtu(self):
3296 """
Alex Chanb7480992017-01-30 14:04:47 +00003297 The value of `OpenSSL.SSL.OP_NO_QUERY_MTU` is 0x1000, the value
3298 of `SSL_OP_NO_QUERY_MTU` defined by `openssl/ssl.h`.
Hynek Schlawack35618382015-09-05 21:54:25 +02003299 """
Alex Chanb7480992017-01-30 14:04:47 +00003300 assert OP_NO_QUERY_MTU == 0x1000
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003301
Hynek Schlawack35618382015-09-05 21:54:25 +02003302 @pytest.mark.skipif(
3303 OP_COOKIE_EXCHANGE is None,
3304 reason="OP_COOKIE_EXCHANGE unavailable - "
Alex Gaynor03737182020-07-23 20:40:46 -04003305 "OpenSSL version may be too old",
Hynek Schlawack35618382015-09-05 21:54:25 +02003306 )
3307 def test_op_cookie_exchange(self):
3308 """
Alex Chanb7480992017-01-30 14:04:47 +00003309 The value of `OpenSSL.SSL.OP_COOKIE_EXCHANGE` is 0x2000, the
3310 value of `SSL_OP_COOKIE_EXCHANGE` defined by `openssl/ssl.h`.
Hynek Schlawack35618382015-09-05 21:54:25 +02003311 """
Alex Chanb7480992017-01-30 14:04:47 +00003312 assert OP_COOKIE_EXCHANGE == 0x2000
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003313
Hynek Schlawack35618382015-09-05 21:54:25 +02003314 @pytest.mark.skipif(
3315 OP_NO_TICKET is None,
Alex Gaynor03737182020-07-23 20:40:46 -04003316 reason="OP_NO_TICKET unavailable - OpenSSL version may be too old",
Hynek Schlawack35618382015-09-05 21:54:25 +02003317 )
3318 def test_op_no_ticket(self):
3319 """
Alex Chanb7480992017-01-30 14:04:47 +00003320 The value of `OpenSSL.SSL.OP_NO_TICKET` is 0x4000, the value of
3321 `SSL_OP_NO_TICKET` defined by `openssl/ssl.h`.
Hynek Schlawack35618382015-09-05 21:54:25 +02003322 """
Alex Chanb7480992017-01-30 14:04:47 +00003323 assert OP_NO_TICKET == 0x4000
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003324
Hynek Schlawack35618382015-09-05 21:54:25 +02003325 @pytest.mark.skipif(
3326 OP_NO_COMPRESSION is None,
Alex Gaynor03737182020-07-23 20:40:46 -04003327 reason=(
3328 "OP_NO_COMPRESSION unavailable - OpenSSL version may be too old"
3329 ),
Hynek Schlawack35618382015-09-05 21:54:25 +02003330 )
3331 def test_op_no_compression(self):
3332 """
Alex Chanb7480992017-01-30 14:04:47 +00003333 The value of `OpenSSL.SSL.OP_NO_COMPRESSION` is 0x20000, the
3334 value of `SSL_OP_NO_COMPRESSION` defined by `openssl/ssl.h`.
Hynek Schlawack35618382015-09-05 21:54:25 +02003335 """
Alex Chanb7480992017-01-30 14:04:47 +00003336 assert OP_NO_COMPRESSION == 0x20000
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04003337
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003338 def test_sess_cache_off(self):
3339 """
Alex Chanb7480992017-01-30 14:04:47 +00003340 The value of `OpenSSL.SSL.SESS_CACHE_OFF` 0x0, the value of
3341 `SSL_SESS_CACHE_OFF` defined by `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003342 """
Alex Chanb7480992017-01-30 14:04:47 +00003343 assert 0x0 == SESS_CACHE_OFF
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003344
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003345 def test_sess_cache_client(self):
3346 """
Alex Chanb7480992017-01-30 14:04:47 +00003347 The value of `OpenSSL.SSL.SESS_CACHE_CLIENT` 0x1, the value of
3348 `SSL_SESS_CACHE_CLIENT` defined by `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003349 """
Alex Chanb7480992017-01-30 14:04:47 +00003350 assert 0x1 == SESS_CACHE_CLIENT
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003351
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003352 def test_sess_cache_server(self):
3353 """
Alex Chanb7480992017-01-30 14:04:47 +00003354 The value of `OpenSSL.SSL.SESS_CACHE_SERVER` 0x2, the value of
3355 `SSL_SESS_CACHE_SERVER` defined by `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003356 """
Alex Chanb7480992017-01-30 14:04:47 +00003357 assert 0x2 == SESS_CACHE_SERVER
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003358
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003359 def test_sess_cache_both(self):
3360 """
Alex Chanb7480992017-01-30 14:04:47 +00003361 The value of `OpenSSL.SSL.SESS_CACHE_BOTH` 0x3, the value of
3362 `SSL_SESS_CACHE_BOTH` defined by `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003363 """
Alex Chanb7480992017-01-30 14:04:47 +00003364 assert 0x3 == SESS_CACHE_BOTH
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003365
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003366 def test_sess_cache_no_auto_clear(self):
3367 """
Alex Chanb7480992017-01-30 14:04:47 +00003368 The value of `OpenSSL.SSL.SESS_CACHE_NO_AUTO_CLEAR` 0x80, the
3369 value of `SSL_SESS_CACHE_NO_AUTO_CLEAR` defined by
3370 `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003371 """
Alex Chanb7480992017-01-30 14:04:47 +00003372 assert 0x80 == SESS_CACHE_NO_AUTO_CLEAR
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003373
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003374 def test_sess_cache_no_internal_lookup(self):
3375 """
Alex Chanb7480992017-01-30 14:04:47 +00003376 The value of `OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_LOOKUP` 0x100,
3377 the value of `SSL_SESS_CACHE_NO_INTERNAL_LOOKUP` defined by
3378 `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003379 """
Alex Chanb7480992017-01-30 14:04:47 +00003380 assert 0x100 == SESS_CACHE_NO_INTERNAL_LOOKUP
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003381
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003382 def test_sess_cache_no_internal_store(self):
3383 """
Alex Chanb7480992017-01-30 14:04:47 +00003384 The value of `OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_STORE` 0x200,
3385 the value of `SSL_SESS_CACHE_NO_INTERNAL_STORE` defined by
3386 `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003387 """
Alex Chanb7480992017-01-30 14:04:47 +00003388 assert 0x200 == SESS_CACHE_NO_INTERNAL_STORE
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003389
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003390 def test_sess_cache_no_internal(self):
3391 """
Alex Chanb7480992017-01-30 14:04:47 +00003392 The value of `OpenSSL.SSL.SESS_CACHE_NO_INTERNAL` 0x300, the
3393 value of `SSL_SESS_CACHE_NO_INTERNAL` defined by
3394 `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003395 """
Alex Chanb7480992017-01-30 14:04:47 +00003396 assert 0x300 == SESS_CACHE_NO_INTERNAL
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003397
3398
Alex Chanb7480992017-01-30 14:04:47 +00003399class TestMemoryBIO(object):
Rick Deanb71c0d22009-04-01 14:09:23 -05003400 """
Alex Chanb7480992017-01-30 14:04:47 +00003401 Tests for `OpenSSL.SSL.Connection` using a memory BIO.
Rick Deanb71c0d22009-04-01 14:09:23 -05003402 """
Alex Gaynor03737182020-07-23 20:40:46 -04003403
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003404 def _server(self, sock):
3405 """
Alex Chanb7480992017-01-30 14:04:47 +00003406 Create a new server-side SSL `Connection` object wrapped around `sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003407 """
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003408 # Create the server side Connection. This is mostly setup boilerplate
3409 # - use TLSv1, use a particular certificate, etc.
Paul Kehrer688538c2020-08-03 19:18:15 -05003410 server_ctx = Context(SSLv23_METHOD)
Alex Gaynor43307782015-09-04 09:05:45 -04003411 server_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE)
Hynek Schlawack35618382015-09-05 21:54:25 +02003412 server_ctx.set_verify(
3413 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT | VERIFY_CLIENT_ONCE,
Alex Gaynor03737182020-07-23 20:40:46 -04003414 verify_cb,
Hynek Schlawack35618382015-09-05 21:54:25 +02003415 )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003416 server_store = server_ctx.get_cert_store()
Hynek Schlawack35618382015-09-05 21:54:25 +02003417 server_ctx.use_privatekey(
Alex Gaynor03737182020-07-23 20:40:46 -04003418 load_privatekey(FILETYPE_PEM, server_key_pem)
3419 )
Hynek Schlawack35618382015-09-05 21:54:25 +02003420 server_ctx.use_certificate(
Alex Gaynor03737182020-07-23 20:40:46 -04003421 load_certificate(FILETYPE_PEM, server_cert_pem)
3422 )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003423 server_ctx.check_privatekey()
3424 server_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Hynek Schlawack35618382015-09-05 21:54:25 +02003425 # Here the Connection is actually created. If None is passed as the
3426 # 2nd parameter, it indicates a memory BIO should be created.
Rick Deanb1ccd562009-07-09 23:52:39 -05003427 server_conn = Connection(server_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003428 server_conn.set_accept_state()
3429 return server_conn
3430
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003431 def _client(self, sock):
3432 """
Alex Chanb7480992017-01-30 14:04:47 +00003433 Create a new client-side SSL `Connection` object wrapped around `sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003434 """
3435 # Now create the client side Connection. Similar boilerplate to the
3436 # above.
Paul Kehrer688538c2020-08-03 19:18:15 -05003437 client_ctx = Context(SSLv23_METHOD)
Alex Gaynor43307782015-09-04 09:05:45 -04003438 client_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE)
Hynek Schlawack35618382015-09-05 21:54:25 +02003439 client_ctx.set_verify(
3440 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT | VERIFY_CLIENT_ONCE,
Alex Gaynor03737182020-07-23 20:40:46 -04003441 verify_cb,
Hynek Schlawack35618382015-09-05 21:54:25 +02003442 )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003443 client_store = client_ctx.get_cert_store()
Hynek Schlawack35618382015-09-05 21:54:25 +02003444 client_ctx.use_privatekey(
Alex Gaynor03737182020-07-23 20:40:46 -04003445 load_privatekey(FILETYPE_PEM, client_key_pem)
3446 )
Hynek Schlawack35618382015-09-05 21:54:25 +02003447 client_ctx.use_certificate(
Alex Gaynor03737182020-07-23 20:40:46 -04003448 load_certificate(FILETYPE_PEM, client_cert_pem)
3449 )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003450 client_ctx.check_privatekey()
3451 client_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05003452 client_conn = Connection(client_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003453 client_conn.set_connect_state()
3454 return client_conn
3455
Alex Chanb7480992017-01-30 14:04:47 +00003456 def test_memory_connect(self):
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003457 """
Alex Chanb7480992017-01-30 14:04:47 +00003458 Two `Connection`s which use memory BIOs can be manually connected by
3459 reading from the output of each and writing those bytes to the input of
3460 the other and in this way establish a connection and exchange
3461 application-level bytes with each other.
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003462 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003463 server_conn = self._server(None)
3464 client_conn = self._client(None)
Rick Deanb71c0d22009-04-01 14:09:23 -05003465
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003466 # There should be no key or nonces yet.
Alex Chanb7480992017-01-30 14:04:47 +00003467 assert server_conn.master_key() is None
3468 assert server_conn.client_random() is None
3469 assert server_conn.server_random() is None
Rick Deanb71c0d22009-04-01 14:09:23 -05003470
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003471 # First, the handshake needs to happen. We'll deliver bytes back and
3472 # forth between the client and server until neither of them feels like
3473 # speaking any more.
Alex Chanb7480992017-01-30 14:04:47 +00003474 assert interact_in_memory(client_conn, server_conn) is None
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003475
3476 # Now that the handshake is done, there should be a key and nonces.
Alex Chanb7480992017-01-30 14:04:47 +00003477 assert server_conn.master_key() is not None
3478 assert server_conn.client_random() is not None
3479 assert server_conn.server_random() is not None
3480 assert server_conn.client_random() == client_conn.client_random()
3481 assert server_conn.server_random() == client_conn.server_random()
3482 assert server_conn.client_random() != server_conn.server_random()
3483 assert client_conn.client_random() != client_conn.server_random()
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003484
Paul Kehrerbdb76392017-12-01 04:54:32 +08003485 # Export key material for other uses.
Alex Gaynor03737182020-07-23 20:40:46 -04003486 cekm = client_conn.export_keying_material(b"LABEL", 32)
3487 sekm = server_conn.export_keying_material(b"LABEL", 32)
Paul Kehrerbdb76392017-12-01 04:54:32 +08003488 assert cekm is not None
3489 assert sekm is not None
3490 assert cekm == sekm
3491 assert len(sekm) == 32
3492
3493 # Export key material for other uses with additional context.
Alex Gaynor03737182020-07-23 20:40:46 -04003494 cekmc = client_conn.export_keying_material(b"LABEL", 32, b"CONTEXT")
3495 sekmc = server_conn.export_keying_material(b"LABEL", 32, b"CONTEXT")
Paul Kehrerbdb76392017-12-01 04:54:32 +08003496 assert cekmc is not None
3497 assert sekmc is not None
3498 assert cekmc == sekmc
3499 assert cekmc != cekm
3500 assert sekmc != sekm
3501 # Export with alternate label
Alex Gaynor03737182020-07-23 20:40:46 -04003502 cekmt = client_conn.export_keying_material(b"test", 32, b"CONTEXT")
3503 sekmt = server_conn.export_keying_material(b"test", 32, b"CONTEXT")
Paul Kehrerbdb76392017-12-01 04:54:32 +08003504 assert cekmc != cekmt
3505 assert sekmc != sekmt
3506
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003507 # Here are the bytes we'll try to send.
Alex Gaynor03737182020-07-23 20:40:46 -04003508 important_message = b"One if by land, two if by sea."
Rick Deanb71c0d22009-04-01 14:09:23 -05003509
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003510 server_conn.write(important_message)
Alex Gaynor03737182020-07-23 20:40:46 -04003511 assert interact_in_memory(client_conn, server_conn) == (
3512 client_conn,
3513 important_message,
3514 )
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003515
3516 client_conn.write(important_message[::-1])
Alex Gaynor03737182020-07-23 20:40:46 -04003517 assert interact_in_memory(client_conn, server_conn) == (
3518 server_conn,
3519 important_message[::-1],
3520 )
Rick Deanb71c0d22009-04-01 14:09:23 -05003521
Alex Chanb7480992017-01-30 14:04:47 +00003522 def test_socket_connect(self):
Rick Deanb1ccd562009-07-09 23:52:39 -05003523 """
Alex Chanb7480992017-01-30 14:04:47 +00003524 Just like `test_memory_connect` but with an actual socket.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003525
Hynek Schlawack35618382015-09-05 21:54:25 +02003526 This is primarily to rule out the memory BIO code as the source of any
Alex Chanb7480992017-01-30 14:04:47 +00003527 problems encountered while passing data over a `Connection` (if
Hynek Schlawack35618382015-09-05 21:54:25 +02003528 this test fails, there must be a problem outside the memory BIO code,
3529 as no memory BIO is involved here). Even though this isn't a memory
3530 BIO test, it's convenient to have it here.
Rick Deanb1ccd562009-07-09 23:52:39 -05003531 """
Alex Chanb7480992017-01-30 14:04:47 +00003532 server_conn, client_conn = loopback()
Rick Deanb1ccd562009-07-09 23:52:39 -05003533
Alex Gaynore7f51982016-09-11 11:48:14 -04003534 important_message = b"Help me Obi Wan Kenobi, you're my only hope."
Rick Deanb1ccd562009-07-09 23:52:39 -05003535 client_conn.send(important_message)
3536 msg = server_conn.recv(1024)
Alex Chanb7480992017-01-30 14:04:47 +00003537 assert msg == important_message
Rick Deanb1ccd562009-07-09 23:52:39 -05003538
3539 # Again in the other direction, just for fun.
3540 important_message = important_message[::-1]
3541 server_conn.send(important_message)
3542 msg = client_conn.recv(1024)
Alex Chanb7480992017-01-30 14:04:47 +00003543 assert msg == important_message
Rick Deanb1ccd562009-07-09 23:52:39 -05003544
Alex Chanb7480992017-01-30 14:04:47 +00003545 def test_socket_overrides_memory(self):
Rick Deanb71c0d22009-04-01 14:09:23 -05003546 """
Alex Chanb7480992017-01-30 14:04:47 +00003547 Test that `OpenSSL.SSL.bio_read` and `OpenSSL.SSL.bio_write` don't
3548 work on `OpenSSL.SSL.Connection`() that use sockets.
Rick Deanb71c0d22009-04-01 14:09:23 -05003549 """
Paul Kehrer688538c2020-08-03 19:18:15 -05003550 context = Context(SSLv23_METHOD)
David Benjamin1fbe0642019-04-15 17:05:13 -05003551 client = socket_any_family()
Rick Deanb71c0d22009-04-01 14:09:23 -05003552 clientSSL = Connection(context, client)
Alex Chanb7480992017-01-30 14:04:47 +00003553 with pytest.raises(TypeError):
3554 clientSSL.bio_read(100)
3555 with pytest.raises(TypeError):
Paul Kehrerc45a6ea2020-08-03 15:54:20 -05003556 clientSSL.bio_write(b"foo")
Alex Chanb7480992017-01-30 14:04:47 +00003557 with pytest.raises(TypeError):
3558 clientSSL.bio_shutdown()
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003559
Alex Chanb7480992017-01-30 14:04:47 +00003560 def test_outgoing_overflow(self):
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003561 """
3562 If more bytes than can be written to the memory BIO are passed to
Alex Chanb7480992017-01-30 14:04:47 +00003563 `Connection.send` at once, the number of bytes which were written is
3564 returned and that many bytes from the beginning of the input can be
3565 read from the other end of the connection.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003566 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003567 server = self._server(None)
3568 client = self._client(None)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003569
Alex Chanb7480992017-01-30 14:04:47 +00003570 interact_in_memory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003571
3572 size = 2 ** 15
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003573 sent = client.send(b"x" * size)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003574 # Sanity check. We're trying to test what happens when the entire
3575 # input can't be sent. If the entire input was sent, this test is
3576 # meaningless.
Alex Chanb7480992017-01-30 14:04:47 +00003577 assert sent < size
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003578
Alex Chanb7480992017-01-30 14:04:47 +00003579 receiver, received = interact_in_memory(client, server)
3580 assert receiver is server
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003581
3582 # We can rely on all of these bytes being received at once because
Alex Chanb7480992017-01-30 14:04:47 +00003583 # loopback passes 2 ** 16 to recv - more than 2 ** 15.
3584 assert len(received) == sent
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003585
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003586 def test_shutdown(self):
3587 """
Alex Chanb7480992017-01-30 14:04:47 +00003588 `Connection.bio_shutdown` signals the end of the data stream
3589 from which the `Connection` reads.
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003590 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003591 server = self._server(None)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003592 server.bio_shutdown()
Alex Chanb7480992017-01-30 14:04:47 +00003593 with pytest.raises(Error) as err:
3594 server.recv(1024)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003595 # We don't want WantReadError or ZeroReturnError or anything - it's a
3596 # handshake failure.
Alex Chanb7480992017-01-30 14:04:47 +00003597 assert type(err.value) in [Error, SysCallError]
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003598
Alex Chanb7480992017-01-30 14:04:47 +00003599 def test_unexpected_EOF(self):
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003600 """
3601 If the connection is lost before an orderly SSL shutdown occurs,
Alex Chanb7480992017-01-30 14:04:47 +00003602 `OpenSSL.SSL.SysCallError` is raised with a message of
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003603 "Unexpected EOF".
3604 """
Alex Chanb7480992017-01-30 14:04:47 +00003605 server_conn, client_conn = loopback()
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003606 client_conn.sock_shutdown(SHUT_RDWR)
Alex Chanb7480992017-01-30 14:04:47 +00003607 with pytest.raises(SysCallError) as err:
3608 server_conn.recv(1024)
3609 assert err.value.args == (-1, "Unexpected EOF")
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003610
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003611 def _check_client_ca_list(self, func):
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003612 """
Alex Chanb7480992017-01-30 14:04:47 +00003613 Verify the return value of the `get_client_ca_list` method for
Hynek Schlawack35618382015-09-05 21:54:25 +02003614 server and client connections.
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003615
Jonathan Ballet78b92a22011-07-16 08:07:26 +09003616 :param func: A function which will be called with the server context
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003617 before the client and server are connected to each other. This
3618 function should specify a list of CAs for the server to send to the
3619 client and return that same list. The list will be used to verify
Alex Chanb7480992017-01-30 14:04:47 +00003620 that `get_client_ca_list` returns the proper value at
Hynek Schlawack35618382015-09-05 21:54:25 +02003621 various times.
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003622 """
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003623 server = self._server(None)
3624 client = self._client(None)
Alex Chanb7480992017-01-30 14:04:47 +00003625 assert client.get_client_ca_list() == []
3626 assert server.get_client_ca_list() == []
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003627 ctx = server.get_context()
3628 expected = func(ctx)
Alex Chanb7480992017-01-30 14:04:47 +00003629 assert client.get_client_ca_list() == []
3630 assert server.get_client_ca_list() == expected
3631 interact_in_memory(client, server)
3632 assert client.get_client_ca_list() == expected
3633 assert server.get_client_ca_list() == expected
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003634
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003635 def test_set_client_ca_list_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003636 """
Alex Chanb7480992017-01-30 14:04:47 +00003637 `Context.set_client_ca_list` raises a `TypeError` if called with a
3638 non-list or a list that contains objects other than X509Names.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003639 """
Paul Kehrer688538c2020-08-03 19:18:15 -05003640 ctx = Context(SSLv23_METHOD)
Alex Chanb7480992017-01-30 14:04:47 +00003641 with pytest.raises(TypeError):
3642 ctx.set_client_ca_list("spam")
3643 with pytest.raises(TypeError):
3644 ctx.set_client_ca_list(["spam"])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003645
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003646 def test_set_empty_ca_list(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003647 """
Alex Chanb7480992017-01-30 14:04:47 +00003648 If passed an empty list, `Context.set_client_ca_list` configures the
3649 context to send no CA names to the client and, on both the server and
3650 client sides, `Connection.get_client_ca_list` returns an empty list
3651 after the connection is set up.
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003652 """
Alex Gaynor03737182020-07-23 20:40:46 -04003653
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003654 def no_ca(ctx):
3655 ctx.set_client_ca_list([])
3656 return []
Alex Gaynor03737182020-07-23 20:40:46 -04003657
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003658 self._check_client_ca_list(no_ca)
3659
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003660 def test_set_one_ca_list(self):
3661 """
3662 If passed a list containing a single X509Name,
Alex Chanb7480992017-01-30 14:04:47 +00003663 `Context.set_client_ca_list` configures the context to send
Hynek Schlawack35618382015-09-05 21:54:25 +02003664 that CA name to the client and, on both the server and client sides,
Alex Chanb7480992017-01-30 14:04:47 +00003665 `Connection.get_client_ca_list` returns a list containing that
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003666 X509Name after the connection is set up.
3667 """
3668 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3669 cadesc = cacert.get_subject()
Hynek Schlawack35618382015-09-05 21:54:25 +02003670
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003671 def single_ca(ctx):
3672 ctx.set_client_ca_list([cadesc])
3673 return [cadesc]
Alex Gaynor03737182020-07-23 20:40:46 -04003674
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003675 self._check_client_ca_list(single_ca)
3676
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003677 def test_set_multiple_ca_list(self):
3678 """
3679 If passed a list containing multiple X509Name objects,
Alex Chanb7480992017-01-30 14:04:47 +00003680 `Context.set_client_ca_list` configures the context to send
Hynek Schlawack35618382015-09-05 21:54:25 +02003681 those CA names to the client and, on both the server and client sides,
Alex Chanb7480992017-01-30 14:04:47 +00003682 `Connection.get_client_ca_list` returns a list containing those
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003683 X509Names after the connection is set up.
3684 """
3685 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3686 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3687
3688 sedesc = secert.get_subject()
3689 cldesc = clcert.get_subject()
3690
3691 def multiple_ca(ctx):
3692 L = [sedesc, cldesc]
3693 ctx.set_client_ca_list(L)
3694 return L
Alex Gaynor03737182020-07-23 20:40:46 -04003695
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003696 self._check_client_ca_list(multiple_ca)
3697
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003698 def test_reset_ca_list(self):
3699 """
3700 If called multiple times, only the X509Names passed to the final call
Alex Chanb7480992017-01-30 14:04:47 +00003701 of `Context.set_client_ca_list` are used to configure the CA
Hynek Schlawack35618382015-09-05 21:54:25 +02003702 names sent to the client.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003703 """
3704 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3705 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3706 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3707
3708 cadesc = cacert.get_subject()
3709 sedesc = secert.get_subject()
3710 cldesc = clcert.get_subject()
3711
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003712 def changed_ca(ctx):
3713 ctx.set_client_ca_list([sedesc, cldesc])
3714 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003715 return [cadesc]
Alex Gaynor03737182020-07-23 20:40:46 -04003716
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003717 self._check_client_ca_list(changed_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003718
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003719 def test_mutated_ca_list(self):
3720 """
Alex Chanb7480992017-01-30 14:04:47 +00003721 If the list passed to `Context.set_client_ca_list` is mutated
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003722 afterwards, this does not affect the list of CA names sent to the
3723 client.
3724 """
3725 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3726 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3727
3728 cadesc = cacert.get_subject()
3729 sedesc = secert.get_subject()
3730
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003731 def mutated_ca(ctx):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003732 L = [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003733 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003734 L.append(sedesc)
3735 return [cadesc]
Alex Gaynor03737182020-07-23 20:40:46 -04003736
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003737 self._check_client_ca_list(mutated_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003738
Alex Chanb7480992017-01-30 14:04:47 +00003739 def test_add_client_ca_wrong_args(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003740 """
Alex Chanb7480992017-01-30 14:04:47 +00003741 `Context.add_client_ca` raises `TypeError` if called with
3742 a non-X509 object.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003743 """
Paul Kehrer688538c2020-08-03 19:18:15 -05003744 ctx = Context(SSLv23_METHOD)
Alex Chanb7480992017-01-30 14:04:47 +00003745 with pytest.raises(TypeError):
3746 ctx.add_client_ca("spam")
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003747
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003748 def test_one_add_client_ca(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003749 """
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003750 A certificate's subject can be added as a CA to be sent to the client
Alex Chanb7480992017-01-30 14:04:47 +00003751 with `Context.add_client_ca`.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003752 """
3753 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3754 cadesc = cacert.get_subject()
Hynek Schlawack35618382015-09-05 21:54:25 +02003755
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003756 def single_ca(ctx):
3757 ctx.add_client_ca(cacert)
3758 return [cadesc]
Alex Gaynor03737182020-07-23 20:40:46 -04003759
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003760 self._check_client_ca_list(single_ca)
3761
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003762 def test_multiple_add_client_ca(self):
3763 """
3764 Multiple CA names can be sent to the client by calling
Alex Chanb7480992017-01-30 14:04:47 +00003765 `Context.add_client_ca` with multiple X509 objects.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003766 """
3767 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3768 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3769
3770 cadesc = cacert.get_subject()
3771 sedesc = secert.get_subject()
3772
3773 def multiple_ca(ctx):
3774 ctx.add_client_ca(cacert)
3775 ctx.add_client_ca(secert)
3776 return [cadesc, sedesc]
Alex Gaynor03737182020-07-23 20:40:46 -04003777
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003778 self._check_client_ca_list(multiple_ca)
3779
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003780 def test_set_and_add_client_ca(self):
3781 """
Alex Chanb7480992017-01-30 14:04:47 +00003782 A call to `Context.set_client_ca_list` followed by a call to
3783 `Context.add_client_ca` results in using the CA names from the
Hynek Schlawack35618382015-09-05 21:54:25 +02003784 first call and the CA name from the second call.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003785 """
3786 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3787 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3788 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3789
3790 cadesc = cacert.get_subject()
3791 sedesc = secert.get_subject()
3792 cldesc = clcert.get_subject()
3793
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003794 def mixed_set_add_ca(ctx):
3795 ctx.set_client_ca_list([cadesc, sedesc])
3796 ctx.add_client_ca(clcert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003797 return [cadesc, sedesc, cldesc]
Alex Gaynor03737182020-07-23 20:40:46 -04003798
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003799 self._check_client_ca_list(mixed_set_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003800
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003801 def test_set_after_add_client_ca(self):
3802 """
Alex Chanb7480992017-01-30 14:04:47 +00003803 A call to `Context.set_client_ca_list` after a call to
3804 `Context.add_client_ca` replaces the CA name specified by the
Hynek Schlawack35618382015-09-05 21:54:25 +02003805 former call with the names specified by the latter call.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003806 """
3807 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3808 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3809 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3810
3811 cadesc = cacert.get_subject()
3812 sedesc = secert.get_subject()
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003813
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003814 def set_replaces_add_ca(ctx):
3815 ctx.add_client_ca(clcert)
3816 ctx.set_client_ca_list([cadesc])
3817 ctx.add_client_ca(secert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003818 return [cadesc, sedesc]
Alex Gaynor03737182020-07-23 20:40:46 -04003819
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003820 self._check_client_ca_list(set_replaces_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003821
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003822
Alex Chanb7480992017-01-30 14:04:47 +00003823class TestInfoConstants(object):
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003824 """
3825 Tests for assorted constants exposed for use in info callbacks.
3826 """
Alex Gaynor03737182020-07-23 20:40:46 -04003827
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003828 def test_integers(self):
3829 """
3830 All of the info constants are integers.
3831
3832 This is a very weak test. It would be nice to have one that actually
3833 verifies that as certain info events happen, the value passed to the
3834 info callback matches up with the constant exposed by OpenSSL.SSL.
3835 """
3836 for const in [
Alex Gaynor03737182020-07-23 20:40:46 -04003837 SSL_ST_CONNECT,
3838 SSL_ST_ACCEPT,
3839 SSL_ST_MASK,
3840 SSL_CB_LOOP,
3841 SSL_CB_EXIT,
3842 SSL_CB_READ,
3843 SSL_CB_WRITE,
3844 SSL_CB_ALERT,
3845 SSL_CB_READ_ALERT,
3846 SSL_CB_WRITE_ALERT,
3847 SSL_CB_ACCEPT_LOOP,
3848 SSL_CB_ACCEPT_EXIT,
3849 SSL_CB_CONNECT_LOOP,
3850 SSL_CB_CONNECT_EXIT,
3851 SSL_CB_HANDSHAKE_START,
3852 SSL_CB_HANDSHAKE_DONE,
Hynek Schlawack35618382015-09-05 21:54:25 +02003853 ]:
Alex Gaynor5af32d02016-09-24 01:52:21 -04003854 assert isinstance(const, int)
3855
3856 # These constants don't exist on OpenSSL 1.1.0
3857 for const in [
Alex Gaynor03737182020-07-23 20:40:46 -04003858 SSL_ST_INIT,
3859 SSL_ST_BEFORE,
3860 SSL_ST_OK,
3861 SSL_ST_RENEGOTIATE,
Alex Gaynor5af32d02016-09-24 01:52:21 -04003862 ]:
3863 assert const is None or isinstance(const, int)
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003864
Ziga Seilnacht44611bf2009-08-31 20:49:30 +02003865
Cory Benfield1d142142016-03-30 11:51:45 +01003866class TestRequires(object):
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003867 """
3868 Tests for the decorator factory used to conditionally raise
Cory Benfield1d142142016-03-30 11:51:45 +01003869 NotImplementedError when older OpenSSLs are used.
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003870 """
Alex Gaynor03737182020-07-23 20:40:46 -04003871
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003872 def test_available(self):
3873 """
3874 When the OpenSSL functionality is available the decorated functions
3875 work appropriately.
3876 """
3877 feature_guard = _make_requires(True, "Error text")
3878 results = []
3879
3880 @feature_guard
3881 def inner():
3882 results.append(True)
3883 return True
3884
Cory Benfield2333e5e2016-03-30 14:24:16 +01003885 assert inner() is True
3886 assert [True] == results
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003887
3888 def test_unavailable(self):
3889 """
3890 When the OpenSSL functionality is not available the decorated function
3891 does not execute and NotImplementedError is raised.
3892 """
3893 feature_guard = _make_requires(False, "Error text")
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003894
3895 @feature_guard
Alex Chanfb078d82017-04-20 11:16:15 +01003896 def inner(): # pragma: nocover
3897 pytest.fail("Should not be called")
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003898
Cory Benfield1d142142016-03-30 11:51:45 +01003899 with pytest.raises(NotImplementedError) as e:
3900 inner()
3901
3902 assert "Error text" in str(e.value)
Cory Benfield496652a2017-01-24 11:42:56 +00003903
3904
Alex Chanb7480992017-01-30 14:04:47 +00003905class TestOCSP(object):
Cory Benfield496652a2017-01-24 11:42:56 +00003906 """
3907 Tests for PyOpenSSL's OCSP stapling support.
3908 """
Alex Gaynor03737182020-07-23 20:40:46 -04003909
Cory Benfield496652a2017-01-24 11:42:56 +00003910 sample_ocsp_data = b"this is totally ocsp data"
3911
3912 def _client_connection(self, callback, data, request_ocsp=True):
3913 """
3914 Builds a client connection suitable for using OCSP.
3915
3916 :param callback: The callback to register for OCSP.
3917 :param data: The opaque data object that will be handed to the
3918 OCSP callback.
3919 :param request_ocsp: Whether the client will actually ask for OCSP
3920 stapling. Useful for testing only.
3921 """
3922 ctx = Context(SSLv23_METHOD)
3923 ctx.set_ocsp_client_callback(callback, data)
3924 client = Connection(ctx)
3925
3926 if request_ocsp:
3927 client.request_ocsp()
3928
3929 client.set_connect_state()
3930 return client
3931
3932 def _server_connection(self, callback, data):
3933 """
3934 Builds a server connection suitable for using OCSP.
3935
3936 :param callback: The callback to register for OCSP.
3937 :param data: The opaque data object that will be handed to the
3938 OCSP callback.
3939 """
3940 ctx = Context(SSLv23_METHOD)
3941 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
3942 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
3943 ctx.set_ocsp_server_callback(callback, data)
3944 server = Connection(ctx)
3945 server.set_accept_state()
3946 return server
3947
3948 def test_callbacks_arent_called_by_default(self):
3949 """
3950 If both the client and the server have registered OCSP callbacks, but
3951 the client does not send the OCSP request, neither callback gets
3952 called.
3953 """
Alex Gaynor03737182020-07-23 20:40:46 -04003954
Alex Chanfb078d82017-04-20 11:16:15 +01003955 def ocsp_callback(*args, **kwargs): # pragma: nocover
3956 pytest.fail("Should not be called")
Cory Benfield496652a2017-01-24 11:42:56 +00003957
3958 client = self._client_connection(
3959 callback=ocsp_callback, data=None, request_ocsp=False
3960 )
3961 server = self._server_connection(callback=ocsp_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00003962 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003963
Cory Benfield496652a2017-01-24 11:42:56 +00003964 def test_client_negotiates_without_server(self):
3965 """
3966 If the client wants to do OCSP but the server does not, the handshake
3967 succeeds, and the client callback fires with an empty byte string.
3968 """
3969 called = []
3970
3971 def ocsp_callback(conn, ocsp_data, ignored):
3972 called.append(ocsp_data)
3973 return True
3974
3975 client = self._client_connection(callback=ocsp_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00003976 server = loopback_server_factory(socket=None)
3977 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003978
3979 assert len(called) == 1
Alex Gaynor03737182020-07-23 20:40:46 -04003980 assert called[0] == b""
Cory Benfield496652a2017-01-24 11:42:56 +00003981
3982 def test_client_receives_servers_data(self):
3983 """
3984 The data the server sends in its callback is received by the client.
3985 """
3986 calls = []
3987
3988 def server_callback(*args, **kwargs):
3989 return self.sample_ocsp_data
3990
3991 def client_callback(conn, ocsp_data, ignored):
3992 calls.append(ocsp_data)
3993 return True
3994
3995 client = self._client_connection(callback=client_callback, data=None)
3996 server = self._server_connection(callback=server_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00003997 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003998
3999 assert len(calls) == 1
4000 assert calls[0] == self.sample_ocsp_data
4001
4002 def test_callbacks_are_invoked_with_connections(self):
4003 """
4004 The first arguments to both callbacks are their respective connections.
4005 """
4006 client_calls = []
4007 server_calls = []
4008
4009 def client_callback(conn, *args, **kwargs):
4010 client_calls.append(conn)
4011 return True
4012
4013 def server_callback(conn, *args, **kwargs):
4014 server_calls.append(conn)
4015 return self.sample_ocsp_data
4016
4017 client = self._client_connection(callback=client_callback, data=None)
4018 server = self._server_connection(callback=server_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00004019 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00004020
4021 assert len(client_calls) == 1
4022 assert len(server_calls) == 1
4023 assert client_calls[0] is client
4024 assert server_calls[0] is server
4025
4026 def test_opaque_data_is_passed_through(self):
4027 """
4028 Both callbacks receive an opaque, user-provided piece of data in their
4029 callbacks as the final argument.
4030 """
4031 calls = []
4032
4033 def server_callback(*args):
4034 calls.append(args)
4035 return self.sample_ocsp_data
4036
4037 def client_callback(*args):
4038 calls.append(args)
4039 return True
4040
4041 sentinel = object()
4042
4043 client = self._client_connection(
4044 callback=client_callback, data=sentinel
4045 )
4046 server = self._server_connection(
4047 callback=server_callback, data=sentinel
4048 )
Alex Chanb7480992017-01-30 14:04:47 +00004049 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00004050
4051 assert len(calls) == 2
4052 assert calls[0][-1] is sentinel
4053 assert calls[1][-1] is sentinel
4054
4055 def test_server_returns_empty_string(self):
4056 """
4057 If the server returns an empty bytestring from its callback, the
4058 client callback is called with the empty bytestring.
4059 """
4060 client_calls = []
4061
4062 def server_callback(*args):
Alex Gaynor03737182020-07-23 20:40:46 -04004063 return b""
Cory Benfield496652a2017-01-24 11:42:56 +00004064
4065 def client_callback(conn, ocsp_data, ignored):
4066 client_calls.append(ocsp_data)
4067 return True
4068
4069 client = self._client_connection(callback=client_callback, data=None)
4070 server = self._server_connection(callback=server_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00004071 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00004072
4073 assert len(client_calls) == 1
Alex Gaynor03737182020-07-23 20:40:46 -04004074 assert client_calls[0] == b""
Cory Benfield496652a2017-01-24 11:42:56 +00004075
4076 def test_client_returns_false_terminates_handshake(self):
4077 """
4078 If the client returns False from its callback, the handshake fails.
4079 """
Alex Gaynor03737182020-07-23 20:40:46 -04004080
Cory Benfield496652a2017-01-24 11:42:56 +00004081 def server_callback(*args):
4082 return self.sample_ocsp_data
4083
4084 def client_callback(*args):
4085 return False
4086
4087 client = self._client_connection(callback=client_callback, data=None)
4088 server = self._server_connection(callback=server_callback, data=None)
4089
4090 with pytest.raises(Error):
Alex Chanb7480992017-01-30 14:04:47 +00004091 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00004092
4093 def test_exceptions_in_client_bubble_up(self):
4094 """
4095 The callbacks thrown in the client callback bubble up to the caller.
4096 """
Alex Gaynor03737182020-07-23 20:40:46 -04004097
Cory Benfield496652a2017-01-24 11:42:56 +00004098 class SentinelException(Exception):
4099 pass
4100
4101 def server_callback(*args):
4102 return self.sample_ocsp_data
4103
4104 def client_callback(*args):
4105 raise SentinelException()
4106
4107 client = self._client_connection(callback=client_callback, data=None)
4108 server = self._server_connection(callback=server_callback, data=None)
4109
4110 with pytest.raises(SentinelException):
Alex Chanb7480992017-01-30 14:04:47 +00004111 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00004112
4113 def test_exceptions_in_server_bubble_up(self):
4114 """
4115 The callbacks thrown in the server callback bubble up to the caller.
4116 """
Alex Gaynor03737182020-07-23 20:40:46 -04004117
Cory Benfield496652a2017-01-24 11:42:56 +00004118 class SentinelException(Exception):
4119 pass
4120
4121 def server_callback(*args):
4122 raise SentinelException()
4123
Alex Chanfb078d82017-04-20 11:16:15 +01004124 def client_callback(*args): # pragma: nocover
Cory Benfield496652a2017-01-24 11:42:56 +00004125 pytest.fail("Should not be called")
4126
4127 client = self._client_connection(callback=client_callback, data=None)
4128 server = self._server_connection(callback=server_callback, data=None)
4129
4130 with pytest.raises(SentinelException):
Alex Chanb7480992017-01-30 14:04:47 +00004131 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00004132
4133 def test_server_must_return_bytes(self):
4134 """
4135 The server callback must return a bytestring, or a TypeError is thrown.
4136 """
Alex Gaynor03737182020-07-23 20:40:46 -04004137
Cory Benfield496652a2017-01-24 11:42:56 +00004138 def server_callback(*args):
Alex Gaynor03737182020-07-23 20:40:46 -04004139 return self.sample_ocsp_data.decode("ascii")
Cory Benfield496652a2017-01-24 11:42:56 +00004140
Alex Chanfb078d82017-04-20 11:16:15 +01004141 def client_callback(*args): # pragma: nocover
Cory Benfield496652a2017-01-24 11:42:56 +00004142 pytest.fail("Should not be called")
4143
4144 client = self._client_connection(callback=client_callback, data=None)
4145 server = self._server_connection(callback=server_callback, data=None)
4146
4147 with pytest.raises(TypeError):
Alex Chanb7480992017-01-30 14:04:47 +00004148 handshake_in_memory(client, server)