blob: ed911ded6e4e9f881d04abf4deaaa5cf2911f833 [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
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +020013from errno import ECONNREFUSED, EINPROGRESS, EWOULDBLOCK, EPIPE, ESHUTDOWN
Jeremy Lainé1ae7cb62018-03-21 14:49:42 +010014from sys import platform, getfilesystemencoding
Maximilian Hils1d95dea2015-08-17 19:27:20 +020015from socket import MSG_PEEK, SHUT_RDWR, error, socket
Jean-Paul Calderonea65cf6c2009-07-19 10:26:52 -040016from os import makedirs
Jean-Paul Calderone1461c492013-10-03 16:05:00 -040017from os.path import join
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -040018from weakref import ref
Alex Chanb7480992017-01-30 14:04:47 +000019from warnings import simplefilter
Jean-Paul Calderone460cc1f2009-03-07 11:31:12 -050020
Hynek Schlawack734d3022015-09-05 19:19:32 +020021import pytest
22
Paul Kehrer55fb3412017-06-29 18:44:08 -050023from pretend import raiser
24
Hynek Schlawackf90e3682016-03-11 11:21:13 +010025from six import PY3, text_type
Jean-Paul Calderonec76c61c2014-01-18 13:21:52 -050026
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +010027from cryptography import x509
28from cryptography.hazmat.backends import default_backend
29from cryptography.hazmat.primitives import hashes
30from cryptography.hazmat.primitives import serialization
31from cryptography.hazmat.primitives.asymmetric import rsa
32from cryptography.x509.oid import NameOID
33
34
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040035from OpenSSL.crypto import TYPE_RSA, FILETYPE_PEM
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -080036from OpenSSL.crypto import PKey, X509, X509Extension, X509Store
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040037from OpenSSL.crypto import dump_privatekey, load_privatekey
38from OpenSSL.crypto import dump_certificate, load_certificate
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -040039from OpenSSL.crypto import get_elliptic_curves
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040040
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -040041from OpenSSL.SSL import OPENSSL_VERSION_NUMBER, SSLEAY_VERSION, SSLEAY_CFLAGS
42from OpenSSL.SSL import SSLEAY_PLATFORM, SSLEAY_DIR, SSLEAY_BUILT_ON
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -040043from OpenSSL.SSL import SENT_SHUTDOWN, RECEIVED_SHUTDOWN
Jean-Paul Calderone1461c492013-10-03 16:05:00 -040044from OpenSSL.SSL import (
45 SSLv2_METHOD, SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD,
46 TLSv1_1_METHOD, TLSv1_2_METHOD)
47from OpenSSL.SSL import OP_SINGLE_DH_USE, OP_NO_SSLv2, OP_NO_SSLv3
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040048from OpenSSL.SSL import (
49 VERIFY_PEER, VERIFY_FAIL_IF_NO_PEER_CERT, VERIFY_CLIENT_ONCE, VERIFY_NONE)
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040050
Paul Kehrer55fb3412017-06-29 18:44:08 -050051from OpenSSL import SSL
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040052from OpenSSL.SSL import (
Jean-Paul Calderone313bf012012-02-08 13:02:49 -050053 SESS_CACHE_OFF, SESS_CACHE_CLIENT, SESS_CACHE_SERVER, SESS_CACHE_BOTH,
54 SESS_CACHE_NO_AUTO_CLEAR, SESS_CACHE_NO_INTERNAL_LOOKUP,
55 SESS_CACHE_NO_INTERNAL_STORE, SESS_CACHE_NO_INTERNAL)
56
57from OpenSSL.SSL import (
Jean-Paul Calderoned899af02013-03-19 22:10:37 -070058 Error, SysCallError, WantReadError, WantWriteError, ZeroReturnError)
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -050059from OpenSSL.SSL import (
Alex Gaynor01f90a12019-02-07 09:14:48 -050060 Context, Session, Connection, SSLeay_version)
Cory Benfield0ba57ec2016-03-30 09:35:05 +010061from OpenSSL.SSL import _make_requires
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040062
Paul Kehrer55fb3412017-06-29 18:44:08 -050063from OpenSSL._util import ffi as _ffi, lib as _lib
Cory Benfieldba1820d2015-04-13 17:39:12 -040064
Alex Gaynord3b5d9b2016-07-31 10:54:24 -040065from OpenSSL.SSL import (
66 OP_NO_QUERY_MTU, OP_COOKIE_EXCHANGE, OP_NO_TICKET, OP_NO_COMPRESSION,
67 MODE_RELEASE_BUFFERS)
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040068
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -040069from OpenSSL.SSL import (
Alex Gaynor5af32d02016-09-24 01:52:21 -040070 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK,
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -040071 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
72 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
73 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
74 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE)
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -040075
Alex Gaynor5af32d02016-09-24 01:52:21 -040076try:
77 from OpenSSL.SSL import (
78 SSL_ST_INIT, SSL_ST_BEFORE, SSL_ST_OK, SSL_ST_RENEGOTIATE
79 )
80except ImportError:
81 SSL_ST_INIT = SSL_ST_BEFORE = SSL_ST_OK = SSL_ST_RENEGOTIATE = None
82
Alex Chanb7480992017-01-30 14:04:47 +000083from .util import WARNING_TYPE_EXPECTED, NON_ASCII, is_consistent_type
Hynek Schlawackf0e66852015-10-16 20:18:38 +020084from .test_crypto import (
85 cleartextCertificatePEM, cleartextPrivateKeyPEM,
86 client_cert_pem, client_key_pem, server_cert_pem, server_key_pem,
87 root_cert_pem)
88
Hynek Schlawackde00dd52015-09-05 19:09:26 +020089
Alex Gaynord0bdd2d2016-09-10 14:23:46 -040090# openssl dhparam 1024 -out dh-1024.pem (note that 1024 is a small number of
91# bits to use)
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -040092dhparam = """\
93-----BEGIN DH PARAMETERS-----
Alex Gaynord0bdd2d2016-09-10 14:23:46 -040094MIGHAoGBALdUMvn+C9MM+y5BWZs11mSeH6HHoEq0UVbzVq7UojC1hbsZUuGukQ3a
95Qh2/pwqb18BZFykrWB0zv/OkLa0kx4cuUgNrUVq1EFheBiX6YqryJ7t2sO09NQiO
96V7H54LmltOT/hEh6QWsJqb6BQgH65bswvV/XkYGja8/T0GzvbaVzAgEC
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -040097-----END DH PARAMETERS-----
98"""
99
100
Hynek Schlawackb4f02402015-09-05 20:48:34 +0200101skip_if_py3 = pytest.mark.skipif(PY3, reason="Python 2 only")
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200102
103
Jean-Paul Calderone05826732015-04-12 11:38:49 -0400104def join_bytes_or_unicode(prefix, suffix):
105 """
106 Join two path components of either ``bytes`` or ``unicode``.
107
108 The return type is the same as the type of ``prefix``.
109 """
110 # If the types are the same, nothing special is necessary.
111 if type(prefix) == type(suffix):
112 return join(prefix, suffix)
113
114 # Otherwise, coerce suffix to the type of prefix.
115 if isinstance(prefix, text_type):
116 return join(prefix, suffix.decode(getfilesystemencoding()))
117 else:
118 return join(prefix, suffix.encode(getfilesystemencoding()))
119
120
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400121def verify_cb(conn, cert, errnum, depth, ok):
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400122 return ok
123
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400124
Rick Deanb1ccd562009-07-09 23:52:39 -0500125def socket_pair():
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400126 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400127 Establish and return a pair of network sockets connected to each other.
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400128 """
129 # Connect a pair of sockets
Rick Deanb1ccd562009-07-09 23:52:39 -0500130 port = socket()
131 port.bind(('', 0))
132 port.listen(1)
133 client = socket()
134 client.setblocking(False)
Jean-Paul Calderonef23c5d92009-07-23 17:58:15 -0400135 client.connect_ex(("127.0.0.1", port.getsockname()[1]))
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400136 client.setblocking(True)
Rick Deanb1ccd562009-07-09 23:52:39 -0500137 server = port.accept()[0]
Rick Deanb1ccd562009-07-09 23:52:39 -0500138
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400139 # Let's pass some unencrypted data to make sure our socket connection is
140 # fine. Just one byte, so we don't have to worry about buffers getting
141 # filled up or fragmentation.
Alex Gaynore7f51982016-09-11 11:48:14 -0400142 server.send(b"x")
143 assert client.recv(1024) == b"x"
144 client.send(b"y")
145 assert server.recv(1024) == b"y"
Rick Deanb1ccd562009-07-09 23:52:39 -0500146
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -0400147 # Most of our callers want non-blocking sockets, make it easy for them.
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400148 server.setblocking(False)
149 client.setblocking(False)
Jim Shaver46f28912015-05-29 19:32:16 -0400150
Rick Deanb1ccd562009-07-09 23:52:39 -0500151 return (server, client)
152
153
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400154def handshake(client, server):
155 conns = [client, server]
156 while conns:
157 for conn in conns:
158 try:
159 conn.do_handshake()
160 except WantReadError:
161 pass
162 else:
163 conns.remove(conn)
164
165
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400166def _create_certificate_chain():
167 """
168 Construct and return a chain of certificates.
169
170 1. A new self-signed certificate authority certificate (cacert)
171 2. A new intermediate certificate signed by cacert (icert)
172 3. A new server certificate signed by icert (scert)
173 """
Alex Gaynore7f51982016-09-11 11:48:14 -0400174 caext = X509Extension(b'basicConstraints', False, b'CA:true')
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400175
176 # Step 1
177 cakey = PKey()
Alex Gaynor0737a5e2016-09-10 14:35:09 -0400178 cakey.generate_key(TYPE_RSA, 1024)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400179 cacert = X509()
180 cacert.get_subject().commonName = "Authority Certificate"
181 cacert.set_issuer(cacert.get_subject())
182 cacert.set_pubkey(cakey)
Alex Gaynore7f51982016-09-11 11:48:14 -0400183 cacert.set_notBefore(b"20000101000000Z")
184 cacert.set_notAfter(b"20200101000000Z")
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400185 cacert.add_extensions([caext])
186 cacert.set_serial_number(0)
187 cacert.sign(cakey, "sha1")
188
189 # Step 2
190 ikey = PKey()
Alex Gaynor0737a5e2016-09-10 14:35:09 -0400191 ikey.generate_key(TYPE_RSA, 1024)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400192 icert = X509()
193 icert.get_subject().commonName = "Intermediate Certificate"
194 icert.set_issuer(cacert.get_subject())
195 icert.set_pubkey(ikey)
Alex Gaynore7f51982016-09-11 11:48:14 -0400196 icert.set_notBefore(b"20000101000000Z")
197 icert.set_notAfter(b"20200101000000Z")
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400198 icert.add_extensions([caext])
199 icert.set_serial_number(0)
200 icert.sign(cakey, "sha1")
201
202 # Step 3
203 skey = PKey()
Alex Gaynor0737a5e2016-09-10 14:35:09 -0400204 skey.generate_key(TYPE_RSA, 1024)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400205 scert = X509()
206 scert.get_subject().commonName = "Server Certificate"
207 scert.set_issuer(icert.get_subject())
208 scert.set_pubkey(skey)
Alex Gaynore7f51982016-09-11 11:48:14 -0400209 scert.set_notBefore(b"20000101000000Z")
210 scert.set_notAfter(b"20200101000000Z")
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400211 scert.add_extensions([
Alex Gaynore7f51982016-09-11 11:48:14 -0400212 X509Extension(b'basicConstraints', True, b'CA:false')])
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400213 scert.set_serial_number(0)
214 scert.sign(ikey, "sha1")
215
216 return [(cakey, cacert), (ikey, icert), (skey, scert)]
217
218
Paul Kehrer7d5a3bf2019-01-21 12:24:02 -0600219def loopback_client_factory(socket, version=SSLv23_METHOD):
220 client = Connection(Context(version), socket)
Alex Chan1c0cb662017-01-30 07:13:30 +0000221 client.set_connect_state()
222 return client
223
224
Paul Kehrer7d5a3bf2019-01-21 12:24:02 -0600225def loopback_server_factory(socket, version=SSLv23_METHOD):
226 ctx = Context(version)
Alex Chan1c0cb662017-01-30 07:13:30 +0000227 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
228 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
229 server = Connection(ctx, socket)
230 server.set_accept_state()
231 return server
232
233
234def loopback(server_factory=None, client_factory=None):
235 """
236 Create a connected socket pair and force two connected SSL sockets
237 to talk to each other via memory BIOs.
238 """
239 if server_factory is None:
240 server_factory = loopback_server_factory
241 if client_factory is None:
242 client_factory = loopback_client_factory
243
244 (server, client) = socket_pair()
245 server = server_factory(server)
246 client = client_factory(client)
247
248 handshake(client, server)
249
250 server.setblocking(True)
251 client.setblocking(True)
252 return server, client
253
254
Alex Chan1ca9e3a2016-11-05 13:01:51 +0000255def interact_in_memory(client_conn, server_conn):
256 """
257 Try to read application bytes from each of the two `Connection` objects.
258 Copy bytes back and forth between their send/receive buffers for as long
259 as there is anything to copy. When there is nothing more to copy,
260 return `None`. If one of them actually manages to deliver some application
261 bytes, return a two-tuple of the connection from which the bytes were read
262 and the bytes themselves.
263 """
264 wrote = True
265 while wrote:
266 # Loop until neither side has anything to say
267 wrote = False
268
269 # Copy stuff from each side's send buffer to the other side's
270 # receive buffer.
271 for (read, write) in [(client_conn, server_conn),
272 (server_conn, client_conn)]:
273
274 # Give the side a chance to generate some more bytes, or succeed.
275 try:
276 data = read.recv(2 ** 16)
277 except WantReadError:
278 # It didn't succeed, so we'll hope it generated some output.
279 pass
280 else:
281 # It did succeed, so we'll stop now and let the caller deal
282 # with it.
283 return (read, data)
284
285 while True:
286 # Keep copying as long as there's more stuff there.
287 try:
288 dirty = read.bio_read(4096)
289 except WantReadError:
290 # Okay, nothing more waiting to be sent. Stop
291 # processing this send buffer.
292 break
293 else:
294 # Keep track of the fact that someone generated some
295 # output.
296 wrote = True
297 write.bio_write(dirty)
298
299
Alex Chan532b79e2017-01-24 15:14:52 +0000300def handshake_in_memory(client_conn, server_conn):
301 """
302 Perform the TLS handshake between two `Connection` instances connected to
303 each other via memory BIOs.
304 """
305 client_conn.set_connect_state()
306 server_conn.set_accept_state()
307
308 for conn in [client_conn, server_conn]:
309 try:
310 conn.do_handshake()
311 except WantReadError:
312 pass
313
314 interact_in_memory(client_conn, server_conn)
315
316
Alex Chanb7480992017-01-30 14:04:47 +0000317class TestVersion(object):
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400318 """
Alex Chanb7480992017-01-30 14:04:47 +0000319 Tests for version information exposed by `OpenSSL.SSL.SSLeay_version` and
320 `OpenSSL.SSL.OPENSSL_VERSION_NUMBER`.
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400321 """
322 def test_OPENSSL_VERSION_NUMBER(self):
323 """
Alex Chanb7480992017-01-30 14:04:47 +0000324 `OPENSSL_VERSION_NUMBER` is an integer with status in the low byte and
325 the patch, fix, minor, and major versions in the nibbles above that.
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400326 """
Alex Chanb7480992017-01-30 14:04:47 +0000327 assert isinstance(OPENSSL_VERSION_NUMBER, int)
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400328
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400329 def test_SSLeay_version(self):
330 """
Alex Chanb7480992017-01-30 14:04:47 +0000331 `SSLeay_version` takes a version type indicator and returns one of a
332 number of version strings based on that indicator.
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400333 """
334 versions = {}
335 for t in [SSLEAY_VERSION, SSLEAY_CFLAGS, SSLEAY_BUILT_ON,
336 SSLEAY_PLATFORM, SSLEAY_DIR]:
337 version = SSLeay_version(t)
338 versions[version] = t
Alex Chanb7480992017-01-30 14:04:47 +0000339 assert isinstance(version, bytes)
340 assert len(versions) == 5
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400341
342
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100343@pytest.fixture
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100344def ca_file(tmpdir):
345 """
346 Create a valid PEM file with CA certificates and return the path.
347 """
348 key = rsa.generate_private_key(
349 public_exponent=65537,
350 key_size=2048,
351 backend=default_backend()
352 )
353 public_key = key.public_key()
354
355 builder = x509.CertificateBuilder()
356 builder = builder.subject_name(x509.Name([
357 x509.NameAttribute(NameOID.COMMON_NAME, u"pyopenssl.org"),
358 ]))
359 builder = builder.issuer_name(x509.Name([
360 x509.NameAttribute(NameOID.COMMON_NAME, u"pyopenssl.org"),
361 ]))
362 one_day = datetime.timedelta(1, 0, 0)
363 builder = builder.not_valid_before(datetime.datetime.today() - one_day)
364 builder = builder.not_valid_after(datetime.datetime.today() + one_day)
365 builder = builder.serial_number(int(uuid.uuid4()))
366 builder = builder.public_key(public_key)
367 builder = builder.add_extension(
368 x509.BasicConstraints(ca=True, path_length=None), critical=True,
369 )
370
371 certificate = builder.sign(
372 private_key=key, algorithm=hashes.SHA256(),
373 backend=default_backend()
374 )
375
376 ca_file = tmpdir.join("test.pem")
377 ca_file.write_binary(
378 certificate.public_bytes(
379 encoding=serialization.Encoding.PEM,
380 )
381 )
382
383 return str(ca_file).encode("ascii")
384
385
386@pytest.fixture
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100387def context():
388 """
389 A simple TLS 1.0 context.
390 """
391 return Context(TLSv1_METHOD)
392
393
394class TestContext(object):
Hynek Schlawackaa861212016-03-13 13:53:48 +0100395 """
Alex Chan532b79e2017-01-24 15:14:52 +0000396 Unit tests for `OpenSSL.SSL.Context`.
Hynek Schlawackaa861212016-03-13 13:53:48 +0100397 """
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100398 @pytest.mark.parametrize("cipher_string", [
399 b"hello world:AES128-SHA",
400 u"hello world:AES128-SHA",
401 ])
402 def test_set_cipher_list(self, context, cipher_string):
403 """
Alex Chan532b79e2017-01-24 15:14:52 +0000404 `Context.set_cipher_list` accepts both byte and unicode strings
Hynek Schlawacka7a63af2016-03-11 12:05:26 +0100405 for naming the ciphers which connections created with the context
406 object will be able to choose from.
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100407 """
408 context.set_cipher_list(cipher_string)
409 conn = Connection(context, None)
410
411 assert "AES128-SHA" in conn.get_cipher_list()
412
Mark Williamsdf2480d2019-02-14 19:30:07 -0800413 def test_set_cipher_list_wrong_type(self, context):
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100414 """
Alex Chan532b79e2017-01-24 15:14:52 +0000415 `Context.set_cipher_list` raises `TypeError` when passed a non-string
Mark Williamsdf2480d2019-02-14 19:30:07 -0800416 argument.
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100417 """
Mark Williamsdf2480d2019-02-14 19:30:07 -0800418 with pytest.raises(TypeError):
419 context.set_cipher_list(object())
420
421 def test_set_cipher_list_no_cipher_match(self, context):
422 """
423 `Context.set_cipher_list` raises `OpenSSL.SSL.Error` with a
424 `"no cipher match"` reason string regardless of the TLS
425 version.
426 """
427 with pytest.raises(Error) as excinfo:
428 context.set_cipher_list(b"imaginary-cipher")
429 assert excinfo.value.args == (
430 [
431 (
432 'SSL routines',
433 'SSL_CTX_set_cipher_list',
434 'no cipher match',
435 ),
436 ],
437 )
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100438
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100439 def test_load_client_ca(self, context, ca_file):
440 """
Alex Chan532b79e2017-01-24 15:14:52 +0000441 `Context.load_client_ca` works as far as we can tell.
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100442 """
443 context.load_client_ca(ca_file)
444
445 def test_load_client_ca_invalid(self, context, tmpdir):
446 """
Alex Chan532b79e2017-01-24 15:14:52 +0000447 `Context.load_client_ca` raises an Error if the ca file is invalid.
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100448 """
449 ca_file = tmpdir.join("test.pem")
450 ca_file.write("")
451
452 with pytest.raises(Error) as e:
453 context.load_client_ca(str(ca_file).encode("ascii"))
454
455 assert "PEM routines" == e.value.args[0][0][0]
456
457 def test_load_client_ca_unicode(self, context, ca_file):
458 """
459 Passing the path as unicode raises a warning but works.
460 """
461 pytest.deprecated_call(
462 context.load_client_ca, ca_file.decode("ascii")
463 )
464
465 def test_set_session_id(self, context):
466 """
Alex Chan532b79e2017-01-24 15:14:52 +0000467 `Context.set_session_id` works as far as we can tell.
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100468 """
469 context.set_session_id(b"abc")
470
471 def test_set_session_id_fail(self, context):
472 """
Alex Chan532b79e2017-01-24 15:14:52 +0000473 `Context.set_session_id` errors are propagated.
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100474 """
475 with pytest.raises(Error) as e:
476 context.set_session_id(b"abc" * 1000)
477
478 assert [
479 ("SSL routines",
480 "SSL_CTX_set_session_id_context",
481 "ssl session id context too long")
482 ] == e.value.args[0]
483
484 def test_set_session_id_unicode(self, context):
485 """
Alex Chan532b79e2017-01-24 15:14:52 +0000486 `Context.set_session_id` raises a warning if a unicode string is
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100487 passed.
488 """
489 pytest.deprecated_call(context.set_session_id, u"abc")
490
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400491 def test_method(self):
492 """
Alex Chan532b79e2017-01-24 15:14:52 +0000493 `Context` can be instantiated with one of `SSLv2_METHOD`,
494 `SSLv3_METHOD`, `SSLv23_METHOD`, `TLSv1_METHOD`, `TLSv1_1_METHOD`,
495 or `TLSv1_2_METHOD`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400496 """
Alex Gaynor5af32d02016-09-24 01:52:21 -0400497 methods = [SSLv23_METHOD, TLSv1_METHOD]
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400498 for meth in methods:
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400499 Context(meth)
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400500
Alex Gaynor5af32d02016-09-24 01:52:21 -0400501 maybe = [SSLv2_METHOD, SSLv3_METHOD, TLSv1_1_METHOD, TLSv1_2_METHOD]
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400502 for meth in maybe:
503 try:
504 Context(meth)
505 except (Error, ValueError):
506 # Some versions of OpenSSL have SSLv2 / TLSv1.1 / TLSv1.2, some
507 # don't. Difficult to say in advance.
508 pass
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400509
Alex Chan532b79e2017-01-24 15:14:52 +0000510 with pytest.raises(TypeError):
511 Context("")
512 with pytest.raises(ValueError):
513 Context(10)
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400514
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200515 @skip_if_py3
516 def test_method_long(self):
517 """
Alex Chan532b79e2017-01-24 15:14:52 +0000518 On Python 2 `Context` accepts values of type `long` as well as `int`.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200519 """
520 Context(long(TLSv1_METHOD))
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500521
Rick Deane15b1472009-07-09 15:53:42 -0500522 def test_type(self):
523 """
Alex Gaynor01f90a12019-02-07 09:14:48 -0500524 `Context` can be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -0500525 """
Alex Chan532b79e2017-01-24 15:14:52 +0000526 assert is_consistent_type(Context, 'Context', TLSv1_METHOD)
Rick Deane15b1472009-07-09 15:53:42 -0500527
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400528 def test_use_privatekey(self):
529 """
Alex Chan532b79e2017-01-24 15:14:52 +0000530 `Context.use_privatekey` takes an `OpenSSL.crypto.PKey` instance.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400531 """
532 key = PKey()
Alex Gaynor6e9f9762018-05-12 07:44:37 -0400533 key.generate_key(TYPE_RSA, 512)
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400534 ctx = Context(TLSv1_METHOD)
535 ctx.use_privatekey(key)
Alex Chan532b79e2017-01-24 15:14:52 +0000536 with pytest.raises(TypeError):
537 ctx.use_privatekey("")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400538
Alex Chan532b79e2017-01-24 15:14:52 +0000539 def test_use_privatekey_file_missing(self, tmpfile):
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800540 """
Alex Chan532b79e2017-01-24 15:14:52 +0000541 `Context.use_privatekey_file` raises `OpenSSL.SSL.Error` when passed
542 the name of a file which does not exist.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800543 """
544 ctx = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000545 with pytest.raises(Error):
546 ctx.use_privatekey_file(tmpfile)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800547
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400548 def _use_privatekey_file_test(self, pemfile, filetype):
549 """
550 Verify that calling ``Context.use_privatekey_file`` with the given
551 arguments does not raise an exception.
552 """
553 key = PKey()
Alex Gaynor6e9f9762018-05-12 07:44:37 -0400554 key.generate_key(TYPE_RSA, 512)
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400555
556 with open(pemfile, "wt") as pem:
557 pem.write(
558 dump_privatekey(FILETYPE_PEM, key).decode("ascii")
559 )
560
561 ctx = Context(TLSv1_METHOD)
562 ctx.use_privatekey_file(pemfile, filetype)
563
Alex Chanfb078d82017-04-20 11:16:15 +0100564 @pytest.mark.parametrize('filetype', [object(), "", None, 1.0])
565 def test_wrong_privatekey_file_wrong_args(self, tmpfile, filetype):
566 """
567 `Context.use_privatekey_file` raises `TypeError` when called with
568 a `filetype` which is not a valid file encoding.
569 """
570 ctx = Context(TLSv1_METHOD)
571 with pytest.raises(TypeError):
572 ctx.use_privatekey_file(tmpfile, filetype)
573
Alex Chan532b79e2017-01-24 15:14:52 +0000574 def test_use_privatekey_file_bytes(self, tmpfile):
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400575 """
576 A private key can be specified from a file by passing a ``bytes``
577 instance giving the file name to ``Context.use_privatekey_file``.
578 """
579 self._use_privatekey_file_test(
Alex Chan532b79e2017-01-24 15:14:52 +0000580 tmpfile + NON_ASCII.encode(getfilesystemencoding()),
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400581 FILETYPE_PEM,
582 )
583
Alex Chan532b79e2017-01-24 15:14:52 +0000584 def test_use_privatekey_file_unicode(self, tmpfile):
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400585 """
586 A private key can be specified from a file by passing a ``unicode``
587 instance giving the file name to ``Context.use_privatekey_file``.
588 """
589 self._use_privatekey_file_test(
Alex Chan532b79e2017-01-24 15:14:52 +0000590 tmpfile.decode(getfilesystemencoding()) + NON_ASCII,
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400591 FILETYPE_PEM,
592 )
593
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200594 @skip_if_py3
Alex Chan532b79e2017-01-24 15:14:52 +0000595 def test_use_privatekey_file_long(self, tmpfile):
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200596 """
Alex Chan532b79e2017-01-24 15:14:52 +0000597 On Python 2 `Context.use_privatekey_file` accepts a filetype of
598 type `long` as well as `int`.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200599 """
Alex Chan532b79e2017-01-24 15:14:52 +0000600 self._use_privatekey_file_test(tmpfile, long(FILETYPE_PEM))
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500601
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800602 def test_use_certificate_wrong_args(self):
603 """
Alex Chan532b79e2017-01-24 15:14:52 +0000604 `Context.use_certificate_wrong_args` raises `TypeError` when not passed
605 exactly one `OpenSSL.crypto.X509` instance as an argument.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800606 """
607 ctx = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000608 with pytest.raises(TypeError):
609 ctx.use_certificate("hello, world")
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800610
611 def test_use_certificate_uninitialized(self):
612 """
Alex Chan532b79e2017-01-24 15:14:52 +0000613 `Context.use_certificate` raises `OpenSSL.SSL.Error` when passed a
614 `OpenSSL.crypto.X509` instance which has not been initialized
615 (ie, which does not actually have any certificate data).
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800616 """
617 ctx = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000618 with pytest.raises(Error):
619 ctx.use_certificate(X509())
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800620
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800621 def test_use_certificate(self):
622 """
Alex Chan532b79e2017-01-24 15:14:52 +0000623 `Context.use_certificate` sets the certificate which will be
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800624 used to identify connections created using the context.
625 """
626 # TODO
627 # Hard to assert anything. But we could set a privatekey then ask
628 # OpenSSL if the cert and key agree using check_privatekey. Then as
629 # long as check_privatekey works right we're good...
630 ctx = Context(TLSv1_METHOD)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200631 ctx.use_certificate(
632 load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
633 )
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800634
635 def test_use_certificate_file_wrong_args(self):
636 """
Alex Chan532b79e2017-01-24 15:14:52 +0000637 `Context.use_certificate_file` raises `TypeError` if the first
638 argument is not a byte string or the second argument is not an integer.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800639 """
640 ctx = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000641 with pytest.raises(TypeError):
642 ctx.use_certificate_file(object(), FILETYPE_PEM)
643 with pytest.raises(TypeError):
644 ctx.use_certificate_file(b"somefile", object())
645 with pytest.raises(TypeError):
646 ctx.use_certificate_file(object(), FILETYPE_PEM)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800647
Alex Chan532b79e2017-01-24 15:14:52 +0000648 def test_use_certificate_file_missing(self, tmpfile):
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800649 """
Alex Chan532b79e2017-01-24 15:14:52 +0000650 `Context.use_certificate_file` raises `OpenSSL.SSL.Error` if passed
651 the name of a file which does not exist.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800652 """
653 ctx = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000654 with pytest.raises(Error):
655 ctx.use_certificate_file(tmpfile)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800656
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400657 def _use_certificate_file_test(self, certificate_file):
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800658 """
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400659 Verify that calling ``Context.use_certificate_file`` with the given
660 filename doesn't raise an exception.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800661 """
662 # TODO
663 # Hard to assert anything. But we could set a privatekey then ask
664 # OpenSSL if the cert and key agree using check_privatekey. Then as
665 # long as check_privatekey works right we're good...
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400666 with open(certificate_file, "wb") as pem_file:
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800667 pem_file.write(cleartextCertificatePEM)
668
669 ctx = Context(TLSv1_METHOD)
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400670 ctx.use_certificate_file(certificate_file)
671
Alex Chan532b79e2017-01-24 15:14:52 +0000672 def test_use_certificate_file_bytes(self, tmpfile):
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400673 """
Alex Chan532b79e2017-01-24 15:14:52 +0000674 `Context.use_certificate_file` sets the certificate (given as a
675 `bytes` filename) which will be used to identify connections created
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400676 using the context.
677 """
Alex Chan532b79e2017-01-24 15:14:52 +0000678 filename = tmpfile + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400679 self._use_certificate_file_test(filename)
680
Alex Chan532b79e2017-01-24 15:14:52 +0000681 def test_use_certificate_file_unicode(self, tmpfile):
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400682 """
Alex Chan532b79e2017-01-24 15:14:52 +0000683 `Context.use_certificate_file` sets the certificate (given as a
684 `bytes` filename) which will be used to identify connections created
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400685 using the context.
686 """
Alex Chan532b79e2017-01-24 15:14:52 +0000687 filename = tmpfile.decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400688 self._use_certificate_file_test(filename)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800689
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200690 @skip_if_py3
Alex Chan532b79e2017-01-24 15:14:52 +0000691 def test_use_certificate_file_long(self, tmpfile):
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200692 """
Alex Chan532b79e2017-01-24 15:14:52 +0000693 On Python 2 `Context.use_certificate_file` accepts a
694 filetype of type `long` as well as `int`.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200695 """
Alex Chan532b79e2017-01-24 15:14:52 +0000696 pem_filename = tmpfile
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200697 with open(pem_filename, "wb") as pem_file:
698 pem_file.write(cleartextCertificatePEM)
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500699
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200700 ctx = Context(TLSv1_METHOD)
701 ctx.use_certificate_file(pem_filename, long(FILETYPE_PEM))
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500702
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500703 def test_check_privatekey_valid(self):
704 """
Alex Chan532b79e2017-01-24 15:14:52 +0000705 `Context.check_privatekey` returns `None` if the `Context` instance
706 has been configured to use a matched key and certificate pair.
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500707 """
708 key = load_privatekey(FILETYPE_PEM, client_key_pem)
709 cert = load_certificate(FILETYPE_PEM, client_cert_pem)
710 context = Context(TLSv1_METHOD)
711 context.use_privatekey(key)
712 context.use_certificate(cert)
Alex Chan532b79e2017-01-24 15:14:52 +0000713 assert None is context.check_privatekey()
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500714
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500715 def test_check_privatekey_invalid(self):
716 """
Alex Chan532b79e2017-01-24 15:14:52 +0000717 `Context.check_privatekey` raises `Error` if the `Context` instance
718 has been configured to use a key and certificate pair which don't
719 relate to each other.
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500720 """
721 key = load_privatekey(FILETYPE_PEM, client_key_pem)
722 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
723 context = Context(TLSv1_METHOD)
724 context.use_privatekey(key)
725 context.use_certificate(cert)
Alex Chan532b79e2017-01-24 15:14:52 +0000726 with pytest.raises(Error):
727 context.check_privatekey()
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400728
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400729 def test_app_data(self):
730 """
Alex Chan532b79e2017-01-24 15:14:52 +0000731 `Context.set_app_data` stores an object for later retrieval
732 using `Context.get_app_data`.
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400733 """
734 app_data = object()
735 context = Context(TLSv1_METHOD)
736 context.set_app_data(app_data)
Alex Chan532b79e2017-01-24 15:14:52 +0000737 assert context.get_app_data() is app_data
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400738
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400739 def test_set_options_wrong_args(self):
740 """
Alex Chan532b79e2017-01-24 15:14:52 +0000741 `Context.set_options` raises `TypeError` if called with
742 a non-`int` argument.
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400743 """
744 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000745 with pytest.raises(TypeError):
746 context.set_options(None)
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400747
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500748 def test_set_options(self):
749 """
Alex Chan532b79e2017-01-24 15:14:52 +0000750 `Context.set_options` returns the new options value.
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500751 """
752 context = Context(TLSv1_METHOD)
753 options = context.set_options(OP_NO_SSLv2)
Alex Gaynor2310f8b2016-09-10 14:39:32 -0400754 assert options & OP_NO_SSLv2 == OP_NO_SSLv2
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500755
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200756 @skip_if_py3
757 def test_set_options_long(self):
758 """
Alex Chan532b79e2017-01-24 15:14:52 +0000759 On Python 2 `Context.set_options` accepts values of type
760 `long` as well as `int`.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200761 """
762 context = Context(TLSv1_METHOD)
763 options = context.set_options(long(OP_NO_SSLv2))
Alex Gaynor2310f8b2016-09-10 14:39:32 -0400764 assert options & OP_NO_SSLv2 == OP_NO_SSLv2
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500765
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300766 def test_set_mode_wrong_args(self):
767 """
Alex Chan532b79e2017-01-24 15:14:52 +0000768 `Context.set_mode` raises `TypeError` if called with
769 a non-`int` argument.
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300770 """
771 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000772 with pytest.raises(TypeError):
773 context.set_mode(None)
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300774
Alex Gaynord3b5d9b2016-07-31 10:54:24 -0400775 def test_set_mode(self):
776 """
Alex Chan532b79e2017-01-24 15:14:52 +0000777 `Context.set_mode` accepts a mode bitvector and returns the
Alex Gaynord3b5d9b2016-07-31 10:54:24 -0400778 newly set mode.
779 """
780 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000781 assert MODE_RELEASE_BUFFERS & context.set_mode(MODE_RELEASE_BUFFERS)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500782
Alex Gaynord3b5d9b2016-07-31 10:54:24 -0400783 @skip_if_py3
784 def test_set_mode_long(self):
785 """
Alex Chan532b79e2017-01-24 15:14:52 +0000786 On Python 2 `Context.set_mode` accepts values of type `long` as well
787 as `int`.
Alex Gaynord3b5d9b2016-07-31 10:54:24 -0400788 """
789 context = Context(TLSv1_METHOD)
790 mode = context.set_mode(long(MODE_RELEASE_BUFFERS))
Alex Chan532b79e2017-01-24 15:14:52 +0000791 assert MODE_RELEASE_BUFFERS & mode
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400792
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400793 def test_set_timeout_wrong_args(self):
794 """
Alex Chan532b79e2017-01-24 15:14:52 +0000795 `Context.set_timeout` raises `TypeError` if called with
796 a non-`int` argument.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400797 """
798 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000799 with pytest.raises(TypeError):
800 context.set_timeout(None)
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400801
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400802 def test_timeout(self):
803 """
Alex Chan532b79e2017-01-24 15:14:52 +0000804 `Context.set_timeout` sets the session timeout for all connections
805 created using the context object. `Context.get_timeout` retrieves
806 this value.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400807 """
808 context = Context(TLSv1_METHOD)
809 context.set_timeout(1234)
Alex Chan532b79e2017-01-24 15:14:52 +0000810 assert context.get_timeout() == 1234
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400811
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200812 @skip_if_py3
813 def test_timeout_long(self):
814 """
Alex Chan532b79e2017-01-24 15:14:52 +0000815 On Python 2 `Context.set_timeout` accepts values of type `long` as
816 well as int.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200817 """
818 context = Context(TLSv1_METHOD)
819 context.set_timeout(long(1234))
Alex Chan532b79e2017-01-24 15:14:52 +0000820 assert context.get_timeout() == 1234
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500821
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400822 def test_set_verify_depth_wrong_args(self):
823 """
Alex Chan532b79e2017-01-24 15:14:52 +0000824 `Context.set_verify_depth` raises `TypeError` if called with a
825 non-`int` argument.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400826 """
827 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000828 with pytest.raises(TypeError):
829 context.set_verify_depth(None)
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400830
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400831 def test_verify_depth(self):
832 """
Alex Chan532b79e2017-01-24 15:14:52 +0000833 `Context.set_verify_depth` sets the number of certificates in
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200834 a chain to follow before giving up. The value can be retrieved with
Alex Chan532b79e2017-01-24 15:14:52 +0000835 `Context.get_verify_depth`.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400836 """
837 context = Context(TLSv1_METHOD)
838 context.set_verify_depth(11)
Alex Chan532b79e2017-01-24 15:14:52 +0000839 assert context.get_verify_depth() == 11
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400840
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200841 @skip_if_py3
842 def test_verify_depth_long(self):
843 """
Alex Chan532b79e2017-01-24 15:14:52 +0000844 On Python 2 `Context.set_verify_depth` accepts values of type `long`
845 as well as int.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200846 """
847 context = Context(TLSv1_METHOD)
848 context.set_verify_depth(long(11))
Alex Chan532b79e2017-01-24 15:14:52 +0000849 assert context.get_verify_depth() == 11
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500850
Alex Chan532b79e2017-01-24 15:14:52 +0000851 def _write_encrypted_pem(self, passphrase, tmpfile):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400852 """
853 Write a new private key out to a new file, encrypted using the given
854 passphrase. Return the path to the new file.
855 """
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400856 key = PKey()
Alex Gaynor6e9f9762018-05-12 07:44:37 -0400857 key.generate_key(TYPE_RSA, 512)
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400858 pem = dump_privatekey(FILETYPE_PEM, key, "blowfish", passphrase)
Alex Chan532b79e2017-01-24 15:14:52 +0000859 with open(tmpfile, 'w') as fObj:
860 fObj.write(pem.decode('ascii'))
861 return tmpfile
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400862
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400863 def test_set_passwd_cb_wrong_args(self):
864 """
Alex Chan532b79e2017-01-24 15:14:52 +0000865 `Context.set_passwd_cb` raises `TypeError` if called with a
866 non-callable first argument.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400867 """
868 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000869 with pytest.raises(TypeError):
870 context.set_passwd_cb(None)
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400871
Alex Chan532b79e2017-01-24 15:14:52 +0000872 def test_set_passwd_cb(self, tmpfile):
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400873 """
Alex Chan532b79e2017-01-24 15:14:52 +0000874 `Context.set_passwd_cb` accepts a callable which will be invoked when
875 a private key is loaded from an encrypted PEM.
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400876 """
Alex Gaynore7f51982016-09-11 11:48:14 -0400877 passphrase = b"foobar"
Alex Chan532b79e2017-01-24 15:14:52 +0000878 pemFile = self._write_encrypted_pem(passphrase, tmpfile)
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400879 calledWith = []
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200880
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400881 def passphraseCallback(maxlen, verify, extra):
882 calledWith.append((maxlen, verify, extra))
883 return passphrase
884 context = Context(TLSv1_METHOD)
885 context.set_passwd_cb(passphraseCallback)
886 context.use_privatekey_file(pemFile)
Alex Chan532b79e2017-01-24 15:14:52 +0000887 assert len(calledWith) == 1
888 assert isinstance(calledWith[0][0], int)
889 assert isinstance(calledWith[0][1], int)
890 assert calledWith[0][2] is None
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400891
Alex Chan532b79e2017-01-24 15:14:52 +0000892 def test_passwd_callback_exception(self, tmpfile):
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400893 """
Alex Chan532b79e2017-01-24 15:14:52 +0000894 `Context.use_privatekey_file` propagates any exception raised
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200895 by the passphrase callback.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400896 """
Alex Chan532b79e2017-01-24 15:14:52 +0000897 pemFile = self._write_encrypted_pem(b"monkeys are nice", tmpfile)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200898
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400899 def passphraseCallback(maxlen, verify, extra):
900 raise RuntimeError("Sorry, I am a fail.")
901
902 context = Context(TLSv1_METHOD)
903 context.set_passwd_cb(passphraseCallback)
Alex Chan532b79e2017-01-24 15:14:52 +0000904 with pytest.raises(RuntimeError):
905 context.use_privatekey_file(pemFile)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400906
Alex Chan532b79e2017-01-24 15:14:52 +0000907 def test_passwd_callback_false(self, tmpfile):
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400908 """
Alex Chan532b79e2017-01-24 15:14:52 +0000909 `Context.use_privatekey_file` raises `OpenSSL.SSL.Error` if the
910 passphrase callback returns a false value.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400911 """
Alex Chan532b79e2017-01-24 15:14:52 +0000912 pemFile = self._write_encrypted_pem(b"monkeys are nice", tmpfile)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200913
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400914 def passphraseCallback(maxlen, verify, extra):
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500915 return b""
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400916
917 context = Context(TLSv1_METHOD)
918 context.set_passwd_cb(passphraseCallback)
Alex Chan532b79e2017-01-24 15:14:52 +0000919 with pytest.raises(Error):
920 context.use_privatekey_file(pemFile)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400921
Alex Chan532b79e2017-01-24 15:14:52 +0000922 def test_passwd_callback_non_string(self, tmpfile):
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400923 """
Alex Chan532b79e2017-01-24 15:14:52 +0000924 `Context.use_privatekey_file` raises `OpenSSL.SSL.Error` if the
925 passphrase callback returns a true non-string value.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400926 """
Alex Chan532b79e2017-01-24 15:14:52 +0000927 pemFile = self._write_encrypted_pem(b"monkeys are nice", tmpfile)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200928
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400929 def passphraseCallback(maxlen, verify, extra):
930 return 10
931
932 context = Context(TLSv1_METHOD)
933 context.set_passwd_cb(passphraseCallback)
Alex Chan532b79e2017-01-24 15:14:52 +0000934 # TODO: Surely this is the wrong error?
935 with pytest.raises(ValueError):
936 context.use_privatekey_file(pemFile)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400937
Alex Chan532b79e2017-01-24 15:14:52 +0000938 def test_passwd_callback_too_long(self, tmpfile):
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400939 """
940 If the passphrase returned by the passphrase callback returns a string
941 longer than the indicated maximum length, it is truncated.
942 """
943 # A priori knowledge!
Alex Gaynore7f51982016-09-11 11:48:14 -0400944 passphrase = b"x" * 1024
Alex Chan532b79e2017-01-24 15:14:52 +0000945 pemFile = self._write_encrypted_pem(passphrase, tmpfile)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200946
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400947 def passphraseCallback(maxlen, verify, extra):
948 assert maxlen == 1024
Alex Gaynore7f51982016-09-11 11:48:14 -0400949 return passphrase + b"y"
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400950
951 context = Context(TLSv1_METHOD)
952 context.set_passwd_cb(passphraseCallback)
953 # This shall succeed because the truncated result is the correct
954 # passphrase.
955 context.use_privatekey_file(pemFile)
956
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400957 def test_set_info_callback(self):
958 """
Alex Chan532b79e2017-01-24 15:14:52 +0000959 `Context.set_info_callback` accepts a callable which will be
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200960 invoked when certain information about an SSL connection is available.
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400961 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500962 (server, client) = socket_pair()
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400963
964 clientSSL = Connection(Context(TLSv1_METHOD), client)
965 clientSSL.set_connect_state()
966
967 called = []
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200968
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400969 def info(conn, where, ret):
970 called.append((conn, where, ret))
971 context = Context(TLSv1_METHOD)
972 context.set_info_callback(info)
973 context.use_certificate(
974 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
975 context.use_privatekey(
976 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
977
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400978 serverSSL = Connection(context, server)
979 serverSSL.set_accept_state()
980
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -0500981 handshake(clientSSL, serverSSL)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400982
Jean-Paul Calderone3835e522014-02-02 11:12:30 -0500983 # The callback must always be called with a Connection instance as the
984 # first argument. It would probably be better to split this into
985 # separate tests for client and server side info callbacks so we could
986 # assert it is called with the right Connection instance. It would
987 # also be good to assert *something* about `where` and `ret`.
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -0500988 notConnections = [
989 conn for (conn, where, ret) in called
990 if not isinstance(conn, Connection)]
Alex Chan532b79e2017-01-24 15:14:52 +0000991 assert [] == notConnections, (
992 "Some info callback arguments were not Connection instances.")
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400993
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400994 def _load_verify_locations_test(self, *args):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400995 """
996 Create a client context which will verify the peer certificate and call
Alex Chan532b79e2017-01-24 15:14:52 +0000997 its `load_verify_locations` method with the given arguments.
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -0400998 Then connect it to a server and ensure that the handshake succeeds.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400999 """
Rick Deanb1ccd562009-07-09 23:52:39 -05001000 (server, client) = socket_pair()
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001001
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001002 clientContext = Context(TLSv1_METHOD)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001003 clientContext.load_verify_locations(*args)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001004 # Require that the server certificate verify properly or the
1005 # connection will fail.
1006 clientContext.set_verify(
1007 VERIFY_PEER,
1008 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
1009
1010 clientSSL = Connection(clientContext, client)
1011 clientSSL.set_connect_state()
1012
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001013 serverContext = Context(TLSv1_METHOD)
1014 serverContext.use_certificate(
1015 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1016 serverContext.use_privatekey(
1017 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1018
1019 serverSSL = Connection(serverContext, server)
1020 serverSSL.set_accept_state()
1021
Jean-Paul Calderonef8742032010-09-25 00:00:32 -04001022 # Without load_verify_locations above, the handshake
1023 # will fail:
1024 # Error: [('SSL routines', 'SSL3_GET_SERVER_CERTIFICATE',
1025 # 'certificate verify failed')]
1026 handshake(clientSSL, serverSSL)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001027
1028 cert = clientSSL.get_peer_certificate()
Alex Chan532b79e2017-01-24 15:14:52 +00001029 assert cert.get_subject().CN == 'Testing Root CA'
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -04001030
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001031 def _load_verify_cafile(self, cafile):
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001032 """
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001033 Verify that if path to a file containing a certificate is passed to
Alex Chan532b79e2017-01-24 15:14:52 +00001034 `Context.load_verify_locations` for the ``cafile`` parameter, that
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001035 certificate is used as a trust root for the purposes of verifying
Alex Chan532b79e2017-01-24 15:14:52 +00001036 connections created using that `Context`.
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001037 """
Alex Chan532b79e2017-01-24 15:14:52 +00001038 with open(cafile, 'w') as fObj:
1039 fObj.write(cleartextCertificatePEM.decode('ascii'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001040
1041 self._load_verify_locations_test(cafile)
1042
Alex Chan532b79e2017-01-24 15:14:52 +00001043 def test_load_verify_bytes_cafile(self, tmpfile):
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001044 """
Alex Chan532b79e2017-01-24 15:14:52 +00001045 `Context.load_verify_locations` accepts a file name as a `bytes`
1046 instance and uses the certificates within for verification purposes.
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001047 """
Alex Chan532b79e2017-01-24 15:14:52 +00001048 cafile = tmpfile + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001049 self._load_verify_cafile(cafile)
1050
Alex Chan532b79e2017-01-24 15:14:52 +00001051 def test_load_verify_unicode_cafile(self, tmpfile):
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001052 """
Alex Chan532b79e2017-01-24 15:14:52 +00001053 `Context.load_verify_locations` accepts a file name as a `unicode`
1054 instance and uses the certificates within for verification purposes.
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001055 """
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001056 self._load_verify_cafile(
Alex Chan532b79e2017-01-24 15:14:52 +00001057 tmpfile.decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001058 )
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001059
Alex Chan532b79e2017-01-24 15:14:52 +00001060 def test_load_verify_invalid_file(self, tmpfile):
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -04001061 """
Alex Chan532b79e2017-01-24 15:14:52 +00001062 `Context.load_verify_locations` raises `Error` when passed a
1063 non-existent cafile.
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -04001064 """
1065 clientContext = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001066 with pytest.raises(Error):
1067 clientContext.load_verify_locations(tmpfile)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001068
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001069 def _load_verify_directory_locations_capath(self, capath):
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001070 """
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001071 Verify that if path to a directory containing certificate files is
1072 passed to ``Context.load_verify_locations`` for the ``capath``
1073 parameter, those certificates are used as trust roots for the purposes
1074 of verifying connections created using that ``Context``.
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001075 """
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001076 makedirs(capath)
Jean-Paul Calderone24dfb332011-05-04 18:10:26 -04001077 # Hash values computed manually with c_rehash to avoid depending on
1078 # c_rehash in the test suite. One is from OpenSSL 0.9.8, the other
1079 # from OpenSSL 1.0.0.
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001080 for name in [b'c7adac82.0', b'c3705638.0']:
Jean-Paul Calderone05826732015-04-12 11:38:49 -04001081 cafile = join_bytes_or_unicode(capath, name)
1082 with open(cafile, 'w') as fObj:
1083 fObj.write(cleartextCertificatePEM.decode('ascii'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001084
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001085 self._load_verify_locations_test(None, capath)
1086
Alex Chan532b79e2017-01-24 15:14:52 +00001087 def test_load_verify_directory_bytes_capath(self, tmpfile):
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001088 """
Alex Chan532b79e2017-01-24 15:14:52 +00001089 `Context.load_verify_locations` accepts a directory name as a `bytes`
1090 instance and uses the certificates within for verification purposes.
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001091 """
1092 self._load_verify_directory_locations_capath(
Alex Chan532b79e2017-01-24 15:14:52 +00001093 tmpfile + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001094 )
1095
Alex Chan532b79e2017-01-24 15:14:52 +00001096 def test_load_verify_directory_unicode_capath(self, tmpfile):
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001097 """
Alex Chan532b79e2017-01-24 15:14:52 +00001098 `Context.load_verify_locations` accepts a directory name as a `unicode`
1099 instance and uses the certificates within for verification purposes.
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001100 """
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001101 self._load_verify_directory_locations_capath(
Alex Chan532b79e2017-01-24 15:14:52 +00001102 tmpfile.decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001103 )
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001104
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001105 def test_load_verify_locations_wrong_args(self):
1106 """
Alex Chan532b79e2017-01-24 15:14:52 +00001107 `Context.load_verify_locations` raises `TypeError` if with non-`str`
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001108 arguments.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001109 """
1110 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001111 with pytest.raises(TypeError):
1112 context.load_verify_locations(object())
1113 with pytest.raises(TypeError):
1114 context.load_verify_locations(object(), object())
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001115
Hynek Schlawack734d3022015-09-05 19:19:32 +02001116 @pytest.mark.skipif(
Paul Kehrer55fb3412017-06-29 18:44:08 -05001117 not platform.startswith("linux"),
1118 reason="Loading fallback paths is a linux-specific behavior to "
1119 "accommodate pyca/cryptography manylinux1 wheels"
1120 )
1121 def test_fallback_default_verify_paths(self, monkeypatch):
1122 """
1123 Test that we load certificates successfully on linux from the fallback
1124 path. To do this we set the _CRYPTOGRAPHY_MANYLINUX1_CA_FILE and
1125 _CRYPTOGRAPHY_MANYLINUX1_CA_DIR vars to be equal to whatever the
1126 current OpenSSL default is and we disable
1127 SSL_CTX_SET_default_verify_paths so that it can't find certs unless
1128 it loads via fallback.
1129 """
1130 context = Context(TLSv1_METHOD)
1131 monkeypatch.setattr(
1132 _lib, "SSL_CTX_set_default_verify_paths", lambda x: 1
1133 )
1134 monkeypatch.setattr(
1135 SSL,
1136 "_CRYPTOGRAPHY_MANYLINUX1_CA_FILE",
1137 _ffi.string(_lib.X509_get_default_cert_file())
1138 )
1139 monkeypatch.setattr(
1140 SSL,
1141 "_CRYPTOGRAPHY_MANYLINUX1_CA_DIR",
1142 _ffi.string(_lib.X509_get_default_cert_dir())
1143 )
1144 context.set_default_verify_paths()
1145 store = context.get_cert_store()
1146 sk_obj = _lib.X509_STORE_get0_objects(store._store)
1147 assert sk_obj != _ffi.NULL
1148 num = _lib.sk_X509_OBJECT_num(sk_obj)
1149 assert num != 0
1150
1151 def test_check_env_vars(self, monkeypatch):
1152 """
1153 Test that we return True/False appropriately if the env vars are set.
1154 """
1155 context = Context(TLSv1_METHOD)
1156 dir_var = "CUSTOM_DIR_VAR"
1157 file_var = "CUSTOM_FILE_VAR"
1158 assert context._check_env_vars_set(dir_var, file_var) is False
1159 monkeypatch.setenv(dir_var, "value")
1160 monkeypatch.setenv(file_var, "value")
1161 assert context._check_env_vars_set(dir_var, file_var) is True
1162 assert context._check_env_vars_set(dir_var, file_var) is True
1163
1164 def test_verify_no_fallback_if_env_vars_set(self, monkeypatch):
1165 """
1166 Test that we don't use the fallback path if env vars are set.
1167 """
1168 context = Context(TLSv1_METHOD)
1169 monkeypatch.setattr(
1170 _lib, "SSL_CTX_set_default_verify_paths", lambda x: 1
1171 )
1172 dir_env_var = _ffi.string(
1173 _lib.X509_get_default_cert_dir_env()
1174 ).decode("ascii")
1175 file_env_var = _ffi.string(
1176 _lib.X509_get_default_cert_file_env()
1177 ).decode("ascii")
1178 monkeypatch.setenv(dir_env_var, "value")
1179 monkeypatch.setenv(file_env_var, "value")
1180 context.set_default_verify_paths()
1181
1182 monkeypatch.setattr(
1183 context,
1184 "_fallback_default_verify_paths",
1185 raiser(SystemError)
1186 )
1187 context.set_default_verify_paths()
1188
1189 @pytest.mark.skipif(
Hynek Schlawack734d3022015-09-05 19:19:32 +02001190 platform == "win32",
1191 reason="set_default_verify_paths appears not to work on Windows. "
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -04001192 "See LP#404343 and LP#404344."
Hynek Schlawack734d3022015-09-05 19:19:32 +02001193 )
1194 def test_set_default_verify_paths(self):
1195 """
Alex Chan532b79e2017-01-24 15:14:52 +00001196 `Context.set_default_verify_paths` causes the platform-specific CA
1197 certificate locations to be used for verification purposes.
Hynek Schlawack734d3022015-09-05 19:19:32 +02001198 """
1199 # Testing this requires a server with a certificate signed by one
1200 # of the CAs in the platform CA location. Getting one of those
1201 # costs money. Fortunately (or unfortunately, depending on your
1202 # perspective), it's easy to think of a public server on the
1203 # internet which has such a certificate. Connecting to the network
1204 # in a unit test is bad, but it's the only way I can think of to
1205 # really test this. -exarkun
Hynek Schlawackbf887932015-10-21 17:13:47 +02001206 context = Context(SSLv23_METHOD)
Hynek Schlawack734d3022015-09-05 19:19:32 +02001207 context.set_default_verify_paths()
1208 context.set_verify(
1209 VERIFY_PEER,
1210 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001211
Hynek Schlawack734d3022015-09-05 19:19:32 +02001212 client = socket()
Hynek Schlawackbf887932015-10-21 17:13:47 +02001213 client.connect(("encrypted.google.com", 443))
Hynek Schlawack734d3022015-09-05 19:19:32 +02001214 clientSSL = Connection(context, client)
1215 clientSSL.set_connect_state()
Alex Gaynor373926c2018-05-12 07:43:07 -04001216 clientSSL.set_tlsext_host_name(b"encrypted.google.com")
Hynek Schlawack734d3022015-09-05 19:19:32 +02001217 clientSSL.do_handshake()
1218 clientSSL.send(b"GET / HTTP/1.0\r\n\r\n")
Alex Chan532b79e2017-01-24 15:14:52 +00001219 assert clientSSL.recv(1024)
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05001220
Paul Kehrer55fb3412017-06-29 18:44:08 -05001221 def test_fallback_path_is_not_file_or_dir(self):
1222 """
1223 Test that when passed empty arrays or paths that do not exist no
1224 errors are raised.
1225 """
1226 context = Context(TLSv1_METHOD)
1227 context._fallback_default_verify_paths([], [])
1228 context._fallback_default_verify_paths(
1229 ["/not/a/file"], ["/not/a/dir"]
1230 )
1231
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001232 def test_add_extra_chain_cert_invalid_cert(self):
1233 """
Alex Chan532b79e2017-01-24 15:14:52 +00001234 `Context.add_extra_chain_cert` raises `TypeError` if called with an
1235 object which is not an instance of `X509`.
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001236 """
1237 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001238 with pytest.raises(TypeError):
1239 context.add_extra_chain_cert(object())
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001240
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001241 def _handshake_test(self, serverContext, clientContext):
1242 """
1243 Verify that a client and server created with the given contexts can
1244 successfully handshake and communicate.
1245 """
1246 serverSocket, clientSocket = socket_pair()
1247
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001248 server = Connection(serverContext, serverSocket)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001249 server.set_accept_state()
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001250
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001251 client = Connection(clientContext, clientSocket)
1252 client.set_connect_state()
1253
1254 # Make them talk to each other.
Alex Chan532b79e2017-01-24 15:14:52 +00001255 # interact_in_memory(client, server)
1256 for _ in range(3):
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001257 for s in [client, server]:
1258 try:
1259 s.do_handshake()
1260 except WantReadError:
1261 pass
1262
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001263 def test_set_verify_callback_connection_argument(self):
1264 """
1265 The first argument passed to the verify callback is the
Alex Chan532b79e2017-01-24 15:14:52 +00001266 `Connection` instance for which verification is taking place.
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001267 """
1268 serverContext = Context(TLSv1_METHOD)
1269 serverContext.use_privatekey(
1270 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1271 serverContext.use_certificate(
1272 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1273 serverConnection = Connection(serverContext, None)
1274
1275 class VerifyCallback(object):
1276 def callback(self, connection, *args):
1277 self.connection = connection
1278 return 1
1279
1280 verify = VerifyCallback()
1281 clientContext = Context(TLSv1_METHOD)
1282 clientContext.set_verify(VERIFY_PEER, verify.callback)
1283 clientConnection = Connection(clientContext, None)
1284 clientConnection.set_connect_state()
1285
Alex Chan532b79e2017-01-24 15:14:52 +00001286 handshake_in_memory(clientConnection, serverConnection)
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001287
Alex Chan532b79e2017-01-24 15:14:52 +00001288 assert verify.connection is clientConnection
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001289
Paul Kehrere7381862017-11-30 20:55:25 +08001290 def test_x509_in_verify_works(self):
1291 """
1292 We had a bug where the X509 cert instantiated in the callback wrapper
1293 didn't __init__ so it was missing objects needed when calling
1294 get_subject. This test sets up a handshake where we call get_subject
1295 on the cert provided to the verify callback.
1296 """
1297 serverContext = Context(TLSv1_METHOD)
1298 serverContext.use_privatekey(
1299 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1300 serverContext.use_certificate(
1301 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1302 serverConnection = Connection(serverContext, None)
1303
1304 def verify_cb_get_subject(conn, cert, errnum, depth, ok):
1305 assert cert.get_subject()
1306 return 1
1307
1308 clientContext = Context(TLSv1_METHOD)
1309 clientContext.set_verify(VERIFY_PEER, verify_cb_get_subject)
1310 clientConnection = Connection(clientContext, None)
1311 clientConnection.set_connect_state()
1312
1313 handshake_in_memory(clientConnection, serverConnection)
1314
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001315 def test_set_verify_callback_exception(self):
1316 """
Alex Chan532b79e2017-01-24 15:14:52 +00001317 If the verify callback passed to `Context.set_verify` raises an
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001318 exception, verification fails and the exception is propagated to the
Alex Chan532b79e2017-01-24 15:14:52 +00001319 caller of `Connection.do_handshake`.
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001320 """
Paul Kehrer7d5a3bf2019-01-21 12:24:02 -06001321 serverContext = Context(TLSv1_2_METHOD)
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001322 serverContext.use_privatekey(
1323 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1324 serverContext.use_certificate(
1325 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1326
Paul Kehrer7d5a3bf2019-01-21 12:24:02 -06001327 clientContext = Context(TLSv1_2_METHOD)
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001328
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001329 def verify_callback(*args):
1330 raise Exception("silly verify failure")
1331 clientContext.set_verify(VERIFY_PEER, verify_callback)
1332
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01001333 with pytest.raises(Exception) as exc:
1334 self._handshake_test(serverContext, clientContext)
1335
Alex Chan532b79e2017-01-24 15:14:52 +00001336 assert "silly verify failure" == str(exc.value)
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001337
Alex Chan532b79e2017-01-24 15:14:52 +00001338 def test_add_extra_chain_cert(self, tmpdir):
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001339 """
Alex Chan532b79e2017-01-24 15:14:52 +00001340 `Context.add_extra_chain_cert` accepts an `X509`
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001341 instance to add to the certificate chain.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001342
Alex Chan532b79e2017-01-24 15:14:52 +00001343 See `_create_certificate_chain` for the details of the
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001344 certificate chain tested.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001345
1346 The chain is tested by starting a server with scert and connecting
1347 to it with a client which trusts cacert and requires verification to
1348 succeed.
1349 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001350 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001351 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1352
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001353 # Dump the CA certificate to a file because that's the only way to load
1354 # it as a trusted CA in the client context.
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001355 for cert, name in [(cacert, 'ca.pem'),
1356 (icert, 'i.pem'),
1357 (scert, 's.pem')]:
Alex Chan532b79e2017-01-24 15:14:52 +00001358 with tmpdir.join(name).open('w') as f:
Hynek Schlawacke90680f2015-04-16 15:09:27 -04001359 f.write(dump_certificate(FILETYPE_PEM, cert).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001360
Hynek Schlawack1902c012015-04-16 15:06:41 -04001361 for key, name in [(cakey, 'ca.key'),
1362 (ikey, 'i.key'),
1363 (skey, 's.key')]:
Alex Chan532b79e2017-01-24 15:14:52 +00001364 with tmpdir.join(name).open('w') as f:
Hynek Schlawacke90680f2015-04-16 15:09:27 -04001365 f.write(dump_privatekey(FILETYPE_PEM, key).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001366
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001367 # Create the server context
1368 serverContext = Context(TLSv1_METHOD)
1369 serverContext.use_privatekey(skey)
1370 serverContext.use_certificate(scert)
Jean-Paul Calderone16cf03d2010-09-08 18:53:39 -04001371 # The client already has cacert, we only need to give them icert.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001372 serverContext.add_extra_chain_cert(icert)
1373
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001374 # Create the client
1375 clientContext = Context(TLSv1_METHOD)
1376 clientContext.set_verify(
1377 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Alex Chan532b79e2017-01-24 15:14:52 +00001378 clientContext.load_verify_locations(str(tmpdir.join("ca.pem")))
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001379
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001380 # Try it out.
1381 self._handshake_test(serverContext, clientContext)
1382
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001383 def _use_certificate_chain_file_test(self, certdir):
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001384 """
Alex Chan532b79e2017-01-24 15:14:52 +00001385 Verify that `Context.use_certificate_chain_file` reads a
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001386 certificate chain from a specified file.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001387
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001388 The chain is tested by starting a server with scert and connecting to
1389 it with a client which trusts cacert and requires verification to
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001390 succeed.
1391 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001392 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001393 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1394
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001395 makedirs(certdir)
1396
Jean-Paul Calderone05826732015-04-12 11:38:49 -04001397 chainFile = join_bytes_or_unicode(certdir, "chain.pem")
1398 caFile = join_bytes_or_unicode(certdir, "ca.pem")
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001399
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001400 # Write out the chain file.
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001401 with open(chainFile, 'wb') as fObj:
1402 # Most specific to least general.
1403 fObj.write(dump_certificate(FILETYPE_PEM, scert))
1404 fObj.write(dump_certificate(FILETYPE_PEM, icert))
1405 fObj.write(dump_certificate(FILETYPE_PEM, cacert))
1406
1407 with open(caFile, 'w') as fObj:
1408 fObj.write(dump_certificate(FILETYPE_PEM, cacert).decode('ascii'))
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001409
1410 serverContext = Context(TLSv1_METHOD)
1411 serverContext.use_certificate_chain_file(chainFile)
1412 serverContext.use_privatekey(skey)
1413
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001414 clientContext = Context(TLSv1_METHOD)
1415 clientContext.set_verify(
1416 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001417 clientContext.load_verify_locations(caFile)
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001418
1419 self._handshake_test(serverContext, clientContext)
1420
Alex Chan532b79e2017-01-24 15:14:52 +00001421 def test_use_certificate_chain_file_bytes(self, tmpfile):
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001422 """
1423 ``Context.use_certificate_chain_file`` accepts the name of a file (as
1424 an instance of ``bytes``) to specify additional certificates to use to
1425 construct and verify a trust chain.
1426 """
1427 self._use_certificate_chain_file_test(
Alex Chan532b79e2017-01-24 15:14:52 +00001428 tmpfile + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001429 )
1430
Alex Chan532b79e2017-01-24 15:14:52 +00001431 def test_use_certificate_chain_file_unicode(self, tmpfile):
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001432 """
1433 ``Context.use_certificate_chain_file`` accepts the name of a file (as
1434 an instance of ``unicode``) to specify additional certificates to use
1435 to construct and verify a trust chain.
1436 """
1437 self._use_certificate_chain_file_test(
Alex Chan532b79e2017-01-24 15:14:52 +00001438 tmpfile.decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001439 )
1440
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001441 def test_use_certificate_chain_file_wrong_args(self):
1442 """
Alex Chan532b79e2017-01-24 15:14:52 +00001443 `Context.use_certificate_chain_file` raises `TypeError` if passed a
1444 non-byte string single argument.
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001445 """
1446 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001447 with pytest.raises(TypeError):
1448 context.use_certificate_chain_file(object())
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001449
Alex Chan532b79e2017-01-24 15:14:52 +00001450 def test_use_certificate_chain_file_missing_file(self, tmpfile):
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001451 """
Alex Chan532b79e2017-01-24 15:14:52 +00001452 `Context.use_certificate_chain_file` raises `OpenSSL.SSL.Error` when
1453 passed a bad chain file name (for example, the name of a file which
1454 does not exist).
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001455 """
1456 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001457 with pytest.raises(Error):
1458 context.use_certificate_chain_file(tmpfile)
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001459
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001460 def test_set_verify_mode(self):
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001461 """
Alex Chan532b79e2017-01-24 15:14:52 +00001462 `Context.get_verify_mode` returns the verify mode flags previously
1463 passed to `Context.set_verify`.
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001464 """
1465 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001466 assert context.get_verify_mode() == 0
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001467 context.set_verify(
1468 VERIFY_PEER | VERIFY_CLIENT_ONCE, lambda *args: None)
Alex Chan532b79e2017-01-24 15:14:52 +00001469 assert context.get_verify_mode() == (VERIFY_PEER | VERIFY_CLIENT_ONCE)
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001470
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001471 @skip_if_py3
1472 def test_set_verify_mode_long(self):
1473 """
Alex Chan532b79e2017-01-24 15:14:52 +00001474 On Python 2 `Context.set_verify_mode` accepts values of type `long`
1475 as well as `int`.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001476 """
1477 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001478 assert context.get_verify_mode() == 0
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001479 context.set_verify(
Hynek Schlawackb4ceed32015-09-05 20:55:19 +02001480 long(VERIFY_PEER | VERIFY_CLIENT_ONCE), lambda *args: None
1481 ) # pragma: nocover
Alex Chan532b79e2017-01-24 15:14:52 +00001482 assert context.get_verify_mode() == (VERIFY_PEER | VERIFY_CLIENT_ONCE)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001483
Alex Chanfb078d82017-04-20 11:16:15 +01001484 @pytest.mark.parametrize('mode', [None, 1.0, object(), 'mode'])
1485 def test_set_verify_wrong_mode_arg(self, mode):
1486 """
1487 `Context.set_verify` raises `TypeError` if the first argument is
1488 not an integer.
1489 """
1490 context = Context(TLSv1_METHOD)
1491 with pytest.raises(TypeError):
1492 context.set_verify(mode=mode, callback=lambda *args: None)
1493
1494 @pytest.mark.parametrize('callback', [None, 1.0, 'mode', ('foo', 'bar')])
1495 def test_set_verify_wrong_callable_arg(self, callback):
1496 """
Alex Gaynor40bc0f12018-05-14 14:06:16 -04001497 `Context.set_verify` raises `TypeError` if the second argument
Alex Chanfb078d82017-04-20 11:16:15 +01001498 is not callable.
1499 """
1500 context = Context(TLSv1_METHOD)
1501 with pytest.raises(TypeError):
1502 context.set_verify(mode=VERIFY_PEER, callback=callback)
1503
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001504 def test_load_tmp_dh_wrong_args(self):
1505 """
Alex Chan532b79e2017-01-24 15:14:52 +00001506 `Context.load_tmp_dh` raises `TypeError` if called with a
1507 non-`str` argument.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001508 """
1509 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001510 with pytest.raises(TypeError):
1511 context.load_tmp_dh(object())
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001512
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001513 def test_load_tmp_dh_missing_file(self):
1514 """
Alex Chan532b79e2017-01-24 15:14:52 +00001515 `Context.load_tmp_dh` raises `OpenSSL.SSL.Error` if the
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001516 specified file does not exist.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001517 """
1518 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001519 with pytest.raises(Error):
1520 context.load_tmp_dh(b"hello")
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001521
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001522 def _load_tmp_dh_test(self, dhfilename):
Jean-Paul Calderone4e0c43f2015-04-13 10:15:17 -04001523 """
1524 Verify that calling ``Context.load_tmp_dh`` with the given filename
1525 does not raise an exception.
1526 """
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001527 context = Context(TLSv1_METHOD)
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001528 with open(dhfilename, "w") as dhfile:
1529 dhfile.write(dhparam)
1530
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001531 context.load_tmp_dh(dhfilename)
1532 # XXX What should I assert here? -exarkun
1533
Alex Chan532b79e2017-01-24 15:14:52 +00001534 def test_load_tmp_dh_bytes(self, tmpfile):
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001535 """
Alex Chan532b79e2017-01-24 15:14:52 +00001536 `Context.load_tmp_dh` loads Diffie-Hellman parameters from the
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001537 specified file (given as ``bytes``).
1538 """
1539 self._load_tmp_dh_test(
Alex Chan532b79e2017-01-24 15:14:52 +00001540 tmpfile + NON_ASCII.encode(getfilesystemencoding()),
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001541 )
1542
Alex Chan532b79e2017-01-24 15:14:52 +00001543 def test_load_tmp_dh_unicode(self, tmpfile):
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001544 """
Alex Chan532b79e2017-01-24 15:14:52 +00001545 `Context.load_tmp_dh` loads Diffie-Hellman parameters from the
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001546 specified file (given as ``unicode``).
1547 """
1548 self._load_tmp_dh_test(
Alex Chan532b79e2017-01-24 15:14:52 +00001549 tmpfile.decode(getfilesystemencoding()) + NON_ASCII,
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001550 )
1551
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001552 def test_set_tmp_ecdh(self):
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001553 """
Alex Chan532b79e2017-01-24 15:14:52 +00001554 `Context.set_tmp_ecdh` sets the elliptic curve for Diffie-Hellman to
1555 the specified curve.
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001556 """
1557 context = Context(TLSv1_METHOD)
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001558 for curve in get_elliptic_curves():
Hynek Schlawacka07fa8c2015-10-17 10:15:28 +02001559 if curve.name.startswith(u"Oakley-"):
Hynek Schlawack7408aff2015-10-17 09:51:16 +02001560 # Setting Oakley-EC2N-4 and Oakley-EC2N-3 adds
1561 # ('bignum routines', 'BN_mod_inverse', 'no inverse') to the
1562 # error queue on OpenSSL 1.0.2.
1563 continue
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001564 # The only easily "assertable" thing is that it does not raise an
1565 # exception.
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001566 context.set_tmp_ecdh(curve)
Alex Gaynor12dc0842014-01-17 12:51:31 -06001567
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001568 def test_set_session_cache_mode_wrong_args(self):
1569 """
Alex Chan532b79e2017-01-24 15:14:52 +00001570 `Context.set_session_cache_mode` raises `TypeError` if called with
1571 a non-integer argument.
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001572 called with other than one integer argument.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001573 """
1574 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001575 with pytest.raises(TypeError):
1576 context.set_session_cache_mode(object())
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001577
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001578 def test_session_cache_mode(self):
1579 """
Alex Chan532b79e2017-01-24 15:14:52 +00001580 `Context.set_session_cache_mode` specifies how sessions are cached.
1581 The setting can be retrieved via `Context.get_session_cache_mode`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001582 """
1583 context = Context(TLSv1_METHOD)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001584 context.set_session_cache_mode(SESS_CACHE_OFF)
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001585 off = context.set_session_cache_mode(SESS_CACHE_BOTH)
Alex Chan532b79e2017-01-24 15:14:52 +00001586 assert SESS_CACHE_OFF == off
1587 assert SESS_CACHE_BOTH == context.get_session_cache_mode()
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001588
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001589 @skip_if_py3
1590 def test_session_cache_mode_long(self):
1591 """
Alex Chan532b79e2017-01-24 15:14:52 +00001592 On Python 2 `Context.set_session_cache_mode` accepts values
1593 of type `long` as well as `int`.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001594 """
1595 context = Context(TLSv1_METHOD)
1596 context.set_session_cache_mode(long(SESS_CACHE_BOTH))
Alex Chan532b79e2017-01-24 15:14:52 +00001597 assert SESS_CACHE_BOTH == context.get_session_cache_mode()
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001598
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001599 def test_get_cert_store(self):
1600 """
Alex Chan532b79e2017-01-24 15:14:52 +00001601 `Context.get_cert_store` returns a `X509Store` instance.
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001602 """
1603 context = Context(TLSv1_METHOD)
1604 store = context.get_cert_store()
Alex Chan532b79e2017-01-24 15:14:52 +00001605 assert isinstance(store, X509Store)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001606
Jeremy Lainé02261ad2018-05-16 18:33:25 +02001607 def test_set_tlsext_use_srtp_not_bytes(self):
1608 """
1609 `Context.set_tlsext_use_srtp' enables negotiating SRTP keying material.
1610
1611 It raises a TypeError if the list of profiles is not a byte string.
1612 """
1613 context = Context(TLSv1_METHOD)
1614 with pytest.raises(TypeError):
1615 context.set_tlsext_use_srtp(text_type('SRTP_AES128_CM_SHA1_80'))
1616
1617 def test_set_tlsext_use_srtp_invalid_profile(self):
1618 """
1619 `Context.set_tlsext_use_srtp' enables negotiating SRTP keying material.
1620
1621 It raises an Error if the call to OpenSSL fails.
1622 """
1623 context = Context(TLSv1_METHOD)
1624 with pytest.raises(Error):
1625 context.set_tlsext_use_srtp(b'SRTP_BOGUS')
1626
1627 def test_set_tlsext_use_srtp_valid(self):
1628 """
1629 `Context.set_tlsext_use_srtp' enables negotiating SRTP keying material.
1630
1631 It does not return anything.
1632 """
1633 context = Context(TLSv1_METHOD)
1634 assert context.set_tlsext_use_srtp(b'SRTP_AES128_CM_SHA1_80') is None
1635
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001636
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001637class TestServerNameCallback(object):
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001638 """
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001639 Tests for `Context.set_tlsext_servername_callback` and its
1640 interaction with `Connection`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001641 """
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001642 def test_old_callback_forgotten(self):
1643 """
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001644 If `Context.set_tlsext_servername_callback` is used to specify
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001645 a new callback, the one it replaces is dereferenced.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001646 """
Alex Chanfb078d82017-04-20 11:16:15 +01001647 def callback(connection): # pragma: no cover
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001648 pass
1649
Alex Chanfb078d82017-04-20 11:16:15 +01001650 def replacement(connection): # pragma: no cover
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001651 pass
1652
1653 context = Context(TLSv1_METHOD)
1654 context.set_tlsext_servername_callback(callback)
1655
1656 tracker = ref(callback)
1657 del callback
1658
1659 context.set_tlsext_servername_callback(replacement)
Jean-Paul Calderoned4033eb2014-01-11 08:21:46 -05001660
1661 # One run of the garbage collector happens to work on CPython. PyPy
1662 # doesn't collect the underlying object until a second run for whatever
1663 # reason. That's fine, it still demonstrates our code has properly
1664 # dropped the reference.
1665 collect()
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001666 collect()
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001667
1668 callback = tracker()
1669 if callback is not None:
1670 referrers = get_referrers(callback)
Alex Chanfb078d82017-04-20 11:16:15 +01001671 if len(referrers) > 1: # pragma: nocover
1672 pytest.fail("Some references remain: %r" % (referrers,))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001673
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001674 def test_no_servername(self):
1675 """
1676 When a client specifies no server name, the callback passed to
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001677 `Context.set_tlsext_servername_callback` is invoked and the
1678 result of `Connection.get_servername` is `None`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001679 """
1680 args = []
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001681
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001682 def servername(conn):
1683 args.append((conn, conn.get_servername()))
1684 context = Context(TLSv1_METHOD)
1685 context.set_tlsext_servername_callback(servername)
1686
1687 # Lose our reference to it. The Context is responsible for keeping it
1688 # alive now.
1689 del servername
1690 collect()
1691
1692 # Necessary to actually accept the connection
1693 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001694 context.use_certificate(
1695 load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001696
1697 # Do a little connection to trigger the logic
1698 server = Connection(context, None)
1699 server.set_accept_state()
1700
1701 client = Connection(Context(TLSv1_METHOD), None)
1702 client.set_connect_state()
1703
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001704 interact_in_memory(server, client)
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001705
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001706 assert args == [(server, None)]
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001707
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001708 def test_servername(self):
1709 """
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001710 When a client specifies a server name in its hello message, the
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001711 callback passed to `Contexts.set_tlsext_servername_callback` is
1712 invoked and the result of `Connection.get_servername` is that
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001713 server name.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001714 """
1715 args = []
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001716
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001717 def servername(conn):
1718 args.append((conn, conn.get_servername()))
1719 context = Context(TLSv1_METHOD)
1720 context.set_tlsext_servername_callback(servername)
1721
1722 # Necessary to actually accept the connection
1723 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001724 context.use_certificate(
1725 load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001726
1727 # Do a little connection to trigger the logic
1728 server = Connection(context, None)
1729 server.set_accept_state()
1730
1731 client = Connection(Context(TLSv1_METHOD), None)
1732 client.set_connect_state()
Alex Gaynore7f51982016-09-11 11:48:14 -04001733 client.set_tlsext_host_name(b"foo1.example.com")
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001734
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001735 interact_in_memory(server, client)
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001736
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001737 assert args == [(server, b"foo1.example.com")]
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001738
1739
Paul Kehrer4d575902019-02-26 21:42:12 +08001740@pytest.mark.skipif(
1741 not _lib.Cryptography_HAS_NEXTPROTONEG, reason="NPN is not available"
1742)
Alex Chan9e08b3e2016-11-10 12:18:54 +00001743class TestNextProtoNegotiation(object):
Cory Benfield84a121e2014-03-31 20:30:25 +01001744 """
1745 Test for Next Protocol Negotiation in PyOpenSSL.
1746 """
Alex Chan9e08b3e2016-11-10 12:18:54 +00001747 def test_npn_success(self):
1748 """
1749 Tests that clients and servers that agree on the negotiated next
1750 protocol can correct establish a connection, and that the agreed
1751 protocol is reported by the connections.
1752 """
1753 advertise_args = []
1754 select_args = []
1755
1756 def advertise(conn):
1757 advertise_args.append((conn,))
1758 return [b'http/1.1', b'spdy/2']
1759
1760 def select(conn, options):
1761 select_args.append((conn, options))
1762 return b'spdy/2'
1763
1764 server_context = Context(TLSv1_METHOD)
1765 server_context.set_npn_advertise_callback(advertise)
1766
1767 client_context = Context(TLSv1_METHOD)
1768 client_context.set_npn_select_callback(select)
1769
1770 # Necessary to actually accept the connection
1771 server_context.use_privatekey(
1772 load_privatekey(FILETYPE_PEM, server_key_pem))
1773 server_context.use_certificate(
1774 load_certificate(FILETYPE_PEM, server_cert_pem))
1775
1776 # Do a little connection to trigger the logic
1777 server = Connection(server_context, None)
1778 server.set_accept_state()
1779
1780 client = Connection(client_context, None)
1781 client.set_connect_state()
1782
1783 interact_in_memory(server, client)
1784
1785 assert advertise_args == [(server,)]
1786 assert select_args == [(client, [b'http/1.1', b'spdy/2'])]
1787
1788 assert server.get_next_proto_negotiated() == b'spdy/2'
1789 assert client.get_next_proto_negotiated() == b'spdy/2'
1790
1791 def test_npn_client_fail(self):
1792 """
1793 Tests that when clients and servers cannot agree on what protocol
1794 to use next that the TLS connection does not get established.
1795 """
1796 advertise_args = []
1797 select_args = []
1798
1799 def advertise(conn):
1800 advertise_args.append((conn,))
1801 return [b'http/1.1', b'spdy/2']
1802
1803 def select(conn, options):
1804 select_args.append((conn, options))
1805 return b''
1806
1807 server_context = Context(TLSv1_METHOD)
1808 server_context.set_npn_advertise_callback(advertise)
1809
1810 client_context = Context(TLSv1_METHOD)
1811 client_context.set_npn_select_callback(select)
1812
1813 # Necessary to actually accept the connection
1814 server_context.use_privatekey(
1815 load_privatekey(FILETYPE_PEM, server_key_pem))
1816 server_context.use_certificate(
1817 load_certificate(FILETYPE_PEM, server_cert_pem))
1818
1819 # Do a little connection to trigger the logic
1820 server = Connection(server_context, None)
1821 server.set_accept_state()
1822
1823 client = Connection(client_context, None)
1824 client.set_connect_state()
1825
1826 # If the client doesn't return anything, the connection will fail.
1827 with pytest.raises(Error):
1828 interact_in_memory(server, client)
1829
1830 assert advertise_args == [(server,)]
1831 assert select_args == [(client, [b'http/1.1', b'spdy/2'])]
1832
1833 def test_npn_select_error(self):
1834 """
1835 Test that we can handle exceptions in the select callback. If
1836 select fails it should be fatal to the connection.
1837 """
1838 advertise_args = []
1839
1840 def advertise(conn):
1841 advertise_args.append((conn,))
1842 return [b'http/1.1', b'spdy/2']
1843
1844 def select(conn, options):
1845 raise TypeError
1846
1847 server_context = Context(TLSv1_METHOD)
1848 server_context.set_npn_advertise_callback(advertise)
1849
1850 client_context = Context(TLSv1_METHOD)
1851 client_context.set_npn_select_callback(select)
1852
1853 # Necessary to actually accept the connection
1854 server_context.use_privatekey(
1855 load_privatekey(FILETYPE_PEM, server_key_pem))
1856 server_context.use_certificate(
1857 load_certificate(FILETYPE_PEM, server_cert_pem))
1858
1859 # Do a little connection to trigger the logic
1860 server = Connection(server_context, None)
1861 server.set_accept_state()
1862
1863 client = Connection(client_context, None)
1864 client.set_connect_state()
1865
1866 # If the callback throws an exception it should be raised here.
1867 with pytest.raises(TypeError):
1868 interact_in_memory(server, client)
1869 assert advertise_args == [(server,), ]
1870
1871 def test_npn_advertise_error(self):
1872 """
1873 Test that we can handle exceptions in the advertise callback. If
1874 advertise fails no NPN is advertised to the client.
1875 """
1876 select_args = []
1877
1878 def advertise(conn):
1879 raise TypeError
1880
1881 def select(conn, options): # pragma: nocover
Cory Benfieldba1820d2015-04-13 17:39:12 -04001882 """
Alex Chan9e08b3e2016-11-10 12:18:54 +00001883 Assert later that no args are actually appended.
Cory Benfieldba1820d2015-04-13 17:39:12 -04001884 """
Alex Chan9e08b3e2016-11-10 12:18:54 +00001885 select_args.append((conn, options))
1886 return b''
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001887
Alex Chan9e08b3e2016-11-10 12:18:54 +00001888 server_context = Context(TLSv1_METHOD)
1889 server_context.set_npn_advertise_callback(advertise)
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001890
Alex Chan9e08b3e2016-11-10 12:18:54 +00001891 client_context = Context(TLSv1_METHOD)
1892 client_context.set_npn_select_callback(select)
Cory Benfield84a121e2014-03-31 20:30:25 +01001893
Alex Chan9e08b3e2016-11-10 12:18:54 +00001894 # Necessary to actually accept the connection
1895 server_context.use_privatekey(
1896 load_privatekey(FILETYPE_PEM, server_key_pem))
1897 server_context.use_certificate(
1898 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield84a121e2014-03-31 20:30:25 +01001899
Alex Chan9e08b3e2016-11-10 12:18:54 +00001900 # Do a little connection to trigger the logic
1901 server = Connection(server_context, None)
1902 server.set_accept_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001903
Alex Chan9e08b3e2016-11-10 12:18:54 +00001904 client = Connection(client_context, None)
1905 client.set_connect_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001906
Alex Chan9e08b3e2016-11-10 12:18:54 +00001907 # If the client doesn't return anything, the connection will fail.
1908 with pytest.raises(TypeError):
1909 interact_in_memory(server, client)
1910 assert select_args == []
Cory Benfield0ea76e72015-03-22 09:05:28 +00001911
1912
Alex Chanec1e32d2016-11-10 14:11:45 +00001913class TestApplicationLayerProtoNegotiation(object):
Cory Benfield12eae892014-06-07 15:42:56 +01001914 """
1915 Tests for ALPN in PyOpenSSL.
1916 """
Cory Benfielde46fa842015-04-13 16:50:49 -04001917 # Skip tests on versions that don't support ALPN.
1918 if _lib.Cryptography_HAS_ALPN:
Cory Benfield12eae892014-06-07 15:42:56 +01001919
Cory Benfielde46fa842015-04-13 16:50:49 -04001920 def test_alpn_success(self):
1921 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04001922 Clients and servers that agree on the negotiated ALPN protocol can
1923 correct establish a connection, and the agreed protocol is reported
1924 by the connections.
Cory Benfielde46fa842015-04-13 16:50:49 -04001925 """
1926 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001927
Cory Benfielde46fa842015-04-13 16:50:49 -04001928 def select(conn, options):
1929 select_args.append((conn, options))
1930 return b'spdy/2'
Cory Benfield12eae892014-06-07 15:42:56 +01001931
Cory Benfielde46fa842015-04-13 16:50:49 -04001932 client_context = Context(TLSv1_METHOD)
1933 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfield12eae892014-06-07 15:42:56 +01001934
Cory Benfielde46fa842015-04-13 16:50:49 -04001935 server_context = Context(TLSv1_METHOD)
1936 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01001937
Cory Benfielde46fa842015-04-13 16:50:49 -04001938 # Necessary to actually accept the connection
1939 server_context.use_privatekey(
1940 load_privatekey(FILETYPE_PEM, server_key_pem))
1941 server_context.use_certificate(
1942 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield12eae892014-06-07 15:42:56 +01001943
Cory Benfielde46fa842015-04-13 16:50:49 -04001944 # Do a little connection to trigger the logic
1945 server = Connection(server_context, None)
1946 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001947
Cory Benfielde46fa842015-04-13 16:50:49 -04001948 client = Connection(client_context, None)
1949 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001950
Alex Chanec1e32d2016-11-10 14:11:45 +00001951 interact_in_memory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001952
Alex Chanec1e32d2016-11-10 14:11:45 +00001953 assert select_args == [(server, [b'http/1.1', b'spdy/2'])]
Cory Benfielde46fa842015-04-13 16:50:49 -04001954
Alex Chanec1e32d2016-11-10 14:11:45 +00001955 assert server.get_alpn_proto_negotiated() == b'spdy/2'
1956 assert client.get_alpn_proto_negotiated() == b'spdy/2'
Cory Benfield12eae892014-06-07 15:42:56 +01001957
Cory Benfielde46fa842015-04-13 16:50:49 -04001958 def test_alpn_set_on_connection(self):
1959 """
1960 The same as test_alpn_success, but setting the ALPN protocols on
1961 the connection rather than the context.
1962 """
1963 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001964
Cory Benfielde46fa842015-04-13 16:50:49 -04001965 def select(conn, options):
1966 select_args.append((conn, options))
1967 return b'spdy/2'
Cory Benfield12eae892014-06-07 15:42:56 +01001968
Cory Benfielde46fa842015-04-13 16:50:49 -04001969 # Setup the client context but don't set any ALPN protocols.
1970 client_context = Context(TLSv1_METHOD)
Cory Benfield12eae892014-06-07 15:42:56 +01001971
Cory Benfielde46fa842015-04-13 16:50:49 -04001972 server_context = Context(TLSv1_METHOD)
1973 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01001974
Cory Benfielde46fa842015-04-13 16:50:49 -04001975 # Necessary to actually accept the connection
1976 server_context.use_privatekey(
1977 load_privatekey(FILETYPE_PEM, server_key_pem))
1978 server_context.use_certificate(
1979 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield12eae892014-06-07 15:42:56 +01001980
Cory Benfielde46fa842015-04-13 16:50:49 -04001981 # Do a little connection to trigger the logic
1982 server = Connection(server_context, None)
1983 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001984
Cory Benfielde46fa842015-04-13 16:50:49 -04001985 # Set the ALPN protocols on the client connection.
1986 client = Connection(client_context, None)
1987 client.set_alpn_protos([b'http/1.1', b'spdy/2'])
1988 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001989
Alex Chanec1e32d2016-11-10 14:11:45 +00001990 interact_in_memory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001991
Alex Chanec1e32d2016-11-10 14:11:45 +00001992 assert select_args == [(server, [b'http/1.1', b'spdy/2'])]
Cory Benfield12eae892014-06-07 15:42:56 +01001993
Alex Chanec1e32d2016-11-10 14:11:45 +00001994 assert server.get_alpn_proto_negotiated() == b'spdy/2'
1995 assert client.get_alpn_proto_negotiated() == b'spdy/2'
Cory Benfield12eae892014-06-07 15:42:56 +01001996
Cory Benfielde46fa842015-04-13 16:50:49 -04001997 def test_alpn_server_fail(self):
1998 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04001999 When clients and servers cannot agree on what protocol to use next
2000 the TLS connection does not get established.
Cory Benfielde46fa842015-04-13 16:50:49 -04002001 """
2002 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002003
Cory Benfielde46fa842015-04-13 16:50:49 -04002004 def select(conn, options):
2005 select_args.append((conn, options))
2006 return b''
Cory Benfield12eae892014-06-07 15:42:56 +01002007
Cory Benfielde46fa842015-04-13 16:50:49 -04002008 client_context = Context(TLSv1_METHOD)
2009 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfield12eae892014-06-07 15:42:56 +01002010
Cory Benfielde46fa842015-04-13 16:50:49 -04002011 server_context = Context(TLSv1_METHOD)
2012 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01002013
Cory Benfielde46fa842015-04-13 16:50:49 -04002014 # Necessary to actually accept the connection
2015 server_context.use_privatekey(
2016 load_privatekey(FILETYPE_PEM, server_key_pem))
2017 server_context.use_certificate(
2018 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield12eae892014-06-07 15:42:56 +01002019
Cory Benfielde46fa842015-04-13 16:50:49 -04002020 # Do a little connection to trigger the logic
2021 server = Connection(server_context, None)
2022 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01002023
Cory Benfielde46fa842015-04-13 16:50:49 -04002024 client = Connection(client_context, None)
2025 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01002026
Cory Benfielde46fa842015-04-13 16:50:49 -04002027 # If the client doesn't return anything, the connection will fail.
Alex Chanec1e32d2016-11-10 14:11:45 +00002028 with pytest.raises(Error):
2029 interact_in_memory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01002030
Alex Chanec1e32d2016-11-10 14:11:45 +00002031 assert select_args == [(server, [b'http/1.1', b'spdy/2'])]
Cory Benfield12eae892014-06-07 15:42:56 +01002032
Cory Benfielde46fa842015-04-13 16:50:49 -04002033 def test_alpn_no_server(self):
2034 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04002035 When clients and servers cannot agree on what protocol to use next
2036 because the server doesn't offer ALPN, no protocol is negotiated.
Cory Benfielde46fa842015-04-13 16:50:49 -04002037 """
2038 client_context = Context(TLSv1_METHOD)
2039 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfielde3d57152015-04-11 17:57:35 -04002040
Cory Benfielde46fa842015-04-13 16:50:49 -04002041 server_context = Context(TLSv1_METHOD)
Cory Benfielde3d57152015-04-11 17:57:35 -04002042
Cory Benfielde46fa842015-04-13 16:50:49 -04002043 # Necessary to actually accept the connection
2044 server_context.use_privatekey(
2045 load_privatekey(FILETYPE_PEM, server_key_pem))
2046 server_context.use_certificate(
2047 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfielde3d57152015-04-11 17:57:35 -04002048
Cory Benfielde46fa842015-04-13 16:50:49 -04002049 # Do a little connection to trigger the logic
2050 server = Connection(server_context, None)
2051 server.set_accept_state()
Cory Benfielde3d57152015-04-11 17:57:35 -04002052
Cory Benfielde46fa842015-04-13 16:50:49 -04002053 client = Connection(client_context, None)
2054 client.set_connect_state()
Cory Benfielde3d57152015-04-11 17:57:35 -04002055
Cory Benfielde46fa842015-04-13 16:50:49 -04002056 # Do the dance.
Alex Chanec1e32d2016-11-10 14:11:45 +00002057 interact_in_memory(server, client)
Cory Benfielde3d57152015-04-11 17:57:35 -04002058
Alex Chanec1e32d2016-11-10 14:11:45 +00002059 assert client.get_alpn_proto_negotiated() == b''
Cory Benfielde3d57152015-04-11 17:57:35 -04002060
Cory Benfielde46fa842015-04-13 16:50:49 -04002061 def test_alpn_callback_exception(self):
2062 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04002063 We can handle exceptions in the ALPN select callback.
Cory Benfielde46fa842015-04-13 16:50:49 -04002064 """
2065 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002066
Cory Benfielde46fa842015-04-13 16:50:49 -04002067 def select(conn, options):
2068 select_args.append((conn, options))
Cory Benfieldef401452015-04-13 18:17:36 -04002069 raise TypeError()
Cory Benfieldf1177e72015-04-12 09:11:49 -04002070
Cory Benfielde46fa842015-04-13 16:50:49 -04002071 client_context = Context(TLSv1_METHOD)
2072 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfieldf1177e72015-04-12 09:11:49 -04002073
Cory Benfielde46fa842015-04-13 16:50:49 -04002074 server_context = Context(TLSv1_METHOD)
2075 server_context.set_alpn_select_callback(select)
Cory Benfieldf1177e72015-04-12 09:11:49 -04002076
Cory Benfielde46fa842015-04-13 16:50:49 -04002077 # Necessary to actually accept the connection
2078 server_context.use_privatekey(
2079 load_privatekey(FILETYPE_PEM, server_key_pem))
2080 server_context.use_certificate(
2081 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfieldf1177e72015-04-12 09:11:49 -04002082
Cory Benfielde46fa842015-04-13 16:50:49 -04002083 # Do a little connection to trigger the logic
2084 server = Connection(server_context, None)
2085 server.set_accept_state()
Cory Benfieldf1177e72015-04-12 09:11:49 -04002086
Cory Benfielde46fa842015-04-13 16:50:49 -04002087 client = Connection(client_context, None)
2088 client.set_connect_state()
Cory Benfieldf1177e72015-04-12 09:11:49 -04002089
Alex Chanec1e32d2016-11-10 14:11:45 +00002090 with pytest.raises(TypeError):
2091 interact_in_memory(server, client)
2092 assert select_args == [(server, [b'http/1.1', b'spdy/2'])]
Cory Benfieldf1177e72015-04-12 09:11:49 -04002093
Cory Benfield0f7b04c2015-04-13 17:51:12 -04002094 else:
2095 # No ALPN.
2096 def test_alpn_not_implemented(self):
Cory Benfieldef401452015-04-13 18:17:36 -04002097 """
2098 If ALPN is not in OpenSSL, we should raise NotImplementedError.
2099 """
Cory Benfield0f7b04c2015-04-13 17:51:12 -04002100 # Test the context methods first.
2101 context = Context(TLSv1_METHOD)
Alex Chanec1e32d2016-11-10 14:11:45 +00002102 with pytest.raises(NotImplementedError):
2103 context.set_alpn_protos(None)
2104 with pytest.raises(NotImplementedError):
2105 context.set_alpn_select_callback(None)
Cory Benfield0f7b04c2015-04-13 17:51:12 -04002106
2107 # Now test a connection.
2108 conn = Connection(context)
Alex Chanec1e32d2016-11-10 14:11:45 +00002109 with pytest.raises(NotImplementedError):
2110 conn.set_alpn_protos(None)
Cory Benfield0f7b04c2015-04-13 17:51:12 -04002111
Cory Benfieldf1177e72015-04-12 09:11:49 -04002112
Alex Chanec1e32d2016-11-10 14:11:45 +00002113class TestSession(object):
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05002114 """
2115 Unit tests for :py:obj:`OpenSSL.SSL.Session`.
2116 """
2117 def test_construction(self):
2118 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002119 :py:class:`Session` can be constructed with no arguments, creating
2120 a new instance of that type.
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05002121 """
2122 new_session = Session()
Alex Chanec1e32d2016-11-10 14:11:45 +00002123 assert isinstance(new_session, Session)
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05002124
2125
Alex Chan1c0cb662017-01-30 07:13:30 +00002126class TestConnection(object):
Rick Deane15b1472009-07-09 15:53:42 -05002127 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002128 Unit tests for `OpenSSL.SSL.Connection`.
Rick Deane15b1472009-07-09 15:53:42 -05002129 """
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04002130 # XXX get_peer_certificate -> None
2131 # XXX sock_shutdown
2132 # XXX master_key -> TypeError
2133 # XXX server_random -> TypeError
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04002134 # XXX connect -> TypeError
2135 # XXX connect_ex -> TypeError
2136 # XXX set_connect_state -> TypeError
2137 # XXX set_accept_state -> TypeError
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04002138 # XXX do_handshake -> TypeError
2139 # XXX bio_read -> TypeError
2140 # XXX recv -> TypeError
2141 # XXX send -> TypeError
2142 # XXX bio_write -> TypeError
2143
Rick Deane15b1472009-07-09 15:53:42 -05002144 def test_type(self):
2145 """
Alex Gaynor01f90a12019-02-07 09:14:48 -05002146 `Connection` can be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -05002147 """
2148 ctx = Context(TLSv1_METHOD)
Alex Chan1c0cb662017-01-30 07:13:30 +00002149 assert is_consistent_type(Connection, 'Connection', ctx, None)
Rick Deane15b1472009-07-09 15:53:42 -05002150
Alex Chanfb078d82017-04-20 11:16:15 +01002151 @pytest.mark.parametrize('bad_context', [object(), 'context', None, 1])
2152 def test_wrong_args(self, bad_context):
2153 """
2154 `Connection.__init__` raises `TypeError` if called with a non-`Context`
2155 instance argument.
2156 """
2157 with pytest.raises(TypeError):
2158 Connection(bad_context)
2159
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002160 def test_get_context(self):
2161 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002162 `Connection.get_context` returns the `Context` instance used to
2163 construct the `Connection` instance.
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002164 """
2165 context = Context(TLSv1_METHOD)
2166 connection = Connection(context, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002167 assert connection.get_context() is context
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002168
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002169 def test_set_context_wrong_args(self):
2170 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002171 `Connection.set_context` raises `TypeError` if called with a
Alex Chanfb078d82017-04-20 11:16:15 +01002172 non-`Context` instance argument.
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002173 """
2174 ctx = Context(TLSv1_METHOD)
2175 connection = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002176 with pytest.raises(TypeError):
2177 connection.set_context(object())
2178 with pytest.raises(TypeError):
2179 connection.set_context("hello")
2180 with pytest.raises(TypeError):
2181 connection.set_context(1)
2182 assert ctx is connection.get_context()
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002183
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002184 def test_set_context(self):
2185 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002186 `Connection.set_context` specifies a new `Context` instance to be
2187 used for the connection.
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002188 """
2189 original = Context(SSLv23_METHOD)
2190 replacement = Context(TLSv1_METHOD)
2191 connection = Connection(original, None)
2192 connection.set_context(replacement)
Alex Chan1c0cb662017-01-30 07:13:30 +00002193 assert replacement is connection.get_context()
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002194 # Lose our references to the contexts, just in case the Connection
2195 # isn't properly managing its own contributions to their reference
2196 # counts.
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002197 del original, replacement
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002198 collect()
2199
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002200 def test_set_tlsext_host_name_wrong_args(self):
2201 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002202 If `Connection.set_tlsext_host_name` is called with a non-byte string
2203 argument or a byte string with an embedded NUL, `TypeError` is raised.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002204 """
2205 conn = Connection(Context(TLSv1_METHOD), None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002206 with pytest.raises(TypeError):
2207 conn.set_tlsext_host_name(object())
2208 with pytest.raises(TypeError):
2209 conn.set_tlsext_host_name(b"with\0null")
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002210
Abraham Martinc5484ba2015-03-25 15:33:05 +00002211 if PY3:
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002212 # On Python 3.x, don't accidentally implicitly convert from text.
Alex Chan1c0cb662017-01-30 07:13:30 +00002213 with pytest.raises(TypeError):
2214 conn.set_tlsext_host_name(b"example.com".decode("ascii"))
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04002215
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002216 def test_pending(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002217 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002218 `Connection.pending` returns the number of bytes available for
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002219 immediate read.
2220 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002221 connection = Connection(Context(TLSv1_METHOD), None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002222 assert connection.pending() == 0
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002223
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002224 def test_peek(self):
2225 """
Hynek Schlawack3bcf3152017-02-18 08:25:34 +01002226 `Connection.recv` peeks into the connection if `socket.MSG_PEEK` is
2227 passed.
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002228 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002229 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002230 server.send(b'xy')
Alex Chan1c0cb662017-01-30 07:13:30 +00002231 assert client.recv(2, MSG_PEEK) == b'xy'
2232 assert client.recv(2, MSG_PEEK) == b'xy'
2233 assert client.recv(2) == b'xy'
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002234
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002235 def test_connect_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002236 """
Hynek Schlawack3bcf3152017-02-18 08:25:34 +01002237 `Connection.connect` raises `TypeError` if called with a non-address
2238 argument.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002239 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002240 connection = Connection(Context(TLSv1_METHOD), socket())
Alex Chan1c0cb662017-01-30 07:13:30 +00002241 with pytest.raises(TypeError):
2242 connection.connect(None)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002243
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002244 def test_connect_refused(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002245 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002246 `Connection.connect` raises `socket.error` if the underlying socket
2247 connect method raises it.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002248 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002249 client = socket()
2250 context = Context(TLSv1_METHOD)
2251 clientSSL = Connection(context, client)
Alex Gaynor122717b2015-09-05 14:14:18 -04002252 # pytest.raises here doesn't work because of a bug in py.test on Python
2253 # 2.6: https://github.com/pytest-dev/pytest/issues/988
Alex Gaynore69c2782015-09-05 14:07:48 -04002254 try:
Alex Gaynor1aabb2e2015-09-05 13:35:18 -04002255 clientSSL.connect(("127.0.0.1", 1))
Alex Gaynore69c2782015-09-05 14:07:48 -04002256 except error as e:
Alex Gaynor20a4c082015-09-05 14:24:15 -04002257 exc = e
2258 assert exc.args[0] == ECONNREFUSED
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002259
2260 def test_connect(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002261 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002262 `Connection.connect` establishes a connection to the specified address.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002263 """
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002264 port = socket()
2265 port.bind(('', 0))
2266 port.listen(3)
2267
2268 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002269 clientSSL.connect(('127.0.0.1', port.getsockname()[1]))
2270 # XXX An assertion? Or something?
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002271
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002272 @pytest.mark.skipif(
2273 platform == "darwin",
2274 reason="connect_ex sometimes causes a kernel panic on OS X 10.6.4"
2275 )
2276 def test_connect_ex(self):
2277 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002278 If there is a connection error, `Connection.connect_ex` returns the
2279 errno instead of raising an exception.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002280 """
2281 port = socket()
2282 port.bind(('', 0))
2283 port.listen(3)
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002284
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002285 clientSSL = Connection(Context(TLSv1_METHOD), socket())
2286 clientSSL.setblocking(False)
2287 result = clientSSL.connect_ex(port.getsockname())
2288 expected = (EINPROGRESS, EWOULDBLOCK)
Alex Chan1c0cb662017-01-30 07:13:30 +00002289 assert result in expected
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002290
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002291 def test_accept(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002292 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002293 `Connection.accept` accepts a pending connection attempt and returns a
2294 tuple of a new `Connection` (the accepted client) and the address the
2295 connection originated from.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002296 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002297 ctx = Context(TLSv1_METHOD)
2298 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2299 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002300 port = socket()
2301 portSSL = Connection(ctx, port)
2302 portSSL.bind(('', 0))
2303 portSSL.listen(3)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002304
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002305 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002306
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002307 # Calling portSSL.getsockname() here to get the server IP address
2308 # sounds great, but frequently fails on Windows.
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002309 clientSSL.connect(('127.0.0.1', portSSL.getsockname()[1]))
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002310
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002311 serverSSL, address = portSSL.accept()
2312
Alex Chan1c0cb662017-01-30 07:13:30 +00002313 assert isinstance(serverSSL, Connection)
2314 assert serverSSL.get_context() is ctx
2315 assert address == clientSSL.getsockname()
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002316
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002317 def test_shutdown_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002318 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002319 `Connection.set_shutdown` raises `TypeError` if called with arguments
2320 other than integers.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002321 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002322 connection = Connection(Context(TLSv1_METHOD), None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002323 with pytest.raises(TypeError):
2324 connection.set_shutdown(None)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002325
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002326 def test_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002327 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002328 `Connection.shutdown` performs an SSL-level connection shutdown.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002329 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002330 server, client = loopback()
2331 assert not server.shutdown()
2332 assert server.get_shutdown() == SENT_SHUTDOWN
2333 with pytest.raises(ZeroReturnError):
2334 client.recv(1024)
2335 assert client.get_shutdown() == RECEIVED_SHUTDOWN
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04002336 client.shutdown()
Alex Chan1c0cb662017-01-30 07:13:30 +00002337 assert client.get_shutdown() == (SENT_SHUTDOWN | RECEIVED_SHUTDOWN)
2338 with pytest.raises(ZeroReturnError):
2339 server.recv(1024)
2340 assert server.get_shutdown() == (SENT_SHUTDOWN | RECEIVED_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002341
Paul Aurichc85e0862015-01-08 08:34:33 -08002342 def test_shutdown_closed(self):
2343 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002344 If the underlying socket is closed, `Connection.shutdown` propagates
2345 the write error from the low level write call.
Paul Aurichc85e0862015-01-08 08:34:33 -08002346 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002347 server, client = loopback()
Paul Aurichc85e0862015-01-08 08:34:33 -08002348 server.sock_shutdown(2)
Alex Chan1c0cb662017-01-30 07:13:30 +00002349 with pytest.raises(SysCallError) as exc:
2350 server.shutdown()
Alex Chanfb078d82017-04-20 11:16:15 +01002351 if platform == "win32":
2352 assert exc.value.args[0] == ESHUTDOWN
2353 else:
2354 assert exc.value.args[0] == EPIPE
Paul Aurichc85e0862015-01-08 08:34:33 -08002355
Glyph89389472015-04-14 17:29:26 -04002356 def test_shutdown_truncated(self):
Glyph6064ec32015-04-14 16:38:22 -04002357 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002358 If the underlying connection is truncated, `Connection.shutdown`
2359 raises an `Error`.
Glyph6064ec32015-04-14 16:38:22 -04002360 """
Glyph89389472015-04-14 17:29:26 -04002361 server_ctx = Context(TLSv1_METHOD)
2362 client_ctx = Context(TLSv1_METHOD)
2363 server_ctx.use_privatekey(
2364 load_privatekey(FILETYPE_PEM, server_key_pem))
2365 server_ctx.use_certificate(
2366 load_certificate(FILETYPE_PEM, server_cert_pem))
2367 server = Connection(server_ctx, None)
2368 client = Connection(client_ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002369 handshake_in_memory(client, server)
2370 assert not server.shutdown()
2371 with pytest.raises(WantReadError):
2372 server.shutdown()
Glyph89389472015-04-14 17:29:26 -04002373 server.bio_shutdown()
Alex Chan1c0cb662017-01-30 07:13:30 +00002374 with pytest.raises(Error):
2375 server.shutdown()
Glyph6064ec32015-04-14 16:38:22 -04002376
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002377 def test_set_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002378 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002379 `Connection.set_shutdown` sets the state of the SSL connection
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002380 shutdown process.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002381 """
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002382 connection = Connection(Context(TLSv1_METHOD), socket())
2383 connection.set_shutdown(RECEIVED_SHUTDOWN)
Alex Chan1c0cb662017-01-30 07:13:30 +00002384 assert connection.get_shutdown() == RECEIVED_SHUTDOWN
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002385
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002386 @skip_if_py3
2387 def test_set_shutdown_long(self):
2388 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002389 On Python 2 `Connection.set_shutdown` accepts an argument
2390 of type `long` as well as `int`.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002391 """
2392 connection = Connection(Context(TLSv1_METHOD), socket())
2393 connection.set_shutdown(long(RECEIVED_SHUTDOWN))
Alex Chan1c0cb662017-01-30 07:13:30 +00002394 assert connection.get_shutdown() == RECEIVED_SHUTDOWN
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -05002395
kjavaf248592015-09-07 12:14:01 +01002396 def test_state_string(self):
2397 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002398 `Connection.state_string` verbosely describes the current state of
2399 the `Connection`.
kjavaf248592015-09-07 12:14:01 +01002400 """
Hynek Schlawackb0274ce2015-10-16 19:56:26 +02002401 server, client = socket_pair()
Alex Chan1c0cb662017-01-30 07:13:30 +00002402 server = loopback_server_factory(server)
2403 client = loopback_client_factory(client)
kjavaf248592015-09-07 12:14:01 +01002404
Alex Gaynor5af32d02016-09-24 01:52:21 -04002405 assert server.get_state_string() in [
2406 b"before/accept initialization", b"before SSL initialization"
2407 ]
2408 assert client.get_state_string() in [
2409 b"before/connect initialization", b"before SSL initialization"
2410 ]
kjavaf248592015-09-07 12:14:01 +01002411
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002412 def test_app_data(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002413 """
2414 Any object can be set as app data by passing it to
Alex Chan1c0cb662017-01-30 07:13:30 +00002415 `Connection.set_app_data` and later retrieved with
2416 `Connection.get_app_data`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002417 """
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002418 conn = Connection(Context(TLSv1_METHOD), None)
Todd Chapman4f73e4f2015-08-27 11:26:43 -04002419 assert None is conn.get_app_data()
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002420 app_data = object()
2421 conn.set_app_data(app_data)
Todd Chapman4f73e4f2015-08-27 11:26:43 -04002422 assert conn.get_app_data() is app_data
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002423
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002424 def test_makefile(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002425 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002426 `Connection.makefile` is not implemented and calling that
2427 method raises `NotImplementedError`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002428 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002429 conn = Connection(Context(TLSv1_METHOD), None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002430 with pytest.raises(NotImplementedError):
2431 conn.makefile()
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002432
Jeremy Lainé460a19d2018-05-16 19:44:19 +02002433 def test_get_certificate(self):
2434 """
2435 `Connection.get_certificate` returns the local certificate.
2436 """
2437 chain = _create_certificate_chain()
2438 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
2439
2440 context = Context(TLSv1_METHOD)
2441 context.use_certificate(scert)
2442 client = Connection(context, None)
2443 cert = client.get_certificate()
2444 assert cert is not None
2445 assert "Server Certificate" == cert.get_subject().CN
2446
2447 def test_get_certificate_none(self):
2448 """
2449 `Connection.get_certificate` returns the local certificate.
2450
2451 If there is no certificate, it returns None.
2452 """
2453 context = Context(TLSv1_METHOD)
2454 client = Connection(context, None)
2455 cert = client.get_certificate()
2456 assert cert is None
2457
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002458 def test_get_peer_cert_chain(self):
2459 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002460 `Connection.get_peer_cert_chain` returns a list of certificates
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002461 which the connected server returned for the certification verification.
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002462 """
2463 chain = _create_certificate_chain()
2464 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
2465
2466 serverContext = Context(TLSv1_METHOD)
2467 serverContext.use_privatekey(skey)
2468 serverContext.use_certificate(scert)
2469 serverContext.add_extra_chain_cert(icert)
2470 serverContext.add_extra_chain_cert(cacert)
2471 server = Connection(serverContext, None)
2472 server.set_accept_state()
2473
2474 # Create the client
2475 clientContext = Context(TLSv1_METHOD)
2476 clientContext.set_verify(VERIFY_NONE, verify_cb)
2477 client = Connection(clientContext, None)
2478 client.set_connect_state()
2479
Alex Chan1c0cb662017-01-30 07:13:30 +00002480 interact_in_memory(client, server)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002481
2482 chain = client.get_peer_cert_chain()
Alex Chan1c0cb662017-01-30 07:13:30 +00002483 assert len(chain) == 3
2484 assert "Server Certificate" == chain[0].get_subject().CN
2485 assert "Intermediate Certificate" == chain[1].get_subject().CN
2486 assert "Authority Certificate" == chain[2].get_subject().CN
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002487
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002488 def test_get_peer_cert_chain_none(self):
2489 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002490 `Connection.get_peer_cert_chain` returns `None` if the peer sends
2491 no certificate chain.
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002492 """
2493 ctx = Context(TLSv1_METHOD)
2494 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2495 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
2496 server = Connection(ctx, None)
2497 server.set_accept_state()
2498 client = Connection(Context(TLSv1_METHOD), None)
2499 client.set_connect_state()
Alex Chan1c0cb662017-01-30 07:13:30 +00002500 interact_in_memory(client, server)
2501 assert None is server.get_peer_cert_chain()
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002502
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002503 def test_get_session_unconnected(self):
2504 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002505 `Connection.get_session` returns `None` when used with an object
2506 which has not been connected.
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002507 """
2508 ctx = Context(TLSv1_METHOD)
2509 server = Connection(ctx, None)
2510 session = server.get_session()
Alex Chan1c0cb662017-01-30 07:13:30 +00002511 assert None is session
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002512
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002513 def test_server_get_session(self):
2514 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002515 On the server side of a connection, `Connection.get_session` returns a
2516 `Session` instance representing the SSL session for that connection.
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002517 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002518 server, client = loopback()
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002519 session = server.get_session()
Alex Chan1c0cb662017-01-30 07:13:30 +00002520 assert isinstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002521
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002522 def test_client_get_session(self):
2523 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002524 On the client side of a connection, `Connection.get_session`
2525 returns a `Session` instance representing the SSL session for
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002526 that connection.
2527 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002528 server, client = loopback()
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002529 session = client.get_session()
Alex Chan1c0cb662017-01-30 07:13:30 +00002530 assert isinstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002531
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002532 def test_set_session_wrong_args(self):
2533 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002534 `Connection.set_session` raises `TypeError` if called with an object
2535 that is not an instance of `Session`.
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002536 """
2537 ctx = Context(TLSv1_METHOD)
2538 connection = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002539 with pytest.raises(TypeError):
2540 connection.set_session(123)
2541 with pytest.raises(TypeError):
2542 connection.set_session("hello")
2543 with pytest.raises(TypeError):
2544 connection.set_session(object())
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002545
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002546 def test_client_set_session(self):
2547 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002548 `Connection.set_session`, when used prior to a connection being
2549 established, accepts a `Session` instance and causes an attempt to
2550 re-use the session it represents when the SSL handshake is performed.
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002551 """
2552 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2553 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
Paul Kehrer7d5a3bf2019-01-21 12:24:02 -06002554 ctx = Context(TLSv1_2_METHOD)
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002555 ctx.use_privatekey(key)
2556 ctx.use_certificate(cert)
2557 ctx.set_session_id("unity-test")
2558
2559 def makeServer(socket):
2560 server = Connection(ctx, socket)
2561 server.set_accept_state()
2562 return server
2563
Alex Chan1c0cb662017-01-30 07:13:30 +00002564 originalServer, originalClient = loopback(
2565 server_factory=makeServer)
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002566 originalSession = originalClient.get_session()
2567
2568 def makeClient(socket):
Alex Chan1c0cb662017-01-30 07:13:30 +00002569 client = loopback_client_factory(socket)
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002570 client.set_session(originalSession)
2571 return client
Alex Chan1c0cb662017-01-30 07:13:30 +00002572 resumedServer, resumedClient = loopback(
2573 server_factory=makeServer,
2574 client_factory=makeClient)
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002575
2576 # This is a proxy: in general, we have no access to any unique
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002577 # identifier for the session (new enough versions of OpenSSL expose
2578 # a hash which could be usable, but "new enough" is very, very new).
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002579 # Instead, exploit the fact that the master key is re-used if the
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002580 # session is re-used. As long as the master key for the two
2581 # connections is the same, the session was re-used!
Alex Chan1c0cb662017-01-30 07:13:30 +00002582 assert originalServer.master_key() == resumedServer.master_key()
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002583
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002584 def test_set_session_wrong_method(self):
2585 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002586 If `Connection.set_session` is passed a `Session` instance associated
2587 with a context using a different SSL method than the `Connection`
2588 is using, a `OpenSSL.SSL.Error` is raised.
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002589 """
Alex Gaynor5af32d02016-09-24 01:52:21 -04002590 # Make this work on both OpenSSL 1.0.0, which doesn't support TLSv1.2
2591 # and also on OpenSSL 1.1.0 which doesn't support SSLv3. (SSL_ST_INIT
2592 # is a way to check for 1.1.0)
Alex Gaynoraa32e712017-06-29 20:56:12 -07002593 if SSL_ST_INIT is None:
2594 v1 = TLSv1_2_METHOD
2595 v2 = TLSv1_METHOD
2596 elif hasattr(_lib, "SSLv3_method"):
Alex Gaynor5af32d02016-09-24 01:52:21 -04002597 v1 = TLSv1_METHOD
2598 v2 = SSLv3_METHOD
2599 else:
Alex Gaynoraa32e712017-06-29 20:56:12 -07002600 pytest.skip("Test requires either OpenSSL 1.1.0 or SSLv3")
Alex Gaynor5af32d02016-09-24 01:52:21 -04002601
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002602 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2603 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
Alex Gaynor5af32d02016-09-24 01:52:21 -04002604 ctx = Context(v1)
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002605 ctx.use_privatekey(key)
2606 ctx.use_certificate(cert)
2607 ctx.set_session_id("unity-test")
2608
2609 def makeServer(socket):
2610 server = Connection(ctx, socket)
2611 server.set_accept_state()
2612 return server
2613
Alex Gaynor5af32d02016-09-24 01:52:21 -04002614 def makeOriginalClient(socket):
2615 client = Connection(Context(v1), socket)
2616 client.set_connect_state()
2617 return client
2618
Alex Chan1c0cb662017-01-30 07:13:30 +00002619 originalServer, originalClient = loopback(
2620 server_factory=makeServer, client_factory=makeOriginalClient)
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002621 originalSession = originalClient.get_session()
2622
2623 def makeClient(socket):
2624 # Intentionally use a different, incompatible method here.
Alex Gaynor5af32d02016-09-24 01:52:21 -04002625 client = Connection(Context(v2), socket)
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002626 client.set_connect_state()
2627 client.set_session(originalSession)
2628 return client
2629
Alex Chan1c0cb662017-01-30 07:13:30 +00002630 with pytest.raises(Error):
2631 loopback(client_factory=makeClient, server_factory=makeServer)
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002632
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002633 def test_wantWriteError(self):
2634 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002635 `Connection` methods which generate output raise
2636 `OpenSSL.SSL.WantWriteError` if writing to the connection's BIO
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002637 fail indicating a should-write state.
2638 """
2639 client_socket, server_socket = socket_pair()
2640 # Fill up the client's send buffer so Connection won't be able to write
Jean-Paul Calderonebbff8b92014-03-22 14:20:30 -04002641 # anything. Only write a single byte at a time so we can be sure we
2642 # completely fill the buffer. Even though the socket API is allowed to
2643 # signal a short write via its return value it seems this doesn't
2644 # always happen on all platforms (FreeBSD and OS X particular) for the
2645 # very last bit of available buffer space.
2646 msg = b"x"
caternb2777a42018-08-09 15:38:13 -04002647 for i in range(1024 * 1024 * 64):
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002648 try:
2649 client_socket.send(msg)
2650 except error as e:
2651 if e.errno == EWOULDBLOCK:
2652 break
2653 raise
2654 else:
Alex Chan1c0cb662017-01-30 07:13:30 +00002655 pytest.fail(
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002656 "Failed to fill socket buffer, cannot test BIO want write")
2657
2658 ctx = Context(TLSv1_METHOD)
2659 conn = Connection(ctx, client_socket)
2660 # Client's speak first, so make it an SSL client
2661 conn.set_connect_state()
Alex Chan1c0cb662017-01-30 07:13:30 +00002662 with pytest.raises(WantWriteError):
2663 conn.do_handshake()
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002664
2665 # XXX want_read
2666
Fedor Brunner416f4a12014-03-28 13:18:38 +01002667 def test_get_finished_before_connect(self):
Fedor Brunner5747b932014-03-05 14:22:34 +01002668 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002669 `Connection.get_finished` returns `None` before TLS handshake
2670 is completed.
Fedor Brunner5747b932014-03-05 14:22:34 +01002671 """
Fedor Brunner5747b932014-03-05 14:22:34 +01002672 ctx = Context(TLSv1_METHOD)
2673 connection = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002674 assert connection.get_finished() is None
Fedor Brunner416f4a12014-03-28 13:18:38 +01002675
2676 def test_get_peer_finished_before_connect(self):
2677 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002678 `Connection.get_peer_finished` returns `None` before TLS handshake
2679 is completed.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002680 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002681 ctx = Context(TLSv1_METHOD)
2682 connection = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002683 assert connection.get_peer_finished() is None
Fedor Brunner5747b932014-03-05 14:22:34 +01002684
Fedor Brunner416f4a12014-03-28 13:18:38 +01002685 def test_get_finished(self):
2686 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002687 `Connection.get_finished` method returns the TLS Finished message send
2688 from client, or server. Finished messages are send during
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002689 TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002690 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002691 server, client = loopback()
Fedor Brunner416f4a12014-03-28 13:18:38 +01002692
Alex Chan1c0cb662017-01-30 07:13:30 +00002693 assert server.get_finished() is not None
2694 assert len(server.get_finished()) > 0
Fedor Brunner416f4a12014-03-28 13:18:38 +01002695
2696 def test_get_peer_finished(self):
2697 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002698 `Connection.get_peer_finished` method returns the TLS Finished
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002699 message received from client, or server. Finished messages are send
2700 during TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002701 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002702 server, client = loopback()
Fedor Brunner416f4a12014-03-28 13:18:38 +01002703
Alex Chan1c0cb662017-01-30 07:13:30 +00002704 assert server.get_peer_finished() is not None
2705 assert len(server.get_peer_finished()) > 0
Fedor Brunner5747b932014-03-05 14:22:34 +01002706
Fedor Brunner416f4a12014-03-28 13:18:38 +01002707 def test_tls_finished_message_symmetry(self):
2708 """
Hynek Schlawackdddd1112015-09-05 21:12:30 +02002709 The TLS Finished message send by server must be the TLS Finished
2710 message received by client.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002711
Hynek Schlawackdddd1112015-09-05 21:12:30 +02002712 The TLS Finished message send by client must be the TLS Finished
2713 message received by server.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002714 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002715 server, client = loopback()
Fedor Brunner416f4a12014-03-28 13:18:38 +01002716
Alex Chan1c0cb662017-01-30 07:13:30 +00002717 assert server.get_finished() == client.get_peer_finished()
2718 assert client.get_finished() == server.get_peer_finished()
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002719
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002720 def test_get_cipher_name_before_connect(self):
2721 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002722 `Connection.get_cipher_name` returns `None` if no connection
2723 has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002724 """
2725 ctx = Context(TLSv1_METHOD)
2726 conn = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002727 assert conn.get_cipher_name() is None
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002728
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002729 def test_get_cipher_name(self):
2730 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002731 `Connection.get_cipher_name` returns a `unicode` string giving the
2732 name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002733 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002734 server, client = loopback()
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002735 server_cipher_name, client_cipher_name = \
2736 server.get_cipher_name(), client.get_cipher_name()
2737
Alex Chan1c0cb662017-01-30 07:13:30 +00002738 assert isinstance(server_cipher_name, text_type)
2739 assert isinstance(client_cipher_name, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002740
Alex Chan1c0cb662017-01-30 07:13:30 +00002741 assert server_cipher_name == client_cipher_name
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002742
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002743 def test_get_cipher_version_before_connect(self):
2744 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002745 `Connection.get_cipher_version` returns `None` if no connection
2746 has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002747 """
2748 ctx = Context(TLSv1_METHOD)
2749 conn = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002750 assert conn.get_cipher_version() is None
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002751
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002752 def test_get_cipher_version(self):
2753 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002754 `Connection.get_cipher_version` returns a `unicode` string giving
2755 the protocol name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002756 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002757 server, client = loopback()
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002758 server_cipher_version, client_cipher_version = \
2759 server.get_cipher_version(), client.get_cipher_version()
2760
Alex Chan1c0cb662017-01-30 07:13:30 +00002761 assert isinstance(server_cipher_version, text_type)
2762 assert isinstance(client_cipher_version, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002763
Alex Chan1c0cb662017-01-30 07:13:30 +00002764 assert server_cipher_version == client_cipher_version
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002765
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002766 def test_get_cipher_bits_before_connect(self):
2767 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002768 `Connection.get_cipher_bits` returns `None` if no connection has
2769 been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002770 """
2771 ctx = Context(TLSv1_METHOD)
2772 conn = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002773 assert conn.get_cipher_bits() is None
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002774
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002775 def test_get_cipher_bits(self):
2776 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002777 `Connection.get_cipher_bits` returns the number of secret bits
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002778 of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002779 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002780 server, client = loopback()
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002781 server_cipher_bits, client_cipher_bits = \
2782 server.get_cipher_bits(), client.get_cipher_bits()
2783
Alex Chan1c0cb662017-01-30 07:13:30 +00002784 assert isinstance(server_cipher_bits, int)
2785 assert isinstance(client_cipher_bits, int)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002786
Alex Chan1c0cb662017-01-30 07:13:30 +00002787 assert server_cipher_bits == client_cipher_bits
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002788
Jim Shaverabff1882015-05-27 09:15:55 -04002789 def test_get_protocol_version_name(self):
2790 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002791 `Connection.get_protocol_version_name()` returns a string giving the
2792 protocol version of the current connection.
Jim Shaverabff1882015-05-27 09:15:55 -04002793 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002794 server, client = loopback()
Jim Shaverabff1882015-05-27 09:15:55 -04002795 client_protocol_version_name = client.get_protocol_version_name()
2796 server_protocol_version_name = server.get_protocol_version_name()
2797
Alex Chan1c0cb662017-01-30 07:13:30 +00002798 assert isinstance(server_protocol_version_name, text_type)
2799 assert isinstance(client_protocol_version_name, text_type)
Jim Shaverabff1882015-05-27 09:15:55 -04002800
Alex Chan1c0cb662017-01-30 07:13:30 +00002801 assert server_protocol_version_name == client_protocol_version_name
Jim Shaverabff1882015-05-27 09:15:55 -04002802
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002803 def test_get_protocol_version(self):
2804 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002805 `Connection.get_protocol_version()` returns an integer
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002806 giving the protocol version of the current connection.
2807 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002808 server, client = loopback()
Jim Shaver85a4dff2015-04-27 17:42:46 -04002809 client_protocol_version = client.get_protocol_version()
2810 server_protocol_version = server.get_protocol_version()
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002811
Alex Chan1c0cb662017-01-30 07:13:30 +00002812 assert isinstance(server_protocol_version, int)
2813 assert isinstance(client_protocol_version, int)
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002814
Alex Chan1c0cb662017-01-30 07:13:30 +00002815 assert server_protocol_version == client_protocol_version
2816
2817 def test_wantReadError(self):
2818 """
2819 `Connection.bio_read` raises `OpenSSL.SSL.WantReadError` if there are
2820 no bytes available to be read from the BIO.
2821 """
2822 ctx = Context(TLSv1_METHOD)
2823 conn = Connection(ctx, None)
2824 with pytest.raises(WantReadError):
2825 conn.bio_read(1024)
2826
Alex Chanfb078d82017-04-20 11:16:15 +01002827 @pytest.mark.parametrize('bufsize', [1.0, None, object(), 'bufsize'])
2828 def test_bio_read_wrong_args(self, bufsize):
2829 """
2830 `Connection.bio_read` raises `TypeError` if passed a non-integer
2831 argument.
2832 """
2833 ctx = Context(TLSv1_METHOD)
2834 conn = Connection(ctx, None)
2835 with pytest.raises(TypeError):
2836 conn.bio_read(bufsize)
2837
Alex Chan1c0cb662017-01-30 07:13:30 +00002838 def test_buffer_size(self):
2839 """
2840 `Connection.bio_read` accepts an integer giving the maximum number
2841 of bytes to read and return.
2842 """
2843 ctx = Context(TLSv1_METHOD)
2844 conn = Connection(ctx, None)
2845 conn.set_connect_state()
2846 try:
2847 conn.do_handshake()
2848 except WantReadError:
2849 pass
2850 data = conn.bio_read(2)
2851 assert 2 == len(data)
2852
2853 @skip_if_py3
2854 def test_buffer_size_long(self):
2855 """
2856 On Python 2 `Connection.bio_read` accepts values of type `long` as
2857 well as `int`.
2858 """
2859 ctx = Context(TLSv1_METHOD)
2860 conn = Connection(ctx, None)
2861 conn.set_connect_state()
2862 try:
2863 conn.do_handshake()
2864 except WantReadError:
2865 pass
2866 data = conn.bio_read(long(2))
2867 assert 2 == len(data)
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002868
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002869
Alex Chanb7480992017-01-30 14:04:47 +00002870class TestConnectionGetCipherList(object):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002871 """
Alex Chanb7480992017-01-30 14:04:47 +00002872 Tests for `Connection.get_cipher_list`.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002873 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002874 def test_result(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002875 """
Alex Chanb7480992017-01-30 14:04:47 +00002876 `Connection.get_cipher_list` returns a list of `bytes` giving the
2877 names of the ciphers which might be used.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002878 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002879 connection = Connection(Context(TLSv1_METHOD), None)
2880 ciphers = connection.get_cipher_list()
Alex Chanb7480992017-01-30 14:04:47 +00002881 assert isinstance(ciphers, list)
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002882 for cipher in ciphers:
Alex Chanb7480992017-01-30 14:04:47 +00002883 assert isinstance(cipher, str)
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002884
2885
Maximilian Hils868dc3c2017-02-10 14:56:55 +01002886class VeryLarge(bytes):
2887 """
2888 Mock object so that we don't have to allocate 2**31 bytes
2889 """
2890 def __len__(self):
2891 return 2**31
2892
2893
Alex Chanb7480992017-01-30 14:04:47 +00002894class TestConnectionSend(object):
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002895 """
Alex Chanb7480992017-01-30 14:04:47 +00002896 Tests for `Connection.send`.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002897 """
2898 def test_wrong_args(self):
2899 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002900 When called with arguments other than string argument for its first
Alex Chanb7480992017-01-30 14:04:47 +00002901 parameter, `Connection.send` raises `TypeError`.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002902 """
2903 connection = Connection(Context(TLSv1_METHOD), None)
Alex Chanb7480992017-01-30 14:04:47 +00002904 with pytest.raises(TypeError):
2905 connection.send(object())
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002906
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002907 def test_short_bytes(self):
2908 """
Alex Chanb7480992017-01-30 14:04:47 +00002909 When passed a short byte string, `Connection.send` transmits all of it
2910 and returns the number of bytes sent.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002911 """
Alex Chanb7480992017-01-30 14:04:47 +00002912 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002913 count = server.send(b'xy')
Alex Chanb7480992017-01-30 14:04:47 +00002914 assert count == 2
2915 assert client.recv(2) == b'xy'
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002916
Abraham Martinef063482015-03-25 14:06:24 +00002917 def test_text(self):
2918 """
Alex Chanb7480992017-01-30 14:04:47 +00002919 When passed a text, `Connection.send` transmits all of it and
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002920 returns the number of bytes sent. It also raises a DeprecationWarning.
Abraham Martinef063482015-03-25 14:06:24 +00002921 """
Alex Chanb7480992017-01-30 14:04:47 +00002922 server, client = loopback()
2923 with pytest.warns(DeprecationWarning) as w:
Abraham Martinef063482015-03-25 14:06:24 +00002924 simplefilter("always")
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002925 count = server.send(b"xy".decode("ascii"))
Alex Chanb7480992017-01-30 14:04:47 +00002926 assert (
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002927 "{0} for buf is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002928 WARNING_TYPE_EXPECTED
Alex Chanb7480992017-01-30 14:04:47 +00002929 ) == str(w[-1].message))
2930 assert count == 2
2931 assert client.recv(2) == b'xy'
Abraham Martinef063482015-03-25 14:06:24 +00002932
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002933 def test_short_memoryview(self):
2934 """
2935 When passed a memoryview onto a small number of bytes,
Alex Chanb7480992017-01-30 14:04:47 +00002936 `Connection.send` transmits all of them and returns the number
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002937 of bytes sent.
2938 """
Alex Chanb7480992017-01-30 14:04:47 +00002939 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002940 count = server.send(memoryview(b'xy'))
Alex Chanb7480992017-01-30 14:04:47 +00002941 assert count == 2
2942 assert client.recv(2) == b'xy'
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002943
Hynek Schlawack8e94f1b2015-09-05 21:31:00 +02002944 @skip_if_py3
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002945 def test_short_buffer(self):
2946 """
2947 When passed a buffer containing a small number of bytes,
Alex Chanb7480992017-01-30 14:04:47 +00002948 `Connection.send` transmits all of them and returns the number
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002949 of bytes sent.
2950 """
Alex Chanb7480992017-01-30 14:04:47 +00002951 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002952 count = server.send(buffer(b'xy'))
Alex Chanb7480992017-01-30 14:04:47 +00002953 assert count == 2
2954 assert client.recv(2) == b'xy'
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02002955
Maximilian Hils868dc3c2017-02-10 14:56:55 +01002956 @pytest.mark.skipif(
2957 sys.maxsize < 2**31,
2958 reason="sys.maxsize < 2**31 - test requires 64 bit"
2959 )
2960 def test_buf_too_large(self):
2961 """
2962 When passed a buffer containing >= 2**31 bytes,
2963 `Connection.send` bails out as SSL_write only
2964 accepts an int for the buffer length.
2965 """
2966 connection = Connection(Context(TLSv1_METHOD), None)
2967 with pytest.raises(ValueError) as exc_info:
2968 connection.send(VeryLarge())
2969 exc_info.match(r"Cannot send more than .+ bytes at once")
2970
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05002971
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002972def _make_memoryview(size):
2973 """
2974 Create a new ``memoryview`` wrapped around a ``bytearray`` of the given
2975 size.
2976 """
2977 return memoryview(bytearray(size))
2978
2979
Alex Chanb7480992017-01-30 14:04:47 +00002980class TestConnectionRecvInto(object):
Cory Benfield62d10332014-06-15 10:03:41 +01002981 """
Alex Chanb7480992017-01-30 14:04:47 +00002982 Tests for `Connection.recv_into`.
Cory Benfield62d10332014-06-15 10:03:41 +01002983 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002984 def _no_length_test(self, factory):
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04002985 """
Alex Chanb7480992017-01-30 14:04:47 +00002986 Assert that when the given buffer is passed to `Connection.recv_into`,
2987 whatever bytes are available to be received that fit into that buffer
2988 are written into that buffer.
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04002989 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002990 output_buffer = factory(5)
2991
Alex Chanb7480992017-01-30 14:04:47 +00002992 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002993 server.send(b'xy')
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04002994
Alex Chanb7480992017-01-30 14:04:47 +00002995 assert client.recv_into(output_buffer) == 2
2996 assert output_buffer == bytearray(b'xy\x00\x00\x00')
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04002997
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002998 def test_bytearray_no_length(self):
Cory Benfield62d10332014-06-15 10:03:41 +01002999 """
Alex Chanb7480992017-01-30 14:04:47 +00003000 `Connection.recv_into` can be passed a `bytearray` instance and data
3001 in the receive buffer is written to it.
Cory Benfield62d10332014-06-15 10:03:41 +01003002 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003003 self._no_length_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01003004
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003005 def _respects_length_test(self, factory):
Cory Benfield62d10332014-06-15 10:03:41 +01003006 """
Alex Chanb7480992017-01-30 14:04:47 +00003007 Assert that when the given buffer is passed to `Connection.recv_into`
3008 along with a value for `nbytes` that is less than the size of that
3009 buffer, only `nbytes` bytes are written into the buffer.
Cory Benfield62d10332014-06-15 10:03:41 +01003010 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003011 output_buffer = factory(10)
3012
Alex Chanb7480992017-01-30 14:04:47 +00003013 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04003014 server.send(b'abcdefghij')
Cory Benfield62d10332014-06-15 10:03:41 +01003015
Alex Chanb7480992017-01-30 14:04:47 +00003016 assert client.recv_into(output_buffer, 5) == 5
3017 assert output_buffer == bytearray(b'abcde\x00\x00\x00\x00\x00')
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04003018
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04003019 def test_bytearray_respects_length(self):
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04003020 """
Alex Chanb7480992017-01-30 14:04:47 +00003021 When called with a `bytearray` instance, `Connection.recv_into`
3022 respects the `nbytes` parameter and doesn't copy in more than that
3023 number of bytes.
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04003024 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003025 self._respects_length_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01003026
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003027 def _doesnt_overfill_test(self, factory):
Cory Benfield62d10332014-06-15 10:03:41 +01003028 """
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04003029 Assert that if there are more bytes available to be read from the
3030 receive buffer than would fit into the buffer passed to
Alex Chanb7480992017-01-30 14:04:47 +00003031 `Connection.recv_into`, only as many as fit are written into it.
Cory Benfield62d10332014-06-15 10:03:41 +01003032 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003033 output_buffer = factory(5)
3034
Alex Chanb7480992017-01-30 14:04:47 +00003035 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04003036 server.send(b'abcdefghij')
Cory Benfield62d10332014-06-15 10:03:41 +01003037
Alex Chanb7480992017-01-30 14:04:47 +00003038 assert client.recv_into(output_buffer) == 5
3039 assert output_buffer == bytearray(b'abcde')
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04003040 rest = client.recv(5)
Alex Chanb7480992017-01-30 14:04:47 +00003041 assert b'fghij' == rest
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04003042
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04003043 def test_bytearray_doesnt_overfill(self):
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04003044 """
Alex Chanb7480992017-01-30 14:04:47 +00003045 When called with a `bytearray` instance, `Connection.recv_into`
3046 respects the size of the array and doesn't write more bytes into it
3047 than will fit.
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04003048 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003049 self._doesnt_overfill_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01003050
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04003051 def test_bytearray_really_doesnt_overfill(self):
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003052 """
Alex Chanb7480992017-01-30 14:04:47 +00003053 When called with a `bytearray` instance and an `nbytes` value that is
3054 too large, `Connection.recv_into` respects the size of the array and
3055 not the `nbytes` value and doesn't write more bytes into the buffer
3056 than will fit.
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003057 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003058 self._doesnt_overfill_test(bytearray)
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003059
Maximilian Hils1d95dea2015-08-17 19:27:20 +02003060 def test_peek(self):
Alex Chanb7480992017-01-30 14:04:47 +00003061 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04003062 server.send(b'xy')
Maximilian Hils1d95dea2015-08-17 19:27:20 +02003063
3064 for _ in range(2):
3065 output_buffer = bytearray(5)
Alex Chanb7480992017-01-30 14:04:47 +00003066 assert client.recv_into(output_buffer, flags=MSG_PEEK) == 2
3067 assert output_buffer == bytearray(b'xy\x00\x00\x00')
Maximilian Hils1d95dea2015-08-17 19:27:20 +02003068
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003069 def test_memoryview_no_length(self):
3070 """
Alex Chanb7480992017-01-30 14:04:47 +00003071 `Connection.recv_into` can be passed a `memoryview` instance and data
3072 in the receive buffer is written to it.
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003073 """
3074 self._no_length_test(_make_memoryview)
Maximilian Hils1d95dea2015-08-17 19:27:20 +02003075
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003076 def test_memoryview_respects_length(self):
3077 """
Alex Chanb7480992017-01-30 14:04:47 +00003078 When called with a `memoryview` instance, `Connection.recv_into`
3079 respects the ``nbytes`` parameter and doesn't copy more than that
3080 number of bytes in.
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003081 """
3082 self._respects_length_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01003083
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003084 def test_memoryview_doesnt_overfill(self):
3085 """
Alex Chanb7480992017-01-30 14:04:47 +00003086 When called with a `memoryview` instance, `Connection.recv_into`
3087 respects the size of the array and doesn't write more bytes into it
3088 than will fit.
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003089 """
3090 self._doesnt_overfill_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01003091
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003092 def test_memoryview_really_doesnt_overfill(self):
3093 """
Alex Chanb7480992017-01-30 14:04:47 +00003094 When called with a `memoryview` instance and an `nbytes` value that is
3095 too large, `Connection.recv_into` respects the size of the array and
3096 not the `nbytes` value and doesn't write more bytes into the buffer
3097 than will fit.
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003098 """
3099 self._doesnt_overfill_test(_make_memoryview)
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003100
Cory Benfield62d10332014-06-15 10:03:41 +01003101
Alex Chanb7480992017-01-30 14:04:47 +00003102class TestConnectionSendall(object):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003103 """
Alex Chanb7480992017-01-30 14:04:47 +00003104 Tests for `Connection.sendall`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003105 """
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003106 def test_wrong_args(self):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003107 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003108 When called with arguments other than a string argument for its first
Alex Chanb7480992017-01-30 14:04:47 +00003109 parameter, `Connection.sendall` raises `TypeError`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003110 """
3111 connection = Connection(Context(TLSv1_METHOD), None)
Alex Chanb7480992017-01-30 14:04:47 +00003112 with pytest.raises(TypeError):
3113 connection.sendall(object())
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003114
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003115 def test_short(self):
3116 """
Alex Chanb7480992017-01-30 14:04:47 +00003117 `Connection.sendall` transmits all of the bytes in the string
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003118 passed to it.
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003119 """
Alex Chanb7480992017-01-30 14:04:47 +00003120 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04003121 server.sendall(b'x')
Alex Chanb7480992017-01-30 14:04:47 +00003122 assert client.recv(1) == b'x'
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003123
Abraham Martinef063482015-03-25 14:06:24 +00003124 def test_text(self):
3125 """
Alex Chanb7480992017-01-30 14:04:47 +00003126 `Connection.sendall` transmits all the content in the string passed
3127 to it, raising a DeprecationWarning in case of this being a text.
Abraham Martinef063482015-03-25 14:06:24 +00003128 """
Alex Chanb7480992017-01-30 14:04:47 +00003129 server, client = loopback()
3130 with pytest.warns(DeprecationWarning) as w:
Abraham Martinef063482015-03-25 14:06:24 +00003131 simplefilter("always")
Jean-Paul Calderone8dc37a12015-03-29 08:16:52 -04003132 server.sendall(b"x".decode("ascii"))
Alex Chanb7480992017-01-30 14:04:47 +00003133 assert (
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04003134 "{0} for buf is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04003135 WARNING_TYPE_EXPECTED
Alex Chanb7480992017-01-30 14:04:47 +00003136 ) == str(w[-1].message))
3137 assert client.recv(1) == b"x"
Abraham Martinef063482015-03-25 14:06:24 +00003138
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003139 def test_short_memoryview(self):
3140 """
3141 When passed a memoryview onto a small number of bytes,
Alex Chanb7480992017-01-30 14:04:47 +00003142 `Connection.sendall` transmits all of them.
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003143 """
Alex Chanb7480992017-01-30 14:04:47 +00003144 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04003145 server.sendall(memoryview(b'x'))
Alex Chanb7480992017-01-30 14:04:47 +00003146 assert client.recv(1) == b'x'
Abraham Martinef063482015-03-25 14:06:24 +00003147
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003148 @skip_if_py3
3149 def test_short_buffers(self):
3150 """
3151 When passed a buffer containing a small number of bytes,
Alex Chanb7480992017-01-30 14:04:47 +00003152 `Connection.sendall` transmits all of them.
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003153 """
Alex Chanb7480992017-01-30 14:04:47 +00003154 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04003155 server.sendall(buffer(b'x'))
Alex Chanb7480992017-01-30 14:04:47 +00003156 assert client.recv(1) == b'x'
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02003157
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003158 def test_long(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003159 """
Alex Chanb7480992017-01-30 14:04:47 +00003160 `Connection.sendall` transmits all the bytes in the string passed to it
3161 even if this requires multiple calls of an underlying write function.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003162 """
Alex Chanb7480992017-01-30 14:04:47 +00003163 server, client = loopback()
Jean-Paul Calderone6241c702010-09-16 19:59:24 -04003164 # Should be enough, underlying SSL_write should only do 16k at a time.
Hynek Schlawack35618382015-09-05 21:54:25 +02003165 # On Windows, after 32k of bytes the write will block (forever
3166 # - because no one is yet reading).
Alex Gaynore7f51982016-09-11 11:48:14 -04003167 message = b'x' * (1024 * 32 - 1) + b'y'
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003168 server.sendall(message)
3169 accum = []
3170 received = 0
3171 while received < len(message):
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04003172 data = client.recv(1024)
3173 accum.append(data)
3174 received += len(data)
Alex Chanb7480992017-01-30 14:04:47 +00003175 assert message == b''.join(accum)
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003176
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003177 def test_closed(self):
3178 """
Alex Chanb7480992017-01-30 14:04:47 +00003179 If the underlying socket is closed, `Connection.sendall` propagates the
3180 write error from the low level write call.
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003181 """
Alex Chanb7480992017-01-30 14:04:47 +00003182 server, client = loopback()
Jean-Paul Calderone05d43e82010-09-24 18:01:36 -04003183 server.sock_shutdown(2)
Alex Chanb7480992017-01-30 14:04:47 +00003184 with pytest.raises(SysCallError) as err:
3185 server.sendall(b"hello, world")
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +02003186 if platform == "win32":
Alex Chanb7480992017-01-30 14:04:47 +00003187 assert err.value.args[0] == ESHUTDOWN
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +02003188 else:
Alex Chanb7480992017-01-30 14:04:47 +00003189 assert err.value.args[0] == EPIPE
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003190
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003191
Alex Chanb7480992017-01-30 14:04:47 +00003192class TestConnectionRenegotiate(object):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003193 """
3194 Tests for SSL renegotiation APIs.
3195 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003196 def test_total_renegotiations(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003197 """
Alex Chanb7480992017-01-30 14:04:47 +00003198 `Connection.total_renegotiations` returns `0` before any renegotiations
3199 have happened.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003200 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003201 connection = Connection(Context(TLSv1_METHOD), None)
Alex Chanb7480992017-01-30 14:04:47 +00003202 assert connection.total_renegotiations() == 0
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003203
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003204 def test_renegotiate(self):
3205 """
3206 Go through a complete renegotiation cycle.
3207 """
Paul Kehrer7d5a3bf2019-01-21 12:24:02 -06003208 server, client = loopback(
3209 lambda s: loopback_server_factory(s, TLSv1_2_METHOD),
3210 lambda s: loopback_client_factory(s, TLSv1_2_METHOD),
3211 )
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003212
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003213 server.send(b"hello world")
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003214
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003215 assert b"hello world" == client.recv(len(b"hello world"))
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003216
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003217 assert 0 == server.total_renegotiations()
3218 assert False is server.renegotiate_pending()
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003219
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003220 assert True is server.renegotiate()
3221
3222 assert True is server.renegotiate_pending()
3223
3224 server.setblocking(False)
3225 client.setblocking(False)
3226
3227 client.do_handshake()
3228 server.do_handshake()
3229
3230 assert 1 == server.total_renegotiations()
3231 while False is server.renegotiate_pending():
3232 pass
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003233
3234
Alex Chanb7480992017-01-30 14:04:47 +00003235class TestError(object):
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003236 """
Alex Chanb7480992017-01-30 14:04:47 +00003237 Unit tests for `OpenSSL.SSL.Error`.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003238 """
3239 def test_type(self):
3240 """
Alex Chanb7480992017-01-30 14:04:47 +00003241 `Error` is an exception type.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003242 """
Alex Chanb7480992017-01-30 14:04:47 +00003243 assert issubclass(Error, Exception)
3244 assert Error.__name__ == 'Error'
Rick Deane15b1472009-07-09 15:53:42 -05003245
3246
Alex Chanb7480992017-01-30 14:04:47 +00003247class TestConstants(object):
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003248 """
Alex Chanb7480992017-01-30 14:04:47 +00003249 Tests for the values of constants exposed in `OpenSSL.SSL`.
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003250
3251 These are values defined by OpenSSL intended only to be used as flags to
3252 OpenSSL APIs. The only assertions it seems can be made about them is
3253 their values.
3254 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003255 @pytest.mark.skipif(
3256 OP_NO_QUERY_MTU is None,
3257 reason="OP_NO_QUERY_MTU unavailable - OpenSSL version may be too old"
3258 )
3259 def test_op_no_query_mtu(self):
3260 """
Alex Chanb7480992017-01-30 14:04:47 +00003261 The value of `OpenSSL.SSL.OP_NO_QUERY_MTU` is 0x1000, the value
3262 of `SSL_OP_NO_QUERY_MTU` defined by `openssl/ssl.h`.
Hynek Schlawack35618382015-09-05 21:54:25 +02003263 """
Alex Chanb7480992017-01-30 14:04:47 +00003264 assert OP_NO_QUERY_MTU == 0x1000
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003265
Hynek Schlawack35618382015-09-05 21:54:25 +02003266 @pytest.mark.skipif(
3267 OP_COOKIE_EXCHANGE is None,
3268 reason="OP_COOKIE_EXCHANGE unavailable - "
3269 "OpenSSL version may be too old"
3270 )
3271 def test_op_cookie_exchange(self):
3272 """
Alex Chanb7480992017-01-30 14:04:47 +00003273 The value of `OpenSSL.SSL.OP_COOKIE_EXCHANGE` is 0x2000, the
3274 value of `SSL_OP_COOKIE_EXCHANGE` defined by `openssl/ssl.h`.
Hynek Schlawack35618382015-09-05 21:54:25 +02003275 """
Alex Chanb7480992017-01-30 14:04:47 +00003276 assert OP_COOKIE_EXCHANGE == 0x2000
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003277
Hynek Schlawack35618382015-09-05 21:54:25 +02003278 @pytest.mark.skipif(
3279 OP_NO_TICKET is None,
3280 reason="OP_NO_TICKET unavailable - OpenSSL version may be too old"
3281 )
3282 def test_op_no_ticket(self):
3283 """
Alex Chanb7480992017-01-30 14:04:47 +00003284 The value of `OpenSSL.SSL.OP_NO_TICKET` is 0x4000, the value of
3285 `SSL_OP_NO_TICKET` defined by `openssl/ssl.h`.
Hynek Schlawack35618382015-09-05 21:54:25 +02003286 """
Alex Chanb7480992017-01-30 14:04:47 +00003287 assert OP_NO_TICKET == 0x4000
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003288
Hynek Schlawack35618382015-09-05 21:54:25 +02003289 @pytest.mark.skipif(
3290 OP_NO_COMPRESSION is None,
3291 reason="OP_NO_COMPRESSION unavailable - OpenSSL version may be too old"
3292 )
3293 def test_op_no_compression(self):
3294 """
Alex Chanb7480992017-01-30 14:04:47 +00003295 The value of `OpenSSL.SSL.OP_NO_COMPRESSION` is 0x20000, the
3296 value of `SSL_OP_NO_COMPRESSION` defined by `openssl/ssl.h`.
Hynek Schlawack35618382015-09-05 21:54:25 +02003297 """
Alex Chanb7480992017-01-30 14:04:47 +00003298 assert OP_NO_COMPRESSION == 0x20000
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04003299
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003300 def test_sess_cache_off(self):
3301 """
Alex Chanb7480992017-01-30 14:04:47 +00003302 The value of `OpenSSL.SSL.SESS_CACHE_OFF` 0x0, the value of
3303 `SSL_SESS_CACHE_OFF` defined by `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003304 """
Alex Chanb7480992017-01-30 14:04:47 +00003305 assert 0x0 == SESS_CACHE_OFF
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003306
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003307 def test_sess_cache_client(self):
3308 """
Alex Chanb7480992017-01-30 14:04:47 +00003309 The value of `OpenSSL.SSL.SESS_CACHE_CLIENT` 0x1, the value of
3310 `SSL_SESS_CACHE_CLIENT` defined by `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003311 """
Alex Chanb7480992017-01-30 14:04:47 +00003312 assert 0x1 == SESS_CACHE_CLIENT
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003313
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003314 def test_sess_cache_server(self):
3315 """
Alex Chanb7480992017-01-30 14:04:47 +00003316 The value of `OpenSSL.SSL.SESS_CACHE_SERVER` 0x2, the value of
3317 `SSL_SESS_CACHE_SERVER` defined by `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003318 """
Alex Chanb7480992017-01-30 14:04:47 +00003319 assert 0x2 == SESS_CACHE_SERVER
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003320
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003321 def test_sess_cache_both(self):
3322 """
Alex Chanb7480992017-01-30 14:04:47 +00003323 The value of `OpenSSL.SSL.SESS_CACHE_BOTH` 0x3, the value of
3324 `SSL_SESS_CACHE_BOTH` defined by `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003325 """
Alex Chanb7480992017-01-30 14:04:47 +00003326 assert 0x3 == SESS_CACHE_BOTH
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003327
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003328 def test_sess_cache_no_auto_clear(self):
3329 """
Alex Chanb7480992017-01-30 14:04:47 +00003330 The value of `OpenSSL.SSL.SESS_CACHE_NO_AUTO_CLEAR` 0x80, the
3331 value of `SSL_SESS_CACHE_NO_AUTO_CLEAR` defined by
3332 `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003333 """
Alex Chanb7480992017-01-30 14:04:47 +00003334 assert 0x80 == SESS_CACHE_NO_AUTO_CLEAR
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003335
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003336 def test_sess_cache_no_internal_lookup(self):
3337 """
Alex Chanb7480992017-01-30 14:04:47 +00003338 The value of `OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_LOOKUP` 0x100,
3339 the value of `SSL_SESS_CACHE_NO_INTERNAL_LOOKUP` defined by
3340 `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003341 """
Alex Chanb7480992017-01-30 14:04:47 +00003342 assert 0x100 == SESS_CACHE_NO_INTERNAL_LOOKUP
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003343
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003344 def test_sess_cache_no_internal_store(self):
3345 """
Alex Chanb7480992017-01-30 14:04:47 +00003346 The value of `OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_STORE` 0x200,
3347 the value of `SSL_SESS_CACHE_NO_INTERNAL_STORE` defined by
3348 `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003349 """
Alex Chanb7480992017-01-30 14:04:47 +00003350 assert 0x200 == SESS_CACHE_NO_INTERNAL_STORE
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003351
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003352 def test_sess_cache_no_internal(self):
3353 """
Alex Chanb7480992017-01-30 14:04:47 +00003354 The value of `OpenSSL.SSL.SESS_CACHE_NO_INTERNAL` 0x300, the
3355 value of `SSL_SESS_CACHE_NO_INTERNAL` defined by
3356 `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003357 """
Alex Chanb7480992017-01-30 14:04:47 +00003358 assert 0x300 == SESS_CACHE_NO_INTERNAL
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003359
3360
Alex Chanb7480992017-01-30 14:04:47 +00003361class TestMemoryBIO(object):
Rick Deanb71c0d22009-04-01 14:09:23 -05003362 """
Alex Chanb7480992017-01-30 14:04:47 +00003363 Tests for `OpenSSL.SSL.Connection` using a memory BIO.
Rick Deanb71c0d22009-04-01 14:09:23 -05003364 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003365 def _server(self, sock):
3366 """
Alex Chanb7480992017-01-30 14:04:47 +00003367 Create a new server-side SSL `Connection` object wrapped around `sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003368 """
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003369 # Create the server side Connection. This is mostly setup boilerplate
3370 # - use TLSv1, use a particular certificate, etc.
3371 server_ctx = Context(TLSv1_METHOD)
Alex Gaynor43307782015-09-04 09:05:45 -04003372 server_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE)
Hynek Schlawack35618382015-09-05 21:54:25 +02003373 server_ctx.set_verify(
3374 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT | VERIFY_CLIENT_ONCE,
3375 verify_cb
3376 )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003377 server_store = server_ctx.get_cert_store()
Hynek Schlawack35618382015-09-05 21:54:25 +02003378 server_ctx.use_privatekey(
3379 load_privatekey(FILETYPE_PEM, server_key_pem))
3380 server_ctx.use_certificate(
3381 load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003382 server_ctx.check_privatekey()
3383 server_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Hynek Schlawack35618382015-09-05 21:54:25 +02003384 # Here the Connection is actually created. If None is passed as the
3385 # 2nd parameter, it indicates a memory BIO should be created.
Rick Deanb1ccd562009-07-09 23:52:39 -05003386 server_conn = Connection(server_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003387 server_conn.set_accept_state()
3388 return server_conn
3389
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003390 def _client(self, sock):
3391 """
Alex Chanb7480992017-01-30 14:04:47 +00003392 Create a new client-side SSL `Connection` object wrapped around `sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003393 """
3394 # Now create the client side Connection. Similar boilerplate to the
3395 # above.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003396 client_ctx = Context(TLSv1_METHOD)
Alex Gaynor43307782015-09-04 09:05:45 -04003397 client_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE)
Hynek Schlawack35618382015-09-05 21:54:25 +02003398 client_ctx.set_verify(
3399 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT | VERIFY_CLIENT_ONCE,
3400 verify_cb
3401 )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003402 client_store = client_ctx.get_cert_store()
Hynek Schlawack35618382015-09-05 21:54:25 +02003403 client_ctx.use_privatekey(
3404 load_privatekey(FILETYPE_PEM, client_key_pem))
3405 client_ctx.use_certificate(
3406 load_certificate(FILETYPE_PEM, client_cert_pem))
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003407 client_ctx.check_privatekey()
3408 client_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05003409 client_conn = Connection(client_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003410 client_conn.set_connect_state()
3411 return client_conn
3412
Alex Chanb7480992017-01-30 14:04:47 +00003413 def test_memory_connect(self):
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003414 """
Alex Chanb7480992017-01-30 14:04:47 +00003415 Two `Connection`s which use memory BIOs can be manually connected by
3416 reading from the output of each and writing those bytes to the input of
3417 the other and in this way establish a connection and exchange
3418 application-level bytes with each other.
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003419 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003420 server_conn = self._server(None)
3421 client_conn = self._client(None)
Rick Deanb71c0d22009-04-01 14:09:23 -05003422
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003423 # There should be no key or nonces yet.
Alex Chanb7480992017-01-30 14:04:47 +00003424 assert server_conn.master_key() is None
3425 assert server_conn.client_random() is None
3426 assert server_conn.server_random() is None
Rick Deanb71c0d22009-04-01 14:09:23 -05003427
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003428 # First, the handshake needs to happen. We'll deliver bytes back and
3429 # forth between the client and server until neither of them feels like
3430 # speaking any more.
Alex Chanb7480992017-01-30 14:04:47 +00003431 assert interact_in_memory(client_conn, server_conn) is None
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003432
3433 # Now that the handshake is done, there should be a key and nonces.
Alex Chanb7480992017-01-30 14:04:47 +00003434 assert server_conn.master_key() is not None
3435 assert server_conn.client_random() is not None
3436 assert server_conn.server_random() is not None
3437 assert server_conn.client_random() == client_conn.client_random()
3438 assert server_conn.server_random() == client_conn.server_random()
3439 assert server_conn.client_random() != server_conn.server_random()
3440 assert client_conn.client_random() != client_conn.server_random()
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003441
Paul Kehrerbdb76392017-12-01 04:54:32 +08003442 # Export key material for other uses.
3443 cekm = client_conn.export_keying_material(b'LABEL', 32)
3444 sekm = server_conn.export_keying_material(b'LABEL', 32)
3445 assert cekm is not None
3446 assert sekm is not None
3447 assert cekm == sekm
3448 assert len(sekm) == 32
3449
3450 # Export key material for other uses with additional context.
3451 cekmc = client_conn.export_keying_material(b'LABEL', 32, b'CONTEXT')
3452 sekmc = server_conn.export_keying_material(b'LABEL', 32, b'CONTEXT')
3453 assert cekmc is not None
3454 assert sekmc is not None
3455 assert cekmc == sekmc
3456 assert cekmc != cekm
3457 assert sekmc != sekm
3458 # Export with alternate label
3459 cekmt = client_conn.export_keying_material(b'test', 32, b'CONTEXT')
3460 sekmt = server_conn.export_keying_material(b'test', 32, b'CONTEXT')
3461 assert cekmc != cekmt
3462 assert sekmc != sekmt
3463
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003464 # Here are the bytes we'll try to send.
Alex Gaynore7f51982016-09-11 11:48:14 -04003465 important_message = b'One if by land, two if by sea.'
Rick Deanb71c0d22009-04-01 14:09:23 -05003466
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003467 server_conn.write(important_message)
Alex Chanb7480992017-01-30 14:04:47 +00003468 assert (
3469 interact_in_memory(client_conn, server_conn) ==
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003470 (client_conn, important_message))
3471
3472 client_conn.write(important_message[::-1])
Alex Chanb7480992017-01-30 14:04:47 +00003473 assert (
3474 interact_in_memory(client_conn, server_conn) ==
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003475 (server_conn, important_message[::-1]))
Rick Deanb71c0d22009-04-01 14:09:23 -05003476
Alex Chanb7480992017-01-30 14:04:47 +00003477 def test_socket_connect(self):
Rick Deanb1ccd562009-07-09 23:52:39 -05003478 """
Alex Chanb7480992017-01-30 14:04:47 +00003479 Just like `test_memory_connect` but with an actual socket.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003480
Hynek Schlawack35618382015-09-05 21:54:25 +02003481 This is primarily to rule out the memory BIO code as the source of any
Alex Chanb7480992017-01-30 14:04:47 +00003482 problems encountered while passing data over a `Connection` (if
Hynek Schlawack35618382015-09-05 21:54:25 +02003483 this test fails, there must be a problem outside the memory BIO code,
3484 as no memory BIO is involved here). Even though this isn't a memory
3485 BIO test, it's convenient to have it here.
Rick Deanb1ccd562009-07-09 23:52:39 -05003486 """
Alex Chanb7480992017-01-30 14:04:47 +00003487 server_conn, client_conn = loopback()
Rick Deanb1ccd562009-07-09 23:52:39 -05003488
Alex Gaynore7f51982016-09-11 11:48:14 -04003489 important_message = b"Help me Obi Wan Kenobi, you're my only hope."
Rick Deanb1ccd562009-07-09 23:52:39 -05003490 client_conn.send(important_message)
3491 msg = server_conn.recv(1024)
Alex Chanb7480992017-01-30 14:04:47 +00003492 assert msg == important_message
Rick Deanb1ccd562009-07-09 23:52:39 -05003493
3494 # Again in the other direction, just for fun.
3495 important_message = important_message[::-1]
3496 server_conn.send(important_message)
3497 msg = client_conn.recv(1024)
Alex Chanb7480992017-01-30 14:04:47 +00003498 assert msg == important_message
Rick Deanb1ccd562009-07-09 23:52:39 -05003499
Alex Chanb7480992017-01-30 14:04:47 +00003500 def test_socket_overrides_memory(self):
Rick Deanb71c0d22009-04-01 14:09:23 -05003501 """
Alex Chanb7480992017-01-30 14:04:47 +00003502 Test that `OpenSSL.SSL.bio_read` and `OpenSSL.SSL.bio_write` don't
3503 work on `OpenSSL.SSL.Connection`() that use sockets.
Rick Deanb71c0d22009-04-01 14:09:23 -05003504 """
Alex Gaynor51d424c2016-09-10 14:50:11 -04003505 context = Context(TLSv1_METHOD)
Rick Deanb71c0d22009-04-01 14:09:23 -05003506 client = socket()
3507 clientSSL = Connection(context, client)
Alex Chanb7480992017-01-30 14:04:47 +00003508 with pytest.raises(TypeError):
3509 clientSSL.bio_read(100)
3510 with pytest.raises(TypeError):
3511 clientSSL.bio_write("foo")
3512 with pytest.raises(TypeError):
3513 clientSSL.bio_shutdown()
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003514
Alex Chanb7480992017-01-30 14:04:47 +00003515 def test_outgoing_overflow(self):
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003516 """
3517 If more bytes than can be written to the memory BIO are passed to
Alex Chanb7480992017-01-30 14:04:47 +00003518 `Connection.send` at once, the number of bytes which were written is
3519 returned and that many bytes from the beginning of the input can be
3520 read from the other end of the connection.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003521 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003522 server = self._server(None)
3523 client = self._client(None)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003524
Alex Chanb7480992017-01-30 14:04:47 +00003525 interact_in_memory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003526
3527 size = 2 ** 15
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003528 sent = client.send(b"x" * size)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003529 # Sanity check. We're trying to test what happens when the entire
3530 # input can't be sent. If the entire input was sent, this test is
3531 # meaningless.
Alex Chanb7480992017-01-30 14:04:47 +00003532 assert sent < size
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003533
Alex Chanb7480992017-01-30 14:04:47 +00003534 receiver, received = interact_in_memory(client, server)
3535 assert receiver is server
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003536
3537 # We can rely on all of these bytes being received at once because
Alex Chanb7480992017-01-30 14:04:47 +00003538 # loopback passes 2 ** 16 to recv - more than 2 ** 15.
3539 assert len(received) == sent
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003540
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003541 def test_shutdown(self):
3542 """
Alex Chanb7480992017-01-30 14:04:47 +00003543 `Connection.bio_shutdown` signals the end of the data stream
3544 from which the `Connection` reads.
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003545 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003546 server = self._server(None)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003547 server.bio_shutdown()
Alex Chanb7480992017-01-30 14:04:47 +00003548 with pytest.raises(Error) as err:
3549 server.recv(1024)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003550 # We don't want WantReadError or ZeroReturnError or anything - it's a
3551 # handshake failure.
Alex Chanb7480992017-01-30 14:04:47 +00003552 assert type(err.value) in [Error, SysCallError]
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003553
Alex Chanb7480992017-01-30 14:04:47 +00003554 def test_unexpected_EOF(self):
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003555 """
3556 If the connection is lost before an orderly SSL shutdown occurs,
Alex Chanb7480992017-01-30 14:04:47 +00003557 `OpenSSL.SSL.SysCallError` is raised with a message of
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003558 "Unexpected EOF".
3559 """
Alex Chanb7480992017-01-30 14:04:47 +00003560 server_conn, client_conn = loopback()
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003561 client_conn.sock_shutdown(SHUT_RDWR)
Alex Chanb7480992017-01-30 14:04:47 +00003562 with pytest.raises(SysCallError) as err:
3563 server_conn.recv(1024)
3564 assert err.value.args == (-1, "Unexpected EOF")
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003565
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003566 def _check_client_ca_list(self, func):
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003567 """
Alex Chanb7480992017-01-30 14:04:47 +00003568 Verify the return value of the `get_client_ca_list` method for
Hynek Schlawack35618382015-09-05 21:54:25 +02003569 server and client connections.
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003570
Jonathan Ballet78b92a22011-07-16 08:07:26 +09003571 :param func: A function which will be called with the server context
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003572 before the client and server are connected to each other. This
3573 function should specify a list of CAs for the server to send to the
3574 client and return that same list. The list will be used to verify
Alex Chanb7480992017-01-30 14:04:47 +00003575 that `get_client_ca_list` returns the proper value at
Hynek Schlawack35618382015-09-05 21:54:25 +02003576 various times.
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003577 """
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003578 server = self._server(None)
3579 client = self._client(None)
Alex Chanb7480992017-01-30 14:04:47 +00003580 assert client.get_client_ca_list() == []
3581 assert server.get_client_ca_list() == []
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003582 ctx = server.get_context()
3583 expected = func(ctx)
Alex Chanb7480992017-01-30 14:04:47 +00003584 assert client.get_client_ca_list() == []
3585 assert server.get_client_ca_list() == expected
3586 interact_in_memory(client, server)
3587 assert client.get_client_ca_list() == expected
3588 assert server.get_client_ca_list() == expected
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003589
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003590 def test_set_client_ca_list_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003591 """
Alex Chanb7480992017-01-30 14:04:47 +00003592 `Context.set_client_ca_list` raises a `TypeError` if called with a
3593 non-list or a list that contains objects other than X509Names.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003594 """
3595 ctx = Context(TLSv1_METHOD)
Alex Chanb7480992017-01-30 14:04:47 +00003596 with pytest.raises(TypeError):
3597 ctx.set_client_ca_list("spam")
3598 with pytest.raises(TypeError):
3599 ctx.set_client_ca_list(["spam"])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003600
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003601 def test_set_empty_ca_list(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003602 """
Alex Chanb7480992017-01-30 14:04:47 +00003603 If passed an empty list, `Context.set_client_ca_list` configures the
3604 context to send no CA names to the client and, on both the server and
3605 client sides, `Connection.get_client_ca_list` returns an empty list
3606 after the connection is set up.
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003607 """
3608 def no_ca(ctx):
3609 ctx.set_client_ca_list([])
3610 return []
3611 self._check_client_ca_list(no_ca)
3612
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003613 def test_set_one_ca_list(self):
3614 """
3615 If passed a list containing a single X509Name,
Alex Chanb7480992017-01-30 14:04:47 +00003616 `Context.set_client_ca_list` configures the context to send
Hynek Schlawack35618382015-09-05 21:54:25 +02003617 that CA name to the client and, on both the server and client sides,
Alex Chanb7480992017-01-30 14:04:47 +00003618 `Connection.get_client_ca_list` returns a list containing that
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003619 X509Name after the connection is set up.
3620 """
3621 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3622 cadesc = cacert.get_subject()
Hynek Schlawack35618382015-09-05 21:54:25 +02003623
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003624 def single_ca(ctx):
3625 ctx.set_client_ca_list([cadesc])
3626 return [cadesc]
3627 self._check_client_ca_list(single_ca)
3628
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003629 def test_set_multiple_ca_list(self):
3630 """
3631 If passed a list containing multiple X509Name objects,
Alex Chanb7480992017-01-30 14:04:47 +00003632 `Context.set_client_ca_list` configures the context to send
Hynek Schlawack35618382015-09-05 21:54:25 +02003633 those CA names to the client and, on both the server and client sides,
Alex Chanb7480992017-01-30 14:04:47 +00003634 `Connection.get_client_ca_list` returns a list containing those
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003635 X509Names after the connection is set up.
3636 """
3637 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3638 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3639
3640 sedesc = secert.get_subject()
3641 cldesc = clcert.get_subject()
3642
3643 def multiple_ca(ctx):
3644 L = [sedesc, cldesc]
3645 ctx.set_client_ca_list(L)
3646 return L
3647 self._check_client_ca_list(multiple_ca)
3648
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003649 def test_reset_ca_list(self):
3650 """
3651 If called multiple times, only the X509Names passed to the final call
Alex Chanb7480992017-01-30 14:04:47 +00003652 of `Context.set_client_ca_list` are used to configure the CA
Hynek Schlawack35618382015-09-05 21:54:25 +02003653 names sent to the client.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003654 """
3655 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3656 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3657 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3658
3659 cadesc = cacert.get_subject()
3660 sedesc = secert.get_subject()
3661 cldesc = clcert.get_subject()
3662
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003663 def changed_ca(ctx):
3664 ctx.set_client_ca_list([sedesc, cldesc])
3665 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003666 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003667 self._check_client_ca_list(changed_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003668
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003669 def test_mutated_ca_list(self):
3670 """
Alex Chanb7480992017-01-30 14:04:47 +00003671 If the list passed to `Context.set_client_ca_list` is mutated
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003672 afterwards, this does not affect the list of CA names sent to the
3673 client.
3674 """
3675 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3676 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3677
3678 cadesc = cacert.get_subject()
3679 sedesc = secert.get_subject()
3680
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003681 def mutated_ca(ctx):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003682 L = [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003683 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003684 L.append(sedesc)
3685 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003686 self._check_client_ca_list(mutated_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003687
Alex Chanb7480992017-01-30 14:04:47 +00003688 def test_add_client_ca_wrong_args(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003689 """
Alex Chanb7480992017-01-30 14:04:47 +00003690 `Context.add_client_ca` raises `TypeError` if called with
3691 a non-X509 object.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003692 """
3693 ctx = Context(TLSv1_METHOD)
Alex Chanb7480992017-01-30 14:04:47 +00003694 with pytest.raises(TypeError):
3695 ctx.add_client_ca("spam")
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003696
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003697 def test_one_add_client_ca(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003698 """
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003699 A certificate's subject can be added as a CA to be sent to the client
Alex Chanb7480992017-01-30 14:04:47 +00003700 with `Context.add_client_ca`.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003701 """
3702 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3703 cadesc = cacert.get_subject()
Hynek Schlawack35618382015-09-05 21:54:25 +02003704
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003705 def single_ca(ctx):
3706 ctx.add_client_ca(cacert)
3707 return [cadesc]
3708 self._check_client_ca_list(single_ca)
3709
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003710 def test_multiple_add_client_ca(self):
3711 """
3712 Multiple CA names can be sent to the client by calling
Alex Chanb7480992017-01-30 14:04:47 +00003713 `Context.add_client_ca` with multiple X509 objects.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003714 """
3715 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3716 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3717
3718 cadesc = cacert.get_subject()
3719 sedesc = secert.get_subject()
3720
3721 def multiple_ca(ctx):
3722 ctx.add_client_ca(cacert)
3723 ctx.add_client_ca(secert)
3724 return [cadesc, sedesc]
3725 self._check_client_ca_list(multiple_ca)
3726
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003727 def test_set_and_add_client_ca(self):
3728 """
Alex Chanb7480992017-01-30 14:04:47 +00003729 A call to `Context.set_client_ca_list` followed by a call to
3730 `Context.add_client_ca` results in using the CA names from the
Hynek Schlawack35618382015-09-05 21:54:25 +02003731 first call and the CA name from the second call.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003732 """
3733 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3734 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3735 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3736
3737 cadesc = cacert.get_subject()
3738 sedesc = secert.get_subject()
3739 cldesc = clcert.get_subject()
3740
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003741 def mixed_set_add_ca(ctx):
3742 ctx.set_client_ca_list([cadesc, sedesc])
3743 ctx.add_client_ca(clcert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003744 return [cadesc, sedesc, cldesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003745 self._check_client_ca_list(mixed_set_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003746
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003747 def test_set_after_add_client_ca(self):
3748 """
Alex Chanb7480992017-01-30 14:04:47 +00003749 A call to `Context.set_client_ca_list` after a call to
3750 `Context.add_client_ca` replaces the CA name specified by the
Hynek Schlawack35618382015-09-05 21:54:25 +02003751 former call with the names specified by the latter call.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003752 """
3753 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3754 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3755 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3756
3757 cadesc = cacert.get_subject()
3758 sedesc = secert.get_subject()
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003759
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003760 def set_replaces_add_ca(ctx):
3761 ctx.add_client_ca(clcert)
3762 ctx.set_client_ca_list([cadesc])
3763 ctx.add_client_ca(secert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003764 return [cadesc, sedesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003765 self._check_client_ca_list(set_replaces_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003766
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003767
Alex Chanb7480992017-01-30 14:04:47 +00003768class TestInfoConstants(object):
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003769 """
3770 Tests for assorted constants exposed for use in info callbacks.
3771 """
3772 def test_integers(self):
3773 """
3774 All of the info constants are integers.
3775
3776 This is a very weak test. It would be nice to have one that actually
3777 verifies that as certain info events happen, the value passed to the
3778 info callback matches up with the constant exposed by OpenSSL.SSL.
3779 """
3780 for const in [
Alex Gaynor5af32d02016-09-24 01:52:21 -04003781 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK,
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003782 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
3783 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
3784 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
Hynek Schlawack35618382015-09-05 21:54:25 +02003785 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE
3786 ]:
Alex Gaynor5af32d02016-09-24 01:52:21 -04003787 assert isinstance(const, int)
3788
3789 # These constants don't exist on OpenSSL 1.1.0
3790 for const in [
3791 SSL_ST_INIT, SSL_ST_BEFORE, SSL_ST_OK, SSL_ST_RENEGOTIATE
3792 ]:
3793 assert const is None or isinstance(const, int)
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003794
Ziga Seilnacht44611bf2009-08-31 20:49:30 +02003795
Cory Benfield1d142142016-03-30 11:51:45 +01003796class TestRequires(object):
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003797 """
3798 Tests for the decorator factory used to conditionally raise
Cory Benfield1d142142016-03-30 11:51:45 +01003799 NotImplementedError when older OpenSSLs are used.
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003800 """
3801 def test_available(self):
3802 """
3803 When the OpenSSL functionality is available the decorated functions
3804 work appropriately.
3805 """
3806 feature_guard = _make_requires(True, "Error text")
3807 results = []
3808
3809 @feature_guard
3810 def inner():
3811 results.append(True)
3812 return True
3813
Cory Benfield2333e5e2016-03-30 14:24:16 +01003814 assert inner() is True
3815 assert [True] == results
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003816
3817 def test_unavailable(self):
3818 """
3819 When the OpenSSL functionality is not available the decorated function
3820 does not execute and NotImplementedError is raised.
3821 """
3822 feature_guard = _make_requires(False, "Error text")
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003823
3824 @feature_guard
Alex Chanfb078d82017-04-20 11:16:15 +01003825 def inner(): # pragma: nocover
3826 pytest.fail("Should not be called")
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003827
Cory Benfield1d142142016-03-30 11:51:45 +01003828 with pytest.raises(NotImplementedError) as e:
3829 inner()
3830
3831 assert "Error text" in str(e.value)
Cory Benfield496652a2017-01-24 11:42:56 +00003832
3833
Alex Chanb7480992017-01-30 14:04:47 +00003834class TestOCSP(object):
Cory Benfield496652a2017-01-24 11:42:56 +00003835 """
3836 Tests for PyOpenSSL's OCSP stapling support.
3837 """
3838 sample_ocsp_data = b"this is totally ocsp data"
3839
3840 def _client_connection(self, callback, data, request_ocsp=True):
3841 """
3842 Builds a client connection suitable for using OCSP.
3843
3844 :param callback: The callback to register for OCSP.
3845 :param data: The opaque data object that will be handed to the
3846 OCSP callback.
3847 :param request_ocsp: Whether the client will actually ask for OCSP
3848 stapling. Useful for testing only.
3849 """
3850 ctx = Context(SSLv23_METHOD)
3851 ctx.set_ocsp_client_callback(callback, data)
3852 client = Connection(ctx)
3853
3854 if request_ocsp:
3855 client.request_ocsp()
3856
3857 client.set_connect_state()
3858 return client
3859
3860 def _server_connection(self, callback, data):
3861 """
3862 Builds a server connection suitable for using OCSP.
3863
3864 :param callback: The callback to register for OCSP.
3865 :param data: The opaque data object that will be handed to the
3866 OCSP callback.
3867 """
3868 ctx = Context(SSLv23_METHOD)
3869 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
3870 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
3871 ctx.set_ocsp_server_callback(callback, data)
3872 server = Connection(ctx)
3873 server.set_accept_state()
3874 return server
3875
3876 def test_callbacks_arent_called_by_default(self):
3877 """
3878 If both the client and the server have registered OCSP callbacks, but
3879 the client does not send the OCSP request, neither callback gets
3880 called.
3881 """
Alex Chanfb078d82017-04-20 11:16:15 +01003882 def ocsp_callback(*args, **kwargs): # pragma: nocover
3883 pytest.fail("Should not be called")
Cory Benfield496652a2017-01-24 11:42:56 +00003884
3885 client = self._client_connection(
3886 callback=ocsp_callback, data=None, request_ocsp=False
3887 )
3888 server = self._server_connection(callback=ocsp_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00003889 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003890
Cory Benfield496652a2017-01-24 11:42:56 +00003891 def test_client_negotiates_without_server(self):
3892 """
3893 If the client wants to do OCSP but the server does not, the handshake
3894 succeeds, and the client callback fires with an empty byte string.
3895 """
3896 called = []
3897
3898 def ocsp_callback(conn, ocsp_data, ignored):
3899 called.append(ocsp_data)
3900 return True
3901
3902 client = self._client_connection(callback=ocsp_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00003903 server = loopback_server_factory(socket=None)
3904 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003905
3906 assert len(called) == 1
3907 assert called[0] == b''
3908
3909 def test_client_receives_servers_data(self):
3910 """
3911 The data the server sends in its callback is received by the client.
3912 """
3913 calls = []
3914
3915 def server_callback(*args, **kwargs):
3916 return self.sample_ocsp_data
3917
3918 def client_callback(conn, ocsp_data, ignored):
3919 calls.append(ocsp_data)
3920 return True
3921
3922 client = self._client_connection(callback=client_callback, data=None)
3923 server = self._server_connection(callback=server_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00003924 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003925
3926 assert len(calls) == 1
3927 assert calls[0] == self.sample_ocsp_data
3928
3929 def test_callbacks_are_invoked_with_connections(self):
3930 """
3931 The first arguments to both callbacks are their respective connections.
3932 """
3933 client_calls = []
3934 server_calls = []
3935
3936 def client_callback(conn, *args, **kwargs):
3937 client_calls.append(conn)
3938 return True
3939
3940 def server_callback(conn, *args, **kwargs):
3941 server_calls.append(conn)
3942 return self.sample_ocsp_data
3943
3944 client = self._client_connection(callback=client_callback, data=None)
3945 server = self._server_connection(callback=server_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00003946 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003947
3948 assert len(client_calls) == 1
3949 assert len(server_calls) == 1
3950 assert client_calls[0] is client
3951 assert server_calls[0] is server
3952
3953 def test_opaque_data_is_passed_through(self):
3954 """
3955 Both callbacks receive an opaque, user-provided piece of data in their
3956 callbacks as the final argument.
3957 """
3958 calls = []
3959
3960 def server_callback(*args):
3961 calls.append(args)
3962 return self.sample_ocsp_data
3963
3964 def client_callback(*args):
3965 calls.append(args)
3966 return True
3967
3968 sentinel = object()
3969
3970 client = self._client_connection(
3971 callback=client_callback, data=sentinel
3972 )
3973 server = self._server_connection(
3974 callback=server_callback, data=sentinel
3975 )
Alex Chanb7480992017-01-30 14:04:47 +00003976 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003977
3978 assert len(calls) == 2
3979 assert calls[0][-1] is sentinel
3980 assert calls[1][-1] is sentinel
3981
3982 def test_server_returns_empty_string(self):
3983 """
3984 If the server returns an empty bytestring from its callback, the
3985 client callback is called with the empty bytestring.
3986 """
3987 client_calls = []
3988
3989 def server_callback(*args):
3990 return b''
3991
3992 def client_callback(conn, ocsp_data, ignored):
3993 client_calls.append(ocsp_data)
3994 return True
3995
3996 client = self._client_connection(callback=client_callback, data=None)
3997 server = self._server_connection(callback=server_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00003998 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003999
4000 assert len(client_calls) == 1
4001 assert client_calls[0] == b''
4002
4003 def test_client_returns_false_terminates_handshake(self):
4004 """
4005 If the client returns False from its callback, the handshake fails.
4006 """
4007 def server_callback(*args):
4008 return self.sample_ocsp_data
4009
4010 def client_callback(*args):
4011 return False
4012
4013 client = self._client_connection(callback=client_callback, data=None)
4014 server = self._server_connection(callback=server_callback, data=None)
4015
4016 with pytest.raises(Error):
Alex Chanb7480992017-01-30 14:04:47 +00004017 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00004018
4019 def test_exceptions_in_client_bubble_up(self):
4020 """
4021 The callbacks thrown in the client callback bubble up to the caller.
4022 """
4023 class SentinelException(Exception):
4024 pass
4025
4026 def server_callback(*args):
4027 return self.sample_ocsp_data
4028
4029 def client_callback(*args):
4030 raise SentinelException()
4031
4032 client = self._client_connection(callback=client_callback, data=None)
4033 server = self._server_connection(callback=server_callback, data=None)
4034
4035 with pytest.raises(SentinelException):
Alex Chanb7480992017-01-30 14:04:47 +00004036 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00004037
4038 def test_exceptions_in_server_bubble_up(self):
4039 """
4040 The callbacks thrown in the server callback bubble up to the caller.
4041 """
4042 class SentinelException(Exception):
4043 pass
4044
4045 def server_callback(*args):
4046 raise SentinelException()
4047
Alex Chanfb078d82017-04-20 11:16:15 +01004048 def client_callback(*args): # pragma: nocover
Cory Benfield496652a2017-01-24 11:42:56 +00004049 pytest.fail("Should not be called")
4050
4051 client = self._client_connection(callback=client_callback, data=None)
4052 server = self._server_connection(callback=server_callback, data=None)
4053
4054 with pytest.raises(SentinelException):
Alex Chanb7480992017-01-30 14:04:47 +00004055 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00004056
4057 def test_server_must_return_bytes(self):
4058 """
4059 The server callback must return a bytestring, or a TypeError is thrown.
4060 """
4061 def server_callback(*args):
4062 return self.sample_ocsp_data.decode('ascii')
4063
Alex Chanfb078d82017-04-20 11:16:15 +01004064 def client_callback(*args): # pragma: nocover
Cory Benfield496652a2017-01-24 11:42:56 +00004065 pytest.fail("Should not be called")
4066
4067 client = self._client_connection(callback=client_callback, data=None)
4068 server = self._server_connection(callback=server_callback, data=None)
4069
4070 with pytest.raises(TypeError):
Alex Chanb7480992017-01-30 14:04:47 +00004071 handshake_in_memory(client, server)