blob: 7704c72a0907aa76923c741f181117d29706c3d6 [file] [log] [blame]
Jean-Paul Calderone8671c852011-03-02 19:26:20 -05001# Copyright (C) Jean-Paul Calderone
2# See LICENSE for details.
Jean-Paul Calderone8b63d452008-03-21 18:31:12 -04003
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -04004"""
Hynek Schlawackf90e3682016-03-11 11:21:13 +01005Unit tests for :mod:`OpenSSL.SSL`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -04006"""
7
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01008import datetime
Maximilian Hils868dc3c2017-02-10 14:56:55 +01009import sys
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +010010import uuid
11
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -050012from gc import collect, get_referrers
David Benjamin1fbe0642019-04-15 17:05:13 -050013from errno import (
14 EAFNOSUPPORT, ECONNREFUSED, EINPROGRESS, EWOULDBLOCK, EPIPE, ESHUTDOWN)
Jeremy Lainé1ae7cb62018-03-21 14:49:42 +010015from sys import platform, getfilesystemencoding
David Benjamin1fbe0642019-04-15 17:05:13 -050016from socket import AF_INET, AF_INET6, MSG_PEEK, SHUT_RDWR, error, socket
Jean-Paul Calderonea65cf6c2009-07-19 10:26:52 -040017from os import makedirs
Jean-Paul Calderone1461c492013-10-03 16:05:00 -040018from os.path import join
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -040019from weakref import ref
Alex Chanb7480992017-01-30 14:04:47 +000020from warnings import simplefilter
Jean-Paul Calderone460cc1f2009-03-07 11:31:12 -050021
Alex Gaynor963ae032019-07-06 17:38:32 -040022import flaky
23
Hynek Schlawack734d3022015-09-05 19:19:32 +020024import pytest
25
Paul Kehrer55fb3412017-06-29 18:44:08 -050026from pretend import raiser
27
Hynek Schlawackf90e3682016-03-11 11:21:13 +010028from six import PY3, text_type
Jean-Paul Calderonec76c61c2014-01-18 13:21:52 -050029
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +010030from cryptography import x509
31from cryptography.hazmat.backends import default_backend
32from cryptography.hazmat.primitives import hashes
33from cryptography.hazmat.primitives import serialization
34from cryptography.hazmat.primitives.asymmetric import rsa
35from cryptography.x509.oid import NameOID
36
37
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040038from OpenSSL.crypto import TYPE_RSA, FILETYPE_PEM
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -080039from OpenSSL.crypto import PKey, X509, X509Extension, X509Store
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040040from OpenSSL.crypto import dump_privatekey, load_privatekey
41from OpenSSL.crypto import dump_certificate, load_certificate
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -040042from OpenSSL.crypto import get_elliptic_curves
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040043
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -040044from OpenSSL.SSL import OPENSSL_VERSION_NUMBER, SSLEAY_VERSION, SSLEAY_CFLAGS
45from OpenSSL.SSL import SSLEAY_PLATFORM, SSLEAY_DIR, SSLEAY_BUILT_ON
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -040046from OpenSSL.SSL import SENT_SHUTDOWN, RECEIVED_SHUTDOWN
Jean-Paul Calderone1461c492013-10-03 16:05:00 -040047from OpenSSL.SSL import (
48 SSLv2_METHOD, SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD,
49 TLSv1_1_METHOD, TLSv1_2_METHOD)
50from OpenSSL.SSL import OP_SINGLE_DH_USE, OP_NO_SSLv2, OP_NO_SSLv3
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040051from OpenSSL.SSL import (
52 VERIFY_PEER, VERIFY_FAIL_IF_NO_PEER_CERT, VERIFY_CLIENT_ONCE, VERIFY_NONE)
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040053
Paul Kehrer55fb3412017-06-29 18:44:08 -050054from OpenSSL import SSL
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040055from OpenSSL.SSL import (
Jean-Paul Calderone313bf012012-02-08 13:02:49 -050056 SESS_CACHE_OFF, SESS_CACHE_CLIENT, SESS_CACHE_SERVER, SESS_CACHE_BOTH,
57 SESS_CACHE_NO_AUTO_CLEAR, SESS_CACHE_NO_INTERNAL_LOOKUP,
58 SESS_CACHE_NO_INTERNAL_STORE, SESS_CACHE_NO_INTERNAL)
59
60from OpenSSL.SSL import (
Jean-Paul Calderoned899af02013-03-19 22:10:37 -070061 Error, SysCallError, WantReadError, WantWriteError, ZeroReturnError)
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -050062from OpenSSL.SSL import (
Alex Gaynor01f90a12019-02-07 09:14:48 -050063 Context, Session, Connection, SSLeay_version)
Cory Benfield0ba57ec2016-03-30 09:35:05 +010064from OpenSSL.SSL import _make_requires
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040065
Paul Kehrer55fb3412017-06-29 18:44:08 -050066from OpenSSL._util import ffi as _ffi, lib as _lib
Cory Benfieldba1820d2015-04-13 17:39:12 -040067
Alex Gaynord3b5d9b2016-07-31 10:54:24 -040068from OpenSSL.SSL import (
69 OP_NO_QUERY_MTU, OP_COOKIE_EXCHANGE, OP_NO_TICKET, OP_NO_COMPRESSION,
70 MODE_RELEASE_BUFFERS)
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040071
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -040072from OpenSSL.SSL import (
Alex Gaynor5af32d02016-09-24 01:52:21 -040073 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK,
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -040074 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
75 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
76 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
77 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE)
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -040078
Alex Gaynor5af32d02016-09-24 01:52:21 -040079try:
80 from OpenSSL.SSL import (
81 SSL_ST_INIT, SSL_ST_BEFORE, SSL_ST_OK, SSL_ST_RENEGOTIATE
82 )
83except ImportError:
84 SSL_ST_INIT = SSL_ST_BEFORE = SSL_ST_OK = SSL_ST_RENEGOTIATE = None
85
Alex Chanb7480992017-01-30 14:04:47 +000086from .util import WARNING_TYPE_EXPECTED, NON_ASCII, is_consistent_type
Hynek Schlawackf0e66852015-10-16 20:18:38 +020087from .test_crypto import (
88 cleartextCertificatePEM, cleartextPrivateKeyPEM,
89 client_cert_pem, client_key_pem, server_cert_pem, server_key_pem,
90 root_cert_pem)
91
Hynek Schlawackde00dd52015-09-05 19:09:26 +020092
Alex Gaynord0bdd2d2016-09-10 14:23:46 -040093# openssl dhparam 1024 -out dh-1024.pem (note that 1024 is a small number of
94# bits to use)
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -040095dhparam = """\
96-----BEGIN DH PARAMETERS-----
Alex Gaynord0bdd2d2016-09-10 14:23:46 -040097MIGHAoGBALdUMvn+C9MM+y5BWZs11mSeH6HHoEq0UVbzVq7UojC1hbsZUuGukQ3a
98Qh2/pwqb18BZFykrWB0zv/OkLa0kx4cuUgNrUVq1EFheBiX6YqryJ7t2sO09NQiO
99V7H54LmltOT/hEh6QWsJqb6BQgH65bswvV/XkYGja8/T0GzvbaVzAgEC
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -0400100-----END DH PARAMETERS-----
101"""
102
103
Hynek Schlawackb4f02402015-09-05 20:48:34 +0200104skip_if_py3 = pytest.mark.skipif(PY3, reason="Python 2 only")
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200105
106
David Benjamin1fbe0642019-04-15 17:05:13 -0500107def socket_any_family():
108 try:
109 return socket(AF_INET)
110 except error as e:
111 if e.errno == EAFNOSUPPORT:
112 return socket(AF_INET6)
113 raise
114
115
116def loopback_address(socket):
117 if socket.family == AF_INET:
118 return "127.0.0.1"
119 else:
120 assert socket.family == AF_INET6
121 return "::1"
122
123
Jean-Paul Calderone05826732015-04-12 11:38:49 -0400124def join_bytes_or_unicode(prefix, suffix):
125 """
126 Join two path components of either ``bytes`` or ``unicode``.
127
128 The return type is the same as the type of ``prefix``.
129 """
130 # If the types are the same, nothing special is necessary.
131 if type(prefix) == type(suffix):
132 return join(prefix, suffix)
133
134 # Otherwise, coerce suffix to the type of prefix.
135 if isinstance(prefix, text_type):
136 return join(prefix, suffix.decode(getfilesystemencoding()))
137 else:
138 return join(prefix, suffix.encode(getfilesystemencoding()))
139
140
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400141def verify_cb(conn, cert, errnum, depth, ok):
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400142 return ok
143
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400144
Rick Deanb1ccd562009-07-09 23:52:39 -0500145def socket_pair():
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400146 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400147 Establish and return a pair of network sockets connected to each other.
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400148 """
149 # Connect a pair of sockets
David Benjamin1fbe0642019-04-15 17:05:13 -0500150 port = socket_any_family()
Rick Deanb1ccd562009-07-09 23:52:39 -0500151 port.bind(('', 0))
152 port.listen(1)
David Benjamin1fbe0642019-04-15 17:05:13 -0500153 client = socket(port.family)
Rick Deanb1ccd562009-07-09 23:52:39 -0500154 client.setblocking(False)
David Benjamin1fbe0642019-04-15 17:05:13 -0500155 client.connect_ex((loopback_address(port), port.getsockname()[1]))
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400156 client.setblocking(True)
Rick Deanb1ccd562009-07-09 23:52:39 -0500157 server = port.accept()[0]
Rick Deanb1ccd562009-07-09 23:52:39 -0500158
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400159 # Let's pass some unencrypted data to make sure our socket connection is
160 # fine. Just one byte, so we don't have to worry about buffers getting
161 # filled up or fragmentation.
Alex Gaynore7f51982016-09-11 11:48:14 -0400162 server.send(b"x")
163 assert client.recv(1024) == b"x"
164 client.send(b"y")
165 assert server.recv(1024) == b"y"
Rick Deanb1ccd562009-07-09 23:52:39 -0500166
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -0400167 # Most of our callers want non-blocking sockets, make it easy for them.
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400168 server.setblocking(False)
169 client.setblocking(False)
Jim Shaver46f28912015-05-29 19:32:16 -0400170
Rick Deanb1ccd562009-07-09 23:52:39 -0500171 return (server, client)
172
173
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400174def handshake(client, server):
175 conns = [client, server]
176 while conns:
177 for conn in conns:
178 try:
179 conn.do_handshake()
180 except WantReadError:
181 pass
182 else:
183 conns.remove(conn)
184
185
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400186def _create_certificate_chain():
187 """
188 Construct and return a chain of certificates.
189
190 1. A new self-signed certificate authority certificate (cacert)
191 2. A new intermediate certificate signed by cacert (icert)
192 3. A new server certificate signed by icert (scert)
193 """
Alex Gaynore7f51982016-09-11 11:48:14 -0400194 caext = X509Extension(b'basicConstraints', False, b'CA:true')
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400195
196 # Step 1
197 cakey = PKey()
Alex Gaynor0737a5e2016-09-10 14:35:09 -0400198 cakey.generate_key(TYPE_RSA, 1024)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400199 cacert = X509()
200 cacert.get_subject().commonName = "Authority Certificate"
201 cacert.set_issuer(cacert.get_subject())
202 cacert.set_pubkey(cakey)
Alex Gaynore7f51982016-09-11 11:48:14 -0400203 cacert.set_notBefore(b"20000101000000Z")
204 cacert.set_notAfter(b"20200101000000Z")
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400205 cacert.add_extensions([caext])
206 cacert.set_serial_number(0)
207 cacert.sign(cakey, "sha1")
208
209 # Step 2
210 ikey = PKey()
Alex Gaynor0737a5e2016-09-10 14:35:09 -0400211 ikey.generate_key(TYPE_RSA, 1024)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400212 icert = X509()
213 icert.get_subject().commonName = "Intermediate Certificate"
214 icert.set_issuer(cacert.get_subject())
215 icert.set_pubkey(ikey)
Alex Gaynore7f51982016-09-11 11:48:14 -0400216 icert.set_notBefore(b"20000101000000Z")
217 icert.set_notAfter(b"20200101000000Z")
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400218 icert.add_extensions([caext])
219 icert.set_serial_number(0)
220 icert.sign(cakey, "sha1")
221
222 # Step 3
223 skey = PKey()
Alex Gaynor0737a5e2016-09-10 14:35:09 -0400224 skey.generate_key(TYPE_RSA, 1024)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400225 scert = X509()
226 scert.get_subject().commonName = "Server Certificate"
227 scert.set_issuer(icert.get_subject())
228 scert.set_pubkey(skey)
Alex Gaynore7f51982016-09-11 11:48:14 -0400229 scert.set_notBefore(b"20000101000000Z")
230 scert.set_notAfter(b"20200101000000Z")
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400231 scert.add_extensions([
Alex Gaynore7f51982016-09-11 11:48:14 -0400232 X509Extension(b'basicConstraints', True, b'CA:false')])
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400233 scert.set_serial_number(0)
234 scert.sign(ikey, "sha1")
235
236 return [(cakey, cacert), (ikey, icert), (skey, scert)]
237
238
Paul Kehrer7d5a3bf2019-01-21 12:24:02 -0600239def loopback_client_factory(socket, version=SSLv23_METHOD):
240 client = Connection(Context(version), socket)
Alex Chan1c0cb662017-01-30 07:13:30 +0000241 client.set_connect_state()
242 return client
243
244
Paul Kehrer7d5a3bf2019-01-21 12:24:02 -0600245def loopback_server_factory(socket, version=SSLv23_METHOD):
246 ctx = Context(version)
Alex Chan1c0cb662017-01-30 07:13:30 +0000247 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
248 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
249 server = Connection(ctx, socket)
250 server.set_accept_state()
251 return server
252
253
254def loopback(server_factory=None, client_factory=None):
255 """
256 Create a connected socket pair and force two connected SSL sockets
257 to talk to each other via memory BIOs.
258 """
259 if server_factory is None:
260 server_factory = loopback_server_factory
261 if client_factory is None:
262 client_factory = loopback_client_factory
263
264 (server, client) = socket_pair()
265 server = server_factory(server)
266 client = client_factory(client)
267
268 handshake(client, server)
269
270 server.setblocking(True)
271 client.setblocking(True)
272 return server, client
273
274
Alex Chan1ca9e3a2016-11-05 13:01:51 +0000275def interact_in_memory(client_conn, server_conn):
276 """
277 Try to read application bytes from each of the two `Connection` objects.
278 Copy bytes back and forth between their send/receive buffers for as long
279 as there is anything to copy. When there is nothing more to copy,
280 return `None`. If one of them actually manages to deliver some application
281 bytes, return a two-tuple of the connection from which the bytes were read
282 and the bytes themselves.
283 """
284 wrote = True
285 while wrote:
286 # Loop until neither side has anything to say
287 wrote = False
288
289 # Copy stuff from each side's send buffer to the other side's
290 # receive buffer.
291 for (read, write) in [(client_conn, server_conn),
292 (server_conn, client_conn)]:
293
294 # Give the side a chance to generate some more bytes, or succeed.
295 try:
296 data = read.recv(2 ** 16)
297 except WantReadError:
298 # It didn't succeed, so we'll hope it generated some output.
299 pass
300 else:
301 # It did succeed, so we'll stop now and let the caller deal
302 # with it.
303 return (read, data)
304
305 while True:
306 # Keep copying as long as there's more stuff there.
307 try:
308 dirty = read.bio_read(4096)
309 except WantReadError:
310 # Okay, nothing more waiting to be sent. Stop
311 # processing this send buffer.
312 break
313 else:
314 # Keep track of the fact that someone generated some
315 # output.
316 wrote = True
317 write.bio_write(dirty)
318
319
Alex Chan532b79e2017-01-24 15:14:52 +0000320def handshake_in_memory(client_conn, server_conn):
321 """
322 Perform the TLS handshake between two `Connection` instances connected to
323 each other via memory BIOs.
324 """
325 client_conn.set_connect_state()
326 server_conn.set_accept_state()
327
328 for conn in [client_conn, server_conn]:
329 try:
330 conn.do_handshake()
331 except WantReadError:
332 pass
333
334 interact_in_memory(client_conn, server_conn)
335
336
Alex Chanb7480992017-01-30 14:04:47 +0000337class TestVersion(object):
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400338 """
Alex Chanb7480992017-01-30 14:04:47 +0000339 Tests for version information exposed by `OpenSSL.SSL.SSLeay_version` and
340 `OpenSSL.SSL.OPENSSL_VERSION_NUMBER`.
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400341 """
342 def test_OPENSSL_VERSION_NUMBER(self):
343 """
Alex Chanb7480992017-01-30 14:04:47 +0000344 `OPENSSL_VERSION_NUMBER` is an integer with status in the low byte and
345 the patch, fix, minor, and major versions in the nibbles above that.
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400346 """
Alex Chanb7480992017-01-30 14:04:47 +0000347 assert isinstance(OPENSSL_VERSION_NUMBER, int)
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400348
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400349 def test_SSLeay_version(self):
350 """
Alex Chanb7480992017-01-30 14:04:47 +0000351 `SSLeay_version` takes a version type indicator and returns one of a
352 number of version strings based on that indicator.
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400353 """
354 versions = {}
355 for t in [SSLEAY_VERSION, SSLEAY_CFLAGS, SSLEAY_BUILT_ON,
356 SSLEAY_PLATFORM, SSLEAY_DIR]:
357 version = SSLeay_version(t)
358 versions[version] = t
Alex Chanb7480992017-01-30 14:04:47 +0000359 assert isinstance(version, bytes)
360 assert len(versions) == 5
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400361
362
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100363@pytest.fixture
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100364def ca_file(tmpdir):
365 """
366 Create a valid PEM file with CA certificates and return the path.
367 """
368 key = rsa.generate_private_key(
369 public_exponent=65537,
370 key_size=2048,
371 backend=default_backend()
372 )
373 public_key = key.public_key()
374
375 builder = x509.CertificateBuilder()
376 builder = builder.subject_name(x509.Name([
377 x509.NameAttribute(NameOID.COMMON_NAME, u"pyopenssl.org"),
378 ]))
379 builder = builder.issuer_name(x509.Name([
380 x509.NameAttribute(NameOID.COMMON_NAME, u"pyopenssl.org"),
381 ]))
382 one_day = datetime.timedelta(1, 0, 0)
383 builder = builder.not_valid_before(datetime.datetime.today() - one_day)
384 builder = builder.not_valid_after(datetime.datetime.today() + one_day)
385 builder = builder.serial_number(int(uuid.uuid4()))
386 builder = builder.public_key(public_key)
387 builder = builder.add_extension(
388 x509.BasicConstraints(ca=True, path_length=None), critical=True,
389 )
390
391 certificate = builder.sign(
392 private_key=key, algorithm=hashes.SHA256(),
393 backend=default_backend()
394 )
395
396 ca_file = tmpdir.join("test.pem")
397 ca_file.write_binary(
398 certificate.public_bytes(
399 encoding=serialization.Encoding.PEM,
400 )
401 )
402
403 return str(ca_file).encode("ascii")
404
405
406@pytest.fixture
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100407def context():
408 """
409 A simple TLS 1.0 context.
410 """
411 return Context(TLSv1_METHOD)
412
413
414class TestContext(object):
Hynek Schlawackaa861212016-03-13 13:53:48 +0100415 """
Alex Chan532b79e2017-01-24 15:14:52 +0000416 Unit tests for `OpenSSL.SSL.Context`.
Hynek Schlawackaa861212016-03-13 13:53:48 +0100417 """
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100418 @pytest.mark.parametrize("cipher_string", [
419 b"hello world:AES128-SHA",
420 u"hello world:AES128-SHA",
421 ])
422 def test_set_cipher_list(self, context, cipher_string):
423 """
Alex Chan532b79e2017-01-24 15:14:52 +0000424 `Context.set_cipher_list` accepts both byte and unicode strings
Hynek Schlawacka7a63af2016-03-11 12:05:26 +0100425 for naming the ciphers which connections created with the context
426 object will be able to choose from.
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100427 """
428 context.set_cipher_list(cipher_string)
429 conn = Connection(context, None)
430
431 assert "AES128-SHA" in conn.get_cipher_list()
432
Mark Williamsdf2480d2019-02-14 19:30:07 -0800433 def test_set_cipher_list_wrong_type(self, context):
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100434 """
Alex Chan532b79e2017-01-24 15:14:52 +0000435 `Context.set_cipher_list` raises `TypeError` when passed a non-string
Mark Williamsdf2480d2019-02-14 19:30:07 -0800436 argument.
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100437 """
Mark Williamsdf2480d2019-02-14 19:30:07 -0800438 with pytest.raises(TypeError):
439 context.set_cipher_list(object())
440
Alex Gaynor963ae032019-07-06 17:38:32 -0400441 @flaky.flaky
Mark Williamsdf2480d2019-02-14 19:30:07 -0800442 def test_set_cipher_list_no_cipher_match(self, context):
443 """
444 `Context.set_cipher_list` raises `OpenSSL.SSL.Error` with a
445 `"no cipher match"` reason string regardless of the TLS
446 version.
447 """
448 with pytest.raises(Error) as excinfo:
449 context.set_cipher_list(b"imaginary-cipher")
450 assert excinfo.value.args == (
451 [
452 (
453 'SSL routines',
454 'SSL_CTX_set_cipher_list',
455 'no cipher match',
456 ),
457 ],
458 )
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100459
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100460 def test_load_client_ca(self, context, ca_file):
461 """
Alex Chan532b79e2017-01-24 15:14:52 +0000462 `Context.load_client_ca` works as far as we can tell.
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100463 """
464 context.load_client_ca(ca_file)
465
466 def test_load_client_ca_invalid(self, context, tmpdir):
467 """
Alex Chan532b79e2017-01-24 15:14:52 +0000468 `Context.load_client_ca` raises an Error if the ca file is invalid.
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100469 """
470 ca_file = tmpdir.join("test.pem")
471 ca_file.write("")
472
473 with pytest.raises(Error) as e:
474 context.load_client_ca(str(ca_file).encode("ascii"))
475
476 assert "PEM routines" == e.value.args[0][0][0]
477
478 def test_load_client_ca_unicode(self, context, ca_file):
479 """
480 Passing the path as unicode raises a warning but works.
481 """
482 pytest.deprecated_call(
483 context.load_client_ca, ca_file.decode("ascii")
484 )
485
486 def test_set_session_id(self, context):
487 """
Alex Chan532b79e2017-01-24 15:14:52 +0000488 `Context.set_session_id` works as far as we can tell.
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100489 """
490 context.set_session_id(b"abc")
491
492 def test_set_session_id_fail(self, context):
493 """
Alex Chan532b79e2017-01-24 15:14:52 +0000494 `Context.set_session_id` errors are propagated.
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100495 """
496 with pytest.raises(Error) as e:
497 context.set_session_id(b"abc" * 1000)
498
499 assert [
500 ("SSL routines",
501 "SSL_CTX_set_session_id_context",
502 "ssl session id context too long")
503 ] == e.value.args[0]
504
505 def test_set_session_id_unicode(self, context):
506 """
Alex Chan532b79e2017-01-24 15:14:52 +0000507 `Context.set_session_id` raises a warning if a unicode string is
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100508 passed.
509 """
510 pytest.deprecated_call(context.set_session_id, u"abc")
511
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400512 def test_method(self):
513 """
Alex Chan532b79e2017-01-24 15:14:52 +0000514 `Context` can be instantiated with one of `SSLv2_METHOD`,
515 `SSLv3_METHOD`, `SSLv23_METHOD`, `TLSv1_METHOD`, `TLSv1_1_METHOD`,
516 or `TLSv1_2_METHOD`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400517 """
Alex Gaynor5af32d02016-09-24 01:52:21 -0400518 methods = [SSLv23_METHOD, TLSv1_METHOD]
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400519 for meth in methods:
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400520 Context(meth)
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400521
Alex Gaynor5af32d02016-09-24 01:52:21 -0400522 maybe = [SSLv2_METHOD, SSLv3_METHOD, TLSv1_1_METHOD, TLSv1_2_METHOD]
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400523 for meth in maybe:
524 try:
525 Context(meth)
526 except (Error, ValueError):
527 # Some versions of OpenSSL have SSLv2 / TLSv1.1 / TLSv1.2, some
528 # don't. Difficult to say in advance.
529 pass
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400530
Alex Chan532b79e2017-01-24 15:14:52 +0000531 with pytest.raises(TypeError):
532 Context("")
533 with pytest.raises(ValueError):
534 Context(10)
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400535
Rick Deane15b1472009-07-09 15:53:42 -0500536 def test_type(self):
537 """
Alex Gaynor01f90a12019-02-07 09:14:48 -0500538 `Context` can be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -0500539 """
Alex Chan532b79e2017-01-24 15:14:52 +0000540 assert is_consistent_type(Context, 'Context', TLSv1_METHOD)
Rick Deane15b1472009-07-09 15:53:42 -0500541
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400542 def test_use_privatekey(self):
543 """
Alex Chan532b79e2017-01-24 15:14:52 +0000544 `Context.use_privatekey` takes an `OpenSSL.crypto.PKey` instance.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400545 """
546 key = PKey()
Alex Gaynor6e9f9762018-05-12 07:44:37 -0400547 key.generate_key(TYPE_RSA, 512)
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400548 ctx = Context(TLSv1_METHOD)
549 ctx.use_privatekey(key)
Alex Chan532b79e2017-01-24 15:14:52 +0000550 with pytest.raises(TypeError):
551 ctx.use_privatekey("")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400552
Alex Chan532b79e2017-01-24 15:14:52 +0000553 def test_use_privatekey_file_missing(self, tmpfile):
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800554 """
Alex Chan532b79e2017-01-24 15:14:52 +0000555 `Context.use_privatekey_file` raises `OpenSSL.SSL.Error` when passed
556 the name of a file which does not exist.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800557 """
558 ctx = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000559 with pytest.raises(Error):
560 ctx.use_privatekey_file(tmpfile)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800561
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400562 def _use_privatekey_file_test(self, pemfile, filetype):
563 """
564 Verify that calling ``Context.use_privatekey_file`` with the given
565 arguments does not raise an exception.
566 """
567 key = PKey()
Alex Gaynor6e9f9762018-05-12 07:44:37 -0400568 key.generate_key(TYPE_RSA, 512)
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400569
570 with open(pemfile, "wt") as pem:
571 pem.write(
572 dump_privatekey(FILETYPE_PEM, key).decode("ascii")
573 )
574
575 ctx = Context(TLSv1_METHOD)
576 ctx.use_privatekey_file(pemfile, filetype)
577
Alex Chanfb078d82017-04-20 11:16:15 +0100578 @pytest.mark.parametrize('filetype', [object(), "", None, 1.0])
579 def test_wrong_privatekey_file_wrong_args(self, tmpfile, filetype):
580 """
581 `Context.use_privatekey_file` raises `TypeError` when called with
582 a `filetype` which is not a valid file encoding.
583 """
584 ctx = Context(TLSv1_METHOD)
585 with pytest.raises(TypeError):
586 ctx.use_privatekey_file(tmpfile, filetype)
587
Alex Chan532b79e2017-01-24 15:14:52 +0000588 def test_use_privatekey_file_bytes(self, tmpfile):
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400589 """
590 A private key can be specified from a file by passing a ``bytes``
591 instance giving the file name to ``Context.use_privatekey_file``.
592 """
593 self._use_privatekey_file_test(
Alex Chan532b79e2017-01-24 15:14:52 +0000594 tmpfile + NON_ASCII.encode(getfilesystemencoding()),
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400595 FILETYPE_PEM,
596 )
597
Alex Chan532b79e2017-01-24 15:14:52 +0000598 def test_use_privatekey_file_unicode(self, tmpfile):
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400599 """
600 A private key can be specified from a file by passing a ``unicode``
601 instance giving the file name to ``Context.use_privatekey_file``.
602 """
603 self._use_privatekey_file_test(
Alex Chan532b79e2017-01-24 15:14:52 +0000604 tmpfile.decode(getfilesystemencoding()) + NON_ASCII,
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400605 FILETYPE_PEM,
606 )
607
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800608 def test_use_certificate_wrong_args(self):
609 """
Alex Chan532b79e2017-01-24 15:14:52 +0000610 `Context.use_certificate_wrong_args` raises `TypeError` when not passed
611 exactly one `OpenSSL.crypto.X509` instance as an argument.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800612 """
613 ctx = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000614 with pytest.raises(TypeError):
615 ctx.use_certificate("hello, world")
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800616
617 def test_use_certificate_uninitialized(self):
618 """
Alex Chan532b79e2017-01-24 15:14:52 +0000619 `Context.use_certificate` raises `OpenSSL.SSL.Error` when passed a
620 `OpenSSL.crypto.X509` instance which has not been initialized
621 (ie, which does not actually have any certificate data).
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800622 """
623 ctx = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000624 with pytest.raises(Error):
625 ctx.use_certificate(X509())
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800626
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800627 def test_use_certificate(self):
628 """
Alex Chan532b79e2017-01-24 15:14:52 +0000629 `Context.use_certificate` sets the certificate which will be
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800630 used to identify connections created using the context.
631 """
632 # TODO
633 # Hard to assert anything. But we could set a privatekey then ask
634 # OpenSSL if the cert and key agree using check_privatekey. Then as
635 # long as check_privatekey works right we're good...
636 ctx = Context(TLSv1_METHOD)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200637 ctx.use_certificate(
638 load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
639 )
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800640
641 def test_use_certificate_file_wrong_args(self):
642 """
Alex Chan532b79e2017-01-24 15:14:52 +0000643 `Context.use_certificate_file` raises `TypeError` if the first
644 argument is not a byte string or the second argument is not an integer.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800645 """
646 ctx = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000647 with pytest.raises(TypeError):
648 ctx.use_certificate_file(object(), FILETYPE_PEM)
649 with pytest.raises(TypeError):
650 ctx.use_certificate_file(b"somefile", object())
651 with pytest.raises(TypeError):
652 ctx.use_certificate_file(object(), FILETYPE_PEM)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800653
Alex Chan532b79e2017-01-24 15:14:52 +0000654 def test_use_certificate_file_missing(self, tmpfile):
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800655 """
Alex Chan532b79e2017-01-24 15:14:52 +0000656 `Context.use_certificate_file` raises `OpenSSL.SSL.Error` if passed
657 the name of a file which does not exist.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800658 """
659 ctx = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000660 with pytest.raises(Error):
661 ctx.use_certificate_file(tmpfile)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800662
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400663 def _use_certificate_file_test(self, certificate_file):
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800664 """
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400665 Verify that calling ``Context.use_certificate_file`` with the given
666 filename doesn't raise an exception.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800667 """
668 # TODO
669 # Hard to assert anything. But we could set a privatekey then ask
670 # OpenSSL if the cert and key agree using check_privatekey. Then as
671 # long as check_privatekey works right we're good...
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400672 with open(certificate_file, "wb") as pem_file:
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800673 pem_file.write(cleartextCertificatePEM)
674
675 ctx = Context(TLSv1_METHOD)
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400676 ctx.use_certificate_file(certificate_file)
677
Alex Chan532b79e2017-01-24 15:14:52 +0000678 def test_use_certificate_file_bytes(self, tmpfile):
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400679 """
Alex Chan532b79e2017-01-24 15:14:52 +0000680 `Context.use_certificate_file` sets the certificate (given as a
681 `bytes` filename) which will be used to identify connections created
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400682 using the context.
683 """
Alex Chan532b79e2017-01-24 15:14:52 +0000684 filename = tmpfile + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400685 self._use_certificate_file_test(filename)
686
Alex Chan532b79e2017-01-24 15:14:52 +0000687 def test_use_certificate_file_unicode(self, tmpfile):
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400688 """
Alex Chan532b79e2017-01-24 15:14:52 +0000689 `Context.use_certificate_file` sets the certificate (given as a
690 `bytes` filename) which will be used to identify connections created
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400691 using the context.
692 """
Alex Chan532b79e2017-01-24 15:14:52 +0000693 filename = tmpfile.decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400694 self._use_certificate_file_test(filename)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800695
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500696 def test_check_privatekey_valid(self):
697 """
Alex Chan532b79e2017-01-24 15:14:52 +0000698 `Context.check_privatekey` returns `None` if the `Context` instance
699 has been configured to use a matched key and certificate pair.
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500700 """
701 key = load_privatekey(FILETYPE_PEM, client_key_pem)
702 cert = load_certificate(FILETYPE_PEM, client_cert_pem)
703 context = Context(TLSv1_METHOD)
704 context.use_privatekey(key)
705 context.use_certificate(cert)
Alex Chan532b79e2017-01-24 15:14:52 +0000706 assert None is context.check_privatekey()
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500707
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500708 def test_check_privatekey_invalid(self):
709 """
Alex Chan532b79e2017-01-24 15:14:52 +0000710 `Context.check_privatekey` raises `Error` if the `Context` instance
711 has been configured to use a key and certificate pair which don't
712 relate to each other.
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500713 """
714 key = load_privatekey(FILETYPE_PEM, client_key_pem)
715 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
716 context = Context(TLSv1_METHOD)
717 context.use_privatekey(key)
718 context.use_certificate(cert)
Alex Chan532b79e2017-01-24 15:14:52 +0000719 with pytest.raises(Error):
720 context.check_privatekey()
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400721
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400722 def test_app_data(self):
723 """
Alex Chan532b79e2017-01-24 15:14:52 +0000724 `Context.set_app_data` stores an object for later retrieval
725 using `Context.get_app_data`.
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400726 """
727 app_data = object()
728 context = Context(TLSv1_METHOD)
729 context.set_app_data(app_data)
Alex Chan532b79e2017-01-24 15:14:52 +0000730 assert context.get_app_data() is app_data
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400731
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400732 def test_set_options_wrong_args(self):
733 """
Alex Chan532b79e2017-01-24 15:14:52 +0000734 `Context.set_options` raises `TypeError` if called with
735 a non-`int` argument.
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400736 """
737 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000738 with pytest.raises(TypeError):
739 context.set_options(None)
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400740
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500741 def test_set_options(self):
742 """
Alex Chan532b79e2017-01-24 15:14:52 +0000743 `Context.set_options` returns the new options value.
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500744 """
745 context = Context(TLSv1_METHOD)
746 options = context.set_options(OP_NO_SSLv2)
Alex Gaynor2310f8b2016-09-10 14:39:32 -0400747 assert options & OP_NO_SSLv2 == OP_NO_SSLv2
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500748
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300749 def test_set_mode_wrong_args(self):
750 """
Alex Chan532b79e2017-01-24 15:14:52 +0000751 `Context.set_mode` raises `TypeError` if called with
752 a non-`int` argument.
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300753 """
754 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000755 with pytest.raises(TypeError):
756 context.set_mode(None)
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300757
Alex Gaynord3b5d9b2016-07-31 10:54:24 -0400758 def test_set_mode(self):
759 """
Alex Chan532b79e2017-01-24 15:14:52 +0000760 `Context.set_mode` accepts a mode bitvector and returns the
Alex Gaynord3b5d9b2016-07-31 10:54:24 -0400761 newly set mode.
762 """
763 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000764 assert MODE_RELEASE_BUFFERS & context.set_mode(MODE_RELEASE_BUFFERS)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500765
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400766 def test_set_timeout_wrong_args(self):
767 """
Alex Chan532b79e2017-01-24 15:14:52 +0000768 `Context.set_timeout` raises `TypeError` if called with
769 a non-`int` argument.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400770 """
771 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000772 with pytest.raises(TypeError):
773 context.set_timeout(None)
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400774
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400775 def test_timeout(self):
776 """
Alex Chan532b79e2017-01-24 15:14:52 +0000777 `Context.set_timeout` sets the session timeout for all connections
778 created using the context object. `Context.get_timeout` retrieves
779 this value.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400780 """
781 context = Context(TLSv1_METHOD)
782 context.set_timeout(1234)
Alex Chan532b79e2017-01-24 15:14:52 +0000783 assert context.get_timeout() == 1234
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400784
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400785 def test_set_verify_depth_wrong_args(self):
786 """
Alex Chan532b79e2017-01-24 15:14:52 +0000787 `Context.set_verify_depth` raises `TypeError` if called with a
788 non-`int` argument.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400789 """
790 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000791 with pytest.raises(TypeError):
792 context.set_verify_depth(None)
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400793
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400794 def test_verify_depth(self):
795 """
Alex Chan532b79e2017-01-24 15:14:52 +0000796 `Context.set_verify_depth` sets the number of certificates in
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200797 a chain to follow before giving up. The value can be retrieved with
Alex Chan532b79e2017-01-24 15:14:52 +0000798 `Context.get_verify_depth`.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400799 """
800 context = Context(TLSv1_METHOD)
801 context.set_verify_depth(11)
Alex Chan532b79e2017-01-24 15:14:52 +0000802 assert context.get_verify_depth() == 11
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400803
Alex Chan532b79e2017-01-24 15:14:52 +0000804 def _write_encrypted_pem(self, passphrase, tmpfile):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400805 """
806 Write a new private key out to a new file, encrypted using the given
807 passphrase. Return the path to the new file.
808 """
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400809 key = PKey()
Alex Gaynor6e9f9762018-05-12 07:44:37 -0400810 key.generate_key(TYPE_RSA, 512)
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400811 pem = dump_privatekey(FILETYPE_PEM, key, "blowfish", passphrase)
Alex Chan532b79e2017-01-24 15:14:52 +0000812 with open(tmpfile, 'w') as fObj:
813 fObj.write(pem.decode('ascii'))
814 return tmpfile
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400815
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400816 def test_set_passwd_cb_wrong_args(self):
817 """
Alex Chan532b79e2017-01-24 15:14:52 +0000818 `Context.set_passwd_cb` raises `TypeError` if called with a
819 non-callable first argument.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400820 """
821 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000822 with pytest.raises(TypeError):
823 context.set_passwd_cb(None)
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400824
Alex Chan532b79e2017-01-24 15:14:52 +0000825 def test_set_passwd_cb(self, tmpfile):
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400826 """
Alex Chan532b79e2017-01-24 15:14:52 +0000827 `Context.set_passwd_cb` accepts a callable which will be invoked when
828 a private key is loaded from an encrypted PEM.
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400829 """
Alex Gaynore7f51982016-09-11 11:48:14 -0400830 passphrase = b"foobar"
Alex Chan532b79e2017-01-24 15:14:52 +0000831 pemFile = self._write_encrypted_pem(passphrase, tmpfile)
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400832 calledWith = []
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200833
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400834 def passphraseCallback(maxlen, verify, extra):
835 calledWith.append((maxlen, verify, extra))
836 return passphrase
837 context = Context(TLSv1_METHOD)
838 context.set_passwd_cb(passphraseCallback)
839 context.use_privatekey_file(pemFile)
Alex Chan532b79e2017-01-24 15:14:52 +0000840 assert len(calledWith) == 1
841 assert isinstance(calledWith[0][0], int)
842 assert isinstance(calledWith[0][1], int)
843 assert calledWith[0][2] is None
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400844
Alex Chan532b79e2017-01-24 15:14:52 +0000845 def test_passwd_callback_exception(self, tmpfile):
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400846 """
Alex Chan532b79e2017-01-24 15:14:52 +0000847 `Context.use_privatekey_file` propagates any exception raised
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200848 by the passphrase callback.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400849 """
Alex Chan532b79e2017-01-24 15:14:52 +0000850 pemFile = self._write_encrypted_pem(b"monkeys are nice", tmpfile)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200851
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400852 def passphraseCallback(maxlen, verify, extra):
853 raise RuntimeError("Sorry, I am a fail.")
854
855 context = Context(TLSv1_METHOD)
856 context.set_passwd_cb(passphraseCallback)
Alex Chan532b79e2017-01-24 15:14:52 +0000857 with pytest.raises(RuntimeError):
858 context.use_privatekey_file(pemFile)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400859
Alex Chan532b79e2017-01-24 15:14:52 +0000860 def test_passwd_callback_false(self, tmpfile):
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400861 """
Alex Chan532b79e2017-01-24 15:14:52 +0000862 `Context.use_privatekey_file` raises `OpenSSL.SSL.Error` if the
863 passphrase callback returns a false value.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400864 """
Alex Chan532b79e2017-01-24 15:14:52 +0000865 pemFile = self._write_encrypted_pem(b"monkeys are nice", tmpfile)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200866
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400867 def passphraseCallback(maxlen, verify, extra):
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500868 return b""
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400869
870 context = Context(TLSv1_METHOD)
871 context.set_passwd_cb(passphraseCallback)
Alex Chan532b79e2017-01-24 15:14:52 +0000872 with pytest.raises(Error):
873 context.use_privatekey_file(pemFile)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400874
Alex Chan532b79e2017-01-24 15:14:52 +0000875 def test_passwd_callback_non_string(self, tmpfile):
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400876 """
Alex Chan532b79e2017-01-24 15:14:52 +0000877 `Context.use_privatekey_file` raises `OpenSSL.SSL.Error` if the
878 passphrase callback returns a true non-string value.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400879 """
Alex Chan532b79e2017-01-24 15:14:52 +0000880 pemFile = self._write_encrypted_pem(b"monkeys are nice", tmpfile)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200881
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400882 def passphraseCallback(maxlen, verify, extra):
883 return 10
884
885 context = Context(TLSv1_METHOD)
886 context.set_passwd_cb(passphraseCallback)
Alex Chan532b79e2017-01-24 15:14:52 +0000887 # TODO: Surely this is the wrong error?
888 with pytest.raises(ValueError):
889 context.use_privatekey_file(pemFile)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400890
Alex Chan532b79e2017-01-24 15:14:52 +0000891 def test_passwd_callback_too_long(self, tmpfile):
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400892 """
893 If the passphrase returned by the passphrase callback returns a string
894 longer than the indicated maximum length, it is truncated.
895 """
896 # A priori knowledge!
Alex Gaynore7f51982016-09-11 11:48:14 -0400897 passphrase = b"x" * 1024
Alex Chan532b79e2017-01-24 15:14:52 +0000898 pemFile = self._write_encrypted_pem(passphrase, tmpfile)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200899
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400900 def passphraseCallback(maxlen, verify, extra):
901 assert maxlen == 1024
Alex Gaynore7f51982016-09-11 11:48:14 -0400902 return passphrase + b"y"
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400903
904 context = Context(TLSv1_METHOD)
905 context.set_passwd_cb(passphraseCallback)
906 # This shall succeed because the truncated result is the correct
907 # passphrase.
908 context.use_privatekey_file(pemFile)
909
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400910 def test_set_info_callback(self):
911 """
Alex Chan532b79e2017-01-24 15:14:52 +0000912 `Context.set_info_callback` accepts a callable which will be
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200913 invoked when certain information about an SSL connection is available.
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400914 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500915 (server, client) = socket_pair()
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400916
917 clientSSL = Connection(Context(TLSv1_METHOD), client)
918 clientSSL.set_connect_state()
919
920 called = []
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200921
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400922 def info(conn, where, ret):
923 called.append((conn, where, ret))
924 context = Context(TLSv1_METHOD)
925 context.set_info_callback(info)
926 context.use_certificate(
927 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
928 context.use_privatekey(
929 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
930
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400931 serverSSL = Connection(context, server)
932 serverSSL.set_accept_state()
933
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -0500934 handshake(clientSSL, serverSSL)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400935
Jean-Paul Calderone3835e522014-02-02 11:12:30 -0500936 # The callback must always be called with a Connection instance as the
937 # first argument. It would probably be better to split this into
938 # separate tests for client and server side info callbacks so we could
939 # assert it is called with the right Connection instance. It would
940 # also be good to assert *something* about `where` and `ret`.
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -0500941 notConnections = [
942 conn for (conn, where, ret) in called
943 if not isinstance(conn, Connection)]
Alex Chan532b79e2017-01-24 15:14:52 +0000944 assert [] == notConnections, (
945 "Some info callback arguments were not Connection instances.")
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400946
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400947 def _load_verify_locations_test(self, *args):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400948 """
949 Create a client context which will verify the peer certificate and call
Alex Chan532b79e2017-01-24 15:14:52 +0000950 its `load_verify_locations` method with the given arguments.
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -0400951 Then connect it to a server and ensure that the handshake succeeds.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400952 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500953 (server, client) = socket_pair()
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400954
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400955 clientContext = Context(TLSv1_METHOD)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400956 clientContext.load_verify_locations(*args)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400957 # Require that the server certificate verify properly or the
958 # connection will fail.
959 clientContext.set_verify(
960 VERIFY_PEER,
961 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
962
963 clientSSL = Connection(clientContext, client)
964 clientSSL.set_connect_state()
965
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400966 serverContext = Context(TLSv1_METHOD)
967 serverContext.use_certificate(
968 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
969 serverContext.use_privatekey(
970 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
971
972 serverSSL = Connection(serverContext, server)
973 serverSSL.set_accept_state()
974
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400975 # Without load_verify_locations above, the handshake
976 # will fail:
977 # Error: [('SSL routines', 'SSL3_GET_SERVER_CERTIFICATE',
978 # 'certificate verify failed')]
979 handshake(clientSSL, serverSSL)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400980
981 cert = clientSSL.get_peer_certificate()
Alex Chan532b79e2017-01-24 15:14:52 +0000982 assert cert.get_subject().CN == 'Testing Root CA'
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -0400983
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400984 def _load_verify_cafile(self, cafile):
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400985 """
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400986 Verify that if path to a file containing a certificate is passed to
Alex Chan532b79e2017-01-24 15:14:52 +0000987 `Context.load_verify_locations` for the ``cafile`` parameter, that
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400988 certificate is used as a trust root for the purposes of verifying
Alex Chan532b79e2017-01-24 15:14:52 +0000989 connections created using that `Context`.
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400990 """
Alex Chan532b79e2017-01-24 15:14:52 +0000991 with open(cafile, 'w') as fObj:
992 fObj.write(cleartextCertificatePEM.decode('ascii'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400993
994 self._load_verify_locations_test(cafile)
995
Alex Chan532b79e2017-01-24 15:14:52 +0000996 def test_load_verify_bytes_cafile(self, tmpfile):
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -0400997 """
Alex Chan532b79e2017-01-24 15:14:52 +0000998 `Context.load_verify_locations` accepts a file name as a `bytes`
999 instance and uses the certificates within for verification purposes.
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001000 """
Alex Chan532b79e2017-01-24 15:14:52 +00001001 cafile = tmpfile + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001002 self._load_verify_cafile(cafile)
1003
Alex Chan532b79e2017-01-24 15:14:52 +00001004 def test_load_verify_unicode_cafile(self, tmpfile):
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001005 """
Alex Chan532b79e2017-01-24 15:14:52 +00001006 `Context.load_verify_locations` accepts a file name as a `unicode`
1007 instance and uses the certificates within for verification purposes.
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001008 """
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001009 self._load_verify_cafile(
Alex Chan532b79e2017-01-24 15:14:52 +00001010 tmpfile.decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001011 )
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001012
Alex Chan532b79e2017-01-24 15:14:52 +00001013 def test_load_verify_invalid_file(self, tmpfile):
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -04001014 """
Alex Chan532b79e2017-01-24 15:14:52 +00001015 `Context.load_verify_locations` raises `Error` when passed a
1016 non-existent cafile.
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -04001017 """
1018 clientContext = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001019 with pytest.raises(Error):
1020 clientContext.load_verify_locations(tmpfile)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001021
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001022 def _load_verify_directory_locations_capath(self, capath):
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001023 """
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001024 Verify that if path to a directory containing certificate files is
1025 passed to ``Context.load_verify_locations`` for the ``capath``
1026 parameter, those certificates are used as trust roots for the purposes
1027 of verifying connections created using that ``Context``.
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001028 """
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001029 makedirs(capath)
Jean-Paul Calderone24dfb332011-05-04 18:10:26 -04001030 # Hash values computed manually with c_rehash to avoid depending on
1031 # c_rehash in the test suite. One is from OpenSSL 0.9.8, the other
1032 # from OpenSSL 1.0.0.
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001033 for name in [b'c7adac82.0', b'c3705638.0']:
Jean-Paul Calderone05826732015-04-12 11:38:49 -04001034 cafile = join_bytes_or_unicode(capath, name)
1035 with open(cafile, 'w') as fObj:
1036 fObj.write(cleartextCertificatePEM.decode('ascii'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001037
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001038 self._load_verify_locations_test(None, capath)
1039
Alex Chan532b79e2017-01-24 15:14:52 +00001040 def test_load_verify_directory_bytes_capath(self, tmpfile):
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001041 """
Alex Chan532b79e2017-01-24 15:14:52 +00001042 `Context.load_verify_locations` accepts a directory name as a `bytes`
1043 instance and uses the certificates within for verification purposes.
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001044 """
1045 self._load_verify_directory_locations_capath(
Alex Chan532b79e2017-01-24 15:14:52 +00001046 tmpfile + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001047 )
1048
Alex Chan532b79e2017-01-24 15:14:52 +00001049 def test_load_verify_directory_unicode_capath(self, tmpfile):
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001050 """
Alex Chan532b79e2017-01-24 15:14:52 +00001051 `Context.load_verify_locations` accepts a directory name as a `unicode`
1052 instance and uses the certificates within for verification purposes.
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001053 """
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001054 self._load_verify_directory_locations_capath(
Alex Chan532b79e2017-01-24 15:14:52 +00001055 tmpfile.decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001056 )
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001057
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001058 def test_load_verify_locations_wrong_args(self):
1059 """
Alex Chan532b79e2017-01-24 15:14:52 +00001060 `Context.load_verify_locations` raises `TypeError` if with non-`str`
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001061 arguments.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001062 """
1063 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001064 with pytest.raises(TypeError):
1065 context.load_verify_locations(object())
1066 with pytest.raises(TypeError):
1067 context.load_verify_locations(object(), object())
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001068
Hynek Schlawack734d3022015-09-05 19:19:32 +02001069 @pytest.mark.skipif(
Paul Kehrer55fb3412017-06-29 18:44:08 -05001070 not platform.startswith("linux"),
1071 reason="Loading fallback paths is a linux-specific behavior to "
1072 "accommodate pyca/cryptography manylinux1 wheels"
1073 )
1074 def test_fallback_default_verify_paths(self, monkeypatch):
1075 """
1076 Test that we load certificates successfully on linux from the fallback
1077 path. To do this we set the _CRYPTOGRAPHY_MANYLINUX1_CA_FILE and
1078 _CRYPTOGRAPHY_MANYLINUX1_CA_DIR vars to be equal to whatever the
1079 current OpenSSL default is and we disable
1080 SSL_CTX_SET_default_verify_paths so that it can't find certs unless
1081 it loads via fallback.
1082 """
1083 context = Context(TLSv1_METHOD)
1084 monkeypatch.setattr(
1085 _lib, "SSL_CTX_set_default_verify_paths", lambda x: 1
1086 )
1087 monkeypatch.setattr(
1088 SSL,
1089 "_CRYPTOGRAPHY_MANYLINUX1_CA_FILE",
1090 _ffi.string(_lib.X509_get_default_cert_file())
1091 )
1092 monkeypatch.setattr(
1093 SSL,
1094 "_CRYPTOGRAPHY_MANYLINUX1_CA_DIR",
1095 _ffi.string(_lib.X509_get_default_cert_dir())
1096 )
1097 context.set_default_verify_paths()
1098 store = context.get_cert_store()
1099 sk_obj = _lib.X509_STORE_get0_objects(store._store)
1100 assert sk_obj != _ffi.NULL
1101 num = _lib.sk_X509_OBJECT_num(sk_obj)
1102 assert num != 0
1103
1104 def test_check_env_vars(self, monkeypatch):
1105 """
1106 Test that we return True/False appropriately if the env vars are set.
1107 """
1108 context = Context(TLSv1_METHOD)
1109 dir_var = "CUSTOM_DIR_VAR"
1110 file_var = "CUSTOM_FILE_VAR"
1111 assert context._check_env_vars_set(dir_var, file_var) is False
1112 monkeypatch.setenv(dir_var, "value")
1113 monkeypatch.setenv(file_var, "value")
1114 assert context._check_env_vars_set(dir_var, file_var) is True
1115 assert context._check_env_vars_set(dir_var, file_var) is True
1116
1117 def test_verify_no_fallback_if_env_vars_set(self, monkeypatch):
1118 """
1119 Test that we don't use the fallback path if env vars are set.
1120 """
1121 context = Context(TLSv1_METHOD)
1122 monkeypatch.setattr(
1123 _lib, "SSL_CTX_set_default_verify_paths", lambda x: 1
1124 )
1125 dir_env_var = _ffi.string(
1126 _lib.X509_get_default_cert_dir_env()
1127 ).decode("ascii")
1128 file_env_var = _ffi.string(
1129 _lib.X509_get_default_cert_file_env()
1130 ).decode("ascii")
1131 monkeypatch.setenv(dir_env_var, "value")
1132 monkeypatch.setenv(file_env_var, "value")
1133 context.set_default_verify_paths()
1134
1135 monkeypatch.setattr(
1136 context,
1137 "_fallback_default_verify_paths",
1138 raiser(SystemError)
1139 )
1140 context.set_default_verify_paths()
1141
1142 @pytest.mark.skipif(
Hynek Schlawack734d3022015-09-05 19:19:32 +02001143 platform == "win32",
1144 reason="set_default_verify_paths appears not to work on Windows. "
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -04001145 "See LP#404343 and LP#404344."
Hynek Schlawack734d3022015-09-05 19:19:32 +02001146 )
1147 def test_set_default_verify_paths(self):
1148 """
Alex Chan532b79e2017-01-24 15:14:52 +00001149 `Context.set_default_verify_paths` causes the platform-specific CA
1150 certificate locations to be used for verification purposes.
Hynek Schlawack734d3022015-09-05 19:19:32 +02001151 """
1152 # Testing this requires a server with a certificate signed by one
1153 # of the CAs in the platform CA location. Getting one of those
1154 # costs money. Fortunately (or unfortunately, depending on your
1155 # perspective), it's easy to think of a public server on the
1156 # internet which has such a certificate. Connecting to the network
1157 # in a unit test is bad, but it's the only way I can think of to
1158 # really test this. -exarkun
Hynek Schlawackbf887932015-10-21 17:13:47 +02001159 context = Context(SSLv23_METHOD)
Hynek Schlawack734d3022015-09-05 19:19:32 +02001160 context.set_default_verify_paths()
1161 context.set_verify(
1162 VERIFY_PEER,
1163 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001164
David Benjamin1fbe0642019-04-15 17:05:13 -05001165 client = socket_any_family()
Hynek Schlawackbf887932015-10-21 17:13:47 +02001166 client.connect(("encrypted.google.com", 443))
Hynek Schlawack734d3022015-09-05 19:19:32 +02001167 clientSSL = Connection(context, client)
1168 clientSSL.set_connect_state()
Alex Gaynor373926c2018-05-12 07:43:07 -04001169 clientSSL.set_tlsext_host_name(b"encrypted.google.com")
Hynek Schlawack734d3022015-09-05 19:19:32 +02001170 clientSSL.do_handshake()
1171 clientSSL.send(b"GET / HTTP/1.0\r\n\r\n")
Alex Chan532b79e2017-01-24 15:14:52 +00001172 assert clientSSL.recv(1024)
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05001173
Paul Kehrer55fb3412017-06-29 18:44:08 -05001174 def test_fallback_path_is_not_file_or_dir(self):
1175 """
1176 Test that when passed empty arrays or paths that do not exist no
1177 errors are raised.
1178 """
1179 context = Context(TLSv1_METHOD)
1180 context._fallback_default_verify_paths([], [])
1181 context._fallback_default_verify_paths(
1182 ["/not/a/file"], ["/not/a/dir"]
1183 )
1184
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001185 def test_add_extra_chain_cert_invalid_cert(self):
1186 """
Alex Chan532b79e2017-01-24 15:14:52 +00001187 `Context.add_extra_chain_cert` raises `TypeError` if called with an
1188 object which is not an instance of `X509`.
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001189 """
1190 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001191 with pytest.raises(TypeError):
1192 context.add_extra_chain_cert(object())
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001193
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001194 def _handshake_test(self, serverContext, clientContext):
1195 """
1196 Verify that a client and server created with the given contexts can
1197 successfully handshake and communicate.
1198 """
1199 serverSocket, clientSocket = socket_pair()
1200
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001201 server = Connection(serverContext, serverSocket)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001202 server.set_accept_state()
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001203
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001204 client = Connection(clientContext, clientSocket)
1205 client.set_connect_state()
1206
1207 # Make them talk to each other.
Alex Chan532b79e2017-01-24 15:14:52 +00001208 # interact_in_memory(client, server)
1209 for _ in range(3):
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001210 for s in [client, server]:
1211 try:
1212 s.do_handshake()
1213 except WantReadError:
1214 pass
1215
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001216 def test_set_verify_callback_connection_argument(self):
1217 """
1218 The first argument passed to the verify callback is the
Alex Chan532b79e2017-01-24 15:14:52 +00001219 `Connection` instance for which verification is taking place.
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001220 """
1221 serverContext = Context(TLSv1_METHOD)
1222 serverContext.use_privatekey(
1223 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1224 serverContext.use_certificate(
1225 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1226 serverConnection = Connection(serverContext, None)
1227
1228 class VerifyCallback(object):
1229 def callback(self, connection, *args):
1230 self.connection = connection
1231 return 1
1232
1233 verify = VerifyCallback()
1234 clientContext = Context(TLSv1_METHOD)
1235 clientContext.set_verify(VERIFY_PEER, verify.callback)
1236 clientConnection = Connection(clientContext, None)
1237 clientConnection.set_connect_state()
1238
Alex Chan532b79e2017-01-24 15:14:52 +00001239 handshake_in_memory(clientConnection, serverConnection)
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001240
Alex Chan532b79e2017-01-24 15:14:52 +00001241 assert verify.connection is clientConnection
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001242
Paul Kehrere7381862017-11-30 20:55:25 +08001243 def test_x509_in_verify_works(self):
1244 """
1245 We had a bug where the X509 cert instantiated in the callback wrapper
1246 didn't __init__ so it was missing objects needed when calling
1247 get_subject. This test sets up a handshake where we call get_subject
1248 on the cert provided to the verify callback.
1249 """
1250 serverContext = Context(TLSv1_METHOD)
1251 serverContext.use_privatekey(
1252 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1253 serverContext.use_certificate(
1254 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1255 serverConnection = Connection(serverContext, None)
1256
1257 def verify_cb_get_subject(conn, cert, errnum, depth, ok):
1258 assert cert.get_subject()
1259 return 1
1260
1261 clientContext = Context(TLSv1_METHOD)
1262 clientContext.set_verify(VERIFY_PEER, verify_cb_get_subject)
1263 clientConnection = Connection(clientContext, None)
1264 clientConnection.set_connect_state()
1265
1266 handshake_in_memory(clientConnection, serverConnection)
1267
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001268 def test_set_verify_callback_exception(self):
1269 """
Alex Chan532b79e2017-01-24 15:14:52 +00001270 If the verify callback passed to `Context.set_verify` raises an
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001271 exception, verification fails and the exception is propagated to the
Alex Chan532b79e2017-01-24 15:14:52 +00001272 caller of `Connection.do_handshake`.
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001273 """
Paul Kehrer7d5a3bf2019-01-21 12:24:02 -06001274 serverContext = Context(TLSv1_2_METHOD)
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001275 serverContext.use_privatekey(
1276 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1277 serverContext.use_certificate(
1278 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1279
Paul Kehrer7d5a3bf2019-01-21 12:24:02 -06001280 clientContext = Context(TLSv1_2_METHOD)
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001281
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001282 def verify_callback(*args):
1283 raise Exception("silly verify failure")
1284 clientContext.set_verify(VERIFY_PEER, verify_callback)
1285
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01001286 with pytest.raises(Exception) as exc:
1287 self._handshake_test(serverContext, clientContext)
1288
Alex Chan532b79e2017-01-24 15:14:52 +00001289 assert "silly verify failure" == str(exc.value)
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001290
Alex Chan532b79e2017-01-24 15:14:52 +00001291 def test_add_extra_chain_cert(self, tmpdir):
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001292 """
Alex Chan532b79e2017-01-24 15:14:52 +00001293 `Context.add_extra_chain_cert` accepts an `X509`
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001294 instance to add to the certificate chain.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001295
Alex Chan532b79e2017-01-24 15:14:52 +00001296 See `_create_certificate_chain` for the details of the
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001297 certificate chain tested.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001298
1299 The chain is tested by starting a server with scert and connecting
1300 to it with a client which trusts cacert and requires verification to
1301 succeed.
1302 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001303 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001304 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1305
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001306 # Dump the CA certificate to a file because that's the only way to load
1307 # it as a trusted CA in the client context.
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001308 for cert, name in [(cacert, 'ca.pem'),
1309 (icert, 'i.pem'),
1310 (scert, 's.pem')]:
Alex Chan532b79e2017-01-24 15:14:52 +00001311 with tmpdir.join(name).open('w') as f:
Hynek Schlawacke90680f2015-04-16 15:09:27 -04001312 f.write(dump_certificate(FILETYPE_PEM, cert).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001313
Hynek Schlawack1902c012015-04-16 15:06:41 -04001314 for key, name in [(cakey, 'ca.key'),
1315 (ikey, 'i.key'),
1316 (skey, 's.key')]:
Alex Chan532b79e2017-01-24 15:14:52 +00001317 with tmpdir.join(name).open('w') as f:
Hynek Schlawacke90680f2015-04-16 15:09:27 -04001318 f.write(dump_privatekey(FILETYPE_PEM, key).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001319
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001320 # Create the server context
1321 serverContext = Context(TLSv1_METHOD)
1322 serverContext.use_privatekey(skey)
1323 serverContext.use_certificate(scert)
Jean-Paul Calderone16cf03d2010-09-08 18:53:39 -04001324 # The client already has cacert, we only need to give them icert.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001325 serverContext.add_extra_chain_cert(icert)
1326
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001327 # Create the client
1328 clientContext = Context(TLSv1_METHOD)
1329 clientContext.set_verify(
1330 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Alex Chan532b79e2017-01-24 15:14:52 +00001331 clientContext.load_verify_locations(str(tmpdir.join("ca.pem")))
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001332
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001333 # Try it out.
1334 self._handshake_test(serverContext, clientContext)
1335
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001336 def _use_certificate_chain_file_test(self, certdir):
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001337 """
Alex Chan532b79e2017-01-24 15:14:52 +00001338 Verify that `Context.use_certificate_chain_file` reads a
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001339 certificate chain from a specified file.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001340
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001341 The chain is tested by starting a server with scert and connecting to
1342 it with a client which trusts cacert and requires verification to
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001343 succeed.
1344 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001345 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001346 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1347
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001348 makedirs(certdir)
1349
Jean-Paul Calderone05826732015-04-12 11:38:49 -04001350 chainFile = join_bytes_or_unicode(certdir, "chain.pem")
1351 caFile = join_bytes_or_unicode(certdir, "ca.pem")
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001352
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001353 # Write out the chain file.
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001354 with open(chainFile, 'wb') as fObj:
1355 # Most specific to least general.
1356 fObj.write(dump_certificate(FILETYPE_PEM, scert))
1357 fObj.write(dump_certificate(FILETYPE_PEM, icert))
1358 fObj.write(dump_certificate(FILETYPE_PEM, cacert))
1359
1360 with open(caFile, 'w') as fObj:
1361 fObj.write(dump_certificate(FILETYPE_PEM, cacert).decode('ascii'))
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001362
1363 serverContext = Context(TLSv1_METHOD)
1364 serverContext.use_certificate_chain_file(chainFile)
1365 serverContext.use_privatekey(skey)
1366
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001367 clientContext = Context(TLSv1_METHOD)
1368 clientContext.set_verify(
1369 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001370 clientContext.load_verify_locations(caFile)
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001371
1372 self._handshake_test(serverContext, clientContext)
1373
Alex Chan532b79e2017-01-24 15:14:52 +00001374 def test_use_certificate_chain_file_bytes(self, tmpfile):
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001375 """
1376 ``Context.use_certificate_chain_file`` accepts the name of a file (as
1377 an instance of ``bytes``) to specify additional certificates to use to
1378 construct and verify a trust chain.
1379 """
1380 self._use_certificate_chain_file_test(
Alex Chan532b79e2017-01-24 15:14:52 +00001381 tmpfile + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001382 )
1383
Alex Chan532b79e2017-01-24 15:14:52 +00001384 def test_use_certificate_chain_file_unicode(self, tmpfile):
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001385 """
1386 ``Context.use_certificate_chain_file`` accepts the name of a file (as
1387 an instance of ``unicode``) to specify additional certificates to use
1388 to construct and verify a trust chain.
1389 """
1390 self._use_certificate_chain_file_test(
Alex Chan532b79e2017-01-24 15:14:52 +00001391 tmpfile.decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001392 )
1393
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001394 def test_use_certificate_chain_file_wrong_args(self):
1395 """
Alex Chan532b79e2017-01-24 15:14:52 +00001396 `Context.use_certificate_chain_file` raises `TypeError` if passed a
1397 non-byte string single argument.
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001398 """
1399 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001400 with pytest.raises(TypeError):
1401 context.use_certificate_chain_file(object())
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001402
Alex Chan532b79e2017-01-24 15:14:52 +00001403 def test_use_certificate_chain_file_missing_file(self, tmpfile):
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001404 """
Alex Chan532b79e2017-01-24 15:14:52 +00001405 `Context.use_certificate_chain_file` raises `OpenSSL.SSL.Error` when
1406 passed a bad chain file name (for example, the name of a file which
1407 does not exist).
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001408 """
1409 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001410 with pytest.raises(Error):
1411 context.use_certificate_chain_file(tmpfile)
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001412
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001413 def test_set_verify_mode(self):
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001414 """
Alex Chan532b79e2017-01-24 15:14:52 +00001415 `Context.get_verify_mode` returns the verify mode flags previously
1416 passed to `Context.set_verify`.
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001417 """
1418 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001419 assert context.get_verify_mode() == 0
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001420 context.set_verify(
1421 VERIFY_PEER | VERIFY_CLIENT_ONCE, lambda *args: None)
Alex Chan532b79e2017-01-24 15:14:52 +00001422 assert context.get_verify_mode() == (VERIFY_PEER | VERIFY_CLIENT_ONCE)
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001423
Alex Chanfb078d82017-04-20 11:16:15 +01001424 @pytest.mark.parametrize('mode', [None, 1.0, object(), 'mode'])
1425 def test_set_verify_wrong_mode_arg(self, mode):
1426 """
1427 `Context.set_verify` raises `TypeError` if the first argument is
1428 not an integer.
1429 """
1430 context = Context(TLSv1_METHOD)
1431 with pytest.raises(TypeError):
1432 context.set_verify(mode=mode, callback=lambda *args: None)
1433
1434 @pytest.mark.parametrize('callback', [None, 1.0, 'mode', ('foo', 'bar')])
1435 def test_set_verify_wrong_callable_arg(self, callback):
1436 """
Alex Gaynor40bc0f12018-05-14 14:06:16 -04001437 `Context.set_verify` raises `TypeError` if the second argument
Alex Chanfb078d82017-04-20 11:16:15 +01001438 is not callable.
1439 """
1440 context = Context(TLSv1_METHOD)
1441 with pytest.raises(TypeError):
1442 context.set_verify(mode=VERIFY_PEER, callback=callback)
1443
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001444 def test_load_tmp_dh_wrong_args(self):
1445 """
Alex Chan532b79e2017-01-24 15:14:52 +00001446 `Context.load_tmp_dh` raises `TypeError` if called with a
1447 non-`str` argument.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001448 """
1449 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001450 with pytest.raises(TypeError):
1451 context.load_tmp_dh(object())
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001452
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001453 def test_load_tmp_dh_missing_file(self):
1454 """
Alex Chan532b79e2017-01-24 15:14:52 +00001455 `Context.load_tmp_dh` raises `OpenSSL.SSL.Error` if the
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001456 specified file does not exist.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001457 """
1458 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001459 with pytest.raises(Error):
1460 context.load_tmp_dh(b"hello")
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001461
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001462 def _load_tmp_dh_test(self, dhfilename):
Jean-Paul Calderone4e0c43f2015-04-13 10:15:17 -04001463 """
1464 Verify that calling ``Context.load_tmp_dh`` with the given filename
1465 does not raise an exception.
1466 """
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001467 context = Context(TLSv1_METHOD)
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001468 with open(dhfilename, "w") as dhfile:
1469 dhfile.write(dhparam)
1470
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001471 context.load_tmp_dh(dhfilename)
1472 # XXX What should I assert here? -exarkun
1473
Alex Chan532b79e2017-01-24 15:14:52 +00001474 def test_load_tmp_dh_bytes(self, tmpfile):
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001475 """
Alex Chan532b79e2017-01-24 15:14:52 +00001476 `Context.load_tmp_dh` loads Diffie-Hellman parameters from the
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001477 specified file (given as ``bytes``).
1478 """
1479 self._load_tmp_dh_test(
Alex Chan532b79e2017-01-24 15:14:52 +00001480 tmpfile + NON_ASCII.encode(getfilesystemencoding()),
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001481 )
1482
Alex Chan532b79e2017-01-24 15:14:52 +00001483 def test_load_tmp_dh_unicode(self, tmpfile):
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001484 """
Alex Chan532b79e2017-01-24 15:14:52 +00001485 `Context.load_tmp_dh` loads Diffie-Hellman parameters from the
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001486 specified file (given as ``unicode``).
1487 """
1488 self._load_tmp_dh_test(
Alex Chan532b79e2017-01-24 15:14:52 +00001489 tmpfile.decode(getfilesystemencoding()) + NON_ASCII,
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001490 )
1491
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001492 def test_set_tmp_ecdh(self):
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001493 """
Alex Chan532b79e2017-01-24 15:14:52 +00001494 `Context.set_tmp_ecdh` sets the elliptic curve for Diffie-Hellman to
1495 the specified curve.
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001496 """
1497 context = Context(TLSv1_METHOD)
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001498 for curve in get_elliptic_curves():
Hynek Schlawacka07fa8c2015-10-17 10:15:28 +02001499 if curve.name.startswith(u"Oakley-"):
Hynek Schlawack7408aff2015-10-17 09:51:16 +02001500 # Setting Oakley-EC2N-4 and Oakley-EC2N-3 adds
1501 # ('bignum routines', 'BN_mod_inverse', 'no inverse') to the
1502 # error queue on OpenSSL 1.0.2.
1503 continue
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001504 # The only easily "assertable" thing is that it does not raise an
1505 # exception.
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001506 context.set_tmp_ecdh(curve)
Alex Gaynor12dc0842014-01-17 12:51:31 -06001507
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001508 def test_set_session_cache_mode_wrong_args(self):
1509 """
Alex Chan532b79e2017-01-24 15:14:52 +00001510 `Context.set_session_cache_mode` raises `TypeError` if called with
1511 a non-integer argument.
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001512 called with other than one integer argument.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001513 """
1514 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001515 with pytest.raises(TypeError):
1516 context.set_session_cache_mode(object())
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001517
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001518 def test_session_cache_mode(self):
1519 """
Alex Chan532b79e2017-01-24 15:14:52 +00001520 `Context.set_session_cache_mode` specifies how sessions are cached.
1521 The setting can be retrieved via `Context.get_session_cache_mode`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001522 """
1523 context = Context(TLSv1_METHOD)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001524 context.set_session_cache_mode(SESS_CACHE_OFF)
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001525 off = context.set_session_cache_mode(SESS_CACHE_BOTH)
Alex Chan532b79e2017-01-24 15:14:52 +00001526 assert SESS_CACHE_OFF == off
1527 assert SESS_CACHE_BOTH == context.get_session_cache_mode()
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001528
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001529 def test_get_cert_store(self):
1530 """
Alex Chan532b79e2017-01-24 15:14:52 +00001531 `Context.get_cert_store` returns a `X509Store` instance.
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001532 """
1533 context = Context(TLSv1_METHOD)
1534 store = context.get_cert_store()
Alex Chan532b79e2017-01-24 15:14:52 +00001535 assert isinstance(store, X509Store)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001536
Jeremy Lainé02261ad2018-05-16 18:33:25 +02001537 def test_set_tlsext_use_srtp_not_bytes(self):
1538 """
1539 `Context.set_tlsext_use_srtp' enables negotiating SRTP keying material.
1540
1541 It raises a TypeError if the list of profiles is not a byte string.
1542 """
1543 context = Context(TLSv1_METHOD)
1544 with pytest.raises(TypeError):
1545 context.set_tlsext_use_srtp(text_type('SRTP_AES128_CM_SHA1_80'))
1546
1547 def test_set_tlsext_use_srtp_invalid_profile(self):
1548 """
1549 `Context.set_tlsext_use_srtp' enables negotiating SRTP keying material.
1550
1551 It raises an Error if the call to OpenSSL fails.
1552 """
1553 context = Context(TLSv1_METHOD)
1554 with pytest.raises(Error):
1555 context.set_tlsext_use_srtp(b'SRTP_BOGUS')
1556
1557 def test_set_tlsext_use_srtp_valid(self):
1558 """
1559 `Context.set_tlsext_use_srtp' enables negotiating SRTP keying material.
1560
1561 It does not return anything.
1562 """
1563 context = Context(TLSv1_METHOD)
1564 assert context.set_tlsext_use_srtp(b'SRTP_AES128_CM_SHA1_80') is None
1565
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001566
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001567class TestServerNameCallback(object):
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001568 """
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001569 Tests for `Context.set_tlsext_servername_callback` and its
1570 interaction with `Connection`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001571 """
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001572 def test_old_callback_forgotten(self):
1573 """
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001574 If `Context.set_tlsext_servername_callback` is used to specify
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001575 a new callback, the one it replaces is dereferenced.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001576 """
Alex Chanfb078d82017-04-20 11:16:15 +01001577 def callback(connection): # pragma: no cover
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001578 pass
1579
Alex Chanfb078d82017-04-20 11:16:15 +01001580 def replacement(connection): # pragma: no cover
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001581 pass
1582
1583 context = Context(TLSv1_METHOD)
1584 context.set_tlsext_servername_callback(callback)
1585
1586 tracker = ref(callback)
1587 del callback
1588
1589 context.set_tlsext_servername_callback(replacement)
Jean-Paul Calderoned4033eb2014-01-11 08:21:46 -05001590
1591 # One run of the garbage collector happens to work on CPython. PyPy
1592 # doesn't collect the underlying object until a second run for whatever
1593 # reason. That's fine, it still demonstrates our code has properly
1594 # dropped the reference.
1595 collect()
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001596 collect()
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001597
1598 callback = tracker()
1599 if callback is not None:
1600 referrers = get_referrers(callback)
Alex Chanfb078d82017-04-20 11:16:15 +01001601 if len(referrers) > 1: # pragma: nocover
1602 pytest.fail("Some references remain: %r" % (referrers,))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001603
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001604 def test_no_servername(self):
1605 """
1606 When a client specifies no server name, the callback passed to
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001607 `Context.set_tlsext_servername_callback` is invoked and the
1608 result of `Connection.get_servername` is `None`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001609 """
1610 args = []
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001611
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001612 def servername(conn):
1613 args.append((conn, conn.get_servername()))
1614 context = Context(TLSv1_METHOD)
1615 context.set_tlsext_servername_callback(servername)
1616
1617 # Lose our reference to it. The Context is responsible for keeping it
1618 # alive now.
1619 del servername
1620 collect()
1621
1622 # Necessary to actually accept the connection
1623 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001624 context.use_certificate(
1625 load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001626
1627 # Do a little connection to trigger the logic
1628 server = Connection(context, None)
1629 server.set_accept_state()
1630
1631 client = Connection(Context(TLSv1_METHOD), None)
1632 client.set_connect_state()
1633
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001634 interact_in_memory(server, client)
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001635
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001636 assert args == [(server, None)]
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001637
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001638 def test_servername(self):
1639 """
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001640 When a client specifies a server name in its hello message, the
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001641 callback passed to `Contexts.set_tlsext_servername_callback` is
1642 invoked and the result of `Connection.get_servername` is that
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001643 server name.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001644 """
1645 args = []
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001646
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001647 def servername(conn):
1648 args.append((conn, conn.get_servername()))
1649 context = Context(TLSv1_METHOD)
1650 context.set_tlsext_servername_callback(servername)
1651
1652 # Necessary to actually accept the connection
1653 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001654 context.use_certificate(
1655 load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001656
1657 # Do a little connection to trigger the logic
1658 server = Connection(context, None)
1659 server.set_accept_state()
1660
1661 client = Connection(Context(TLSv1_METHOD), None)
1662 client.set_connect_state()
Alex Gaynore7f51982016-09-11 11:48:14 -04001663 client.set_tlsext_host_name(b"foo1.example.com")
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001664
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001665 interact_in_memory(server, client)
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001666
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001667 assert args == [(server, b"foo1.example.com")]
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001668
1669
Paul Kehrer4d575902019-02-26 21:42:12 +08001670@pytest.mark.skipif(
1671 not _lib.Cryptography_HAS_NEXTPROTONEG, reason="NPN is not available"
1672)
Alex Chan9e08b3e2016-11-10 12:18:54 +00001673class TestNextProtoNegotiation(object):
Cory Benfield84a121e2014-03-31 20:30:25 +01001674 """
1675 Test for Next Protocol Negotiation in PyOpenSSL.
1676 """
Alex Chan9e08b3e2016-11-10 12:18:54 +00001677 def test_npn_success(self):
1678 """
1679 Tests that clients and servers that agree on the negotiated next
1680 protocol can correct establish a connection, and that the agreed
1681 protocol is reported by the connections.
1682 """
1683 advertise_args = []
1684 select_args = []
1685
1686 def advertise(conn):
1687 advertise_args.append((conn,))
1688 return [b'http/1.1', b'spdy/2']
1689
1690 def select(conn, options):
1691 select_args.append((conn, options))
1692 return b'spdy/2'
1693
1694 server_context = Context(TLSv1_METHOD)
1695 server_context.set_npn_advertise_callback(advertise)
1696
1697 client_context = Context(TLSv1_METHOD)
1698 client_context.set_npn_select_callback(select)
1699
1700 # Necessary to actually accept the connection
1701 server_context.use_privatekey(
1702 load_privatekey(FILETYPE_PEM, server_key_pem))
1703 server_context.use_certificate(
1704 load_certificate(FILETYPE_PEM, server_cert_pem))
1705
1706 # Do a little connection to trigger the logic
1707 server = Connection(server_context, None)
1708 server.set_accept_state()
1709
1710 client = Connection(client_context, None)
1711 client.set_connect_state()
1712
1713 interact_in_memory(server, client)
1714
1715 assert advertise_args == [(server,)]
1716 assert select_args == [(client, [b'http/1.1', b'spdy/2'])]
1717
1718 assert server.get_next_proto_negotiated() == b'spdy/2'
1719 assert client.get_next_proto_negotiated() == b'spdy/2'
1720
1721 def test_npn_client_fail(self):
1722 """
1723 Tests that when clients and servers cannot agree on what protocol
1724 to use next that the TLS connection does not get established.
1725 """
1726 advertise_args = []
1727 select_args = []
1728
1729 def advertise(conn):
1730 advertise_args.append((conn,))
1731 return [b'http/1.1', b'spdy/2']
1732
1733 def select(conn, options):
1734 select_args.append((conn, options))
1735 return b''
1736
1737 server_context = Context(TLSv1_METHOD)
1738 server_context.set_npn_advertise_callback(advertise)
1739
1740 client_context = Context(TLSv1_METHOD)
1741 client_context.set_npn_select_callback(select)
1742
1743 # Necessary to actually accept the connection
1744 server_context.use_privatekey(
1745 load_privatekey(FILETYPE_PEM, server_key_pem))
1746 server_context.use_certificate(
1747 load_certificate(FILETYPE_PEM, server_cert_pem))
1748
1749 # Do a little connection to trigger the logic
1750 server = Connection(server_context, None)
1751 server.set_accept_state()
1752
1753 client = Connection(client_context, None)
1754 client.set_connect_state()
1755
1756 # If the client doesn't return anything, the connection will fail.
1757 with pytest.raises(Error):
1758 interact_in_memory(server, client)
1759
1760 assert advertise_args == [(server,)]
1761 assert select_args == [(client, [b'http/1.1', b'spdy/2'])]
1762
1763 def test_npn_select_error(self):
1764 """
1765 Test that we can handle exceptions in the select callback. If
1766 select fails it should be fatal to the connection.
1767 """
1768 advertise_args = []
1769
1770 def advertise(conn):
1771 advertise_args.append((conn,))
1772 return [b'http/1.1', b'spdy/2']
1773
1774 def select(conn, options):
1775 raise TypeError
1776
1777 server_context = Context(TLSv1_METHOD)
1778 server_context.set_npn_advertise_callback(advertise)
1779
1780 client_context = Context(TLSv1_METHOD)
1781 client_context.set_npn_select_callback(select)
1782
1783 # Necessary to actually accept the connection
1784 server_context.use_privatekey(
1785 load_privatekey(FILETYPE_PEM, server_key_pem))
1786 server_context.use_certificate(
1787 load_certificate(FILETYPE_PEM, server_cert_pem))
1788
1789 # Do a little connection to trigger the logic
1790 server = Connection(server_context, None)
1791 server.set_accept_state()
1792
1793 client = Connection(client_context, None)
1794 client.set_connect_state()
1795
1796 # If the callback throws an exception it should be raised here.
1797 with pytest.raises(TypeError):
1798 interact_in_memory(server, client)
1799 assert advertise_args == [(server,), ]
1800
1801 def test_npn_advertise_error(self):
1802 """
1803 Test that we can handle exceptions in the advertise callback. If
1804 advertise fails no NPN is advertised to the client.
1805 """
1806 select_args = []
1807
1808 def advertise(conn):
1809 raise TypeError
1810
1811 def select(conn, options): # pragma: nocover
Cory Benfieldba1820d2015-04-13 17:39:12 -04001812 """
Alex Chan9e08b3e2016-11-10 12:18:54 +00001813 Assert later that no args are actually appended.
Cory Benfieldba1820d2015-04-13 17:39:12 -04001814 """
Alex Chan9e08b3e2016-11-10 12:18:54 +00001815 select_args.append((conn, options))
1816 return b''
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001817
Alex Chan9e08b3e2016-11-10 12:18:54 +00001818 server_context = Context(TLSv1_METHOD)
1819 server_context.set_npn_advertise_callback(advertise)
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001820
Alex Chan9e08b3e2016-11-10 12:18:54 +00001821 client_context = Context(TLSv1_METHOD)
1822 client_context.set_npn_select_callback(select)
Cory Benfield84a121e2014-03-31 20:30:25 +01001823
Alex Chan9e08b3e2016-11-10 12:18:54 +00001824 # Necessary to actually accept the connection
1825 server_context.use_privatekey(
1826 load_privatekey(FILETYPE_PEM, server_key_pem))
1827 server_context.use_certificate(
1828 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield84a121e2014-03-31 20:30:25 +01001829
Alex Chan9e08b3e2016-11-10 12:18:54 +00001830 # Do a little connection to trigger the logic
1831 server = Connection(server_context, None)
1832 server.set_accept_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001833
Alex Chan9e08b3e2016-11-10 12:18:54 +00001834 client = Connection(client_context, None)
1835 client.set_connect_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001836
Alex Chan9e08b3e2016-11-10 12:18:54 +00001837 # If the client doesn't return anything, the connection will fail.
1838 with pytest.raises(TypeError):
1839 interact_in_memory(server, client)
1840 assert select_args == []
Cory Benfield0ea76e72015-03-22 09:05:28 +00001841
1842
Alex Chanec1e32d2016-11-10 14:11:45 +00001843class TestApplicationLayerProtoNegotiation(object):
Cory Benfield12eae892014-06-07 15:42:56 +01001844 """
1845 Tests for ALPN in PyOpenSSL.
1846 """
Cory Benfielde46fa842015-04-13 16:50:49 -04001847 # Skip tests on versions that don't support ALPN.
1848 if _lib.Cryptography_HAS_ALPN:
Cory Benfield12eae892014-06-07 15:42:56 +01001849
Cory Benfielde46fa842015-04-13 16:50:49 -04001850 def test_alpn_success(self):
1851 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04001852 Clients and servers that agree on the negotiated ALPN protocol can
1853 correct establish a connection, and the agreed protocol is reported
1854 by the connections.
Cory Benfielde46fa842015-04-13 16:50:49 -04001855 """
1856 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001857
Cory Benfielde46fa842015-04-13 16:50:49 -04001858 def select(conn, options):
1859 select_args.append((conn, options))
1860 return b'spdy/2'
Cory Benfield12eae892014-06-07 15:42:56 +01001861
Cory Benfielde46fa842015-04-13 16:50:49 -04001862 client_context = Context(TLSv1_METHOD)
1863 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfield12eae892014-06-07 15:42:56 +01001864
Cory Benfielde46fa842015-04-13 16:50:49 -04001865 server_context = Context(TLSv1_METHOD)
1866 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01001867
Cory Benfielde46fa842015-04-13 16:50:49 -04001868 # Necessary to actually accept the connection
1869 server_context.use_privatekey(
1870 load_privatekey(FILETYPE_PEM, server_key_pem))
1871 server_context.use_certificate(
1872 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield12eae892014-06-07 15:42:56 +01001873
Cory Benfielde46fa842015-04-13 16:50:49 -04001874 # Do a little connection to trigger the logic
1875 server = Connection(server_context, None)
1876 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001877
Cory Benfielde46fa842015-04-13 16:50:49 -04001878 client = Connection(client_context, None)
1879 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001880
Alex Chanec1e32d2016-11-10 14:11:45 +00001881 interact_in_memory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001882
Alex Chanec1e32d2016-11-10 14:11:45 +00001883 assert select_args == [(server, [b'http/1.1', b'spdy/2'])]
Cory Benfielde46fa842015-04-13 16:50:49 -04001884
Alex Chanec1e32d2016-11-10 14:11:45 +00001885 assert server.get_alpn_proto_negotiated() == b'spdy/2'
1886 assert client.get_alpn_proto_negotiated() == b'spdy/2'
Cory Benfield12eae892014-06-07 15:42:56 +01001887
Cory Benfielde46fa842015-04-13 16:50:49 -04001888 def test_alpn_set_on_connection(self):
1889 """
1890 The same as test_alpn_success, but setting the ALPN protocols on
1891 the connection rather than the context.
1892 """
1893 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001894
Cory Benfielde46fa842015-04-13 16:50:49 -04001895 def select(conn, options):
1896 select_args.append((conn, options))
1897 return b'spdy/2'
Cory Benfield12eae892014-06-07 15:42:56 +01001898
Cory Benfielde46fa842015-04-13 16:50:49 -04001899 # Setup the client context but don't set any ALPN protocols.
1900 client_context = Context(TLSv1_METHOD)
Cory Benfield12eae892014-06-07 15:42:56 +01001901
Cory Benfielde46fa842015-04-13 16:50:49 -04001902 server_context = Context(TLSv1_METHOD)
1903 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01001904
Cory Benfielde46fa842015-04-13 16:50:49 -04001905 # Necessary to actually accept the connection
1906 server_context.use_privatekey(
1907 load_privatekey(FILETYPE_PEM, server_key_pem))
1908 server_context.use_certificate(
1909 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield12eae892014-06-07 15:42:56 +01001910
Cory Benfielde46fa842015-04-13 16:50:49 -04001911 # Do a little connection to trigger the logic
1912 server = Connection(server_context, None)
1913 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001914
Cory Benfielde46fa842015-04-13 16:50:49 -04001915 # Set the ALPN protocols on the client connection.
1916 client = Connection(client_context, None)
1917 client.set_alpn_protos([b'http/1.1', b'spdy/2'])
1918 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001919
Alex Chanec1e32d2016-11-10 14:11:45 +00001920 interact_in_memory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001921
Alex Chanec1e32d2016-11-10 14:11:45 +00001922 assert select_args == [(server, [b'http/1.1', b'spdy/2'])]
Cory Benfield12eae892014-06-07 15:42:56 +01001923
Alex Chanec1e32d2016-11-10 14:11:45 +00001924 assert server.get_alpn_proto_negotiated() == b'spdy/2'
1925 assert client.get_alpn_proto_negotiated() == b'spdy/2'
Cory Benfield12eae892014-06-07 15:42:56 +01001926
Cory Benfielde46fa842015-04-13 16:50:49 -04001927 def test_alpn_server_fail(self):
1928 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04001929 When clients and servers cannot agree on what protocol to use next
1930 the TLS connection does not get established.
Cory Benfielde46fa842015-04-13 16:50:49 -04001931 """
1932 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001933
Cory Benfielde46fa842015-04-13 16:50:49 -04001934 def select(conn, options):
1935 select_args.append((conn, options))
1936 return b''
Cory Benfield12eae892014-06-07 15:42:56 +01001937
Cory Benfielde46fa842015-04-13 16:50:49 -04001938 client_context = Context(TLSv1_METHOD)
1939 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfield12eae892014-06-07 15:42:56 +01001940
Cory Benfielde46fa842015-04-13 16:50:49 -04001941 server_context = Context(TLSv1_METHOD)
1942 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01001943
Cory Benfielde46fa842015-04-13 16:50:49 -04001944 # Necessary to actually accept the connection
1945 server_context.use_privatekey(
1946 load_privatekey(FILETYPE_PEM, server_key_pem))
1947 server_context.use_certificate(
1948 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield12eae892014-06-07 15:42:56 +01001949
Cory Benfielde46fa842015-04-13 16:50:49 -04001950 # Do a little connection to trigger the logic
1951 server = Connection(server_context, None)
1952 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001953
Cory Benfielde46fa842015-04-13 16:50:49 -04001954 client = Connection(client_context, None)
1955 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001956
Cory Benfielde46fa842015-04-13 16:50:49 -04001957 # If the client doesn't return anything, the connection will fail.
Alex Chanec1e32d2016-11-10 14:11:45 +00001958 with pytest.raises(Error):
1959 interact_in_memory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001960
Alex Chanec1e32d2016-11-10 14:11:45 +00001961 assert select_args == [(server, [b'http/1.1', b'spdy/2'])]
Cory Benfield12eae892014-06-07 15:42:56 +01001962
Cory Benfielde46fa842015-04-13 16:50:49 -04001963 def test_alpn_no_server(self):
1964 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04001965 When clients and servers cannot agree on what protocol to use next
1966 because the server doesn't offer ALPN, no protocol is negotiated.
Cory Benfielde46fa842015-04-13 16:50:49 -04001967 """
1968 client_context = Context(TLSv1_METHOD)
1969 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfielde3d57152015-04-11 17:57:35 -04001970
Cory Benfielde46fa842015-04-13 16:50:49 -04001971 server_context = Context(TLSv1_METHOD)
Cory Benfielde3d57152015-04-11 17:57:35 -04001972
Cory Benfielde46fa842015-04-13 16:50:49 -04001973 # Necessary to actually accept the connection
1974 server_context.use_privatekey(
1975 load_privatekey(FILETYPE_PEM, server_key_pem))
1976 server_context.use_certificate(
1977 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfielde3d57152015-04-11 17:57:35 -04001978
Cory Benfielde46fa842015-04-13 16:50:49 -04001979 # Do a little connection to trigger the logic
1980 server = Connection(server_context, None)
1981 server.set_accept_state()
Cory Benfielde3d57152015-04-11 17:57:35 -04001982
Cory Benfielde46fa842015-04-13 16:50:49 -04001983 client = Connection(client_context, None)
1984 client.set_connect_state()
Cory Benfielde3d57152015-04-11 17:57:35 -04001985
Cory Benfielde46fa842015-04-13 16:50:49 -04001986 # Do the dance.
Alex Chanec1e32d2016-11-10 14:11:45 +00001987 interact_in_memory(server, client)
Cory Benfielde3d57152015-04-11 17:57:35 -04001988
Alex Chanec1e32d2016-11-10 14:11:45 +00001989 assert client.get_alpn_proto_negotiated() == b''
Cory Benfielde3d57152015-04-11 17:57:35 -04001990
Cory Benfielde46fa842015-04-13 16:50:49 -04001991 def test_alpn_callback_exception(self):
1992 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04001993 We can handle exceptions in the ALPN select callback.
Cory Benfielde46fa842015-04-13 16:50:49 -04001994 """
1995 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001996
Cory Benfielde46fa842015-04-13 16:50:49 -04001997 def select(conn, options):
1998 select_args.append((conn, options))
Cory Benfieldef401452015-04-13 18:17:36 -04001999 raise TypeError()
Cory Benfieldf1177e72015-04-12 09:11:49 -04002000
Cory Benfielde46fa842015-04-13 16:50:49 -04002001 client_context = Context(TLSv1_METHOD)
2002 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfieldf1177e72015-04-12 09:11:49 -04002003
Cory Benfielde46fa842015-04-13 16:50:49 -04002004 server_context = Context(TLSv1_METHOD)
2005 server_context.set_alpn_select_callback(select)
Cory Benfieldf1177e72015-04-12 09:11:49 -04002006
Cory Benfielde46fa842015-04-13 16:50:49 -04002007 # Necessary to actually accept the connection
2008 server_context.use_privatekey(
2009 load_privatekey(FILETYPE_PEM, server_key_pem))
2010 server_context.use_certificate(
2011 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfieldf1177e72015-04-12 09:11:49 -04002012
Cory Benfielde46fa842015-04-13 16:50:49 -04002013 # Do a little connection to trigger the logic
2014 server = Connection(server_context, None)
2015 server.set_accept_state()
Cory Benfieldf1177e72015-04-12 09:11:49 -04002016
Cory Benfielde46fa842015-04-13 16:50:49 -04002017 client = Connection(client_context, None)
2018 client.set_connect_state()
Cory Benfieldf1177e72015-04-12 09:11:49 -04002019
Alex Chanec1e32d2016-11-10 14:11:45 +00002020 with pytest.raises(TypeError):
2021 interact_in_memory(server, client)
2022 assert select_args == [(server, [b'http/1.1', b'spdy/2'])]
Cory Benfieldf1177e72015-04-12 09:11:49 -04002023
Cory Benfield0f7b04c2015-04-13 17:51:12 -04002024 else:
2025 # No ALPN.
2026 def test_alpn_not_implemented(self):
Cory Benfieldef401452015-04-13 18:17:36 -04002027 """
2028 If ALPN is not in OpenSSL, we should raise NotImplementedError.
2029 """
Cory Benfield0f7b04c2015-04-13 17:51:12 -04002030 # Test the context methods first.
2031 context = Context(TLSv1_METHOD)
Alex Chanec1e32d2016-11-10 14:11:45 +00002032 with pytest.raises(NotImplementedError):
2033 context.set_alpn_protos(None)
2034 with pytest.raises(NotImplementedError):
2035 context.set_alpn_select_callback(None)
Cory Benfield0f7b04c2015-04-13 17:51:12 -04002036
2037 # Now test a connection.
2038 conn = Connection(context)
Alex Chanec1e32d2016-11-10 14:11:45 +00002039 with pytest.raises(NotImplementedError):
2040 conn.set_alpn_protos(None)
Cory Benfield0f7b04c2015-04-13 17:51:12 -04002041
Cory Benfieldf1177e72015-04-12 09:11:49 -04002042
Alex Chanec1e32d2016-11-10 14:11:45 +00002043class TestSession(object):
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05002044 """
2045 Unit tests for :py:obj:`OpenSSL.SSL.Session`.
2046 """
2047 def test_construction(self):
2048 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002049 :py:class:`Session` can be constructed with no arguments, creating
2050 a new instance of that type.
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05002051 """
2052 new_session = Session()
Alex Chanec1e32d2016-11-10 14:11:45 +00002053 assert isinstance(new_session, Session)
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05002054
2055
Alex Chan1c0cb662017-01-30 07:13:30 +00002056class TestConnection(object):
Rick Deane15b1472009-07-09 15:53:42 -05002057 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002058 Unit tests for `OpenSSL.SSL.Connection`.
Rick Deane15b1472009-07-09 15:53:42 -05002059 """
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04002060 # XXX get_peer_certificate -> None
2061 # XXX sock_shutdown
2062 # XXX master_key -> TypeError
2063 # XXX server_random -> TypeError
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04002064 # XXX connect -> TypeError
2065 # XXX connect_ex -> TypeError
2066 # XXX set_connect_state -> TypeError
2067 # XXX set_accept_state -> TypeError
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04002068 # XXX do_handshake -> TypeError
2069 # XXX bio_read -> TypeError
2070 # XXX recv -> TypeError
2071 # XXX send -> TypeError
2072 # XXX bio_write -> TypeError
2073
Rick Deane15b1472009-07-09 15:53:42 -05002074 def test_type(self):
2075 """
Alex Gaynor01f90a12019-02-07 09:14:48 -05002076 `Connection` can be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -05002077 """
2078 ctx = Context(TLSv1_METHOD)
Alex Chan1c0cb662017-01-30 07:13:30 +00002079 assert is_consistent_type(Connection, 'Connection', ctx, None)
Rick Deane15b1472009-07-09 15:53:42 -05002080
Alex Chanfb078d82017-04-20 11:16:15 +01002081 @pytest.mark.parametrize('bad_context', [object(), 'context', None, 1])
2082 def test_wrong_args(self, bad_context):
2083 """
2084 `Connection.__init__` raises `TypeError` if called with a non-`Context`
2085 instance argument.
2086 """
2087 with pytest.raises(TypeError):
2088 Connection(bad_context)
2089
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002090 def test_get_context(self):
2091 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002092 `Connection.get_context` returns the `Context` instance used to
2093 construct the `Connection` instance.
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002094 """
2095 context = Context(TLSv1_METHOD)
2096 connection = Connection(context, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002097 assert connection.get_context() is context
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002098
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002099 def test_set_context_wrong_args(self):
2100 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002101 `Connection.set_context` raises `TypeError` if called with a
Alex Chanfb078d82017-04-20 11:16:15 +01002102 non-`Context` instance argument.
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002103 """
2104 ctx = Context(TLSv1_METHOD)
2105 connection = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002106 with pytest.raises(TypeError):
2107 connection.set_context(object())
2108 with pytest.raises(TypeError):
2109 connection.set_context("hello")
2110 with pytest.raises(TypeError):
2111 connection.set_context(1)
2112 assert ctx is connection.get_context()
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002113
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002114 def test_set_context(self):
2115 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002116 `Connection.set_context` specifies a new `Context` instance to be
2117 used for the connection.
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002118 """
2119 original = Context(SSLv23_METHOD)
2120 replacement = Context(TLSv1_METHOD)
2121 connection = Connection(original, None)
2122 connection.set_context(replacement)
Alex Chan1c0cb662017-01-30 07:13:30 +00002123 assert replacement is connection.get_context()
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002124 # Lose our references to the contexts, just in case the Connection
2125 # isn't properly managing its own contributions to their reference
2126 # counts.
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002127 del original, replacement
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002128 collect()
2129
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002130 def test_set_tlsext_host_name_wrong_args(self):
2131 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002132 If `Connection.set_tlsext_host_name` is called with a non-byte string
2133 argument or a byte string with an embedded NUL, `TypeError` is raised.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002134 """
2135 conn = Connection(Context(TLSv1_METHOD), None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002136 with pytest.raises(TypeError):
2137 conn.set_tlsext_host_name(object())
2138 with pytest.raises(TypeError):
2139 conn.set_tlsext_host_name(b"with\0null")
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002140
Abraham Martinc5484ba2015-03-25 15:33:05 +00002141 if PY3:
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002142 # On Python 3.x, don't accidentally implicitly convert from text.
Alex Chan1c0cb662017-01-30 07:13:30 +00002143 with pytest.raises(TypeError):
2144 conn.set_tlsext_host_name(b"example.com".decode("ascii"))
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04002145
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002146 def test_pending(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002147 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002148 `Connection.pending` returns the number of bytes available for
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002149 immediate read.
2150 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002151 connection = Connection(Context(TLSv1_METHOD), None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002152 assert connection.pending() == 0
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002153
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002154 def test_peek(self):
2155 """
Hynek Schlawack3bcf3152017-02-18 08:25:34 +01002156 `Connection.recv` peeks into the connection if `socket.MSG_PEEK` is
2157 passed.
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002158 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002159 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002160 server.send(b'xy')
Alex Chan1c0cb662017-01-30 07:13:30 +00002161 assert client.recv(2, MSG_PEEK) == b'xy'
2162 assert client.recv(2, MSG_PEEK) == b'xy'
2163 assert client.recv(2) == b'xy'
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002164
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002165 def test_connect_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002166 """
Hynek Schlawack3bcf3152017-02-18 08:25:34 +01002167 `Connection.connect` raises `TypeError` if called with a non-address
2168 argument.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002169 """
David Benjamin1fbe0642019-04-15 17:05:13 -05002170 connection = Connection(Context(TLSv1_METHOD), socket_any_family())
Alex Chan1c0cb662017-01-30 07:13:30 +00002171 with pytest.raises(TypeError):
2172 connection.connect(None)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002173
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002174 def test_connect_refused(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002175 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002176 `Connection.connect` raises `socket.error` if the underlying socket
2177 connect method raises it.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002178 """
David Benjamin1fbe0642019-04-15 17:05:13 -05002179 client = socket_any_family()
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002180 context = Context(TLSv1_METHOD)
2181 clientSSL = Connection(context, client)
Alex Gaynor122717b2015-09-05 14:14:18 -04002182 # pytest.raises here doesn't work because of a bug in py.test on Python
2183 # 2.6: https://github.com/pytest-dev/pytest/issues/988
Alex Gaynore69c2782015-09-05 14:07:48 -04002184 try:
David Benjamin1fbe0642019-04-15 17:05:13 -05002185 clientSSL.connect((loopback_address(client), 1))
Alex Gaynore69c2782015-09-05 14:07:48 -04002186 except error as e:
Alex Gaynor20a4c082015-09-05 14:24:15 -04002187 exc = e
2188 assert exc.args[0] == ECONNREFUSED
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002189
2190 def test_connect(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002191 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002192 `Connection.connect` establishes a connection to the specified address.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002193 """
David Benjamin1fbe0642019-04-15 17:05:13 -05002194 port = socket_any_family()
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002195 port.bind(('', 0))
2196 port.listen(3)
2197
David Benjamin1fbe0642019-04-15 17:05:13 -05002198 clientSSL = Connection(Context(TLSv1_METHOD), socket(port.family))
2199 clientSSL.connect((loopback_address(port), port.getsockname()[1]))
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002200 # XXX An assertion? Or something?
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002201
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002202 @pytest.mark.skipif(
2203 platform == "darwin",
2204 reason="connect_ex sometimes causes a kernel panic on OS X 10.6.4"
2205 )
2206 def test_connect_ex(self):
2207 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002208 If there is a connection error, `Connection.connect_ex` returns the
2209 errno instead of raising an exception.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002210 """
David Benjamin1fbe0642019-04-15 17:05:13 -05002211 port = socket_any_family()
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002212 port.bind(('', 0))
2213 port.listen(3)
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002214
David Benjamin1fbe0642019-04-15 17:05:13 -05002215 clientSSL = Connection(Context(TLSv1_METHOD), socket(port.family))
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002216 clientSSL.setblocking(False)
2217 result = clientSSL.connect_ex(port.getsockname())
2218 expected = (EINPROGRESS, EWOULDBLOCK)
Alex Chan1c0cb662017-01-30 07:13:30 +00002219 assert result in expected
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002220
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002221 def test_accept(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002222 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002223 `Connection.accept` accepts a pending connection attempt and returns a
2224 tuple of a new `Connection` (the accepted client) and the address the
2225 connection originated from.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002226 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002227 ctx = Context(TLSv1_METHOD)
2228 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2229 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
David Benjamin1fbe0642019-04-15 17:05:13 -05002230 port = socket_any_family()
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002231 portSSL = Connection(ctx, port)
2232 portSSL.bind(('', 0))
2233 portSSL.listen(3)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002234
David Benjamin1fbe0642019-04-15 17:05:13 -05002235 clientSSL = Connection(Context(TLSv1_METHOD), socket(port.family))
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002236
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002237 # Calling portSSL.getsockname() here to get the server IP address
2238 # sounds great, but frequently fails on Windows.
David Benjamin1fbe0642019-04-15 17:05:13 -05002239 clientSSL.connect((loopback_address(port), portSSL.getsockname()[1]))
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002240
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002241 serverSSL, address = portSSL.accept()
2242
Alex Chan1c0cb662017-01-30 07:13:30 +00002243 assert isinstance(serverSSL, Connection)
2244 assert serverSSL.get_context() is ctx
2245 assert address == clientSSL.getsockname()
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002246
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002247 def test_shutdown_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002248 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002249 `Connection.set_shutdown` raises `TypeError` if called with arguments
2250 other than integers.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002251 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002252 connection = Connection(Context(TLSv1_METHOD), None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002253 with pytest.raises(TypeError):
2254 connection.set_shutdown(None)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002255
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002256 def test_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002257 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002258 `Connection.shutdown` performs an SSL-level connection shutdown.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002259 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002260 server, client = loopback()
2261 assert not server.shutdown()
2262 assert server.get_shutdown() == SENT_SHUTDOWN
2263 with pytest.raises(ZeroReturnError):
2264 client.recv(1024)
2265 assert client.get_shutdown() == RECEIVED_SHUTDOWN
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04002266 client.shutdown()
Alex Chan1c0cb662017-01-30 07:13:30 +00002267 assert client.get_shutdown() == (SENT_SHUTDOWN | RECEIVED_SHUTDOWN)
2268 with pytest.raises(ZeroReturnError):
2269 server.recv(1024)
2270 assert server.get_shutdown() == (SENT_SHUTDOWN | RECEIVED_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002271
Paul Aurichc85e0862015-01-08 08:34:33 -08002272 def test_shutdown_closed(self):
2273 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002274 If the underlying socket is closed, `Connection.shutdown` propagates
2275 the write error from the low level write call.
Paul Aurichc85e0862015-01-08 08:34:33 -08002276 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002277 server, client = loopback()
Paul Aurichc85e0862015-01-08 08:34:33 -08002278 server.sock_shutdown(2)
Alex Chan1c0cb662017-01-30 07:13:30 +00002279 with pytest.raises(SysCallError) as exc:
2280 server.shutdown()
Alex Chanfb078d82017-04-20 11:16:15 +01002281 if platform == "win32":
2282 assert exc.value.args[0] == ESHUTDOWN
2283 else:
2284 assert exc.value.args[0] == EPIPE
Paul Aurichc85e0862015-01-08 08:34:33 -08002285
Glyph89389472015-04-14 17:29:26 -04002286 def test_shutdown_truncated(self):
Glyph6064ec32015-04-14 16:38:22 -04002287 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002288 If the underlying connection is truncated, `Connection.shutdown`
2289 raises an `Error`.
Glyph6064ec32015-04-14 16:38:22 -04002290 """
Glyph89389472015-04-14 17:29:26 -04002291 server_ctx = Context(TLSv1_METHOD)
2292 client_ctx = Context(TLSv1_METHOD)
2293 server_ctx.use_privatekey(
2294 load_privatekey(FILETYPE_PEM, server_key_pem))
2295 server_ctx.use_certificate(
2296 load_certificate(FILETYPE_PEM, server_cert_pem))
2297 server = Connection(server_ctx, None)
2298 client = Connection(client_ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002299 handshake_in_memory(client, server)
2300 assert not server.shutdown()
2301 with pytest.raises(WantReadError):
2302 server.shutdown()
Glyph89389472015-04-14 17:29:26 -04002303 server.bio_shutdown()
Alex Chan1c0cb662017-01-30 07:13:30 +00002304 with pytest.raises(Error):
2305 server.shutdown()
Glyph6064ec32015-04-14 16:38:22 -04002306
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002307 def test_set_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002308 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002309 `Connection.set_shutdown` sets the state of the SSL connection
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002310 shutdown process.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002311 """
David Benjamin1fbe0642019-04-15 17:05:13 -05002312 connection = Connection(Context(TLSv1_METHOD), socket_any_family())
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002313 connection.set_shutdown(RECEIVED_SHUTDOWN)
Alex Chan1c0cb662017-01-30 07:13:30 +00002314 assert connection.get_shutdown() == RECEIVED_SHUTDOWN
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002315
kjavaf248592015-09-07 12:14:01 +01002316 def test_state_string(self):
2317 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002318 `Connection.state_string` verbosely describes the current state of
2319 the `Connection`.
kjavaf248592015-09-07 12:14:01 +01002320 """
Hynek Schlawackb0274ce2015-10-16 19:56:26 +02002321 server, client = socket_pair()
Alex Chan1c0cb662017-01-30 07:13:30 +00002322 server = loopback_server_factory(server)
2323 client = loopback_client_factory(client)
kjavaf248592015-09-07 12:14:01 +01002324
Alex Gaynor5af32d02016-09-24 01:52:21 -04002325 assert server.get_state_string() in [
2326 b"before/accept initialization", b"before SSL initialization"
2327 ]
2328 assert client.get_state_string() in [
2329 b"before/connect initialization", b"before SSL initialization"
2330 ]
kjavaf248592015-09-07 12:14:01 +01002331
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002332 def test_app_data(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002333 """
2334 Any object can be set as app data by passing it to
Alex Chan1c0cb662017-01-30 07:13:30 +00002335 `Connection.set_app_data` and later retrieved with
2336 `Connection.get_app_data`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002337 """
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002338 conn = Connection(Context(TLSv1_METHOD), None)
Todd Chapman4f73e4f2015-08-27 11:26:43 -04002339 assert None is conn.get_app_data()
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002340 app_data = object()
2341 conn.set_app_data(app_data)
Todd Chapman4f73e4f2015-08-27 11:26:43 -04002342 assert conn.get_app_data() is app_data
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002343
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002344 def test_makefile(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002345 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002346 `Connection.makefile` is not implemented and calling that
2347 method raises `NotImplementedError`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002348 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002349 conn = Connection(Context(TLSv1_METHOD), None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002350 with pytest.raises(NotImplementedError):
2351 conn.makefile()
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002352
Jeremy Lainé460a19d2018-05-16 19:44:19 +02002353 def test_get_certificate(self):
2354 """
2355 `Connection.get_certificate` returns the local certificate.
2356 """
2357 chain = _create_certificate_chain()
2358 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
2359
2360 context = Context(TLSv1_METHOD)
2361 context.use_certificate(scert)
2362 client = Connection(context, None)
2363 cert = client.get_certificate()
2364 assert cert is not None
2365 assert "Server Certificate" == cert.get_subject().CN
2366
2367 def test_get_certificate_none(self):
2368 """
2369 `Connection.get_certificate` returns the local certificate.
2370
2371 If there is no certificate, it returns None.
2372 """
2373 context = Context(TLSv1_METHOD)
2374 client = Connection(context, None)
2375 cert = client.get_certificate()
2376 assert cert is None
2377
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002378 def test_get_peer_cert_chain(self):
2379 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002380 `Connection.get_peer_cert_chain` returns a list of certificates
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002381 which the connected server returned for the certification verification.
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002382 """
2383 chain = _create_certificate_chain()
2384 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
2385
2386 serverContext = Context(TLSv1_METHOD)
2387 serverContext.use_privatekey(skey)
2388 serverContext.use_certificate(scert)
2389 serverContext.add_extra_chain_cert(icert)
2390 serverContext.add_extra_chain_cert(cacert)
2391 server = Connection(serverContext, None)
2392 server.set_accept_state()
2393
2394 # Create the client
2395 clientContext = Context(TLSv1_METHOD)
2396 clientContext.set_verify(VERIFY_NONE, verify_cb)
2397 client = Connection(clientContext, None)
2398 client.set_connect_state()
2399
Alex Chan1c0cb662017-01-30 07:13:30 +00002400 interact_in_memory(client, server)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002401
2402 chain = client.get_peer_cert_chain()
Alex Chan1c0cb662017-01-30 07:13:30 +00002403 assert len(chain) == 3
2404 assert "Server Certificate" == chain[0].get_subject().CN
2405 assert "Intermediate Certificate" == chain[1].get_subject().CN
2406 assert "Authority Certificate" == chain[2].get_subject().CN
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002407
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002408 def test_get_peer_cert_chain_none(self):
2409 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002410 `Connection.get_peer_cert_chain` returns `None` if the peer sends
2411 no certificate chain.
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002412 """
2413 ctx = Context(TLSv1_METHOD)
2414 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2415 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
2416 server = Connection(ctx, None)
2417 server.set_accept_state()
2418 client = Connection(Context(TLSv1_METHOD), None)
2419 client.set_connect_state()
Alex Chan1c0cb662017-01-30 07:13:30 +00002420 interact_in_memory(client, server)
2421 assert None is server.get_peer_cert_chain()
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002422
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002423 def test_get_session_unconnected(self):
2424 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002425 `Connection.get_session` returns `None` when used with an object
2426 which has not been connected.
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002427 """
2428 ctx = Context(TLSv1_METHOD)
2429 server = Connection(ctx, None)
2430 session = server.get_session()
Alex Chan1c0cb662017-01-30 07:13:30 +00002431 assert None is session
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002432
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002433 def test_server_get_session(self):
2434 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002435 On the server side of a connection, `Connection.get_session` returns a
2436 `Session` instance representing the SSL session for that connection.
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002437 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002438 server, client = loopback()
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002439 session = server.get_session()
Alex Chan1c0cb662017-01-30 07:13:30 +00002440 assert isinstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002441
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002442 def test_client_get_session(self):
2443 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002444 On the client side of a connection, `Connection.get_session`
2445 returns a `Session` instance representing the SSL session for
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002446 that connection.
2447 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002448 server, client = loopback()
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002449 session = client.get_session()
Alex Chan1c0cb662017-01-30 07:13:30 +00002450 assert isinstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002451
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002452 def test_set_session_wrong_args(self):
2453 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002454 `Connection.set_session` raises `TypeError` if called with an object
2455 that is not an instance of `Session`.
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002456 """
2457 ctx = Context(TLSv1_METHOD)
2458 connection = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002459 with pytest.raises(TypeError):
2460 connection.set_session(123)
2461 with pytest.raises(TypeError):
2462 connection.set_session("hello")
2463 with pytest.raises(TypeError):
2464 connection.set_session(object())
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002465
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002466 def test_client_set_session(self):
2467 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002468 `Connection.set_session`, when used prior to a connection being
2469 established, accepts a `Session` instance and causes an attempt to
2470 re-use the session it represents when the SSL handshake is performed.
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002471 """
2472 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2473 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
Paul Kehrer7d5a3bf2019-01-21 12:24:02 -06002474 ctx = Context(TLSv1_2_METHOD)
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002475 ctx.use_privatekey(key)
2476 ctx.use_certificate(cert)
2477 ctx.set_session_id("unity-test")
2478
2479 def makeServer(socket):
2480 server = Connection(ctx, socket)
2481 server.set_accept_state()
2482 return server
2483
Alex Chan1c0cb662017-01-30 07:13:30 +00002484 originalServer, originalClient = loopback(
2485 server_factory=makeServer)
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002486 originalSession = originalClient.get_session()
2487
2488 def makeClient(socket):
Alex Chan1c0cb662017-01-30 07:13:30 +00002489 client = loopback_client_factory(socket)
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002490 client.set_session(originalSession)
2491 return client
Alex Chan1c0cb662017-01-30 07:13:30 +00002492 resumedServer, resumedClient = loopback(
2493 server_factory=makeServer,
2494 client_factory=makeClient)
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002495
2496 # This is a proxy: in general, we have no access to any unique
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002497 # identifier for the session (new enough versions of OpenSSL expose
2498 # a hash which could be usable, but "new enough" is very, very new).
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002499 # Instead, exploit the fact that the master key is re-used if the
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002500 # session is re-used. As long as the master key for the two
2501 # connections is the same, the session was re-used!
Alex Chan1c0cb662017-01-30 07:13:30 +00002502 assert originalServer.master_key() == resumedServer.master_key()
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002503
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002504 def test_set_session_wrong_method(self):
2505 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002506 If `Connection.set_session` is passed a `Session` instance associated
2507 with a context using a different SSL method than the `Connection`
2508 is using, a `OpenSSL.SSL.Error` is raised.
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002509 """
Alex Gaynor5af32d02016-09-24 01:52:21 -04002510 # Make this work on both OpenSSL 1.0.0, which doesn't support TLSv1.2
2511 # and also on OpenSSL 1.1.0 which doesn't support SSLv3. (SSL_ST_INIT
2512 # is a way to check for 1.1.0)
Alex Gaynoraa32e712017-06-29 20:56:12 -07002513 if SSL_ST_INIT is None:
2514 v1 = TLSv1_2_METHOD
2515 v2 = TLSv1_METHOD
2516 elif hasattr(_lib, "SSLv3_method"):
Alex Gaynor5af32d02016-09-24 01:52:21 -04002517 v1 = TLSv1_METHOD
2518 v2 = SSLv3_METHOD
2519 else:
Alex Gaynoraa32e712017-06-29 20:56:12 -07002520 pytest.skip("Test requires either OpenSSL 1.1.0 or SSLv3")
Alex Gaynor5af32d02016-09-24 01:52:21 -04002521
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002522 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2523 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
Alex Gaynor5af32d02016-09-24 01:52:21 -04002524 ctx = Context(v1)
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002525 ctx.use_privatekey(key)
2526 ctx.use_certificate(cert)
2527 ctx.set_session_id("unity-test")
2528
2529 def makeServer(socket):
2530 server = Connection(ctx, socket)
2531 server.set_accept_state()
2532 return server
2533
Alex Gaynor5af32d02016-09-24 01:52:21 -04002534 def makeOriginalClient(socket):
2535 client = Connection(Context(v1), socket)
2536 client.set_connect_state()
2537 return client
2538
Alex Chan1c0cb662017-01-30 07:13:30 +00002539 originalServer, originalClient = loopback(
2540 server_factory=makeServer, client_factory=makeOriginalClient)
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002541 originalSession = originalClient.get_session()
2542
2543 def makeClient(socket):
2544 # Intentionally use a different, incompatible method here.
Alex Gaynor5af32d02016-09-24 01:52:21 -04002545 client = Connection(Context(v2), socket)
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002546 client.set_connect_state()
2547 client.set_session(originalSession)
2548 return client
2549
Alex Chan1c0cb662017-01-30 07:13:30 +00002550 with pytest.raises(Error):
2551 loopback(client_factory=makeClient, server_factory=makeServer)
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002552
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002553 def test_wantWriteError(self):
2554 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002555 `Connection` methods which generate output raise
2556 `OpenSSL.SSL.WantWriteError` if writing to the connection's BIO
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002557 fail indicating a should-write state.
2558 """
2559 client_socket, server_socket = socket_pair()
2560 # Fill up the client's send buffer so Connection won't be able to write
Jean-Paul Calderonebbff8b92014-03-22 14:20:30 -04002561 # anything. Only write a single byte at a time so we can be sure we
2562 # completely fill the buffer. Even though the socket API is allowed to
2563 # signal a short write via its return value it seems this doesn't
2564 # always happen on all platforms (FreeBSD and OS X particular) for the
2565 # very last bit of available buffer space.
2566 msg = b"x"
caternb2777a42018-08-09 15:38:13 -04002567 for i in range(1024 * 1024 * 64):
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002568 try:
2569 client_socket.send(msg)
2570 except error as e:
2571 if e.errno == EWOULDBLOCK:
2572 break
2573 raise
2574 else:
Alex Chan1c0cb662017-01-30 07:13:30 +00002575 pytest.fail(
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002576 "Failed to fill socket buffer, cannot test BIO want write")
2577
2578 ctx = Context(TLSv1_METHOD)
2579 conn = Connection(ctx, client_socket)
2580 # Client's speak first, so make it an SSL client
2581 conn.set_connect_state()
Alex Chan1c0cb662017-01-30 07:13:30 +00002582 with pytest.raises(WantWriteError):
2583 conn.do_handshake()
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002584
2585 # XXX want_read
2586
Fedor Brunner416f4a12014-03-28 13:18:38 +01002587 def test_get_finished_before_connect(self):
Fedor Brunner5747b932014-03-05 14:22:34 +01002588 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002589 `Connection.get_finished` returns `None` before TLS handshake
2590 is completed.
Fedor Brunner5747b932014-03-05 14:22:34 +01002591 """
Fedor Brunner5747b932014-03-05 14:22:34 +01002592 ctx = Context(TLSv1_METHOD)
2593 connection = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002594 assert connection.get_finished() is None
Fedor Brunner416f4a12014-03-28 13:18:38 +01002595
2596 def test_get_peer_finished_before_connect(self):
2597 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002598 `Connection.get_peer_finished` returns `None` before TLS handshake
2599 is completed.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002600 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002601 ctx = Context(TLSv1_METHOD)
2602 connection = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002603 assert connection.get_peer_finished() is None
Fedor Brunner5747b932014-03-05 14:22:34 +01002604
Fedor Brunner416f4a12014-03-28 13:18:38 +01002605 def test_get_finished(self):
2606 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002607 `Connection.get_finished` method returns the TLS Finished message send
2608 from client, or server. Finished messages are send during
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002609 TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002610 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002611 server, client = loopback()
Fedor Brunner416f4a12014-03-28 13:18:38 +01002612
Alex Chan1c0cb662017-01-30 07:13:30 +00002613 assert server.get_finished() is not None
2614 assert len(server.get_finished()) > 0
Fedor Brunner416f4a12014-03-28 13:18:38 +01002615
2616 def test_get_peer_finished(self):
2617 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002618 `Connection.get_peer_finished` method returns the TLS Finished
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002619 message received from client, or server. Finished messages are send
2620 during TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002621 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002622 server, client = loopback()
Fedor Brunner416f4a12014-03-28 13:18:38 +01002623
Alex Chan1c0cb662017-01-30 07:13:30 +00002624 assert server.get_peer_finished() is not None
2625 assert len(server.get_peer_finished()) > 0
Fedor Brunner5747b932014-03-05 14:22:34 +01002626
Fedor Brunner416f4a12014-03-28 13:18:38 +01002627 def test_tls_finished_message_symmetry(self):
2628 """
Hynek Schlawackdddd1112015-09-05 21:12:30 +02002629 The TLS Finished message send by server must be the TLS Finished
2630 message received by client.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002631
Hynek Schlawackdddd1112015-09-05 21:12:30 +02002632 The TLS Finished message send by client must be the TLS Finished
2633 message received by server.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002634 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002635 server, client = loopback()
Fedor Brunner416f4a12014-03-28 13:18:38 +01002636
Alex Chan1c0cb662017-01-30 07:13:30 +00002637 assert server.get_finished() == client.get_peer_finished()
2638 assert client.get_finished() == server.get_peer_finished()
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002639
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002640 def test_get_cipher_name_before_connect(self):
2641 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002642 `Connection.get_cipher_name` returns `None` if no connection
2643 has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002644 """
2645 ctx = Context(TLSv1_METHOD)
2646 conn = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002647 assert conn.get_cipher_name() is None
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002648
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002649 def test_get_cipher_name(self):
2650 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002651 `Connection.get_cipher_name` returns a `unicode` string giving the
2652 name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002653 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002654 server, client = loopback()
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002655 server_cipher_name, client_cipher_name = \
2656 server.get_cipher_name(), client.get_cipher_name()
2657
Alex Chan1c0cb662017-01-30 07:13:30 +00002658 assert isinstance(server_cipher_name, text_type)
2659 assert isinstance(client_cipher_name, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002660
Alex Chan1c0cb662017-01-30 07:13:30 +00002661 assert server_cipher_name == client_cipher_name
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002662
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002663 def test_get_cipher_version_before_connect(self):
2664 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002665 `Connection.get_cipher_version` returns `None` if no connection
2666 has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002667 """
2668 ctx = Context(TLSv1_METHOD)
2669 conn = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002670 assert conn.get_cipher_version() is None
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002671
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002672 def test_get_cipher_version(self):
2673 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002674 `Connection.get_cipher_version` returns a `unicode` string giving
2675 the protocol name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002676 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002677 server, client = loopback()
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002678 server_cipher_version, client_cipher_version = \
2679 server.get_cipher_version(), client.get_cipher_version()
2680
Alex Chan1c0cb662017-01-30 07:13:30 +00002681 assert isinstance(server_cipher_version, text_type)
2682 assert isinstance(client_cipher_version, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002683
Alex Chan1c0cb662017-01-30 07:13:30 +00002684 assert server_cipher_version == client_cipher_version
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002685
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002686 def test_get_cipher_bits_before_connect(self):
2687 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002688 `Connection.get_cipher_bits` returns `None` if no connection has
2689 been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002690 """
2691 ctx = Context(TLSv1_METHOD)
2692 conn = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002693 assert conn.get_cipher_bits() is None
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002694
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002695 def test_get_cipher_bits(self):
2696 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002697 `Connection.get_cipher_bits` returns the number of secret bits
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002698 of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002699 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002700 server, client = loopback()
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002701 server_cipher_bits, client_cipher_bits = \
2702 server.get_cipher_bits(), client.get_cipher_bits()
2703
Alex Chan1c0cb662017-01-30 07:13:30 +00002704 assert isinstance(server_cipher_bits, int)
2705 assert isinstance(client_cipher_bits, int)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002706
Alex Chan1c0cb662017-01-30 07:13:30 +00002707 assert server_cipher_bits == client_cipher_bits
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002708
Jim Shaverabff1882015-05-27 09:15:55 -04002709 def test_get_protocol_version_name(self):
2710 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002711 `Connection.get_protocol_version_name()` returns a string giving the
2712 protocol version of the current connection.
Jim Shaverabff1882015-05-27 09:15:55 -04002713 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002714 server, client = loopback()
Jim Shaverabff1882015-05-27 09:15:55 -04002715 client_protocol_version_name = client.get_protocol_version_name()
2716 server_protocol_version_name = server.get_protocol_version_name()
2717
Alex Chan1c0cb662017-01-30 07:13:30 +00002718 assert isinstance(server_protocol_version_name, text_type)
2719 assert isinstance(client_protocol_version_name, text_type)
Jim Shaverabff1882015-05-27 09:15:55 -04002720
Alex Chan1c0cb662017-01-30 07:13:30 +00002721 assert server_protocol_version_name == client_protocol_version_name
Jim Shaverabff1882015-05-27 09:15:55 -04002722
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002723 def test_get_protocol_version(self):
2724 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002725 `Connection.get_protocol_version()` returns an integer
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002726 giving the protocol version of the current connection.
2727 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002728 server, client = loopback()
Jim Shaver85a4dff2015-04-27 17:42:46 -04002729 client_protocol_version = client.get_protocol_version()
2730 server_protocol_version = server.get_protocol_version()
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002731
Alex Chan1c0cb662017-01-30 07:13:30 +00002732 assert isinstance(server_protocol_version, int)
2733 assert isinstance(client_protocol_version, int)
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002734
Alex Chan1c0cb662017-01-30 07:13:30 +00002735 assert server_protocol_version == client_protocol_version
2736
2737 def test_wantReadError(self):
2738 """
2739 `Connection.bio_read` raises `OpenSSL.SSL.WantReadError` if there are
2740 no bytes available to be read from the BIO.
2741 """
2742 ctx = Context(TLSv1_METHOD)
2743 conn = Connection(ctx, None)
2744 with pytest.raises(WantReadError):
2745 conn.bio_read(1024)
2746
Alex Chanfb078d82017-04-20 11:16:15 +01002747 @pytest.mark.parametrize('bufsize', [1.0, None, object(), 'bufsize'])
2748 def test_bio_read_wrong_args(self, bufsize):
2749 """
2750 `Connection.bio_read` raises `TypeError` if passed a non-integer
2751 argument.
2752 """
2753 ctx = Context(TLSv1_METHOD)
2754 conn = Connection(ctx, None)
2755 with pytest.raises(TypeError):
2756 conn.bio_read(bufsize)
2757
Alex Chan1c0cb662017-01-30 07:13:30 +00002758 def test_buffer_size(self):
2759 """
2760 `Connection.bio_read` accepts an integer giving the maximum number
2761 of bytes to read and return.
2762 """
2763 ctx = Context(TLSv1_METHOD)
2764 conn = Connection(ctx, None)
2765 conn.set_connect_state()
2766 try:
2767 conn.do_handshake()
2768 except WantReadError:
2769 pass
2770 data = conn.bio_read(2)
2771 assert 2 == len(data)
2772
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002773
Alex Chanb7480992017-01-30 14:04:47 +00002774class TestConnectionGetCipherList(object):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002775 """
Alex Chanb7480992017-01-30 14:04:47 +00002776 Tests for `Connection.get_cipher_list`.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002777 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002778 def test_result(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002779 """
Alex Chanb7480992017-01-30 14:04:47 +00002780 `Connection.get_cipher_list` returns a list of `bytes` giving the
2781 names of the ciphers which might be used.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002782 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002783 connection = Connection(Context(TLSv1_METHOD), None)
2784 ciphers = connection.get_cipher_list()
Alex Chanb7480992017-01-30 14:04:47 +00002785 assert isinstance(ciphers, list)
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002786 for cipher in ciphers:
Alex Chanb7480992017-01-30 14:04:47 +00002787 assert isinstance(cipher, str)
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002788
2789
Maximilian Hils868dc3c2017-02-10 14:56:55 +01002790class VeryLarge(bytes):
2791 """
2792 Mock object so that we don't have to allocate 2**31 bytes
2793 """
2794 def __len__(self):
2795 return 2**31
2796
2797
Alex Chanb7480992017-01-30 14:04:47 +00002798class TestConnectionSend(object):
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002799 """
Alex Chanb7480992017-01-30 14:04:47 +00002800 Tests for `Connection.send`.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002801 """
2802 def test_wrong_args(self):
2803 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002804 When called with arguments other than string argument for its first
Alex Chanb7480992017-01-30 14:04:47 +00002805 parameter, `Connection.send` raises `TypeError`.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002806 """
2807 connection = Connection(Context(TLSv1_METHOD), None)
Alex Chanb7480992017-01-30 14:04:47 +00002808 with pytest.raises(TypeError):
2809 connection.send(object())
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002810
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002811 def test_short_bytes(self):
2812 """
Alex Chanb7480992017-01-30 14:04:47 +00002813 When passed a short byte string, `Connection.send` transmits all of it
2814 and returns the number of bytes sent.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002815 """
Alex Chanb7480992017-01-30 14:04:47 +00002816 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002817 count = server.send(b'xy')
Alex Chanb7480992017-01-30 14:04:47 +00002818 assert count == 2
2819 assert client.recv(2) == b'xy'
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002820
Abraham Martinef063482015-03-25 14:06:24 +00002821 def test_text(self):
2822 """
Alex Chanb7480992017-01-30 14:04:47 +00002823 When passed a text, `Connection.send` transmits all of it and
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002824 returns the number of bytes sent. It also raises a DeprecationWarning.
Abraham Martinef063482015-03-25 14:06:24 +00002825 """
Alex Chanb7480992017-01-30 14:04:47 +00002826 server, client = loopback()
2827 with pytest.warns(DeprecationWarning) as w:
Abraham Martinef063482015-03-25 14:06:24 +00002828 simplefilter("always")
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002829 count = server.send(b"xy".decode("ascii"))
Alex Chanb7480992017-01-30 14:04:47 +00002830 assert (
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002831 "{0} for buf is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002832 WARNING_TYPE_EXPECTED
Alex Chanb7480992017-01-30 14:04:47 +00002833 ) == str(w[-1].message))
2834 assert count == 2
2835 assert client.recv(2) == b'xy'
Abraham Martinef063482015-03-25 14:06:24 +00002836
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002837 def test_short_memoryview(self):
2838 """
2839 When passed a memoryview onto a small number of bytes,
Alex Chanb7480992017-01-30 14:04:47 +00002840 `Connection.send` transmits all of them and returns the number
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002841 of bytes sent.
2842 """
Alex Chanb7480992017-01-30 14:04:47 +00002843 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002844 count = server.send(memoryview(b'xy'))
Alex Chanb7480992017-01-30 14:04:47 +00002845 assert count == 2
2846 assert client.recv(2) == b'xy'
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002847
Hynek Schlawack8e94f1b2015-09-05 21:31:00 +02002848 @skip_if_py3
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002849 def test_short_buffer(self):
2850 """
2851 When passed a buffer containing a small number of bytes,
Alex Chanb7480992017-01-30 14:04:47 +00002852 `Connection.send` transmits all of them and returns the number
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002853 of bytes sent.
2854 """
Alex Chanb7480992017-01-30 14:04:47 +00002855 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002856 count = server.send(buffer(b'xy'))
Alex Chanb7480992017-01-30 14:04:47 +00002857 assert count == 2
2858 assert client.recv(2) == b'xy'
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02002859
Maximilian Hils868dc3c2017-02-10 14:56:55 +01002860 @pytest.mark.skipif(
2861 sys.maxsize < 2**31,
2862 reason="sys.maxsize < 2**31 - test requires 64 bit"
2863 )
2864 def test_buf_too_large(self):
2865 """
2866 When passed a buffer containing >= 2**31 bytes,
2867 `Connection.send` bails out as SSL_write only
2868 accepts an int for the buffer length.
2869 """
2870 connection = Connection(Context(TLSv1_METHOD), None)
2871 with pytest.raises(ValueError) as exc_info:
2872 connection.send(VeryLarge())
2873 exc_info.match(r"Cannot send more than .+ bytes at once")
2874
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05002875
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002876def _make_memoryview(size):
2877 """
2878 Create a new ``memoryview`` wrapped around a ``bytearray`` of the given
2879 size.
2880 """
2881 return memoryview(bytearray(size))
2882
2883
Alex Chanb7480992017-01-30 14:04:47 +00002884class TestConnectionRecvInto(object):
Cory Benfield62d10332014-06-15 10:03:41 +01002885 """
Alex Chanb7480992017-01-30 14:04:47 +00002886 Tests for `Connection.recv_into`.
Cory Benfield62d10332014-06-15 10:03:41 +01002887 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002888 def _no_length_test(self, factory):
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04002889 """
Alex Chanb7480992017-01-30 14:04:47 +00002890 Assert that when the given buffer is passed to `Connection.recv_into`,
2891 whatever bytes are available to be received that fit into that buffer
2892 are written into that buffer.
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04002893 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002894 output_buffer = factory(5)
2895
Alex Chanb7480992017-01-30 14:04:47 +00002896 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002897 server.send(b'xy')
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04002898
Alex Chanb7480992017-01-30 14:04:47 +00002899 assert client.recv_into(output_buffer) == 2
2900 assert output_buffer == bytearray(b'xy\x00\x00\x00')
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04002901
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002902 def test_bytearray_no_length(self):
Cory Benfield62d10332014-06-15 10:03:41 +01002903 """
Alex Chanb7480992017-01-30 14:04:47 +00002904 `Connection.recv_into` can be passed a `bytearray` instance and data
2905 in the receive buffer is written to it.
Cory Benfield62d10332014-06-15 10:03:41 +01002906 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002907 self._no_length_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01002908
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002909 def _respects_length_test(self, factory):
Cory Benfield62d10332014-06-15 10:03:41 +01002910 """
Alex Chanb7480992017-01-30 14:04:47 +00002911 Assert that when the given buffer is passed to `Connection.recv_into`
2912 along with a value for `nbytes` that is less than the size of that
2913 buffer, only `nbytes` bytes are written into the buffer.
Cory Benfield62d10332014-06-15 10:03:41 +01002914 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002915 output_buffer = factory(10)
2916
Alex Chanb7480992017-01-30 14:04:47 +00002917 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002918 server.send(b'abcdefghij')
Cory Benfield62d10332014-06-15 10:03:41 +01002919
Alex Chanb7480992017-01-30 14:04:47 +00002920 assert client.recv_into(output_buffer, 5) == 5
2921 assert output_buffer == bytearray(b'abcde\x00\x00\x00\x00\x00')
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002922
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002923 def test_bytearray_respects_length(self):
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002924 """
Alex Chanb7480992017-01-30 14:04:47 +00002925 When called with a `bytearray` instance, `Connection.recv_into`
2926 respects the `nbytes` parameter and doesn't copy in more than that
2927 number of bytes.
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002928 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002929 self._respects_length_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01002930
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002931 def _doesnt_overfill_test(self, factory):
Cory Benfield62d10332014-06-15 10:03:41 +01002932 """
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002933 Assert that if there are more bytes available to be read from the
2934 receive buffer than would fit into the buffer passed to
Alex Chanb7480992017-01-30 14:04:47 +00002935 `Connection.recv_into`, only as many as fit are written into it.
Cory Benfield62d10332014-06-15 10:03:41 +01002936 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002937 output_buffer = factory(5)
2938
Alex Chanb7480992017-01-30 14:04:47 +00002939 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002940 server.send(b'abcdefghij')
Cory Benfield62d10332014-06-15 10:03:41 +01002941
Alex Chanb7480992017-01-30 14:04:47 +00002942 assert client.recv_into(output_buffer) == 5
2943 assert output_buffer == bytearray(b'abcde')
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002944 rest = client.recv(5)
Alex Chanb7480992017-01-30 14:04:47 +00002945 assert b'fghij' == rest
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002946
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002947 def test_bytearray_doesnt_overfill(self):
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002948 """
Alex Chanb7480992017-01-30 14:04:47 +00002949 When called with a `bytearray` instance, `Connection.recv_into`
2950 respects the size of the array and doesn't write more bytes into it
2951 than will fit.
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002952 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002953 self._doesnt_overfill_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01002954
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002955 def test_bytearray_really_doesnt_overfill(self):
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04002956 """
Alex Chanb7480992017-01-30 14:04:47 +00002957 When called with a `bytearray` instance and an `nbytes` value that is
2958 too large, `Connection.recv_into` respects the size of the array and
2959 not the `nbytes` value and doesn't write more bytes into the buffer
2960 than will fit.
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04002961 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002962 self._doesnt_overfill_test(bytearray)
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04002963
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002964 def test_peek(self):
Alex Chanb7480992017-01-30 14:04:47 +00002965 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002966 server.send(b'xy')
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002967
2968 for _ in range(2):
2969 output_buffer = bytearray(5)
Alex Chanb7480992017-01-30 14:04:47 +00002970 assert client.recv_into(output_buffer, flags=MSG_PEEK) == 2
2971 assert output_buffer == bytearray(b'xy\x00\x00\x00')
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002972
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002973 def test_memoryview_no_length(self):
2974 """
Alex Chanb7480992017-01-30 14:04:47 +00002975 `Connection.recv_into` can be passed a `memoryview` instance and data
2976 in the receive buffer is written to it.
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002977 """
2978 self._no_length_test(_make_memoryview)
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002979
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002980 def test_memoryview_respects_length(self):
2981 """
Alex Chanb7480992017-01-30 14:04:47 +00002982 When called with a `memoryview` instance, `Connection.recv_into`
2983 respects the ``nbytes`` parameter and doesn't copy more than that
2984 number of bytes in.
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002985 """
2986 self._respects_length_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01002987
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002988 def test_memoryview_doesnt_overfill(self):
2989 """
Alex Chanb7480992017-01-30 14:04:47 +00002990 When called with a `memoryview` instance, `Connection.recv_into`
2991 respects the size of the array and doesn't write more bytes into it
2992 than will fit.
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002993 """
2994 self._doesnt_overfill_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01002995
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002996 def test_memoryview_really_doesnt_overfill(self):
2997 """
Alex Chanb7480992017-01-30 14:04:47 +00002998 When called with a `memoryview` instance and an `nbytes` value that is
2999 too large, `Connection.recv_into` respects the size of the array and
3000 not the `nbytes` value and doesn't write more bytes into the buffer
3001 than will fit.
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003002 """
3003 self._doesnt_overfill_test(_make_memoryview)
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003004
Cory Benfield62d10332014-06-15 10:03:41 +01003005
Alex Chanb7480992017-01-30 14:04:47 +00003006class TestConnectionSendall(object):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003007 """
Alex Chanb7480992017-01-30 14:04:47 +00003008 Tests for `Connection.sendall`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003009 """
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003010 def test_wrong_args(self):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003011 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003012 When called with arguments other than a string argument for its first
Alex Chanb7480992017-01-30 14:04:47 +00003013 parameter, `Connection.sendall` raises `TypeError`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003014 """
3015 connection = Connection(Context(TLSv1_METHOD), None)
Alex Chanb7480992017-01-30 14:04:47 +00003016 with pytest.raises(TypeError):
3017 connection.sendall(object())
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003018
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003019 def test_short(self):
3020 """
Alex Chanb7480992017-01-30 14:04:47 +00003021 `Connection.sendall` transmits all of the bytes in the string
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003022 passed to it.
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003023 """
Alex Chanb7480992017-01-30 14:04:47 +00003024 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04003025 server.sendall(b'x')
Alex Chanb7480992017-01-30 14:04:47 +00003026 assert client.recv(1) == b'x'
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003027
Abraham Martinef063482015-03-25 14:06:24 +00003028 def test_text(self):
3029 """
Alex Chanb7480992017-01-30 14:04:47 +00003030 `Connection.sendall` transmits all the content in the string passed
3031 to it, raising a DeprecationWarning in case of this being a text.
Abraham Martinef063482015-03-25 14:06:24 +00003032 """
Alex Chanb7480992017-01-30 14:04:47 +00003033 server, client = loopback()
3034 with pytest.warns(DeprecationWarning) as w:
Abraham Martinef063482015-03-25 14:06:24 +00003035 simplefilter("always")
Jean-Paul Calderone8dc37a12015-03-29 08:16:52 -04003036 server.sendall(b"x".decode("ascii"))
Alex Chanb7480992017-01-30 14:04:47 +00003037 assert (
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04003038 "{0} for buf is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04003039 WARNING_TYPE_EXPECTED
Alex Chanb7480992017-01-30 14:04:47 +00003040 ) == str(w[-1].message))
3041 assert client.recv(1) == b"x"
Abraham Martinef063482015-03-25 14:06:24 +00003042
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003043 def test_short_memoryview(self):
3044 """
3045 When passed a memoryview onto a small number of bytes,
Alex Chanb7480992017-01-30 14:04:47 +00003046 `Connection.sendall` transmits all of them.
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003047 """
Alex Chanb7480992017-01-30 14:04:47 +00003048 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04003049 server.sendall(memoryview(b'x'))
Alex Chanb7480992017-01-30 14:04:47 +00003050 assert client.recv(1) == b'x'
Abraham Martinef063482015-03-25 14:06:24 +00003051
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003052 @skip_if_py3
3053 def test_short_buffers(self):
3054 """
3055 When passed a buffer containing a small number of bytes,
Alex Chanb7480992017-01-30 14:04:47 +00003056 `Connection.sendall` transmits all of them.
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003057 """
Alex Chanb7480992017-01-30 14:04:47 +00003058 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04003059 server.sendall(buffer(b'x'))
Alex Chanb7480992017-01-30 14:04:47 +00003060 assert client.recv(1) == b'x'
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02003061
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003062 def test_long(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003063 """
Alex Chanb7480992017-01-30 14:04:47 +00003064 `Connection.sendall` transmits all the bytes in the string passed to it
3065 even if this requires multiple calls of an underlying write function.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003066 """
Alex Chanb7480992017-01-30 14:04:47 +00003067 server, client = loopback()
Jean-Paul Calderone6241c702010-09-16 19:59:24 -04003068 # Should be enough, underlying SSL_write should only do 16k at a time.
Hynek Schlawack35618382015-09-05 21:54:25 +02003069 # On Windows, after 32k of bytes the write will block (forever
3070 # - because no one is yet reading).
Alex Gaynore7f51982016-09-11 11:48:14 -04003071 message = b'x' * (1024 * 32 - 1) + b'y'
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003072 server.sendall(message)
3073 accum = []
3074 received = 0
3075 while received < len(message):
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04003076 data = client.recv(1024)
3077 accum.append(data)
3078 received += len(data)
Alex Chanb7480992017-01-30 14:04:47 +00003079 assert message == b''.join(accum)
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003080
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003081 def test_closed(self):
3082 """
Alex Chanb7480992017-01-30 14:04:47 +00003083 If the underlying socket is closed, `Connection.sendall` propagates the
3084 write error from the low level write call.
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003085 """
Alex Chanb7480992017-01-30 14:04:47 +00003086 server, client = loopback()
Jean-Paul Calderone05d43e82010-09-24 18:01:36 -04003087 server.sock_shutdown(2)
Alex Chanb7480992017-01-30 14:04:47 +00003088 with pytest.raises(SysCallError) as err:
3089 server.sendall(b"hello, world")
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +02003090 if platform == "win32":
Alex Chanb7480992017-01-30 14:04:47 +00003091 assert err.value.args[0] == ESHUTDOWN
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +02003092 else:
Alex Chanb7480992017-01-30 14:04:47 +00003093 assert err.value.args[0] == EPIPE
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003094
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003095
Alex Chanb7480992017-01-30 14:04:47 +00003096class TestConnectionRenegotiate(object):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003097 """
3098 Tests for SSL renegotiation APIs.
3099 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003100 def test_total_renegotiations(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003101 """
Alex Chanb7480992017-01-30 14:04:47 +00003102 `Connection.total_renegotiations` returns `0` before any renegotiations
3103 have happened.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003104 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003105 connection = Connection(Context(TLSv1_METHOD), None)
Alex Chanb7480992017-01-30 14:04:47 +00003106 assert connection.total_renegotiations() == 0
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003107
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003108 def test_renegotiate(self):
3109 """
3110 Go through a complete renegotiation cycle.
3111 """
Paul Kehrer7d5a3bf2019-01-21 12:24:02 -06003112 server, client = loopback(
3113 lambda s: loopback_server_factory(s, TLSv1_2_METHOD),
3114 lambda s: loopback_client_factory(s, TLSv1_2_METHOD),
3115 )
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003116
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003117 server.send(b"hello world")
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003118
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003119 assert b"hello world" == client.recv(len(b"hello world"))
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003120
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003121 assert 0 == server.total_renegotiations()
3122 assert False is server.renegotiate_pending()
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003123
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003124 assert True is server.renegotiate()
3125
3126 assert True is server.renegotiate_pending()
3127
3128 server.setblocking(False)
3129 client.setblocking(False)
3130
3131 client.do_handshake()
3132 server.do_handshake()
3133
3134 assert 1 == server.total_renegotiations()
3135 while False is server.renegotiate_pending():
3136 pass
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003137
3138
Alex Chanb7480992017-01-30 14:04:47 +00003139class TestError(object):
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003140 """
Alex Chanb7480992017-01-30 14:04:47 +00003141 Unit tests for `OpenSSL.SSL.Error`.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003142 """
3143 def test_type(self):
3144 """
Alex Chanb7480992017-01-30 14:04:47 +00003145 `Error` is an exception type.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003146 """
Alex Chanb7480992017-01-30 14:04:47 +00003147 assert issubclass(Error, Exception)
3148 assert Error.__name__ == 'Error'
Rick Deane15b1472009-07-09 15:53:42 -05003149
3150
Alex Chanb7480992017-01-30 14:04:47 +00003151class TestConstants(object):
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003152 """
Alex Chanb7480992017-01-30 14:04:47 +00003153 Tests for the values of constants exposed in `OpenSSL.SSL`.
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003154
3155 These are values defined by OpenSSL intended only to be used as flags to
3156 OpenSSL APIs. The only assertions it seems can be made about them is
3157 their values.
3158 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003159 @pytest.mark.skipif(
3160 OP_NO_QUERY_MTU is None,
3161 reason="OP_NO_QUERY_MTU unavailable - OpenSSL version may be too old"
3162 )
3163 def test_op_no_query_mtu(self):
3164 """
Alex Chanb7480992017-01-30 14:04:47 +00003165 The value of `OpenSSL.SSL.OP_NO_QUERY_MTU` is 0x1000, the value
3166 of `SSL_OP_NO_QUERY_MTU` defined by `openssl/ssl.h`.
Hynek Schlawack35618382015-09-05 21:54:25 +02003167 """
Alex Chanb7480992017-01-30 14:04:47 +00003168 assert OP_NO_QUERY_MTU == 0x1000
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003169
Hynek Schlawack35618382015-09-05 21:54:25 +02003170 @pytest.mark.skipif(
3171 OP_COOKIE_EXCHANGE is None,
3172 reason="OP_COOKIE_EXCHANGE unavailable - "
3173 "OpenSSL version may be too old"
3174 )
3175 def test_op_cookie_exchange(self):
3176 """
Alex Chanb7480992017-01-30 14:04:47 +00003177 The value of `OpenSSL.SSL.OP_COOKIE_EXCHANGE` is 0x2000, the
3178 value of `SSL_OP_COOKIE_EXCHANGE` defined by `openssl/ssl.h`.
Hynek Schlawack35618382015-09-05 21:54:25 +02003179 """
Alex Chanb7480992017-01-30 14:04:47 +00003180 assert OP_COOKIE_EXCHANGE == 0x2000
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003181
Hynek Schlawack35618382015-09-05 21:54:25 +02003182 @pytest.mark.skipif(
3183 OP_NO_TICKET is None,
3184 reason="OP_NO_TICKET unavailable - OpenSSL version may be too old"
3185 )
3186 def test_op_no_ticket(self):
3187 """
Alex Chanb7480992017-01-30 14:04:47 +00003188 The value of `OpenSSL.SSL.OP_NO_TICKET` is 0x4000, the value of
3189 `SSL_OP_NO_TICKET` defined by `openssl/ssl.h`.
Hynek Schlawack35618382015-09-05 21:54:25 +02003190 """
Alex Chanb7480992017-01-30 14:04:47 +00003191 assert OP_NO_TICKET == 0x4000
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003192
Hynek Schlawack35618382015-09-05 21:54:25 +02003193 @pytest.mark.skipif(
3194 OP_NO_COMPRESSION is None,
3195 reason="OP_NO_COMPRESSION unavailable - OpenSSL version may be too old"
3196 )
3197 def test_op_no_compression(self):
3198 """
Alex Chanb7480992017-01-30 14:04:47 +00003199 The value of `OpenSSL.SSL.OP_NO_COMPRESSION` is 0x20000, the
3200 value of `SSL_OP_NO_COMPRESSION` defined by `openssl/ssl.h`.
Hynek Schlawack35618382015-09-05 21:54:25 +02003201 """
Alex Chanb7480992017-01-30 14:04:47 +00003202 assert OP_NO_COMPRESSION == 0x20000
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04003203
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003204 def test_sess_cache_off(self):
3205 """
Alex Chanb7480992017-01-30 14:04:47 +00003206 The value of `OpenSSL.SSL.SESS_CACHE_OFF` 0x0, the value of
3207 `SSL_SESS_CACHE_OFF` defined by `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003208 """
Alex Chanb7480992017-01-30 14:04:47 +00003209 assert 0x0 == SESS_CACHE_OFF
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003210
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003211 def test_sess_cache_client(self):
3212 """
Alex Chanb7480992017-01-30 14:04:47 +00003213 The value of `OpenSSL.SSL.SESS_CACHE_CLIENT` 0x1, the value of
3214 `SSL_SESS_CACHE_CLIENT` defined by `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003215 """
Alex Chanb7480992017-01-30 14:04:47 +00003216 assert 0x1 == SESS_CACHE_CLIENT
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003217
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003218 def test_sess_cache_server(self):
3219 """
Alex Chanb7480992017-01-30 14:04:47 +00003220 The value of `OpenSSL.SSL.SESS_CACHE_SERVER` 0x2, the value of
3221 `SSL_SESS_CACHE_SERVER` defined by `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003222 """
Alex Chanb7480992017-01-30 14:04:47 +00003223 assert 0x2 == SESS_CACHE_SERVER
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003224
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003225 def test_sess_cache_both(self):
3226 """
Alex Chanb7480992017-01-30 14:04:47 +00003227 The value of `OpenSSL.SSL.SESS_CACHE_BOTH` 0x3, the value of
3228 `SSL_SESS_CACHE_BOTH` defined by `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003229 """
Alex Chanb7480992017-01-30 14:04:47 +00003230 assert 0x3 == SESS_CACHE_BOTH
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003231
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003232 def test_sess_cache_no_auto_clear(self):
3233 """
Alex Chanb7480992017-01-30 14:04:47 +00003234 The value of `OpenSSL.SSL.SESS_CACHE_NO_AUTO_CLEAR` 0x80, the
3235 value of `SSL_SESS_CACHE_NO_AUTO_CLEAR` defined by
3236 `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003237 """
Alex Chanb7480992017-01-30 14:04:47 +00003238 assert 0x80 == SESS_CACHE_NO_AUTO_CLEAR
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003239
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003240 def test_sess_cache_no_internal_lookup(self):
3241 """
Alex Chanb7480992017-01-30 14:04:47 +00003242 The value of `OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_LOOKUP` 0x100,
3243 the value of `SSL_SESS_CACHE_NO_INTERNAL_LOOKUP` defined by
3244 `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003245 """
Alex Chanb7480992017-01-30 14:04:47 +00003246 assert 0x100 == SESS_CACHE_NO_INTERNAL_LOOKUP
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003247
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003248 def test_sess_cache_no_internal_store(self):
3249 """
Alex Chanb7480992017-01-30 14:04:47 +00003250 The value of `OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_STORE` 0x200,
3251 the value of `SSL_SESS_CACHE_NO_INTERNAL_STORE` defined by
3252 `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003253 """
Alex Chanb7480992017-01-30 14:04:47 +00003254 assert 0x200 == SESS_CACHE_NO_INTERNAL_STORE
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003255
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003256 def test_sess_cache_no_internal(self):
3257 """
Alex Chanb7480992017-01-30 14:04:47 +00003258 The value of `OpenSSL.SSL.SESS_CACHE_NO_INTERNAL` 0x300, the
3259 value of `SSL_SESS_CACHE_NO_INTERNAL` defined by
3260 `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003261 """
Alex Chanb7480992017-01-30 14:04:47 +00003262 assert 0x300 == SESS_CACHE_NO_INTERNAL
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003263
3264
Alex Chanb7480992017-01-30 14:04:47 +00003265class TestMemoryBIO(object):
Rick Deanb71c0d22009-04-01 14:09:23 -05003266 """
Alex Chanb7480992017-01-30 14:04:47 +00003267 Tests for `OpenSSL.SSL.Connection` using a memory BIO.
Rick Deanb71c0d22009-04-01 14:09:23 -05003268 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003269 def _server(self, sock):
3270 """
Alex Chanb7480992017-01-30 14:04:47 +00003271 Create a new server-side SSL `Connection` object wrapped around `sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003272 """
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003273 # Create the server side Connection. This is mostly setup boilerplate
3274 # - use TLSv1, use a particular certificate, etc.
3275 server_ctx = Context(TLSv1_METHOD)
Alex Gaynor43307782015-09-04 09:05:45 -04003276 server_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE)
Hynek Schlawack35618382015-09-05 21:54:25 +02003277 server_ctx.set_verify(
3278 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT | VERIFY_CLIENT_ONCE,
3279 verify_cb
3280 )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003281 server_store = server_ctx.get_cert_store()
Hynek Schlawack35618382015-09-05 21:54:25 +02003282 server_ctx.use_privatekey(
3283 load_privatekey(FILETYPE_PEM, server_key_pem))
3284 server_ctx.use_certificate(
3285 load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003286 server_ctx.check_privatekey()
3287 server_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Hynek Schlawack35618382015-09-05 21:54:25 +02003288 # Here the Connection is actually created. If None is passed as the
3289 # 2nd parameter, it indicates a memory BIO should be created.
Rick Deanb1ccd562009-07-09 23:52:39 -05003290 server_conn = Connection(server_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003291 server_conn.set_accept_state()
3292 return server_conn
3293
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003294 def _client(self, sock):
3295 """
Alex Chanb7480992017-01-30 14:04:47 +00003296 Create a new client-side SSL `Connection` object wrapped around `sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003297 """
3298 # Now create the client side Connection. Similar boilerplate to the
3299 # above.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003300 client_ctx = Context(TLSv1_METHOD)
Alex Gaynor43307782015-09-04 09:05:45 -04003301 client_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE)
Hynek Schlawack35618382015-09-05 21:54:25 +02003302 client_ctx.set_verify(
3303 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT | VERIFY_CLIENT_ONCE,
3304 verify_cb
3305 )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003306 client_store = client_ctx.get_cert_store()
Hynek Schlawack35618382015-09-05 21:54:25 +02003307 client_ctx.use_privatekey(
3308 load_privatekey(FILETYPE_PEM, client_key_pem))
3309 client_ctx.use_certificate(
3310 load_certificate(FILETYPE_PEM, client_cert_pem))
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003311 client_ctx.check_privatekey()
3312 client_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05003313 client_conn = Connection(client_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003314 client_conn.set_connect_state()
3315 return client_conn
3316
Alex Chanb7480992017-01-30 14:04:47 +00003317 def test_memory_connect(self):
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003318 """
Alex Chanb7480992017-01-30 14:04:47 +00003319 Two `Connection`s which use memory BIOs can be manually connected by
3320 reading from the output of each and writing those bytes to the input of
3321 the other and in this way establish a connection and exchange
3322 application-level bytes with each other.
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003323 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003324 server_conn = self._server(None)
3325 client_conn = self._client(None)
Rick Deanb71c0d22009-04-01 14:09:23 -05003326
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003327 # There should be no key or nonces yet.
Alex Chanb7480992017-01-30 14:04:47 +00003328 assert server_conn.master_key() is None
3329 assert server_conn.client_random() is None
3330 assert server_conn.server_random() is None
Rick Deanb71c0d22009-04-01 14:09:23 -05003331
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003332 # First, the handshake needs to happen. We'll deliver bytes back and
3333 # forth between the client and server until neither of them feels like
3334 # speaking any more.
Alex Chanb7480992017-01-30 14:04:47 +00003335 assert interact_in_memory(client_conn, server_conn) is None
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003336
3337 # Now that the handshake is done, there should be a key and nonces.
Alex Chanb7480992017-01-30 14:04:47 +00003338 assert server_conn.master_key() is not None
3339 assert server_conn.client_random() is not None
3340 assert server_conn.server_random() is not None
3341 assert server_conn.client_random() == client_conn.client_random()
3342 assert server_conn.server_random() == client_conn.server_random()
3343 assert server_conn.client_random() != server_conn.server_random()
3344 assert client_conn.client_random() != client_conn.server_random()
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003345
Paul Kehrerbdb76392017-12-01 04:54:32 +08003346 # Export key material for other uses.
3347 cekm = client_conn.export_keying_material(b'LABEL', 32)
3348 sekm = server_conn.export_keying_material(b'LABEL', 32)
3349 assert cekm is not None
3350 assert sekm is not None
3351 assert cekm == sekm
3352 assert len(sekm) == 32
3353
3354 # Export key material for other uses with additional context.
3355 cekmc = client_conn.export_keying_material(b'LABEL', 32, b'CONTEXT')
3356 sekmc = server_conn.export_keying_material(b'LABEL', 32, b'CONTEXT')
3357 assert cekmc is not None
3358 assert sekmc is not None
3359 assert cekmc == sekmc
3360 assert cekmc != cekm
3361 assert sekmc != sekm
3362 # Export with alternate label
3363 cekmt = client_conn.export_keying_material(b'test', 32, b'CONTEXT')
3364 sekmt = server_conn.export_keying_material(b'test', 32, b'CONTEXT')
3365 assert cekmc != cekmt
3366 assert sekmc != sekmt
3367
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003368 # Here are the bytes we'll try to send.
Alex Gaynore7f51982016-09-11 11:48:14 -04003369 important_message = b'One if by land, two if by sea.'
Rick Deanb71c0d22009-04-01 14:09:23 -05003370
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003371 server_conn.write(important_message)
Alex Chanb7480992017-01-30 14:04:47 +00003372 assert (
3373 interact_in_memory(client_conn, server_conn) ==
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003374 (client_conn, important_message))
3375
3376 client_conn.write(important_message[::-1])
Alex Chanb7480992017-01-30 14:04:47 +00003377 assert (
3378 interact_in_memory(client_conn, server_conn) ==
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003379 (server_conn, important_message[::-1]))
Rick Deanb71c0d22009-04-01 14:09:23 -05003380
Alex Chanb7480992017-01-30 14:04:47 +00003381 def test_socket_connect(self):
Rick Deanb1ccd562009-07-09 23:52:39 -05003382 """
Alex Chanb7480992017-01-30 14:04:47 +00003383 Just like `test_memory_connect` but with an actual socket.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003384
Hynek Schlawack35618382015-09-05 21:54:25 +02003385 This is primarily to rule out the memory BIO code as the source of any
Alex Chanb7480992017-01-30 14:04:47 +00003386 problems encountered while passing data over a `Connection` (if
Hynek Schlawack35618382015-09-05 21:54:25 +02003387 this test fails, there must be a problem outside the memory BIO code,
3388 as no memory BIO is involved here). Even though this isn't a memory
3389 BIO test, it's convenient to have it here.
Rick Deanb1ccd562009-07-09 23:52:39 -05003390 """
Alex Chanb7480992017-01-30 14:04:47 +00003391 server_conn, client_conn = loopback()
Rick Deanb1ccd562009-07-09 23:52:39 -05003392
Alex Gaynore7f51982016-09-11 11:48:14 -04003393 important_message = b"Help me Obi Wan Kenobi, you're my only hope."
Rick Deanb1ccd562009-07-09 23:52:39 -05003394 client_conn.send(important_message)
3395 msg = server_conn.recv(1024)
Alex Chanb7480992017-01-30 14:04:47 +00003396 assert msg == important_message
Rick Deanb1ccd562009-07-09 23:52:39 -05003397
3398 # Again in the other direction, just for fun.
3399 important_message = important_message[::-1]
3400 server_conn.send(important_message)
3401 msg = client_conn.recv(1024)
Alex Chanb7480992017-01-30 14:04:47 +00003402 assert msg == important_message
Rick Deanb1ccd562009-07-09 23:52:39 -05003403
Alex Chanb7480992017-01-30 14:04:47 +00003404 def test_socket_overrides_memory(self):
Rick Deanb71c0d22009-04-01 14:09:23 -05003405 """
Alex Chanb7480992017-01-30 14:04:47 +00003406 Test that `OpenSSL.SSL.bio_read` and `OpenSSL.SSL.bio_write` don't
3407 work on `OpenSSL.SSL.Connection`() that use sockets.
Rick Deanb71c0d22009-04-01 14:09:23 -05003408 """
Alex Gaynor51d424c2016-09-10 14:50:11 -04003409 context = Context(TLSv1_METHOD)
David Benjamin1fbe0642019-04-15 17:05:13 -05003410 client = socket_any_family()
Rick Deanb71c0d22009-04-01 14:09:23 -05003411 clientSSL = Connection(context, client)
Alex Chanb7480992017-01-30 14:04:47 +00003412 with pytest.raises(TypeError):
3413 clientSSL.bio_read(100)
3414 with pytest.raises(TypeError):
3415 clientSSL.bio_write("foo")
3416 with pytest.raises(TypeError):
3417 clientSSL.bio_shutdown()
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003418
Alex Chanb7480992017-01-30 14:04:47 +00003419 def test_outgoing_overflow(self):
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003420 """
3421 If more bytes than can be written to the memory BIO are passed to
Alex Chanb7480992017-01-30 14:04:47 +00003422 `Connection.send` at once, the number of bytes which were written is
3423 returned and that many bytes from the beginning of the input can be
3424 read from the other end of the connection.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003425 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003426 server = self._server(None)
3427 client = self._client(None)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003428
Alex Chanb7480992017-01-30 14:04:47 +00003429 interact_in_memory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003430
3431 size = 2 ** 15
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003432 sent = client.send(b"x" * size)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003433 # Sanity check. We're trying to test what happens when the entire
3434 # input can't be sent. If the entire input was sent, this test is
3435 # meaningless.
Alex Chanb7480992017-01-30 14:04:47 +00003436 assert sent < size
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003437
Alex Chanb7480992017-01-30 14:04:47 +00003438 receiver, received = interact_in_memory(client, server)
3439 assert receiver is server
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003440
3441 # We can rely on all of these bytes being received at once because
Alex Chanb7480992017-01-30 14:04:47 +00003442 # loopback passes 2 ** 16 to recv - more than 2 ** 15.
3443 assert len(received) == sent
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003444
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003445 def test_shutdown(self):
3446 """
Alex Chanb7480992017-01-30 14:04:47 +00003447 `Connection.bio_shutdown` signals the end of the data stream
3448 from which the `Connection` reads.
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003449 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003450 server = self._server(None)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003451 server.bio_shutdown()
Alex Chanb7480992017-01-30 14:04:47 +00003452 with pytest.raises(Error) as err:
3453 server.recv(1024)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003454 # We don't want WantReadError or ZeroReturnError or anything - it's a
3455 # handshake failure.
Alex Chanb7480992017-01-30 14:04:47 +00003456 assert type(err.value) in [Error, SysCallError]
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003457
Alex Chanb7480992017-01-30 14:04:47 +00003458 def test_unexpected_EOF(self):
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003459 """
3460 If the connection is lost before an orderly SSL shutdown occurs,
Alex Chanb7480992017-01-30 14:04:47 +00003461 `OpenSSL.SSL.SysCallError` is raised with a message of
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003462 "Unexpected EOF".
3463 """
Alex Chanb7480992017-01-30 14:04:47 +00003464 server_conn, client_conn = loopback()
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003465 client_conn.sock_shutdown(SHUT_RDWR)
Alex Chanb7480992017-01-30 14:04:47 +00003466 with pytest.raises(SysCallError) as err:
3467 server_conn.recv(1024)
3468 assert err.value.args == (-1, "Unexpected EOF")
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003469
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003470 def _check_client_ca_list(self, func):
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003471 """
Alex Chanb7480992017-01-30 14:04:47 +00003472 Verify the return value of the `get_client_ca_list` method for
Hynek Schlawack35618382015-09-05 21:54:25 +02003473 server and client connections.
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003474
Jonathan Ballet78b92a22011-07-16 08:07:26 +09003475 :param func: A function which will be called with the server context
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003476 before the client and server are connected to each other. This
3477 function should specify a list of CAs for the server to send to the
3478 client and return that same list. The list will be used to verify
Alex Chanb7480992017-01-30 14:04:47 +00003479 that `get_client_ca_list` returns the proper value at
Hynek Schlawack35618382015-09-05 21:54:25 +02003480 various times.
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003481 """
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003482 server = self._server(None)
3483 client = self._client(None)
Alex Chanb7480992017-01-30 14:04:47 +00003484 assert client.get_client_ca_list() == []
3485 assert server.get_client_ca_list() == []
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003486 ctx = server.get_context()
3487 expected = func(ctx)
Alex Chanb7480992017-01-30 14:04:47 +00003488 assert client.get_client_ca_list() == []
3489 assert server.get_client_ca_list() == expected
3490 interact_in_memory(client, server)
3491 assert client.get_client_ca_list() == expected
3492 assert server.get_client_ca_list() == expected
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003493
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003494 def test_set_client_ca_list_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003495 """
Alex Chanb7480992017-01-30 14:04:47 +00003496 `Context.set_client_ca_list` raises a `TypeError` if called with a
3497 non-list or a list that contains objects other than X509Names.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003498 """
3499 ctx = Context(TLSv1_METHOD)
Alex Chanb7480992017-01-30 14:04:47 +00003500 with pytest.raises(TypeError):
3501 ctx.set_client_ca_list("spam")
3502 with pytest.raises(TypeError):
3503 ctx.set_client_ca_list(["spam"])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003504
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003505 def test_set_empty_ca_list(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003506 """
Alex Chanb7480992017-01-30 14:04:47 +00003507 If passed an empty list, `Context.set_client_ca_list` configures the
3508 context to send no CA names to the client and, on both the server and
3509 client sides, `Connection.get_client_ca_list` returns an empty list
3510 after the connection is set up.
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003511 """
3512 def no_ca(ctx):
3513 ctx.set_client_ca_list([])
3514 return []
3515 self._check_client_ca_list(no_ca)
3516
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003517 def test_set_one_ca_list(self):
3518 """
3519 If passed a list containing a single X509Name,
Alex Chanb7480992017-01-30 14:04:47 +00003520 `Context.set_client_ca_list` configures the context to send
Hynek Schlawack35618382015-09-05 21:54:25 +02003521 that CA name to the client and, on both the server and client sides,
Alex Chanb7480992017-01-30 14:04:47 +00003522 `Connection.get_client_ca_list` returns a list containing that
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003523 X509Name after the connection is set up.
3524 """
3525 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3526 cadesc = cacert.get_subject()
Hynek Schlawack35618382015-09-05 21:54:25 +02003527
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003528 def single_ca(ctx):
3529 ctx.set_client_ca_list([cadesc])
3530 return [cadesc]
3531 self._check_client_ca_list(single_ca)
3532
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003533 def test_set_multiple_ca_list(self):
3534 """
3535 If passed a list containing multiple X509Name objects,
Alex Chanb7480992017-01-30 14:04:47 +00003536 `Context.set_client_ca_list` configures the context to send
Hynek Schlawack35618382015-09-05 21:54:25 +02003537 those CA names to the client and, on both the server and client sides,
Alex Chanb7480992017-01-30 14:04:47 +00003538 `Connection.get_client_ca_list` returns a list containing those
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003539 X509Names after the connection is set up.
3540 """
3541 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3542 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3543
3544 sedesc = secert.get_subject()
3545 cldesc = clcert.get_subject()
3546
3547 def multiple_ca(ctx):
3548 L = [sedesc, cldesc]
3549 ctx.set_client_ca_list(L)
3550 return L
3551 self._check_client_ca_list(multiple_ca)
3552
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003553 def test_reset_ca_list(self):
3554 """
3555 If called multiple times, only the X509Names passed to the final call
Alex Chanb7480992017-01-30 14:04:47 +00003556 of `Context.set_client_ca_list` are used to configure the CA
Hynek Schlawack35618382015-09-05 21:54:25 +02003557 names sent to the client.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003558 """
3559 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3560 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3561 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3562
3563 cadesc = cacert.get_subject()
3564 sedesc = secert.get_subject()
3565 cldesc = clcert.get_subject()
3566
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003567 def changed_ca(ctx):
3568 ctx.set_client_ca_list([sedesc, cldesc])
3569 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003570 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003571 self._check_client_ca_list(changed_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003572
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003573 def test_mutated_ca_list(self):
3574 """
Alex Chanb7480992017-01-30 14:04:47 +00003575 If the list passed to `Context.set_client_ca_list` is mutated
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003576 afterwards, this does not affect the list of CA names sent to the
3577 client.
3578 """
3579 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3580 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3581
3582 cadesc = cacert.get_subject()
3583 sedesc = secert.get_subject()
3584
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003585 def mutated_ca(ctx):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003586 L = [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003587 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003588 L.append(sedesc)
3589 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003590 self._check_client_ca_list(mutated_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003591
Alex Chanb7480992017-01-30 14:04:47 +00003592 def test_add_client_ca_wrong_args(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003593 """
Alex Chanb7480992017-01-30 14:04:47 +00003594 `Context.add_client_ca` raises `TypeError` if called with
3595 a non-X509 object.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003596 """
3597 ctx = Context(TLSv1_METHOD)
Alex Chanb7480992017-01-30 14:04:47 +00003598 with pytest.raises(TypeError):
3599 ctx.add_client_ca("spam")
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003600
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003601 def test_one_add_client_ca(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003602 """
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003603 A certificate's subject can be added as a CA to be sent to the client
Alex Chanb7480992017-01-30 14:04:47 +00003604 with `Context.add_client_ca`.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003605 """
3606 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3607 cadesc = cacert.get_subject()
Hynek Schlawack35618382015-09-05 21:54:25 +02003608
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003609 def single_ca(ctx):
3610 ctx.add_client_ca(cacert)
3611 return [cadesc]
3612 self._check_client_ca_list(single_ca)
3613
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003614 def test_multiple_add_client_ca(self):
3615 """
3616 Multiple CA names can be sent to the client by calling
Alex Chanb7480992017-01-30 14:04:47 +00003617 `Context.add_client_ca` with multiple X509 objects.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003618 """
3619 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3620 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3621
3622 cadesc = cacert.get_subject()
3623 sedesc = secert.get_subject()
3624
3625 def multiple_ca(ctx):
3626 ctx.add_client_ca(cacert)
3627 ctx.add_client_ca(secert)
3628 return [cadesc, sedesc]
3629 self._check_client_ca_list(multiple_ca)
3630
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003631 def test_set_and_add_client_ca(self):
3632 """
Alex Chanb7480992017-01-30 14:04:47 +00003633 A call to `Context.set_client_ca_list` followed by a call to
3634 `Context.add_client_ca` results in using the CA names from the
Hynek Schlawack35618382015-09-05 21:54:25 +02003635 first call and the CA name from the second call.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003636 """
3637 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3638 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3639 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3640
3641 cadesc = cacert.get_subject()
3642 sedesc = secert.get_subject()
3643 cldesc = clcert.get_subject()
3644
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003645 def mixed_set_add_ca(ctx):
3646 ctx.set_client_ca_list([cadesc, sedesc])
3647 ctx.add_client_ca(clcert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003648 return [cadesc, sedesc, cldesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003649 self._check_client_ca_list(mixed_set_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003650
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003651 def test_set_after_add_client_ca(self):
3652 """
Alex Chanb7480992017-01-30 14:04:47 +00003653 A call to `Context.set_client_ca_list` after a call to
3654 `Context.add_client_ca` replaces the CA name specified by the
Hynek Schlawack35618382015-09-05 21:54:25 +02003655 former call with the names specified by the latter call.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003656 """
3657 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3658 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3659 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3660
3661 cadesc = cacert.get_subject()
3662 sedesc = secert.get_subject()
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003663
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003664 def set_replaces_add_ca(ctx):
3665 ctx.add_client_ca(clcert)
3666 ctx.set_client_ca_list([cadesc])
3667 ctx.add_client_ca(secert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003668 return [cadesc, sedesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003669 self._check_client_ca_list(set_replaces_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003670
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003671
Alex Chanb7480992017-01-30 14:04:47 +00003672class TestInfoConstants(object):
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003673 """
3674 Tests for assorted constants exposed for use in info callbacks.
3675 """
3676 def test_integers(self):
3677 """
3678 All of the info constants are integers.
3679
3680 This is a very weak test. It would be nice to have one that actually
3681 verifies that as certain info events happen, the value passed to the
3682 info callback matches up with the constant exposed by OpenSSL.SSL.
3683 """
3684 for const in [
Alex Gaynor5af32d02016-09-24 01:52:21 -04003685 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK,
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003686 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
3687 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
3688 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
Hynek Schlawack35618382015-09-05 21:54:25 +02003689 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE
3690 ]:
Alex Gaynor5af32d02016-09-24 01:52:21 -04003691 assert isinstance(const, int)
3692
3693 # These constants don't exist on OpenSSL 1.1.0
3694 for const in [
3695 SSL_ST_INIT, SSL_ST_BEFORE, SSL_ST_OK, SSL_ST_RENEGOTIATE
3696 ]:
3697 assert const is None or isinstance(const, int)
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003698
Ziga Seilnacht44611bf2009-08-31 20:49:30 +02003699
Cory Benfield1d142142016-03-30 11:51:45 +01003700class TestRequires(object):
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003701 """
3702 Tests for the decorator factory used to conditionally raise
Cory Benfield1d142142016-03-30 11:51:45 +01003703 NotImplementedError when older OpenSSLs are used.
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003704 """
3705 def test_available(self):
3706 """
3707 When the OpenSSL functionality is available the decorated functions
3708 work appropriately.
3709 """
3710 feature_guard = _make_requires(True, "Error text")
3711 results = []
3712
3713 @feature_guard
3714 def inner():
3715 results.append(True)
3716 return True
3717
Cory Benfield2333e5e2016-03-30 14:24:16 +01003718 assert inner() is True
3719 assert [True] == results
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003720
3721 def test_unavailable(self):
3722 """
3723 When the OpenSSL functionality is not available the decorated function
3724 does not execute and NotImplementedError is raised.
3725 """
3726 feature_guard = _make_requires(False, "Error text")
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003727
3728 @feature_guard
Alex Chanfb078d82017-04-20 11:16:15 +01003729 def inner(): # pragma: nocover
3730 pytest.fail("Should not be called")
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003731
Cory Benfield1d142142016-03-30 11:51:45 +01003732 with pytest.raises(NotImplementedError) as e:
3733 inner()
3734
3735 assert "Error text" in str(e.value)
Cory Benfield496652a2017-01-24 11:42:56 +00003736
3737
Alex Chanb7480992017-01-30 14:04:47 +00003738class TestOCSP(object):
Cory Benfield496652a2017-01-24 11:42:56 +00003739 """
3740 Tests for PyOpenSSL's OCSP stapling support.
3741 """
3742 sample_ocsp_data = b"this is totally ocsp data"
3743
3744 def _client_connection(self, callback, data, request_ocsp=True):
3745 """
3746 Builds a client connection suitable for using OCSP.
3747
3748 :param callback: The callback to register for OCSP.
3749 :param data: The opaque data object that will be handed to the
3750 OCSP callback.
3751 :param request_ocsp: Whether the client will actually ask for OCSP
3752 stapling. Useful for testing only.
3753 """
3754 ctx = Context(SSLv23_METHOD)
3755 ctx.set_ocsp_client_callback(callback, data)
3756 client = Connection(ctx)
3757
3758 if request_ocsp:
3759 client.request_ocsp()
3760
3761 client.set_connect_state()
3762 return client
3763
3764 def _server_connection(self, callback, data):
3765 """
3766 Builds a server connection suitable for using OCSP.
3767
3768 :param callback: The callback to register for OCSP.
3769 :param data: The opaque data object that will be handed to the
3770 OCSP callback.
3771 """
3772 ctx = Context(SSLv23_METHOD)
3773 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
3774 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
3775 ctx.set_ocsp_server_callback(callback, data)
3776 server = Connection(ctx)
3777 server.set_accept_state()
3778 return server
3779
3780 def test_callbacks_arent_called_by_default(self):
3781 """
3782 If both the client and the server have registered OCSP callbacks, but
3783 the client does not send the OCSP request, neither callback gets
3784 called.
3785 """
Alex Chanfb078d82017-04-20 11:16:15 +01003786 def ocsp_callback(*args, **kwargs): # pragma: nocover
3787 pytest.fail("Should not be called")
Cory Benfield496652a2017-01-24 11:42:56 +00003788
3789 client = self._client_connection(
3790 callback=ocsp_callback, data=None, request_ocsp=False
3791 )
3792 server = self._server_connection(callback=ocsp_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00003793 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003794
Cory Benfield496652a2017-01-24 11:42:56 +00003795 def test_client_negotiates_without_server(self):
3796 """
3797 If the client wants to do OCSP but the server does not, the handshake
3798 succeeds, and the client callback fires with an empty byte string.
3799 """
3800 called = []
3801
3802 def ocsp_callback(conn, ocsp_data, ignored):
3803 called.append(ocsp_data)
3804 return True
3805
3806 client = self._client_connection(callback=ocsp_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00003807 server = loopback_server_factory(socket=None)
3808 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003809
3810 assert len(called) == 1
3811 assert called[0] == b''
3812
3813 def test_client_receives_servers_data(self):
3814 """
3815 The data the server sends in its callback is received by the client.
3816 """
3817 calls = []
3818
3819 def server_callback(*args, **kwargs):
3820 return self.sample_ocsp_data
3821
3822 def client_callback(conn, ocsp_data, ignored):
3823 calls.append(ocsp_data)
3824 return True
3825
3826 client = self._client_connection(callback=client_callback, data=None)
3827 server = self._server_connection(callback=server_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00003828 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003829
3830 assert len(calls) == 1
3831 assert calls[0] == self.sample_ocsp_data
3832
3833 def test_callbacks_are_invoked_with_connections(self):
3834 """
3835 The first arguments to both callbacks are their respective connections.
3836 """
3837 client_calls = []
3838 server_calls = []
3839
3840 def client_callback(conn, *args, **kwargs):
3841 client_calls.append(conn)
3842 return True
3843
3844 def server_callback(conn, *args, **kwargs):
3845 server_calls.append(conn)
3846 return self.sample_ocsp_data
3847
3848 client = self._client_connection(callback=client_callback, data=None)
3849 server = self._server_connection(callback=server_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00003850 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003851
3852 assert len(client_calls) == 1
3853 assert len(server_calls) == 1
3854 assert client_calls[0] is client
3855 assert server_calls[0] is server
3856
3857 def test_opaque_data_is_passed_through(self):
3858 """
3859 Both callbacks receive an opaque, user-provided piece of data in their
3860 callbacks as the final argument.
3861 """
3862 calls = []
3863
3864 def server_callback(*args):
3865 calls.append(args)
3866 return self.sample_ocsp_data
3867
3868 def client_callback(*args):
3869 calls.append(args)
3870 return True
3871
3872 sentinel = object()
3873
3874 client = self._client_connection(
3875 callback=client_callback, data=sentinel
3876 )
3877 server = self._server_connection(
3878 callback=server_callback, data=sentinel
3879 )
Alex Chanb7480992017-01-30 14:04:47 +00003880 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003881
3882 assert len(calls) == 2
3883 assert calls[0][-1] is sentinel
3884 assert calls[1][-1] is sentinel
3885
3886 def test_server_returns_empty_string(self):
3887 """
3888 If the server returns an empty bytestring from its callback, the
3889 client callback is called with the empty bytestring.
3890 """
3891 client_calls = []
3892
3893 def server_callback(*args):
3894 return b''
3895
3896 def client_callback(conn, ocsp_data, ignored):
3897 client_calls.append(ocsp_data)
3898 return True
3899
3900 client = self._client_connection(callback=client_callback, data=None)
3901 server = self._server_connection(callback=server_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00003902 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003903
3904 assert len(client_calls) == 1
3905 assert client_calls[0] == b''
3906
3907 def test_client_returns_false_terminates_handshake(self):
3908 """
3909 If the client returns False from its callback, the handshake fails.
3910 """
3911 def server_callback(*args):
3912 return self.sample_ocsp_data
3913
3914 def client_callback(*args):
3915 return False
3916
3917 client = self._client_connection(callback=client_callback, data=None)
3918 server = self._server_connection(callback=server_callback, data=None)
3919
3920 with pytest.raises(Error):
Alex Chanb7480992017-01-30 14:04:47 +00003921 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003922
3923 def test_exceptions_in_client_bubble_up(self):
3924 """
3925 The callbacks thrown in the client callback bubble up to the caller.
3926 """
3927 class SentinelException(Exception):
3928 pass
3929
3930 def server_callback(*args):
3931 return self.sample_ocsp_data
3932
3933 def client_callback(*args):
3934 raise SentinelException()
3935
3936 client = self._client_connection(callback=client_callback, data=None)
3937 server = self._server_connection(callback=server_callback, data=None)
3938
3939 with pytest.raises(SentinelException):
Alex Chanb7480992017-01-30 14:04:47 +00003940 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003941
3942 def test_exceptions_in_server_bubble_up(self):
3943 """
3944 The callbacks thrown in the server callback bubble up to the caller.
3945 """
3946 class SentinelException(Exception):
3947 pass
3948
3949 def server_callback(*args):
3950 raise SentinelException()
3951
Alex Chanfb078d82017-04-20 11:16:15 +01003952 def client_callback(*args): # pragma: nocover
Cory Benfield496652a2017-01-24 11:42:56 +00003953 pytest.fail("Should not be called")
3954
3955 client = self._client_connection(callback=client_callback, data=None)
3956 server = self._server_connection(callback=server_callback, data=None)
3957
3958 with pytest.raises(SentinelException):
Alex Chanb7480992017-01-30 14:04:47 +00003959 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003960
3961 def test_server_must_return_bytes(self):
3962 """
3963 The server callback must return a bytestring, or a TypeError is thrown.
3964 """
3965 def server_callback(*args):
3966 return self.sample_ocsp_data.decode('ascii')
3967
Alex Chanfb078d82017-04-20 11:16:15 +01003968 def client_callback(*args): # pragma: nocover
Cory Benfield496652a2017-01-24 11:42:56 +00003969 pytest.fail("Should not be called")
3970
3971 client = self._client_connection(callback=client_callback, data=None)
3972 server = self._server_connection(callback=server_callback, data=None)
3973
3974 with pytest.raises(TypeError):
Alex Chanb7480992017-01-30 14:04:47 +00003975 handshake_in_memory(client, server)