blob: 8fdcae291b77103055fe7fd0a269b2ae5a6ec4eb [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
Arne Schwabe3562df82020-11-27 19:29:49 +01009import gc
Maximilian Hils868dc3c2017-02-10 14:56:55 +010010import sys
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +010011import uuid
12
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -050013from gc import collect, get_referrers
David Benjamin1fbe0642019-04-15 17:05:13 -050014from errno import (
Alex Gaynor03737182020-07-23 20:40:46 -040015 EAFNOSUPPORT,
16 ECONNREFUSED,
17 EINPROGRESS,
18 EWOULDBLOCK,
19 EPIPE,
20 ESHUTDOWN,
21)
Jeremy Lainé1ae7cb62018-03-21 14:49:42 +010022from sys import platform, getfilesystemencoding
David Benjamin1fbe0642019-04-15 17:05:13 -050023from socket import AF_INET, AF_INET6, MSG_PEEK, SHUT_RDWR, error, socket
Jean-Paul Calderonea65cf6c2009-07-19 10:26:52 -040024from os import makedirs
Jean-Paul Calderone1461c492013-10-03 16:05:00 -040025from os.path import join
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -040026from weakref import ref
Alex Chanb7480992017-01-30 14:04:47 +000027from warnings import simplefilter
Jean-Paul Calderone460cc1f2009-03-07 11:31:12 -050028
Alex Gaynor963ae032019-07-06 17:38:32 -040029import flaky
30
Hynek Schlawack734d3022015-09-05 19:19:32 +020031import pytest
32
Paul Kehrer55fb3412017-06-29 18:44:08 -050033from pretend import raiser
34
Hugo van Kemenade60827f82019-08-30 00:39:35 +030035from six import PY2, text_type
Jean-Paul Calderonec76c61c2014-01-18 13:21:52 -050036
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +010037from cryptography import x509
38from cryptography.hazmat.backends import default_backend
39from cryptography.hazmat.primitives import hashes
40from cryptography.hazmat.primitives import serialization
41from cryptography.hazmat.primitives.asymmetric import rsa
42from cryptography.x509.oid import NameOID
43
44
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040045from OpenSSL.crypto import TYPE_RSA, FILETYPE_PEM
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -080046from OpenSSL.crypto import PKey, X509, X509Extension, X509Store
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040047from OpenSSL.crypto import dump_privatekey, load_privatekey
48from OpenSSL.crypto import dump_certificate, load_certificate
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -040049from OpenSSL.crypto import get_elliptic_curves
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040050
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -040051from OpenSSL.SSL import OPENSSL_VERSION_NUMBER, SSLEAY_VERSION, SSLEAY_CFLAGS
52from OpenSSL.SSL import SSLEAY_PLATFORM, SSLEAY_DIR, SSLEAY_BUILT_ON
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -040053from OpenSSL.SSL import SENT_SHUTDOWN, RECEIVED_SHUTDOWN
Jean-Paul Calderone1461c492013-10-03 16:05:00 -040054from OpenSSL.SSL import (
Alex Gaynor03737182020-07-23 20:40:46 -040055 SSLv2_METHOD,
56 SSLv3_METHOD,
57 SSLv23_METHOD,
58 TLSv1_METHOD,
59 TLSv1_1_METHOD,
60 TLSv1_2_METHOD,
61)
Jean-Paul Calderone1461c492013-10-03 16:05:00 -040062from OpenSSL.SSL import OP_SINGLE_DH_USE, OP_NO_SSLv2, OP_NO_SSLv3
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040063from OpenSSL.SSL import (
Alex Gaynor03737182020-07-23 20:40:46 -040064 VERIFY_PEER,
65 VERIFY_FAIL_IF_NO_PEER_CERT,
66 VERIFY_CLIENT_ONCE,
67 VERIFY_NONE,
68)
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040069
Paul Kehrer55fb3412017-06-29 18:44:08 -050070from OpenSSL import SSL
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040071from OpenSSL.SSL import (
Alex Gaynor03737182020-07-23 20:40:46 -040072 SESS_CACHE_OFF,
73 SESS_CACHE_CLIENT,
74 SESS_CACHE_SERVER,
75 SESS_CACHE_BOTH,
76 SESS_CACHE_NO_AUTO_CLEAR,
77 SESS_CACHE_NO_INTERNAL_LOOKUP,
78 SESS_CACHE_NO_INTERNAL_STORE,
79 SESS_CACHE_NO_INTERNAL,
80)
Jean-Paul Calderone313bf012012-02-08 13:02:49 -050081
82from OpenSSL.SSL import (
Alex Gaynor03737182020-07-23 20:40:46 -040083 Error,
84 SysCallError,
85 WantReadError,
86 WantWriteError,
87 ZeroReturnError,
88)
89from OpenSSL.SSL import Context, Session, Connection, SSLeay_version
Cory Benfield0ba57ec2016-03-30 09:35:05 +010090from OpenSSL.SSL import _make_requires
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040091
Paul Kehrer55fb3412017-06-29 18:44:08 -050092from OpenSSL._util import ffi as _ffi, lib as _lib
Cory Benfieldba1820d2015-04-13 17:39:12 -040093
Alex Gaynord3b5d9b2016-07-31 10:54:24 -040094from OpenSSL.SSL import (
Alex Gaynor03737182020-07-23 20:40:46 -040095 OP_NO_QUERY_MTU,
96 OP_COOKIE_EXCHANGE,
97 OP_NO_TICKET,
98 OP_NO_COMPRESSION,
99 MODE_RELEASE_BUFFERS,
100 NO_OVERLAPPING_PROTOCOLS,
101)
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400102
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -0400103from OpenSSL.SSL import (
Alex Gaynor03737182020-07-23 20:40:46 -0400104 SSL_ST_CONNECT,
105 SSL_ST_ACCEPT,
106 SSL_ST_MASK,
107 SSL_CB_LOOP,
108 SSL_CB_EXIT,
109 SSL_CB_READ,
110 SSL_CB_WRITE,
111 SSL_CB_ALERT,
112 SSL_CB_READ_ALERT,
113 SSL_CB_WRITE_ALERT,
114 SSL_CB_ACCEPT_LOOP,
115 SSL_CB_ACCEPT_EXIT,
116 SSL_CB_CONNECT_LOOP,
117 SSL_CB_CONNECT_EXIT,
118 SSL_CB_HANDSHAKE_START,
119 SSL_CB_HANDSHAKE_DONE,
120)
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400121
Alex Gaynor5af32d02016-09-24 01:52:21 -0400122try:
123 from OpenSSL.SSL import (
Alex Gaynor03737182020-07-23 20:40:46 -0400124 SSL_ST_INIT,
125 SSL_ST_BEFORE,
126 SSL_ST_OK,
127 SSL_ST_RENEGOTIATE,
Alex Gaynor5af32d02016-09-24 01:52:21 -0400128 )
129except ImportError:
130 SSL_ST_INIT = SSL_ST_BEFORE = SSL_ST_OK = SSL_ST_RENEGOTIATE = None
131
Alex Chanb7480992017-01-30 14:04:47 +0000132from .util import WARNING_TYPE_EXPECTED, NON_ASCII, is_consistent_type
Hynek Schlawackf0e66852015-10-16 20:18:38 +0200133from .test_crypto import (
Alex Gaynor03737182020-07-23 20:40:46 -0400134 client_cert_pem,
135 client_key_pem,
136 server_cert_pem,
137 server_key_pem,
138 root_cert_pem,
Paul Kehrerbeaf9f52020-08-03 17:50:31 -0500139 root_key_pem,
Alex Gaynor03737182020-07-23 20:40:46 -0400140)
Hynek Schlawackf0e66852015-10-16 20:18:38 +0200141
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200142
Paul Kehrer41dc1362020-08-04 23:44:18 -0500143# openssl dhparam 2048 -out dh-2048.pem
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -0400144dhparam = """\
145-----BEGIN DH PARAMETERS-----
Paul Kehrer41dc1362020-08-04 23:44:18 -0500146MIIBCAKCAQEA2F5e976d/GjsaCdKv5RMWL/YV7fq1UUWpPAer5fDXflLMVUuYXxE
1473m3ayZob9lbpgEU0jlPAsXHfQPGxpKmvhv+xV26V/DEoukED8JeZUY/z4pigoptl
148+8+TYdNNE/rFSZQFXIp+v2D91IEgmHBnZlKFSbKR+p8i0KjExXGjU6ji3S5jkOku
149ogikc7df1Ui0hWNJCmTjExq07aXghk97PsdFSxjdawuG3+vos5bnNoUwPLYlFc/z
150ITYG0KXySiCLi4UDlXTZTz7u/+OYczPEgqa/JPUddbM/kfvaRAnjY38cfQ7qXf8Y
151i5s5yYK7a/0eWxxRr2qraYaUj8RwDpH9CwIBAg==
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -0400152-----END DH PARAMETERS-----
153"""
154
155
Hugo van Kemenade60827f82019-08-30 00:39:35 +0300156skip_if_py3 = pytest.mark.skipif(not PY2, reason="Python 2 only")
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200157
158
David Benjamin1fbe0642019-04-15 17:05:13 -0500159def socket_any_family():
160 try:
161 return socket(AF_INET)
162 except error as e:
163 if e.errno == EAFNOSUPPORT:
164 return socket(AF_INET6)
165 raise
166
167
168def loopback_address(socket):
169 if socket.family == AF_INET:
170 return "127.0.0.1"
171 else:
172 assert socket.family == AF_INET6
173 return "::1"
174
175
Jean-Paul Calderone05826732015-04-12 11:38:49 -0400176def join_bytes_or_unicode(prefix, suffix):
177 """
178 Join two path components of either ``bytes`` or ``unicode``.
179
180 The return type is the same as the type of ``prefix``.
181 """
182 # If the types are the same, nothing special is necessary.
183 if type(prefix) == type(suffix):
184 return join(prefix, suffix)
185
186 # Otherwise, coerce suffix to the type of prefix.
187 if isinstance(prefix, text_type):
188 return join(prefix, suffix.decode(getfilesystemencoding()))
189 else:
190 return join(prefix, suffix.encode(getfilesystemencoding()))
191
192
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400193def verify_cb(conn, cert, errnum, depth, ok):
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400194 return ok
195
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400196
Rick Deanb1ccd562009-07-09 23:52:39 -0500197def socket_pair():
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400198 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400199 Establish and return a pair of network sockets connected to each other.
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400200 """
201 # Connect a pair of sockets
David Benjamin1fbe0642019-04-15 17:05:13 -0500202 port = socket_any_family()
Alex Gaynor03737182020-07-23 20:40:46 -0400203 port.bind(("", 0))
Rick Deanb1ccd562009-07-09 23:52:39 -0500204 port.listen(1)
David Benjamin1fbe0642019-04-15 17:05:13 -0500205 client = socket(port.family)
Rick Deanb1ccd562009-07-09 23:52:39 -0500206 client.setblocking(False)
David Benjamin1fbe0642019-04-15 17:05:13 -0500207 client.connect_ex((loopback_address(port), port.getsockname()[1]))
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400208 client.setblocking(True)
Rick Deanb1ccd562009-07-09 23:52:39 -0500209 server = port.accept()[0]
Rick Deanb1ccd562009-07-09 23:52:39 -0500210
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400211 # Let's pass some unencrypted data to make sure our socket connection is
212 # fine. Just one byte, so we don't have to worry about buffers getting
213 # filled up or fragmentation.
Alex Gaynore7f51982016-09-11 11:48:14 -0400214 server.send(b"x")
215 assert client.recv(1024) == b"x"
216 client.send(b"y")
217 assert server.recv(1024) == b"y"
Rick Deanb1ccd562009-07-09 23:52:39 -0500218
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -0400219 # Most of our callers want non-blocking sockets, make it easy for them.
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400220 server.setblocking(False)
221 client.setblocking(False)
Jim Shaver46f28912015-05-29 19:32:16 -0400222
Rick Deanb1ccd562009-07-09 23:52:39 -0500223 return (server, client)
224
225
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400226def handshake(client, server):
227 conns = [client, server]
228 while conns:
229 for conn in conns:
230 try:
231 conn.do_handshake()
232 except WantReadError:
233 pass
234 else:
235 conns.remove(conn)
236
237
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400238def _create_certificate_chain():
239 """
240 Construct and return a chain of certificates.
241
242 1. A new self-signed certificate authority certificate (cacert)
243 2. A new intermediate certificate signed by cacert (icert)
244 3. A new server certificate signed by icert (scert)
245 """
Alex Gaynor03737182020-07-23 20:40:46 -0400246 caext = X509Extension(b"basicConstraints", False, b"CA:true")
247 not_after_date = datetime.date.today() + datetime.timedelta(days=365)
Alex Gaynor675534c2020-01-12 11:59:49 -0600248 not_after = not_after_date.strftime("%Y%m%d%H%M%SZ").encode("ascii")
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400249
250 # Step 1
251 cakey = PKey()
Alex Gaynor8cd336e2020-08-03 10:36:32 -0400252 cakey.generate_key(TYPE_RSA, 2048)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400253 cacert = X509()
David Benjamin6b799472020-06-24 17:14:16 -0400254 cacert.set_version(2)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400255 cacert.get_subject().commonName = "Authority Certificate"
256 cacert.set_issuer(cacert.get_subject())
257 cacert.set_pubkey(cakey)
Alex Gaynore7f51982016-09-11 11:48:14 -0400258 cacert.set_notBefore(b"20000101000000Z")
Alex Gaynor675534c2020-01-12 11:59:49 -0600259 cacert.set_notAfter(not_after)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400260 cacert.add_extensions([caext])
261 cacert.set_serial_number(0)
Paul Kehrerd4b60462020-08-03 18:26:03 -0500262 cacert.sign(cakey, "sha256")
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400263
264 # Step 2
265 ikey = PKey()
Alex Gaynor8cd336e2020-08-03 10:36:32 -0400266 ikey.generate_key(TYPE_RSA, 2048)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400267 icert = X509()
David Benjamin6b799472020-06-24 17:14:16 -0400268 icert.set_version(2)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400269 icert.get_subject().commonName = "Intermediate Certificate"
270 icert.set_issuer(cacert.get_subject())
271 icert.set_pubkey(ikey)
Alex Gaynore7f51982016-09-11 11:48:14 -0400272 icert.set_notBefore(b"20000101000000Z")
Alex Gaynor675534c2020-01-12 11:59:49 -0600273 icert.set_notAfter(not_after)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400274 icert.add_extensions([caext])
275 icert.set_serial_number(0)
Paul Kehrerd4b60462020-08-03 18:26:03 -0500276 icert.sign(cakey, "sha256")
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400277
278 # Step 3
279 skey = PKey()
Alex Gaynor8cd336e2020-08-03 10:36:32 -0400280 skey.generate_key(TYPE_RSA, 2048)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400281 scert = X509()
David Benjamin6b799472020-06-24 17:14:16 -0400282 scert.set_version(2)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400283 scert.get_subject().commonName = "Server Certificate"
284 scert.set_issuer(icert.get_subject())
285 scert.set_pubkey(skey)
Alex Gaynore7f51982016-09-11 11:48:14 -0400286 scert.set_notBefore(b"20000101000000Z")
Alex Gaynor675534c2020-01-12 11:59:49 -0600287 scert.set_notAfter(not_after)
Alex Gaynor03737182020-07-23 20:40:46 -0400288 scert.add_extensions(
289 [X509Extension(b"basicConstraints", True, b"CA:false")]
290 )
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400291 scert.set_serial_number(0)
Paul Kehrerd4b60462020-08-03 18:26:03 -0500292 scert.sign(ikey, "sha256")
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400293
294 return [(cakey, cacert), (ikey, icert), (skey, scert)]
295
296
Paul Kehrer7d5a3bf2019-01-21 12:24:02 -0600297def loopback_client_factory(socket, version=SSLv23_METHOD):
298 client = Connection(Context(version), socket)
Alex Chan1c0cb662017-01-30 07:13:30 +0000299 client.set_connect_state()
300 return client
301
302
Paul Kehrer7d5a3bf2019-01-21 12:24:02 -0600303def loopback_server_factory(socket, version=SSLv23_METHOD):
304 ctx = Context(version)
Alex Chan1c0cb662017-01-30 07:13:30 +0000305 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
306 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
307 server = Connection(ctx, socket)
308 server.set_accept_state()
309 return server
310
311
312def loopback(server_factory=None, client_factory=None):
313 """
314 Create a connected socket pair and force two connected SSL sockets
315 to talk to each other via memory BIOs.
316 """
317 if server_factory is None:
318 server_factory = loopback_server_factory
319 if client_factory is None:
320 client_factory = loopback_client_factory
321
322 (server, client) = socket_pair()
323 server = server_factory(server)
324 client = client_factory(client)
325
326 handshake(client, server)
327
328 server.setblocking(True)
329 client.setblocking(True)
330 return server, client
331
332
Alex Chan1ca9e3a2016-11-05 13:01:51 +0000333def interact_in_memory(client_conn, server_conn):
334 """
335 Try to read application bytes from each of the two `Connection` objects.
336 Copy bytes back and forth between their send/receive buffers for as long
337 as there is anything to copy. When there is nothing more to copy,
338 return `None`. If one of them actually manages to deliver some application
339 bytes, return a two-tuple of the connection from which the bytes were read
340 and the bytes themselves.
341 """
342 wrote = True
343 while wrote:
344 # Loop until neither side has anything to say
345 wrote = False
346
347 # Copy stuff from each side's send buffer to the other side's
348 # receive buffer.
Alex Gaynor03737182020-07-23 20:40:46 -0400349 for (read, write) in [
350 (client_conn, server_conn),
351 (server_conn, client_conn),
352 ]:
Alex Chan1ca9e3a2016-11-05 13:01:51 +0000353
354 # Give the side a chance to generate some more bytes, or succeed.
355 try:
356 data = read.recv(2 ** 16)
357 except WantReadError:
358 # It didn't succeed, so we'll hope it generated some output.
359 pass
360 else:
361 # It did succeed, so we'll stop now and let the caller deal
362 # with it.
363 return (read, data)
364
365 while True:
366 # Keep copying as long as there's more stuff there.
367 try:
368 dirty = read.bio_read(4096)
369 except WantReadError:
370 # Okay, nothing more waiting to be sent. Stop
371 # processing this send buffer.
372 break
373 else:
374 # Keep track of the fact that someone generated some
375 # output.
376 wrote = True
377 write.bio_write(dirty)
378
379
Alex Chan532b79e2017-01-24 15:14:52 +0000380def handshake_in_memory(client_conn, server_conn):
381 """
382 Perform the TLS handshake between two `Connection` instances connected to
383 each other via memory BIOs.
384 """
385 client_conn.set_connect_state()
386 server_conn.set_accept_state()
387
388 for conn in [client_conn, server_conn]:
389 try:
390 conn.do_handshake()
391 except WantReadError:
392 pass
393
394 interact_in_memory(client_conn, server_conn)
395
396
Alex Chanb7480992017-01-30 14:04:47 +0000397class TestVersion(object):
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400398 """
Alex Chanb7480992017-01-30 14:04:47 +0000399 Tests for version information exposed by `OpenSSL.SSL.SSLeay_version` and
400 `OpenSSL.SSL.OPENSSL_VERSION_NUMBER`.
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400401 """
Alex Gaynor03737182020-07-23 20:40:46 -0400402
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400403 def test_OPENSSL_VERSION_NUMBER(self):
404 """
Alex Chanb7480992017-01-30 14:04:47 +0000405 `OPENSSL_VERSION_NUMBER` is an integer with status in the low byte and
406 the patch, fix, minor, and major versions in the nibbles above that.
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400407 """
Alex Chanb7480992017-01-30 14:04:47 +0000408 assert isinstance(OPENSSL_VERSION_NUMBER, int)
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400409
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400410 def test_SSLeay_version(self):
411 """
Alex Chanb7480992017-01-30 14:04:47 +0000412 `SSLeay_version` takes a version type indicator and returns one of a
413 number of version strings based on that indicator.
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400414 """
415 versions = {}
Alex Gaynor03737182020-07-23 20:40:46 -0400416 for t in [
417 SSLEAY_VERSION,
418 SSLEAY_CFLAGS,
419 SSLEAY_BUILT_ON,
420 SSLEAY_PLATFORM,
421 SSLEAY_DIR,
422 ]:
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400423 version = SSLeay_version(t)
424 versions[version] = t
Alex Chanb7480992017-01-30 14:04:47 +0000425 assert isinstance(version, bytes)
426 assert len(versions) == 5
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400427
428
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100429@pytest.fixture
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100430def ca_file(tmpdir):
431 """
432 Create a valid PEM file with CA certificates and return the path.
433 """
434 key = rsa.generate_private_key(
Alex Gaynor03737182020-07-23 20:40:46 -0400435 public_exponent=65537, key_size=2048, backend=default_backend()
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100436 )
437 public_key = key.public_key()
438
439 builder = x509.CertificateBuilder()
Alex Gaynor03737182020-07-23 20:40:46 -0400440 builder = builder.subject_name(
441 x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, u"pyopenssl.org")])
442 )
443 builder = builder.issuer_name(
444 x509.Name([x509.NameAttribute(NameOID.COMMON_NAME, u"pyopenssl.org")])
445 )
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100446 one_day = datetime.timedelta(1, 0, 0)
447 builder = builder.not_valid_before(datetime.datetime.today() - one_day)
448 builder = builder.not_valid_after(datetime.datetime.today() + one_day)
449 builder = builder.serial_number(int(uuid.uuid4()))
450 builder = builder.public_key(public_key)
451 builder = builder.add_extension(
Alex Gaynor04882142020-08-26 22:50:40 -0400452 x509.BasicConstraints(ca=True, path_length=None),
453 critical=True,
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100454 )
455
456 certificate = builder.sign(
Alex Gaynor03737182020-07-23 20:40:46 -0400457 private_key=key, algorithm=hashes.SHA256(), backend=default_backend()
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100458 )
459
460 ca_file = tmpdir.join("test.pem")
461 ca_file.write_binary(
Alex Gaynor04882142020-08-26 22:50:40 -0400462 certificate.public_bytes(
463 encoding=serialization.Encoding.PEM,
464 )
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100465 )
466
467 return str(ca_file).encode("ascii")
468
469
470@pytest.fixture
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100471def context():
472 """
Paul Kehrer688538c2020-08-03 19:18:15 -0500473 A simple "best TLS you can get" context. TLS 1.2+ in any reasonable OpenSSL
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100474 """
Paul Kehrer688538c2020-08-03 19:18:15 -0500475 return Context(SSLv23_METHOD)
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100476
477
478class TestContext(object):
Hynek Schlawackaa861212016-03-13 13:53:48 +0100479 """
Alex Chan532b79e2017-01-24 15:14:52 +0000480 Unit tests for `OpenSSL.SSL.Context`.
Hynek Schlawackaa861212016-03-13 13:53:48 +0100481 """
Alex Gaynor03737182020-07-23 20:40:46 -0400482
483 @pytest.mark.parametrize(
484 "cipher_string",
485 [b"hello world:AES128-SHA", u"hello world:AES128-SHA"],
486 )
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100487 def test_set_cipher_list(self, context, cipher_string):
488 """
Alex Chan532b79e2017-01-24 15:14:52 +0000489 `Context.set_cipher_list` accepts both byte and unicode strings
Hynek Schlawacka7a63af2016-03-11 12:05:26 +0100490 for naming the ciphers which connections created with the context
491 object will be able to choose from.
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100492 """
493 context.set_cipher_list(cipher_string)
494 conn = Connection(context, None)
495
496 assert "AES128-SHA" in conn.get_cipher_list()
497
Mark Williamsdf2480d2019-02-14 19:30:07 -0800498 def test_set_cipher_list_wrong_type(self, context):
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100499 """
Alex Chan532b79e2017-01-24 15:14:52 +0000500 `Context.set_cipher_list` raises `TypeError` when passed a non-string
Mark Williamsdf2480d2019-02-14 19:30:07 -0800501 argument.
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100502 """
Mark Williamsdf2480d2019-02-14 19:30:07 -0800503 with pytest.raises(TypeError):
504 context.set_cipher_list(object())
505
Alex Gaynor963ae032019-07-06 17:38:32 -0400506 @flaky.flaky
Mark Williamsdf2480d2019-02-14 19:30:07 -0800507 def test_set_cipher_list_no_cipher_match(self, context):
508 """
509 `Context.set_cipher_list` raises `OpenSSL.SSL.Error` with a
510 `"no cipher match"` reason string regardless of the TLS
511 version.
512 """
513 with pytest.raises(Error) as excinfo:
514 context.set_cipher_list(b"imaginary-cipher")
515 assert excinfo.value.args == (
Alex Gaynor04882142020-08-26 22:50:40 -0400516 [
517 (
518 "SSL routines",
519 "SSL_CTX_set_cipher_list",
520 "no cipher match",
521 )
522 ],
Alex Gaynor03737182020-07-23 20:40:46 -0400523 )
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100524
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100525 def test_load_client_ca(self, context, ca_file):
526 """
Alex Chan532b79e2017-01-24 15:14:52 +0000527 `Context.load_client_ca` works as far as we can tell.
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100528 """
529 context.load_client_ca(ca_file)
530
531 def test_load_client_ca_invalid(self, context, tmpdir):
532 """
Alex Chan532b79e2017-01-24 15:14:52 +0000533 `Context.load_client_ca` raises an Error if the ca file is invalid.
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100534 """
535 ca_file = tmpdir.join("test.pem")
536 ca_file.write("")
537
538 with pytest.raises(Error) as e:
539 context.load_client_ca(str(ca_file).encode("ascii"))
540
541 assert "PEM routines" == e.value.args[0][0][0]
542
543 def test_load_client_ca_unicode(self, context, ca_file):
544 """
545 Passing the path as unicode raises a warning but works.
546 """
Alex Gaynor03737182020-07-23 20:40:46 -0400547 pytest.deprecated_call(context.load_client_ca, ca_file.decode("ascii"))
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100548
549 def test_set_session_id(self, context):
550 """
Alex Chan532b79e2017-01-24 15:14:52 +0000551 `Context.set_session_id` works as far as we can tell.
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100552 """
553 context.set_session_id(b"abc")
554
555 def test_set_session_id_fail(self, context):
556 """
Alex Chan532b79e2017-01-24 15:14:52 +0000557 `Context.set_session_id` errors are propagated.
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100558 """
559 with pytest.raises(Error) as e:
560 context.set_session_id(b"abc" * 1000)
561
562 assert [
Alex Gaynor03737182020-07-23 20:40:46 -0400563 (
564 "SSL routines",
565 "SSL_CTX_set_session_id_context",
566 "ssl session id context too long",
567 )
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100568 ] == e.value.args[0]
569
570 def test_set_session_id_unicode(self, context):
571 """
Alex Chan532b79e2017-01-24 15:14:52 +0000572 `Context.set_session_id` raises a warning if a unicode string is
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100573 passed.
574 """
575 pytest.deprecated_call(context.set_session_id, u"abc")
576
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400577 def test_method(self):
578 """
Alex Chan532b79e2017-01-24 15:14:52 +0000579 `Context` can be instantiated with one of `SSLv2_METHOD`,
580 `SSLv3_METHOD`, `SSLv23_METHOD`, `TLSv1_METHOD`, `TLSv1_1_METHOD`,
581 or `TLSv1_2_METHOD`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400582 """
Alex Gaynor5af32d02016-09-24 01:52:21 -0400583 methods = [SSLv23_METHOD, TLSv1_METHOD]
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400584 for meth in methods:
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400585 Context(meth)
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400586
Alex Gaynor5af32d02016-09-24 01:52:21 -0400587 maybe = [SSLv2_METHOD, SSLv3_METHOD, TLSv1_1_METHOD, TLSv1_2_METHOD]
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400588 for meth in maybe:
589 try:
590 Context(meth)
591 except (Error, ValueError):
592 # Some versions of OpenSSL have SSLv2 / TLSv1.1 / TLSv1.2, some
593 # don't. Difficult to say in advance.
594 pass
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400595
Alex Chan532b79e2017-01-24 15:14:52 +0000596 with pytest.raises(TypeError):
597 Context("")
598 with pytest.raises(ValueError):
599 Context(10)
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400600
Rick Deane15b1472009-07-09 15:53:42 -0500601 def test_type(self):
602 """
Alex Gaynor01f90a12019-02-07 09:14:48 -0500603 `Context` can be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -0500604 """
Alex Gaynor03737182020-07-23 20:40:46 -0400605 assert is_consistent_type(Context, "Context", TLSv1_METHOD)
Rick Deane15b1472009-07-09 15:53:42 -0500606
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400607 def test_use_privatekey(self):
608 """
Alex Chan532b79e2017-01-24 15:14:52 +0000609 `Context.use_privatekey` takes an `OpenSSL.crypto.PKey` instance.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400610 """
611 key = PKey()
Paul Kehrerc45a6ea2020-08-03 15:54:20 -0500612 key.generate_key(TYPE_RSA, 1024)
Paul Kehrer688538c2020-08-03 19:18:15 -0500613 ctx = Context(SSLv23_METHOD)
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400614 ctx.use_privatekey(key)
Alex Chan532b79e2017-01-24 15:14:52 +0000615 with pytest.raises(TypeError):
616 ctx.use_privatekey("")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400617
Alex Chan532b79e2017-01-24 15:14:52 +0000618 def test_use_privatekey_file_missing(self, tmpfile):
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800619 """
Alex Chan532b79e2017-01-24 15:14:52 +0000620 `Context.use_privatekey_file` raises `OpenSSL.SSL.Error` when passed
621 the name of a file which does not exist.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800622 """
Paul Kehrer688538c2020-08-03 19:18:15 -0500623 ctx = Context(SSLv23_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000624 with pytest.raises(Error):
625 ctx.use_privatekey_file(tmpfile)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800626
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400627 def _use_privatekey_file_test(self, pemfile, filetype):
628 """
629 Verify that calling ``Context.use_privatekey_file`` with the given
630 arguments does not raise an exception.
631 """
632 key = PKey()
Paul Kehrerc45a6ea2020-08-03 15:54:20 -0500633 key.generate_key(TYPE_RSA, 1024)
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400634
635 with open(pemfile, "wt") as pem:
Alex Gaynor03737182020-07-23 20:40:46 -0400636 pem.write(dump_privatekey(FILETYPE_PEM, key).decode("ascii"))
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400637
Paul Kehrer688538c2020-08-03 19:18:15 -0500638 ctx = Context(SSLv23_METHOD)
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400639 ctx.use_privatekey_file(pemfile, filetype)
640
Alex Gaynor03737182020-07-23 20:40:46 -0400641 @pytest.mark.parametrize("filetype", [object(), "", None, 1.0])
Alex Chanfb078d82017-04-20 11:16:15 +0100642 def test_wrong_privatekey_file_wrong_args(self, tmpfile, filetype):
643 """
644 `Context.use_privatekey_file` raises `TypeError` when called with
645 a `filetype` which is not a valid file encoding.
646 """
Paul Kehrer688538c2020-08-03 19:18:15 -0500647 ctx = Context(SSLv23_METHOD)
Alex Chanfb078d82017-04-20 11:16:15 +0100648 with pytest.raises(TypeError):
649 ctx.use_privatekey_file(tmpfile, filetype)
650
Alex Chan532b79e2017-01-24 15:14:52 +0000651 def test_use_privatekey_file_bytes(self, tmpfile):
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400652 """
653 A private key can be specified from a file by passing a ``bytes``
654 instance giving the file name to ``Context.use_privatekey_file``.
655 """
656 self._use_privatekey_file_test(
Alex Gaynor04882142020-08-26 22:50:40 -0400657 tmpfile + NON_ASCII.encode(getfilesystemencoding()),
658 FILETYPE_PEM,
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400659 )
660
Alex Chan532b79e2017-01-24 15:14:52 +0000661 def test_use_privatekey_file_unicode(self, tmpfile):
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400662 """
663 A private key can be specified from a file by passing a ``unicode``
664 instance giving the file name to ``Context.use_privatekey_file``.
665 """
666 self._use_privatekey_file_test(
Alex Gaynor04882142020-08-26 22:50:40 -0400667 tmpfile.decode(getfilesystemencoding()) + NON_ASCII,
668 FILETYPE_PEM,
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400669 )
670
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800671 def test_use_certificate_wrong_args(self):
672 """
Alex Chan532b79e2017-01-24 15:14:52 +0000673 `Context.use_certificate_wrong_args` raises `TypeError` when not passed
674 exactly one `OpenSSL.crypto.X509` instance as an argument.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800675 """
Paul Kehrer688538c2020-08-03 19:18:15 -0500676 ctx = Context(SSLv23_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000677 with pytest.raises(TypeError):
678 ctx.use_certificate("hello, world")
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800679
680 def test_use_certificate_uninitialized(self):
681 """
Alex Chan532b79e2017-01-24 15:14:52 +0000682 `Context.use_certificate` raises `OpenSSL.SSL.Error` when passed a
683 `OpenSSL.crypto.X509` instance which has not been initialized
684 (ie, which does not actually have any certificate data).
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800685 """
Paul Kehrer688538c2020-08-03 19:18:15 -0500686 ctx = Context(SSLv23_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000687 with pytest.raises(Error):
688 ctx.use_certificate(X509())
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800689
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800690 def test_use_certificate(self):
691 """
Alex Chan532b79e2017-01-24 15:14:52 +0000692 `Context.use_certificate` sets the certificate which will be
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800693 used to identify connections created using the context.
694 """
695 # TODO
696 # Hard to assert anything. But we could set a privatekey then ask
697 # OpenSSL if the cert and key agree using check_privatekey. Then as
698 # long as check_privatekey works right we're good...
Paul Kehrer688538c2020-08-03 19:18:15 -0500699 ctx = Context(SSLv23_METHOD)
Paul Kehrerbeaf9f52020-08-03 17:50:31 -0500700 ctx.use_certificate(load_certificate(FILETYPE_PEM, root_cert_pem))
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800701
702 def test_use_certificate_file_wrong_args(self):
703 """
Alex Chan532b79e2017-01-24 15:14:52 +0000704 `Context.use_certificate_file` raises `TypeError` if the first
705 argument is not a byte string or the second argument is not an integer.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800706 """
Paul Kehrer688538c2020-08-03 19:18:15 -0500707 ctx = Context(SSLv23_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000708 with pytest.raises(TypeError):
709 ctx.use_certificate_file(object(), FILETYPE_PEM)
710 with pytest.raises(TypeError):
711 ctx.use_certificate_file(b"somefile", object())
712 with pytest.raises(TypeError):
713 ctx.use_certificate_file(object(), FILETYPE_PEM)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800714
Alex Chan532b79e2017-01-24 15:14:52 +0000715 def test_use_certificate_file_missing(self, tmpfile):
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800716 """
Alex Chan532b79e2017-01-24 15:14:52 +0000717 `Context.use_certificate_file` raises `OpenSSL.SSL.Error` if passed
718 the name of a file which does not exist.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800719 """
Paul Kehrer688538c2020-08-03 19:18:15 -0500720 ctx = Context(SSLv23_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000721 with pytest.raises(Error):
722 ctx.use_certificate_file(tmpfile)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800723
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400724 def _use_certificate_file_test(self, certificate_file):
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800725 """
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400726 Verify that calling ``Context.use_certificate_file`` with the given
727 filename doesn't raise an exception.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800728 """
729 # TODO
730 # Hard to assert anything. But we could set a privatekey then ask
731 # OpenSSL if the cert and key agree using check_privatekey. Then as
732 # long as check_privatekey works right we're good...
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400733 with open(certificate_file, "wb") as pem_file:
Paul Kehrerbeaf9f52020-08-03 17:50:31 -0500734 pem_file.write(root_cert_pem)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800735
Paul Kehrer688538c2020-08-03 19:18:15 -0500736 ctx = Context(SSLv23_METHOD)
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400737 ctx.use_certificate_file(certificate_file)
738
Alex Chan532b79e2017-01-24 15:14:52 +0000739 def test_use_certificate_file_bytes(self, tmpfile):
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400740 """
Alex Chan532b79e2017-01-24 15:14:52 +0000741 `Context.use_certificate_file` sets the certificate (given as a
742 `bytes` filename) which will be used to identify connections created
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400743 using the context.
744 """
Alex Chan532b79e2017-01-24 15:14:52 +0000745 filename = tmpfile + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400746 self._use_certificate_file_test(filename)
747
Alex Chan532b79e2017-01-24 15:14:52 +0000748 def test_use_certificate_file_unicode(self, tmpfile):
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400749 """
Alex Chan532b79e2017-01-24 15:14:52 +0000750 `Context.use_certificate_file` sets the certificate (given as a
751 `bytes` filename) which will be used to identify connections created
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400752 using the context.
753 """
Alex Chan532b79e2017-01-24 15:14:52 +0000754 filename = tmpfile.decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400755 self._use_certificate_file_test(filename)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800756
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500757 def test_check_privatekey_valid(self):
758 """
Alex Chan532b79e2017-01-24 15:14:52 +0000759 `Context.check_privatekey` returns `None` if the `Context` instance
760 has been configured to use a matched key and certificate pair.
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500761 """
762 key = load_privatekey(FILETYPE_PEM, client_key_pem)
763 cert = load_certificate(FILETYPE_PEM, client_cert_pem)
Paul Kehrer688538c2020-08-03 19:18:15 -0500764 context = Context(SSLv23_METHOD)
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500765 context.use_privatekey(key)
766 context.use_certificate(cert)
Alex Chan532b79e2017-01-24 15:14:52 +0000767 assert None is context.check_privatekey()
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500768
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500769 def test_check_privatekey_invalid(self):
770 """
Alex Chan532b79e2017-01-24 15:14:52 +0000771 `Context.check_privatekey` raises `Error` if the `Context` instance
772 has been configured to use a key and certificate pair which don't
773 relate to each other.
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500774 """
775 key = load_privatekey(FILETYPE_PEM, client_key_pem)
776 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
Paul Kehrer688538c2020-08-03 19:18:15 -0500777 context = Context(SSLv23_METHOD)
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500778 context.use_privatekey(key)
779 context.use_certificate(cert)
Alex Chan532b79e2017-01-24 15:14:52 +0000780 with pytest.raises(Error):
781 context.check_privatekey()
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400782
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400783 def test_app_data(self):
784 """
Alex Chan532b79e2017-01-24 15:14:52 +0000785 `Context.set_app_data` stores an object for later retrieval
786 using `Context.get_app_data`.
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400787 """
788 app_data = object()
Paul Kehrer688538c2020-08-03 19:18:15 -0500789 context = Context(SSLv23_METHOD)
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400790 context.set_app_data(app_data)
Alex Chan532b79e2017-01-24 15:14:52 +0000791 assert context.get_app_data() is app_data
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400792
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400793 def test_set_options_wrong_args(self):
794 """
Alex Chan532b79e2017-01-24 15:14:52 +0000795 `Context.set_options` raises `TypeError` if called with
796 a non-`int` argument.
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400797 """
Paul Kehrer688538c2020-08-03 19:18:15 -0500798 context = Context(SSLv23_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000799 with pytest.raises(TypeError):
800 context.set_options(None)
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400801
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500802 def test_set_options(self):
803 """
Alex Chan532b79e2017-01-24 15:14:52 +0000804 `Context.set_options` returns the new options value.
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500805 """
Paul Kehrer688538c2020-08-03 19:18:15 -0500806 context = Context(SSLv23_METHOD)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500807 options = context.set_options(OP_NO_SSLv2)
Alex Gaynor2310f8b2016-09-10 14:39:32 -0400808 assert options & OP_NO_SSLv2 == OP_NO_SSLv2
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500809
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300810 def test_set_mode_wrong_args(self):
811 """
Alex Chan532b79e2017-01-24 15:14:52 +0000812 `Context.set_mode` raises `TypeError` if called with
813 a non-`int` argument.
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300814 """
Paul Kehrer688538c2020-08-03 19:18:15 -0500815 context = Context(SSLv23_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000816 with pytest.raises(TypeError):
817 context.set_mode(None)
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300818
Alex Gaynord3b5d9b2016-07-31 10:54:24 -0400819 def test_set_mode(self):
820 """
Alex Chan532b79e2017-01-24 15:14:52 +0000821 `Context.set_mode` accepts a mode bitvector and returns the
Alex Gaynord3b5d9b2016-07-31 10:54:24 -0400822 newly set mode.
823 """
Paul Kehrer688538c2020-08-03 19:18:15 -0500824 context = Context(SSLv23_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000825 assert MODE_RELEASE_BUFFERS & context.set_mode(MODE_RELEASE_BUFFERS)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500826
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400827 def test_set_timeout_wrong_args(self):
828 """
Alex Chan532b79e2017-01-24 15:14:52 +0000829 `Context.set_timeout` raises `TypeError` if called with
830 a non-`int` argument.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400831 """
Paul Kehrer688538c2020-08-03 19:18:15 -0500832 context = Context(SSLv23_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000833 with pytest.raises(TypeError):
834 context.set_timeout(None)
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400835
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400836 def test_timeout(self):
837 """
Alex Chan532b79e2017-01-24 15:14:52 +0000838 `Context.set_timeout` sets the session timeout for all connections
839 created using the context object. `Context.get_timeout` retrieves
840 this value.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400841 """
Paul Kehrer688538c2020-08-03 19:18:15 -0500842 context = Context(SSLv23_METHOD)
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400843 context.set_timeout(1234)
Alex Chan532b79e2017-01-24 15:14:52 +0000844 assert context.get_timeout() == 1234
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400845
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400846 def test_set_verify_depth_wrong_args(self):
847 """
Alex Chan532b79e2017-01-24 15:14:52 +0000848 `Context.set_verify_depth` raises `TypeError` if called with a
849 non-`int` argument.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400850 """
Paul Kehrer688538c2020-08-03 19:18:15 -0500851 context = Context(SSLv23_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000852 with pytest.raises(TypeError):
853 context.set_verify_depth(None)
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400854
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400855 def test_verify_depth(self):
856 """
Alex Chan532b79e2017-01-24 15:14:52 +0000857 `Context.set_verify_depth` sets the number of certificates in
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200858 a chain to follow before giving up. The value can be retrieved with
Alex Chan532b79e2017-01-24 15:14:52 +0000859 `Context.get_verify_depth`.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400860 """
Paul Kehrer688538c2020-08-03 19:18:15 -0500861 context = Context(SSLv23_METHOD)
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400862 context.set_verify_depth(11)
Alex Chan532b79e2017-01-24 15:14:52 +0000863 assert context.get_verify_depth() == 11
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400864
Alex Chan532b79e2017-01-24 15:14:52 +0000865 def _write_encrypted_pem(self, passphrase, tmpfile):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400866 """
867 Write a new private key out to a new file, encrypted using the given
868 passphrase. Return the path to the new file.
869 """
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400870 key = PKey()
Paul Kehrerc45a6ea2020-08-03 15:54:20 -0500871 key.generate_key(TYPE_RSA, 1024)
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400872 pem = dump_privatekey(FILETYPE_PEM, key, "blowfish", passphrase)
Alex Gaynor03737182020-07-23 20:40:46 -0400873 with open(tmpfile, "w") as fObj:
874 fObj.write(pem.decode("ascii"))
Alex Chan532b79e2017-01-24 15:14:52 +0000875 return tmpfile
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400876
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400877 def test_set_passwd_cb_wrong_args(self):
878 """
Alex Chan532b79e2017-01-24 15:14:52 +0000879 `Context.set_passwd_cb` raises `TypeError` if called with a
880 non-callable first argument.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400881 """
Paul Kehrer688538c2020-08-03 19:18:15 -0500882 context = Context(SSLv23_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000883 with pytest.raises(TypeError):
884 context.set_passwd_cb(None)
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400885
Alex Chan532b79e2017-01-24 15:14:52 +0000886 def test_set_passwd_cb(self, tmpfile):
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400887 """
Alex Chan532b79e2017-01-24 15:14:52 +0000888 `Context.set_passwd_cb` accepts a callable which will be invoked when
889 a private key is loaded from an encrypted PEM.
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400890 """
Alex Gaynore7f51982016-09-11 11:48:14 -0400891 passphrase = b"foobar"
Alex Chan532b79e2017-01-24 15:14:52 +0000892 pemFile = self._write_encrypted_pem(passphrase, tmpfile)
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400893 calledWith = []
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200894
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400895 def passphraseCallback(maxlen, verify, extra):
896 calledWith.append((maxlen, verify, extra))
897 return passphrase
Alex Gaynor03737182020-07-23 20:40:46 -0400898
Paul Kehrer688538c2020-08-03 19:18:15 -0500899 context = Context(SSLv23_METHOD)
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400900 context.set_passwd_cb(passphraseCallback)
901 context.use_privatekey_file(pemFile)
Alex Chan532b79e2017-01-24 15:14:52 +0000902 assert len(calledWith) == 1
903 assert isinstance(calledWith[0][0], int)
904 assert isinstance(calledWith[0][1], int)
905 assert calledWith[0][2] is None
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400906
Alex Chan532b79e2017-01-24 15:14:52 +0000907 def test_passwd_callback_exception(self, tmpfile):
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400908 """
Alex Chan532b79e2017-01-24 15:14:52 +0000909 `Context.use_privatekey_file` propagates any exception raised
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200910 by the passphrase callback.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400911 """
Alex Chan532b79e2017-01-24 15:14:52 +0000912 pemFile = self._write_encrypted_pem(b"monkeys are nice", tmpfile)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200913
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400914 def passphraseCallback(maxlen, verify, extra):
915 raise RuntimeError("Sorry, I am a fail.")
916
Paul Kehrer688538c2020-08-03 19:18:15 -0500917 context = Context(SSLv23_METHOD)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400918 context.set_passwd_cb(passphraseCallback)
Alex Chan532b79e2017-01-24 15:14:52 +0000919 with pytest.raises(RuntimeError):
920 context.use_privatekey_file(pemFile)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400921
Alex Chan532b79e2017-01-24 15:14:52 +0000922 def test_passwd_callback_false(self, tmpfile):
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400923 """
Alex Chan532b79e2017-01-24 15:14:52 +0000924 `Context.use_privatekey_file` raises `OpenSSL.SSL.Error` if the
925 passphrase callback returns a false value.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400926 """
Alex Chan532b79e2017-01-24 15:14:52 +0000927 pemFile = self._write_encrypted_pem(b"monkeys are nice", tmpfile)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200928
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400929 def passphraseCallback(maxlen, verify, extra):
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500930 return b""
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400931
Paul Kehrer688538c2020-08-03 19:18:15 -0500932 context = Context(SSLv23_METHOD)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400933 context.set_passwd_cb(passphraseCallback)
Alex Chan532b79e2017-01-24 15:14:52 +0000934 with pytest.raises(Error):
935 context.use_privatekey_file(pemFile)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400936
Alex Chan532b79e2017-01-24 15:14:52 +0000937 def test_passwd_callback_non_string(self, tmpfile):
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400938 """
Alex Chan532b79e2017-01-24 15:14:52 +0000939 `Context.use_privatekey_file` raises `OpenSSL.SSL.Error` if the
940 passphrase callback returns a true non-string value.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400941 """
Alex Chan532b79e2017-01-24 15:14:52 +0000942 pemFile = self._write_encrypted_pem(b"monkeys are nice", tmpfile)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200943
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400944 def passphraseCallback(maxlen, verify, extra):
945 return 10
946
Paul Kehrer688538c2020-08-03 19:18:15 -0500947 context = Context(SSLv23_METHOD)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400948 context.set_passwd_cb(passphraseCallback)
Alex Chan532b79e2017-01-24 15:14:52 +0000949 # TODO: Surely this is the wrong error?
950 with pytest.raises(ValueError):
951 context.use_privatekey_file(pemFile)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400952
Alex Chan532b79e2017-01-24 15:14:52 +0000953 def test_passwd_callback_too_long(self, tmpfile):
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400954 """
955 If the passphrase returned by the passphrase callback returns a string
956 longer than the indicated maximum length, it is truncated.
957 """
958 # A priori knowledge!
Alex Gaynore7f51982016-09-11 11:48:14 -0400959 passphrase = b"x" * 1024
Alex Chan532b79e2017-01-24 15:14:52 +0000960 pemFile = self._write_encrypted_pem(passphrase, tmpfile)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200961
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400962 def passphraseCallback(maxlen, verify, extra):
963 assert maxlen == 1024
Alex Gaynore7f51982016-09-11 11:48:14 -0400964 return passphrase + b"y"
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400965
Paul Kehrer688538c2020-08-03 19:18:15 -0500966 context = Context(SSLv23_METHOD)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400967 context.set_passwd_cb(passphraseCallback)
968 # This shall succeed because the truncated result is the correct
969 # passphrase.
970 context.use_privatekey_file(pemFile)
971
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400972 def test_set_info_callback(self):
973 """
Alex Chan532b79e2017-01-24 15:14:52 +0000974 `Context.set_info_callback` accepts a callable which will be
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200975 invoked when certain information about an SSL connection is available.
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400976 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500977 (server, client) = socket_pair()
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400978
Paul Kehrer688538c2020-08-03 19:18:15 -0500979 clientSSL = Connection(Context(SSLv23_METHOD), client)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400980 clientSSL.set_connect_state()
981
982 called = []
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200983
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400984 def info(conn, where, ret):
985 called.append((conn, where, ret))
Alex Gaynor03737182020-07-23 20:40:46 -0400986
Paul Kehrer688538c2020-08-03 19:18:15 -0500987 context = Context(SSLv23_METHOD)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400988 context.set_info_callback(info)
Paul Kehrerbeaf9f52020-08-03 17:50:31 -0500989 context.use_certificate(load_certificate(FILETYPE_PEM, root_cert_pem))
990 context.use_privatekey(load_privatekey(FILETYPE_PEM, root_key_pem))
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400991
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400992 serverSSL = Connection(context, server)
993 serverSSL.set_accept_state()
994
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -0500995 handshake(clientSSL, serverSSL)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400996
Jean-Paul Calderone3835e522014-02-02 11:12:30 -0500997 # The callback must always be called with a Connection instance as the
998 # first argument. It would probably be better to split this into
999 # separate tests for client and server side info callbacks so we could
1000 # assert it is called with the right Connection instance. It would
1001 # also be good to assert *something* about `where` and `ret`.
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -05001002 notConnections = [
Alex Gaynor03737182020-07-23 20:40:46 -04001003 conn
1004 for (conn, where, ret) in called
1005 if not isinstance(conn, Connection)
1006 ]
1007 assert (
1008 [] == notConnections
1009 ), "Some info callback arguments were not Connection instances."
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001010
Maximilian Hilsb2bca412020-07-28 16:31:22 +02001011 @pytest.mark.skipif(
1012 not getattr(_lib, "Cryptography_HAS_KEYLOG", None),
1013 reason="SSL_CTX_set_keylog_callback unavailable",
1014 )
1015 def test_set_keylog_callback(self):
1016 """
1017 `Context.set_keylog_callback` accepts a callable which will be
1018 invoked when key material is generated or received.
1019 """
1020 called = []
1021
1022 def keylog(conn, line):
1023 called.append((conn, line))
1024
Paul Kehrer688538c2020-08-03 19:18:15 -05001025 server_context = Context(TLSv1_2_METHOD)
Maximilian Hilsb2bca412020-07-28 16:31:22 +02001026 server_context.set_keylog_callback(keylog)
1027 server_context.use_certificate(
Paul Kehrerbeaf9f52020-08-03 17:50:31 -05001028 load_certificate(FILETYPE_PEM, root_cert_pem)
Maximilian Hilsb2bca412020-07-28 16:31:22 +02001029 )
1030 server_context.use_privatekey(
Paul Kehrerbeaf9f52020-08-03 17:50:31 -05001031 load_privatekey(FILETYPE_PEM, root_key_pem)
Maximilian Hilsb2bca412020-07-28 16:31:22 +02001032 )
1033
Paul Kehrer688538c2020-08-03 19:18:15 -05001034 client_context = Context(SSLv23_METHOD)
Maximilian Hilsb2bca412020-07-28 16:31:22 +02001035
1036 self._handshake_test(server_context, client_context)
1037
1038 assert called
1039 assert all(isinstance(conn, Connection) for conn, line in called)
1040 assert all(b"CLIENT_RANDOM" in line for conn, line in called)
1041
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001042 def _load_verify_locations_test(self, *args):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001043 """
1044 Create a client context which will verify the peer certificate and call
Alex Chan532b79e2017-01-24 15:14:52 +00001045 its `load_verify_locations` method with the given arguments.
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04001046 Then connect it to a server and ensure that the handshake succeeds.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001047 """
Rick Deanb1ccd562009-07-09 23:52:39 -05001048 (server, client) = socket_pair()
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001049
Paul Kehrer688538c2020-08-03 19:18:15 -05001050 clientContext = Context(SSLv23_METHOD)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001051 clientContext.load_verify_locations(*args)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001052 # Require that the server certificate verify properly or the
1053 # connection will fail.
1054 clientContext.set_verify(
1055 VERIFY_PEER,
Alex Gaynor03737182020-07-23 20:40:46 -04001056 lambda conn, cert, errno, depth, preverify_ok: preverify_ok,
1057 )
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001058
1059 clientSSL = Connection(clientContext, client)
1060 clientSSL.set_connect_state()
1061
Paul Kehrer688538c2020-08-03 19:18:15 -05001062 serverContext = Context(SSLv23_METHOD)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001063 serverContext.use_certificate(
Paul Kehrerbeaf9f52020-08-03 17:50:31 -05001064 load_certificate(FILETYPE_PEM, root_cert_pem)
Alex Gaynor03737182020-07-23 20:40:46 -04001065 )
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001066 serverContext.use_privatekey(
Paul Kehrerbeaf9f52020-08-03 17:50:31 -05001067 load_privatekey(FILETYPE_PEM, root_key_pem)
Alex Gaynor03737182020-07-23 20:40:46 -04001068 )
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001069
1070 serverSSL = Connection(serverContext, server)
1071 serverSSL.set_accept_state()
1072
Jean-Paul Calderonef8742032010-09-25 00:00:32 -04001073 # Without load_verify_locations above, the handshake
1074 # will fail:
1075 # Error: [('SSL routines', 'SSL3_GET_SERVER_CERTIFICATE',
1076 # 'certificate verify failed')]
1077 handshake(clientSSL, serverSSL)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001078
1079 cert = clientSSL.get_peer_certificate()
Alex Gaynor03737182020-07-23 20:40:46 -04001080 assert cert.get_subject().CN == "Testing Root CA"
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -04001081
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001082 def _load_verify_cafile(self, cafile):
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001083 """
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001084 Verify that if path to a file containing a certificate is passed to
Alex Chan532b79e2017-01-24 15:14:52 +00001085 `Context.load_verify_locations` for the ``cafile`` parameter, that
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001086 certificate is used as a trust root for the purposes of verifying
Alex Chan532b79e2017-01-24 15:14:52 +00001087 connections created using that `Context`.
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001088 """
Alex Gaynor03737182020-07-23 20:40:46 -04001089 with open(cafile, "w") as fObj:
Paul Kehrerbeaf9f52020-08-03 17:50:31 -05001090 fObj.write(root_cert_pem.decode("ascii"))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001091
1092 self._load_verify_locations_test(cafile)
1093
Alex Chan532b79e2017-01-24 15:14:52 +00001094 def test_load_verify_bytes_cafile(self, tmpfile):
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001095 """
Alex Chan532b79e2017-01-24 15:14:52 +00001096 `Context.load_verify_locations` accepts a file name as a `bytes`
1097 instance and uses the certificates within for verification purposes.
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001098 """
Alex Chan532b79e2017-01-24 15:14:52 +00001099 cafile = tmpfile + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001100 self._load_verify_cafile(cafile)
1101
Alex Chan532b79e2017-01-24 15:14:52 +00001102 def test_load_verify_unicode_cafile(self, tmpfile):
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001103 """
Alex Chan532b79e2017-01-24 15:14:52 +00001104 `Context.load_verify_locations` accepts a file name as a `unicode`
1105 instance and uses the certificates within for verification purposes.
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001106 """
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001107 self._load_verify_cafile(
Alex Chan532b79e2017-01-24 15:14:52 +00001108 tmpfile.decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001109 )
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001110
Alex Chan532b79e2017-01-24 15:14:52 +00001111 def test_load_verify_invalid_file(self, tmpfile):
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -04001112 """
Alex Chan532b79e2017-01-24 15:14:52 +00001113 `Context.load_verify_locations` raises `Error` when passed a
1114 non-existent cafile.
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -04001115 """
Paul Kehrer688538c2020-08-03 19:18:15 -05001116 clientContext = Context(SSLv23_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001117 with pytest.raises(Error):
1118 clientContext.load_verify_locations(tmpfile)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001119
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001120 def _load_verify_directory_locations_capath(self, capath):
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001121 """
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001122 Verify that if path to a directory containing certificate files is
1123 passed to ``Context.load_verify_locations`` for the ``capath``
1124 parameter, those certificates are used as trust roots for the purposes
1125 of verifying connections created using that ``Context``.
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001126 """
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001127 makedirs(capath)
Jean-Paul Calderone24dfb332011-05-04 18:10:26 -04001128 # Hash values computed manually with c_rehash to avoid depending on
1129 # c_rehash in the test suite. One is from OpenSSL 0.9.8, the other
1130 # from OpenSSL 1.0.0.
Alex Gaynor03737182020-07-23 20:40:46 -04001131 for name in [b"c7adac82.0", b"c3705638.0"]:
Jean-Paul Calderone05826732015-04-12 11:38:49 -04001132 cafile = join_bytes_or_unicode(capath, name)
Alex Gaynor03737182020-07-23 20:40:46 -04001133 with open(cafile, "w") as fObj:
Paul Kehrerbeaf9f52020-08-03 17:50:31 -05001134 fObj.write(root_cert_pem.decode("ascii"))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001135
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001136 self._load_verify_locations_test(None, capath)
1137
Alex Chan532b79e2017-01-24 15:14:52 +00001138 def test_load_verify_directory_bytes_capath(self, tmpfile):
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001139 """
Alex Chan532b79e2017-01-24 15:14:52 +00001140 `Context.load_verify_locations` accepts a directory name as a `bytes`
1141 instance and uses the certificates within for verification purposes.
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001142 """
1143 self._load_verify_directory_locations_capath(
Alex Chan532b79e2017-01-24 15:14:52 +00001144 tmpfile + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001145 )
1146
Alex Chan532b79e2017-01-24 15:14:52 +00001147 def test_load_verify_directory_unicode_capath(self, tmpfile):
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001148 """
Alex Chan532b79e2017-01-24 15:14:52 +00001149 `Context.load_verify_locations` accepts a directory name as a `unicode`
1150 instance and uses the certificates within for verification purposes.
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001151 """
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001152 self._load_verify_directory_locations_capath(
Alex Chan532b79e2017-01-24 15:14:52 +00001153 tmpfile.decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001154 )
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001155
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001156 def test_load_verify_locations_wrong_args(self):
1157 """
Alex Chan532b79e2017-01-24 15:14:52 +00001158 `Context.load_verify_locations` raises `TypeError` if with non-`str`
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001159 arguments.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001160 """
Paul Kehrer688538c2020-08-03 19:18:15 -05001161 context = Context(SSLv23_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001162 with pytest.raises(TypeError):
1163 context.load_verify_locations(object())
1164 with pytest.raises(TypeError):
1165 context.load_verify_locations(object(), object())
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001166
Hynek Schlawack734d3022015-09-05 19:19:32 +02001167 @pytest.mark.skipif(
Paul Kehrer55fb3412017-06-29 18:44:08 -05001168 not platform.startswith("linux"),
1169 reason="Loading fallback paths is a linux-specific behavior to "
Alex Gaynor03737182020-07-23 20:40:46 -04001170 "accommodate pyca/cryptography manylinux1 wheels",
Paul Kehrer55fb3412017-06-29 18:44:08 -05001171 )
1172 def test_fallback_default_verify_paths(self, monkeypatch):
1173 """
1174 Test that we load certificates successfully on linux from the fallback
1175 path. To do this we set the _CRYPTOGRAPHY_MANYLINUX1_CA_FILE and
1176 _CRYPTOGRAPHY_MANYLINUX1_CA_DIR vars to be equal to whatever the
1177 current OpenSSL default is and we disable
1178 SSL_CTX_SET_default_verify_paths so that it can't find certs unless
1179 it loads via fallback.
1180 """
Paul Kehrer688538c2020-08-03 19:18:15 -05001181 context = Context(SSLv23_METHOD)
Paul Kehrer55fb3412017-06-29 18:44:08 -05001182 monkeypatch.setattr(
1183 _lib, "SSL_CTX_set_default_verify_paths", lambda x: 1
1184 )
1185 monkeypatch.setattr(
1186 SSL,
1187 "_CRYPTOGRAPHY_MANYLINUX1_CA_FILE",
Alex Gaynor03737182020-07-23 20:40:46 -04001188 _ffi.string(_lib.X509_get_default_cert_file()),
Paul Kehrer55fb3412017-06-29 18:44:08 -05001189 )
1190 monkeypatch.setattr(
1191 SSL,
1192 "_CRYPTOGRAPHY_MANYLINUX1_CA_DIR",
Alex Gaynor03737182020-07-23 20:40:46 -04001193 _ffi.string(_lib.X509_get_default_cert_dir()),
Paul Kehrer55fb3412017-06-29 18:44:08 -05001194 )
1195 context.set_default_verify_paths()
1196 store = context.get_cert_store()
1197 sk_obj = _lib.X509_STORE_get0_objects(store._store)
1198 assert sk_obj != _ffi.NULL
1199 num = _lib.sk_X509_OBJECT_num(sk_obj)
1200 assert num != 0
1201
1202 def test_check_env_vars(self, monkeypatch):
1203 """
1204 Test that we return True/False appropriately if the env vars are set.
1205 """
Paul Kehrer688538c2020-08-03 19:18:15 -05001206 context = Context(SSLv23_METHOD)
Paul Kehrer55fb3412017-06-29 18:44:08 -05001207 dir_var = "CUSTOM_DIR_VAR"
1208 file_var = "CUSTOM_FILE_VAR"
1209 assert context._check_env_vars_set(dir_var, file_var) is False
1210 monkeypatch.setenv(dir_var, "value")
1211 monkeypatch.setenv(file_var, "value")
1212 assert context._check_env_vars_set(dir_var, file_var) is True
1213 assert context._check_env_vars_set(dir_var, file_var) is True
1214
1215 def test_verify_no_fallback_if_env_vars_set(self, monkeypatch):
1216 """
1217 Test that we don't use the fallback path if env vars are set.
1218 """
Paul Kehrer688538c2020-08-03 19:18:15 -05001219 context = Context(SSLv23_METHOD)
Paul Kehrer55fb3412017-06-29 18:44:08 -05001220 monkeypatch.setattr(
1221 _lib, "SSL_CTX_set_default_verify_paths", lambda x: 1
1222 )
Alex Gaynor03737182020-07-23 20:40:46 -04001223 dir_env_var = _ffi.string(_lib.X509_get_default_cert_dir_env()).decode(
1224 "ascii"
1225 )
Paul Kehrer55fb3412017-06-29 18:44:08 -05001226 file_env_var = _ffi.string(
1227 _lib.X509_get_default_cert_file_env()
1228 ).decode("ascii")
1229 monkeypatch.setenv(dir_env_var, "value")
1230 monkeypatch.setenv(file_env_var, "value")
1231 context.set_default_verify_paths()
1232
1233 monkeypatch.setattr(
Alex Gaynor03737182020-07-23 20:40:46 -04001234 context, "_fallback_default_verify_paths", raiser(SystemError)
Paul Kehrer55fb3412017-06-29 18:44:08 -05001235 )
1236 context.set_default_verify_paths()
1237
1238 @pytest.mark.skipif(
Hynek Schlawack734d3022015-09-05 19:19:32 +02001239 platform == "win32",
1240 reason="set_default_verify_paths appears not to work on Windows. "
Alex Gaynor03737182020-07-23 20:40:46 -04001241 "See LP#404343 and LP#404344.",
Hynek Schlawack734d3022015-09-05 19:19:32 +02001242 )
1243 def test_set_default_verify_paths(self):
1244 """
Alex Chan532b79e2017-01-24 15:14:52 +00001245 `Context.set_default_verify_paths` causes the platform-specific CA
1246 certificate locations to be used for verification purposes.
Hynek Schlawack734d3022015-09-05 19:19:32 +02001247 """
1248 # Testing this requires a server with a certificate signed by one
1249 # of the CAs in the platform CA location. Getting one of those
1250 # costs money. Fortunately (or unfortunately, depending on your
1251 # perspective), it's easy to think of a public server on the
1252 # internet which has such a certificate. Connecting to the network
1253 # in a unit test is bad, but it's the only way I can think of to
1254 # really test this. -exarkun
Hynek Schlawackbf887932015-10-21 17:13:47 +02001255 context = Context(SSLv23_METHOD)
Hynek Schlawack734d3022015-09-05 19:19:32 +02001256 context.set_default_verify_paths()
1257 context.set_verify(
1258 VERIFY_PEER,
Alex Gaynor03737182020-07-23 20:40:46 -04001259 lambda conn, cert, errno, depth, preverify_ok: preverify_ok,
1260 )
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001261
David Benjamin1fbe0642019-04-15 17:05:13 -05001262 client = socket_any_family()
Hynek Schlawackbf887932015-10-21 17:13:47 +02001263 client.connect(("encrypted.google.com", 443))
Hynek Schlawack734d3022015-09-05 19:19:32 +02001264 clientSSL = Connection(context, client)
1265 clientSSL.set_connect_state()
Alex Gaynor373926c2018-05-12 07:43:07 -04001266 clientSSL.set_tlsext_host_name(b"encrypted.google.com")
Hynek Schlawack734d3022015-09-05 19:19:32 +02001267 clientSSL.do_handshake()
1268 clientSSL.send(b"GET / HTTP/1.0\r\n\r\n")
Alex Chan532b79e2017-01-24 15:14:52 +00001269 assert clientSSL.recv(1024)
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05001270
Paul Kehrer55fb3412017-06-29 18:44:08 -05001271 def test_fallback_path_is_not_file_or_dir(self):
1272 """
1273 Test that when passed empty arrays or paths that do not exist no
1274 errors are raised.
1275 """
Paul Kehrer688538c2020-08-03 19:18:15 -05001276 context = Context(SSLv23_METHOD)
Paul Kehrer55fb3412017-06-29 18:44:08 -05001277 context._fallback_default_verify_paths([], [])
Alex Gaynor03737182020-07-23 20:40:46 -04001278 context._fallback_default_verify_paths(["/not/a/file"], ["/not/a/dir"])
Paul Kehrer55fb3412017-06-29 18:44:08 -05001279
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001280 def test_add_extra_chain_cert_invalid_cert(self):
1281 """
Alex Chan532b79e2017-01-24 15:14:52 +00001282 `Context.add_extra_chain_cert` raises `TypeError` if called with an
1283 object which is not an instance of `X509`.
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001284 """
Paul Kehrer688538c2020-08-03 19:18:15 -05001285 context = Context(SSLv23_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001286 with pytest.raises(TypeError):
1287 context.add_extra_chain_cert(object())
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001288
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001289 def _handshake_test(self, serverContext, clientContext):
1290 """
1291 Verify that a client and server created with the given contexts can
1292 successfully handshake and communicate.
1293 """
1294 serverSocket, clientSocket = socket_pair()
1295
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001296 server = Connection(serverContext, serverSocket)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001297 server.set_accept_state()
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001298
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001299 client = Connection(clientContext, clientSocket)
1300 client.set_connect_state()
1301
1302 # Make them talk to each other.
Alex Chan532b79e2017-01-24 15:14:52 +00001303 # interact_in_memory(client, server)
1304 for _ in range(3):
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001305 for s in [client, server]:
1306 try:
1307 s.do_handshake()
1308 except WantReadError:
1309 pass
1310
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001311 def test_set_verify_callback_connection_argument(self):
1312 """
1313 The first argument passed to the verify callback is the
Alex Chan532b79e2017-01-24 15:14:52 +00001314 `Connection` instance for which verification is taking place.
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001315 """
Paul Kehrer688538c2020-08-03 19:18:15 -05001316 serverContext = Context(SSLv23_METHOD)
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001317 serverContext.use_privatekey(
Paul Kehrerbeaf9f52020-08-03 17:50:31 -05001318 load_privatekey(FILETYPE_PEM, root_key_pem)
Alex Gaynor03737182020-07-23 20:40:46 -04001319 )
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001320 serverContext.use_certificate(
Paul Kehrerbeaf9f52020-08-03 17:50:31 -05001321 load_certificate(FILETYPE_PEM, root_cert_pem)
Alex Gaynor03737182020-07-23 20:40:46 -04001322 )
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001323 serverConnection = Connection(serverContext, None)
1324
1325 class VerifyCallback(object):
1326 def callback(self, connection, *args):
1327 self.connection = connection
1328 return 1
1329
1330 verify = VerifyCallback()
Paul Kehrer688538c2020-08-03 19:18:15 -05001331 clientContext = Context(SSLv23_METHOD)
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001332 clientContext.set_verify(VERIFY_PEER, verify.callback)
1333 clientConnection = Connection(clientContext, None)
1334 clientConnection.set_connect_state()
1335
Alex Chan532b79e2017-01-24 15:14:52 +00001336 handshake_in_memory(clientConnection, serverConnection)
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001337
Alex Chan532b79e2017-01-24 15:14:52 +00001338 assert verify.connection is clientConnection
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001339
Paul Kehrere7381862017-11-30 20:55:25 +08001340 def test_x509_in_verify_works(self):
1341 """
1342 We had a bug where the X509 cert instantiated in the callback wrapper
1343 didn't __init__ so it was missing objects needed when calling
1344 get_subject. This test sets up a handshake where we call get_subject
1345 on the cert provided to the verify callback.
1346 """
Paul Kehrer688538c2020-08-03 19:18:15 -05001347 serverContext = Context(SSLv23_METHOD)
Paul Kehrere7381862017-11-30 20:55:25 +08001348 serverContext.use_privatekey(
Paul Kehrerbeaf9f52020-08-03 17:50:31 -05001349 load_privatekey(FILETYPE_PEM, root_key_pem)
Alex Gaynor03737182020-07-23 20:40:46 -04001350 )
Paul Kehrere7381862017-11-30 20:55:25 +08001351 serverContext.use_certificate(
Paul Kehrerbeaf9f52020-08-03 17:50:31 -05001352 load_certificate(FILETYPE_PEM, root_cert_pem)
Alex Gaynor03737182020-07-23 20:40:46 -04001353 )
Paul Kehrere7381862017-11-30 20:55:25 +08001354 serverConnection = Connection(serverContext, None)
1355
1356 def verify_cb_get_subject(conn, cert, errnum, depth, ok):
1357 assert cert.get_subject()
1358 return 1
1359
Paul Kehrer688538c2020-08-03 19:18:15 -05001360 clientContext = Context(SSLv23_METHOD)
Paul Kehrere7381862017-11-30 20:55:25 +08001361 clientContext.set_verify(VERIFY_PEER, verify_cb_get_subject)
1362 clientConnection = Connection(clientContext, None)
1363 clientConnection.set_connect_state()
1364
1365 handshake_in_memory(clientConnection, serverConnection)
1366
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001367 def test_set_verify_callback_exception(self):
1368 """
Alex Chan532b79e2017-01-24 15:14:52 +00001369 If the verify callback passed to `Context.set_verify` raises an
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001370 exception, verification fails and the exception is propagated to the
Alex Chan532b79e2017-01-24 15:14:52 +00001371 caller of `Connection.do_handshake`.
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001372 """
Paul Kehrer7d5a3bf2019-01-21 12:24:02 -06001373 serverContext = Context(TLSv1_2_METHOD)
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001374 serverContext.use_privatekey(
Paul Kehrerbeaf9f52020-08-03 17:50:31 -05001375 load_privatekey(FILETYPE_PEM, root_key_pem)
Alex Gaynor03737182020-07-23 20:40:46 -04001376 )
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001377 serverContext.use_certificate(
Paul Kehrerbeaf9f52020-08-03 17:50:31 -05001378 load_certificate(FILETYPE_PEM, root_cert_pem)
Alex Gaynor03737182020-07-23 20:40:46 -04001379 )
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001380
Paul Kehrer7d5a3bf2019-01-21 12:24:02 -06001381 clientContext = Context(TLSv1_2_METHOD)
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001382
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001383 def verify_callback(*args):
1384 raise Exception("silly verify failure")
Alex Gaynor03737182020-07-23 20:40:46 -04001385
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001386 clientContext.set_verify(VERIFY_PEER, verify_callback)
1387
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01001388 with pytest.raises(Exception) as exc:
1389 self._handshake_test(serverContext, clientContext)
1390
Alex Chan532b79e2017-01-24 15:14:52 +00001391 assert "silly verify failure" == str(exc.value)
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001392
Arne Schwabe3562df82020-11-27 19:29:49 +01001393 def test_set_verify_callback_reference(self):
1394 """
1395 If the verify callback passed to `Context.set_verify` is set multiple
1396 times, the pointers to the old call functions should not be dangling
1397 and trigger a segfault.
1398 """
1399 serverContext = Context(TLSv1_2_METHOD)
1400 serverContext.use_privatekey(
1401 load_privatekey(FILETYPE_PEM, root_key_pem)
1402 )
1403 serverContext.use_certificate(
1404 load_certificate(FILETYPE_PEM, root_cert_pem)
1405 )
1406
1407 clientContext = Context(TLSv1_2_METHOD)
1408
1409 clients = []
1410
1411 for i in range(5):
1412
1413 def verify_callback(*args):
1414 return True
1415
1416 serverSocket, clientSocket = socket_pair()
1417 client = Connection(clientContext, clientSocket)
1418
1419 clients.append((serverSocket, client))
1420
1421 clientContext.set_verify(VERIFY_PEER, verify_callback)
1422
1423 gc.collect()
1424
1425 # Make them talk to each other.
1426 for serverSocket, client in clients:
1427 server = Connection(serverContext, serverSocket)
1428 server.set_accept_state()
1429 client.set_connect_state()
1430
1431 for _ in range(5):
1432 for s in [client, server]:
1433 try:
1434 s.do_handshake()
1435 except WantReadError:
1436 pass
1437
Maximilian Hils79b9c792020-08-08 03:08:17 +02001438 @pytest.mark.parametrize("mode", [SSL.VERIFY_PEER, SSL.VERIFY_NONE])
1439 def test_set_verify_default_callback(self, mode):
1440 """
1441 If the verify callback is omitted, the preverify value is used.
1442 """
1443 serverContext = Context(TLSv1_2_METHOD)
1444 serverContext.use_privatekey(
1445 load_privatekey(FILETYPE_PEM, root_key_pem)
1446 )
1447 serverContext.use_certificate(
1448 load_certificate(FILETYPE_PEM, root_cert_pem)
1449 )
1450
1451 clientContext = Context(TLSv1_2_METHOD)
1452 clientContext.set_verify(mode, None)
1453
1454 if mode == SSL.VERIFY_PEER:
1455 with pytest.raises(Exception) as exc:
1456 self._handshake_test(serverContext, clientContext)
1457 assert "certificate verify failed" in str(exc.value)
1458 else:
1459 self._handshake_test(serverContext, clientContext)
1460
Alex Chan532b79e2017-01-24 15:14:52 +00001461 def test_add_extra_chain_cert(self, tmpdir):
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001462 """
Alex Chan532b79e2017-01-24 15:14:52 +00001463 `Context.add_extra_chain_cert` accepts an `X509`
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001464 instance to add to the certificate chain.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001465
Alex Chan532b79e2017-01-24 15:14:52 +00001466 See `_create_certificate_chain` for the details of the
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001467 certificate chain tested.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001468
1469 The chain is tested by starting a server with scert and connecting
1470 to it with a client which trusts cacert and requires verification to
1471 succeed.
1472 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001473 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001474 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1475
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001476 # Dump the CA certificate to a file because that's the only way to load
1477 # it as a trusted CA in the client context.
Alex Gaynor03737182020-07-23 20:40:46 -04001478 for cert, name in [
1479 (cacert, "ca.pem"),
1480 (icert, "i.pem"),
1481 (scert, "s.pem"),
1482 ]:
1483 with tmpdir.join(name).open("w") as f:
1484 f.write(dump_certificate(FILETYPE_PEM, cert).decode("ascii"))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001485
Alex Gaynor03737182020-07-23 20:40:46 -04001486 for key, name in [(cakey, "ca.key"), (ikey, "i.key"), (skey, "s.key")]:
1487 with tmpdir.join(name).open("w") as f:
1488 f.write(dump_privatekey(FILETYPE_PEM, key).decode("ascii"))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001489
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001490 # Create the server context
Paul Kehrer688538c2020-08-03 19:18:15 -05001491 serverContext = Context(SSLv23_METHOD)
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001492 serverContext.use_privatekey(skey)
1493 serverContext.use_certificate(scert)
Jean-Paul Calderone16cf03d2010-09-08 18:53:39 -04001494 # The client already has cacert, we only need to give them icert.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001495 serverContext.add_extra_chain_cert(icert)
1496
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001497 # Create the client
Paul Kehrer688538c2020-08-03 19:18:15 -05001498 clientContext = Context(SSLv23_METHOD)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001499 clientContext.set_verify(
Alex Gaynor03737182020-07-23 20:40:46 -04001500 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb
1501 )
Alex Chan532b79e2017-01-24 15:14:52 +00001502 clientContext.load_verify_locations(str(tmpdir.join("ca.pem")))
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001503
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001504 # Try it out.
1505 self._handshake_test(serverContext, clientContext)
1506
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001507 def _use_certificate_chain_file_test(self, certdir):
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001508 """
Alex Chan532b79e2017-01-24 15:14:52 +00001509 Verify that `Context.use_certificate_chain_file` reads a
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001510 certificate chain from a specified file.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001511
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001512 The chain is tested by starting a server with scert and connecting to
1513 it with a client which trusts cacert and requires verification to
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001514 succeed.
1515 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001516 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001517 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1518
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001519 makedirs(certdir)
1520
Jean-Paul Calderone05826732015-04-12 11:38:49 -04001521 chainFile = join_bytes_or_unicode(certdir, "chain.pem")
1522 caFile = join_bytes_or_unicode(certdir, "ca.pem")
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001523
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001524 # Write out the chain file.
Alex Gaynor03737182020-07-23 20:40:46 -04001525 with open(chainFile, "wb") as fObj:
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001526 # Most specific to least general.
1527 fObj.write(dump_certificate(FILETYPE_PEM, scert))
1528 fObj.write(dump_certificate(FILETYPE_PEM, icert))
1529 fObj.write(dump_certificate(FILETYPE_PEM, cacert))
1530
Alex Gaynor03737182020-07-23 20:40:46 -04001531 with open(caFile, "w") as fObj:
1532 fObj.write(dump_certificate(FILETYPE_PEM, cacert).decode("ascii"))
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001533
Paul Kehrer688538c2020-08-03 19:18:15 -05001534 serverContext = Context(SSLv23_METHOD)
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001535 serverContext.use_certificate_chain_file(chainFile)
1536 serverContext.use_privatekey(skey)
1537
Paul Kehrer688538c2020-08-03 19:18:15 -05001538 clientContext = Context(SSLv23_METHOD)
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001539 clientContext.set_verify(
Alex Gaynor03737182020-07-23 20:40:46 -04001540 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb
1541 )
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001542 clientContext.load_verify_locations(caFile)
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001543
1544 self._handshake_test(serverContext, clientContext)
1545
Alex Chan532b79e2017-01-24 15:14:52 +00001546 def test_use_certificate_chain_file_bytes(self, tmpfile):
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001547 """
1548 ``Context.use_certificate_chain_file`` accepts the name of a file (as
1549 an instance of ``bytes``) to specify additional certificates to use to
1550 construct and verify a trust chain.
1551 """
1552 self._use_certificate_chain_file_test(
Alex Chan532b79e2017-01-24 15:14:52 +00001553 tmpfile + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001554 )
1555
Alex Chan532b79e2017-01-24 15:14:52 +00001556 def test_use_certificate_chain_file_unicode(self, tmpfile):
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001557 """
1558 ``Context.use_certificate_chain_file`` accepts the name of a file (as
1559 an instance of ``unicode``) to specify additional certificates to use
1560 to construct and verify a trust chain.
1561 """
1562 self._use_certificate_chain_file_test(
Alex Chan532b79e2017-01-24 15:14:52 +00001563 tmpfile.decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001564 )
1565
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001566 def test_use_certificate_chain_file_wrong_args(self):
1567 """
Alex Chan532b79e2017-01-24 15:14:52 +00001568 `Context.use_certificate_chain_file` raises `TypeError` if passed a
1569 non-byte string single argument.
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001570 """
Paul Kehrer688538c2020-08-03 19:18:15 -05001571 context = Context(SSLv23_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001572 with pytest.raises(TypeError):
1573 context.use_certificate_chain_file(object())
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001574
Alex Chan532b79e2017-01-24 15:14:52 +00001575 def test_use_certificate_chain_file_missing_file(self, tmpfile):
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001576 """
Alex Chan532b79e2017-01-24 15:14:52 +00001577 `Context.use_certificate_chain_file` raises `OpenSSL.SSL.Error` when
1578 passed a bad chain file name (for example, the name of a file which
1579 does not exist).
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001580 """
Paul Kehrer688538c2020-08-03 19:18:15 -05001581 context = Context(SSLv23_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001582 with pytest.raises(Error):
1583 context.use_certificate_chain_file(tmpfile)
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001584
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001585 def test_set_verify_mode(self):
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001586 """
Alex Chan532b79e2017-01-24 15:14:52 +00001587 `Context.get_verify_mode` returns the verify mode flags previously
1588 passed to `Context.set_verify`.
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001589 """
Paul Kehrer688538c2020-08-03 19:18:15 -05001590 context = Context(SSLv23_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001591 assert context.get_verify_mode() == 0
Maximilian Hils79b9c792020-08-08 03:08:17 +02001592 context.set_verify(VERIFY_PEER | VERIFY_CLIENT_ONCE)
Alex Chan532b79e2017-01-24 15:14:52 +00001593 assert context.get_verify_mode() == (VERIFY_PEER | VERIFY_CLIENT_ONCE)
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001594
Alex Gaynor03737182020-07-23 20:40:46 -04001595 @pytest.mark.parametrize("mode", [None, 1.0, object(), "mode"])
Alex Chanfb078d82017-04-20 11:16:15 +01001596 def test_set_verify_wrong_mode_arg(self, mode):
1597 """
1598 `Context.set_verify` raises `TypeError` if the first argument is
1599 not an integer.
1600 """
Paul Kehrer688538c2020-08-03 19:18:15 -05001601 context = Context(SSLv23_METHOD)
Alex Chanfb078d82017-04-20 11:16:15 +01001602 with pytest.raises(TypeError):
Maximilian Hils79b9c792020-08-08 03:08:17 +02001603 context.set_verify(mode=mode)
Alex Chanfb078d82017-04-20 11:16:15 +01001604
Maximilian Hils79b9c792020-08-08 03:08:17 +02001605 @pytest.mark.parametrize("callback", [1.0, "mode", ("foo", "bar")])
Alex Chanfb078d82017-04-20 11:16:15 +01001606 def test_set_verify_wrong_callable_arg(self, callback):
1607 """
Alex Gaynor40bc0f12018-05-14 14:06:16 -04001608 `Context.set_verify` raises `TypeError` if the second argument
Alex Chanfb078d82017-04-20 11:16:15 +01001609 is not callable.
1610 """
Paul Kehrer688538c2020-08-03 19:18:15 -05001611 context = Context(SSLv23_METHOD)
Alex Chanfb078d82017-04-20 11:16:15 +01001612 with pytest.raises(TypeError):
1613 context.set_verify(mode=VERIFY_PEER, callback=callback)
1614
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001615 def test_load_tmp_dh_wrong_args(self):
1616 """
Alex Chan532b79e2017-01-24 15:14:52 +00001617 `Context.load_tmp_dh` raises `TypeError` if called with a
1618 non-`str` argument.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001619 """
Paul Kehrer688538c2020-08-03 19:18:15 -05001620 context = Context(SSLv23_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001621 with pytest.raises(TypeError):
1622 context.load_tmp_dh(object())
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001623
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001624 def test_load_tmp_dh_missing_file(self):
1625 """
Alex Chan532b79e2017-01-24 15:14:52 +00001626 `Context.load_tmp_dh` raises `OpenSSL.SSL.Error` if the
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001627 specified file does not exist.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001628 """
Paul Kehrer688538c2020-08-03 19:18:15 -05001629 context = Context(SSLv23_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001630 with pytest.raises(Error):
1631 context.load_tmp_dh(b"hello")
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001632
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001633 def _load_tmp_dh_test(self, dhfilename):
Jean-Paul Calderone4e0c43f2015-04-13 10:15:17 -04001634 """
1635 Verify that calling ``Context.load_tmp_dh`` with the given filename
1636 does not raise an exception.
1637 """
Paul Kehrer688538c2020-08-03 19:18:15 -05001638 context = Context(SSLv23_METHOD)
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001639 with open(dhfilename, "w") as dhfile:
1640 dhfile.write(dhparam)
1641
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001642 context.load_tmp_dh(dhfilename)
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001643
Alex Chan532b79e2017-01-24 15:14:52 +00001644 def test_load_tmp_dh_bytes(self, tmpfile):
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001645 """
Alex Chan532b79e2017-01-24 15:14:52 +00001646 `Context.load_tmp_dh` loads Diffie-Hellman parameters from the
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001647 specified file (given as ``bytes``).
1648 """
1649 self._load_tmp_dh_test(
Alex Chan532b79e2017-01-24 15:14:52 +00001650 tmpfile + NON_ASCII.encode(getfilesystemencoding()),
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001651 )
1652
Alex Chan532b79e2017-01-24 15:14:52 +00001653 def test_load_tmp_dh_unicode(self, tmpfile):
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001654 """
Alex Chan532b79e2017-01-24 15:14:52 +00001655 `Context.load_tmp_dh` loads Diffie-Hellman parameters from the
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001656 specified file (given as ``unicode``).
1657 """
1658 self._load_tmp_dh_test(
Alex Chan532b79e2017-01-24 15:14:52 +00001659 tmpfile.decode(getfilesystemencoding()) + NON_ASCII,
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001660 )
1661
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001662 def test_set_tmp_ecdh(self):
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001663 """
Alex Chan532b79e2017-01-24 15:14:52 +00001664 `Context.set_tmp_ecdh` sets the elliptic curve for Diffie-Hellman to
1665 the specified curve.
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001666 """
Paul Kehrer688538c2020-08-03 19:18:15 -05001667 context = Context(SSLv23_METHOD)
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001668 for curve in get_elliptic_curves():
Hynek Schlawacka07fa8c2015-10-17 10:15:28 +02001669 if curve.name.startswith(u"Oakley-"):
Hynek Schlawack7408aff2015-10-17 09:51:16 +02001670 # Setting Oakley-EC2N-4 and Oakley-EC2N-3 adds
1671 # ('bignum routines', 'BN_mod_inverse', 'no inverse') to the
1672 # error queue on OpenSSL 1.0.2.
1673 continue
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001674 # The only easily "assertable" thing is that it does not raise an
1675 # exception.
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001676 context.set_tmp_ecdh(curve)
Alex Gaynor12dc0842014-01-17 12:51:31 -06001677
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001678 def test_set_session_cache_mode_wrong_args(self):
1679 """
Alex Chan532b79e2017-01-24 15:14:52 +00001680 `Context.set_session_cache_mode` raises `TypeError` if called with
1681 a non-integer argument.
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001682 called with other than one integer argument.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001683 """
Paul Kehrer688538c2020-08-03 19:18:15 -05001684 context = Context(SSLv23_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001685 with pytest.raises(TypeError):
1686 context.set_session_cache_mode(object())
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001687
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001688 def test_session_cache_mode(self):
1689 """
Alex Chan532b79e2017-01-24 15:14:52 +00001690 `Context.set_session_cache_mode` specifies how sessions are cached.
1691 The setting can be retrieved via `Context.get_session_cache_mode`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001692 """
Paul Kehrer688538c2020-08-03 19:18:15 -05001693 context = Context(SSLv23_METHOD)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001694 context.set_session_cache_mode(SESS_CACHE_OFF)
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001695 off = context.set_session_cache_mode(SESS_CACHE_BOTH)
Alex Chan532b79e2017-01-24 15:14:52 +00001696 assert SESS_CACHE_OFF == off
1697 assert SESS_CACHE_BOTH == context.get_session_cache_mode()
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001698
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001699 def test_get_cert_store(self):
1700 """
Alex Chan532b79e2017-01-24 15:14:52 +00001701 `Context.get_cert_store` returns a `X509Store` instance.
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001702 """
Paul Kehrer688538c2020-08-03 19:18:15 -05001703 context = Context(SSLv23_METHOD)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001704 store = context.get_cert_store()
Alex Chan532b79e2017-01-24 15:14:52 +00001705 assert isinstance(store, X509Store)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001706
Jeremy Lainé02261ad2018-05-16 18:33:25 +02001707 def test_set_tlsext_use_srtp_not_bytes(self):
1708 """
1709 `Context.set_tlsext_use_srtp' enables negotiating SRTP keying material.
1710
1711 It raises a TypeError if the list of profiles is not a byte string.
1712 """
Paul Kehrer688538c2020-08-03 19:18:15 -05001713 context = Context(SSLv23_METHOD)
Jeremy Lainé02261ad2018-05-16 18:33:25 +02001714 with pytest.raises(TypeError):
Alex Gaynor03737182020-07-23 20:40:46 -04001715 context.set_tlsext_use_srtp(text_type("SRTP_AES128_CM_SHA1_80"))
Jeremy Lainé02261ad2018-05-16 18:33:25 +02001716
1717 def test_set_tlsext_use_srtp_invalid_profile(self):
1718 """
1719 `Context.set_tlsext_use_srtp' enables negotiating SRTP keying material.
1720
1721 It raises an Error if the call to OpenSSL fails.
1722 """
Paul Kehrer688538c2020-08-03 19:18:15 -05001723 context = Context(SSLv23_METHOD)
Jeremy Lainé02261ad2018-05-16 18:33:25 +02001724 with pytest.raises(Error):
Alex Gaynor03737182020-07-23 20:40:46 -04001725 context.set_tlsext_use_srtp(b"SRTP_BOGUS")
Jeremy Lainé02261ad2018-05-16 18:33:25 +02001726
1727 def test_set_tlsext_use_srtp_valid(self):
1728 """
1729 `Context.set_tlsext_use_srtp' enables negotiating SRTP keying material.
1730
1731 It does not return anything.
1732 """
Paul Kehrer688538c2020-08-03 19:18:15 -05001733 context = Context(SSLv23_METHOD)
Alex Gaynor03737182020-07-23 20:40:46 -04001734 assert context.set_tlsext_use_srtp(b"SRTP_AES128_CM_SHA1_80") is None
Jeremy Lainé02261ad2018-05-16 18:33:25 +02001735
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001736
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001737class TestServerNameCallback(object):
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001738 """
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001739 Tests for `Context.set_tlsext_servername_callback` and its
1740 interaction with `Connection`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001741 """
Alex Gaynor03737182020-07-23 20:40:46 -04001742
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001743 def test_old_callback_forgotten(self):
1744 """
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001745 If `Context.set_tlsext_servername_callback` is used to specify
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001746 a new callback, the one it replaces is dereferenced.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001747 """
Alex Gaynor03737182020-07-23 20:40:46 -04001748
Alex Chanfb078d82017-04-20 11:16:15 +01001749 def callback(connection): # pragma: no cover
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001750 pass
1751
Alex Chanfb078d82017-04-20 11:16:15 +01001752 def replacement(connection): # pragma: no cover
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001753 pass
1754
Paul Kehrer688538c2020-08-03 19:18:15 -05001755 context = Context(SSLv23_METHOD)
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001756 context.set_tlsext_servername_callback(callback)
1757
1758 tracker = ref(callback)
1759 del callback
1760
1761 context.set_tlsext_servername_callback(replacement)
Jean-Paul Calderoned4033eb2014-01-11 08:21:46 -05001762
1763 # One run of the garbage collector happens to work on CPython. PyPy
1764 # doesn't collect the underlying object until a second run for whatever
1765 # reason. That's fine, it still demonstrates our code has properly
1766 # dropped the reference.
1767 collect()
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001768 collect()
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001769
1770 callback = tracker()
1771 if callback is not None:
1772 referrers = get_referrers(callback)
Alex Chanfb078d82017-04-20 11:16:15 +01001773 if len(referrers) > 1: # pragma: nocover
1774 pytest.fail("Some references remain: %r" % (referrers,))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001775
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001776 def test_no_servername(self):
1777 """
1778 When a client specifies no server name, the callback passed to
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001779 `Context.set_tlsext_servername_callback` is invoked and the
1780 result of `Connection.get_servername` is `None`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001781 """
1782 args = []
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001783
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001784 def servername(conn):
1785 args.append((conn, conn.get_servername()))
Alex Gaynor03737182020-07-23 20:40:46 -04001786
Paul Kehrer688538c2020-08-03 19:18:15 -05001787 context = Context(SSLv23_METHOD)
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001788 context.set_tlsext_servername_callback(servername)
1789
1790 # Lose our reference to it. The Context is responsible for keeping it
1791 # alive now.
1792 del servername
1793 collect()
1794
1795 # Necessary to actually accept the connection
1796 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001797 context.use_certificate(
Alex Gaynor03737182020-07-23 20:40:46 -04001798 load_certificate(FILETYPE_PEM, server_cert_pem)
1799 )
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001800
1801 # Do a little connection to trigger the logic
1802 server = Connection(context, None)
1803 server.set_accept_state()
1804
Paul Kehrer688538c2020-08-03 19:18:15 -05001805 client = Connection(Context(SSLv23_METHOD), None)
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001806 client.set_connect_state()
1807
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001808 interact_in_memory(server, client)
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001809
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001810 assert args == [(server, None)]
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001811
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001812 def test_servername(self):
1813 """
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001814 When a client specifies a server name in its hello message, the
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001815 callback passed to `Contexts.set_tlsext_servername_callback` is
1816 invoked and the result of `Connection.get_servername` is that
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001817 server name.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001818 """
1819 args = []
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001820
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001821 def servername(conn):
1822 args.append((conn, conn.get_servername()))
Alex Gaynor03737182020-07-23 20:40:46 -04001823
Paul Kehrer688538c2020-08-03 19:18:15 -05001824 context = Context(SSLv23_METHOD)
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001825 context.set_tlsext_servername_callback(servername)
1826
1827 # Necessary to actually accept the connection
1828 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001829 context.use_certificate(
Alex Gaynor03737182020-07-23 20:40:46 -04001830 load_certificate(FILETYPE_PEM, server_cert_pem)
1831 )
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001832
1833 # Do a little connection to trigger the logic
1834 server = Connection(context, None)
1835 server.set_accept_state()
1836
Paul Kehrer688538c2020-08-03 19:18:15 -05001837 client = Connection(Context(SSLv23_METHOD), None)
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001838 client.set_connect_state()
Alex Gaynore7f51982016-09-11 11:48:14 -04001839 client.set_tlsext_host_name(b"foo1.example.com")
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001840
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001841 interact_in_memory(server, client)
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001842
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001843 assert args == [(server, b"foo1.example.com")]
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001844
1845
Alex Chanec1e32d2016-11-10 14:11:45 +00001846class TestApplicationLayerProtoNegotiation(object):
Cory Benfield12eae892014-06-07 15:42:56 +01001847 """
1848 Tests for ALPN in PyOpenSSL.
1849 """
Alex Gaynor03737182020-07-23 20:40:46 -04001850
Alex Gaynor77debda2020-04-07 13:40:59 -04001851 def test_alpn_success(self):
1852 """
1853 Clients and servers that agree on the negotiated ALPN protocol can
1854 correct establish a connection, and the agreed protocol is reported
1855 by the connections.
1856 """
1857 select_args = []
Cory Benfield12eae892014-06-07 15:42:56 +01001858
Alex Gaynor77debda2020-04-07 13:40:59 -04001859 def select(conn, options):
1860 select_args.append((conn, options))
Alex Gaynor03737182020-07-23 20:40:46 -04001861 return b"spdy/2"
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001862
Paul Kehrer688538c2020-08-03 19:18:15 -05001863 client_context = Context(SSLv23_METHOD)
Alex Gaynor03737182020-07-23 20:40:46 -04001864 client_context.set_alpn_protos([b"http/1.1", b"spdy/2"])
Cory Benfield12eae892014-06-07 15:42:56 +01001865
Paul Kehrer688538c2020-08-03 19:18:15 -05001866 server_context = Context(SSLv23_METHOD)
Alex Gaynor77debda2020-04-07 13:40:59 -04001867 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01001868
Alex Gaynor77debda2020-04-07 13:40:59 -04001869 # Necessary to actually accept the connection
1870 server_context.use_privatekey(
Alex Gaynor03737182020-07-23 20:40:46 -04001871 load_privatekey(FILETYPE_PEM, server_key_pem)
1872 )
Alex Gaynor77debda2020-04-07 13:40:59 -04001873 server_context.use_certificate(
Alex Gaynor03737182020-07-23 20:40:46 -04001874 load_certificate(FILETYPE_PEM, server_cert_pem)
1875 )
Cory Benfield12eae892014-06-07 15:42:56 +01001876
Alex Gaynor77debda2020-04-07 13:40:59 -04001877 # Do a little connection to trigger the logic
1878 server = Connection(server_context, None)
1879 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001880
Alex Gaynor77debda2020-04-07 13:40:59 -04001881 client = Connection(client_context, None)
1882 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001883
Alex Gaynor77debda2020-04-07 13:40:59 -04001884 interact_in_memory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001885
Alex Gaynor03737182020-07-23 20:40:46 -04001886 assert select_args == [(server, [b"http/1.1", b"spdy/2"])]
Alex Gaynor77debda2020-04-07 13:40:59 -04001887
Alex Gaynor03737182020-07-23 20:40:46 -04001888 assert server.get_alpn_proto_negotiated() == b"spdy/2"
1889 assert client.get_alpn_proto_negotiated() == b"spdy/2"
Alex Gaynor77debda2020-04-07 13:40:59 -04001890
1891 def test_alpn_set_on_connection(self):
1892 """
1893 The same as test_alpn_success, but setting the ALPN protocols on
1894 the connection rather than the context.
1895 """
1896 select_args = []
1897
1898 def select(conn, options):
1899 select_args.append((conn, options))
Alex Gaynor03737182020-07-23 20:40:46 -04001900 return b"spdy/2"
Alex Gaynor77debda2020-04-07 13:40:59 -04001901
1902 # Setup the client context but don't set any ALPN protocols.
Paul Kehrer688538c2020-08-03 19:18:15 -05001903 client_context = Context(SSLv23_METHOD)
Alex Gaynor77debda2020-04-07 13:40:59 -04001904
Paul Kehrer688538c2020-08-03 19:18:15 -05001905 server_context = Context(SSLv23_METHOD)
Alex Gaynor77debda2020-04-07 13:40:59 -04001906 server_context.set_alpn_select_callback(select)
1907
1908 # Necessary to actually accept the connection
1909 server_context.use_privatekey(
Alex Gaynor03737182020-07-23 20:40:46 -04001910 load_privatekey(FILETYPE_PEM, server_key_pem)
1911 )
Alex Gaynor77debda2020-04-07 13:40:59 -04001912 server_context.use_certificate(
Alex Gaynor03737182020-07-23 20:40:46 -04001913 load_certificate(FILETYPE_PEM, server_cert_pem)
1914 )
Alex Gaynor77debda2020-04-07 13:40:59 -04001915
1916 # Do a little connection to trigger the logic
1917 server = Connection(server_context, None)
1918 server.set_accept_state()
1919
1920 # Set the ALPN protocols on the client connection.
1921 client = Connection(client_context, None)
Alex Gaynor03737182020-07-23 20:40:46 -04001922 client.set_alpn_protos([b"http/1.1", b"spdy/2"])
Alex Gaynor77debda2020-04-07 13:40:59 -04001923 client.set_connect_state()
1924
1925 interact_in_memory(server, client)
1926
Alex Gaynor03737182020-07-23 20:40:46 -04001927 assert select_args == [(server, [b"http/1.1", b"spdy/2"])]
Alex Gaynor77debda2020-04-07 13:40:59 -04001928
Alex Gaynor03737182020-07-23 20:40:46 -04001929 assert server.get_alpn_proto_negotiated() == b"spdy/2"
1930 assert client.get_alpn_proto_negotiated() == b"spdy/2"
Alex Gaynor77debda2020-04-07 13:40:59 -04001931
1932 def test_alpn_server_fail(self):
1933 """
1934 When clients and servers cannot agree on what protocol to use next
1935 the TLS connection does not get established.
1936 """
1937 select_args = []
1938
1939 def select(conn, options):
1940 select_args.append((conn, options))
Alex Gaynor03737182020-07-23 20:40:46 -04001941 return b""
Alex Gaynor77debda2020-04-07 13:40:59 -04001942
Paul Kehrer688538c2020-08-03 19:18:15 -05001943 client_context = Context(SSLv23_METHOD)
Alex Gaynor03737182020-07-23 20:40:46 -04001944 client_context.set_alpn_protos([b"http/1.1", b"spdy/2"])
Alex Gaynor77debda2020-04-07 13:40:59 -04001945
Paul Kehrer688538c2020-08-03 19:18:15 -05001946 server_context = Context(SSLv23_METHOD)
Alex Gaynor77debda2020-04-07 13:40:59 -04001947 server_context.set_alpn_select_callback(select)
1948
1949 # Necessary to actually accept the connection
1950 server_context.use_privatekey(
Alex Gaynor03737182020-07-23 20:40:46 -04001951 load_privatekey(FILETYPE_PEM, server_key_pem)
1952 )
Alex Gaynor77debda2020-04-07 13:40:59 -04001953 server_context.use_certificate(
Alex Gaynor03737182020-07-23 20:40:46 -04001954 load_certificate(FILETYPE_PEM, server_cert_pem)
1955 )
Alex Gaynor77debda2020-04-07 13:40:59 -04001956
1957 # Do a little connection to trigger the logic
1958 server = Connection(server_context, None)
1959 server.set_accept_state()
1960
1961 client = Connection(client_context, None)
1962 client.set_connect_state()
1963
1964 # If the client doesn't return anything, the connection will fail.
1965 with pytest.raises(Error):
Alex Chanec1e32d2016-11-10 14:11:45 +00001966 interact_in_memory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001967
Alex Gaynor03737182020-07-23 20:40:46 -04001968 assert select_args == [(server, [b"http/1.1", b"spdy/2"])]
Cory Benfielde46fa842015-04-13 16:50:49 -04001969
Alex Gaynor77debda2020-04-07 13:40:59 -04001970 def test_alpn_no_server_overlap(self):
1971 """
1972 A server can allow a TLS handshake to complete without
1973 agreeing to an application protocol by returning
1974 ``NO_OVERLAPPING_PROTOCOLS``.
1975 """
1976 refusal_args = []
Cory Benfield12eae892014-06-07 15:42:56 +01001977
Alex Gaynor77debda2020-04-07 13:40:59 -04001978 def refusal(conn, options):
1979 refusal_args.append((conn, options))
1980 return NO_OVERLAPPING_PROTOCOLS
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001981
Alex Gaynor77debda2020-04-07 13:40:59 -04001982 client_context = Context(SSLv23_METHOD)
Alex Gaynor03737182020-07-23 20:40:46 -04001983 client_context.set_alpn_protos([b"http/1.1", b"spdy/2"])
Cory Benfield12eae892014-06-07 15:42:56 +01001984
Alex Gaynor77debda2020-04-07 13:40:59 -04001985 server_context = Context(SSLv23_METHOD)
1986 server_context.set_alpn_select_callback(refusal)
Cory Benfield12eae892014-06-07 15:42:56 +01001987
Alex Gaynor77debda2020-04-07 13:40:59 -04001988 # Necessary to actually accept the connection
1989 server_context.use_privatekey(
Alex Gaynor03737182020-07-23 20:40:46 -04001990 load_privatekey(FILETYPE_PEM, server_key_pem)
1991 )
Alex Gaynor77debda2020-04-07 13:40:59 -04001992 server_context.use_certificate(
Alex Gaynor03737182020-07-23 20:40:46 -04001993 load_certificate(FILETYPE_PEM, server_cert_pem)
1994 )
Cory Benfield12eae892014-06-07 15:42:56 +01001995
Alex Gaynor77debda2020-04-07 13:40:59 -04001996 # Do a little connection to trigger the logic
1997 server = Connection(server_context, None)
1998 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001999
Alex Gaynor77debda2020-04-07 13:40:59 -04002000 client = Connection(client_context, None)
2001 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01002002
Alex Gaynor77debda2020-04-07 13:40:59 -04002003 # Do the dance.
2004 interact_in_memory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01002005
Alex Gaynor03737182020-07-23 20:40:46 -04002006 assert refusal_args == [(server, [b"http/1.1", b"spdy/2"])]
Alex Gaynor77debda2020-04-07 13:40:59 -04002007
Alex Gaynor03737182020-07-23 20:40:46 -04002008 assert client.get_alpn_proto_negotiated() == b""
Alex Gaynor77debda2020-04-07 13:40:59 -04002009
2010 def test_alpn_select_cb_returns_invalid_value(self):
2011 """
2012 If the ALPN selection callback returns anything other than
2013 a bytestring or ``NO_OVERLAPPING_PROTOCOLS``, a
2014 :py:exc:`TypeError` is raised.
2015 """
2016 invalid_cb_args = []
2017
2018 def invalid_cb(conn, options):
2019 invalid_cb_args.append((conn, options))
2020 return u"can't return unicode"
2021
2022 client_context = Context(SSLv23_METHOD)
Alex Gaynor03737182020-07-23 20:40:46 -04002023 client_context.set_alpn_protos([b"http/1.1", b"spdy/2"])
Alex Gaynor77debda2020-04-07 13:40:59 -04002024
2025 server_context = Context(SSLv23_METHOD)
2026 server_context.set_alpn_select_callback(invalid_cb)
2027
2028 # Necessary to actually accept the connection
2029 server_context.use_privatekey(
Alex Gaynor03737182020-07-23 20:40:46 -04002030 load_privatekey(FILETYPE_PEM, server_key_pem)
2031 )
Alex Gaynor77debda2020-04-07 13:40:59 -04002032 server_context.use_certificate(
Alex Gaynor03737182020-07-23 20:40:46 -04002033 load_certificate(FILETYPE_PEM, server_cert_pem)
2034 )
Alex Gaynor77debda2020-04-07 13:40:59 -04002035
2036 # Do a little connection to trigger the logic
2037 server = Connection(server_context, None)
2038 server.set_accept_state()
2039
2040 client = Connection(client_context, None)
2041 client.set_connect_state()
2042
2043 # Do the dance.
2044 with pytest.raises(TypeError):
Alex Chanec1e32d2016-11-10 14:11:45 +00002045 interact_in_memory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01002046
Alex Gaynor03737182020-07-23 20:40:46 -04002047 assert invalid_cb_args == [(server, [b"http/1.1", b"spdy/2"])]
Cory Benfield12eae892014-06-07 15:42:56 +01002048
Alex Gaynor03737182020-07-23 20:40:46 -04002049 assert client.get_alpn_proto_negotiated() == b""
Cory Benfield12eae892014-06-07 15:42:56 +01002050
Alex Gaynor77debda2020-04-07 13:40:59 -04002051 def test_alpn_no_server(self):
2052 """
2053 When clients and servers cannot agree on what protocol to use next
2054 because the server doesn't offer ALPN, no protocol is negotiated.
2055 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002056 client_context = Context(SSLv23_METHOD)
Alex Gaynor03737182020-07-23 20:40:46 -04002057 client_context.set_alpn_protos([b"http/1.1", b"spdy/2"])
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002058
Paul Kehrer688538c2020-08-03 19:18:15 -05002059 server_context = Context(SSLv23_METHOD)
Cory Benfield12eae892014-06-07 15:42:56 +01002060
Alex Gaynor77debda2020-04-07 13:40:59 -04002061 # Necessary to actually accept the connection
2062 server_context.use_privatekey(
Alex Gaynor03737182020-07-23 20:40:46 -04002063 load_privatekey(FILETYPE_PEM, server_key_pem)
2064 )
Alex Gaynor77debda2020-04-07 13:40:59 -04002065 server_context.use_certificate(
Alex Gaynor03737182020-07-23 20:40:46 -04002066 load_certificate(FILETYPE_PEM, server_cert_pem)
2067 )
Cory Benfield12eae892014-06-07 15:42:56 +01002068
Alex Gaynor77debda2020-04-07 13:40:59 -04002069 # Do a little connection to trigger the logic
2070 server = Connection(server_context, None)
2071 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01002072
Alex Gaynor77debda2020-04-07 13:40:59 -04002073 client = Connection(client_context, None)
2074 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01002075
Alex Gaynor77debda2020-04-07 13:40:59 -04002076 # Do the dance.
2077 interact_in_memory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01002078
Alex Gaynor03737182020-07-23 20:40:46 -04002079 assert client.get_alpn_proto_negotiated() == b""
Cory Benfield12eae892014-06-07 15:42:56 +01002080
Alex Gaynor77debda2020-04-07 13:40:59 -04002081 def test_alpn_callback_exception(self):
2082 """
2083 We can handle exceptions in the ALPN select callback.
2084 """
2085 select_args = []
Cory Benfield12eae892014-06-07 15:42:56 +01002086
Alex Gaynor77debda2020-04-07 13:40:59 -04002087 def select(conn, options):
2088 select_args.append((conn, options))
2089 raise TypeError()
Cory Benfield12eae892014-06-07 15:42:56 +01002090
Paul Kehrer688538c2020-08-03 19:18:15 -05002091 client_context = Context(SSLv23_METHOD)
Alex Gaynor03737182020-07-23 20:40:46 -04002092 client_context.set_alpn_protos([b"http/1.1", b"spdy/2"])
Mark Williams5d890a02019-11-17 19:56:26 -08002093
Paul Kehrer688538c2020-08-03 19:18:15 -05002094 server_context = Context(SSLv23_METHOD)
Alex Gaynor77debda2020-04-07 13:40:59 -04002095 server_context.set_alpn_select_callback(select)
Mark Williams5d890a02019-11-17 19:56:26 -08002096
Alex Gaynor77debda2020-04-07 13:40:59 -04002097 # Necessary to actually accept the connection
2098 server_context.use_privatekey(
Alex Gaynor03737182020-07-23 20:40:46 -04002099 load_privatekey(FILETYPE_PEM, server_key_pem)
2100 )
Alex Gaynor77debda2020-04-07 13:40:59 -04002101 server_context.use_certificate(
Alex Gaynor03737182020-07-23 20:40:46 -04002102 load_certificate(FILETYPE_PEM, server_cert_pem)
2103 )
Mark Williams5d890a02019-11-17 19:56:26 -08002104
Alex Gaynor77debda2020-04-07 13:40:59 -04002105 # Do a little connection to trigger the logic
2106 server = Connection(server_context, None)
2107 server.set_accept_state()
Mark Williams5d890a02019-11-17 19:56:26 -08002108
Alex Gaynor77debda2020-04-07 13:40:59 -04002109 client = Connection(client_context, None)
2110 client.set_connect_state()
Mark Williams5d890a02019-11-17 19:56:26 -08002111
Alex Gaynor77debda2020-04-07 13:40:59 -04002112 with pytest.raises(TypeError):
Mark Williams5d890a02019-11-17 19:56:26 -08002113 interact_in_memory(server, client)
Alex Gaynor03737182020-07-23 20:40:46 -04002114 assert select_args == [(server, [b"http/1.1", b"spdy/2"])]
Cory Benfield0f7b04c2015-04-13 17:51:12 -04002115
Cory Benfieldf1177e72015-04-12 09:11:49 -04002116
Alex Chanec1e32d2016-11-10 14:11:45 +00002117class TestSession(object):
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05002118 """
2119 Unit tests for :py:obj:`OpenSSL.SSL.Session`.
2120 """
Alex Gaynor03737182020-07-23 20:40:46 -04002121
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05002122 def test_construction(self):
2123 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002124 :py:class:`Session` can be constructed with no arguments, creating
2125 a new instance of that type.
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05002126 """
2127 new_session = Session()
Alex Chanec1e32d2016-11-10 14:11:45 +00002128 assert isinstance(new_session, Session)
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05002129
2130
Alex Chan1c0cb662017-01-30 07:13:30 +00002131class TestConnection(object):
Rick Deane15b1472009-07-09 15:53:42 -05002132 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002133 Unit tests for `OpenSSL.SSL.Connection`.
Rick Deane15b1472009-07-09 15:53:42 -05002134 """
Alex Gaynor03737182020-07-23 20:40:46 -04002135
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04002136 # XXX get_peer_certificate -> None
2137 # XXX sock_shutdown
2138 # XXX master_key -> TypeError
2139 # XXX server_random -> TypeError
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04002140 # XXX connect -> TypeError
2141 # XXX connect_ex -> TypeError
2142 # XXX set_connect_state -> TypeError
2143 # XXX set_accept_state -> TypeError
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04002144 # XXX do_handshake -> TypeError
2145 # XXX bio_read -> TypeError
2146 # XXX recv -> TypeError
2147 # XXX send -> TypeError
2148 # XXX bio_write -> TypeError
2149
Rick Deane15b1472009-07-09 15:53:42 -05002150 def test_type(self):
2151 """
Alex Gaynor01f90a12019-02-07 09:14:48 -05002152 `Connection` can be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -05002153 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002154 ctx = Context(SSLv23_METHOD)
Alex Gaynor03737182020-07-23 20:40:46 -04002155 assert is_consistent_type(Connection, "Connection", ctx, None)
Rick Deane15b1472009-07-09 15:53:42 -05002156
Alex Gaynor03737182020-07-23 20:40:46 -04002157 @pytest.mark.parametrize("bad_context", [object(), "context", None, 1])
Alex Chanfb078d82017-04-20 11:16:15 +01002158 def test_wrong_args(self, bad_context):
2159 """
2160 `Connection.__init__` raises `TypeError` if called with a non-`Context`
2161 instance argument.
2162 """
2163 with pytest.raises(TypeError):
2164 Connection(bad_context)
2165
Alex Gaynor03737182020-07-23 20:40:46 -04002166 @pytest.mark.parametrize("bad_bio", [object(), None, 1, [1, 2, 3]])
Daniel Holth079c9632019-11-17 22:45:52 -05002167 def test_bio_write_wrong_args(self, bad_bio):
2168 """
2169 `Connection.bio_write` raises `TypeError` if called with a non-bytes
2170 (or text) argument.
2171 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002172 context = Context(SSLv23_METHOD)
Daniel Holth079c9632019-11-17 22:45:52 -05002173 connection = Connection(context, None)
2174 with pytest.raises(TypeError):
2175 connection.bio_write(bad_bio)
2176
2177 def test_bio_write(self):
2178 """
2179 `Connection.bio_write` does not raise if called with bytes or
2180 bytearray, warns if called with text.
2181 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002182 context = Context(SSLv23_METHOD)
Daniel Holth079c9632019-11-17 22:45:52 -05002183 connection = Connection(context, None)
Alex Gaynor03737182020-07-23 20:40:46 -04002184 connection.bio_write(b"xy")
2185 connection.bio_write(bytearray(b"za"))
Daniel Holth079c9632019-11-17 22:45:52 -05002186 with pytest.warns(DeprecationWarning):
Alex Gaynor03737182020-07-23 20:40:46 -04002187 connection.bio_write(u"deprecated")
Daniel Holth079c9632019-11-17 22:45:52 -05002188
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002189 def test_get_context(self):
2190 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002191 `Connection.get_context` returns the `Context` instance used to
2192 construct the `Connection` instance.
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002193 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002194 context = Context(SSLv23_METHOD)
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002195 connection = Connection(context, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002196 assert connection.get_context() is context
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002197
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002198 def test_set_context_wrong_args(self):
2199 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002200 `Connection.set_context` raises `TypeError` if called with a
Alex Chanfb078d82017-04-20 11:16:15 +01002201 non-`Context` instance argument.
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002202 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002203 ctx = Context(SSLv23_METHOD)
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002204 connection = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002205 with pytest.raises(TypeError):
2206 connection.set_context(object())
2207 with pytest.raises(TypeError):
2208 connection.set_context("hello")
2209 with pytest.raises(TypeError):
2210 connection.set_context(1)
2211 assert ctx is connection.get_context()
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002212
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002213 def test_set_context(self):
2214 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002215 `Connection.set_context` specifies a new `Context` instance to be
2216 used for the connection.
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002217 """
2218 original = Context(SSLv23_METHOD)
Paul Kehrer688538c2020-08-03 19:18:15 -05002219 replacement = Context(SSLv23_METHOD)
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002220 connection = Connection(original, None)
2221 connection.set_context(replacement)
Alex Chan1c0cb662017-01-30 07:13:30 +00002222 assert replacement is connection.get_context()
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002223 # Lose our references to the contexts, just in case the Connection
2224 # isn't properly managing its own contributions to their reference
2225 # counts.
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002226 del original, replacement
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002227 collect()
2228
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002229 def test_set_tlsext_host_name_wrong_args(self):
2230 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002231 If `Connection.set_tlsext_host_name` is called with a non-byte string
2232 argument or a byte string with an embedded NUL, `TypeError` is raised.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002233 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002234 conn = Connection(Context(SSLv23_METHOD), None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002235 with pytest.raises(TypeError):
2236 conn.set_tlsext_host_name(object())
2237 with pytest.raises(TypeError):
2238 conn.set_tlsext_host_name(b"with\0null")
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002239
Hugo van Kemenade60827f82019-08-30 00:39:35 +03002240 if not PY2:
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002241 # On Python 3.x, don't accidentally implicitly convert from text.
Alex Chan1c0cb662017-01-30 07:13:30 +00002242 with pytest.raises(TypeError):
2243 conn.set_tlsext_host_name(b"example.com".decode("ascii"))
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04002244
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002245 def test_pending(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002246 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002247 `Connection.pending` returns the number of bytes available for
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002248 immediate read.
2249 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002250 connection = Connection(Context(SSLv23_METHOD), None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002251 assert connection.pending() == 0
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002252
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002253 def test_peek(self):
2254 """
Hynek Schlawack3bcf3152017-02-18 08:25:34 +01002255 `Connection.recv` peeks into the connection if `socket.MSG_PEEK` is
2256 passed.
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002257 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002258 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04002259 server.send(b"xy")
2260 assert client.recv(2, MSG_PEEK) == b"xy"
2261 assert client.recv(2, MSG_PEEK) == b"xy"
2262 assert client.recv(2) == b"xy"
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002263
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002264 def test_connect_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002265 """
Hynek Schlawack3bcf3152017-02-18 08:25:34 +01002266 `Connection.connect` raises `TypeError` if called with a non-address
2267 argument.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002268 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002269 connection = Connection(Context(SSLv23_METHOD), socket_any_family())
Alex Chan1c0cb662017-01-30 07:13:30 +00002270 with pytest.raises(TypeError):
2271 connection.connect(None)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002272
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002273 def test_connect_refused(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002274 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002275 `Connection.connect` raises `socket.error` if the underlying socket
2276 connect method raises it.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002277 """
David Benjamin1fbe0642019-04-15 17:05:13 -05002278 client = socket_any_family()
Paul Kehrer688538c2020-08-03 19:18:15 -05002279 context = Context(SSLv23_METHOD)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002280 clientSSL = Connection(context, client)
Alex Gaynor122717b2015-09-05 14:14:18 -04002281 # pytest.raises here doesn't work because of a bug in py.test on Python
2282 # 2.6: https://github.com/pytest-dev/pytest/issues/988
Alex Gaynore69c2782015-09-05 14:07:48 -04002283 try:
David Benjamin1fbe0642019-04-15 17:05:13 -05002284 clientSSL.connect((loopback_address(client), 1))
Alex Gaynore69c2782015-09-05 14:07:48 -04002285 except error as e:
Alex Gaynor20a4c082015-09-05 14:24:15 -04002286 exc = e
2287 assert exc.args[0] == ECONNREFUSED
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002288
2289 def test_connect(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002290 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002291 `Connection.connect` establishes a connection to the specified address.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002292 """
David Benjamin1fbe0642019-04-15 17:05:13 -05002293 port = socket_any_family()
Alex Gaynor03737182020-07-23 20:40:46 -04002294 port.bind(("", 0))
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002295 port.listen(3)
2296
Paul Kehrer688538c2020-08-03 19:18:15 -05002297 clientSSL = Connection(Context(SSLv23_METHOD), socket(port.family))
David Benjamin1fbe0642019-04-15 17:05:13 -05002298 clientSSL.connect((loopback_address(port), port.getsockname()[1]))
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002299 # XXX An assertion? Or something?
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002300
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002301 @pytest.mark.skipif(
2302 platform == "darwin",
Alex Gaynor03737182020-07-23 20:40:46 -04002303 reason="connect_ex sometimes causes a kernel panic on OS X 10.6.4",
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002304 )
2305 def test_connect_ex(self):
2306 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002307 If there is a connection error, `Connection.connect_ex` returns the
2308 errno instead of raising an exception.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002309 """
David Benjamin1fbe0642019-04-15 17:05:13 -05002310 port = socket_any_family()
Alex Gaynor03737182020-07-23 20:40:46 -04002311 port.bind(("", 0))
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002312 port.listen(3)
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002313
Paul Kehrer688538c2020-08-03 19:18:15 -05002314 clientSSL = Connection(Context(SSLv23_METHOD), socket(port.family))
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002315 clientSSL.setblocking(False)
2316 result = clientSSL.connect_ex(port.getsockname())
2317 expected = (EINPROGRESS, EWOULDBLOCK)
Alex Chan1c0cb662017-01-30 07:13:30 +00002318 assert result in expected
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002319
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002320 def test_accept(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002321 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002322 `Connection.accept` accepts a pending connection attempt and returns a
2323 tuple of a new `Connection` (the accepted client) and the address the
2324 connection originated from.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002325 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002326 ctx = Context(SSLv23_METHOD)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002327 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2328 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
David Benjamin1fbe0642019-04-15 17:05:13 -05002329 port = socket_any_family()
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002330 portSSL = Connection(ctx, port)
Alex Gaynor03737182020-07-23 20:40:46 -04002331 portSSL.bind(("", 0))
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002332 portSSL.listen(3)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002333
Paul Kehrer688538c2020-08-03 19:18:15 -05002334 clientSSL = Connection(Context(SSLv23_METHOD), socket(port.family))
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002335
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002336 # Calling portSSL.getsockname() here to get the server IP address
2337 # sounds great, but frequently fails on Windows.
David Benjamin1fbe0642019-04-15 17:05:13 -05002338 clientSSL.connect((loopback_address(port), portSSL.getsockname()[1]))
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002339
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002340 serverSSL, address = portSSL.accept()
2341
Alex Chan1c0cb662017-01-30 07:13:30 +00002342 assert isinstance(serverSSL, Connection)
2343 assert serverSSL.get_context() is ctx
2344 assert address == clientSSL.getsockname()
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002345
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002346 def test_shutdown_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002347 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002348 `Connection.set_shutdown` raises `TypeError` if called with arguments
2349 other than integers.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002350 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002351 connection = Connection(Context(SSLv23_METHOD), None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002352 with pytest.raises(TypeError):
2353 connection.set_shutdown(None)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002354
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002355 def test_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002356 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002357 `Connection.shutdown` performs an SSL-level connection shutdown.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002358 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002359 server, client = loopback()
2360 assert not server.shutdown()
2361 assert server.get_shutdown() == SENT_SHUTDOWN
2362 with pytest.raises(ZeroReturnError):
2363 client.recv(1024)
2364 assert client.get_shutdown() == RECEIVED_SHUTDOWN
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04002365 client.shutdown()
Alex Chan1c0cb662017-01-30 07:13:30 +00002366 assert client.get_shutdown() == (SENT_SHUTDOWN | RECEIVED_SHUTDOWN)
2367 with pytest.raises(ZeroReturnError):
2368 server.recv(1024)
2369 assert server.get_shutdown() == (SENT_SHUTDOWN | RECEIVED_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002370
Paul Aurichc85e0862015-01-08 08:34:33 -08002371 def test_shutdown_closed(self):
2372 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002373 If the underlying socket is closed, `Connection.shutdown` propagates
2374 the write error from the low level write call.
Paul Aurichc85e0862015-01-08 08:34:33 -08002375 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002376 server, client = loopback()
Paul Aurichc85e0862015-01-08 08:34:33 -08002377 server.sock_shutdown(2)
Alex Chan1c0cb662017-01-30 07:13:30 +00002378 with pytest.raises(SysCallError) as exc:
2379 server.shutdown()
Alex Chanfb078d82017-04-20 11:16:15 +01002380 if platform == "win32":
2381 assert exc.value.args[0] == ESHUTDOWN
2382 else:
2383 assert exc.value.args[0] == EPIPE
Paul Aurichc85e0862015-01-08 08:34:33 -08002384
Glyph89389472015-04-14 17:29:26 -04002385 def test_shutdown_truncated(self):
Glyph6064ec32015-04-14 16:38:22 -04002386 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002387 If the underlying connection is truncated, `Connection.shutdown`
2388 raises an `Error`.
Glyph6064ec32015-04-14 16:38:22 -04002389 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002390 server_ctx = Context(SSLv23_METHOD)
2391 client_ctx = Context(SSLv23_METHOD)
Glyph89389472015-04-14 17:29:26 -04002392 server_ctx.use_privatekey(
Alex Gaynor03737182020-07-23 20:40:46 -04002393 load_privatekey(FILETYPE_PEM, server_key_pem)
2394 )
Glyph89389472015-04-14 17:29:26 -04002395 server_ctx.use_certificate(
Alex Gaynor03737182020-07-23 20:40:46 -04002396 load_certificate(FILETYPE_PEM, server_cert_pem)
2397 )
Glyph89389472015-04-14 17:29:26 -04002398 server = Connection(server_ctx, None)
2399 client = Connection(client_ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002400 handshake_in_memory(client, server)
2401 assert not server.shutdown()
2402 with pytest.raises(WantReadError):
2403 server.shutdown()
Glyph89389472015-04-14 17:29:26 -04002404 server.bio_shutdown()
Alex Chan1c0cb662017-01-30 07:13:30 +00002405 with pytest.raises(Error):
2406 server.shutdown()
Glyph6064ec32015-04-14 16:38:22 -04002407
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002408 def test_set_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002409 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002410 `Connection.set_shutdown` sets the state of the SSL connection
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002411 shutdown process.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002412 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002413 connection = Connection(Context(SSLv23_METHOD), socket_any_family())
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002414 connection.set_shutdown(RECEIVED_SHUTDOWN)
Alex Chan1c0cb662017-01-30 07:13:30 +00002415 assert connection.get_shutdown() == RECEIVED_SHUTDOWN
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002416
kjavaf248592015-09-07 12:14:01 +01002417 def test_state_string(self):
2418 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002419 `Connection.state_string` verbosely describes the current state of
2420 the `Connection`.
kjavaf248592015-09-07 12:14:01 +01002421 """
Hynek Schlawackb0274ce2015-10-16 19:56:26 +02002422 server, client = socket_pair()
Alex Chan1c0cb662017-01-30 07:13:30 +00002423 server = loopback_server_factory(server)
2424 client = loopback_client_factory(client)
kjavaf248592015-09-07 12:14:01 +01002425
Alex Gaynor5af32d02016-09-24 01:52:21 -04002426 assert server.get_state_string() in [
Alex Gaynor03737182020-07-23 20:40:46 -04002427 b"before/accept initialization",
2428 b"before SSL initialization",
Alex Gaynor5af32d02016-09-24 01:52:21 -04002429 ]
2430 assert client.get_state_string() in [
Alex Gaynor03737182020-07-23 20:40:46 -04002431 b"before/connect initialization",
2432 b"before SSL initialization",
Alex Gaynor5af32d02016-09-24 01:52:21 -04002433 ]
kjavaf248592015-09-07 12:14:01 +01002434
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002435 def test_app_data(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002436 """
2437 Any object can be set as app data by passing it to
Alex Chan1c0cb662017-01-30 07:13:30 +00002438 `Connection.set_app_data` and later retrieved with
2439 `Connection.get_app_data`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002440 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002441 conn = Connection(Context(SSLv23_METHOD), None)
Todd Chapman4f73e4f2015-08-27 11:26:43 -04002442 assert None is conn.get_app_data()
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002443 app_data = object()
2444 conn.set_app_data(app_data)
Todd Chapman4f73e4f2015-08-27 11:26:43 -04002445 assert conn.get_app_data() is app_data
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002446
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002447 def test_makefile(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002448 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002449 `Connection.makefile` is not implemented and calling that
2450 method raises `NotImplementedError`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002451 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002452 conn = Connection(Context(SSLv23_METHOD), None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002453 with pytest.raises(NotImplementedError):
2454 conn.makefile()
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002455
Jeremy Lainé460a19d2018-05-16 19:44:19 +02002456 def test_get_certificate(self):
2457 """
2458 `Connection.get_certificate` returns the local certificate.
2459 """
2460 chain = _create_certificate_chain()
2461 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
2462
Paul Kehrer688538c2020-08-03 19:18:15 -05002463 context = Context(SSLv23_METHOD)
Jeremy Lainé460a19d2018-05-16 19:44:19 +02002464 context.use_certificate(scert)
2465 client = Connection(context, None)
2466 cert = client.get_certificate()
2467 assert cert is not None
2468 assert "Server Certificate" == cert.get_subject().CN
2469
2470 def test_get_certificate_none(self):
2471 """
2472 `Connection.get_certificate` returns the local certificate.
2473
2474 If there is no certificate, it returns None.
2475 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002476 context = Context(SSLv23_METHOD)
Jeremy Lainé460a19d2018-05-16 19:44:19 +02002477 client = Connection(context, None)
2478 cert = client.get_certificate()
2479 assert cert is None
2480
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002481 def test_get_peer_cert_chain(self):
2482 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002483 `Connection.get_peer_cert_chain` returns a list of certificates
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002484 which the connected server returned for the certification verification.
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002485 """
2486 chain = _create_certificate_chain()
2487 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
2488
Paul Kehrer688538c2020-08-03 19:18:15 -05002489 serverContext = Context(SSLv23_METHOD)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002490 serverContext.use_privatekey(skey)
2491 serverContext.use_certificate(scert)
2492 serverContext.add_extra_chain_cert(icert)
2493 serverContext.add_extra_chain_cert(cacert)
2494 server = Connection(serverContext, None)
2495 server.set_accept_state()
2496
2497 # Create the client
Paul Kehrer688538c2020-08-03 19:18:15 -05002498 clientContext = Context(SSLv23_METHOD)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002499 clientContext.set_verify(VERIFY_NONE, verify_cb)
2500 client = Connection(clientContext, None)
2501 client.set_connect_state()
2502
Alex Chan1c0cb662017-01-30 07:13:30 +00002503 interact_in_memory(client, server)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002504
2505 chain = client.get_peer_cert_chain()
Alex Chan1c0cb662017-01-30 07:13:30 +00002506 assert len(chain) == 3
2507 assert "Server Certificate" == chain[0].get_subject().CN
2508 assert "Intermediate Certificate" == chain[1].get_subject().CN
2509 assert "Authority Certificate" == chain[2].get_subject().CN
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002510
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002511 def test_get_peer_cert_chain_none(self):
2512 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002513 `Connection.get_peer_cert_chain` returns `None` if the peer sends
2514 no certificate chain.
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002515 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002516 ctx = Context(SSLv23_METHOD)
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002517 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2518 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
2519 server = Connection(ctx, None)
2520 server.set_accept_state()
Paul Kehrer688538c2020-08-03 19:18:15 -05002521 client = Connection(Context(SSLv23_METHOD), None)
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002522 client.set_connect_state()
Alex Chan1c0cb662017-01-30 07:13:30 +00002523 interact_in_memory(client, server)
2524 assert None is server.get_peer_cert_chain()
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002525
Shane Harvey33c54992020-08-05 16:48:51 -07002526 def test_get_verified_chain(self):
2527 """
2528 `Connection.get_verified_chain` returns a list of certificates
2529 which the connected server returned for the certification verification.
2530 """
2531 chain = _create_certificate_chain()
2532 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
2533
2534 serverContext = Context(SSLv23_METHOD)
2535 serverContext.use_privatekey(skey)
2536 serverContext.use_certificate(scert)
2537 serverContext.add_extra_chain_cert(icert)
2538 serverContext.add_extra_chain_cert(cacert)
2539 server = Connection(serverContext, None)
2540 server.set_accept_state()
2541
2542 # Create the client
2543 clientContext = Context(SSLv23_METHOD)
2544 # cacert is self-signed so the client must trust it for verification
2545 # to succeed.
2546 clientContext.get_cert_store().add_cert(cacert)
2547 clientContext.set_verify(VERIFY_PEER, verify_cb)
2548 client = Connection(clientContext, None)
2549 client.set_connect_state()
2550
2551 interact_in_memory(client, server)
2552
2553 chain = client.get_verified_chain()
2554 assert len(chain) == 3
2555 assert "Server Certificate" == chain[0].get_subject().CN
2556 assert "Intermediate Certificate" == chain[1].get_subject().CN
2557 assert "Authority Certificate" == chain[2].get_subject().CN
2558
2559 def test_get_verified_chain_none(self):
2560 """
2561 `Connection.get_verified_chain` returns `None` if the peer sends
2562 no certificate chain.
2563 """
2564 ctx = Context(SSLv23_METHOD)
2565 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2566 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
2567 server = Connection(ctx, None)
2568 server.set_accept_state()
2569 client = Connection(Context(SSLv23_METHOD), None)
2570 client.set_connect_state()
2571 interact_in_memory(client, server)
2572 assert None is server.get_verified_chain()
2573
2574 def test_get_verified_chain_unconnected(self):
2575 """
2576 `Connection.get_verified_chain` returns `None` when used with an object
2577 which has not been connected.
2578 """
2579 ctx = Context(SSLv23_METHOD)
2580 server = Connection(ctx, None)
2581 assert None is server.get_verified_chain()
2582
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002583 def test_get_session_unconnected(self):
2584 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002585 `Connection.get_session` returns `None` when used with an object
2586 which has not been connected.
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002587 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002588 ctx = Context(SSLv23_METHOD)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002589 server = Connection(ctx, None)
2590 session = server.get_session()
Alex Chan1c0cb662017-01-30 07:13:30 +00002591 assert None is session
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002592
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002593 def test_server_get_session(self):
2594 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002595 On the server side of a connection, `Connection.get_session` returns a
2596 `Session` instance representing the SSL session for that connection.
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002597 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002598 server, client = loopback()
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002599 session = server.get_session()
Alex Chan1c0cb662017-01-30 07:13:30 +00002600 assert isinstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002601
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002602 def test_client_get_session(self):
2603 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002604 On the client side of a connection, `Connection.get_session`
2605 returns a `Session` instance representing the SSL session for
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002606 that connection.
2607 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002608 server, client = loopback()
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002609 session = client.get_session()
Alex Chan1c0cb662017-01-30 07:13:30 +00002610 assert isinstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002611
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002612 def test_set_session_wrong_args(self):
2613 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002614 `Connection.set_session` raises `TypeError` if called with an object
2615 that is not an instance of `Session`.
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002616 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002617 ctx = Context(SSLv23_METHOD)
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002618 connection = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002619 with pytest.raises(TypeError):
2620 connection.set_session(123)
2621 with pytest.raises(TypeError):
2622 connection.set_session("hello")
2623 with pytest.raises(TypeError):
2624 connection.set_session(object())
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002625
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002626 def test_client_set_session(self):
2627 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002628 `Connection.set_session`, when used prior to a connection being
2629 established, accepts a `Session` instance and causes an attempt to
2630 re-use the session it represents when the SSL handshake is performed.
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002631 """
2632 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2633 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
Paul Kehrer7d5a3bf2019-01-21 12:24:02 -06002634 ctx = Context(TLSv1_2_METHOD)
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002635 ctx.use_privatekey(key)
2636 ctx.use_certificate(cert)
2637 ctx.set_session_id("unity-test")
2638
2639 def makeServer(socket):
2640 server = Connection(ctx, socket)
2641 server.set_accept_state()
2642 return server
2643
Alex Gaynor03737182020-07-23 20:40:46 -04002644 originalServer, originalClient = loopback(server_factory=makeServer)
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002645 originalSession = originalClient.get_session()
2646
2647 def makeClient(socket):
Alex Chan1c0cb662017-01-30 07:13:30 +00002648 client = loopback_client_factory(socket)
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002649 client.set_session(originalSession)
2650 return client
Alex Gaynor03737182020-07-23 20:40:46 -04002651
Alex Chan1c0cb662017-01-30 07:13:30 +00002652 resumedServer, resumedClient = loopback(
Alex Gaynor03737182020-07-23 20:40:46 -04002653 server_factory=makeServer, client_factory=makeClient
2654 )
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002655
2656 # This is a proxy: in general, we have no access to any unique
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002657 # identifier for the session (new enough versions of OpenSSL expose
2658 # a hash which could be usable, but "new enough" is very, very new).
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002659 # Instead, exploit the fact that the master key is re-used if the
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002660 # session is re-used. As long as the master key for the two
2661 # connections is the same, the session was re-used!
Alex Chan1c0cb662017-01-30 07:13:30 +00002662 assert originalServer.master_key() == resumedServer.master_key()
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002663
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002664 def test_set_session_wrong_method(self):
2665 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002666 If `Connection.set_session` is passed a `Session` instance associated
2667 with a context using a different SSL method than the `Connection`
2668 is using, a `OpenSSL.SSL.Error` is raised.
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002669 """
Alex Gaynor124a0132020-10-27 00:15:17 -04002670 v1 = TLSv1_2_METHOD
2671 v2 = TLSv1_METHOD
Alex Gaynor5af32d02016-09-24 01:52:21 -04002672
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002673 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2674 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
Alex Gaynor5af32d02016-09-24 01:52:21 -04002675 ctx = Context(v1)
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002676 ctx.use_privatekey(key)
2677 ctx.use_certificate(cert)
Paul Kehrerc45a6ea2020-08-03 15:54:20 -05002678 ctx.set_session_id(b"unity-test")
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002679
2680 def makeServer(socket):
2681 server = Connection(ctx, socket)
2682 server.set_accept_state()
2683 return server
2684
Alex Gaynor5af32d02016-09-24 01:52:21 -04002685 def makeOriginalClient(socket):
2686 client = Connection(Context(v1), socket)
2687 client.set_connect_state()
2688 return client
2689
Alex Chan1c0cb662017-01-30 07:13:30 +00002690 originalServer, originalClient = loopback(
Alex Gaynor03737182020-07-23 20:40:46 -04002691 server_factory=makeServer, client_factory=makeOriginalClient
2692 )
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002693 originalSession = originalClient.get_session()
2694
2695 def makeClient(socket):
2696 # Intentionally use a different, incompatible method here.
Alex Gaynor5af32d02016-09-24 01:52:21 -04002697 client = Connection(Context(v2), socket)
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002698 client.set_connect_state()
2699 client.set_session(originalSession)
2700 return client
2701
Alex Chan1c0cb662017-01-30 07:13:30 +00002702 with pytest.raises(Error):
2703 loopback(client_factory=makeClient, server_factory=makeServer)
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002704
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002705 def test_wantWriteError(self):
2706 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002707 `Connection` methods which generate output raise
2708 `OpenSSL.SSL.WantWriteError` if writing to the connection's BIO
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002709 fail indicating a should-write state.
2710 """
2711 client_socket, server_socket = socket_pair()
2712 # Fill up the client's send buffer so Connection won't be able to write
Jean-Paul Calderonebbff8b92014-03-22 14:20:30 -04002713 # anything. Only write a single byte at a time so we can be sure we
2714 # completely fill the buffer. Even though the socket API is allowed to
2715 # signal a short write via its return value it seems this doesn't
2716 # always happen on all platforms (FreeBSD and OS X particular) for the
2717 # very last bit of available buffer space.
2718 msg = b"x"
caternb2777a42018-08-09 15:38:13 -04002719 for i in range(1024 * 1024 * 64):
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002720 try:
2721 client_socket.send(msg)
2722 except error as e:
2723 if e.errno == EWOULDBLOCK:
2724 break
2725 raise
2726 else:
Alex Chan1c0cb662017-01-30 07:13:30 +00002727 pytest.fail(
Alex Gaynor03737182020-07-23 20:40:46 -04002728 "Failed to fill socket buffer, cannot test BIO want write"
2729 )
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002730
Paul Kehrer688538c2020-08-03 19:18:15 -05002731 ctx = Context(SSLv23_METHOD)
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002732 conn = Connection(ctx, client_socket)
2733 # Client's speak first, so make it an SSL client
2734 conn.set_connect_state()
Alex Chan1c0cb662017-01-30 07:13:30 +00002735 with pytest.raises(WantWriteError):
2736 conn.do_handshake()
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002737
2738 # XXX want_read
2739
Fedor Brunner416f4a12014-03-28 13:18:38 +01002740 def test_get_finished_before_connect(self):
Fedor Brunner5747b932014-03-05 14:22:34 +01002741 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002742 `Connection.get_finished` returns `None` before TLS handshake
2743 is completed.
Fedor Brunner5747b932014-03-05 14:22:34 +01002744 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002745 ctx = Context(SSLv23_METHOD)
Fedor Brunner5747b932014-03-05 14:22:34 +01002746 connection = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002747 assert connection.get_finished() is None
Fedor Brunner416f4a12014-03-28 13:18:38 +01002748
2749 def test_get_peer_finished_before_connect(self):
2750 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002751 `Connection.get_peer_finished` returns `None` before TLS handshake
2752 is completed.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002753 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002754 ctx = Context(SSLv23_METHOD)
Fedor Brunner416f4a12014-03-28 13:18:38 +01002755 connection = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002756 assert connection.get_peer_finished() is None
Fedor Brunner5747b932014-03-05 14:22:34 +01002757
Fedor Brunner416f4a12014-03-28 13:18:38 +01002758 def test_get_finished(self):
2759 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002760 `Connection.get_finished` method returns the TLS Finished message send
2761 from client, or server. Finished messages are send during
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002762 TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002763 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002764 server, client = loopback()
Fedor Brunner416f4a12014-03-28 13:18:38 +01002765
Alex Chan1c0cb662017-01-30 07:13:30 +00002766 assert server.get_finished() is not None
2767 assert len(server.get_finished()) > 0
Fedor Brunner416f4a12014-03-28 13:18:38 +01002768
2769 def test_get_peer_finished(self):
2770 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002771 `Connection.get_peer_finished` method returns the TLS Finished
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002772 message received from client, or server. Finished messages are send
2773 during TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002774 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002775 server, client = loopback()
Fedor Brunner416f4a12014-03-28 13:18:38 +01002776
Alex Chan1c0cb662017-01-30 07:13:30 +00002777 assert server.get_peer_finished() is not None
2778 assert len(server.get_peer_finished()) > 0
Fedor Brunner5747b932014-03-05 14:22:34 +01002779
Fedor Brunner416f4a12014-03-28 13:18:38 +01002780 def test_tls_finished_message_symmetry(self):
2781 """
Hynek Schlawackdddd1112015-09-05 21:12:30 +02002782 The TLS Finished message send by server must be the TLS Finished
2783 message received by client.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002784
Hynek Schlawackdddd1112015-09-05 21:12:30 +02002785 The TLS Finished message send by client must be the TLS Finished
2786 message received by server.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002787 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002788 server, client = loopback()
Fedor Brunner416f4a12014-03-28 13:18:38 +01002789
Alex Chan1c0cb662017-01-30 07:13:30 +00002790 assert server.get_finished() == client.get_peer_finished()
2791 assert client.get_finished() == server.get_peer_finished()
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002792
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002793 def test_get_cipher_name_before_connect(self):
2794 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002795 `Connection.get_cipher_name` returns `None` if no connection
2796 has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002797 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002798 ctx = Context(SSLv23_METHOD)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002799 conn = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002800 assert conn.get_cipher_name() is None
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002801
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002802 def test_get_cipher_name(self):
2803 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002804 `Connection.get_cipher_name` returns a `unicode` string giving the
2805 name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002806 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002807 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04002808 server_cipher_name, client_cipher_name = (
2809 server.get_cipher_name(),
2810 client.get_cipher_name(),
2811 )
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002812
Alex Chan1c0cb662017-01-30 07:13:30 +00002813 assert isinstance(server_cipher_name, text_type)
2814 assert isinstance(client_cipher_name, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002815
Alex Chan1c0cb662017-01-30 07:13:30 +00002816 assert server_cipher_name == client_cipher_name
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002817
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002818 def test_get_cipher_version_before_connect(self):
2819 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002820 `Connection.get_cipher_version` returns `None` if no connection
2821 has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002822 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002823 ctx = Context(SSLv23_METHOD)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002824 conn = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002825 assert conn.get_cipher_version() is None
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002826
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002827 def test_get_cipher_version(self):
2828 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002829 `Connection.get_cipher_version` returns a `unicode` string giving
2830 the protocol name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002831 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002832 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04002833 server_cipher_version, client_cipher_version = (
2834 server.get_cipher_version(),
2835 client.get_cipher_version(),
2836 )
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002837
Alex Chan1c0cb662017-01-30 07:13:30 +00002838 assert isinstance(server_cipher_version, text_type)
2839 assert isinstance(client_cipher_version, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002840
Alex Chan1c0cb662017-01-30 07:13:30 +00002841 assert server_cipher_version == client_cipher_version
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002842
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002843 def test_get_cipher_bits_before_connect(self):
2844 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002845 `Connection.get_cipher_bits` returns `None` if no connection has
2846 been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002847 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002848 ctx = Context(SSLv23_METHOD)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002849 conn = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002850 assert conn.get_cipher_bits() is None
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002851
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002852 def test_get_cipher_bits(self):
2853 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002854 `Connection.get_cipher_bits` returns the number of secret bits
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002855 of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002856 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002857 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04002858 server_cipher_bits, client_cipher_bits = (
2859 server.get_cipher_bits(),
2860 client.get_cipher_bits(),
2861 )
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002862
Alex Chan1c0cb662017-01-30 07:13:30 +00002863 assert isinstance(server_cipher_bits, int)
2864 assert isinstance(client_cipher_bits, int)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002865
Alex Chan1c0cb662017-01-30 07:13:30 +00002866 assert server_cipher_bits == client_cipher_bits
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002867
Jim Shaverabff1882015-05-27 09:15:55 -04002868 def test_get_protocol_version_name(self):
2869 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002870 `Connection.get_protocol_version_name()` returns a string giving the
2871 protocol version of the current connection.
Jim Shaverabff1882015-05-27 09:15:55 -04002872 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002873 server, client = loopback()
Jim Shaverabff1882015-05-27 09:15:55 -04002874 client_protocol_version_name = client.get_protocol_version_name()
2875 server_protocol_version_name = server.get_protocol_version_name()
2876
Alex Chan1c0cb662017-01-30 07:13:30 +00002877 assert isinstance(server_protocol_version_name, text_type)
2878 assert isinstance(client_protocol_version_name, text_type)
Jim Shaverabff1882015-05-27 09:15:55 -04002879
Alex Chan1c0cb662017-01-30 07:13:30 +00002880 assert server_protocol_version_name == client_protocol_version_name
Jim Shaverabff1882015-05-27 09:15:55 -04002881
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002882 def test_get_protocol_version(self):
2883 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002884 `Connection.get_protocol_version()` returns an integer
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002885 giving the protocol version of the current connection.
2886 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002887 server, client = loopback()
Jim Shaver85a4dff2015-04-27 17:42:46 -04002888 client_protocol_version = client.get_protocol_version()
2889 server_protocol_version = server.get_protocol_version()
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002890
Alex Chan1c0cb662017-01-30 07:13:30 +00002891 assert isinstance(server_protocol_version, int)
2892 assert isinstance(client_protocol_version, int)
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002893
Alex Chan1c0cb662017-01-30 07:13:30 +00002894 assert server_protocol_version == client_protocol_version
2895
2896 def test_wantReadError(self):
2897 """
2898 `Connection.bio_read` raises `OpenSSL.SSL.WantReadError` if there are
2899 no bytes available to be read from the BIO.
2900 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002901 ctx = Context(SSLv23_METHOD)
Alex Chan1c0cb662017-01-30 07:13:30 +00002902 conn = Connection(ctx, None)
2903 with pytest.raises(WantReadError):
2904 conn.bio_read(1024)
2905
Alex Gaynor03737182020-07-23 20:40:46 -04002906 @pytest.mark.parametrize("bufsize", [1.0, None, object(), "bufsize"])
Alex Chanfb078d82017-04-20 11:16:15 +01002907 def test_bio_read_wrong_args(self, bufsize):
2908 """
2909 `Connection.bio_read` raises `TypeError` if passed a non-integer
2910 argument.
2911 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002912 ctx = Context(SSLv23_METHOD)
Alex Chanfb078d82017-04-20 11:16:15 +01002913 conn = Connection(ctx, None)
2914 with pytest.raises(TypeError):
2915 conn.bio_read(bufsize)
2916
Alex Chan1c0cb662017-01-30 07:13:30 +00002917 def test_buffer_size(self):
2918 """
2919 `Connection.bio_read` accepts an integer giving the maximum number
2920 of bytes to read and return.
2921 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002922 ctx = Context(SSLv23_METHOD)
Alex Chan1c0cb662017-01-30 07:13:30 +00002923 conn = Connection(ctx, None)
2924 conn.set_connect_state()
2925 try:
2926 conn.do_handshake()
2927 except WantReadError:
2928 pass
2929 data = conn.bio_read(2)
2930 assert 2 == len(data)
2931
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002932
Alex Chanb7480992017-01-30 14:04:47 +00002933class TestConnectionGetCipherList(object):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002934 """
Alex Chanb7480992017-01-30 14:04:47 +00002935 Tests for `Connection.get_cipher_list`.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002936 """
Alex Gaynor03737182020-07-23 20:40:46 -04002937
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002938 def test_result(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002939 """
Alex Chanb7480992017-01-30 14:04:47 +00002940 `Connection.get_cipher_list` returns a list of `bytes` giving the
2941 names of the ciphers which might be used.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002942 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002943 connection = Connection(Context(SSLv23_METHOD), None)
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002944 ciphers = connection.get_cipher_list()
Alex Chanb7480992017-01-30 14:04:47 +00002945 assert isinstance(ciphers, list)
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002946 for cipher in ciphers:
Alex Chanb7480992017-01-30 14:04:47 +00002947 assert isinstance(cipher, str)
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002948
2949
Maximilian Hils868dc3c2017-02-10 14:56:55 +01002950class VeryLarge(bytes):
2951 """
2952 Mock object so that we don't have to allocate 2**31 bytes
2953 """
Alex Gaynor03737182020-07-23 20:40:46 -04002954
Maximilian Hils868dc3c2017-02-10 14:56:55 +01002955 def __len__(self):
Alex Gaynor03737182020-07-23 20:40:46 -04002956 return 2 ** 31
Maximilian Hils868dc3c2017-02-10 14:56:55 +01002957
2958
Alex Chanb7480992017-01-30 14:04:47 +00002959class TestConnectionSend(object):
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002960 """
Alex Chanb7480992017-01-30 14:04:47 +00002961 Tests for `Connection.send`.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002962 """
Alex Gaynor03737182020-07-23 20:40:46 -04002963
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002964 def test_wrong_args(self):
2965 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002966 When called with arguments other than string argument for its first
Alex Chanb7480992017-01-30 14:04:47 +00002967 parameter, `Connection.send` raises `TypeError`.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002968 """
Paul Kehrer688538c2020-08-03 19:18:15 -05002969 connection = Connection(Context(SSLv23_METHOD), None)
Alex Chanb7480992017-01-30 14:04:47 +00002970 with pytest.raises(TypeError):
2971 connection.send(object())
Daniel Holth079c9632019-11-17 22:45:52 -05002972 with pytest.raises(TypeError):
2973 connection.send([1, 2, 3])
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002974
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002975 def test_short_bytes(self):
2976 """
Alex Chanb7480992017-01-30 14:04:47 +00002977 When passed a short byte string, `Connection.send` transmits all of it
2978 and returns the number of bytes sent.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002979 """
Alex Chanb7480992017-01-30 14:04:47 +00002980 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04002981 count = server.send(b"xy")
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"
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002984
Abraham Martinef063482015-03-25 14:06:24 +00002985 def test_text(self):
2986 """
Alex Chanb7480992017-01-30 14:04:47 +00002987 When passed a text, `Connection.send` transmits all of it and
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002988 returns the number of bytes sent. It also raises a DeprecationWarning.
Abraham Martinef063482015-03-25 14:06:24 +00002989 """
Alex Chanb7480992017-01-30 14:04:47 +00002990 server, client = loopback()
2991 with pytest.warns(DeprecationWarning) as w:
Abraham Martinef063482015-03-25 14:06:24 +00002992 simplefilter("always")
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002993 count = server.send(b"xy".decode("ascii"))
Alex Gaynor03737182020-07-23 20:40:46 -04002994 assert "{0} for buf is no longer accepted, use bytes".format(
2995 WARNING_TYPE_EXPECTED
2996 ) == str(w[-1].message)
Alex Chanb7480992017-01-30 14:04:47 +00002997 assert count == 2
Alex Gaynor03737182020-07-23 20:40:46 -04002998 assert client.recv(2) == b"xy"
Abraham Martinef063482015-03-25 14:06:24 +00002999
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003000 def test_short_memoryview(self):
3001 """
3002 When passed a memoryview onto a small number of bytes,
Alex Chanb7480992017-01-30 14:04:47 +00003003 `Connection.send` transmits all of them and returns the number
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003004 of bytes sent.
3005 """
Alex Chanb7480992017-01-30 14:04:47 +00003006 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04003007 count = server.send(memoryview(b"xy"))
Alex Chanb7480992017-01-30 14:04:47 +00003008 assert count == 2
Alex Gaynor03737182020-07-23 20:40:46 -04003009 assert client.recv(2) == b"xy"
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05003010
Daniel Holth079c9632019-11-17 22:45:52 -05003011 def test_short_bytearray(self):
3012 """
3013 When passed a short bytearray, `Connection.send` transmits all of
3014 it and returns the number of bytes sent.
3015 """
3016 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04003017 count = server.send(bytearray(b"xy"))
Daniel Holth079c9632019-11-17 22:45:52 -05003018 assert count == 2
Alex Gaynor03737182020-07-23 20:40:46 -04003019 assert client.recv(2) == b"xy"
Daniel Holth079c9632019-11-17 22:45:52 -05003020
Hynek Schlawack8e94f1b2015-09-05 21:31:00 +02003021 @skip_if_py3
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003022 def test_short_buffer(self):
3023 """
3024 When passed a buffer containing a small number of bytes,
Alex Chanb7480992017-01-30 14:04:47 +00003025 `Connection.send` transmits all of them and returns the number
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003026 of bytes sent.
3027 """
Alex Chanb7480992017-01-30 14:04:47 +00003028 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04003029 count = server.send(buffer(b"xy")) # noqa: F821
Alex Chanb7480992017-01-30 14:04:47 +00003030 assert count == 2
Alex Gaynor03737182020-07-23 20:40:46 -04003031 assert client.recv(2) == b"xy"
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02003032
Maximilian Hils868dc3c2017-02-10 14:56:55 +01003033 @pytest.mark.skipif(
Alex Gaynor03737182020-07-23 20:40:46 -04003034 sys.maxsize < 2 ** 31,
3035 reason="sys.maxsize < 2**31 - test requires 64 bit",
Maximilian Hils868dc3c2017-02-10 14:56:55 +01003036 )
3037 def test_buf_too_large(self):
3038 """
3039 When passed a buffer containing >= 2**31 bytes,
3040 `Connection.send` bails out as SSL_write only
3041 accepts an int for the buffer length.
3042 """
Paul Kehrer688538c2020-08-03 19:18:15 -05003043 connection = Connection(Context(SSLv23_METHOD), None)
Maximilian Hils868dc3c2017-02-10 14:56:55 +01003044 with pytest.raises(ValueError) as exc_info:
3045 connection.send(VeryLarge())
3046 exc_info.match(r"Cannot send more than .+ bytes at once")
3047
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05003048
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003049def _make_memoryview(size):
3050 """
3051 Create a new ``memoryview`` wrapped around a ``bytearray`` of the given
3052 size.
3053 """
3054 return memoryview(bytearray(size))
3055
3056
Alex Chanb7480992017-01-30 14:04:47 +00003057class TestConnectionRecvInto(object):
Cory Benfield62d10332014-06-15 10:03:41 +01003058 """
Alex Chanb7480992017-01-30 14:04:47 +00003059 Tests for `Connection.recv_into`.
Cory Benfield62d10332014-06-15 10:03:41 +01003060 """
Alex Gaynor03737182020-07-23 20:40:46 -04003061
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003062 def _no_length_test(self, factory):
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04003063 """
Alex Chanb7480992017-01-30 14:04:47 +00003064 Assert that when the given buffer is passed to `Connection.recv_into`,
3065 whatever bytes are available to be received that fit into that buffer
3066 are written into that buffer.
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04003067 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003068 output_buffer = factory(5)
3069
Alex Chanb7480992017-01-30 14:04:47 +00003070 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04003071 server.send(b"xy")
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04003072
Alex Chanb7480992017-01-30 14:04:47 +00003073 assert client.recv_into(output_buffer) == 2
Alex Gaynor03737182020-07-23 20:40:46 -04003074 assert output_buffer == bytearray(b"xy\x00\x00\x00")
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04003075
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04003076 def test_bytearray_no_length(self):
Cory Benfield62d10332014-06-15 10:03:41 +01003077 """
Alex Chanb7480992017-01-30 14:04:47 +00003078 `Connection.recv_into` can be passed a `bytearray` instance and data
3079 in the receive buffer is written to it.
Cory Benfield62d10332014-06-15 10:03:41 +01003080 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003081 self._no_length_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01003082
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003083 def _respects_length_test(self, factory):
Cory Benfield62d10332014-06-15 10:03:41 +01003084 """
Alex Chanb7480992017-01-30 14:04:47 +00003085 Assert that when the given buffer is passed to `Connection.recv_into`
3086 along with a value for `nbytes` that is less than the size of that
3087 buffer, only `nbytes` bytes are written into the buffer.
Cory Benfield62d10332014-06-15 10:03:41 +01003088 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003089 output_buffer = factory(10)
3090
Alex Chanb7480992017-01-30 14:04:47 +00003091 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04003092 server.send(b"abcdefghij")
Cory Benfield62d10332014-06-15 10:03:41 +01003093
Alex Chanb7480992017-01-30 14:04:47 +00003094 assert client.recv_into(output_buffer, 5) == 5
Alex Gaynor03737182020-07-23 20:40:46 -04003095 assert output_buffer == bytearray(b"abcde\x00\x00\x00\x00\x00")
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04003096
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04003097 def test_bytearray_respects_length(self):
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04003098 """
Alex Chanb7480992017-01-30 14:04:47 +00003099 When called with a `bytearray` instance, `Connection.recv_into`
3100 respects the `nbytes` parameter and doesn't copy in more than that
3101 number of bytes.
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04003102 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003103 self._respects_length_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01003104
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003105 def _doesnt_overfill_test(self, factory):
Cory Benfield62d10332014-06-15 10:03:41 +01003106 """
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04003107 Assert that if there are more bytes available to be read from the
3108 receive buffer than would fit into the buffer passed to
Alex Chanb7480992017-01-30 14:04:47 +00003109 `Connection.recv_into`, only as many as fit are written into it.
Cory Benfield62d10332014-06-15 10:03:41 +01003110 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003111 output_buffer = factory(5)
3112
Alex Chanb7480992017-01-30 14:04:47 +00003113 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04003114 server.send(b"abcdefghij")
Cory Benfield62d10332014-06-15 10:03:41 +01003115
Alex Chanb7480992017-01-30 14:04:47 +00003116 assert client.recv_into(output_buffer) == 5
Alex Gaynor03737182020-07-23 20:40:46 -04003117 assert output_buffer == bytearray(b"abcde")
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04003118 rest = client.recv(5)
Alex Gaynor03737182020-07-23 20:40:46 -04003119 assert b"fghij" == rest
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04003120
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04003121 def test_bytearray_doesnt_overfill(self):
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04003122 """
Alex Chanb7480992017-01-30 14:04:47 +00003123 When called with a `bytearray` instance, `Connection.recv_into`
3124 respects the size of the array and doesn't write more bytes into it
3125 than will fit.
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04003126 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003127 self._doesnt_overfill_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01003128
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04003129 def test_bytearray_really_doesnt_overfill(self):
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003130 """
Alex Chanb7480992017-01-30 14:04:47 +00003131 When called with a `bytearray` instance and an `nbytes` value that is
3132 too large, `Connection.recv_into` respects the size of the array and
3133 not the `nbytes` value and doesn't write more bytes into the buffer
3134 than will fit.
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003135 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003136 self._doesnt_overfill_test(bytearray)
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003137
Maximilian Hils1d95dea2015-08-17 19:27:20 +02003138 def test_peek(self):
Alex Chanb7480992017-01-30 14:04:47 +00003139 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04003140 server.send(b"xy")
Maximilian Hils1d95dea2015-08-17 19:27:20 +02003141
3142 for _ in range(2):
3143 output_buffer = bytearray(5)
Alex Chanb7480992017-01-30 14:04:47 +00003144 assert client.recv_into(output_buffer, flags=MSG_PEEK) == 2
Alex Gaynor03737182020-07-23 20:40:46 -04003145 assert output_buffer == bytearray(b"xy\x00\x00\x00")
Maximilian Hils1d95dea2015-08-17 19:27:20 +02003146
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003147 def test_memoryview_no_length(self):
3148 """
Alex Chanb7480992017-01-30 14:04:47 +00003149 `Connection.recv_into` can be passed a `memoryview` instance and data
3150 in the receive buffer is written to it.
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003151 """
3152 self._no_length_test(_make_memoryview)
Maximilian Hils1d95dea2015-08-17 19:27:20 +02003153
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003154 def test_memoryview_respects_length(self):
3155 """
Alex Chanb7480992017-01-30 14:04:47 +00003156 When called with a `memoryview` instance, `Connection.recv_into`
3157 respects the ``nbytes`` parameter and doesn't copy more than that
3158 number of bytes in.
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003159 """
3160 self._respects_length_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01003161
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003162 def test_memoryview_doesnt_overfill(self):
3163 """
Alex Chanb7480992017-01-30 14:04:47 +00003164 When called with a `memoryview` instance, `Connection.recv_into`
3165 respects the size of the array and doesn't write more bytes into it
3166 than will fit.
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003167 """
3168 self._doesnt_overfill_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01003169
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003170 def test_memoryview_really_doesnt_overfill(self):
3171 """
Alex Chanb7480992017-01-30 14:04:47 +00003172 When called with a `memoryview` instance and an `nbytes` value that is
3173 too large, `Connection.recv_into` respects the size of the array and
3174 not the `nbytes` value and doesn't write more bytes into the buffer
3175 than will fit.
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003176 """
3177 self._doesnt_overfill_test(_make_memoryview)
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003178
Cory Benfield62d10332014-06-15 10:03:41 +01003179
Alex Chanb7480992017-01-30 14:04:47 +00003180class TestConnectionSendall(object):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003181 """
Alex Chanb7480992017-01-30 14:04:47 +00003182 Tests for `Connection.sendall`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003183 """
Alex Gaynor03737182020-07-23 20:40:46 -04003184
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003185 def test_wrong_args(self):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003186 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003187 When called with arguments other than a string argument for its first
Alex Chanb7480992017-01-30 14:04:47 +00003188 parameter, `Connection.sendall` raises `TypeError`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003189 """
Paul Kehrer688538c2020-08-03 19:18:15 -05003190 connection = Connection(Context(SSLv23_METHOD), None)
Alex Chanb7480992017-01-30 14:04:47 +00003191 with pytest.raises(TypeError):
3192 connection.sendall(object())
Daniel Holth079c9632019-11-17 22:45:52 -05003193 with pytest.raises(TypeError):
3194 connection.sendall([1, 2, 3])
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003195
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003196 def test_short(self):
3197 """
Alex Chanb7480992017-01-30 14:04:47 +00003198 `Connection.sendall` transmits all of the bytes in the string
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003199 passed to it.
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003200 """
Alex Chanb7480992017-01-30 14:04:47 +00003201 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04003202 server.sendall(b"x")
3203 assert client.recv(1) == b"x"
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003204
Abraham Martinef063482015-03-25 14:06:24 +00003205 def test_text(self):
3206 """
Alex Chanb7480992017-01-30 14:04:47 +00003207 `Connection.sendall` transmits all the content in the string passed
3208 to it, raising a DeprecationWarning in case of this being a text.
Abraham Martinef063482015-03-25 14:06:24 +00003209 """
Alex Chanb7480992017-01-30 14:04:47 +00003210 server, client = loopback()
3211 with pytest.warns(DeprecationWarning) as w:
Abraham Martinef063482015-03-25 14:06:24 +00003212 simplefilter("always")
Jean-Paul Calderone8dc37a12015-03-29 08:16:52 -04003213 server.sendall(b"x".decode("ascii"))
Alex Gaynor03737182020-07-23 20:40:46 -04003214 assert "{0} for buf is no longer accepted, use bytes".format(
3215 WARNING_TYPE_EXPECTED
3216 ) == str(w[-1].message)
Alex Chanb7480992017-01-30 14:04:47 +00003217 assert client.recv(1) == b"x"
Abraham Martinef063482015-03-25 14:06:24 +00003218
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003219 def test_short_memoryview(self):
3220 """
3221 When passed a memoryview onto a small number of bytes,
Alex Chanb7480992017-01-30 14:04:47 +00003222 `Connection.sendall` transmits all of them.
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003223 """
Alex Chanb7480992017-01-30 14:04:47 +00003224 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04003225 server.sendall(memoryview(b"x"))
3226 assert client.recv(1) == b"x"
Abraham Martinef063482015-03-25 14:06:24 +00003227
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003228 @skip_if_py3
3229 def test_short_buffers(self):
3230 """
3231 When passed a buffer containing a small number of bytes,
Alex Chanb7480992017-01-30 14:04:47 +00003232 `Connection.sendall` transmits all of them.
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003233 """
Alex Chanb7480992017-01-30 14:04:47 +00003234 server, client = loopback()
Alex Gaynor03737182020-07-23 20:40:46 -04003235 count = server.sendall(buffer(b"xy")) # noqa: F821
Daniel Holth079c9632019-11-17 22:45:52 -05003236 assert count == 2
Alex Gaynor03737182020-07-23 20:40:46 -04003237 assert client.recv(2) == b"xy"
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02003238
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003239 def test_long(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003240 """
Alex Chanb7480992017-01-30 14:04:47 +00003241 `Connection.sendall` transmits all the bytes in the string passed to it
3242 even if this requires multiple calls of an underlying write function.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003243 """
Alex Chanb7480992017-01-30 14:04:47 +00003244 server, client = loopback()
Jean-Paul Calderone6241c702010-09-16 19:59:24 -04003245 # Should be enough, underlying SSL_write should only do 16k at a time.
Hynek Schlawack35618382015-09-05 21:54:25 +02003246 # On Windows, after 32k of bytes the write will block (forever
3247 # - because no one is yet reading).
Alex Gaynor03737182020-07-23 20:40:46 -04003248 message = b"x" * (1024 * 32 - 1) + b"y"
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003249 server.sendall(message)
3250 accum = []
3251 received = 0
3252 while received < len(message):
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04003253 data = client.recv(1024)
3254 accum.append(data)
3255 received += len(data)
Alex Gaynor03737182020-07-23 20:40:46 -04003256 assert message == b"".join(accum)
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003257
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003258 def test_closed(self):
3259 """
Alex Chanb7480992017-01-30 14:04:47 +00003260 If the underlying socket is closed, `Connection.sendall` propagates the
3261 write error from the low level write call.
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003262 """
Alex Chanb7480992017-01-30 14:04:47 +00003263 server, client = loopback()
Jean-Paul Calderone05d43e82010-09-24 18:01:36 -04003264 server.sock_shutdown(2)
Alex Chanb7480992017-01-30 14:04:47 +00003265 with pytest.raises(SysCallError) as err:
3266 server.sendall(b"hello, world")
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +02003267 if platform == "win32":
Alex Chanb7480992017-01-30 14:04:47 +00003268 assert err.value.args[0] == ESHUTDOWN
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +02003269 else:
Alex Chanb7480992017-01-30 14:04:47 +00003270 assert err.value.args[0] == EPIPE
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003271
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003272
Alex Chanb7480992017-01-30 14:04:47 +00003273class TestConnectionRenegotiate(object):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003274 """
3275 Tests for SSL renegotiation APIs.
3276 """
Alex Gaynor03737182020-07-23 20:40:46 -04003277
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003278 def test_total_renegotiations(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003279 """
Alex Chanb7480992017-01-30 14:04:47 +00003280 `Connection.total_renegotiations` returns `0` before any renegotiations
3281 have happened.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003282 """
Paul Kehrer688538c2020-08-03 19:18:15 -05003283 connection = Connection(Context(SSLv23_METHOD), None)
Alex Chanb7480992017-01-30 14:04:47 +00003284 assert connection.total_renegotiations() == 0
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003285
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003286 def test_renegotiate(self):
3287 """
3288 Go through a complete renegotiation cycle.
3289 """
Paul Kehrer7d5a3bf2019-01-21 12:24:02 -06003290 server, client = loopback(
3291 lambda s: loopback_server_factory(s, TLSv1_2_METHOD),
3292 lambda s: loopback_client_factory(s, TLSv1_2_METHOD),
3293 )
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003294
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003295 server.send(b"hello world")
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003296
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003297 assert b"hello world" == client.recv(len(b"hello world"))
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003298
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003299 assert 0 == server.total_renegotiations()
3300 assert False is server.renegotiate_pending()
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003301
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003302 assert True is server.renegotiate()
3303
3304 assert True is server.renegotiate_pending()
3305
3306 server.setblocking(False)
3307 client.setblocking(False)
3308
3309 client.do_handshake()
3310 server.do_handshake()
3311
3312 assert 1 == server.total_renegotiations()
3313 while False is server.renegotiate_pending():
3314 pass
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003315
3316
Alex Chanb7480992017-01-30 14:04:47 +00003317class TestError(object):
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003318 """
Alex Chanb7480992017-01-30 14:04:47 +00003319 Unit tests for `OpenSSL.SSL.Error`.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003320 """
Alex Gaynor03737182020-07-23 20:40:46 -04003321
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003322 def test_type(self):
3323 """
Alex Chanb7480992017-01-30 14:04:47 +00003324 `Error` is an exception type.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003325 """
Alex Chanb7480992017-01-30 14:04:47 +00003326 assert issubclass(Error, Exception)
Alex Gaynor03737182020-07-23 20:40:46 -04003327 assert Error.__name__ == "Error"
Rick Deane15b1472009-07-09 15:53:42 -05003328
3329
Alex Chanb7480992017-01-30 14:04:47 +00003330class TestConstants(object):
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003331 """
Alex Chanb7480992017-01-30 14:04:47 +00003332 Tests for the values of constants exposed in `OpenSSL.SSL`.
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003333
3334 These are values defined by OpenSSL intended only to be used as flags to
3335 OpenSSL APIs. The only assertions it seems can be made about them is
3336 their values.
3337 """
Alex Gaynor03737182020-07-23 20:40:46 -04003338
Hynek Schlawack35618382015-09-05 21:54:25 +02003339 @pytest.mark.skipif(
3340 OP_NO_QUERY_MTU is None,
Alex Gaynor03737182020-07-23 20:40:46 -04003341 reason="OP_NO_QUERY_MTU unavailable - OpenSSL version may be too old",
Hynek Schlawack35618382015-09-05 21:54:25 +02003342 )
3343 def test_op_no_query_mtu(self):
3344 """
Alex Chanb7480992017-01-30 14:04:47 +00003345 The value of `OpenSSL.SSL.OP_NO_QUERY_MTU` is 0x1000, the value
3346 of `SSL_OP_NO_QUERY_MTU` defined by `openssl/ssl.h`.
Hynek Schlawack35618382015-09-05 21:54:25 +02003347 """
Alex Chanb7480992017-01-30 14:04:47 +00003348 assert OP_NO_QUERY_MTU == 0x1000
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003349
Hynek Schlawack35618382015-09-05 21:54:25 +02003350 @pytest.mark.skipif(
3351 OP_COOKIE_EXCHANGE is None,
3352 reason="OP_COOKIE_EXCHANGE unavailable - "
Alex Gaynor03737182020-07-23 20:40:46 -04003353 "OpenSSL version may be too old",
Hynek Schlawack35618382015-09-05 21:54:25 +02003354 )
3355 def test_op_cookie_exchange(self):
3356 """
Alex Chanb7480992017-01-30 14:04:47 +00003357 The value of `OpenSSL.SSL.OP_COOKIE_EXCHANGE` is 0x2000, the
3358 value of `SSL_OP_COOKIE_EXCHANGE` defined by `openssl/ssl.h`.
Hynek Schlawack35618382015-09-05 21:54:25 +02003359 """
Alex Chanb7480992017-01-30 14:04:47 +00003360 assert OP_COOKIE_EXCHANGE == 0x2000
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003361
Hynek Schlawack35618382015-09-05 21:54:25 +02003362 @pytest.mark.skipif(
3363 OP_NO_TICKET is None,
Alex Gaynor03737182020-07-23 20:40:46 -04003364 reason="OP_NO_TICKET unavailable - OpenSSL version may be too old",
Hynek Schlawack35618382015-09-05 21:54:25 +02003365 )
3366 def test_op_no_ticket(self):
3367 """
Alex Chanb7480992017-01-30 14:04:47 +00003368 The value of `OpenSSL.SSL.OP_NO_TICKET` is 0x4000, the value of
3369 `SSL_OP_NO_TICKET` defined by `openssl/ssl.h`.
Hynek Schlawack35618382015-09-05 21:54:25 +02003370 """
Alex Chanb7480992017-01-30 14:04:47 +00003371 assert OP_NO_TICKET == 0x4000
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003372
Hynek Schlawack35618382015-09-05 21:54:25 +02003373 @pytest.mark.skipif(
3374 OP_NO_COMPRESSION is None,
Alex Gaynor03737182020-07-23 20:40:46 -04003375 reason=(
3376 "OP_NO_COMPRESSION unavailable - OpenSSL version may be too old"
3377 ),
Hynek Schlawack35618382015-09-05 21:54:25 +02003378 )
3379 def test_op_no_compression(self):
3380 """
Alex Chanb7480992017-01-30 14:04:47 +00003381 The value of `OpenSSL.SSL.OP_NO_COMPRESSION` is 0x20000, the
3382 value of `SSL_OP_NO_COMPRESSION` defined by `openssl/ssl.h`.
Hynek Schlawack35618382015-09-05 21:54:25 +02003383 """
Alex Chanb7480992017-01-30 14:04:47 +00003384 assert OP_NO_COMPRESSION == 0x20000
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04003385
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003386 def test_sess_cache_off(self):
3387 """
Alex Chanb7480992017-01-30 14:04:47 +00003388 The value of `OpenSSL.SSL.SESS_CACHE_OFF` 0x0, the value of
3389 `SSL_SESS_CACHE_OFF` defined by `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003390 """
Alex Chanb7480992017-01-30 14:04:47 +00003391 assert 0x0 == SESS_CACHE_OFF
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003392
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003393 def test_sess_cache_client(self):
3394 """
Alex Chanb7480992017-01-30 14:04:47 +00003395 The value of `OpenSSL.SSL.SESS_CACHE_CLIENT` 0x1, the value of
3396 `SSL_SESS_CACHE_CLIENT` defined by `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003397 """
Alex Chanb7480992017-01-30 14:04:47 +00003398 assert 0x1 == SESS_CACHE_CLIENT
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003399
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003400 def test_sess_cache_server(self):
3401 """
Alex Chanb7480992017-01-30 14:04:47 +00003402 The value of `OpenSSL.SSL.SESS_CACHE_SERVER` 0x2, the value of
3403 `SSL_SESS_CACHE_SERVER` defined by `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003404 """
Alex Chanb7480992017-01-30 14:04:47 +00003405 assert 0x2 == SESS_CACHE_SERVER
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003406
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003407 def test_sess_cache_both(self):
3408 """
Alex Chanb7480992017-01-30 14:04:47 +00003409 The value of `OpenSSL.SSL.SESS_CACHE_BOTH` 0x3, the value of
3410 `SSL_SESS_CACHE_BOTH` defined by `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003411 """
Alex Chanb7480992017-01-30 14:04:47 +00003412 assert 0x3 == SESS_CACHE_BOTH
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003413
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003414 def test_sess_cache_no_auto_clear(self):
3415 """
Alex Chanb7480992017-01-30 14:04:47 +00003416 The value of `OpenSSL.SSL.SESS_CACHE_NO_AUTO_CLEAR` 0x80, the
3417 value of `SSL_SESS_CACHE_NO_AUTO_CLEAR` defined by
3418 `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003419 """
Alex Chanb7480992017-01-30 14:04:47 +00003420 assert 0x80 == SESS_CACHE_NO_AUTO_CLEAR
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003421
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003422 def test_sess_cache_no_internal_lookup(self):
3423 """
Alex Chanb7480992017-01-30 14:04:47 +00003424 The value of `OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_LOOKUP` 0x100,
3425 the value of `SSL_SESS_CACHE_NO_INTERNAL_LOOKUP` defined by
3426 `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003427 """
Alex Chanb7480992017-01-30 14:04:47 +00003428 assert 0x100 == SESS_CACHE_NO_INTERNAL_LOOKUP
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003429
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003430 def test_sess_cache_no_internal_store(self):
3431 """
Alex Chanb7480992017-01-30 14:04:47 +00003432 The value of `OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_STORE` 0x200,
3433 the value of `SSL_SESS_CACHE_NO_INTERNAL_STORE` defined by
3434 `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003435 """
Alex Chanb7480992017-01-30 14:04:47 +00003436 assert 0x200 == SESS_CACHE_NO_INTERNAL_STORE
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003437
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003438 def test_sess_cache_no_internal(self):
3439 """
Alex Chanb7480992017-01-30 14:04:47 +00003440 The value of `OpenSSL.SSL.SESS_CACHE_NO_INTERNAL` 0x300, the
3441 value of `SSL_SESS_CACHE_NO_INTERNAL` defined by
3442 `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003443 """
Alex Chanb7480992017-01-30 14:04:47 +00003444 assert 0x300 == SESS_CACHE_NO_INTERNAL
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003445
3446
Alex Chanb7480992017-01-30 14:04:47 +00003447class TestMemoryBIO(object):
Rick Deanb71c0d22009-04-01 14:09:23 -05003448 """
Alex Chanb7480992017-01-30 14:04:47 +00003449 Tests for `OpenSSL.SSL.Connection` using a memory BIO.
Rick Deanb71c0d22009-04-01 14:09:23 -05003450 """
Alex Gaynor03737182020-07-23 20:40:46 -04003451
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003452 def _server(self, sock):
3453 """
Alex Chanb7480992017-01-30 14:04:47 +00003454 Create a new server-side SSL `Connection` object wrapped around `sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003455 """
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003456 # Create the server side Connection. This is mostly setup boilerplate
3457 # - use TLSv1, use a particular certificate, etc.
Paul Kehrer688538c2020-08-03 19:18:15 -05003458 server_ctx = Context(SSLv23_METHOD)
Alex Gaynor43307782015-09-04 09:05:45 -04003459 server_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE)
Hynek Schlawack35618382015-09-05 21:54:25 +02003460 server_ctx.set_verify(
3461 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT | VERIFY_CLIENT_ONCE,
Alex Gaynor03737182020-07-23 20:40:46 -04003462 verify_cb,
Hynek Schlawack35618382015-09-05 21:54:25 +02003463 )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003464 server_store = server_ctx.get_cert_store()
Hynek Schlawack35618382015-09-05 21:54:25 +02003465 server_ctx.use_privatekey(
Alex Gaynor03737182020-07-23 20:40:46 -04003466 load_privatekey(FILETYPE_PEM, server_key_pem)
3467 )
Hynek Schlawack35618382015-09-05 21:54:25 +02003468 server_ctx.use_certificate(
Alex Gaynor03737182020-07-23 20:40:46 -04003469 load_certificate(FILETYPE_PEM, server_cert_pem)
3470 )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003471 server_ctx.check_privatekey()
3472 server_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Hynek Schlawack35618382015-09-05 21:54:25 +02003473 # Here the Connection is actually created. If None is passed as the
3474 # 2nd parameter, it indicates a memory BIO should be created.
Rick Deanb1ccd562009-07-09 23:52:39 -05003475 server_conn = Connection(server_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003476 server_conn.set_accept_state()
3477 return server_conn
3478
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003479 def _client(self, sock):
3480 """
Alex Chanb7480992017-01-30 14:04:47 +00003481 Create a new client-side SSL `Connection` object wrapped around `sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003482 """
3483 # Now create the client side Connection. Similar boilerplate to the
3484 # above.
Paul Kehrer688538c2020-08-03 19:18:15 -05003485 client_ctx = Context(SSLv23_METHOD)
Alex Gaynor43307782015-09-04 09:05:45 -04003486 client_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE)
Hynek Schlawack35618382015-09-05 21:54:25 +02003487 client_ctx.set_verify(
3488 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT | VERIFY_CLIENT_ONCE,
Alex Gaynor03737182020-07-23 20:40:46 -04003489 verify_cb,
Hynek Schlawack35618382015-09-05 21:54:25 +02003490 )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003491 client_store = client_ctx.get_cert_store()
Hynek Schlawack35618382015-09-05 21:54:25 +02003492 client_ctx.use_privatekey(
Alex Gaynor03737182020-07-23 20:40:46 -04003493 load_privatekey(FILETYPE_PEM, client_key_pem)
3494 )
Hynek Schlawack35618382015-09-05 21:54:25 +02003495 client_ctx.use_certificate(
Alex Gaynor03737182020-07-23 20:40:46 -04003496 load_certificate(FILETYPE_PEM, client_cert_pem)
3497 )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003498 client_ctx.check_privatekey()
3499 client_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05003500 client_conn = Connection(client_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003501 client_conn.set_connect_state()
3502 return client_conn
3503
Alex Chanb7480992017-01-30 14:04:47 +00003504 def test_memory_connect(self):
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003505 """
Alex Chanb7480992017-01-30 14:04:47 +00003506 Two `Connection`s which use memory BIOs can be manually connected by
3507 reading from the output of each and writing those bytes to the input of
3508 the other and in this way establish a connection and exchange
3509 application-level bytes with each other.
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003510 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003511 server_conn = self._server(None)
3512 client_conn = self._client(None)
Rick Deanb71c0d22009-04-01 14:09:23 -05003513
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003514 # There should be no key or nonces yet.
Alex Chanb7480992017-01-30 14:04:47 +00003515 assert server_conn.master_key() is None
3516 assert server_conn.client_random() is None
3517 assert server_conn.server_random() is None
Rick Deanb71c0d22009-04-01 14:09:23 -05003518
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003519 # First, the handshake needs to happen. We'll deliver bytes back and
3520 # forth between the client and server until neither of them feels like
3521 # speaking any more.
Alex Chanb7480992017-01-30 14:04:47 +00003522 assert interact_in_memory(client_conn, server_conn) is None
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003523
3524 # Now that the handshake is done, there should be a key and nonces.
Alex Chanb7480992017-01-30 14:04:47 +00003525 assert server_conn.master_key() is not None
3526 assert server_conn.client_random() is not None
3527 assert server_conn.server_random() is not None
3528 assert server_conn.client_random() == client_conn.client_random()
3529 assert server_conn.server_random() == client_conn.server_random()
3530 assert server_conn.client_random() != server_conn.server_random()
3531 assert client_conn.client_random() != client_conn.server_random()
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003532
Paul Kehrerbdb76392017-12-01 04:54:32 +08003533 # Export key material for other uses.
Alex Gaynor03737182020-07-23 20:40:46 -04003534 cekm = client_conn.export_keying_material(b"LABEL", 32)
3535 sekm = server_conn.export_keying_material(b"LABEL", 32)
Paul Kehrerbdb76392017-12-01 04:54:32 +08003536 assert cekm is not None
3537 assert sekm is not None
3538 assert cekm == sekm
3539 assert len(sekm) == 32
3540
3541 # Export key material for other uses with additional context.
Alex Gaynor03737182020-07-23 20:40:46 -04003542 cekmc = client_conn.export_keying_material(b"LABEL", 32, b"CONTEXT")
3543 sekmc = server_conn.export_keying_material(b"LABEL", 32, b"CONTEXT")
Paul Kehrerbdb76392017-12-01 04:54:32 +08003544 assert cekmc is not None
3545 assert sekmc is not None
3546 assert cekmc == sekmc
3547 assert cekmc != cekm
3548 assert sekmc != sekm
3549 # Export with alternate label
Alex Gaynor03737182020-07-23 20:40:46 -04003550 cekmt = client_conn.export_keying_material(b"test", 32, b"CONTEXT")
3551 sekmt = server_conn.export_keying_material(b"test", 32, b"CONTEXT")
Paul Kehrerbdb76392017-12-01 04:54:32 +08003552 assert cekmc != cekmt
3553 assert sekmc != sekmt
3554
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003555 # Here are the bytes we'll try to send.
Alex Gaynor03737182020-07-23 20:40:46 -04003556 important_message = b"One if by land, two if by sea."
Rick Deanb71c0d22009-04-01 14:09:23 -05003557
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003558 server_conn.write(important_message)
Alex Gaynor03737182020-07-23 20:40:46 -04003559 assert interact_in_memory(client_conn, server_conn) == (
3560 client_conn,
3561 important_message,
3562 )
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003563
3564 client_conn.write(important_message[::-1])
Alex Gaynor03737182020-07-23 20:40:46 -04003565 assert interact_in_memory(client_conn, server_conn) == (
3566 server_conn,
3567 important_message[::-1],
3568 )
Rick Deanb71c0d22009-04-01 14:09:23 -05003569
Alex Chanb7480992017-01-30 14:04:47 +00003570 def test_socket_connect(self):
Rick Deanb1ccd562009-07-09 23:52:39 -05003571 """
Alex Chanb7480992017-01-30 14:04:47 +00003572 Just like `test_memory_connect` but with an actual socket.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003573
Hynek Schlawack35618382015-09-05 21:54:25 +02003574 This is primarily to rule out the memory BIO code as the source of any
Alex Chanb7480992017-01-30 14:04:47 +00003575 problems encountered while passing data over a `Connection` (if
Hynek Schlawack35618382015-09-05 21:54:25 +02003576 this test fails, there must be a problem outside the memory BIO code,
3577 as no memory BIO is involved here). Even though this isn't a memory
3578 BIO test, it's convenient to have it here.
Rick Deanb1ccd562009-07-09 23:52:39 -05003579 """
Alex Chanb7480992017-01-30 14:04:47 +00003580 server_conn, client_conn = loopback()
Rick Deanb1ccd562009-07-09 23:52:39 -05003581
Alex Gaynore7f51982016-09-11 11:48:14 -04003582 important_message = b"Help me Obi Wan Kenobi, you're my only hope."
Rick Deanb1ccd562009-07-09 23:52:39 -05003583 client_conn.send(important_message)
3584 msg = server_conn.recv(1024)
Alex Chanb7480992017-01-30 14:04:47 +00003585 assert msg == important_message
Rick Deanb1ccd562009-07-09 23:52:39 -05003586
3587 # Again in the other direction, just for fun.
3588 important_message = important_message[::-1]
3589 server_conn.send(important_message)
3590 msg = client_conn.recv(1024)
Alex Chanb7480992017-01-30 14:04:47 +00003591 assert msg == important_message
Rick Deanb1ccd562009-07-09 23:52:39 -05003592
Alex Chanb7480992017-01-30 14:04:47 +00003593 def test_socket_overrides_memory(self):
Rick Deanb71c0d22009-04-01 14:09:23 -05003594 """
Alex Chanb7480992017-01-30 14:04:47 +00003595 Test that `OpenSSL.SSL.bio_read` and `OpenSSL.SSL.bio_write` don't
3596 work on `OpenSSL.SSL.Connection`() that use sockets.
Rick Deanb71c0d22009-04-01 14:09:23 -05003597 """
Paul Kehrer688538c2020-08-03 19:18:15 -05003598 context = Context(SSLv23_METHOD)
David Benjamin1fbe0642019-04-15 17:05:13 -05003599 client = socket_any_family()
Rick Deanb71c0d22009-04-01 14:09:23 -05003600 clientSSL = Connection(context, client)
Alex Chanb7480992017-01-30 14:04:47 +00003601 with pytest.raises(TypeError):
3602 clientSSL.bio_read(100)
3603 with pytest.raises(TypeError):
Paul Kehrerc45a6ea2020-08-03 15:54:20 -05003604 clientSSL.bio_write(b"foo")
Alex Chanb7480992017-01-30 14:04:47 +00003605 with pytest.raises(TypeError):
3606 clientSSL.bio_shutdown()
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003607
Alex Chanb7480992017-01-30 14:04:47 +00003608 def test_outgoing_overflow(self):
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003609 """
3610 If more bytes than can be written to the memory BIO are passed to
Alex Chanb7480992017-01-30 14:04:47 +00003611 `Connection.send` at once, the number of bytes which were written is
3612 returned and that many bytes from the beginning of the input can be
3613 read from the other end of the connection.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003614 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003615 server = self._server(None)
3616 client = self._client(None)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003617
Alex Chanb7480992017-01-30 14:04:47 +00003618 interact_in_memory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003619
3620 size = 2 ** 15
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003621 sent = client.send(b"x" * size)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003622 # Sanity check. We're trying to test what happens when the entire
3623 # input can't be sent. If the entire input was sent, this test is
3624 # meaningless.
Alex Chanb7480992017-01-30 14:04:47 +00003625 assert sent < size
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003626
Alex Chanb7480992017-01-30 14:04:47 +00003627 receiver, received = interact_in_memory(client, server)
3628 assert receiver is server
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003629
3630 # We can rely on all of these bytes being received at once because
Alex Chanb7480992017-01-30 14:04:47 +00003631 # loopback passes 2 ** 16 to recv - more than 2 ** 15.
3632 assert len(received) == sent
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003633
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003634 def test_shutdown(self):
3635 """
Alex Chanb7480992017-01-30 14:04:47 +00003636 `Connection.bio_shutdown` signals the end of the data stream
3637 from which the `Connection` reads.
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003638 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003639 server = self._server(None)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003640 server.bio_shutdown()
Alex Chanb7480992017-01-30 14:04:47 +00003641 with pytest.raises(Error) as err:
3642 server.recv(1024)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003643 # We don't want WantReadError or ZeroReturnError or anything - it's a
3644 # handshake failure.
Alex Chanb7480992017-01-30 14:04:47 +00003645 assert type(err.value) in [Error, SysCallError]
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003646
Alex Chanb7480992017-01-30 14:04:47 +00003647 def test_unexpected_EOF(self):
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003648 """
3649 If the connection is lost before an orderly SSL shutdown occurs,
Alex Chanb7480992017-01-30 14:04:47 +00003650 `OpenSSL.SSL.SysCallError` is raised with a message of
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003651 "Unexpected EOF".
3652 """
Alex Chanb7480992017-01-30 14:04:47 +00003653 server_conn, client_conn = loopback()
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003654 client_conn.sock_shutdown(SHUT_RDWR)
Alex Chanb7480992017-01-30 14:04:47 +00003655 with pytest.raises(SysCallError) as err:
3656 server_conn.recv(1024)
3657 assert err.value.args == (-1, "Unexpected EOF")
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003658
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003659 def _check_client_ca_list(self, func):
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003660 """
Alex Chanb7480992017-01-30 14:04:47 +00003661 Verify the return value of the `get_client_ca_list` method for
Hynek Schlawack35618382015-09-05 21:54:25 +02003662 server and client connections.
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003663
Jonathan Ballet78b92a22011-07-16 08:07:26 +09003664 :param func: A function which will be called with the server context
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003665 before the client and server are connected to each other. This
3666 function should specify a list of CAs for the server to send to the
3667 client and return that same list. The list will be used to verify
Alex Chanb7480992017-01-30 14:04:47 +00003668 that `get_client_ca_list` returns the proper value at
Hynek Schlawack35618382015-09-05 21:54:25 +02003669 various times.
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003670 """
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003671 server = self._server(None)
3672 client = self._client(None)
Alex Chanb7480992017-01-30 14:04:47 +00003673 assert client.get_client_ca_list() == []
3674 assert server.get_client_ca_list() == []
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003675 ctx = server.get_context()
3676 expected = func(ctx)
Alex Chanb7480992017-01-30 14:04:47 +00003677 assert client.get_client_ca_list() == []
3678 assert server.get_client_ca_list() == expected
3679 interact_in_memory(client, server)
3680 assert client.get_client_ca_list() == expected
3681 assert server.get_client_ca_list() == expected
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003682
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003683 def test_set_client_ca_list_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003684 """
Alex Chanb7480992017-01-30 14:04:47 +00003685 `Context.set_client_ca_list` raises a `TypeError` if called with a
3686 non-list or a list that contains objects other than X509Names.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003687 """
Paul Kehrer688538c2020-08-03 19:18:15 -05003688 ctx = Context(SSLv23_METHOD)
Alex Chanb7480992017-01-30 14:04:47 +00003689 with pytest.raises(TypeError):
3690 ctx.set_client_ca_list("spam")
3691 with pytest.raises(TypeError):
3692 ctx.set_client_ca_list(["spam"])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003693
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003694 def test_set_empty_ca_list(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003695 """
Alex Chanb7480992017-01-30 14:04:47 +00003696 If passed an empty list, `Context.set_client_ca_list` configures the
3697 context to send no CA names to the client and, on both the server and
3698 client sides, `Connection.get_client_ca_list` returns an empty list
3699 after the connection is set up.
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003700 """
Alex Gaynor03737182020-07-23 20:40:46 -04003701
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003702 def no_ca(ctx):
3703 ctx.set_client_ca_list([])
3704 return []
Alex Gaynor03737182020-07-23 20:40:46 -04003705
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003706 self._check_client_ca_list(no_ca)
3707
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003708 def test_set_one_ca_list(self):
3709 """
3710 If passed a list containing a single X509Name,
Alex Chanb7480992017-01-30 14:04:47 +00003711 `Context.set_client_ca_list` configures the context to send
Hynek Schlawack35618382015-09-05 21:54:25 +02003712 that CA name to the client and, on both the server and client sides,
Alex Chanb7480992017-01-30 14:04:47 +00003713 `Connection.get_client_ca_list` returns a list containing that
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003714 X509Name after the connection is set up.
3715 """
3716 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3717 cadesc = cacert.get_subject()
Hynek Schlawack35618382015-09-05 21:54:25 +02003718
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003719 def single_ca(ctx):
3720 ctx.set_client_ca_list([cadesc])
3721 return [cadesc]
Alex Gaynor03737182020-07-23 20:40:46 -04003722
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003723 self._check_client_ca_list(single_ca)
3724
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003725 def test_set_multiple_ca_list(self):
3726 """
3727 If passed a list containing multiple X509Name objects,
Alex Chanb7480992017-01-30 14:04:47 +00003728 `Context.set_client_ca_list` configures the context to send
Hynek Schlawack35618382015-09-05 21:54:25 +02003729 those CA names to the client and, on both the server and client sides,
Alex Chanb7480992017-01-30 14:04:47 +00003730 `Connection.get_client_ca_list` returns a list containing those
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003731 X509Names after the connection is set up.
3732 """
3733 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3734 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3735
3736 sedesc = secert.get_subject()
3737 cldesc = clcert.get_subject()
3738
3739 def multiple_ca(ctx):
3740 L = [sedesc, cldesc]
3741 ctx.set_client_ca_list(L)
3742 return L
Alex Gaynor03737182020-07-23 20:40:46 -04003743
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003744 self._check_client_ca_list(multiple_ca)
3745
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003746 def test_reset_ca_list(self):
3747 """
3748 If called multiple times, only the X509Names passed to the final call
Alex Chanb7480992017-01-30 14:04:47 +00003749 of `Context.set_client_ca_list` are used to configure the CA
Hynek Schlawack35618382015-09-05 21:54:25 +02003750 names sent to the client.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003751 """
3752 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3753 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3754 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3755
3756 cadesc = cacert.get_subject()
3757 sedesc = secert.get_subject()
3758 cldesc = clcert.get_subject()
3759
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003760 def changed_ca(ctx):
3761 ctx.set_client_ca_list([sedesc, cldesc])
3762 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003763 return [cadesc]
Alex Gaynor03737182020-07-23 20:40:46 -04003764
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003765 self._check_client_ca_list(changed_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003766
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003767 def test_mutated_ca_list(self):
3768 """
Alex Chanb7480992017-01-30 14:04:47 +00003769 If the list passed to `Context.set_client_ca_list` is mutated
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003770 afterwards, this does not affect the list of CA names sent to the
3771 client.
3772 """
3773 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3774 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3775
3776 cadesc = cacert.get_subject()
3777 sedesc = secert.get_subject()
3778
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003779 def mutated_ca(ctx):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003780 L = [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003781 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003782 L.append(sedesc)
3783 return [cadesc]
Alex Gaynor03737182020-07-23 20:40:46 -04003784
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003785 self._check_client_ca_list(mutated_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003786
Alex Chanb7480992017-01-30 14:04:47 +00003787 def test_add_client_ca_wrong_args(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003788 """
Alex Chanb7480992017-01-30 14:04:47 +00003789 `Context.add_client_ca` raises `TypeError` if called with
3790 a non-X509 object.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003791 """
Paul Kehrer688538c2020-08-03 19:18:15 -05003792 ctx = Context(SSLv23_METHOD)
Alex Chanb7480992017-01-30 14:04:47 +00003793 with pytest.raises(TypeError):
3794 ctx.add_client_ca("spam")
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003795
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003796 def test_one_add_client_ca(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003797 """
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003798 A certificate's subject can be added as a CA to be sent to the client
Alex Chanb7480992017-01-30 14:04:47 +00003799 with `Context.add_client_ca`.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003800 """
3801 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3802 cadesc = cacert.get_subject()
Hynek Schlawack35618382015-09-05 21:54:25 +02003803
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003804 def single_ca(ctx):
3805 ctx.add_client_ca(cacert)
3806 return [cadesc]
Alex Gaynor03737182020-07-23 20:40:46 -04003807
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003808 self._check_client_ca_list(single_ca)
3809
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003810 def test_multiple_add_client_ca(self):
3811 """
3812 Multiple CA names can be sent to the client by calling
Alex Chanb7480992017-01-30 14:04:47 +00003813 `Context.add_client_ca` with multiple X509 objects.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003814 """
3815 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3816 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3817
3818 cadesc = cacert.get_subject()
3819 sedesc = secert.get_subject()
3820
3821 def multiple_ca(ctx):
3822 ctx.add_client_ca(cacert)
3823 ctx.add_client_ca(secert)
3824 return [cadesc, sedesc]
Alex Gaynor03737182020-07-23 20:40:46 -04003825
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003826 self._check_client_ca_list(multiple_ca)
3827
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003828 def test_set_and_add_client_ca(self):
3829 """
Alex Chanb7480992017-01-30 14:04:47 +00003830 A call to `Context.set_client_ca_list` followed by a call to
3831 `Context.add_client_ca` results in using the CA names from the
Hynek Schlawack35618382015-09-05 21:54:25 +02003832 first call and the CA name from the second call.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003833 """
3834 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3835 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3836 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3837
3838 cadesc = cacert.get_subject()
3839 sedesc = secert.get_subject()
3840 cldesc = clcert.get_subject()
3841
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003842 def mixed_set_add_ca(ctx):
3843 ctx.set_client_ca_list([cadesc, sedesc])
3844 ctx.add_client_ca(clcert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003845 return [cadesc, sedesc, cldesc]
Alex Gaynor03737182020-07-23 20:40:46 -04003846
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003847 self._check_client_ca_list(mixed_set_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003848
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003849 def test_set_after_add_client_ca(self):
3850 """
Alex Chanb7480992017-01-30 14:04:47 +00003851 A call to `Context.set_client_ca_list` after a call to
3852 `Context.add_client_ca` replaces the CA name specified by the
Hynek Schlawack35618382015-09-05 21:54:25 +02003853 former call with the names specified by the latter call.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003854 """
3855 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3856 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3857 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3858
3859 cadesc = cacert.get_subject()
3860 sedesc = secert.get_subject()
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003861
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003862 def set_replaces_add_ca(ctx):
3863 ctx.add_client_ca(clcert)
3864 ctx.set_client_ca_list([cadesc])
3865 ctx.add_client_ca(secert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003866 return [cadesc, sedesc]
Alex Gaynor03737182020-07-23 20:40:46 -04003867
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003868 self._check_client_ca_list(set_replaces_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003869
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003870
Alex Chanb7480992017-01-30 14:04:47 +00003871class TestInfoConstants(object):
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003872 """
3873 Tests for assorted constants exposed for use in info callbacks.
3874 """
Alex Gaynor03737182020-07-23 20:40:46 -04003875
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003876 def test_integers(self):
3877 """
3878 All of the info constants are integers.
3879
3880 This is a very weak test. It would be nice to have one that actually
3881 verifies that as certain info events happen, the value passed to the
3882 info callback matches up with the constant exposed by OpenSSL.SSL.
3883 """
3884 for const in [
Alex Gaynor03737182020-07-23 20:40:46 -04003885 SSL_ST_CONNECT,
3886 SSL_ST_ACCEPT,
3887 SSL_ST_MASK,
3888 SSL_CB_LOOP,
3889 SSL_CB_EXIT,
3890 SSL_CB_READ,
3891 SSL_CB_WRITE,
3892 SSL_CB_ALERT,
3893 SSL_CB_READ_ALERT,
3894 SSL_CB_WRITE_ALERT,
3895 SSL_CB_ACCEPT_LOOP,
3896 SSL_CB_ACCEPT_EXIT,
3897 SSL_CB_CONNECT_LOOP,
3898 SSL_CB_CONNECT_EXIT,
3899 SSL_CB_HANDSHAKE_START,
3900 SSL_CB_HANDSHAKE_DONE,
Hynek Schlawack35618382015-09-05 21:54:25 +02003901 ]:
Alex Gaynor5af32d02016-09-24 01:52:21 -04003902 assert isinstance(const, int)
3903
3904 # These constants don't exist on OpenSSL 1.1.0
3905 for const in [
Alex Gaynor03737182020-07-23 20:40:46 -04003906 SSL_ST_INIT,
3907 SSL_ST_BEFORE,
3908 SSL_ST_OK,
3909 SSL_ST_RENEGOTIATE,
Alex Gaynor5af32d02016-09-24 01:52:21 -04003910 ]:
3911 assert const is None or isinstance(const, int)
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003912
Ziga Seilnacht44611bf2009-08-31 20:49:30 +02003913
Cory Benfield1d142142016-03-30 11:51:45 +01003914class TestRequires(object):
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003915 """
3916 Tests for the decorator factory used to conditionally raise
Cory Benfield1d142142016-03-30 11:51:45 +01003917 NotImplementedError when older OpenSSLs are used.
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003918 """
Alex Gaynor03737182020-07-23 20:40:46 -04003919
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003920 def test_available(self):
3921 """
3922 When the OpenSSL functionality is available the decorated functions
3923 work appropriately.
3924 """
3925 feature_guard = _make_requires(True, "Error text")
3926 results = []
3927
3928 @feature_guard
3929 def inner():
3930 results.append(True)
3931 return True
3932
Cory Benfield2333e5e2016-03-30 14:24:16 +01003933 assert inner() is True
3934 assert [True] == results
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003935
3936 def test_unavailable(self):
3937 """
3938 When the OpenSSL functionality is not available the decorated function
3939 does not execute and NotImplementedError is raised.
3940 """
3941 feature_guard = _make_requires(False, "Error text")
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003942
3943 @feature_guard
Alex Chanfb078d82017-04-20 11:16:15 +01003944 def inner(): # pragma: nocover
3945 pytest.fail("Should not be called")
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003946
Cory Benfield1d142142016-03-30 11:51:45 +01003947 with pytest.raises(NotImplementedError) as e:
3948 inner()
3949
3950 assert "Error text" in str(e.value)
Cory Benfield496652a2017-01-24 11:42:56 +00003951
3952
Alex Chanb7480992017-01-30 14:04:47 +00003953class TestOCSP(object):
Cory Benfield496652a2017-01-24 11:42:56 +00003954 """
3955 Tests for PyOpenSSL's OCSP stapling support.
3956 """
Alex Gaynor03737182020-07-23 20:40:46 -04003957
Cory Benfield496652a2017-01-24 11:42:56 +00003958 sample_ocsp_data = b"this is totally ocsp data"
3959
3960 def _client_connection(self, callback, data, request_ocsp=True):
3961 """
3962 Builds a client connection suitable for using OCSP.
3963
3964 :param callback: The callback to register for OCSP.
3965 :param data: The opaque data object that will be handed to the
3966 OCSP callback.
3967 :param request_ocsp: Whether the client will actually ask for OCSP
3968 stapling. Useful for testing only.
3969 """
3970 ctx = Context(SSLv23_METHOD)
3971 ctx.set_ocsp_client_callback(callback, data)
3972 client = Connection(ctx)
3973
3974 if request_ocsp:
3975 client.request_ocsp()
3976
3977 client.set_connect_state()
3978 return client
3979
3980 def _server_connection(self, callback, data):
3981 """
3982 Builds a server connection suitable for using OCSP.
3983
3984 :param callback: The callback to register for OCSP.
3985 :param data: The opaque data object that will be handed to the
3986 OCSP callback.
3987 """
3988 ctx = Context(SSLv23_METHOD)
3989 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
3990 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
3991 ctx.set_ocsp_server_callback(callback, data)
3992 server = Connection(ctx)
3993 server.set_accept_state()
3994 return server
3995
3996 def test_callbacks_arent_called_by_default(self):
3997 """
3998 If both the client and the server have registered OCSP callbacks, but
3999 the client does not send the OCSP request, neither callback gets
4000 called.
4001 """
Alex Gaynor03737182020-07-23 20:40:46 -04004002
Alex Chanfb078d82017-04-20 11:16:15 +01004003 def ocsp_callback(*args, **kwargs): # pragma: nocover
4004 pytest.fail("Should not be called")
Cory Benfield496652a2017-01-24 11:42:56 +00004005
4006 client = self._client_connection(
4007 callback=ocsp_callback, data=None, request_ocsp=False
4008 )
4009 server = self._server_connection(callback=ocsp_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00004010 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00004011
Cory Benfield496652a2017-01-24 11:42:56 +00004012 def test_client_negotiates_without_server(self):
4013 """
4014 If the client wants to do OCSP but the server does not, the handshake
4015 succeeds, and the client callback fires with an empty byte string.
4016 """
4017 called = []
4018
4019 def ocsp_callback(conn, ocsp_data, ignored):
4020 called.append(ocsp_data)
4021 return True
4022
4023 client = self._client_connection(callback=ocsp_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00004024 server = loopback_server_factory(socket=None)
4025 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00004026
4027 assert len(called) == 1
Alex Gaynor03737182020-07-23 20:40:46 -04004028 assert called[0] == b""
Cory Benfield496652a2017-01-24 11:42:56 +00004029
4030 def test_client_receives_servers_data(self):
4031 """
4032 The data the server sends in its callback is received by the client.
4033 """
4034 calls = []
4035
4036 def server_callback(*args, **kwargs):
4037 return self.sample_ocsp_data
4038
4039 def client_callback(conn, ocsp_data, ignored):
4040 calls.append(ocsp_data)
4041 return True
4042
4043 client = self._client_connection(callback=client_callback, data=None)
4044 server = self._server_connection(callback=server_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00004045 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00004046
4047 assert len(calls) == 1
4048 assert calls[0] == self.sample_ocsp_data
4049
4050 def test_callbacks_are_invoked_with_connections(self):
4051 """
4052 The first arguments to both callbacks are their respective connections.
4053 """
4054 client_calls = []
4055 server_calls = []
4056
4057 def client_callback(conn, *args, **kwargs):
4058 client_calls.append(conn)
4059 return True
4060
4061 def server_callback(conn, *args, **kwargs):
4062 server_calls.append(conn)
4063 return self.sample_ocsp_data
4064
4065 client = self._client_connection(callback=client_callback, data=None)
4066 server = self._server_connection(callback=server_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00004067 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00004068
4069 assert len(client_calls) == 1
4070 assert len(server_calls) == 1
4071 assert client_calls[0] is client
4072 assert server_calls[0] is server
4073
4074 def test_opaque_data_is_passed_through(self):
4075 """
4076 Both callbacks receive an opaque, user-provided piece of data in their
4077 callbacks as the final argument.
4078 """
4079 calls = []
4080
4081 def server_callback(*args):
4082 calls.append(args)
4083 return self.sample_ocsp_data
4084
4085 def client_callback(*args):
4086 calls.append(args)
4087 return True
4088
4089 sentinel = object()
4090
4091 client = self._client_connection(
4092 callback=client_callback, data=sentinel
4093 )
4094 server = self._server_connection(
4095 callback=server_callback, data=sentinel
4096 )
Alex Chanb7480992017-01-30 14:04:47 +00004097 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00004098
4099 assert len(calls) == 2
4100 assert calls[0][-1] is sentinel
4101 assert calls[1][-1] is sentinel
4102
4103 def test_server_returns_empty_string(self):
4104 """
4105 If the server returns an empty bytestring from its callback, the
4106 client callback is called with the empty bytestring.
4107 """
4108 client_calls = []
4109
4110 def server_callback(*args):
Alex Gaynor03737182020-07-23 20:40:46 -04004111 return b""
Cory Benfield496652a2017-01-24 11:42:56 +00004112
4113 def client_callback(conn, ocsp_data, ignored):
4114 client_calls.append(ocsp_data)
4115 return True
4116
4117 client = self._client_connection(callback=client_callback, data=None)
4118 server = self._server_connection(callback=server_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00004119 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00004120
4121 assert len(client_calls) == 1
Alex Gaynor03737182020-07-23 20:40:46 -04004122 assert client_calls[0] == b""
Cory Benfield496652a2017-01-24 11:42:56 +00004123
4124 def test_client_returns_false_terminates_handshake(self):
4125 """
4126 If the client returns False from its callback, the handshake fails.
4127 """
Alex Gaynor03737182020-07-23 20:40:46 -04004128
Cory Benfield496652a2017-01-24 11:42:56 +00004129 def server_callback(*args):
4130 return self.sample_ocsp_data
4131
4132 def client_callback(*args):
4133 return False
4134
4135 client = self._client_connection(callback=client_callback, data=None)
4136 server = self._server_connection(callback=server_callback, data=None)
4137
4138 with pytest.raises(Error):
Alex Chanb7480992017-01-30 14:04:47 +00004139 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00004140
4141 def test_exceptions_in_client_bubble_up(self):
4142 """
4143 The callbacks thrown in the client callback bubble up to the caller.
4144 """
Alex Gaynor03737182020-07-23 20:40:46 -04004145
Cory Benfield496652a2017-01-24 11:42:56 +00004146 class SentinelException(Exception):
4147 pass
4148
4149 def server_callback(*args):
4150 return self.sample_ocsp_data
4151
4152 def client_callback(*args):
4153 raise SentinelException()
4154
4155 client = self._client_connection(callback=client_callback, data=None)
4156 server = self._server_connection(callback=server_callback, data=None)
4157
4158 with pytest.raises(SentinelException):
Alex Chanb7480992017-01-30 14:04:47 +00004159 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00004160
4161 def test_exceptions_in_server_bubble_up(self):
4162 """
4163 The callbacks thrown in the server callback bubble up to the caller.
4164 """
Alex Gaynor03737182020-07-23 20:40:46 -04004165
Cory Benfield496652a2017-01-24 11:42:56 +00004166 class SentinelException(Exception):
4167 pass
4168
4169 def server_callback(*args):
4170 raise SentinelException()
4171
Alex Chanfb078d82017-04-20 11:16:15 +01004172 def client_callback(*args): # pragma: nocover
Cory Benfield496652a2017-01-24 11:42:56 +00004173 pytest.fail("Should not be called")
4174
4175 client = self._client_connection(callback=client_callback, data=None)
4176 server = self._server_connection(callback=server_callback, data=None)
4177
4178 with pytest.raises(SentinelException):
Alex Chanb7480992017-01-30 14:04:47 +00004179 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00004180
4181 def test_server_must_return_bytes(self):
4182 """
4183 The server callback must return a bytestring, or a TypeError is thrown.
4184 """
Alex Gaynor03737182020-07-23 20:40:46 -04004185
Cory Benfield496652a2017-01-24 11:42:56 +00004186 def server_callback(*args):
Alex Gaynor03737182020-07-23 20:40:46 -04004187 return self.sample_ocsp_data.decode("ascii")
Cory Benfield496652a2017-01-24 11:42:56 +00004188
Alex Chanfb078d82017-04-20 11:16:15 +01004189 def client_callback(*args): # pragma: nocover
Cory Benfield496652a2017-01-24 11:42:56 +00004190 pytest.fail("Should not be called")
4191
4192 client = self._client_connection(callback=client_callback, data=None)
4193 server = self._server_connection(callback=server_callback, data=None)
4194
4195 with pytest.raises(TypeError):
Alex Chanb7480992017-01-30 14:04:47 +00004196 handshake_in_memory(client, server)