blob: 38511a4df617e60ce08cc3a60e9cc2e322ed77c3 [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
413 @pytest.mark.parametrize("cipher_list,error", [
414 (object(), TypeError),
415 ("imaginary-cipher", Error),
416 ])
417 def test_set_cipher_list_wrong_args(self, context, cipher_list, error):
418 """
Alex Chan532b79e2017-01-24 15:14:52 +0000419 `Context.set_cipher_list` raises `TypeError` when passed a non-string
420 argument and raises `OpenSSL.SSL.Error` when passed an incorrect cipher
421 list string.
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100422 """
423 with pytest.raises(error):
424 context.set_cipher_list(cipher_list)
425
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100426 def test_load_client_ca(self, context, ca_file):
427 """
Alex Chan532b79e2017-01-24 15:14:52 +0000428 `Context.load_client_ca` works as far as we can tell.
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100429 """
430 context.load_client_ca(ca_file)
431
432 def test_load_client_ca_invalid(self, context, tmpdir):
433 """
Alex Chan532b79e2017-01-24 15:14:52 +0000434 `Context.load_client_ca` raises an Error if the ca file is invalid.
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100435 """
436 ca_file = tmpdir.join("test.pem")
437 ca_file.write("")
438
439 with pytest.raises(Error) as e:
440 context.load_client_ca(str(ca_file).encode("ascii"))
441
442 assert "PEM routines" == e.value.args[0][0][0]
443
444 def test_load_client_ca_unicode(self, context, ca_file):
445 """
446 Passing the path as unicode raises a warning but works.
447 """
448 pytest.deprecated_call(
449 context.load_client_ca, ca_file.decode("ascii")
450 )
451
452 def test_set_session_id(self, context):
453 """
Alex Chan532b79e2017-01-24 15:14:52 +0000454 `Context.set_session_id` works as far as we can tell.
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100455 """
456 context.set_session_id(b"abc")
457
458 def test_set_session_id_fail(self, context):
459 """
Alex Chan532b79e2017-01-24 15:14:52 +0000460 `Context.set_session_id` errors are propagated.
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100461 """
462 with pytest.raises(Error) as e:
463 context.set_session_id(b"abc" * 1000)
464
465 assert [
466 ("SSL routines",
467 "SSL_CTX_set_session_id_context",
468 "ssl session id context too long")
469 ] == e.value.args[0]
470
471 def test_set_session_id_unicode(self, context):
472 """
Alex Chan532b79e2017-01-24 15:14:52 +0000473 `Context.set_session_id` raises a warning if a unicode string is
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100474 passed.
475 """
476 pytest.deprecated_call(context.set_session_id, u"abc")
477
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400478 def test_method(self):
479 """
Alex Chan532b79e2017-01-24 15:14:52 +0000480 `Context` can be instantiated with one of `SSLv2_METHOD`,
481 `SSLv3_METHOD`, `SSLv23_METHOD`, `TLSv1_METHOD`, `TLSv1_1_METHOD`,
482 or `TLSv1_2_METHOD`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400483 """
Alex Gaynor5af32d02016-09-24 01:52:21 -0400484 methods = [SSLv23_METHOD, TLSv1_METHOD]
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400485 for meth in methods:
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400486 Context(meth)
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400487
Alex Gaynor5af32d02016-09-24 01:52:21 -0400488 maybe = [SSLv2_METHOD, SSLv3_METHOD, TLSv1_1_METHOD, TLSv1_2_METHOD]
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400489 for meth in maybe:
490 try:
491 Context(meth)
492 except (Error, ValueError):
493 # Some versions of OpenSSL have SSLv2 / TLSv1.1 / TLSv1.2, some
494 # don't. Difficult to say in advance.
495 pass
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400496
Alex Chan532b79e2017-01-24 15:14:52 +0000497 with pytest.raises(TypeError):
498 Context("")
499 with pytest.raises(ValueError):
500 Context(10)
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400501
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200502 @skip_if_py3
503 def test_method_long(self):
504 """
Alex Chan532b79e2017-01-24 15:14:52 +0000505 On Python 2 `Context` accepts values of type `long` as well as `int`.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200506 """
507 Context(long(TLSv1_METHOD))
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500508
Rick Deane15b1472009-07-09 15:53:42 -0500509 def test_type(self):
510 """
Alex Gaynor01f90a12019-02-07 09:14:48 -0500511 `Context` can be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -0500512 """
Alex Chan532b79e2017-01-24 15:14:52 +0000513 assert is_consistent_type(Context, 'Context', TLSv1_METHOD)
Rick Deane15b1472009-07-09 15:53:42 -0500514
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400515 def test_use_privatekey(self):
516 """
Alex Chan532b79e2017-01-24 15:14:52 +0000517 `Context.use_privatekey` takes an `OpenSSL.crypto.PKey` instance.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400518 """
519 key = PKey()
Alex Gaynor6e9f9762018-05-12 07:44:37 -0400520 key.generate_key(TYPE_RSA, 512)
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400521 ctx = Context(TLSv1_METHOD)
522 ctx.use_privatekey(key)
Alex Chan532b79e2017-01-24 15:14:52 +0000523 with pytest.raises(TypeError):
524 ctx.use_privatekey("")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400525
Alex Chan532b79e2017-01-24 15:14:52 +0000526 def test_use_privatekey_file_missing(self, tmpfile):
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800527 """
Alex Chan532b79e2017-01-24 15:14:52 +0000528 `Context.use_privatekey_file` raises `OpenSSL.SSL.Error` when passed
529 the name of a file which does not exist.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800530 """
531 ctx = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000532 with pytest.raises(Error):
533 ctx.use_privatekey_file(tmpfile)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800534
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400535 def _use_privatekey_file_test(self, pemfile, filetype):
536 """
537 Verify that calling ``Context.use_privatekey_file`` with the given
538 arguments does not raise an exception.
539 """
540 key = PKey()
Alex Gaynor6e9f9762018-05-12 07:44:37 -0400541 key.generate_key(TYPE_RSA, 512)
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400542
543 with open(pemfile, "wt") as pem:
544 pem.write(
545 dump_privatekey(FILETYPE_PEM, key).decode("ascii")
546 )
547
548 ctx = Context(TLSv1_METHOD)
549 ctx.use_privatekey_file(pemfile, filetype)
550
Alex Chanfb078d82017-04-20 11:16:15 +0100551 @pytest.mark.parametrize('filetype', [object(), "", None, 1.0])
552 def test_wrong_privatekey_file_wrong_args(self, tmpfile, filetype):
553 """
554 `Context.use_privatekey_file` raises `TypeError` when called with
555 a `filetype` which is not a valid file encoding.
556 """
557 ctx = Context(TLSv1_METHOD)
558 with pytest.raises(TypeError):
559 ctx.use_privatekey_file(tmpfile, filetype)
560
Alex Chan532b79e2017-01-24 15:14:52 +0000561 def test_use_privatekey_file_bytes(self, tmpfile):
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400562 """
563 A private key can be specified from a file by passing a ``bytes``
564 instance giving the file name to ``Context.use_privatekey_file``.
565 """
566 self._use_privatekey_file_test(
Alex Chan532b79e2017-01-24 15:14:52 +0000567 tmpfile + NON_ASCII.encode(getfilesystemencoding()),
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400568 FILETYPE_PEM,
569 )
570
Alex Chan532b79e2017-01-24 15:14:52 +0000571 def test_use_privatekey_file_unicode(self, tmpfile):
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400572 """
573 A private key can be specified from a file by passing a ``unicode``
574 instance giving the file name to ``Context.use_privatekey_file``.
575 """
576 self._use_privatekey_file_test(
Alex Chan532b79e2017-01-24 15:14:52 +0000577 tmpfile.decode(getfilesystemencoding()) + NON_ASCII,
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400578 FILETYPE_PEM,
579 )
580
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200581 @skip_if_py3
Alex Chan532b79e2017-01-24 15:14:52 +0000582 def test_use_privatekey_file_long(self, tmpfile):
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200583 """
Alex Chan532b79e2017-01-24 15:14:52 +0000584 On Python 2 `Context.use_privatekey_file` accepts a filetype of
585 type `long` as well as `int`.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200586 """
Alex Chan532b79e2017-01-24 15:14:52 +0000587 self._use_privatekey_file_test(tmpfile, long(FILETYPE_PEM))
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500588
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800589 def test_use_certificate_wrong_args(self):
590 """
Alex Chan532b79e2017-01-24 15:14:52 +0000591 `Context.use_certificate_wrong_args` raises `TypeError` when not passed
592 exactly one `OpenSSL.crypto.X509` instance as an argument.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800593 """
594 ctx = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000595 with pytest.raises(TypeError):
596 ctx.use_certificate("hello, world")
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800597
598 def test_use_certificate_uninitialized(self):
599 """
Alex Chan532b79e2017-01-24 15:14:52 +0000600 `Context.use_certificate` raises `OpenSSL.SSL.Error` when passed a
601 `OpenSSL.crypto.X509` instance which has not been initialized
602 (ie, which does not actually have any certificate data).
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800603 """
604 ctx = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000605 with pytest.raises(Error):
606 ctx.use_certificate(X509())
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800607
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800608 def test_use_certificate(self):
609 """
Alex Chan532b79e2017-01-24 15:14:52 +0000610 `Context.use_certificate` sets the certificate which will be
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800611 used to identify connections created using the context.
612 """
613 # TODO
614 # Hard to assert anything. But we could set a privatekey then ask
615 # OpenSSL if the cert and key agree using check_privatekey. Then as
616 # long as check_privatekey works right we're good...
617 ctx = Context(TLSv1_METHOD)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200618 ctx.use_certificate(
619 load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
620 )
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800621
622 def test_use_certificate_file_wrong_args(self):
623 """
Alex Chan532b79e2017-01-24 15:14:52 +0000624 `Context.use_certificate_file` raises `TypeError` if the first
625 argument is not a byte string or the second argument is not an integer.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800626 """
627 ctx = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000628 with pytest.raises(TypeError):
629 ctx.use_certificate_file(object(), FILETYPE_PEM)
630 with pytest.raises(TypeError):
631 ctx.use_certificate_file(b"somefile", object())
632 with pytest.raises(TypeError):
633 ctx.use_certificate_file(object(), FILETYPE_PEM)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800634
Alex Chan532b79e2017-01-24 15:14:52 +0000635 def test_use_certificate_file_missing(self, tmpfile):
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800636 """
Alex Chan532b79e2017-01-24 15:14:52 +0000637 `Context.use_certificate_file` raises `OpenSSL.SSL.Error` if passed
638 the name of a file which does not exist.
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(Error):
642 ctx.use_certificate_file(tmpfile)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800643
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400644 def _use_certificate_file_test(self, certificate_file):
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800645 """
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400646 Verify that calling ``Context.use_certificate_file`` with the given
647 filename doesn't raise an exception.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800648 """
649 # TODO
650 # Hard to assert anything. But we could set a privatekey then ask
651 # OpenSSL if the cert and key agree using check_privatekey. Then as
652 # long as check_privatekey works right we're good...
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400653 with open(certificate_file, "wb") as pem_file:
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800654 pem_file.write(cleartextCertificatePEM)
655
656 ctx = Context(TLSv1_METHOD)
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400657 ctx.use_certificate_file(certificate_file)
658
Alex Chan532b79e2017-01-24 15:14:52 +0000659 def test_use_certificate_file_bytes(self, tmpfile):
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400660 """
Alex Chan532b79e2017-01-24 15:14:52 +0000661 `Context.use_certificate_file` sets the certificate (given as a
662 `bytes` filename) which will be used to identify connections created
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400663 using the context.
664 """
Alex Chan532b79e2017-01-24 15:14:52 +0000665 filename = tmpfile + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400666 self._use_certificate_file_test(filename)
667
Alex Chan532b79e2017-01-24 15:14:52 +0000668 def test_use_certificate_file_unicode(self, tmpfile):
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400669 """
Alex Chan532b79e2017-01-24 15:14:52 +0000670 `Context.use_certificate_file` sets the certificate (given as a
671 `bytes` filename) which will be used to identify connections created
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400672 using the context.
673 """
Alex Chan532b79e2017-01-24 15:14:52 +0000674 filename = tmpfile.decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400675 self._use_certificate_file_test(filename)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800676
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200677 @skip_if_py3
Alex Chan532b79e2017-01-24 15:14:52 +0000678 def test_use_certificate_file_long(self, tmpfile):
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200679 """
Alex Chan532b79e2017-01-24 15:14:52 +0000680 On Python 2 `Context.use_certificate_file` accepts a
681 filetype of type `long` as well as `int`.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200682 """
Alex Chan532b79e2017-01-24 15:14:52 +0000683 pem_filename = tmpfile
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200684 with open(pem_filename, "wb") as pem_file:
685 pem_file.write(cleartextCertificatePEM)
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500686
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200687 ctx = Context(TLSv1_METHOD)
688 ctx.use_certificate_file(pem_filename, long(FILETYPE_PEM))
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500689
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500690 def test_check_privatekey_valid(self):
691 """
Alex Chan532b79e2017-01-24 15:14:52 +0000692 `Context.check_privatekey` returns `None` if the `Context` instance
693 has been configured to use a matched key and certificate pair.
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500694 """
695 key = load_privatekey(FILETYPE_PEM, client_key_pem)
696 cert = load_certificate(FILETYPE_PEM, client_cert_pem)
697 context = Context(TLSv1_METHOD)
698 context.use_privatekey(key)
699 context.use_certificate(cert)
Alex Chan532b79e2017-01-24 15:14:52 +0000700 assert None is context.check_privatekey()
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500701
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500702 def test_check_privatekey_invalid(self):
703 """
Alex Chan532b79e2017-01-24 15:14:52 +0000704 `Context.check_privatekey` raises `Error` if the `Context` instance
705 has been configured to use a key and certificate pair which don't
706 relate to each other.
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500707 """
708 key = load_privatekey(FILETYPE_PEM, client_key_pem)
709 cert = load_certificate(FILETYPE_PEM, server_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 with pytest.raises(Error):
714 context.check_privatekey()
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400715
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400716 def test_app_data(self):
717 """
Alex Chan532b79e2017-01-24 15:14:52 +0000718 `Context.set_app_data` stores an object for later retrieval
719 using `Context.get_app_data`.
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400720 """
721 app_data = object()
722 context = Context(TLSv1_METHOD)
723 context.set_app_data(app_data)
Alex Chan532b79e2017-01-24 15:14:52 +0000724 assert context.get_app_data() is app_data
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400725
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400726 def test_set_options_wrong_args(self):
727 """
Alex Chan532b79e2017-01-24 15:14:52 +0000728 `Context.set_options` raises `TypeError` if called with
729 a non-`int` argument.
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400730 """
731 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000732 with pytest.raises(TypeError):
733 context.set_options(None)
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400734
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500735 def test_set_options(self):
736 """
Alex Chan532b79e2017-01-24 15:14:52 +0000737 `Context.set_options` returns the new options value.
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500738 """
739 context = Context(TLSv1_METHOD)
740 options = context.set_options(OP_NO_SSLv2)
Alex Gaynor2310f8b2016-09-10 14:39:32 -0400741 assert options & OP_NO_SSLv2 == OP_NO_SSLv2
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500742
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200743 @skip_if_py3
744 def test_set_options_long(self):
745 """
Alex Chan532b79e2017-01-24 15:14:52 +0000746 On Python 2 `Context.set_options` accepts values of type
747 `long` as well as `int`.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200748 """
749 context = Context(TLSv1_METHOD)
750 options = context.set_options(long(OP_NO_SSLv2))
Alex Gaynor2310f8b2016-09-10 14:39:32 -0400751 assert options & OP_NO_SSLv2 == OP_NO_SSLv2
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500752
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300753 def test_set_mode_wrong_args(self):
754 """
Alex Chan532b79e2017-01-24 15:14:52 +0000755 `Context.set_mode` raises `TypeError` if called with
756 a non-`int` argument.
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300757 """
758 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000759 with pytest.raises(TypeError):
760 context.set_mode(None)
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300761
Alex Gaynord3b5d9b2016-07-31 10:54:24 -0400762 def test_set_mode(self):
763 """
Alex Chan532b79e2017-01-24 15:14:52 +0000764 `Context.set_mode` accepts a mode bitvector and returns the
Alex Gaynord3b5d9b2016-07-31 10:54:24 -0400765 newly set mode.
766 """
767 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000768 assert MODE_RELEASE_BUFFERS & context.set_mode(MODE_RELEASE_BUFFERS)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500769
Alex Gaynord3b5d9b2016-07-31 10:54:24 -0400770 @skip_if_py3
771 def test_set_mode_long(self):
772 """
Alex Chan532b79e2017-01-24 15:14:52 +0000773 On Python 2 `Context.set_mode` accepts values of type `long` as well
774 as `int`.
Alex Gaynord3b5d9b2016-07-31 10:54:24 -0400775 """
776 context = Context(TLSv1_METHOD)
777 mode = context.set_mode(long(MODE_RELEASE_BUFFERS))
Alex Chan532b79e2017-01-24 15:14:52 +0000778 assert MODE_RELEASE_BUFFERS & mode
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400779
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400780 def test_set_timeout_wrong_args(self):
781 """
Alex Chan532b79e2017-01-24 15:14:52 +0000782 `Context.set_timeout` raises `TypeError` if called with
783 a non-`int` argument.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400784 """
785 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000786 with pytest.raises(TypeError):
787 context.set_timeout(None)
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400788
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400789 def test_timeout(self):
790 """
Alex Chan532b79e2017-01-24 15:14:52 +0000791 `Context.set_timeout` sets the session timeout for all connections
792 created using the context object. `Context.get_timeout` retrieves
793 this value.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400794 """
795 context = Context(TLSv1_METHOD)
796 context.set_timeout(1234)
Alex Chan532b79e2017-01-24 15:14:52 +0000797 assert context.get_timeout() == 1234
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400798
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200799 @skip_if_py3
800 def test_timeout_long(self):
801 """
Alex Chan532b79e2017-01-24 15:14:52 +0000802 On Python 2 `Context.set_timeout` accepts values of type `long` as
803 well as int.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200804 """
805 context = Context(TLSv1_METHOD)
806 context.set_timeout(long(1234))
Alex Chan532b79e2017-01-24 15:14:52 +0000807 assert context.get_timeout() == 1234
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500808
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400809 def test_set_verify_depth_wrong_args(self):
810 """
Alex Chan532b79e2017-01-24 15:14:52 +0000811 `Context.set_verify_depth` raises `TypeError` if called with a
812 non-`int` argument.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400813 """
814 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000815 with pytest.raises(TypeError):
816 context.set_verify_depth(None)
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400817
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400818 def test_verify_depth(self):
819 """
Alex Chan532b79e2017-01-24 15:14:52 +0000820 `Context.set_verify_depth` sets the number of certificates in
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200821 a chain to follow before giving up. The value can be retrieved with
Alex Chan532b79e2017-01-24 15:14:52 +0000822 `Context.get_verify_depth`.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400823 """
824 context = Context(TLSv1_METHOD)
825 context.set_verify_depth(11)
Alex Chan532b79e2017-01-24 15:14:52 +0000826 assert context.get_verify_depth() == 11
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400827
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200828 @skip_if_py3
829 def test_verify_depth_long(self):
830 """
Alex Chan532b79e2017-01-24 15:14:52 +0000831 On Python 2 `Context.set_verify_depth` accepts values of type `long`
832 as well as int.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200833 """
834 context = Context(TLSv1_METHOD)
835 context.set_verify_depth(long(11))
Alex Chan532b79e2017-01-24 15:14:52 +0000836 assert context.get_verify_depth() == 11
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500837
Alex Chan532b79e2017-01-24 15:14:52 +0000838 def _write_encrypted_pem(self, passphrase, tmpfile):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400839 """
840 Write a new private key out to a new file, encrypted using the given
841 passphrase. Return the path to the new file.
842 """
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400843 key = PKey()
Alex Gaynor6e9f9762018-05-12 07:44:37 -0400844 key.generate_key(TYPE_RSA, 512)
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400845 pem = dump_privatekey(FILETYPE_PEM, key, "blowfish", passphrase)
Alex Chan532b79e2017-01-24 15:14:52 +0000846 with open(tmpfile, 'w') as fObj:
847 fObj.write(pem.decode('ascii'))
848 return tmpfile
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400849
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400850 def test_set_passwd_cb_wrong_args(self):
851 """
Alex Chan532b79e2017-01-24 15:14:52 +0000852 `Context.set_passwd_cb` raises `TypeError` if called with a
853 non-callable first argument.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400854 """
855 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000856 with pytest.raises(TypeError):
857 context.set_passwd_cb(None)
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400858
Alex Chan532b79e2017-01-24 15:14:52 +0000859 def test_set_passwd_cb(self, tmpfile):
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400860 """
Alex Chan532b79e2017-01-24 15:14:52 +0000861 `Context.set_passwd_cb` accepts a callable which will be invoked when
862 a private key is loaded from an encrypted PEM.
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400863 """
Alex Gaynore7f51982016-09-11 11:48:14 -0400864 passphrase = b"foobar"
Alex Chan532b79e2017-01-24 15:14:52 +0000865 pemFile = self._write_encrypted_pem(passphrase, tmpfile)
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400866 calledWith = []
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200867
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400868 def passphraseCallback(maxlen, verify, extra):
869 calledWith.append((maxlen, verify, extra))
870 return passphrase
871 context = Context(TLSv1_METHOD)
872 context.set_passwd_cb(passphraseCallback)
873 context.use_privatekey_file(pemFile)
Alex Chan532b79e2017-01-24 15:14:52 +0000874 assert len(calledWith) == 1
875 assert isinstance(calledWith[0][0], int)
876 assert isinstance(calledWith[0][1], int)
877 assert calledWith[0][2] is None
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400878
Alex Chan532b79e2017-01-24 15:14:52 +0000879 def test_passwd_callback_exception(self, tmpfile):
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400880 """
Alex Chan532b79e2017-01-24 15:14:52 +0000881 `Context.use_privatekey_file` propagates any exception raised
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200882 by the passphrase callback.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400883 """
Alex Chan532b79e2017-01-24 15:14:52 +0000884 pemFile = self._write_encrypted_pem(b"monkeys are nice", tmpfile)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200885
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400886 def passphraseCallback(maxlen, verify, extra):
887 raise RuntimeError("Sorry, I am a fail.")
888
889 context = Context(TLSv1_METHOD)
890 context.set_passwd_cb(passphraseCallback)
Alex Chan532b79e2017-01-24 15:14:52 +0000891 with pytest.raises(RuntimeError):
892 context.use_privatekey_file(pemFile)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400893
Alex Chan532b79e2017-01-24 15:14:52 +0000894 def test_passwd_callback_false(self, tmpfile):
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400895 """
Alex Chan532b79e2017-01-24 15:14:52 +0000896 `Context.use_privatekey_file` raises `OpenSSL.SSL.Error` if the
897 passphrase callback returns a false value.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400898 """
Alex Chan532b79e2017-01-24 15:14:52 +0000899 pemFile = self._write_encrypted_pem(b"monkeys are nice", tmpfile)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200900
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400901 def passphraseCallback(maxlen, verify, extra):
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500902 return b""
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400903
904 context = Context(TLSv1_METHOD)
905 context.set_passwd_cb(passphraseCallback)
Alex Chan532b79e2017-01-24 15:14:52 +0000906 with pytest.raises(Error):
907 context.use_privatekey_file(pemFile)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400908
Alex Chan532b79e2017-01-24 15:14:52 +0000909 def test_passwd_callback_non_string(self, tmpfile):
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400910 """
Alex Chan532b79e2017-01-24 15:14:52 +0000911 `Context.use_privatekey_file` raises `OpenSSL.SSL.Error` if the
912 passphrase callback returns a true non-string value.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400913 """
Alex Chan532b79e2017-01-24 15:14:52 +0000914 pemFile = self._write_encrypted_pem(b"monkeys are nice", tmpfile)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200915
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400916 def passphraseCallback(maxlen, verify, extra):
917 return 10
918
919 context = Context(TLSv1_METHOD)
920 context.set_passwd_cb(passphraseCallback)
Alex Chan532b79e2017-01-24 15:14:52 +0000921 # TODO: Surely this is the wrong error?
922 with pytest.raises(ValueError):
923 context.use_privatekey_file(pemFile)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400924
Alex Chan532b79e2017-01-24 15:14:52 +0000925 def test_passwd_callback_too_long(self, tmpfile):
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400926 """
927 If the passphrase returned by the passphrase callback returns a string
928 longer than the indicated maximum length, it is truncated.
929 """
930 # A priori knowledge!
Alex Gaynore7f51982016-09-11 11:48:14 -0400931 passphrase = b"x" * 1024
Alex Chan532b79e2017-01-24 15:14:52 +0000932 pemFile = self._write_encrypted_pem(passphrase, tmpfile)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200933
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400934 def passphraseCallback(maxlen, verify, extra):
935 assert maxlen == 1024
Alex Gaynore7f51982016-09-11 11:48:14 -0400936 return passphrase + b"y"
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400937
938 context = Context(TLSv1_METHOD)
939 context.set_passwd_cb(passphraseCallback)
940 # This shall succeed because the truncated result is the correct
941 # passphrase.
942 context.use_privatekey_file(pemFile)
943
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400944 def test_set_info_callback(self):
945 """
Alex Chan532b79e2017-01-24 15:14:52 +0000946 `Context.set_info_callback` accepts a callable which will be
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200947 invoked when certain information about an SSL connection is available.
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400948 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500949 (server, client) = socket_pair()
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400950
951 clientSSL = Connection(Context(TLSv1_METHOD), client)
952 clientSSL.set_connect_state()
953
954 called = []
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200955
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400956 def info(conn, where, ret):
957 called.append((conn, where, ret))
958 context = Context(TLSv1_METHOD)
959 context.set_info_callback(info)
960 context.use_certificate(
961 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
962 context.use_privatekey(
963 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
964
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400965 serverSSL = Connection(context, server)
966 serverSSL.set_accept_state()
967
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -0500968 handshake(clientSSL, serverSSL)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400969
Jean-Paul Calderone3835e522014-02-02 11:12:30 -0500970 # The callback must always be called with a Connection instance as the
971 # first argument. It would probably be better to split this into
972 # separate tests for client and server side info callbacks so we could
973 # assert it is called with the right Connection instance. It would
974 # also be good to assert *something* about `where` and `ret`.
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -0500975 notConnections = [
976 conn for (conn, where, ret) in called
977 if not isinstance(conn, Connection)]
Alex Chan532b79e2017-01-24 15:14:52 +0000978 assert [] == notConnections, (
979 "Some info callback arguments were not Connection instances.")
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400980
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400981 def _load_verify_locations_test(self, *args):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400982 """
983 Create a client context which will verify the peer certificate and call
Alex Chan532b79e2017-01-24 15:14:52 +0000984 its `load_verify_locations` method with the given arguments.
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -0400985 Then connect it to a server and ensure that the handshake succeeds.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400986 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500987 (server, client) = socket_pair()
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400988
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400989 clientContext = Context(TLSv1_METHOD)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400990 clientContext.load_verify_locations(*args)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400991 # Require that the server certificate verify properly or the
992 # connection will fail.
993 clientContext.set_verify(
994 VERIFY_PEER,
995 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
996
997 clientSSL = Connection(clientContext, client)
998 clientSSL.set_connect_state()
999
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001000 serverContext = Context(TLSv1_METHOD)
1001 serverContext.use_certificate(
1002 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1003 serverContext.use_privatekey(
1004 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1005
1006 serverSSL = Connection(serverContext, server)
1007 serverSSL.set_accept_state()
1008
Jean-Paul Calderonef8742032010-09-25 00:00:32 -04001009 # Without load_verify_locations above, the handshake
1010 # will fail:
1011 # Error: [('SSL routines', 'SSL3_GET_SERVER_CERTIFICATE',
1012 # 'certificate verify failed')]
1013 handshake(clientSSL, serverSSL)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001014
1015 cert = clientSSL.get_peer_certificate()
Alex Chan532b79e2017-01-24 15:14:52 +00001016 assert cert.get_subject().CN == 'Testing Root CA'
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -04001017
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001018 def _load_verify_cafile(self, cafile):
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001019 """
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001020 Verify that if path to a file containing a certificate is passed to
Alex Chan532b79e2017-01-24 15:14:52 +00001021 `Context.load_verify_locations` for the ``cafile`` parameter, that
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001022 certificate is used as a trust root for the purposes of verifying
Alex Chan532b79e2017-01-24 15:14:52 +00001023 connections created using that `Context`.
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001024 """
Alex Chan532b79e2017-01-24 15:14:52 +00001025 with open(cafile, 'w') as fObj:
1026 fObj.write(cleartextCertificatePEM.decode('ascii'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001027
1028 self._load_verify_locations_test(cafile)
1029
Alex Chan532b79e2017-01-24 15:14:52 +00001030 def test_load_verify_bytes_cafile(self, tmpfile):
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001031 """
Alex Chan532b79e2017-01-24 15:14:52 +00001032 `Context.load_verify_locations` accepts a file name as a `bytes`
1033 instance and uses the certificates within for verification purposes.
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001034 """
Alex Chan532b79e2017-01-24 15:14:52 +00001035 cafile = tmpfile + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001036 self._load_verify_cafile(cafile)
1037
Alex Chan532b79e2017-01-24 15:14:52 +00001038 def test_load_verify_unicode_cafile(self, tmpfile):
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001039 """
Alex Chan532b79e2017-01-24 15:14:52 +00001040 `Context.load_verify_locations` accepts a file name as a `unicode`
1041 instance and uses the certificates within for verification purposes.
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001042 """
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001043 self._load_verify_cafile(
Alex Chan532b79e2017-01-24 15:14:52 +00001044 tmpfile.decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001045 )
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001046
Alex Chan532b79e2017-01-24 15:14:52 +00001047 def test_load_verify_invalid_file(self, tmpfile):
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -04001048 """
Alex Chan532b79e2017-01-24 15:14:52 +00001049 `Context.load_verify_locations` raises `Error` when passed a
1050 non-existent cafile.
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -04001051 """
1052 clientContext = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001053 with pytest.raises(Error):
1054 clientContext.load_verify_locations(tmpfile)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001055
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001056 def _load_verify_directory_locations_capath(self, capath):
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001057 """
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001058 Verify that if path to a directory containing certificate files is
1059 passed to ``Context.load_verify_locations`` for the ``capath``
1060 parameter, those certificates are used as trust roots for the purposes
1061 of verifying connections created using that ``Context``.
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001062 """
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001063 makedirs(capath)
Jean-Paul Calderone24dfb332011-05-04 18:10:26 -04001064 # Hash values computed manually with c_rehash to avoid depending on
1065 # c_rehash in the test suite. One is from OpenSSL 0.9.8, the other
1066 # from OpenSSL 1.0.0.
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001067 for name in [b'c7adac82.0', b'c3705638.0']:
Jean-Paul Calderone05826732015-04-12 11:38:49 -04001068 cafile = join_bytes_or_unicode(capath, name)
1069 with open(cafile, 'w') as fObj:
1070 fObj.write(cleartextCertificatePEM.decode('ascii'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001071
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001072 self._load_verify_locations_test(None, capath)
1073
Alex Chan532b79e2017-01-24 15:14:52 +00001074 def test_load_verify_directory_bytes_capath(self, tmpfile):
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001075 """
Alex Chan532b79e2017-01-24 15:14:52 +00001076 `Context.load_verify_locations` accepts a directory name as a `bytes`
1077 instance and uses the certificates within for verification purposes.
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001078 """
1079 self._load_verify_directory_locations_capath(
Alex Chan532b79e2017-01-24 15:14:52 +00001080 tmpfile + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001081 )
1082
Alex Chan532b79e2017-01-24 15:14:52 +00001083 def test_load_verify_directory_unicode_capath(self, tmpfile):
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001084 """
Alex Chan532b79e2017-01-24 15:14:52 +00001085 `Context.load_verify_locations` accepts a directory name as a `unicode`
1086 instance and uses the certificates within for verification purposes.
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001087 """
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001088 self._load_verify_directory_locations_capath(
Alex Chan532b79e2017-01-24 15:14:52 +00001089 tmpfile.decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001090 )
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001091
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001092 def test_load_verify_locations_wrong_args(self):
1093 """
Alex Chan532b79e2017-01-24 15:14:52 +00001094 `Context.load_verify_locations` raises `TypeError` if with non-`str`
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001095 arguments.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001096 """
1097 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001098 with pytest.raises(TypeError):
1099 context.load_verify_locations(object())
1100 with pytest.raises(TypeError):
1101 context.load_verify_locations(object(), object())
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001102
Hynek Schlawack734d3022015-09-05 19:19:32 +02001103 @pytest.mark.skipif(
Paul Kehrer55fb3412017-06-29 18:44:08 -05001104 not platform.startswith("linux"),
1105 reason="Loading fallback paths is a linux-specific behavior to "
1106 "accommodate pyca/cryptography manylinux1 wheels"
1107 )
1108 def test_fallback_default_verify_paths(self, monkeypatch):
1109 """
1110 Test that we load certificates successfully on linux from the fallback
1111 path. To do this we set the _CRYPTOGRAPHY_MANYLINUX1_CA_FILE and
1112 _CRYPTOGRAPHY_MANYLINUX1_CA_DIR vars to be equal to whatever the
1113 current OpenSSL default is and we disable
1114 SSL_CTX_SET_default_verify_paths so that it can't find certs unless
1115 it loads via fallback.
1116 """
1117 context = Context(TLSv1_METHOD)
1118 monkeypatch.setattr(
1119 _lib, "SSL_CTX_set_default_verify_paths", lambda x: 1
1120 )
1121 monkeypatch.setattr(
1122 SSL,
1123 "_CRYPTOGRAPHY_MANYLINUX1_CA_FILE",
1124 _ffi.string(_lib.X509_get_default_cert_file())
1125 )
1126 monkeypatch.setattr(
1127 SSL,
1128 "_CRYPTOGRAPHY_MANYLINUX1_CA_DIR",
1129 _ffi.string(_lib.X509_get_default_cert_dir())
1130 )
1131 context.set_default_verify_paths()
1132 store = context.get_cert_store()
1133 sk_obj = _lib.X509_STORE_get0_objects(store._store)
1134 assert sk_obj != _ffi.NULL
1135 num = _lib.sk_X509_OBJECT_num(sk_obj)
1136 assert num != 0
1137
1138 def test_check_env_vars(self, monkeypatch):
1139 """
1140 Test that we return True/False appropriately if the env vars are set.
1141 """
1142 context = Context(TLSv1_METHOD)
1143 dir_var = "CUSTOM_DIR_VAR"
1144 file_var = "CUSTOM_FILE_VAR"
1145 assert context._check_env_vars_set(dir_var, file_var) is False
1146 monkeypatch.setenv(dir_var, "value")
1147 monkeypatch.setenv(file_var, "value")
1148 assert context._check_env_vars_set(dir_var, file_var) is True
1149 assert context._check_env_vars_set(dir_var, file_var) is True
1150
1151 def test_verify_no_fallback_if_env_vars_set(self, monkeypatch):
1152 """
1153 Test that we don't use the fallback path if env vars are set.
1154 """
1155 context = Context(TLSv1_METHOD)
1156 monkeypatch.setattr(
1157 _lib, "SSL_CTX_set_default_verify_paths", lambda x: 1
1158 )
1159 dir_env_var = _ffi.string(
1160 _lib.X509_get_default_cert_dir_env()
1161 ).decode("ascii")
1162 file_env_var = _ffi.string(
1163 _lib.X509_get_default_cert_file_env()
1164 ).decode("ascii")
1165 monkeypatch.setenv(dir_env_var, "value")
1166 monkeypatch.setenv(file_env_var, "value")
1167 context.set_default_verify_paths()
1168
1169 monkeypatch.setattr(
1170 context,
1171 "_fallback_default_verify_paths",
1172 raiser(SystemError)
1173 )
1174 context.set_default_verify_paths()
1175
1176 @pytest.mark.skipif(
Hynek Schlawack734d3022015-09-05 19:19:32 +02001177 platform == "win32",
1178 reason="set_default_verify_paths appears not to work on Windows. "
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -04001179 "See LP#404343 and LP#404344."
Hynek Schlawack734d3022015-09-05 19:19:32 +02001180 )
1181 def test_set_default_verify_paths(self):
1182 """
Alex Chan532b79e2017-01-24 15:14:52 +00001183 `Context.set_default_verify_paths` causes the platform-specific CA
1184 certificate locations to be used for verification purposes.
Hynek Schlawack734d3022015-09-05 19:19:32 +02001185 """
1186 # Testing this requires a server with a certificate signed by one
1187 # of the CAs in the platform CA location. Getting one of those
1188 # costs money. Fortunately (or unfortunately, depending on your
1189 # perspective), it's easy to think of a public server on the
1190 # internet which has such a certificate. Connecting to the network
1191 # in a unit test is bad, but it's the only way I can think of to
1192 # really test this. -exarkun
Hynek Schlawackbf887932015-10-21 17:13:47 +02001193 context = Context(SSLv23_METHOD)
Hynek Schlawack734d3022015-09-05 19:19:32 +02001194 context.set_default_verify_paths()
1195 context.set_verify(
1196 VERIFY_PEER,
1197 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001198
Hynek Schlawack734d3022015-09-05 19:19:32 +02001199 client = socket()
Hynek Schlawackbf887932015-10-21 17:13:47 +02001200 client.connect(("encrypted.google.com", 443))
Hynek Schlawack734d3022015-09-05 19:19:32 +02001201 clientSSL = Connection(context, client)
1202 clientSSL.set_connect_state()
Alex Gaynor373926c2018-05-12 07:43:07 -04001203 clientSSL.set_tlsext_host_name(b"encrypted.google.com")
Hynek Schlawack734d3022015-09-05 19:19:32 +02001204 clientSSL.do_handshake()
1205 clientSSL.send(b"GET / HTTP/1.0\r\n\r\n")
Alex Chan532b79e2017-01-24 15:14:52 +00001206 assert clientSSL.recv(1024)
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05001207
Paul Kehrer55fb3412017-06-29 18:44:08 -05001208 def test_fallback_path_is_not_file_or_dir(self):
1209 """
1210 Test that when passed empty arrays or paths that do not exist no
1211 errors are raised.
1212 """
1213 context = Context(TLSv1_METHOD)
1214 context._fallback_default_verify_paths([], [])
1215 context._fallback_default_verify_paths(
1216 ["/not/a/file"], ["/not/a/dir"]
1217 )
1218
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001219 def test_add_extra_chain_cert_invalid_cert(self):
1220 """
Alex Chan532b79e2017-01-24 15:14:52 +00001221 `Context.add_extra_chain_cert` raises `TypeError` if called with an
1222 object which is not an instance of `X509`.
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001223 """
1224 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001225 with pytest.raises(TypeError):
1226 context.add_extra_chain_cert(object())
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001227
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001228 def _handshake_test(self, serverContext, clientContext):
1229 """
1230 Verify that a client and server created with the given contexts can
1231 successfully handshake and communicate.
1232 """
1233 serverSocket, clientSocket = socket_pair()
1234
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001235 server = Connection(serverContext, serverSocket)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001236 server.set_accept_state()
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001237
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001238 client = Connection(clientContext, clientSocket)
1239 client.set_connect_state()
1240
1241 # Make them talk to each other.
Alex Chan532b79e2017-01-24 15:14:52 +00001242 # interact_in_memory(client, server)
1243 for _ in range(3):
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001244 for s in [client, server]:
1245 try:
1246 s.do_handshake()
1247 except WantReadError:
1248 pass
1249
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001250 def test_set_verify_callback_connection_argument(self):
1251 """
1252 The first argument passed to the verify callback is the
Alex Chan532b79e2017-01-24 15:14:52 +00001253 `Connection` instance for which verification is taking place.
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001254 """
1255 serverContext = Context(TLSv1_METHOD)
1256 serverContext.use_privatekey(
1257 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1258 serverContext.use_certificate(
1259 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1260 serverConnection = Connection(serverContext, None)
1261
1262 class VerifyCallback(object):
1263 def callback(self, connection, *args):
1264 self.connection = connection
1265 return 1
1266
1267 verify = VerifyCallback()
1268 clientContext = Context(TLSv1_METHOD)
1269 clientContext.set_verify(VERIFY_PEER, verify.callback)
1270 clientConnection = Connection(clientContext, None)
1271 clientConnection.set_connect_state()
1272
Alex Chan532b79e2017-01-24 15:14:52 +00001273 handshake_in_memory(clientConnection, serverConnection)
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001274
Alex Chan532b79e2017-01-24 15:14:52 +00001275 assert verify.connection is clientConnection
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001276
Paul Kehrere7381862017-11-30 20:55:25 +08001277 def test_x509_in_verify_works(self):
1278 """
1279 We had a bug where the X509 cert instantiated in the callback wrapper
1280 didn't __init__ so it was missing objects needed when calling
1281 get_subject. This test sets up a handshake where we call get_subject
1282 on the cert provided to the verify callback.
1283 """
1284 serverContext = Context(TLSv1_METHOD)
1285 serverContext.use_privatekey(
1286 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1287 serverContext.use_certificate(
1288 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1289 serverConnection = Connection(serverContext, None)
1290
1291 def verify_cb_get_subject(conn, cert, errnum, depth, ok):
1292 assert cert.get_subject()
1293 return 1
1294
1295 clientContext = Context(TLSv1_METHOD)
1296 clientContext.set_verify(VERIFY_PEER, verify_cb_get_subject)
1297 clientConnection = Connection(clientContext, None)
1298 clientConnection.set_connect_state()
1299
1300 handshake_in_memory(clientConnection, serverConnection)
1301
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001302 def test_set_verify_callback_exception(self):
1303 """
Alex Chan532b79e2017-01-24 15:14:52 +00001304 If the verify callback passed to `Context.set_verify` raises an
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001305 exception, verification fails and the exception is propagated to the
Alex Chan532b79e2017-01-24 15:14:52 +00001306 caller of `Connection.do_handshake`.
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001307 """
Paul Kehrer7d5a3bf2019-01-21 12:24:02 -06001308 serverContext = Context(TLSv1_2_METHOD)
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001309 serverContext.use_privatekey(
1310 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1311 serverContext.use_certificate(
1312 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1313
Paul Kehrer7d5a3bf2019-01-21 12:24:02 -06001314 clientContext = Context(TLSv1_2_METHOD)
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001315
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001316 def verify_callback(*args):
1317 raise Exception("silly verify failure")
1318 clientContext.set_verify(VERIFY_PEER, verify_callback)
1319
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01001320 with pytest.raises(Exception) as exc:
1321 self._handshake_test(serverContext, clientContext)
1322
Alex Chan532b79e2017-01-24 15:14:52 +00001323 assert "silly verify failure" == str(exc.value)
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001324
Alex Chan532b79e2017-01-24 15:14:52 +00001325 def test_add_extra_chain_cert(self, tmpdir):
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001326 """
Alex Chan532b79e2017-01-24 15:14:52 +00001327 `Context.add_extra_chain_cert` accepts an `X509`
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001328 instance to add to the certificate chain.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001329
Alex Chan532b79e2017-01-24 15:14:52 +00001330 See `_create_certificate_chain` for the details of the
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001331 certificate chain tested.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001332
1333 The chain is tested by starting a server with scert and connecting
1334 to it with a client which trusts cacert and requires verification to
1335 succeed.
1336 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001337 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001338 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1339
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001340 # Dump the CA certificate to a file because that's the only way to load
1341 # it as a trusted CA in the client context.
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001342 for cert, name in [(cacert, 'ca.pem'),
1343 (icert, 'i.pem'),
1344 (scert, 's.pem')]:
Alex Chan532b79e2017-01-24 15:14:52 +00001345 with tmpdir.join(name).open('w') as f:
Hynek Schlawacke90680f2015-04-16 15:09:27 -04001346 f.write(dump_certificate(FILETYPE_PEM, cert).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001347
Hynek Schlawack1902c012015-04-16 15:06:41 -04001348 for key, name in [(cakey, 'ca.key'),
1349 (ikey, 'i.key'),
1350 (skey, 's.key')]:
Alex Chan532b79e2017-01-24 15:14:52 +00001351 with tmpdir.join(name).open('w') as f:
Hynek Schlawacke90680f2015-04-16 15:09:27 -04001352 f.write(dump_privatekey(FILETYPE_PEM, key).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001353
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001354 # Create the server context
1355 serverContext = Context(TLSv1_METHOD)
1356 serverContext.use_privatekey(skey)
1357 serverContext.use_certificate(scert)
Jean-Paul Calderone16cf03d2010-09-08 18:53:39 -04001358 # The client already has cacert, we only need to give them icert.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001359 serverContext.add_extra_chain_cert(icert)
1360
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001361 # Create the client
1362 clientContext = Context(TLSv1_METHOD)
1363 clientContext.set_verify(
1364 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Alex Chan532b79e2017-01-24 15:14:52 +00001365 clientContext.load_verify_locations(str(tmpdir.join("ca.pem")))
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001366
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001367 # Try it out.
1368 self._handshake_test(serverContext, clientContext)
1369
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001370 def _use_certificate_chain_file_test(self, certdir):
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001371 """
Alex Chan532b79e2017-01-24 15:14:52 +00001372 Verify that `Context.use_certificate_chain_file` reads a
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001373 certificate chain from a specified file.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001374
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001375 The chain is tested by starting a server with scert and connecting to
1376 it with a client which trusts cacert and requires verification to
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001377 succeed.
1378 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001379 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001380 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1381
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001382 makedirs(certdir)
1383
Jean-Paul Calderone05826732015-04-12 11:38:49 -04001384 chainFile = join_bytes_or_unicode(certdir, "chain.pem")
1385 caFile = join_bytes_or_unicode(certdir, "ca.pem")
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001386
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001387 # Write out the chain file.
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001388 with open(chainFile, 'wb') as fObj:
1389 # Most specific to least general.
1390 fObj.write(dump_certificate(FILETYPE_PEM, scert))
1391 fObj.write(dump_certificate(FILETYPE_PEM, icert))
1392 fObj.write(dump_certificate(FILETYPE_PEM, cacert))
1393
1394 with open(caFile, 'w') as fObj:
1395 fObj.write(dump_certificate(FILETYPE_PEM, cacert).decode('ascii'))
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001396
1397 serverContext = Context(TLSv1_METHOD)
1398 serverContext.use_certificate_chain_file(chainFile)
1399 serverContext.use_privatekey(skey)
1400
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001401 clientContext = Context(TLSv1_METHOD)
1402 clientContext.set_verify(
1403 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001404 clientContext.load_verify_locations(caFile)
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001405
1406 self._handshake_test(serverContext, clientContext)
1407
Alex Chan532b79e2017-01-24 15:14:52 +00001408 def test_use_certificate_chain_file_bytes(self, tmpfile):
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001409 """
1410 ``Context.use_certificate_chain_file`` accepts the name of a file (as
1411 an instance of ``bytes``) to specify additional certificates to use to
1412 construct and verify a trust chain.
1413 """
1414 self._use_certificate_chain_file_test(
Alex Chan532b79e2017-01-24 15:14:52 +00001415 tmpfile + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001416 )
1417
Alex Chan532b79e2017-01-24 15:14:52 +00001418 def test_use_certificate_chain_file_unicode(self, tmpfile):
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001419 """
1420 ``Context.use_certificate_chain_file`` accepts the name of a file (as
1421 an instance of ``unicode``) to specify additional certificates to use
1422 to construct and verify a trust chain.
1423 """
1424 self._use_certificate_chain_file_test(
Alex Chan532b79e2017-01-24 15:14:52 +00001425 tmpfile.decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001426 )
1427
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001428 def test_use_certificate_chain_file_wrong_args(self):
1429 """
Alex Chan532b79e2017-01-24 15:14:52 +00001430 `Context.use_certificate_chain_file` raises `TypeError` if passed a
1431 non-byte string single argument.
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001432 """
1433 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001434 with pytest.raises(TypeError):
1435 context.use_certificate_chain_file(object())
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001436
Alex Chan532b79e2017-01-24 15:14:52 +00001437 def test_use_certificate_chain_file_missing_file(self, tmpfile):
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001438 """
Alex Chan532b79e2017-01-24 15:14:52 +00001439 `Context.use_certificate_chain_file` raises `OpenSSL.SSL.Error` when
1440 passed a bad chain file name (for example, the name of a file which
1441 does not exist).
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001442 """
1443 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001444 with pytest.raises(Error):
1445 context.use_certificate_chain_file(tmpfile)
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001446
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001447 def test_set_verify_mode(self):
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001448 """
Alex Chan532b79e2017-01-24 15:14:52 +00001449 `Context.get_verify_mode` returns the verify mode flags previously
1450 passed to `Context.set_verify`.
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001451 """
1452 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001453 assert context.get_verify_mode() == 0
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001454 context.set_verify(
1455 VERIFY_PEER | VERIFY_CLIENT_ONCE, lambda *args: None)
Alex Chan532b79e2017-01-24 15:14:52 +00001456 assert context.get_verify_mode() == (VERIFY_PEER | VERIFY_CLIENT_ONCE)
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001457
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001458 @skip_if_py3
1459 def test_set_verify_mode_long(self):
1460 """
Alex Chan532b79e2017-01-24 15:14:52 +00001461 On Python 2 `Context.set_verify_mode` accepts values of type `long`
1462 as well as `int`.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001463 """
1464 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001465 assert context.get_verify_mode() == 0
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001466 context.set_verify(
Hynek Schlawackb4ceed32015-09-05 20:55:19 +02001467 long(VERIFY_PEER | VERIFY_CLIENT_ONCE), lambda *args: None
1468 ) # pragma: nocover
Alex Chan532b79e2017-01-24 15:14:52 +00001469 assert context.get_verify_mode() == (VERIFY_PEER | VERIFY_CLIENT_ONCE)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001470
Alex Chanfb078d82017-04-20 11:16:15 +01001471 @pytest.mark.parametrize('mode', [None, 1.0, object(), 'mode'])
1472 def test_set_verify_wrong_mode_arg(self, mode):
1473 """
1474 `Context.set_verify` raises `TypeError` if the first argument is
1475 not an integer.
1476 """
1477 context = Context(TLSv1_METHOD)
1478 with pytest.raises(TypeError):
1479 context.set_verify(mode=mode, callback=lambda *args: None)
1480
1481 @pytest.mark.parametrize('callback', [None, 1.0, 'mode', ('foo', 'bar')])
1482 def test_set_verify_wrong_callable_arg(self, callback):
1483 """
Alex Gaynor40bc0f12018-05-14 14:06:16 -04001484 `Context.set_verify` raises `TypeError` if the second argument
Alex Chanfb078d82017-04-20 11:16:15 +01001485 is not callable.
1486 """
1487 context = Context(TLSv1_METHOD)
1488 with pytest.raises(TypeError):
1489 context.set_verify(mode=VERIFY_PEER, callback=callback)
1490
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001491 def test_load_tmp_dh_wrong_args(self):
1492 """
Alex Chan532b79e2017-01-24 15:14:52 +00001493 `Context.load_tmp_dh` raises `TypeError` if called with a
1494 non-`str` argument.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001495 """
1496 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001497 with pytest.raises(TypeError):
1498 context.load_tmp_dh(object())
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001499
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001500 def test_load_tmp_dh_missing_file(self):
1501 """
Alex Chan532b79e2017-01-24 15:14:52 +00001502 `Context.load_tmp_dh` raises `OpenSSL.SSL.Error` if the
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001503 specified file does not exist.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001504 """
1505 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001506 with pytest.raises(Error):
1507 context.load_tmp_dh(b"hello")
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001508
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001509 def _load_tmp_dh_test(self, dhfilename):
Jean-Paul Calderone4e0c43f2015-04-13 10:15:17 -04001510 """
1511 Verify that calling ``Context.load_tmp_dh`` with the given filename
1512 does not raise an exception.
1513 """
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001514 context = Context(TLSv1_METHOD)
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001515 with open(dhfilename, "w") as dhfile:
1516 dhfile.write(dhparam)
1517
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001518 context.load_tmp_dh(dhfilename)
1519 # XXX What should I assert here? -exarkun
1520
Alex Chan532b79e2017-01-24 15:14:52 +00001521 def test_load_tmp_dh_bytes(self, tmpfile):
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001522 """
Alex Chan532b79e2017-01-24 15:14:52 +00001523 `Context.load_tmp_dh` loads Diffie-Hellman parameters from the
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001524 specified file (given as ``bytes``).
1525 """
1526 self._load_tmp_dh_test(
Alex Chan532b79e2017-01-24 15:14:52 +00001527 tmpfile + NON_ASCII.encode(getfilesystemencoding()),
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001528 )
1529
Alex Chan532b79e2017-01-24 15:14:52 +00001530 def test_load_tmp_dh_unicode(self, tmpfile):
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001531 """
Alex Chan532b79e2017-01-24 15:14:52 +00001532 `Context.load_tmp_dh` loads Diffie-Hellman parameters from the
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001533 specified file (given as ``unicode``).
1534 """
1535 self._load_tmp_dh_test(
Alex Chan532b79e2017-01-24 15:14:52 +00001536 tmpfile.decode(getfilesystemencoding()) + NON_ASCII,
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001537 )
1538
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001539 def test_set_tmp_ecdh(self):
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001540 """
Alex Chan532b79e2017-01-24 15:14:52 +00001541 `Context.set_tmp_ecdh` sets the elliptic curve for Diffie-Hellman to
1542 the specified curve.
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001543 """
1544 context = Context(TLSv1_METHOD)
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001545 for curve in get_elliptic_curves():
Hynek Schlawacka07fa8c2015-10-17 10:15:28 +02001546 if curve.name.startswith(u"Oakley-"):
Hynek Schlawack7408aff2015-10-17 09:51:16 +02001547 # Setting Oakley-EC2N-4 and Oakley-EC2N-3 adds
1548 # ('bignum routines', 'BN_mod_inverse', 'no inverse') to the
1549 # error queue on OpenSSL 1.0.2.
1550 continue
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001551 # The only easily "assertable" thing is that it does not raise an
1552 # exception.
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001553 context.set_tmp_ecdh(curve)
Alex Gaynor12dc0842014-01-17 12:51:31 -06001554
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001555 def test_set_session_cache_mode_wrong_args(self):
1556 """
Alex Chan532b79e2017-01-24 15:14:52 +00001557 `Context.set_session_cache_mode` raises `TypeError` if called with
1558 a non-integer argument.
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001559 called with other than one integer argument.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001560 """
1561 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001562 with pytest.raises(TypeError):
1563 context.set_session_cache_mode(object())
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001564
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001565 def test_session_cache_mode(self):
1566 """
Alex Chan532b79e2017-01-24 15:14:52 +00001567 `Context.set_session_cache_mode` specifies how sessions are cached.
1568 The setting can be retrieved via `Context.get_session_cache_mode`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001569 """
1570 context = Context(TLSv1_METHOD)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001571 context.set_session_cache_mode(SESS_CACHE_OFF)
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001572 off = context.set_session_cache_mode(SESS_CACHE_BOTH)
Alex Chan532b79e2017-01-24 15:14:52 +00001573 assert SESS_CACHE_OFF == off
1574 assert SESS_CACHE_BOTH == context.get_session_cache_mode()
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001575
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001576 @skip_if_py3
1577 def test_session_cache_mode_long(self):
1578 """
Alex Chan532b79e2017-01-24 15:14:52 +00001579 On Python 2 `Context.set_session_cache_mode` accepts values
1580 of type `long` as well as `int`.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001581 """
1582 context = Context(TLSv1_METHOD)
1583 context.set_session_cache_mode(long(SESS_CACHE_BOTH))
Alex Chan532b79e2017-01-24 15:14:52 +00001584 assert SESS_CACHE_BOTH == context.get_session_cache_mode()
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001585
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001586 def test_get_cert_store(self):
1587 """
Alex Chan532b79e2017-01-24 15:14:52 +00001588 `Context.get_cert_store` returns a `X509Store` instance.
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001589 """
1590 context = Context(TLSv1_METHOD)
1591 store = context.get_cert_store()
Alex Chan532b79e2017-01-24 15:14:52 +00001592 assert isinstance(store, X509Store)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001593
Jeremy Lainé02261ad2018-05-16 18:33:25 +02001594 def test_set_tlsext_use_srtp_not_bytes(self):
1595 """
1596 `Context.set_tlsext_use_srtp' enables negotiating SRTP keying material.
1597
1598 It raises a TypeError if the list of profiles is not a byte string.
1599 """
1600 context = Context(TLSv1_METHOD)
1601 with pytest.raises(TypeError):
1602 context.set_tlsext_use_srtp(text_type('SRTP_AES128_CM_SHA1_80'))
1603
1604 def test_set_tlsext_use_srtp_invalid_profile(self):
1605 """
1606 `Context.set_tlsext_use_srtp' enables negotiating SRTP keying material.
1607
1608 It raises an Error if the call to OpenSSL fails.
1609 """
1610 context = Context(TLSv1_METHOD)
1611 with pytest.raises(Error):
1612 context.set_tlsext_use_srtp(b'SRTP_BOGUS')
1613
1614 def test_set_tlsext_use_srtp_valid(self):
1615 """
1616 `Context.set_tlsext_use_srtp' enables negotiating SRTP keying material.
1617
1618 It does not return anything.
1619 """
1620 context = Context(TLSv1_METHOD)
1621 assert context.set_tlsext_use_srtp(b'SRTP_AES128_CM_SHA1_80') is None
1622
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001623
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001624class TestServerNameCallback(object):
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001625 """
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001626 Tests for `Context.set_tlsext_servername_callback` and its
1627 interaction with `Connection`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001628 """
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001629 def test_old_callback_forgotten(self):
1630 """
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001631 If `Context.set_tlsext_servername_callback` is used to specify
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001632 a new callback, the one it replaces is dereferenced.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001633 """
Alex Chanfb078d82017-04-20 11:16:15 +01001634 def callback(connection): # pragma: no cover
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001635 pass
1636
Alex Chanfb078d82017-04-20 11:16:15 +01001637 def replacement(connection): # pragma: no cover
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001638 pass
1639
1640 context = Context(TLSv1_METHOD)
1641 context.set_tlsext_servername_callback(callback)
1642
1643 tracker = ref(callback)
1644 del callback
1645
1646 context.set_tlsext_servername_callback(replacement)
Jean-Paul Calderoned4033eb2014-01-11 08:21:46 -05001647
1648 # One run of the garbage collector happens to work on CPython. PyPy
1649 # doesn't collect the underlying object until a second run for whatever
1650 # reason. That's fine, it still demonstrates our code has properly
1651 # dropped the reference.
1652 collect()
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001653 collect()
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001654
1655 callback = tracker()
1656 if callback is not None:
1657 referrers = get_referrers(callback)
Alex Chanfb078d82017-04-20 11:16:15 +01001658 if len(referrers) > 1: # pragma: nocover
1659 pytest.fail("Some references remain: %r" % (referrers,))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001660
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001661 def test_no_servername(self):
1662 """
1663 When a client specifies no server name, the callback passed to
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001664 `Context.set_tlsext_servername_callback` is invoked and the
1665 result of `Connection.get_servername` is `None`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001666 """
1667 args = []
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001668
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001669 def servername(conn):
1670 args.append((conn, conn.get_servername()))
1671 context = Context(TLSv1_METHOD)
1672 context.set_tlsext_servername_callback(servername)
1673
1674 # Lose our reference to it. The Context is responsible for keeping it
1675 # alive now.
1676 del servername
1677 collect()
1678
1679 # Necessary to actually accept the connection
1680 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001681 context.use_certificate(
1682 load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001683
1684 # Do a little connection to trigger the logic
1685 server = Connection(context, None)
1686 server.set_accept_state()
1687
1688 client = Connection(Context(TLSv1_METHOD), None)
1689 client.set_connect_state()
1690
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001691 interact_in_memory(server, client)
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001692
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001693 assert args == [(server, None)]
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001694
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001695 def test_servername(self):
1696 """
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001697 When a client specifies a server name in its hello message, the
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001698 callback passed to `Contexts.set_tlsext_servername_callback` is
1699 invoked and the result of `Connection.get_servername` is that
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001700 server name.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001701 """
1702 args = []
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001703
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001704 def servername(conn):
1705 args.append((conn, conn.get_servername()))
1706 context = Context(TLSv1_METHOD)
1707 context.set_tlsext_servername_callback(servername)
1708
1709 # Necessary to actually accept the connection
1710 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001711 context.use_certificate(
1712 load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001713
1714 # Do a little connection to trigger the logic
1715 server = Connection(context, None)
1716 server.set_accept_state()
1717
1718 client = Connection(Context(TLSv1_METHOD), None)
1719 client.set_connect_state()
Alex Gaynore7f51982016-09-11 11:48:14 -04001720 client.set_tlsext_host_name(b"foo1.example.com")
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001721
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001722 interact_in_memory(server, client)
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001723
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001724 assert args == [(server, b"foo1.example.com")]
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001725
1726
Alex Chan9e08b3e2016-11-10 12:18:54 +00001727class TestNextProtoNegotiation(object):
Cory Benfield84a121e2014-03-31 20:30:25 +01001728 """
1729 Test for Next Protocol Negotiation in PyOpenSSL.
1730 """
Alex Chan9e08b3e2016-11-10 12:18:54 +00001731 def test_npn_success(self):
1732 """
1733 Tests that clients and servers that agree on the negotiated next
1734 protocol can correct establish a connection, and that the agreed
1735 protocol is reported by the connections.
1736 """
1737 advertise_args = []
1738 select_args = []
1739
1740 def advertise(conn):
1741 advertise_args.append((conn,))
1742 return [b'http/1.1', b'spdy/2']
1743
1744 def select(conn, options):
1745 select_args.append((conn, options))
1746 return b'spdy/2'
1747
1748 server_context = Context(TLSv1_METHOD)
1749 server_context.set_npn_advertise_callback(advertise)
1750
1751 client_context = Context(TLSv1_METHOD)
1752 client_context.set_npn_select_callback(select)
1753
1754 # Necessary to actually accept the connection
1755 server_context.use_privatekey(
1756 load_privatekey(FILETYPE_PEM, server_key_pem))
1757 server_context.use_certificate(
1758 load_certificate(FILETYPE_PEM, server_cert_pem))
1759
1760 # Do a little connection to trigger the logic
1761 server = Connection(server_context, None)
1762 server.set_accept_state()
1763
1764 client = Connection(client_context, None)
1765 client.set_connect_state()
1766
1767 interact_in_memory(server, client)
1768
1769 assert advertise_args == [(server,)]
1770 assert select_args == [(client, [b'http/1.1', b'spdy/2'])]
1771
1772 assert server.get_next_proto_negotiated() == b'spdy/2'
1773 assert client.get_next_proto_negotiated() == b'spdy/2'
1774
1775 def test_npn_client_fail(self):
1776 """
1777 Tests that when clients and servers cannot agree on what protocol
1778 to use next that the TLS connection does not get established.
1779 """
1780 advertise_args = []
1781 select_args = []
1782
1783 def advertise(conn):
1784 advertise_args.append((conn,))
1785 return [b'http/1.1', b'spdy/2']
1786
1787 def select(conn, options):
1788 select_args.append((conn, options))
1789 return b''
1790
1791 server_context = Context(TLSv1_METHOD)
1792 server_context.set_npn_advertise_callback(advertise)
1793
1794 client_context = Context(TLSv1_METHOD)
1795 client_context.set_npn_select_callback(select)
1796
1797 # Necessary to actually accept the connection
1798 server_context.use_privatekey(
1799 load_privatekey(FILETYPE_PEM, server_key_pem))
1800 server_context.use_certificate(
1801 load_certificate(FILETYPE_PEM, server_cert_pem))
1802
1803 # Do a little connection to trigger the logic
1804 server = Connection(server_context, None)
1805 server.set_accept_state()
1806
1807 client = Connection(client_context, None)
1808 client.set_connect_state()
1809
1810 # If the client doesn't return anything, the connection will fail.
1811 with pytest.raises(Error):
1812 interact_in_memory(server, client)
1813
1814 assert advertise_args == [(server,)]
1815 assert select_args == [(client, [b'http/1.1', b'spdy/2'])]
1816
1817 def test_npn_select_error(self):
1818 """
1819 Test that we can handle exceptions in the select callback. If
1820 select fails it should be fatal to the connection.
1821 """
1822 advertise_args = []
1823
1824 def advertise(conn):
1825 advertise_args.append((conn,))
1826 return [b'http/1.1', b'spdy/2']
1827
1828 def select(conn, options):
1829 raise TypeError
1830
1831 server_context = Context(TLSv1_METHOD)
1832 server_context.set_npn_advertise_callback(advertise)
1833
1834 client_context = Context(TLSv1_METHOD)
1835 client_context.set_npn_select_callback(select)
1836
1837 # Necessary to actually accept the connection
1838 server_context.use_privatekey(
1839 load_privatekey(FILETYPE_PEM, server_key_pem))
1840 server_context.use_certificate(
1841 load_certificate(FILETYPE_PEM, server_cert_pem))
1842
1843 # Do a little connection to trigger the logic
1844 server = Connection(server_context, None)
1845 server.set_accept_state()
1846
1847 client = Connection(client_context, None)
1848 client.set_connect_state()
1849
1850 # If the callback throws an exception it should be raised here.
1851 with pytest.raises(TypeError):
1852 interact_in_memory(server, client)
1853 assert advertise_args == [(server,), ]
1854
1855 def test_npn_advertise_error(self):
1856 """
1857 Test that we can handle exceptions in the advertise callback. If
1858 advertise fails no NPN is advertised to the client.
1859 """
1860 select_args = []
1861
1862 def advertise(conn):
1863 raise TypeError
1864
1865 def select(conn, options): # pragma: nocover
Cory Benfieldba1820d2015-04-13 17:39:12 -04001866 """
Alex Chan9e08b3e2016-11-10 12:18:54 +00001867 Assert later that no args are actually appended.
Cory Benfieldba1820d2015-04-13 17:39:12 -04001868 """
Alex Chan9e08b3e2016-11-10 12:18:54 +00001869 select_args.append((conn, options))
1870 return b''
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001871
Alex Chan9e08b3e2016-11-10 12:18:54 +00001872 server_context = Context(TLSv1_METHOD)
1873 server_context.set_npn_advertise_callback(advertise)
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001874
Alex Chan9e08b3e2016-11-10 12:18:54 +00001875 client_context = Context(TLSv1_METHOD)
1876 client_context.set_npn_select_callback(select)
Cory Benfield84a121e2014-03-31 20:30:25 +01001877
Alex Chan9e08b3e2016-11-10 12:18:54 +00001878 # Necessary to actually accept the connection
1879 server_context.use_privatekey(
1880 load_privatekey(FILETYPE_PEM, server_key_pem))
1881 server_context.use_certificate(
1882 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield84a121e2014-03-31 20:30:25 +01001883
Alex Chan9e08b3e2016-11-10 12:18:54 +00001884 # Do a little connection to trigger the logic
1885 server = Connection(server_context, None)
1886 server.set_accept_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001887
Alex Chan9e08b3e2016-11-10 12:18:54 +00001888 client = Connection(client_context, None)
1889 client.set_connect_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001890
Alex Chan9e08b3e2016-11-10 12:18:54 +00001891 # If the client doesn't return anything, the connection will fail.
1892 with pytest.raises(TypeError):
1893 interact_in_memory(server, client)
1894 assert select_args == []
Cory Benfield0ea76e72015-03-22 09:05:28 +00001895
1896
Alex Chanec1e32d2016-11-10 14:11:45 +00001897class TestApplicationLayerProtoNegotiation(object):
Cory Benfield12eae892014-06-07 15:42:56 +01001898 """
1899 Tests for ALPN in PyOpenSSL.
1900 """
Cory Benfielde46fa842015-04-13 16:50:49 -04001901 # Skip tests on versions that don't support ALPN.
1902 if _lib.Cryptography_HAS_ALPN:
Cory Benfield12eae892014-06-07 15:42:56 +01001903
Cory Benfielde46fa842015-04-13 16:50:49 -04001904 def test_alpn_success(self):
1905 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04001906 Clients and servers that agree on the negotiated ALPN protocol can
1907 correct establish a connection, and the agreed protocol is reported
1908 by the connections.
Cory Benfielde46fa842015-04-13 16:50:49 -04001909 """
1910 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001911
Cory Benfielde46fa842015-04-13 16:50:49 -04001912 def select(conn, options):
1913 select_args.append((conn, options))
1914 return b'spdy/2'
Cory Benfield12eae892014-06-07 15:42:56 +01001915
Cory Benfielde46fa842015-04-13 16:50:49 -04001916 client_context = Context(TLSv1_METHOD)
1917 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfield12eae892014-06-07 15:42:56 +01001918
Cory Benfielde46fa842015-04-13 16:50:49 -04001919 server_context = Context(TLSv1_METHOD)
1920 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01001921
Cory Benfielde46fa842015-04-13 16:50:49 -04001922 # Necessary to actually accept the connection
1923 server_context.use_privatekey(
1924 load_privatekey(FILETYPE_PEM, server_key_pem))
1925 server_context.use_certificate(
1926 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield12eae892014-06-07 15:42:56 +01001927
Cory Benfielde46fa842015-04-13 16:50:49 -04001928 # Do a little connection to trigger the logic
1929 server = Connection(server_context, None)
1930 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001931
Cory Benfielde46fa842015-04-13 16:50:49 -04001932 client = Connection(client_context, None)
1933 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001934
Alex Chanec1e32d2016-11-10 14:11:45 +00001935 interact_in_memory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001936
Alex Chanec1e32d2016-11-10 14:11:45 +00001937 assert select_args == [(server, [b'http/1.1', b'spdy/2'])]
Cory Benfielde46fa842015-04-13 16:50:49 -04001938
Alex Chanec1e32d2016-11-10 14:11:45 +00001939 assert server.get_alpn_proto_negotiated() == b'spdy/2'
1940 assert client.get_alpn_proto_negotiated() == b'spdy/2'
Cory Benfield12eae892014-06-07 15:42:56 +01001941
Cory Benfielde46fa842015-04-13 16:50:49 -04001942 def test_alpn_set_on_connection(self):
1943 """
1944 The same as test_alpn_success, but setting the ALPN protocols on
1945 the connection rather than the context.
1946 """
1947 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001948
Cory Benfielde46fa842015-04-13 16:50:49 -04001949 def select(conn, options):
1950 select_args.append((conn, options))
1951 return b'spdy/2'
Cory Benfield12eae892014-06-07 15:42:56 +01001952
Cory Benfielde46fa842015-04-13 16:50:49 -04001953 # Setup the client context but don't set any ALPN protocols.
1954 client_context = Context(TLSv1_METHOD)
Cory Benfield12eae892014-06-07 15:42:56 +01001955
Cory Benfielde46fa842015-04-13 16:50:49 -04001956 server_context = Context(TLSv1_METHOD)
1957 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01001958
Cory Benfielde46fa842015-04-13 16:50:49 -04001959 # Necessary to actually accept the connection
1960 server_context.use_privatekey(
1961 load_privatekey(FILETYPE_PEM, server_key_pem))
1962 server_context.use_certificate(
1963 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield12eae892014-06-07 15:42:56 +01001964
Cory Benfielde46fa842015-04-13 16:50:49 -04001965 # Do a little connection to trigger the logic
1966 server = Connection(server_context, None)
1967 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001968
Cory Benfielde46fa842015-04-13 16:50:49 -04001969 # Set the ALPN protocols on the client connection.
1970 client = Connection(client_context, None)
1971 client.set_alpn_protos([b'http/1.1', b'spdy/2'])
1972 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001973
Alex Chanec1e32d2016-11-10 14:11:45 +00001974 interact_in_memory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001975
Alex Chanec1e32d2016-11-10 14:11:45 +00001976 assert select_args == [(server, [b'http/1.1', b'spdy/2'])]
Cory Benfield12eae892014-06-07 15:42:56 +01001977
Alex Chanec1e32d2016-11-10 14:11:45 +00001978 assert server.get_alpn_proto_negotiated() == b'spdy/2'
1979 assert client.get_alpn_proto_negotiated() == b'spdy/2'
Cory Benfield12eae892014-06-07 15:42:56 +01001980
Cory Benfielde46fa842015-04-13 16:50:49 -04001981 def test_alpn_server_fail(self):
1982 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04001983 When clients and servers cannot agree on what protocol to use next
1984 the TLS connection does not get established.
Cory Benfielde46fa842015-04-13 16:50:49 -04001985 """
1986 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001987
Cory Benfielde46fa842015-04-13 16:50:49 -04001988 def select(conn, options):
1989 select_args.append((conn, options))
1990 return b''
Cory Benfield12eae892014-06-07 15:42:56 +01001991
Cory Benfielde46fa842015-04-13 16:50:49 -04001992 client_context = Context(TLSv1_METHOD)
1993 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfield12eae892014-06-07 15:42:56 +01001994
Cory Benfielde46fa842015-04-13 16:50:49 -04001995 server_context = Context(TLSv1_METHOD)
1996 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01001997
Cory Benfielde46fa842015-04-13 16:50:49 -04001998 # Necessary to actually accept the connection
1999 server_context.use_privatekey(
2000 load_privatekey(FILETYPE_PEM, server_key_pem))
2001 server_context.use_certificate(
2002 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield12eae892014-06-07 15:42:56 +01002003
Cory Benfielde46fa842015-04-13 16:50:49 -04002004 # Do a little connection to trigger the logic
2005 server = Connection(server_context, None)
2006 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01002007
Cory Benfielde46fa842015-04-13 16:50:49 -04002008 client = Connection(client_context, None)
2009 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01002010
Cory Benfielde46fa842015-04-13 16:50:49 -04002011 # If the client doesn't return anything, the connection will fail.
Alex Chanec1e32d2016-11-10 14:11:45 +00002012 with pytest.raises(Error):
2013 interact_in_memory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01002014
Alex Chanec1e32d2016-11-10 14:11:45 +00002015 assert select_args == [(server, [b'http/1.1', b'spdy/2'])]
Cory Benfield12eae892014-06-07 15:42:56 +01002016
Cory Benfielde46fa842015-04-13 16:50:49 -04002017 def test_alpn_no_server(self):
2018 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04002019 When clients and servers cannot agree on what protocol to use next
2020 because the server doesn't offer ALPN, no protocol is negotiated.
Cory Benfielde46fa842015-04-13 16:50:49 -04002021 """
2022 client_context = Context(TLSv1_METHOD)
2023 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfielde3d57152015-04-11 17:57:35 -04002024
Cory Benfielde46fa842015-04-13 16:50:49 -04002025 server_context = Context(TLSv1_METHOD)
Cory Benfielde3d57152015-04-11 17:57:35 -04002026
Cory Benfielde46fa842015-04-13 16:50:49 -04002027 # Necessary to actually accept the connection
2028 server_context.use_privatekey(
2029 load_privatekey(FILETYPE_PEM, server_key_pem))
2030 server_context.use_certificate(
2031 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfielde3d57152015-04-11 17:57:35 -04002032
Cory Benfielde46fa842015-04-13 16:50:49 -04002033 # Do a little connection to trigger the logic
2034 server = Connection(server_context, None)
2035 server.set_accept_state()
Cory Benfielde3d57152015-04-11 17:57:35 -04002036
Cory Benfielde46fa842015-04-13 16:50:49 -04002037 client = Connection(client_context, None)
2038 client.set_connect_state()
Cory Benfielde3d57152015-04-11 17:57:35 -04002039
Cory Benfielde46fa842015-04-13 16:50:49 -04002040 # Do the dance.
Alex Chanec1e32d2016-11-10 14:11:45 +00002041 interact_in_memory(server, client)
Cory Benfielde3d57152015-04-11 17:57:35 -04002042
Alex Chanec1e32d2016-11-10 14:11:45 +00002043 assert client.get_alpn_proto_negotiated() == b''
Cory Benfielde3d57152015-04-11 17:57:35 -04002044
Cory Benfielde46fa842015-04-13 16:50:49 -04002045 def test_alpn_callback_exception(self):
2046 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04002047 We can handle exceptions in the ALPN select callback.
Cory Benfielde46fa842015-04-13 16:50:49 -04002048 """
2049 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002050
Cory Benfielde46fa842015-04-13 16:50:49 -04002051 def select(conn, options):
2052 select_args.append((conn, options))
Cory Benfieldef401452015-04-13 18:17:36 -04002053 raise TypeError()
Cory Benfieldf1177e72015-04-12 09:11:49 -04002054
Cory Benfielde46fa842015-04-13 16:50:49 -04002055 client_context = Context(TLSv1_METHOD)
2056 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfieldf1177e72015-04-12 09:11:49 -04002057
Cory Benfielde46fa842015-04-13 16:50:49 -04002058 server_context = Context(TLSv1_METHOD)
2059 server_context.set_alpn_select_callback(select)
Cory Benfieldf1177e72015-04-12 09:11:49 -04002060
Cory Benfielde46fa842015-04-13 16:50:49 -04002061 # Necessary to actually accept the connection
2062 server_context.use_privatekey(
2063 load_privatekey(FILETYPE_PEM, server_key_pem))
2064 server_context.use_certificate(
2065 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfieldf1177e72015-04-12 09:11:49 -04002066
Cory Benfielde46fa842015-04-13 16:50:49 -04002067 # Do a little connection to trigger the logic
2068 server = Connection(server_context, None)
2069 server.set_accept_state()
Cory Benfieldf1177e72015-04-12 09:11:49 -04002070
Cory Benfielde46fa842015-04-13 16:50:49 -04002071 client = Connection(client_context, None)
2072 client.set_connect_state()
Cory Benfieldf1177e72015-04-12 09:11:49 -04002073
Alex Chanec1e32d2016-11-10 14:11:45 +00002074 with pytest.raises(TypeError):
2075 interact_in_memory(server, client)
2076 assert select_args == [(server, [b'http/1.1', b'spdy/2'])]
Cory Benfieldf1177e72015-04-12 09:11:49 -04002077
Cory Benfield0f7b04c2015-04-13 17:51:12 -04002078 else:
2079 # No ALPN.
2080 def test_alpn_not_implemented(self):
Cory Benfieldef401452015-04-13 18:17:36 -04002081 """
2082 If ALPN is not in OpenSSL, we should raise NotImplementedError.
2083 """
Cory Benfield0f7b04c2015-04-13 17:51:12 -04002084 # Test the context methods first.
2085 context = Context(TLSv1_METHOD)
Alex Chanec1e32d2016-11-10 14:11:45 +00002086 with pytest.raises(NotImplementedError):
2087 context.set_alpn_protos(None)
2088 with pytest.raises(NotImplementedError):
2089 context.set_alpn_select_callback(None)
Cory Benfield0f7b04c2015-04-13 17:51:12 -04002090
2091 # Now test a connection.
2092 conn = Connection(context)
Alex Chanec1e32d2016-11-10 14:11:45 +00002093 with pytest.raises(NotImplementedError):
2094 conn.set_alpn_protos(None)
Cory Benfield0f7b04c2015-04-13 17:51:12 -04002095
Cory Benfieldf1177e72015-04-12 09:11:49 -04002096
Alex Chanec1e32d2016-11-10 14:11:45 +00002097class TestSession(object):
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05002098 """
2099 Unit tests for :py:obj:`OpenSSL.SSL.Session`.
2100 """
2101 def test_construction(self):
2102 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002103 :py:class:`Session` can be constructed with no arguments, creating
2104 a new instance of that type.
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05002105 """
2106 new_session = Session()
Alex Chanec1e32d2016-11-10 14:11:45 +00002107 assert isinstance(new_session, Session)
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05002108
2109
Alex Chan1c0cb662017-01-30 07:13:30 +00002110class TestConnection(object):
Rick Deane15b1472009-07-09 15:53:42 -05002111 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002112 Unit tests for `OpenSSL.SSL.Connection`.
Rick Deane15b1472009-07-09 15:53:42 -05002113 """
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04002114 # XXX get_peer_certificate -> None
2115 # XXX sock_shutdown
2116 # XXX master_key -> TypeError
2117 # XXX server_random -> TypeError
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04002118 # XXX connect -> TypeError
2119 # XXX connect_ex -> TypeError
2120 # XXX set_connect_state -> TypeError
2121 # XXX set_accept_state -> TypeError
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04002122 # XXX do_handshake -> TypeError
2123 # XXX bio_read -> TypeError
2124 # XXX recv -> TypeError
2125 # XXX send -> TypeError
2126 # XXX bio_write -> TypeError
2127
Rick Deane15b1472009-07-09 15:53:42 -05002128 def test_type(self):
2129 """
Alex Gaynor01f90a12019-02-07 09:14:48 -05002130 `Connection` can be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -05002131 """
2132 ctx = Context(TLSv1_METHOD)
Alex Chan1c0cb662017-01-30 07:13:30 +00002133 assert is_consistent_type(Connection, 'Connection', ctx, None)
Rick Deane15b1472009-07-09 15:53:42 -05002134
Alex Chanfb078d82017-04-20 11:16:15 +01002135 @pytest.mark.parametrize('bad_context', [object(), 'context', None, 1])
2136 def test_wrong_args(self, bad_context):
2137 """
2138 `Connection.__init__` raises `TypeError` if called with a non-`Context`
2139 instance argument.
2140 """
2141 with pytest.raises(TypeError):
2142 Connection(bad_context)
2143
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002144 def test_get_context(self):
2145 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002146 `Connection.get_context` returns the `Context` instance used to
2147 construct the `Connection` instance.
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002148 """
2149 context = Context(TLSv1_METHOD)
2150 connection = Connection(context, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002151 assert connection.get_context() is context
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002152
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002153 def test_set_context_wrong_args(self):
2154 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002155 `Connection.set_context` raises `TypeError` if called with a
Alex Chanfb078d82017-04-20 11:16:15 +01002156 non-`Context` instance argument.
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002157 """
2158 ctx = Context(TLSv1_METHOD)
2159 connection = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002160 with pytest.raises(TypeError):
2161 connection.set_context(object())
2162 with pytest.raises(TypeError):
2163 connection.set_context("hello")
2164 with pytest.raises(TypeError):
2165 connection.set_context(1)
2166 assert ctx is connection.get_context()
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002167
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002168 def test_set_context(self):
2169 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002170 `Connection.set_context` specifies a new `Context` instance to be
2171 used for the connection.
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002172 """
2173 original = Context(SSLv23_METHOD)
2174 replacement = Context(TLSv1_METHOD)
2175 connection = Connection(original, None)
2176 connection.set_context(replacement)
Alex Chan1c0cb662017-01-30 07:13:30 +00002177 assert replacement is connection.get_context()
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002178 # Lose our references to the contexts, just in case the Connection
2179 # isn't properly managing its own contributions to their reference
2180 # counts.
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002181 del original, replacement
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002182 collect()
2183
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002184 def test_set_tlsext_host_name_wrong_args(self):
2185 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002186 If `Connection.set_tlsext_host_name` is called with a non-byte string
2187 argument or a byte string with an embedded NUL, `TypeError` is raised.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002188 """
2189 conn = Connection(Context(TLSv1_METHOD), None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002190 with pytest.raises(TypeError):
2191 conn.set_tlsext_host_name(object())
2192 with pytest.raises(TypeError):
2193 conn.set_tlsext_host_name(b"with\0null")
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002194
Abraham Martinc5484ba2015-03-25 15:33:05 +00002195 if PY3:
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002196 # On Python 3.x, don't accidentally implicitly convert from text.
Alex Chan1c0cb662017-01-30 07:13:30 +00002197 with pytest.raises(TypeError):
2198 conn.set_tlsext_host_name(b"example.com".decode("ascii"))
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04002199
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002200 def test_pending(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002201 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002202 `Connection.pending` returns the number of bytes available for
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002203 immediate read.
2204 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002205 connection = Connection(Context(TLSv1_METHOD), None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002206 assert connection.pending() == 0
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002207
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002208 def test_peek(self):
2209 """
Hynek Schlawack3bcf3152017-02-18 08:25:34 +01002210 `Connection.recv` peeks into the connection if `socket.MSG_PEEK` is
2211 passed.
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002212 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002213 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002214 server.send(b'xy')
Alex Chan1c0cb662017-01-30 07:13:30 +00002215 assert client.recv(2, MSG_PEEK) == b'xy'
2216 assert client.recv(2, MSG_PEEK) == b'xy'
2217 assert client.recv(2) == b'xy'
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002218
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002219 def test_connect_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002220 """
Hynek Schlawack3bcf3152017-02-18 08:25:34 +01002221 `Connection.connect` raises `TypeError` if called with a non-address
2222 argument.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002223 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002224 connection = Connection(Context(TLSv1_METHOD), socket())
Alex Chan1c0cb662017-01-30 07:13:30 +00002225 with pytest.raises(TypeError):
2226 connection.connect(None)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002227
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002228 def test_connect_refused(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002229 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002230 `Connection.connect` raises `socket.error` if the underlying socket
2231 connect method raises it.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002232 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002233 client = socket()
2234 context = Context(TLSv1_METHOD)
2235 clientSSL = Connection(context, client)
Alex Gaynor122717b2015-09-05 14:14:18 -04002236 # pytest.raises here doesn't work because of a bug in py.test on Python
2237 # 2.6: https://github.com/pytest-dev/pytest/issues/988
Alex Gaynore69c2782015-09-05 14:07:48 -04002238 try:
Alex Gaynor1aabb2e2015-09-05 13:35:18 -04002239 clientSSL.connect(("127.0.0.1", 1))
Alex Gaynore69c2782015-09-05 14:07:48 -04002240 except error as e:
Alex Gaynor20a4c082015-09-05 14:24:15 -04002241 exc = e
2242 assert exc.args[0] == ECONNREFUSED
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002243
2244 def test_connect(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002245 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002246 `Connection.connect` establishes a connection to the specified address.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002247 """
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002248 port = socket()
2249 port.bind(('', 0))
2250 port.listen(3)
2251
2252 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002253 clientSSL.connect(('127.0.0.1', port.getsockname()[1]))
2254 # XXX An assertion? Or something?
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002255
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002256 @pytest.mark.skipif(
2257 platform == "darwin",
2258 reason="connect_ex sometimes causes a kernel panic on OS X 10.6.4"
2259 )
2260 def test_connect_ex(self):
2261 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002262 If there is a connection error, `Connection.connect_ex` returns the
2263 errno instead of raising an exception.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002264 """
2265 port = socket()
2266 port.bind(('', 0))
2267 port.listen(3)
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002268
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002269 clientSSL = Connection(Context(TLSv1_METHOD), socket())
2270 clientSSL.setblocking(False)
2271 result = clientSSL.connect_ex(port.getsockname())
2272 expected = (EINPROGRESS, EWOULDBLOCK)
Alex Chan1c0cb662017-01-30 07:13:30 +00002273 assert result in expected
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002274
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002275 def test_accept(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002276 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002277 `Connection.accept` accepts a pending connection attempt and returns a
2278 tuple of a new `Connection` (the accepted client) and the address the
2279 connection originated from.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002280 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002281 ctx = Context(TLSv1_METHOD)
2282 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2283 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002284 port = socket()
2285 portSSL = Connection(ctx, port)
2286 portSSL.bind(('', 0))
2287 portSSL.listen(3)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002288
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002289 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002290
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002291 # Calling portSSL.getsockname() here to get the server IP address
2292 # sounds great, but frequently fails on Windows.
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002293 clientSSL.connect(('127.0.0.1', portSSL.getsockname()[1]))
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002294
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002295 serverSSL, address = portSSL.accept()
2296
Alex Chan1c0cb662017-01-30 07:13:30 +00002297 assert isinstance(serverSSL, Connection)
2298 assert serverSSL.get_context() is ctx
2299 assert address == clientSSL.getsockname()
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002300
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002301 def test_shutdown_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002302 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002303 `Connection.set_shutdown` raises `TypeError` if called with arguments
2304 other than integers.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002305 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002306 connection = Connection(Context(TLSv1_METHOD), None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002307 with pytest.raises(TypeError):
2308 connection.set_shutdown(None)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002309
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002310 def test_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002311 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002312 `Connection.shutdown` performs an SSL-level connection shutdown.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002313 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002314 server, client = loopback()
2315 assert not server.shutdown()
2316 assert server.get_shutdown() == SENT_SHUTDOWN
2317 with pytest.raises(ZeroReturnError):
2318 client.recv(1024)
2319 assert client.get_shutdown() == RECEIVED_SHUTDOWN
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04002320 client.shutdown()
Alex Chan1c0cb662017-01-30 07:13:30 +00002321 assert client.get_shutdown() == (SENT_SHUTDOWN | RECEIVED_SHUTDOWN)
2322 with pytest.raises(ZeroReturnError):
2323 server.recv(1024)
2324 assert server.get_shutdown() == (SENT_SHUTDOWN | RECEIVED_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002325
Paul Aurichc85e0862015-01-08 08:34:33 -08002326 def test_shutdown_closed(self):
2327 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002328 If the underlying socket is closed, `Connection.shutdown` propagates
2329 the write error from the low level write call.
Paul Aurichc85e0862015-01-08 08:34:33 -08002330 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002331 server, client = loopback()
Paul Aurichc85e0862015-01-08 08:34:33 -08002332 server.sock_shutdown(2)
Alex Chan1c0cb662017-01-30 07:13:30 +00002333 with pytest.raises(SysCallError) as exc:
2334 server.shutdown()
Alex Chanfb078d82017-04-20 11:16:15 +01002335 if platform == "win32":
2336 assert exc.value.args[0] == ESHUTDOWN
2337 else:
2338 assert exc.value.args[0] == EPIPE
Paul Aurichc85e0862015-01-08 08:34:33 -08002339
Glyph89389472015-04-14 17:29:26 -04002340 def test_shutdown_truncated(self):
Glyph6064ec32015-04-14 16:38:22 -04002341 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002342 If the underlying connection is truncated, `Connection.shutdown`
2343 raises an `Error`.
Glyph6064ec32015-04-14 16:38:22 -04002344 """
Glyph89389472015-04-14 17:29:26 -04002345 server_ctx = Context(TLSv1_METHOD)
2346 client_ctx = Context(TLSv1_METHOD)
2347 server_ctx.use_privatekey(
2348 load_privatekey(FILETYPE_PEM, server_key_pem))
2349 server_ctx.use_certificate(
2350 load_certificate(FILETYPE_PEM, server_cert_pem))
2351 server = Connection(server_ctx, None)
2352 client = Connection(client_ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002353 handshake_in_memory(client, server)
2354 assert not server.shutdown()
2355 with pytest.raises(WantReadError):
2356 server.shutdown()
Glyph89389472015-04-14 17:29:26 -04002357 server.bio_shutdown()
Alex Chan1c0cb662017-01-30 07:13:30 +00002358 with pytest.raises(Error):
2359 server.shutdown()
Glyph6064ec32015-04-14 16:38:22 -04002360
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002361 def test_set_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002362 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002363 `Connection.set_shutdown` sets the state of the SSL connection
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002364 shutdown process.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002365 """
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002366 connection = Connection(Context(TLSv1_METHOD), socket())
2367 connection.set_shutdown(RECEIVED_SHUTDOWN)
Alex Chan1c0cb662017-01-30 07:13:30 +00002368 assert connection.get_shutdown() == RECEIVED_SHUTDOWN
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002369
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002370 @skip_if_py3
2371 def test_set_shutdown_long(self):
2372 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002373 On Python 2 `Connection.set_shutdown` accepts an argument
2374 of type `long` as well as `int`.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002375 """
2376 connection = Connection(Context(TLSv1_METHOD), socket())
2377 connection.set_shutdown(long(RECEIVED_SHUTDOWN))
Alex Chan1c0cb662017-01-30 07:13:30 +00002378 assert connection.get_shutdown() == RECEIVED_SHUTDOWN
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -05002379
kjavaf248592015-09-07 12:14:01 +01002380 def test_state_string(self):
2381 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002382 `Connection.state_string` verbosely describes the current state of
2383 the `Connection`.
kjavaf248592015-09-07 12:14:01 +01002384 """
Hynek Schlawackb0274ce2015-10-16 19:56:26 +02002385 server, client = socket_pair()
Alex Chan1c0cb662017-01-30 07:13:30 +00002386 server = loopback_server_factory(server)
2387 client = loopback_client_factory(client)
kjavaf248592015-09-07 12:14:01 +01002388
Alex Gaynor5af32d02016-09-24 01:52:21 -04002389 assert server.get_state_string() in [
2390 b"before/accept initialization", b"before SSL initialization"
2391 ]
2392 assert client.get_state_string() in [
2393 b"before/connect initialization", b"before SSL initialization"
2394 ]
kjavaf248592015-09-07 12:14:01 +01002395
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002396 def test_app_data(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002397 """
2398 Any object can be set as app data by passing it to
Alex Chan1c0cb662017-01-30 07:13:30 +00002399 `Connection.set_app_data` and later retrieved with
2400 `Connection.get_app_data`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002401 """
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002402 conn = Connection(Context(TLSv1_METHOD), None)
Todd Chapman4f73e4f2015-08-27 11:26:43 -04002403 assert None is conn.get_app_data()
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002404 app_data = object()
2405 conn.set_app_data(app_data)
Todd Chapman4f73e4f2015-08-27 11:26:43 -04002406 assert conn.get_app_data() is app_data
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002407
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002408 def test_makefile(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002409 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002410 `Connection.makefile` is not implemented and calling that
2411 method raises `NotImplementedError`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002412 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002413 conn = Connection(Context(TLSv1_METHOD), None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002414 with pytest.raises(NotImplementedError):
2415 conn.makefile()
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002416
Jeremy Lainé460a19d2018-05-16 19:44:19 +02002417 def test_get_certificate(self):
2418 """
2419 `Connection.get_certificate` returns the local certificate.
2420 """
2421 chain = _create_certificate_chain()
2422 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
2423
2424 context = Context(TLSv1_METHOD)
2425 context.use_certificate(scert)
2426 client = Connection(context, None)
2427 cert = client.get_certificate()
2428 assert cert is not None
2429 assert "Server Certificate" == cert.get_subject().CN
2430
2431 def test_get_certificate_none(self):
2432 """
2433 `Connection.get_certificate` returns the local certificate.
2434
2435 If there is no certificate, it returns None.
2436 """
2437 context = Context(TLSv1_METHOD)
2438 client = Connection(context, None)
2439 cert = client.get_certificate()
2440 assert cert is None
2441
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002442 def test_get_peer_cert_chain(self):
2443 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002444 `Connection.get_peer_cert_chain` returns a list of certificates
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002445 which the connected server returned for the certification verification.
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002446 """
2447 chain = _create_certificate_chain()
2448 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
2449
2450 serverContext = Context(TLSv1_METHOD)
2451 serverContext.use_privatekey(skey)
2452 serverContext.use_certificate(scert)
2453 serverContext.add_extra_chain_cert(icert)
2454 serverContext.add_extra_chain_cert(cacert)
2455 server = Connection(serverContext, None)
2456 server.set_accept_state()
2457
2458 # Create the client
2459 clientContext = Context(TLSv1_METHOD)
2460 clientContext.set_verify(VERIFY_NONE, verify_cb)
2461 client = Connection(clientContext, None)
2462 client.set_connect_state()
2463
Alex Chan1c0cb662017-01-30 07:13:30 +00002464 interact_in_memory(client, server)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002465
2466 chain = client.get_peer_cert_chain()
Alex Chan1c0cb662017-01-30 07:13:30 +00002467 assert len(chain) == 3
2468 assert "Server Certificate" == chain[0].get_subject().CN
2469 assert "Intermediate Certificate" == chain[1].get_subject().CN
2470 assert "Authority Certificate" == chain[2].get_subject().CN
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002471
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002472 def test_get_peer_cert_chain_none(self):
2473 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002474 `Connection.get_peer_cert_chain` returns `None` if the peer sends
2475 no certificate chain.
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002476 """
2477 ctx = Context(TLSv1_METHOD)
2478 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2479 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
2480 server = Connection(ctx, None)
2481 server.set_accept_state()
2482 client = Connection(Context(TLSv1_METHOD), None)
2483 client.set_connect_state()
Alex Chan1c0cb662017-01-30 07:13:30 +00002484 interact_in_memory(client, server)
2485 assert None is server.get_peer_cert_chain()
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002486
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002487 def test_get_session_unconnected(self):
2488 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002489 `Connection.get_session` returns `None` when used with an object
2490 which has not been connected.
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002491 """
2492 ctx = Context(TLSv1_METHOD)
2493 server = Connection(ctx, None)
2494 session = server.get_session()
Alex Chan1c0cb662017-01-30 07:13:30 +00002495 assert None is session
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002496
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002497 def test_server_get_session(self):
2498 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002499 On the server side of a connection, `Connection.get_session` returns a
2500 `Session` instance representing the SSL session for that connection.
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002501 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002502 server, client = loopback()
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002503 session = server.get_session()
Alex Chan1c0cb662017-01-30 07:13:30 +00002504 assert isinstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002505
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002506 def test_client_get_session(self):
2507 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002508 On the client side of a connection, `Connection.get_session`
2509 returns a `Session` instance representing the SSL session for
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002510 that connection.
2511 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002512 server, client = loopback()
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002513 session = client.get_session()
Alex Chan1c0cb662017-01-30 07:13:30 +00002514 assert isinstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002515
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002516 def test_set_session_wrong_args(self):
2517 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002518 `Connection.set_session` raises `TypeError` if called with an object
2519 that is not an instance of `Session`.
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002520 """
2521 ctx = Context(TLSv1_METHOD)
2522 connection = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002523 with pytest.raises(TypeError):
2524 connection.set_session(123)
2525 with pytest.raises(TypeError):
2526 connection.set_session("hello")
2527 with pytest.raises(TypeError):
2528 connection.set_session(object())
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002529
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002530 def test_client_set_session(self):
2531 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002532 `Connection.set_session`, when used prior to a connection being
2533 established, accepts a `Session` instance and causes an attempt to
2534 re-use the session it represents when the SSL handshake is performed.
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002535 """
2536 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2537 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
Paul Kehrer7d5a3bf2019-01-21 12:24:02 -06002538 ctx = Context(TLSv1_2_METHOD)
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002539 ctx.use_privatekey(key)
2540 ctx.use_certificate(cert)
2541 ctx.set_session_id("unity-test")
2542
2543 def makeServer(socket):
2544 server = Connection(ctx, socket)
2545 server.set_accept_state()
2546 return server
2547
Alex Chan1c0cb662017-01-30 07:13:30 +00002548 originalServer, originalClient = loopback(
2549 server_factory=makeServer)
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002550 originalSession = originalClient.get_session()
2551
2552 def makeClient(socket):
Alex Chan1c0cb662017-01-30 07:13:30 +00002553 client = loopback_client_factory(socket)
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002554 client.set_session(originalSession)
2555 return client
Alex Chan1c0cb662017-01-30 07:13:30 +00002556 resumedServer, resumedClient = loopback(
2557 server_factory=makeServer,
2558 client_factory=makeClient)
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002559
2560 # This is a proxy: in general, we have no access to any unique
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002561 # identifier for the session (new enough versions of OpenSSL expose
2562 # a hash which could be usable, but "new enough" is very, very new).
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002563 # Instead, exploit the fact that the master key is re-used if the
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002564 # session is re-used. As long as the master key for the two
2565 # connections is the same, the session was re-used!
Alex Chan1c0cb662017-01-30 07:13:30 +00002566 assert originalServer.master_key() == resumedServer.master_key()
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002567
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002568 def test_set_session_wrong_method(self):
2569 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002570 If `Connection.set_session` is passed a `Session` instance associated
2571 with a context using a different SSL method than the `Connection`
2572 is using, a `OpenSSL.SSL.Error` is raised.
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002573 """
Alex Gaynor5af32d02016-09-24 01:52:21 -04002574 # Make this work on both OpenSSL 1.0.0, which doesn't support TLSv1.2
2575 # and also on OpenSSL 1.1.0 which doesn't support SSLv3. (SSL_ST_INIT
2576 # is a way to check for 1.1.0)
Alex Gaynoraa32e712017-06-29 20:56:12 -07002577 if SSL_ST_INIT is None:
2578 v1 = TLSv1_2_METHOD
2579 v2 = TLSv1_METHOD
2580 elif hasattr(_lib, "SSLv3_method"):
Alex Gaynor5af32d02016-09-24 01:52:21 -04002581 v1 = TLSv1_METHOD
2582 v2 = SSLv3_METHOD
2583 else:
Alex Gaynoraa32e712017-06-29 20:56:12 -07002584 pytest.skip("Test requires either OpenSSL 1.1.0 or SSLv3")
Alex Gaynor5af32d02016-09-24 01:52:21 -04002585
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002586 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2587 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
Alex Gaynor5af32d02016-09-24 01:52:21 -04002588 ctx = Context(v1)
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002589 ctx.use_privatekey(key)
2590 ctx.use_certificate(cert)
2591 ctx.set_session_id("unity-test")
2592
2593 def makeServer(socket):
2594 server = Connection(ctx, socket)
2595 server.set_accept_state()
2596 return server
2597
Alex Gaynor5af32d02016-09-24 01:52:21 -04002598 def makeOriginalClient(socket):
2599 client = Connection(Context(v1), socket)
2600 client.set_connect_state()
2601 return client
2602
Alex Chan1c0cb662017-01-30 07:13:30 +00002603 originalServer, originalClient = loopback(
2604 server_factory=makeServer, client_factory=makeOriginalClient)
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002605 originalSession = originalClient.get_session()
2606
2607 def makeClient(socket):
2608 # Intentionally use a different, incompatible method here.
Alex Gaynor5af32d02016-09-24 01:52:21 -04002609 client = Connection(Context(v2), socket)
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002610 client.set_connect_state()
2611 client.set_session(originalSession)
2612 return client
2613
Alex Chan1c0cb662017-01-30 07:13:30 +00002614 with pytest.raises(Error):
2615 loopback(client_factory=makeClient, server_factory=makeServer)
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002616
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002617 def test_wantWriteError(self):
2618 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002619 `Connection` methods which generate output raise
2620 `OpenSSL.SSL.WantWriteError` if writing to the connection's BIO
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002621 fail indicating a should-write state.
2622 """
2623 client_socket, server_socket = socket_pair()
2624 # Fill up the client's send buffer so Connection won't be able to write
Jean-Paul Calderonebbff8b92014-03-22 14:20:30 -04002625 # anything. Only write a single byte at a time so we can be sure we
2626 # completely fill the buffer. Even though the socket API is allowed to
2627 # signal a short write via its return value it seems this doesn't
2628 # always happen on all platforms (FreeBSD and OS X particular) for the
2629 # very last bit of available buffer space.
2630 msg = b"x"
caternb2777a42018-08-09 15:38:13 -04002631 for i in range(1024 * 1024 * 64):
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002632 try:
2633 client_socket.send(msg)
2634 except error as e:
2635 if e.errno == EWOULDBLOCK:
2636 break
2637 raise
2638 else:
Alex Chan1c0cb662017-01-30 07:13:30 +00002639 pytest.fail(
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002640 "Failed to fill socket buffer, cannot test BIO want write")
2641
2642 ctx = Context(TLSv1_METHOD)
2643 conn = Connection(ctx, client_socket)
2644 # Client's speak first, so make it an SSL client
2645 conn.set_connect_state()
Alex Chan1c0cb662017-01-30 07:13:30 +00002646 with pytest.raises(WantWriteError):
2647 conn.do_handshake()
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002648
2649 # XXX want_read
2650
Fedor Brunner416f4a12014-03-28 13:18:38 +01002651 def test_get_finished_before_connect(self):
Fedor Brunner5747b932014-03-05 14:22:34 +01002652 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002653 `Connection.get_finished` returns `None` before TLS handshake
2654 is completed.
Fedor Brunner5747b932014-03-05 14:22:34 +01002655 """
Fedor Brunner5747b932014-03-05 14:22:34 +01002656 ctx = Context(TLSv1_METHOD)
2657 connection = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002658 assert connection.get_finished() is None
Fedor Brunner416f4a12014-03-28 13:18:38 +01002659
2660 def test_get_peer_finished_before_connect(self):
2661 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002662 `Connection.get_peer_finished` returns `None` before TLS handshake
2663 is completed.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002664 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002665 ctx = Context(TLSv1_METHOD)
2666 connection = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002667 assert connection.get_peer_finished() is None
Fedor Brunner5747b932014-03-05 14:22:34 +01002668
Fedor Brunner416f4a12014-03-28 13:18:38 +01002669 def test_get_finished(self):
2670 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002671 `Connection.get_finished` method returns the TLS Finished message send
2672 from client, or server. Finished messages are send during
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002673 TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002674 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002675 server, client = loopback()
Fedor Brunner416f4a12014-03-28 13:18:38 +01002676
Alex Chan1c0cb662017-01-30 07:13:30 +00002677 assert server.get_finished() is not None
2678 assert len(server.get_finished()) > 0
Fedor Brunner416f4a12014-03-28 13:18:38 +01002679
2680 def test_get_peer_finished(self):
2681 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002682 `Connection.get_peer_finished` method returns the TLS Finished
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002683 message received from client, or server. Finished messages are send
2684 during TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002685 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002686 server, client = loopback()
Fedor Brunner416f4a12014-03-28 13:18:38 +01002687
Alex Chan1c0cb662017-01-30 07:13:30 +00002688 assert server.get_peer_finished() is not None
2689 assert len(server.get_peer_finished()) > 0
Fedor Brunner5747b932014-03-05 14:22:34 +01002690
Fedor Brunner416f4a12014-03-28 13:18:38 +01002691 def test_tls_finished_message_symmetry(self):
2692 """
Hynek Schlawackdddd1112015-09-05 21:12:30 +02002693 The TLS Finished message send by server must be the TLS Finished
2694 message received by client.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002695
Hynek Schlawackdddd1112015-09-05 21:12:30 +02002696 The TLS Finished message send by client must be the TLS Finished
2697 message received by server.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002698 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002699 server, client = loopback()
Fedor Brunner416f4a12014-03-28 13:18:38 +01002700
Alex Chan1c0cb662017-01-30 07:13:30 +00002701 assert server.get_finished() == client.get_peer_finished()
2702 assert client.get_finished() == server.get_peer_finished()
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002703
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002704 def test_get_cipher_name_before_connect(self):
2705 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002706 `Connection.get_cipher_name` returns `None` if no connection
2707 has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002708 """
2709 ctx = Context(TLSv1_METHOD)
2710 conn = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002711 assert conn.get_cipher_name() is None
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002712
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002713 def test_get_cipher_name(self):
2714 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002715 `Connection.get_cipher_name` returns a `unicode` string giving the
2716 name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002717 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002718 server, client = loopback()
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002719 server_cipher_name, client_cipher_name = \
2720 server.get_cipher_name(), client.get_cipher_name()
2721
Alex Chan1c0cb662017-01-30 07:13:30 +00002722 assert isinstance(server_cipher_name, text_type)
2723 assert isinstance(client_cipher_name, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002724
Alex Chan1c0cb662017-01-30 07:13:30 +00002725 assert server_cipher_name == client_cipher_name
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002726
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002727 def test_get_cipher_version_before_connect(self):
2728 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002729 `Connection.get_cipher_version` returns `None` if no connection
2730 has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002731 """
2732 ctx = Context(TLSv1_METHOD)
2733 conn = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002734 assert conn.get_cipher_version() is None
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002735
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002736 def test_get_cipher_version(self):
2737 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002738 `Connection.get_cipher_version` returns a `unicode` string giving
2739 the protocol name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002740 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002741 server, client = loopback()
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002742 server_cipher_version, client_cipher_version = \
2743 server.get_cipher_version(), client.get_cipher_version()
2744
Alex Chan1c0cb662017-01-30 07:13:30 +00002745 assert isinstance(server_cipher_version, text_type)
2746 assert isinstance(client_cipher_version, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002747
Alex Chan1c0cb662017-01-30 07:13:30 +00002748 assert server_cipher_version == client_cipher_version
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002749
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002750 def test_get_cipher_bits_before_connect(self):
2751 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002752 `Connection.get_cipher_bits` returns `None` if no connection has
2753 been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002754 """
2755 ctx = Context(TLSv1_METHOD)
2756 conn = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002757 assert conn.get_cipher_bits() is None
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002758
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002759 def test_get_cipher_bits(self):
2760 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002761 `Connection.get_cipher_bits` returns the number of secret bits
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002762 of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002763 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002764 server, client = loopback()
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002765 server_cipher_bits, client_cipher_bits = \
2766 server.get_cipher_bits(), client.get_cipher_bits()
2767
Alex Chan1c0cb662017-01-30 07:13:30 +00002768 assert isinstance(server_cipher_bits, int)
2769 assert isinstance(client_cipher_bits, int)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002770
Alex Chan1c0cb662017-01-30 07:13:30 +00002771 assert server_cipher_bits == client_cipher_bits
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002772
Jim Shaverabff1882015-05-27 09:15:55 -04002773 def test_get_protocol_version_name(self):
2774 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002775 `Connection.get_protocol_version_name()` returns a string giving the
2776 protocol version of the current connection.
Jim Shaverabff1882015-05-27 09:15:55 -04002777 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002778 server, client = loopback()
Jim Shaverabff1882015-05-27 09:15:55 -04002779 client_protocol_version_name = client.get_protocol_version_name()
2780 server_protocol_version_name = server.get_protocol_version_name()
2781
Alex Chan1c0cb662017-01-30 07:13:30 +00002782 assert isinstance(server_protocol_version_name, text_type)
2783 assert isinstance(client_protocol_version_name, text_type)
Jim Shaverabff1882015-05-27 09:15:55 -04002784
Alex Chan1c0cb662017-01-30 07:13:30 +00002785 assert server_protocol_version_name == client_protocol_version_name
Jim Shaverabff1882015-05-27 09:15:55 -04002786
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002787 def test_get_protocol_version(self):
2788 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002789 `Connection.get_protocol_version()` returns an integer
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002790 giving the protocol version of the current connection.
2791 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002792 server, client = loopback()
Jim Shaver85a4dff2015-04-27 17:42:46 -04002793 client_protocol_version = client.get_protocol_version()
2794 server_protocol_version = server.get_protocol_version()
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002795
Alex Chan1c0cb662017-01-30 07:13:30 +00002796 assert isinstance(server_protocol_version, int)
2797 assert isinstance(client_protocol_version, int)
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002798
Alex Chan1c0cb662017-01-30 07:13:30 +00002799 assert server_protocol_version == client_protocol_version
2800
2801 def test_wantReadError(self):
2802 """
2803 `Connection.bio_read` raises `OpenSSL.SSL.WantReadError` if there are
2804 no bytes available to be read from the BIO.
2805 """
2806 ctx = Context(TLSv1_METHOD)
2807 conn = Connection(ctx, None)
2808 with pytest.raises(WantReadError):
2809 conn.bio_read(1024)
2810
Alex Chanfb078d82017-04-20 11:16:15 +01002811 @pytest.mark.parametrize('bufsize', [1.0, None, object(), 'bufsize'])
2812 def test_bio_read_wrong_args(self, bufsize):
2813 """
2814 `Connection.bio_read` raises `TypeError` if passed a non-integer
2815 argument.
2816 """
2817 ctx = Context(TLSv1_METHOD)
2818 conn = Connection(ctx, None)
2819 with pytest.raises(TypeError):
2820 conn.bio_read(bufsize)
2821
Alex Chan1c0cb662017-01-30 07:13:30 +00002822 def test_buffer_size(self):
2823 """
2824 `Connection.bio_read` accepts an integer giving the maximum number
2825 of bytes to read and return.
2826 """
2827 ctx = Context(TLSv1_METHOD)
2828 conn = Connection(ctx, None)
2829 conn.set_connect_state()
2830 try:
2831 conn.do_handshake()
2832 except WantReadError:
2833 pass
2834 data = conn.bio_read(2)
2835 assert 2 == len(data)
2836
2837 @skip_if_py3
2838 def test_buffer_size_long(self):
2839 """
2840 On Python 2 `Connection.bio_read` accepts values of type `long` as
2841 well as `int`.
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(long(2))
2851 assert 2 == len(data)
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002852
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002853
Alex Chanb7480992017-01-30 14:04:47 +00002854class TestConnectionGetCipherList(object):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002855 """
Alex Chanb7480992017-01-30 14:04:47 +00002856 Tests for `Connection.get_cipher_list`.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002857 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002858 def test_result(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002859 """
Alex Chanb7480992017-01-30 14:04:47 +00002860 `Connection.get_cipher_list` returns a list of `bytes` giving the
2861 names of the ciphers which might be used.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002862 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002863 connection = Connection(Context(TLSv1_METHOD), None)
2864 ciphers = connection.get_cipher_list()
Alex Chanb7480992017-01-30 14:04:47 +00002865 assert isinstance(ciphers, list)
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002866 for cipher in ciphers:
Alex Chanb7480992017-01-30 14:04:47 +00002867 assert isinstance(cipher, str)
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002868
2869
Maximilian Hils868dc3c2017-02-10 14:56:55 +01002870class VeryLarge(bytes):
2871 """
2872 Mock object so that we don't have to allocate 2**31 bytes
2873 """
2874 def __len__(self):
2875 return 2**31
2876
2877
Alex Chanb7480992017-01-30 14:04:47 +00002878class TestConnectionSend(object):
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002879 """
Alex Chanb7480992017-01-30 14:04:47 +00002880 Tests for `Connection.send`.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002881 """
2882 def test_wrong_args(self):
2883 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002884 When called with arguments other than string argument for its first
Alex Chanb7480992017-01-30 14:04:47 +00002885 parameter, `Connection.send` raises `TypeError`.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002886 """
2887 connection = Connection(Context(TLSv1_METHOD), None)
Alex Chanb7480992017-01-30 14:04:47 +00002888 with pytest.raises(TypeError):
2889 connection.send(object())
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002890
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002891 def test_short_bytes(self):
2892 """
Alex Chanb7480992017-01-30 14:04:47 +00002893 When passed a short byte string, `Connection.send` transmits all of it
2894 and returns the number of bytes sent.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002895 """
Alex Chanb7480992017-01-30 14:04:47 +00002896 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002897 count = server.send(b'xy')
Alex Chanb7480992017-01-30 14:04:47 +00002898 assert count == 2
2899 assert client.recv(2) == b'xy'
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002900
Abraham Martinef063482015-03-25 14:06:24 +00002901 def test_text(self):
2902 """
Alex Chanb7480992017-01-30 14:04:47 +00002903 When passed a text, `Connection.send` transmits all of it and
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002904 returns the number of bytes sent. It also raises a DeprecationWarning.
Abraham Martinef063482015-03-25 14:06:24 +00002905 """
Alex Chanb7480992017-01-30 14:04:47 +00002906 server, client = loopback()
2907 with pytest.warns(DeprecationWarning) as w:
Abraham Martinef063482015-03-25 14:06:24 +00002908 simplefilter("always")
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002909 count = server.send(b"xy".decode("ascii"))
Alex Chanb7480992017-01-30 14:04:47 +00002910 assert (
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002911 "{0} for buf is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002912 WARNING_TYPE_EXPECTED
Alex Chanb7480992017-01-30 14:04:47 +00002913 ) == str(w[-1].message))
2914 assert count == 2
2915 assert client.recv(2) == b'xy'
Abraham Martinef063482015-03-25 14:06:24 +00002916
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002917 def test_short_memoryview(self):
2918 """
2919 When passed a memoryview onto a small number of bytes,
Alex Chanb7480992017-01-30 14:04:47 +00002920 `Connection.send` transmits all of them and returns the number
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002921 of bytes sent.
2922 """
Alex Chanb7480992017-01-30 14:04:47 +00002923 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002924 count = server.send(memoryview(b'xy'))
Alex Chanb7480992017-01-30 14:04:47 +00002925 assert count == 2
2926 assert client.recv(2) == b'xy'
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002927
Hynek Schlawack8e94f1b2015-09-05 21:31:00 +02002928 @skip_if_py3
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002929 def test_short_buffer(self):
2930 """
2931 When passed a buffer containing a small number of bytes,
Alex Chanb7480992017-01-30 14:04:47 +00002932 `Connection.send` transmits all of them and returns the number
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002933 of bytes sent.
2934 """
Alex Chanb7480992017-01-30 14:04:47 +00002935 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002936 count = server.send(buffer(b'xy'))
Alex Chanb7480992017-01-30 14:04:47 +00002937 assert count == 2
2938 assert client.recv(2) == b'xy'
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02002939
Maximilian Hils868dc3c2017-02-10 14:56:55 +01002940 @pytest.mark.skipif(
2941 sys.maxsize < 2**31,
2942 reason="sys.maxsize < 2**31 - test requires 64 bit"
2943 )
2944 def test_buf_too_large(self):
2945 """
2946 When passed a buffer containing >= 2**31 bytes,
2947 `Connection.send` bails out as SSL_write only
2948 accepts an int for the buffer length.
2949 """
2950 connection = Connection(Context(TLSv1_METHOD), None)
2951 with pytest.raises(ValueError) as exc_info:
2952 connection.send(VeryLarge())
2953 exc_info.match(r"Cannot send more than .+ bytes at once")
2954
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05002955
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002956def _make_memoryview(size):
2957 """
2958 Create a new ``memoryview`` wrapped around a ``bytearray`` of the given
2959 size.
2960 """
2961 return memoryview(bytearray(size))
2962
2963
Alex Chanb7480992017-01-30 14:04:47 +00002964class TestConnectionRecvInto(object):
Cory Benfield62d10332014-06-15 10:03:41 +01002965 """
Alex Chanb7480992017-01-30 14:04:47 +00002966 Tests for `Connection.recv_into`.
Cory Benfield62d10332014-06-15 10:03:41 +01002967 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002968 def _no_length_test(self, factory):
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04002969 """
Alex Chanb7480992017-01-30 14:04:47 +00002970 Assert that when the given buffer is passed to `Connection.recv_into`,
2971 whatever bytes are available to be received that fit into that buffer
2972 are written into that buffer.
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04002973 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002974 output_buffer = factory(5)
2975
Alex Chanb7480992017-01-30 14:04:47 +00002976 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002977 server.send(b'xy')
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04002978
Alex Chanb7480992017-01-30 14:04:47 +00002979 assert client.recv_into(output_buffer) == 2
2980 assert output_buffer == bytearray(b'xy\x00\x00\x00')
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04002981
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002982 def test_bytearray_no_length(self):
Cory Benfield62d10332014-06-15 10:03:41 +01002983 """
Alex Chanb7480992017-01-30 14:04:47 +00002984 `Connection.recv_into` can be passed a `bytearray` instance and data
2985 in the receive buffer is written to it.
Cory Benfield62d10332014-06-15 10:03:41 +01002986 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002987 self._no_length_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01002988
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002989 def _respects_length_test(self, factory):
Cory Benfield62d10332014-06-15 10:03:41 +01002990 """
Alex Chanb7480992017-01-30 14:04:47 +00002991 Assert that when the given buffer is passed to `Connection.recv_into`
2992 along with a value for `nbytes` that is less than the size of that
2993 buffer, only `nbytes` bytes are written into the buffer.
Cory Benfield62d10332014-06-15 10:03:41 +01002994 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002995 output_buffer = factory(10)
2996
Alex Chanb7480992017-01-30 14:04:47 +00002997 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002998 server.send(b'abcdefghij')
Cory Benfield62d10332014-06-15 10:03:41 +01002999
Alex Chanb7480992017-01-30 14:04:47 +00003000 assert client.recv_into(output_buffer, 5) == 5
3001 assert output_buffer == bytearray(b'abcde\x00\x00\x00\x00\x00')
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04003002
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04003003 def test_bytearray_respects_length(self):
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04003004 """
Alex Chanb7480992017-01-30 14:04:47 +00003005 When called with a `bytearray` instance, `Connection.recv_into`
3006 respects the `nbytes` parameter and doesn't copy in more than that
3007 number of bytes.
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04003008 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003009 self._respects_length_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01003010
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003011 def _doesnt_overfill_test(self, factory):
Cory Benfield62d10332014-06-15 10:03:41 +01003012 """
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04003013 Assert that if there are more bytes available to be read from the
3014 receive buffer than would fit into the buffer passed to
Alex Chanb7480992017-01-30 14:04:47 +00003015 `Connection.recv_into`, only as many as fit are written into it.
Cory Benfield62d10332014-06-15 10:03:41 +01003016 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003017 output_buffer = factory(5)
3018
Alex Chanb7480992017-01-30 14:04:47 +00003019 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04003020 server.send(b'abcdefghij')
Cory Benfield62d10332014-06-15 10:03:41 +01003021
Alex Chanb7480992017-01-30 14:04:47 +00003022 assert client.recv_into(output_buffer) == 5
3023 assert output_buffer == bytearray(b'abcde')
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04003024 rest = client.recv(5)
Alex Chanb7480992017-01-30 14:04:47 +00003025 assert b'fghij' == rest
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04003026
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04003027 def test_bytearray_doesnt_overfill(self):
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04003028 """
Alex Chanb7480992017-01-30 14:04:47 +00003029 When called with a `bytearray` instance, `Connection.recv_into`
3030 respects the size of the array and doesn't write more bytes into it
3031 than will fit.
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04003032 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003033 self._doesnt_overfill_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01003034
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04003035 def test_bytearray_really_doesnt_overfill(self):
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003036 """
Alex Chanb7480992017-01-30 14:04:47 +00003037 When called with a `bytearray` instance and an `nbytes` value that is
3038 too large, `Connection.recv_into` respects the size of the array and
3039 not the `nbytes` value and doesn't write more bytes into the buffer
3040 than will fit.
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003041 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003042 self._doesnt_overfill_test(bytearray)
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003043
Maximilian Hils1d95dea2015-08-17 19:27:20 +02003044 def test_peek(self):
Alex Chanb7480992017-01-30 14:04:47 +00003045 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04003046 server.send(b'xy')
Maximilian Hils1d95dea2015-08-17 19:27:20 +02003047
3048 for _ in range(2):
3049 output_buffer = bytearray(5)
Alex Chanb7480992017-01-30 14:04:47 +00003050 assert client.recv_into(output_buffer, flags=MSG_PEEK) == 2
3051 assert output_buffer == bytearray(b'xy\x00\x00\x00')
Maximilian Hils1d95dea2015-08-17 19:27:20 +02003052
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003053 def test_memoryview_no_length(self):
3054 """
Alex Chanb7480992017-01-30 14:04:47 +00003055 `Connection.recv_into` can be passed a `memoryview` instance and data
3056 in the receive buffer is written to it.
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003057 """
3058 self._no_length_test(_make_memoryview)
Maximilian Hils1d95dea2015-08-17 19:27:20 +02003059
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003060 def test_memoryview_respects_length(self):
3061 """
Alex Chanb7480992017-01-30 14:04:47 +00003062 When called with a `memoryview` instance, `Connection.recv_into`
3063 respects the ``nbytes`` parameter and doesn't copy more than that
3064 number of bytes in.
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003065 """
3066 self._respects_length_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01003067
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003068 def test_memoryview_doesnt_overfill(self):
3069 """
Alex Chanb7480992017-01-30 14:04:47 +00003070 When called with a `memoryview` instance, `Connection.recv_into`
3071 respects the size of the array and doesn't write more bytes into it
3072 than will fit.
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003073 """
3074 self._doesnt_overfill_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01003075
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003076 def test_memoryview_really_doesnt_overfill(self):
3077 """
Alex Chanb7480992017-01-30 14:04:47 +00003078 When called with a `memoryview` instance and an `nbytes` value that is
3079 too large, `Connection.recv_into` respects the size of the array and
3080 not the `nbytes` value and doesn't write more bytes into the buffer
3081 than will fit.
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003082 """
3083 self._doesnt_overfill_test(_make_memoryview)
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003084
Cory Benfield62d10332014-06-15 10:03:41 +01003085
Alex Chanb7480992017-01-30 14:04:47 +00003086class TestConnectionSendall(object):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003087 """
Alex Chanb7480992017-01-30 14:04:47 +00003088 Tests for `Connection.sendall`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003089 """
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003090 def test_wrong_args(self):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003091 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003092 When called with arguments other than a string argument for its first
Alex Chanb7480992017-01-30 14:04:47 +00003093 parameter, `Connection.sendall` raises `TypeError`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003094 """
3095 connection = Connection(Context(TLSv1_METHOD), None)
Alex Chanb7480992017-01-30 14:04:47 +00003096 with pytest.raises(TypeError):
3097 connection.sendall(object())
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003098
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003099 def test_short(self):
3100 """
Alex Chanb7480992017-01-30 14:04:47 +00003101 `Connection.sendall` transmits all of the bytes in the string
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003102 passed to it.
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003103 """
Alex Chanb7480992017-01-30 14:04:47 +00003104 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04003105 server.sendall(b'x')
Alex Chanb7480992017-01-30 14:04:47 +00003106 assert client.recv(1) == b'x'
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003107
Abraham Martinef063482015-03-25 14:06:24 +00003108 def test_text(self):
3109 """
Alex Chanb7480992017-01-30 14:04:47 +00003110 `Connection.sendall` transmits all the content in the string passed
3111 to it, raising a DeprecationWarning in case of this being a text.
Abraham Martinef063482015-03-25 14:06:24 +00003112 """
Alex Chanb7480992017-01-30 14:04:47 +00003113 server, client = loopback()
3114 with pytest.warns(DeprecationWarning) as w:
Abraham Martinef063482015-03-25 14:06:24 +00003115 simplefilter("always")
Jean-Paul Calderone8dc37a12015-03-29 08:16:52 -04003116 server.sendall(b"x".decode("ascii"))
Alex Chanb7480992017-01-30 14:04:47 +00003117 assert (
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04003118 "{0} for buf is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04003119 WARNING_TYPE_EXPECTED
Alex Chanb7480992017-01-30 14:04:47 +00003120 ) == str(w[-1].message))
3121 assert client.recv(1) == b"x"
Abraham Martinef063482015-03-25 14:06:24 +00003122
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003123 def test_short_memoryview(self):
3124 """
3125 When passed a memoryview onto a small number of bytes,
Alex Chanb7480992017-01-30 14:04:47 +00003126 `Connection.sendall` transmits all of them.
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003127 """
Alex Chanb7480992017-01-30 14:04:47 +00003128 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04003129 server.sendall(memoryview(b'x'))
Alex Chanb7480992017-01-30 14:04:47 +00003130 assert client.recv(1) == b'x'
Abraham Martinef063482015-03-25 14:06:24 +00003131
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003132 @skip_if_py3
3133 def test_short_buffers(self):
3134 """
3135 When passed a buffer containing a small number of bytes,
Alex Chanb7480992017-01-30 14:04:47 +00003136 `Connection.sendall` transmits all of them.
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003137 """
Alex Chanb7480992017-01-30 14:04:47 +00003138 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04003139 server.sendall(buffer(b'x'))
Alex Chanb7480992017-01-30 14:04:47 +00003140 assert client.recv(1) == b'x'
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02003141
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003142 def test_long(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003143 """
Alex Chanb7480992017-01-30 14:04:47 +00003144 `Connection.sendall` transmits all the bytes in the string passed to it
3145 even if this requires multiple calls of an underlying write function.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003146 """
Alex Chanb7480992017-01-30 14:04:47 +00003147 server, client = loopback()
Jean-Paul Calderone6241c702010-09-16 19:59:24 -04003148 # Should be enough, underlying SSL_write should only do 16k at a time.
Hynek Schlawack35618382015-09-05 21:54:25 +02003149 # On Windows, after 32k of bytes the write will block (forever
3150 # - because no one is yet reading).
Alex Gaynore7f51982016-09-11 11:48:14 -04003151 message = b'x' * (1024 * 32 - 1) + b'y'
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003152 server.sendall(message)
3153 accum = []
3154 received = 0
3155 while received < len(message):
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04003156 data = client.recv(1024)
3157 accum.append(data)
3158 received += len(data)
Alex Chanb7480992017-01-30 14:04:47 +00003159 assert message == b''.join(accum)
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003160
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003161 def test_closed(self):
3162 """
Alex Chanb7480992017-01-30 14:04:47 +00003163 If the underlying socket is closed, `Connection.sendall` propagates the
3164 write error from the low level write call.
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003165 """
Alex Chanb7480992017-01-30 14:04:47 +00003166 server, client = loopback()
Jean-Paul Calderone05d43e82010-09-24 18:01:36 -04003167 server.sock_shutdown(2)
Alex Chanb7480992017-01-30 14:04:47 +00003168 with pytest.raises(SysCallError) as err:
3169 server.sendall(b"hello, world")
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +02003170 if platform == "win32":
Alex Chanb7480992017-01-30 14:04:47 +00003171 assert err.value.args[0] == ESHUTDOWN
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +02003172 else:
Alex Chanb7480992017-01-30 14:04:47 +00003173 assert err.value.args[0] == EPIPE
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003174
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003175
Alex Chanb7480992017-01-30 14:04:47 +00003176class TestConnectionRenegotiate(object):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003177 """
3178 Tests for SSL renegotiation APIs.
3179 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003180 def test_total_renegotiations(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003181 """
Alex Chanb7480992017-01-30 14:04:47 +00003182 `Connection.total_renegotiations` returns `0` before any renegotiations
3183 have happened.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003184 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003185 connection = Connection(Context(TLSv1_METHOD), None)
Alex Chanb7480992017-01-30 14:04:47 +00003186 assert connection.total_renegotiations() == 0
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003187
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003188 def test_renegotiate(self):
3189 """
3190 Go through a complete renegotiation cycle.
3191 """
Paul Kehrer7d5a3bf2019-01-21 12:24:02 -06003192 server, client = loopback(
3193 lambda s: loopback_server_factory(s, TLSv1_2_METHOD),
3194 lambda s: loopback_client_factory(s, TLSv1_2_METHOD),
3195 )
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003196
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003197 server.send(b"hello world")
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003198
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003199 assert b"hello world" == client.recv(len(b"hello world"))
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003200
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003201 assert 0 == server.total_renegotiations()
3202 assert False is server.renegotiate_pending()
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003203
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003204 assert True is server.renegotiate()
3205
3206 assert True is server.renegotiate_pending()
3207
3208 server.setblocking(False)
3209 client.setblocking(False)
3210
3211 client.do_handshake()
3212 server.do_handshake()
3213
3214 assert 1 == server.total_renegotiations()
3215 while False is server.renegotiate_pending():
3216 pass
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003217
3218
Alex Chanb7480992017-01-30 14:04:47 +00003219class TestError(object):
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003220 """
Alex Chanb7480992017-01-30 14:04:47 +00003221 Unit tests for `OpenSSL.SSL.Error`.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003222 """
3223 def test_type(self):
3224 """
Alex Chanb7480992017-01-30 14:04:47 +00003225 `Error` is an exception type.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003226 """
Alex Chanb7480992017-01-30 14:04:47 +00003227 assert issubclass(Error, Exception)
3228 assert Error.__name__ == 'Error'
Rick Deane15b1472009-07-09 15:53:42 -05003229
3230
Alex Chanb7480992017-01-30 14:04:47 +00003231class TestConstants(object):
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003232 """
Alex Chanb7480992017-01-30 14:04:47 +00003233 Tests for the values of constants exposed in `OpenSSL.SSL`.
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003234
3235 These are values defined by OpenSSL intended only to be used as flags to
3236 OpenSSL APIs. The only assertions it seems can be made about them is
3237 their values.
3238 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003239 @pytest.mark.skipif(
3240 OP_NO_QUERY_MTU is None,
3241 reason="OP_NO_QUERY_MTU unavailable - OpenSSL version may be too old"
3242 )
3243 def test_op_no_query_mtu(self):
3244 """
Alex Chanb7480992017-01-30 14:04:47 +00003245 The value of `OpenSSL.SSL.OP_NO_QUERY_MTU` is 0x1000, the value
3246 of `SSL_OP_NO_QUERY_MTU` defined by `openssl/ssl.h`.
Hynek Schlawack35618382015-09-05 21:54:25 +02003247 """
Alex Chanb7480992017-01-30 14:04:47 +00003248 assert OP_NO_QUERY_MTU == 0x1000
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003249
Hynek Schlawack35618382015-09-05 21:54:25 +02003250 @pytest.mark.skipif(
3251 OP_COOKIE_EXCHANGE is None,
3252 reason="OP_COOKIE_EXCHANGE unavailable - "
3253 "OpenSSL version may be too old"
3254 )
3255 def test_op_cookie_exchange(self):
3256 """
Alex Chanb7480992017-01-30 14:04:47 +00003257 The value of `OpenSSL.SSL.OP_COOKIE_EXCHANGE` is 0x2000, the
3258 value of `SSL_OP_COOKIE_EXCHANGE` defined by `openssl/ssl.h`.
Hynek Schlawack35618382015-09-05 21:54:25 +02003259 """
Alex Chanb7480992017-01-30 14:04:47 +00003260 assert OP_COOKIE_EXCHANGE == 0x2000
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003261
Hynek Schlawack35618382015-09-05 21:54:25 +02003262 @pytest.mark.skipif(
3263 OP_NO_TICKET is None,
3264 reason="OP_NO_TICKET unavailable - OpenSSL version may be too old"
3265 )
3266 def test_op_no_ticket(self):
3267 """
Alex Chanb7480992017-01-30 14:04:47 +00003268 The value of `OpenSSL.SSL.OP_NO_TICKET` is 0x4000, the value of
3269 `SSL_OP_NO_TICKET` defined by `openssl/ssl.h`.
Hynek Schlawack35618382015-09-05 21:54:25 +02003270 """
Alex Chanb7480992017-01-30 14:04:47 +00003271 assert OP_NO_TICKET == 0x4000
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003272
Hynek Schlawack35618382015-09-05 21:54:25 +02003273 @pytest.mark.skipif(
3274 OP_NO_COMPRESSION is None,
3275 reason="OP_NO_COMPRESSION unavailable - OpenSSL version may be too old"
3276 )
3277 def test_op_no_compression(self):
3278 """
Alex Chanb7480992017-01-30 14:04:47 +00003279 The value of `OpenSSL.SSL.OP_NO_COMPRESSION` is 0x20000, the
3280 value of `SSL_OP_NO_COMPRESSION` defined by `openssl/ssl.h`.
Hynek Schlawack35618382015-09-05 21:54:25 +02003281 """
Alex Chanb7480992017-01-30 14:04:47 +00003282 assert OP_NO_COMPRESSION == 0x20000
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04003283
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003284 def test_sess_cache_off(self):
3285 """
Alex Chanb7480992017-01-30 14:04:47 +00003286 The value of `OpenSSL.SSL.SESS_CACHE_OFF` 0x0, the value of
3287 `SSL_SESS_CACHE_OFF` defined by `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003288 """
Alex Chanb7480992017-01-30 14:04:47 +00003289 assert 0x0 == SESS_CACHE_OFF
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003290
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003291 def test_sess_cache_client(self):
3292 """
Alex Chanb7480992017-01-30 14:04:47 +00003293 The value of `OpenSSL.SSL.SESS_CACHE_CLIENT` 0x1, the value of
3294 `SSL_SESS_CACHE_CLIENT` defined by `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003295 """
Alex Chanb7480992017-01-30 14:04:47 +00003296 assert 0x1 == SESS_CACHE_CLIENT
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003297
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003298 def test_sess_cache_server(self):
3299 """
Alex Chanb7480992017-01-30 14:04:47 +00003300 The value of `OpenSSL.SSL.SESS_CACHE_SERVER` 0x2, the value of
3301 `SSL_SESS_CACHE_SERVER` defined by `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003302 """
Alex Chanb7480992017-01-30 14:04:47 +00003303 assert 0x2 == SESS_CACHE_SERVER
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003304
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003305 def test_sess_cache_both(self):
3306 """
Alex Chanb7480992017-01-30 14:04:47 +00003307 The value of `OpenSSL.SSL.SESS_CACHE_BOTH` 0x3, the value of
3308 `SSL_SESS_CACHE_BOTH` defined by `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003309 """
Alex Chanb7480992017-01-30 14:04:47 +00003310 assert 0x3 == SESS_CACHE_BOTH
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003311
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003312 def test_sess_cache_no_auto_clear(self):
3313 """
Alex Chanb7480992017-01-30 14:04:47 +00003314 The value of `OpenSSL.SSL.SESS_CACHE_NO_AUTO_CLEAR` 0x80, the
3315 value of `SSL_SESS_CACHE_NO_AUTO_CLEAR` defined by
3316 `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003317 """
Alex Chanb7480992017-01-30 14:04:47 +00003318 assert 0x80 == SESS_CACHE_NO_AUTO_CLEAR
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003319
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003320 def test_sess_cache_no_internal_lookup(self):
3321 """
Alex Chanb7480992017-01-30 14:04:47 +00003322 The value of `OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_LOOKUP` 0x100,
3323 the value of `SSL_SESS_CACHE_NO_INTERNAL_LOOKUP` defined by
3324 `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003325 """
Alex Chanb7480992017-01-30 14:04:47 +00003326 assert 0x100 == SESS_CACHE_NO_INTERNAL_LOOKUP
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003327
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003328 def test_sess_cache_no_internal_store(self):
3329 """
Alex Chanb7480992017-01-30 14:04:47 +00003330 The value of `OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_STORE` 0x200,
3331 the value of `SSL_SESS_CACHE_NO_INTERNAL_STORE` defined by
3332 `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003333 """
Alex Chanb7480992017-01-30 14:04:47 +00003334 assert 0x200 == SESS_CACHE_NO_INTERNAL_STORE
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003335
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003336 def test_sess_cache_no_internal(self):
3337 """
Alex Chanb7480992017-01-30 14:04:47 +00003338 The value of `OpenSSL.SSL.SESS_CACHE_NO_INTERNAL` 0x300, the
3339 value of `SSL_SESS_CACHE_NO_INTERNAL` defined by
3340 `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003341 """
Alex Chanb7480992017-01-30 14:04:47 +00003342 assert 0x300 == SESS_CACHE_NO_INTERNAL
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003343
3344
Alex Chanb7480992017-01-30 14:04:47 +00003345class TestMemoryBIO(object):
Rick Deanb71c0d22009-04-01 14:09:23 -05003346 """
Alex Chanb7480992017-01-30 14:04:47 +00003347 Tests for `OpenSSL.SSL.Connection` using a memory BIO.
Rick Deanb71c0d22009-04-01 14:09:23 -05003348 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003349 def _server(self, sock):
3350 """
Alex Chanb7480992017-01-30 14:04:47 +00003351 Create a new server-side SSL `Connection` object wrapped around `sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003352 """
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003353 # Create the server side Connection. This is mostly setup boilerplate
3354 # - use TLSv1, use a particular certificate, etc.
3355 server_ctx = Context(TLSv1_METHOD)
Alex Gaynor43307782015-09-04 09:05:45 -04003356 server_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE)
Hynek Schlawack35618382015-09-05 21:54:25 +02003357 server_ctx.set_verify(
3358 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT | VERIFY_CLIENT_ONCE,
3359 verify_cb
3360 )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003361 server_store = server_ctx.get_cert_store()
Hynek Schlawack35618382015-09-05 21:54:25 +02003362 server_ctx.use_privatekey(
3363 load_privatekey(FILETYPE_PEM, server_key_pem))
3364 server_ctx.use_certificate(
3365 load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003366 server_ctx.check_privatekey()
3367 server_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Hynek Schlawack35618382015-09-05 21:54:25 +02003368 # Here the Connection is actually created. If None is passed as the
3369 # 2nd parameter, it indicates a memory BIO should be created.
Rick Deanb1ccd562009-07-09 23:52:39 -05003370 server_conn = Connection(server_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003371 server_conn.set_accept_state()
3372 return server_conn
3373
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003374 def _client(self, sock):
3375 """
Alex Chanb7480992017-01-30 14:04:47 +00003376 Create a new client-side SSL `Connection` object wrapped around `sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003377 """
3378 # Now create the client side Connection. Similar boilerplate to the
3379 # above.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003380 client_ctx = Context(TLSv1_METHOD)
Alex Gaynor43307782015-09-04 09:05:45 -04003381 client_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE)
Hynek Schlawack35618382015-09-05 21:54:25 +02003382 client_ctx.set_verify(
3383 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT | VERIFY_CLIENT_ONCE,
3384 verify_cb
3385 )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003386 client_store = client_ctx.get_cert_store()
Hynek Schlawack35618382015-09-05 21:54:25 +02003387 client_ctx.use_privatekey(
3388 load_privatekey(FILETYPE_PEM, client_key_pem))
3389 client_ctx.use_certificate(
3390 load_certificate(FILETYPE_PEM, client_cert_pem))
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003391 client_ctx.check_privatekey()
3392 client_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05003393 client_conn = Connection(client_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003394 client_conn.set_connect_state()
3395 return client_conn
3396
Alex Chanb7480992017-01-30 14:04:47 +00003397 def test_memory_connect(self):
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003398 """
Alex Chanb7480992017-01-30 14:04:47 +00003399 Two `Connection`s which use memory BIOs can be manually connected by
3400 reading from the output of each and writing those bytes to the input of
3401 the other and in this way establish a connection and exchange
3402 application-level bytes with each other.
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003403 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003404 server_conn = self._server(None)
3405 client_conn = self._client(None)
Rick Deanb71c0d22009-04-01 14:09:23 -05003406
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003407 # There should be no key or nonces yet.
Alex Chanb7480992017-01-30 14:04:47 +00003408 assert server_conn.master_key() is None
3409 assert server_conn.client_random() is None
3410 assert server_conn.server_random() is None
Rick Deanb71c0d22009-04-01 14:09:23 -05003411
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003412 # First, the handshake needs to happen. We'll deliver bytes back and
3413 # forth between the client and server until neither of them feels like
3414 # speaking any more.
Alex Chanb7480992017-01-30 14:04:47 +00003415 assert interact_in_memory(client_conn, server_conn) is None
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003416
3417 # Now that the handshake is done, there should be a key and nonces.
Alex Chanb7480992017-01-30 14:04:47 +00003418 assert server_conn.master_key() is not None
3419 assert server_conn.client_random() is not None
3420 assert server_conn.server_random() is not None
3421 assert server_conn.client_random() == client_conn.client_random()
3422 assert server_conn.server_random() == client_conn.server_random()
3423 assert server_conn.client_random() != server_conn.server_random()
3424 assert client_conn.client_random() != client_conn.server_random()
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003425
Paul Kehrerbdb76392017-12-01 04:54:32 +08003426 # Export key material for other uses.
3427 cekm = client_conn.export_keying_material(b'LABEL', 32)
3428 sekm = server_conn.export_keying_material(b'LABEL', 32)
3429 assert cekm is not None
3430 assert sekm is not None
3431 assert cekm == sekm
3432 assert len(sekm) == 32
3433
3434 # Export key material for other uses with additional context.
3435 cekmc = client_conn.export_keying_material(b'LABEL', 32, b'CONTEXT')
3436 sekmc = server_conn.export_keying_material(b'LABEL', 32, b'CONTEXT')
3437 assert cekmc is not None
3438 assert sekmc is not None
3439 assert cekmc == sekmc
3440 assert cekmc != cekm
3441 assert sekmc != sekm
3442 # Export with alternate label
3443 cekmt = client_conn.export_keying_material(b'test', 32, b'CONTEXT')
3444 sekmt = server_conn.export_keying_material(b'test', 32, b'CONTEXT')
3445 assert cekmc != cekmt
3446 assert sekmc != sekmt
3447
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003448 # Here are the bytes we'll try to send.
Alex Gaynore7f51982016-09-11 11:48:14 -04003449 important_message = b'One if by land, two if by sea.'
Rick Deanb71c0d22009-04-01 14:09:23 -05003450
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003451 server_conn.write(important_message)
Alex Chanb7480992017-01-30 14:04:47 +00003452 assert (
3453 interact_in_memory(client_conn, server_conn) ==
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003454 (client_conn, important_message))
3455
3456 client_conn.write(important_message[::-1])
Alex Chanb7480992017-01-30 14:04:47 +00003457 assert (
3458 interact_in_memory(client_conn, server_conn) ==
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003459 (server_conn, important_message[::-1]))
Rick Deanb71c0d22009-04-01 14:09:23 -05003460
Alex Chanb7480992017-01-30 14:04:47 +00003461 def test_socket_connect(self):
Rick Deanb1ccd562009-07-09 23:52:39 -05003462 """
Alex Chanb7480992017-01-30 14:04:47 +00003463 Just like `test_memory_connect` but with an actual socket.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003464
Hynek Schlawack35618382015-09-05 21:54:25 +02003465 This is primarily to rule out the memory BIO code as the source of any
Alex Chanb7480992017-01-30 14:04:47 +00003466 problems encountered while passing data over a `Connection` (if
Hynek Schlawack35618382015-09-05 21:54:25 +02003467 this test fails, there must be a problem outside the memory BIO code,
3468 as no memory BIO is involved here). Even though this isn't a memory
3469 BIO test, it's convenient to have it here.
Rick Deanb1ccd562009-07-09 23:52:39 -05003470 """
Alex Chanb7480992017-01-30 14:04:47 +00003471 server_conn, client_conn = loopback()
Rick Deanb1ccd562009-07-09 23:52:39 -05003472
Alex Gaynore7f51982016-09-11 11:48:14 -04003473 important_message = b"Help me Obi Wan Kenobi, you're my only hope."
Rick Deanb1ccd562009-07-09 23:52:39 -05003474 client_conn.send(important_message)
3475 msg = server_conn.recv(1024)
Alex Chanb7480992017-01-30 14:04:47 +00003476 assert msg == important_message
Rick Deanb1ccd562009-07-09 23:52:39 -05003477
3478 # Again in the other direction, just for fun.
3479 important_message = important_message[::-1]
3480 server_conn.send(important_message)
3481 msg = client_conn.recv(1024)
Alex Chanb7480992017-01-30 14:04:47 +00003482 assert msg == important_message
Rick Deanb1ccd562009-07-09 23:52:39 -05003483
Alex Chanb7480992017-01-30 14:04:47 +00003484 def test_socket_overrides_memory(self):
Rick Deanb71c0d22009-04-01 14:09:23 -05003485 """
Alex Chanb7480992017-01-30 14:04:47 +00003486 Test that `OpenSSL.SSL.bio_read` and `OpenSSL.SSL.bio_write` don't
3487 work on `OpenSSL.SSL.Connection`() that use sockets.
Rick Deanb71c0d22009-04-01 14:09:23 -05003488 """
Alex Gaynor51d424c2016-09-10 14:50:11 -04003489 context = Context(TLSv1_METHOD)
Rick Deanb71c0d22009-04-01 14:09:23 -05003490 client = socket()
3491 clientSSL = Connection(context, client)
Alex Chanb7480992017-01-30 14:04:47 +00003492 with pytest.raises(TypeError):
3493 clientSSL.bio_read(100)
3494 with pytest.raises(TypeError):
3495 clientSSL.bio_write("foo")
3496 with pytest.raises(TypeError):
3497 clientSSL.bio_shutdown()
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003498
Alex Chanb7480992017-01-30 14:04:47 +00003499 def test_outgoing_overflow(self):
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003500 """
3501 If more bytes than can be written to the memory BIO are passed to
Alex Chanb7480992017-01-30 14:04:47 +00003502 `Connection.send` at once, the number of bytes which were written is
3503 returned and that many bytes from the beginning of the input can be
3504 read from the other end of the connection.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003505 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003506 server = self._server(None)
3507 client = self._client(None)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003508
Alex Chanb7480992017-01-30 14:04:47 +00003509 interact_in_memory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003510
3511 size = 2 ** 15
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003512 sent = client.send(b"x" * size)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003513 # Sanity check. We're trying to test what happens when the entire
3514 # input can't be sent. If the entire input was sent, this test is
3515 # meaningless.
Alex Chanb7480992017-01-30 14:04:47 +00003516 assert sent < size
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003517
Alex Chanb7480992017-01-30 14:04:47 +00003518 receiver, received = interact_in_memory(client, server)
3519 assert receiver is server
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003520
3521 # We can rely on all of these bytes being received at once because
Alex Chanb7480992017-01-30 14:04:47 +00003522 # loopback passes 2 ** 16 to recv - more than 2 ** 15.
3523 assert len(received) == sent
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003524
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003525 def test_shutdown(self):
3526 """
Alex Chanb7480992017-01-30 14:04:47 +00003527 `Connection.bio_shutdown` signals the end of the data stream
3528 from which the `Connection` reads.
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003529 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003530 server = self._server(None)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003531 server.bio_shutdown()
Alex Chanb7480992017-01-30 14:04:47 +00003532 with pytest.raises(Error) as err:
3533 server.recv(1024)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003534 # We don't want WantReadError or ZeroReturnError or anything - it's a
3535 # handshake failure.
Alex Chanb7480992017-01-30 14:04:47 +00003536 assert type(err.value) in [Error, SysCallError]
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003537
Alex Chanb7480992017-01-30 14:04:47 +00003538 def test_unexpected_EOF(self):
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003539 """
3540 If the connection is lost before an orderly SSL shutdown occurs,
Alex Chanb7480992017-01-30 14:04:47 +00003541 `OpenSSL.SSL.SysCallError` is raised with a message of
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003542 "Unexpected EOF".
3543 """
Alex Chanb7480992017-01-30 14:04:47 +00003544 server_conn, client_conn = loopback()
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003545 client_conn.sock_shutdown(SHUT_RDWR)
Alex Chanb7480992017-01-30 14:04:47 +00003546 with pytest.raises(SysCallError) as err:
3547 server_conn.recv(1024)
3548 assert err.value.args == (-1, "Unexpected EOF")
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003549
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003550 def _check_client_ca_list(self, func):
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003551 """
Alex Chanb7480992017-01-30 14:04:47 +00003552 Verify the return value of the `get_client_ca_list` method for
Hynek Schlawack35618382015-09-05 21:54:25 +02003553 server and client connections.
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003554
Jonathan Ballet78b92a22011-07-16 08:07:26 +09003555 :param func: A function which will be called with the server context
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003556 before the client and server are connected to each other. This
3557 function should specify a list of CAs for the server to send to the
3558 client and return that same list. The list will be used to verify
Alex Chanb7480992017-01-30 14:04:47 +00003559 that `get_client_ca_list` returns the proper value at
Hynek Schlawack35618382015-09-05 21:54:25 +02003560 various times.
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003561 """
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003562 server = self._server(None)
3563 client = self._client(None)
Alex Chanb7480992017-01-30 14:04:47 +00003564 assert client.get_client_ca_list() == []
3565 assert server.get_client_ca_list() == []
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003566 ctx = server.get_context()
3567 expected = func(ctx)
Alex Chanb7480992017-01-30 14:04:47 +00003568 assert client.get_client_ca_list() == []
3569 assert server.get_client_ca_list() == expected
3570 interact_in_memory(client, server)
3571 assert client.get_client_ca_list() == expected
3572 assert server.get_client_ca_list() == expected
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003573
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003574 def test_set_client_ca_list_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003575 """
Alex Chanb7480992017-01-30 14:04:47 +00003576 `Context.set_client_ca_list` raises a `TypeError` if called with a
3577 non-list or a list that contains objects other than X509Names.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003578 """
3579 ctx = Context(TLSv1_METHOD)
Alex Chanb7480992017-01-30 14:04:47 +00003580 with pytest.raises(TypeError):
3581 ctx.set_client_ca_list("spam")
3582 with pytest.raises(TypeError):
3583 ctx.set_client_ca_list(["spam"])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003584
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003585 def test_set_empty_ca_list(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003586 """
Alex Chanb7480992017-01-30 14:04:47 +00003587 If passed an empty list, `Context.set_client_ca_list` configures the
3588 context to send no CA names to the client and, on both the server and
3589 client sides, `Connection.get_client_ca_list` returns an empty list
3590 after the connection is set up.
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003591 """
3592 def no_ca(ctx):
3593 ctx.set_client_ca_list([])
3594 return []
3595 self._check_client_ca_list(no_ca)
3596
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003597 def test_set_one_ca_list(self):
3598 """
3599 If passed a list containing a single X509Name,
Alex Chanb7480992017-01-30 14:04:47 +00003600 `Context.set_client_ca_list` configures the context to send
Hynek Schlawack35618382015-09-05 21:54:25 +02003601 that CA name to the client and, on both the server and client sides,
Alex Chanb7480992017-01-30 14:04:47 +00003602 `Connection.get_client_ca_list` returns a list containing that
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003603 X509Name after the connection is set up.
3604 """
3605 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3606 cadesc = cacert.get_subject()
Hynek Schlawack35618382015-09-05 21:54:25 +02003607
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003608 def single_ca(ctx):
3609 ctx.set_client_ca_list([cadesc])
3610 return [cadesc]
3611 self._check_client_ca_list(single_ca)
3612
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003613 def test_set_multiple_ca_list(self):
3614 """
3615 If passed a list containing multiple X509Name objects,
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 those CA names 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 those
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003619 X509Names after the connection is set up.
3620 """
3621 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3622 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3623
3624 sedesc = secert.get_subject()
3625 cldesc = clcert.get_subject()
3626
3627 def multiple_ca(ctx):
3628 L = [sedesc, cldesc]
3629 ctx.set_client_ca_list(L)
3630 return L
3631 self._check_client_ca_list(multiple_ca)
3632
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003633 def test_reset_ca_list(self):
3634 """
3635 If called multiple times, only the X509Names passed to the final call
Alex Chanb7480992017-01-30 14:04:47 +00003636 of `Context.set_client_ca_list` are used to configure the CA
Hynek Schlawack35618382015-09-05 21:54:25 +02003637 names sent to the client.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003638 """
3639 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3640 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3641 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3642
3643 cadesc = cacert.get_subject()
3644 sedesc = secert.get_subject()
3645 cldesc = clcert.get_subject()
3646
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003647 def changed_ca(ctx):
3648 ctx.set_client_ca_list([sedesc, cldesc])
3649 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003650 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003651 self._check_client_ca_list(changed_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003652
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003653 def test_mutated_ca_list(self):
3654 """
Alex Chanb7480992017-01-30 14:04:47 +00003655 If the list passed to `Context.set_client_ca_list` is mutated
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003656 afterwards, this does not affect the list of CA names sent to the
3657 client.
3658 """
3659 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3660 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3661
3662 cadesc = cacert.get_subject()
3663 sedesc = secert.get_subject()
3664
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003665 def mutated_ca(ctx):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003666 L = [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003667 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003668 L.append(sedesc)
3669 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003670 self._check_client_ca_list(mutated_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003671
Alex Chanb7480992017-01-30 14:04:47 +00003672 def test_add_client_ca_wrong_args(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003673 """
Alex Chanb7480992017-01-30 14:04:47 +00003674 `Context.add_client_ca` raises `TypeError` if called with
3675 a non-X509 object.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003676 """
3677 ctx = Context(TLSv1_METHOD)
Alex Chanb7480992017-01-30 14:04:47 +00003678 with pytest.raises(TypeError):
3679 ctx.add_client_ca("spam")
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003680
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003681 def test_one_add_client_ca(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003682 """
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003683 A certificate's subject can be added as a CA to be sent to the client
Alex Chanb7480992017-01-30 14:04:47 +00003684 with `Context.add_client_ca`.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003685 """
3686 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3687 cadesc = cacert.get_subject()
Hynek Schlawack35618382015-09-05 21:54:25 +02003688
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003689 def single_ca(ctx):
3690 ctx.add_client_ca(cacert)
3691 return [cadesc]
3692 self._check_client_ca_list(single_ca)
3693
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003694 def test_multiple_add_client_ca(self):
3695 """
3696 Multiple CA names can be sent to the client by calling
Alex Chanb7480992017-01-30 14:04:47 +00003697 `Context.add_client_ca` with multiple X509 objects.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003698 """
3699 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3700 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3701
3702 cadesc = cacert.get_subject()
3703 sedesc = secert.get_subject()
3704
3705 def multiple_ca(ctx):
3706 ctx.add_client_ca(cacert)
3707 ctx.add_client_ca(secert)
3708 return [cadesc, sedesc]
3709 self._check_client_ca_list(multiple_ca)
3710
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003711 def test_set_and_add_client_ca(self):
3712 """
Alex Chanb7480992017-01-30 14:04:47 +00003713 A call to `Context.set_client_ca_list` followed by a call to
3714 `Context.add_client_ca` results in using the CA names from the
Hynek Schlawack35618382015-09-05 21:54:25 +02003715 first call and the CA name from the second call.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003716 """
3717 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3718 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3719 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3720
3721 cadesc = cacert.get_subject()
3722 sedesc = secert.get_subject()
3723 cldesc = clcert.get_subject()
3724
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003725 def mixed_set_add_ca(ctx):
3726 ctx.set_client_ca_list([cadesc, sedesc])
3727 ctx.add_client_ca(clcert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003728 return [cadesc, sedesc, cldesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003729 self._check_client_ca_list(mixed_set_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003730
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003731 def test_set_after_add_client_ca(self):
3732 """
Alex Chanb7480992017-01-30 14:04:47 +00003733 A call to `Context.set_client_ca_list` after a call to
3734 `Context.add_client_ca` replaces the CA name specified by the
Hynek Schlawack35618382015-09-05 21:54:25 +02003735 former call with the names specified by the latter call.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003736 """
3737 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3738 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3739 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3740
3741 cadesc = cacert.get_subject()
3742 sedesc = secert.get_subject()
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003743
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003744 def set_replaces_add_ca(ctx):
3745 ctx.add_client_ca(clcert)
3746 ctx.set_client_ca_list([cadesc])
3747 ctx.add_client_ca(secert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003748 return [cadesc, sedesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003749 self._check_client_ca_list(set_replaces_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003750
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003751
Alex Chanb7480992017-01-30 14:04:47 +00003752class TestInfoConstants(object):
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003753 """
3754 Tests for assorted constants exposed for use in info callbacks.
3755 """
3756 def test_integers(self):
3757 """
3758 All of the info constants are integers.
3759
3760 This is a very weak test. It would be nice to have one that actually
3761 verifies that as certain info events happen, the value passed to the
3762 info callback matches up with the constant exposed by OpenSSL.SSL.
3763 """
3764 for const in [
Alex Gaynor5af32d02016-09-24 01:52:21 -04003765 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK,
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003766 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
3767 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
3768 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
Hynek Schlawack35618382015-09-05 21:54:25 +02003769 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE
3770 ]:
Alex Gaynor5af32d02016-09-24 01:52:21 -04003771 assert isinstance(const, int)
3772
3773 # These constants don't exist on OpenSSL 1.1.0
3774 for const in [
3775 SSL_ST_INIT, SSL_ST_BEFORE, SSL_ST_OK, SSL_ST_RENEGOTIATE
3776 ]:
3777 assert const is None or isinstance(const, int)
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003778
Ziga Seilnacht44611bf2009-08-31 20:49:30 +02003779
Cory Benfield1d142142016-03-30 11:51:45 +01003780class TestRequires(object):
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003781 """
3782 Tests for the decorator factory used to conditionally raise
Cory Benfield1d142142016-03-30 11:51:45 +01003783 NotImplementedError when older OpenSSLs are used.
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003784 """
3785 def test_available(self):
3786 """
3787 When the OpenSSL functionality is available the decorated functions
3788 work appropriately.
3789 """
3790 feature_guard = _make_requires(True, "Error text")
3791 results = []
3792
3793 @feature_guard
3794 def inner():
3795 results.append(True)
3796 return True
3797
Cory Benfield2333e5e2016-03-30 14:24:16 +01003798 assert inner() is True
3799 assert [True] == results
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003800
3801 def test_unavailable(self):
3802 """
3803 When the OpenSSL functionality is not available the decorated function
3804 does not execute and NotImplementedError is raised.
3805 """
3806 feature_guard = _make_requires(False, "Error text")
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003807
3808 @feature_guard
Alex Chanfb078d82017-04-20 11:16:15 +01003809 def inner(): # pragma: nocover
3810 pytest.fail("Should not be called")
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003811
Cory Benfield1d142142016-03-30 11:51:45 +01003812 with pytest.raises(NotImplementedError) as e:
3813 inner()
3814
3815 assert "Error text" in str(e.value)
Cory Benfield496652a2017-01-24 11:42:56 +00003816
3817
Alex Chanb7480992017-01-30 14:04:47 +00003818class TestOCSP(object):
Cory Benfield496652a2017-01-24 11:42:56 +00003819 """
3820 Tests for PyOpenSSL's OCSP stapling support.
3821 """
3822 sample_ocsp_data = b"this is totally ocsp data"
3823
3824 def _client_connection(self, callback, data, request_ocsp=True):
3825 """
3826 Builds a client connection suitable for using OCSP.
3827
3828 :param callback: The callback to register for OCSP.
3829 :param data: The opaque data object that will be handed to the
3830 OCSP callback.
3831 :param request_ocsp: Whether the client will actually ask for OCSP
3832 stapling. Useful for testing only.
3833 """
3834 ctx = Context(SSLv23_METHOD)
3835 ctx.set_ocsp_client_callback(callback, data)
3836 client = Connection(ctx)
3837
3838 if request_ocsp:
3839 client.request_ocsp()
3840
3841 client.set_connect_state()
3842 return client
3843
3844 def _server_connection(self, callback, data):
3845 """
3846 Builds a server connection suitable for using OCSP.
3847
3848 :param callback: The callback to register for OCSP.
3849 :param data: The opaque data object that will be handed to the
3850 OCSP callback.
3851 """
3852 ctx = Context(SSLv23_METHOD)
3853 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
3854 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
3855 ctx.set_ocsp_server_callback(callback, data)
3856 server = Connection(ctx)
3857 server.set_accept_state()
3858 return server
3859
3860 def test_callbacks_arent_called_by_default(self):
3861 """
3862 If both the client and the server have registered OCSP callbacks, but
3863 the client does not send the OCSP request, neither callback gets
3864 called.
3865 """
Alex Chanfb078d82017-04-20 11:16:15 +01003866 def ocsp_callback(*args, **kwargs): # pragma: nocover
3867 pytest.fail("Should not be called")
Cory Benfield496652a2017-01-24 11:42:56 +00003868
3869 client = self._client_connection(
3870 callback=ocsp_callback, data=None, request_ocsp=False
3871 )
3872 server = self._server_connection(callback=ocsp_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00003873 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003874
Cory Benfield496652a2017-01-24 11:42:56 +00003875 def test_client_negotiates_without_server(self):
3876 """
3877 If the client wants to do OCSP but the server does not, the handshake
3878 succeeds, and the client callback fires with an empty byte string.
3879 """
3880 called = []
3881
3882 def ocsp_callback(conn, ocsp_data, ignored):
3883 called.append(ocsp_data)
3884 return True
3885
3886 client = self._client_connection(callback=ocsp_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00003887 server = loopback_server_factory(socket=None)
3888 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003889
3890 assert len(called) == 1
3891 assert called[0] == b''
3892
3893 def test_client_receives_servers_data(self):
3894 """
3895 The data the server sends in its callback is received by the client.
3896 """
3897 calls = []
3898
3899 def server_callback(*args, **kwargs):
3900 return self.sample_ocsp_data
3901
3902 def client_callback(conn, ocsp_data, ignored):
3903 calls.append(ocsp_data)
3904 return True
3905
3906 client = self._client_connection(callback=client_callback, data=None)
3907 server = self._server_connection(callback=server_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00003908 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003909
3910 assert len(calls) == 1
3911 assert calls[0] == self.sample_ocsp_data
3912
3913 def test_callbacks_are_invoked_with_connections(self):
3914 """
3915 The first arguments to both callbacks are their respective connections.
3916 """
3917 client_calls = []
3918 server_calls = []
3919
3920 def client_callback(conn, *args, **kwargs):
3921 client_calls.append(conn)
3922 return True
3923
3924 def server_callback(conn, *args, **kwargs):
3925 server_calls.append(conn)
3926 return self.sample_ocsp_data
3927
3928 client = self._client_connection(callback=client_callback, data=None)
3929 server = self._server_connection(callback=server_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00003930 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003931
3932 assert len(client_calls) == 1
3933 assert len(server_calls) == 1
3934 assert client_calls[0] is client
3935 assert server_calls[0] is server
3936
3937 def test_opaque_data_is_passed_through(self):
3938 """
3939 Both callbacks receive an opaque, user-provided piece of data in their
3940 callbacks as the final argument.
3941 """
3942 calls = []
3943
3944 def server_callback(*args):
3945 calls.append(args)
3946 return self.sample_ocsp_data
3947
3948 def client_callback(*args):
3949 calls.append(args)
3950 return True
3951
3952 sentinel = object()
3953
3954 client = self._client_connection(
3955 callback=client_callback, data=sentinel
3956 )
3957 server = self._server_connection(
3958 callback=server_callback, data=sentinel
3959 )
Alex Chanb7480992017-01-30 14:04:47 +00003960 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003961
3962 assert len(calls) == 2
3963 assert calls[0][-1] is sentinel
3964 assert calls[1][-1] is sentinel
3965
3966 def test_server_returns_empty_string(self):
3967 """
3968 If the server returns an empty bytestring from its callback, the
3969 client callback is called with the empty bytestring.
3970 """
3971 client_calls = []
3972
3973 def server_callback(*args):
3974 return b''
3975
3976 def client_callback(conn, ocsp_data, ignored):
3977 client_calls.append(ocsp_data)
3978 return True
3979
3980 client = self._client_connection(callback=client_callback, data=None)
3981 server = self._server_connection(callback=server_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00003982 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003983
3984 assert len(client_calls) == 1
3985 assert client_calls[0] == b''
3986
3987 def test_client_returns_false_terminates_handshake(self):
3988 """
3989 If the client returns False from its callback, the handshake fails.
3990 """
3991 def server_callback(*args):
3992 return self.sample_ocsp_data
3993
3994 def client_callback(*args):
3995 return False
3996
3997 client = self._client_connection(callback=client_callback, data=None)
3998 server = self._server_connection(callback=server_callback, data=None)
3999
4000 with pytest.raises(Error):
Alex Chanb7480992017-01-30 14:04:47 +00004001 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00004002
4003 def test_exceptions_in_client_bubble_up(self):
4004 """
4005 The callbacks thrown in the client callback bubble up to the caller.
4006 """
4007 class SentinelException(Exception):
4008 pass
4009
4010 def server_callback(*args):
4011 return self.sample_ocsp_data
4012
4013 def client_callback(*args):
4014 raise SentinelException()
4015
4016 client = self._client_connection(callback=client_callback, data=None)
4017 server = self._server_connection(callback=server_callback, data=None)
4018
4019 with pytest.raises(SentinelException):
Alex Chanb7480992017-01-30 14:04:47 +00004020 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00004021
4022 def test_exceptions_in_server_bubble_up(self):
4023 """
4024 The callbacks thrown in the server callback bubble up to the caller.
4025 """
4026 class SentinelException(Exception):
4027 pass
4028
4029 def server_callback(*args):
4030 raise SentinelException()
4031
Alex Chanfb078d82017-04-20 11:16:15 +01004032 def client_callback(*args): # pragma: nocover
Cory Benfield496652a2017-01-24 11:42:56 +00004033 pytest.fail("Should not be called")
4034
4035 client = self._client_connection(callback=client_callback, data=None)
4036 server = self._server_connection(callback=server_callback, data=None)
4037
4038 with pytest.raises(SentinelException):
Alex Chanb7480992017-01-30 14:04:47 +00004039 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00004040
4041 def test_server_must_return_bytes(self):
4042 """
4043 The server callback must return a bytestring, or a TypeError is thrown.
4044 """
4045 def server_callback(*args):
4046 return self.sample_ocsp_data.decode('ascii')
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(TypeError):
Alex Chanb7480992017-01-30 14:04:47 +00004055 handshake_in_memory(client, server)