blob: b09fce79dae9ca1d55b9e9039932a771b6a23f08 [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 (
Jean-Paul Calderoned899af02013-03-19 22:10:37 -070060 Context, ContextType, Session, Connection, ConnectionType, 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
Alex Chan1c0cb662017-01-30 07:13:30 +0000219def loopback_client_factory(socket):
Alex Gaynor85b17582017-08-07 11:52:08 -0400220 client = Connection(Context(SSLv23_METHOD), socket)
Alex Chan1c0cb662017-01-30 07:13:30 +0000221 client.set_connect_state()
222 return client
223
224
225def loopback_server_factory(socket):
Alex Gaynor85b17582017-08-07 11:52:08 -0400226 ctx = Context(SSLv23_METHOD)
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 Chan532b79e2017-01-24 15:14:52 +0000511 `Context` and `ContextType` refer to the same type object and can
512 be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -0500513 """
Alex Chan532b79e2017-01-24 15:14:52 +0000514 assert Context is ContextType
515 assert is_consistent_type(Context, 'Context', TLSv1_METHOD)
Rick Deane15b1472009-07-09 15:53:42 -0500516
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400517 def test_use_privatekey(self):
518 """
Alex Chan532b79e2017-01-24 15:14:52 +0000519 `Context.use_privatekey` takes an `OpenSSL.crypto.PKey` instance.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400520 """
521 key = PKey()
Alex Gaynor6e9f9762018-05-12 07:44:37 -0400522 key.generate_key(TYPE_RSA, 512)
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400523 ctx = Context(TLSv1_METHOD)
524 ctx.use_privatekey(key)
Alex Chan532b79e2017-01-24 15:14:52 +0000525 with pytest.raises(TypeError):
526 ctx.use_privatekey("")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400527
Alex Chan532b79e2017-01-24 15:14:52 +0000528 def test_use_privatekey_file_missing(self, tmpfile):
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800529 """
Alex Chan532b79e2017-01-24 15:14:52 +0000530 `Context.use_privatekey_file` raises `OpenSSL.SSL.Error` when passed
531 the name of a file which does not exist.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800532 """
533 ctx = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000534 with pytest.raises(Error):
535 ctx.use_privatekey_file(tmpfile)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800536
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400537 def _use_privatekey_file_test(self, pemfile, filetype):
538 """
539 Verify that calling ``Context.use_privatekey_file`` with the given
540 arguments does not raise an exception.
541 """
542 key = PKey()
Alex Gaynor6e9f9762018-05-12 07:44:37 -0400543 key.generate_key(TYPE_RSA, 512)
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400544
545 with open(pemfile, "wt") as pem:
546 pem.write(
547 dump_privatekey(FILETYPE_PEM, key).decode("ascii")
548 )
549
550 ctx = Context(TLSv1_METHOD)
551 ctx.use_privatekey_file(pemfile, filetype)
552
Alex Chanfb078d82017-04-20 11:16:15 +0100553 @pytest.mark.parametrize('filetype', [object(), "", None, 1.0])
554 def test_wrong_privatekey_file_wrong_args(self, tmpfile, filetype):
555 """
556 `Context.use_privatekey_file` raises `TypeError` when called with
557 a `filetype` which is not a valid file encoding.
558 """
559 ctx = Context(TLSv1_METHOD)
560 with pytest.raises(TypeError):
561 ctx.use_privatekey_file(tmpfile, filetype)
562
Alex Chan532b79e2017-01-24 15:14:52 +0000563 def test_use_privatekey_file_bytes(self, tmpfile):
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400564 """
565 A private key can be specified from a file by passing a ``bytes``
566 instance giving the file name to ``Context.use_privatekey_file``.
567 """
568 self._use_privatekey_file_test(
Alex Chan532b79e2017-01-24 15:14:52 +0000569 tmpfile + NON_ASCII.encode(getfilesystemencoding()),
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400570 FILETYPE_PEM,
571 )
572
Alex Chan532b79e2017-01-24 15:14:52 +0000573 def test_use_privatekey_file_unicode(self, tmpfile):
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400574 """
575 A private key can be specified from a file by passing a ``unicode``
576 instance giving the file name to ``Context.use_privatekey_file``.
577 """
578 self._use_privatekey_file_test(
Alex Chan532b79e2017-01-24 15:14:52 +0000579 tmpfile.decode(getfilesystemencoding()) + NON_ASCII,
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400580 FILETYPE_PEM,
581 )
582
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200583 @skip_if_py3
Alex Chan532b79e2017-01-24 15:14:52 +0000584 def test_use_privatekey_file_long(self, tmpfile):
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200585 """
Alex Chan532b79e2017-01-24 15:14:52 +0000586 On Python 2 `Context.use_privatekey_file` accepts a filetype of
587 type `long` as well as `int`.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200588 """
Alex Chan532b79e2017-01-24 15:14:52 +0000589 self._use_privatekey_file_test(tmpfile, long(FILETYPE_PEM))
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500590
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800591 def test_use_certificate_wrong_args(self):
592 """
Alex Chan532b79e2017-01-24 15:14:52 +0000593 `Context.use_certificate_wrong_args` raises `TypeError` when not passed
594 exactly one `OpenSSL.crypto.X509` instance as an argument.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800595 """
596 ctx = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000597 with pytest.raises(TypeError):
598 ctx.use_certificate("hello, world")
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800599
600 def test_use_certificate_uninitialized(self):
601 """
Alex Chan532b79e2017-01-24 15:14:52 +0000602 `Context.use_certificate` raises `OpenSSL.SSL.Error` when passed a
603 `OpenSSL.crypto.X509` instance which has not been initialized
604 (ie, which does not actually have any certificate data).
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800605 """
606 ctx = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000607 with pytest.raises(Error):
608 ctx.use_certificate(X509())
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800609
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800610 def test_use_certificate(self):
611 """
Alex Chan532b79e2017-01-24 15:14:52 +0000612 `Context.use_certificate` sets the certificate which will be
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800613 used to identify connections created using the context.
614 """
615 # TODO
616 # Hard to assert anything. But we could set a privatekey then ask
617 # OpenSSL if the cert and key agree using check_privatekey. Then as
618 # long as check_privatekey works right we're good...
619 ctx = Context(TLSv1_METHOD)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200620 ctx.use_certificate(
621 load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
622 )
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800623
624 def test_use_certificate_file_wrong_args(self):
625 """
Alex Chan532b79e2017-01-24 15:14:52 +0000626 `Context.use_certificate_file` raises `TypeError` if the first
627 argument is not a byte string or the second argument is not an integer.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800628 """
629 ctx = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000630 with pytest.raises(TypeError):
631 ctx.use_certificate_file(object(), FILETYPE_PEM)
632 with pytest.raises(TypeError):
633 ctx.use_certificate_file(b"somefile", object())
634 with pytest.raises(TypeError):
635 ctx.use_certificate_file(object(), FILETYPE_PEM)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800636
Alex Chan532b79e2017-01-24 15:14:52 +0000637 def test_use_certificate_file_missing(self, tmpfile):
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800638 """
Alex Chan532b79e2017-01-24 15:14:52 +0000639 `Context.use_certificate_file` raises `OpenSSL.SSL.Error` if passed
640 the name of a file which does not exist.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800641 """
642 ctx = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000643 with pytest.raises(Error):
644 ctx.use_certificate_file(tmpfile)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800645
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400646 def _use_certificate_file_test(self, certificate_file):
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800647 """
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400648 Verify that calling ``Context.use_certificate_file`` with the given
649 filename doesn't raise an exception.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800650 """
651 # TODO
652 # Hard to assert anything. But we could set a privatekey then ask
653 # OpenSSL if the cert and key agree using check_privatekey. Then as
654 # long as check_privatekey works right we're good...
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400655 with open(certificate_file, "wb") as pem_file:
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800656 pem_file.write(cleartextCertificatePEM)
657
658 ctx = Context(TLSv1_METHOD)
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400659 ctx.use_certificate_file(certificate_file)
660
Alex Chan532b79e2017-01-24 15:14:52 +0000661 def test_use_certificate_file_bytes(self, tmpfile):
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400662 """
Alex Chan532b79e2017-01-24 15:14:52 +0000663 `Context.use_certificate_file` sets the certificate (given as a
664 `bytes` filename) which will be used to identify connections created
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400665 using the context.
666 """
Alex Chan532b79e2017-01-24 15:14:52 +0000667 filename = tmpfile + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400668 self._use_certificate_file_test(filename)
669
Alex Chan532b79e2017-01-24 15:14:52 +0000670 def test_use_certificate_file_unicode(self, tmpfile):
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400671 """
Alex Chan532b79e2017-01-24 15:14:52 +0000672 `Context.use_certificate_file` sets the certificate (given as a
673 `bytes` filename) which will be used to identify connections created
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400674 using the context.
675 """
Alex Chan532b79e2017-01-24 15:14:52 +0000676 filename = tmpfile.decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400677 self._use_certificate_file_test(filename)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800678
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200679 @skip_if_py3
Alex Chan532b79e2017-01-24 15:14:52 +0000680 def test_use_certificate_file_long(self, tmpfile):
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200681 """
Alex Chan532b79e2017-01-24 15:14:52 +0000682 On Python 2 `Context.use_certificate_file` accepts a
683 filetype of type `long` as well as `int`.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200684 """
Alex Chan532b79e2017-01-24 15:14:52 +0000685 pem_filename = tmpfile
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200686 with open(pem_filename, "wb") as pem_file:
687 pem_file.write(cleartextCertificatePEM)
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500688
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200689 ctx = Context(TLSv1_METHOD)
690 ctx.use_certificate_file(pem_filename, long(FILETYPE_PEM))
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500691
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500692 def test_check_privatekey_valid(self):
693 """
Alex Chan532b79e2017-01-24 15:14:52 +0000694 `Context.check_privatekey` returns `None` if the `Context` instance
695 has been configured to use a matched key and certificate pair.
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500696 """
697 key = load_privatekey(FILETYPE_PEM, client_key_pem)
698 cert = load_certificate(FILETYPE_PEM, client_cert_pem)
699 context = Context(TLSv1_METHOD)
700 context.use_privatekey(key)
701 context.use_certificate(cert)
Alex Chan532b79e2017-01-24 15:14:52 +0000702 assert None is context.check_privatekey()
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500703
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500704 def test_check_privatekey_invalid(self):
705 """
Alex Chan532b79e2017-01-24 15:14:52 +0000706 `Context.check_privatekey` raises `Error` if the `Context` instance
707 has been configured to use a key and certificate pair which don't
708 relate to each other.
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500709 """
710 key = load_privatekey(FILETYPE_PEM, client_key_pem)
711 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
712 context = Context(TLSv1_METHOD)
713 context.use_privatekey(key)
714 context.use_certificate(cert)
Alex Chan532b79e2017-01-24 15:14:52 +0000715 with pytest.raises(Error):
716 context.check_privatekey()
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400717
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400718 def test_app_data(self):
719 """
Alex Chan532b79e2017-01-24 15:14:52 +0000720 `Context.set_app_data` stores an object for later retrieval
721 using `Context.get_app_data`.
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400722 """
723 app_data = object()
724 context = Context(TLSv1_METHOD)
725 context.set_app_data(app_data)
Alex Chan532b79e2017-01-24 15:14:52 +0000726 assert context.get_app_data() is app_data
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400727
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400728 def test_set_options_wrong_args(self):
729 """
Alex Chan532b79e2017-01-24 15:14:52 +0000730 `Context.set_options` raises `TypeError` if called with
731 a non-`int` argument.
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400732 """
733 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000734 with pytest.raises(TypeError):
735 context.set_options(None)
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400736
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500737 def test_set_options(self):
738 """
Alex Chan532b79e2017-01-24 15:14:52 +0000739 `Context.set_options` returns the new options value.
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500740 """
741 context = Context(TLSv1_METHOD)
742 options = context.set_options(OP_NO_SSLv2)
Alex Gaynor2310f8b2016-09-10 14:39:32 -0400743 assert options & OP_NO_SSLv2 == OP_NO_SSLv2
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500744
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200745 @skip_if_py3
746 def test_set_options_long(self):
747 """
Alex Chan532b79e2017-01-24 15:14:52 +0000748 On Python 2 `Context.set_options` accepts values of type
749 `long` as well as `int`.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200750 """
751 context = Context(TLSv1_METHOD)
752 options = context.set_options(long(OP_NO_SSLv2))
Alex Gaynor2310f8b2016-09-10 14:39:32 -0400753 assert options & OP_NO_SSLv2 == OP_NO_SSLv2
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500754
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300755 def test_set_mode_wrong_args(self):
756 """
Alex Chan532b79e2017-01-24 15:14:52 +0000757 `Context.set_mode` raises `TypeError` if called with
758 a non-`int` argument.
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300759 """
760 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000761 with pytest.raises(TypeError):
762 context.set_mode(None)
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300763
Alex Gaynord3b5d9b2016-07-31 10:54:24 -0400764 def test_set_mode(self):
765 """
Alex Chan532b79e2017-01-24 15:14:52 +0000766 `Context.set_mode` accepts a mode bitvector and returns the
Alex Gaynord3b5d9b2016-07-31 10:54:24 -0400767 newly set mode.
768 """
769 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000770 assert MODE_RELEASE_BUFFERS & context.set_mode(MODE_RELEASE_BUFFERS)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500771
Alex Gaynord3b5d9b2016-07-31 10:54:24 -0400772 @skip_if_py3
773 def test_set_mode_long(self):
774 """
Alex Chan532b79e2017-01-24 15:14:52 +0000775 On Python 2 `Context.set_mode` accepts values of type `long` as well
776 as `int`.
Alex Gaynord3b5d9b2016-07-31 10:54:24 -0400777 """
778 context = Context(TLSv1_METHOD)
779 mode = context.set_mode(long(MODE_RELEASE_BUFFERS))
Alex Chan532b79e2017-01-24 15:14:52 +0000780 assert MODE_RELEASE_BUFFERS & mode
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400781
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400782 def test_set_timeout_wrong_args(self):
783 """
Alex Chan532b79e2017-01-24 15:14:52 +0000784 `Context.set_timeout` raises `TypeError` if called with
785 a non-`int` argument.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400786 """
787 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000788 with pytest.raises(TypeError):
789 context.set_timeout(None)
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400790
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400791 def test_timeout(self):
792 """
Alex Chan532b79e2017-01-24 15:14:52 +0000793 `Context.set_timeout` sets the session timeout for all connections
794 created using the context object. `Context.get_timeout` retrieves
795 this value.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400796 """
797 context = Context(TLSv1_METHOD)
798 context.set_timeout(1234)
Alex Chan532b79e2017-01-24 15:14:52 +0000799 assert context.get_timeout() == 1234
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400800
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200801 @skip_if_py3
802 def test_timeout_long(self):
803 """
Alex Chan532b79e2017-01-24 15:14:52 +0000804 On Python 2 `Context.set_timeout` accepts values of type `long` as
805 well as int.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200806 """
807 context = Context(TLSv1_METHOD)
808 context.set_timeout(long(1234))
Alex Chan532b79e2017-01-24 15:14:52 +0000809 assert context.get_timeout() == 1234
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500810
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400811 def test_set_verify_depth_wrong_args(self):
812 """
Alex Chan532b79e2017-01-24 15:14:52 +0000813 `Context.set_verify_depth` raises `TypeError` if called with a
814 non-`int` argument.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400815 """
816 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000817 with pytest.raises(TypeError):
818 context.set_verify_depth(None)
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400819
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400820 def test_verify_depth(self):
821 """
Alex Chan532b79e2017-01-24 15:14:52 +0000822 `Context.set_verify_depth` sets the number of certificates in
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200823 a chain to follow before giving up. The value can be retrieved with
Alex Chan532b79e2017-01-24 15:14:52 +0000824 `Context.get_verify_depth`.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400825 """
826 context = Context(TLSv1_METHOD)
827 context.set_verify_depth(11)
Alex Chan532b79e2017-01-24 15:14:52 +0000828 assert context.get_verify_depth() == 11
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400829
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200830 @skip_if_py3
831 def test_verify_depth_long(self):
832 """
Alex Chan532b79e2017-01-24 15:14:52 +0000833 On Python 2 `Context.set_verify_depth` accepts values of type `long`
834 as well as int.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200835 """
836 context = Context(TLSv1_METHOD)
837 context.set_verify_depth(long(11))
Alex Chan532b79e2017-01-24 15:14:52 +0000838 assert context.get_verify_depth() == 11
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500839
Alex Chan532b79e2017-01-24 15:14:52 +0000840 def _write_encrypted_pem(self, passphrase, tmpfile):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400841 """
842 Write a new private key out to a new file, encrypted using the given
843 passphrase. Return the path to the new file.
844 """
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400845 key = PKey()
Alex Gaynor6e9f9762018-05-12 07:44:37 -0400846 key.generate_key(TYPE_RSA, 512)
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400847 pem = dump_privatekey(FILETYPE_PEM, key, "blowfish", passphrase)
Alex Chan532b79e2017-01-24 15:14:52 +0000848 with open(tmpfile, 'w') as fObj:
849 fObj.write(pem.decode('ascii'))
850 return tmpfile
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400851
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400852 def test_set_passwd_cb_wrong_args(self):
853 """
Alex Chan532b79e2017-01-24 15:14:52 +0000854 `Context.set_passwd_cb` raises `TypeError` if called with a
855 non-callable first argument.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400856 """
857 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000858 with pytest.raises(TypeError):
859 context.set_passwd_cb(None)
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400860
Alex Chan532b79e2017-01-24 15:14:52 +0000861 def test_set_passwd_cb(self, tmpfile):
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400862 """
Alex Chan532b79e2017-01-24 15:14:52 +0000863 `Context.set_passwd_cb` accepts a callable which will be invoked when
864 a private key is loaded from an encrypted PEM.
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400865 """
Alex Gaynore7f51982016-09-11 11:48:14 -0400866 passphrase = b"foobar"
Alex Chan532b79e2017-01-24 15:14:52 +0000867 pemFile = self._write_encrypted_pem(passphrase, tmpfile)
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400868 calledWith = []
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200869
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400870 def passphraseCallback(maxlen, verify, extra):
871 calledWith.append((maxlen, verify, extra))
872 return passphrase
873 context = Context(TLSv1_METHOD)
874 context.set_passwd_cb(passphraseCallback)
875 context.use_privatekey_file(pemFile)
Alex Chan532b79e2017-01-24 15:14:52 +0000876 assert len(calledWith) == 1
877 assert isinstance(calledWith[0][0], int)
878 assert isinstance(calledWith[0][1], int)
879 assert calledWith[0][2] is None
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400880
Alex Chan532b79e2017-01-24 15:14:52 +0000881 def test_passwd_callback_exception(self, tmpfile):
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400882 """
Alex Chan532b79e2017-01-24 15:14:52 +0000883 `Context.use_privatekey_file` propagates any exception raised
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200884 by the passphrase callback.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400885 """
Alex Chan532b79e2017-01-24 15:14:52 +0000886 pemFile = self._write_encrypted_pem(b"monkeys are nice", tmpfile)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200887
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400888 def passphraseCallback(maxlen, verify, extra):
889 raise RuntimeError("Sorry, I am a fail.")
890
891 context = Context(TLSv1_METHOD)
892 context.set_passwd_cb(passphraseCallback)
Alex Chan532b79e2017-01-24 15:14:52 +0000893 with pytest.raises(RuntimeError):
894 context.use_privatekey_file(pemFile)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400895
Alex Chan532b79e2017-01-24 15:14:52 +0000896 def test_passwd_callback_false(self, tmpfile):
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400897 """
Alex Chan532b79e2017-01-24 15:14:52 +0000898 `Context.use_privatekey_file` raises `OpenSSL.SSL.Error` if the
899 passphrase callback returns a false value.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400900 """
Alex Chan532b79e2017-01-24 15:14:52 +0000901 pemFile = self._write_encrypted_pem(b"monkeys are nice", tmpfile)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200902
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400903 def passphraseCallback(maxlen, verify, extra):
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500904 return b""
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400905
906 context = Context(TLSv1_METHOD)
907 context.set_passwd_cb(passphraseCallback)
Alex Chan532b79e2017-01-24 15:14:52 +0000908 with pytest.raises(Error):
909 context.use_privatekey_file(pemFile)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400910
Alex Chan532b79e2017-01-24 15:14:52 +0000911 def test_passwd_callback_non_string(self, tmpfile):
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400912 """
Alex Chan532b79e2017-01-24 15:14:52 +0000913 `Context.use_privatekey_file` raises `OpenSSL.SSL.Error` if the
914 passphrase callback returns a true non-string value.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400915 """
Alex Chan532b79e2017-01-24 15:14:52 +0000916 pemFile = self._write_encrypted_pem(b"monkeys are nice", tmpfile)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200917
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400918 def passphraseCallback(maxlen, verify, extra):
919 return 10
920
921 context = Context(TLSv1_METHOD)
922 context.set_passwd_cb(passphraseCallback)
Alex Chan532b79e2017-01-24 15:14:52 +0000923 # TODO: Surely this is the wrong error?
924 with pytest.raises(ValueError):
925 context.use_privatekey_file(pemFile)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400926
Alex Chan532b79e2017-01-24 15:14:52 +0000927 def test_passwd_callback_too_long(self, tmpfile):
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400928 """
929 If the passphrase returned by the passphrase callback returns a string
930 longer than the indicated maximum length, it is truncated.
931 """
932 # A priori knowledge!
Alex Gaynore7f51982016-09-11 11:48:14 -0400933 passphrase = b"x" * 1024
Alex Chan532b79e2017-01-24 15:14:52 +0000934 pemFile = self._write_encrypted_pem(passphrase, tmpfile)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200935
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400936 def passphraseCallback(maxlen, verify, extra):
937 assert maxlen == 1024
Alex Gaynore7f51982016-09-11 11:48:14 -0400938 return passphrase + b"y"
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400939
940 context = Context(TLSv1_METHOD)
941 context.set_passwd_cb(passphraseCallback)
942 # This shall succeed because the truncated result is the correct
943 # passphrase.
944 context.use_privatekey_file(pemFile)
945
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400946 def test_set_info_callback(self):
947 """
Alex Chan532b79e2017-01-24 15:14:52 +0000948 `Context.set_info_callback` accepts a callable which will be
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200949 invoked when certain information about an SSL connection is available.
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400950 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500951 (server, client) = socket_pair()
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400952
953 clientSSL = Connection(Context(TLSv1_METHOD), client)
954 clientSSL.set_connect_state()
955
956 called = []
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200957
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400958 def info(conn, where, ret):
959 called.append((conn, where, ret))
960 context = Context(TLSv1_METHOD)
961 context.set_info_callback(info)
962 context.use_certificate(
963 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
964 context.use_privatekey(
965 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
966
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400967 serverSSL = Connection(context, server)
968 serverSSL.set_accept_state()
969
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -0500970 handshake(clientSSL, serverSSL)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400971
Jean-Paul Calderone3835e522014-02-02 11:12:30 -0500972 # The callback must always be called with a Connection instance as the
973 # first argument. It would probably be better to split this into
974 # separate tests for client and server side info callbacks so we could
975 # assert it is called with the right Connection instance. It would
976 # also be good to assert *something* about `where` and `ret`.
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -0500977 notConnections = [
978 conn for (conn, where, ret) in called
979 if not isinstance(conn, Connection)]
Alex Chan532b79e2017-01-24 15:14:52 +0000980 assert [] == notConnections, (
981 "Some info callback arguments were not Connection instances.")
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400982
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400983 def _load_verify_locations_test(self, *args):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400984 """
985 Create a client context which will verify the peer certificate and call
Alex Chan532b79e2017-01-24 15:14:52 +0000986 its `load_verify_locations` method with the given arguments.
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -0400987 Then connect it to a server and ensure that the handshake succeeds.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400988 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500989 (server, client) = socket_pair()
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400990
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400991 clientContext = Context(TLSv1_METHOD)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400992 clientContext.load_verify_locations(*args)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400993 # Require that the server certificate verify properly or the
994 # connection will fail.
995 clientContext.set_verify(
996 VERIFY_PEER,
997 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
998
999 clientSSL = Connection(clientContext, client)
1000 clientSSL.set_connect_state()
1001
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001002 serverContext = Context(TLSv1_METHOD)
1003 serverContext.use_certificate(
1004 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1005 serverContext.use_privatekey(
1006 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1007
1008 serverSSL = Connection(serverContext, server)
1009 serverSSL.set_accept_state()
1010
Jean-Paul Calderonef8742032010-09-25 00:00:32 -04001011 # Without load_verify_locations above, the handshake
1012 # will fail:
1013 # Error: [('SSL routines', 'SSL3_GET_SERVER_CERTIFICATE',
1014 # 'certificate verify failed')]
1015 handshake(clientSSL, serverSSL)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001016
1017 cert = clientSSL.get_peer_certificate()
Alex Chan532b79e2017-01-24 15:14:52 +00001018 assert cert.get_subject().CN == 'Testing Root CA'
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -04001019
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001020 def _load_verify_cafile(self, cafile):
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001021 """
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001022 Verify that if path to a file containing a certificate is passed to
Alex Chan532b79e2017-01-24 15:14:52 +00001023 `Context.load_verify_locations` for the ``cafile`` parameter, that
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001024 certificate is used as a trust root for the purposes of verifying
Alex Chan532b79e2017-01-24 15:14:52 +00001025 connections created using that `Context`.
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001026 """
Alex Chan532b79e2017-01-24 15:14:52 +00001027 with open(cafile, 'w') as fObj:
1028 fObj.write(cleartextCertificatePEM.decode('ascii'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001029
1030 self._load_verify_locations_test(cafile)
1031
Alex Chan532b79e2017-01-24 15:14:52 +00001032 def test_load_verify_bytes_cafile(self, tmpfile):
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001033 """
Alex Chan532b79e2017-01-24 15:14:52 +00001034 `Context.load_verify_locations` accepts a file name as a `bytes`
1035 instance and uses the certificates within for verification purposes.
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001036 """
Alex Chan532b79e2017-01-24 15:14:52 +00001037 cafile = tmpfile + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001038 self._load_verify_cafile(cafile)
1039
Alex Chan532b79e2017-01-24 15:14:52 +00001040 def test_load_verify_unicode_cafile(self, tmpfile):
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001041 """
Alex Chan532b79e2017-01-24 15:14:52 +00001042 `Context.load_verify_locations` accepts a file name as a `unicode`
1043 instance and uses the certificates within for verification purposes.
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001044 """
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001045 self._load_verify_cafile(
Alex Chan532b79e2017-01-24 15:14:52 +00001046 tmpfile.decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001047 )
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001048
Alex Chan532b79e2017-01-24 15:14:52 +00001049 def test_load_verify_invalid_file(self, tmpfile):
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -04001050 """
Alex Chan532b79e2017-01-24 15:14:52 +00001051 `Context.load_verify_locations` raises `Error` when passed a
1052 non-existent cafile.
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -04001053 """
1054 clientContext = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001055 with pytest.raises(Error):
1056 clientContext.load_verify_locations(tmpfile)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001057
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001058 def _load_verify_directory_locations_capath(self, capath):
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001059 """
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001060 Verify that if path to a directory containing certificate files is
1061 passed to ``Context.load_verify_locations`` for the ``capath``
1062 parameter, those certificates are used as trust roots for the purposes
1063 of verifying connections created using that ``Context``.
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001064 """
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001065 makedirs(capath)
Jean-Paul Calderone24dfb332011-05-04 18:10:26 -04001066 # Hash values computed manually with c_rehash to avoid depending on
1067 # c_rehash in the test suite. One is from OpenSSL 0.9.8, the other
1068 # from OpenSSL 1.0.0.
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001069 for name in [b'c7adac82.0', b'c3705638.0']:
Jean-Paul Calderone05826732015-04-12 11:38:49 -04001070 cafile = join_bytes_or_unicode(capath, name)
1071 with open(cafile, 'w') as fObj:
1072 fObj.write(cleartextCertificatePEM.decode('ascii'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001073
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001074 self._load_verify_locations_test(None, capath)
1075
Alex Chan532b79e2017-01-24 15:14:52 +00001076 def test_load_verify_directory_bytes_capath(self, tmpfile):
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001077 """
Alex Chan532b79e2017-01-24 15:14:52 +00001078 `Context.load_verify_locations` accepts a directory name as a `bytes`
1079 instance and uses the certificates within for verification purposes.
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001080 """
1081 self._load_verify_directory_locations_capath(
Alex Chan532b79e2017-01-24 15:14:52 +00001082 tmpfile + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001083 )
1084
Alex Chan532b79e2017-01-24 15:14:52 +00001085 def test_load_verify_directory_unicode_capath(self, tmpfile):
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001086 """
Alex Chan532b79e2017-01-24 15:14:52 +00001087 `Context.load_verify_locations` accepts a directory name as a `unicode`
1088 instance and uses the certificates within for verification purposes.
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001089 """
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001090 self._load_verify_directory_locations_capath(
Alex Chan532b79e2017-01-24 15:14:52 +00001091 tmpfile.decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001092 )
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001093
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001094 def test_load_verify_locations_wrong_args(self):
1095 """
Alex Chan532b79e2017-01-24 15:14:52 +00001096 `Context.load_verify_locations` raises `TypeError` if with non-`str`
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001097 arguments.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001098 """
1099 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001100 with pytest.raises(TypeError):
1101 context.load_verify_locations(object())
1102 with pytest.raises(TypeError):
1103 context.load_verify_locations(object(), object())
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001104
Hynek Schlawack734d3022015-09-05 19:19:32 +02001105 @pytest.mark.skipif(
Paul Kehrer55fb3412017-06-29 18:44:08 -05001106 not platform.startswith("linux"),
1107 reason="Loading fallback paths is a linux-specific behavior to "
1108 "accommodate pyca/cryptography manylinux1 wheels"
1109 )
1110 def test_fallback_default_verify_paths(self, monkeypatch):
1111 """
1112 Test that we load certificates successfully on linux from the fallback
1113 path. To do this we set the _CRYPTOGRAPHY_MANYLINUX1_CA_FILE and
1114 _CRYPTOGRAPHY_MANYLINUX1_CA_DIR vars to be equal to whatever the
1115 current OpenSSL default is and we disable
1116 SSL_CTX_SET_default_verify_paths so that it can't find certs unless
1117 it loads via fallback.
1118 """
1119 context = Context(TLSv1_METHOD)
1120 monkeypatch.setattr(
1121 _lib, "SSL_CTX_set_default_verify_paths", lambda x: 1
1122 )
1123 monkeypatch.setattr(
1124 SSL,
1125 "_CRYPTOGRAPHY_MANYLINUX1_CA_FILE",
1126 _ffi.string(_lib.X509_get_default_cert_file())
1127 )
1128 monkeypatch.setattr(
1129 SSL,
1130 "_CRYPTOGRAPHY_MANYLINUX1_CA_DIR",
1131 _ffi.string(_lib.X509_get_default_cert_dir())
1132 )
1133 context.set_default_verify_paths()
1134 store = context.get_cert_store()
1135 sk_obj = _lib.X509_STORE_get0_objects(store._store)
1136 assert sk_obj != _ffi.NULL
1137 num = _lib.sk_X509_OBJECT_num(sk_obj)
1138 assert num != 0
1139
1140 def test_check_env_vars(self, monkeypatch):
1141 """
1142 Test that we return True/False appropriately if the env vars are set.
1143 """
1144 context = Context(TLSv1_METHOD)
1145 dir_var = "CUSTOM_DIR_VAR"
1146 file_var = "CUSTOM_FILE_VAR"
1147 assert context._check_env_vars_set(dir_var, file_var) is False
1148 monkeypatch.setenv(dir_var, "value")
1149 monkeypatch.setenv(file_var, "value")
1150 assert context._check_env_vars_set(dir_var, file_var) is True
1151 assert context._check_env_vars_set(dir_var, file_var) is True
1152
1153 def test_verify_no_fallback_if_env_vars_set(self, monkeypatch):
1154 """
1155 Test that we don't use the fallback path if env vars are set.
1156 """
1157 context = Context(TLSv1_METHOD)
1158 monkeypatch.setattr(
1159 _lib, "SSL_CTX_set_default_verify_paths", lambda x: 1
1160 )
1161 dir_env_var = _ffi.string(
1162 _lib.X509_get_default_cert_dir_env()
1163 ).decode("ascii")
1164 file_env_var = _ffi.string(
1165 _lib.X509_get_default_cert_file_env()
1166 ).decode("ascii")
1167 monkeypatch.setenv(dir_env_var, "value")
1168 monkeypatch.setenv(file_env_var, "value")
1169 context.set_default_verify_paths()
1170
1171 monkeypatch.setattr(
1172 context,
1173 "_fallback_default_verify_paths",
1174 raiser(SystemError)
1175 )
1176 context.set_default_verify_paths()
1177
1178 @pytest.mark.skipif(
Hynek Schlawack734d3022015-09-05 19:19:32 +02001179 platform == "win32",
1180 reason="set_default_verify_paths appears not to work on Windows. "
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -04001181 "See LP#404343 and LP#404344."
Hynek Schlawack734d3022015-09-05 19:19:32 +02001182 )
1183 def test_set_default_verify_paths(self):
1184 """
Alex Chan532b79e2017-01-24 15:14:52 +00001185 `Context.set_default_verify_paths` causes the platform-specific CA
1186 certificate locations to be used for verification purposes.
Hynek Schlawack734d3022015-09-05 19:19:32 +02001187 """
1188 # Testing this requires a server with a certificate signed by one
1189 # of the CAs in the platform CA location. Getting one of those
1190 # costs money. Fortunately (or unfortunately, depending on your
1191 # perspective), it's easy to think of a public server on the
1192 # internet which has such a certificate. Connecting to the network
1193 # in a unit test is bad, but it's the only way I can think of to
1194 # really test this. -exarkun
Hynek Schlawackbf887932015-10-21 17:13:47 +02001195 context = Context(SSLv23_METHOD)
Hynek Schlawack734d3022015-09-05 19:19:32 +02001196 context.set_default_verify_paths()
1197 context.set_verify(
1198 VERIFY_PEER,
1199 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001200
Hynek Schlawack734d3022015-09-05 19:19:32 +02001201 client = socket()
Hynek Schlawackbf887932015-10-21 17:13:47 +02001202 client.connect(("encrypted.google.com", 443))
Hynek Schlawack734d3022015-09-05 19:19:32 +02001203 clientSSL = Connection(context, client)
1204 clientSSL.set_connect_state()
Alex Gaynor373926c2018-05-12 07:43:07 -04001205 clientSSL.set_tlsext_host_name(b"encrypted.google.com")
Hynek Schlawack734d3022015-09-05 19:19:32 +02001206 clientSSL.do_handshake()
1207 clientSSL.send(b"GET / HTTP/1.0\r\n\r\n")
Alex Chan532b79e2017-01-24 15:14:52 +00001208 assert clientSSL.recv(1024)
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05001209
Paul Kehrer55fb3412017-06-29 18:44:08 -05001210 def test_fallback_path_is_not_file_or_dir(self):
1211 """
1212 Test that when passed empty arrays or paths that do not exist no
1213 errors are raised.
1214 """
1215 context = Context(TLSv1_METHOD)
1216 context._fallback_default_verify_paths([], [])
1217 context._fallback_default_verify_paths(
1218 ["/not/a/file"], ["/not/a/dir"]
1219 )
1220
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001221 def test_add_extra_chain_cert_invalid_cert(self):
1222 """
Alex Chan532b79e2017-01-24 15:14:52 +00001223 `Context.add_extra_chain_cert` raises `TypeError` if called with an
1224 object which is not an instance of `X509`.
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001225 """
1226 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001227 with pytest.raises(TypeError):
1228 context.add_extra_chain_cert(object())
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001229
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001230 def _handshake_test(self, serverContext, clientContext):
1231 """
1232 Verify that a client and server created with the given contexts can
1233 successfully handshake and communicate.
1234 """
1235 serverSocket, clientSocket = socket_pair()
1236
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001237 server = Connection(serverContext, serverSocket)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001238 server.set_accept_state()
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001239
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001240 client = Connection(clientContext, clientSocket)
1241 client.set_connect_state()
1242
1243 # Make them talk to each other.
Alex Chan532b79e2017-01-24 15:14:52 +00001244 # interact_in_memory(client, server)
1245 for _ in range(3):
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001246 for s in [client, server]:
1247 try:
1248 s.do_handshake()
1249 except WantReadError:
1250 pass
1251
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001252 def test_set_verify_callback_connection_argument(self):
1253 """
1254 The first argument passed to the verify callback is the
Alex Chan532b79e2017-01-24 15:14:52 +00001255 `Connection` instance for which verification is taking place.
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001256 """
1257 serverContext = Context(TLSv1_METHOD)
1258 serverContext.use_privatekey(
1259 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1260 serverContext.use_certificate(
1261 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1262 serverConnection = Connection(serverContext, None)
1263
1264 class VerifyCallback(object):
1265 def callback(self, connection, *args):
1266 self.connection = connection
1267 return 1
1268
1269 verify = VerifyCallback()
1270 clientContext = Context(TLSv1_METHOD)
1271 clientContext.set_verify(VERIFY_PEER, verify.callback)
1272 clientConnection = Connection(clientContext, None)
1273 clientConnection.set_connect_state()
1274
Alex Chan532b79e2017-01-24 15:14:52 +00001275 handshake_in_memory(clientConnection, serverConnection)
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001276
Alex Chan532b79e2017-01-24 15:14:52 +00001277 assert verify.connection is clientConnection
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001278
Paul Kehrere7381862017-11-30 20:55:25 +08001279 def test_x509_in_verify_works(self):
1280 """
1281 We had a bug where the X509 cert instantiated in the callback wrapper
1282 didn't __init__ so it was missing objects needed when calling
1283 get_subject. This test sets up a handshake where we call get_subject
1284 on the cert provided to the verify callback.
1285 """
1286 serverContext = Context(TLSv1_METHOD)
1287 serverContext.use_privatekey(
1288 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1289 serverContext.use_certificate(
1290 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1291 serverConnection = Connection(serverContext, None)
1292
1293 def verify_cb_get_subject(conn, cert, errnum, depth, ok):
1294 assert cert.get_subject()
1295 return 1
1296
1297 clientContext = Context(TLSv1_METHOD)
1298 clientContext.set_verify(VERIFY_PEER, verify_cb_get_subject)
1299 clientConnection = Connection(clientContext, None)
1300 clientConnection.set_connect_state()
1301
1302 handshake_in_memory(clientConnection, serverConnection)
1303
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001304 def test_set_verify_callback_exception(self):
1305 """
Alex Chan532b79e2017-01-24 15:14:52 +00001306 If the verify callback passed to `Context.set_verify` raises an
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001307 exception, verification fails and the exception is propagated to the
Alex Chan532b79e2017-01-24 15:14:52 +00001308 caller of `Connection.do_handshake`.
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001309 """
1310 serverContext = Context(TLSv1_METHOD)
1311 serverContext.use_privatekey(
1312 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1313 serverContext.use_certificate(
1314 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1315
1316 clientContext = Context(TLSv1_METHOD)
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001317
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001318 def verify_callback(*args):
1319 raise Exception("silly verify failure")
1320 clientContext.set_verify(VERIFY_PEER, verify_callback)
1321
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01001322 with pytest.raises(Exception) as exc:
1323 self._handshake_test(serverContext, clientContext)
1324
Alex Chan532b79e2017-01-24 15:14:52 +00001325 assert "silly verify failure" == str(exc.value)
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001326
Alex Chan532b79e2017-01-24 15:14:52 +00001327 def test_add_extra_chain_cert(self, tmpdir):
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001328 """
Alex Chan532b79e2017-01-24 15:14:52 +00001329 `Context.add_extra_chain_cert` accepts an `X509`
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001330 instance to add to the certificate chain.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001331
Alex Chan532b79e2017-01-24 15:14:52 +00001332 See `_create_certificate_chain` for the details of the
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001333 certificate chain tested.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001334
1335 The chain is tested by starting a server with scert and connecting
1336 to it with a client which trusts cacert and requires verification to
1337 succeed.
1338 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001339 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001340 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1341
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001342 # Dump the CA certificate to a file because that's the only way to load
1343 # it as a trusted CA in the client context.
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001344 for cert, name in [(cacert, 'ca.pem'),
1345 (icert, 'i.pem'),
1346 (scert, 's.pem')]:
Alex Chan532b79e2017-01-24 15:14:52 +00001347 with tmpdir.join(name).open('w') as f:
Hynek Schlawacke90680f2015-04-16 15:09:27 -04001348 f.write(dump_certificate(FILETYPE_PEM, cert).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001349
Hynek Schlawack1902c012015-04-16 15:06:41 -04001350 for key, name in [(cakey, 'ca.key'),
1351 (ikey, 'i.key'),
1352 (skey, 's.key')]:
Alex Chan532b79e2017-01-24 15:14:52 +00001353 with tmpdir.join(name).open('w') as f:
Hynek Schlawacke90680f2015-04-16 15:09:27 -04001354 f.write(dump_privatekey(FILETYPE_PEM, key).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001355
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001356 # Create the server context
1357 serverContext = Context(TLSv1_METHOD)
1358 serverContext.use_privatekey(skey)
1359 serverContext.use_certificate(scert)
Jean-Paul Calderone16cf03d2010-09-08 18:53:39 -04001360 # The client already has cacert, we only need to give them icert.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001361 serverContext.add_extra_chain_cert(icert)
1362
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001363 # Create the client
1364 clientContext = Context(TLSv1_METHOD)
1365 clientContext.set_verify(
1366 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Alex Chan532b79e2017-01-24 15:14:52 +00001367 clientContext.load_verify_locations(str(tmpdir.join("ca.pem")))
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001368
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001369 # Try it out.
1370 self._handshake_test(serverContext, clientContext)
1371
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001372 def _use_certificate_chain_file_test(self, certdir):
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001373 """
Alex Chan532b79e2017-01-24 15:14:52 +00001374 Verify that `Context.use_certificate_chain_file` reads a
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001375 certificate chain from a specified file.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001376
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001377 The chain is tested by starting a server with scert and connecting to
1378 it with a client which trusts cacert and requires verification to
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001379 succeed.
1380 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001381 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001382 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1383
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001384 makedirs(certdir)
1385
Jean-Paul Calderone05826732015-04-12 11:38:49 -04001386 chainFile = join_bytes_or_unicode(certdir, "chain.pem")
1387 caFile = join_bytes_or_unicode(certdir, "ca.pem")
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001388
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001389 # Write out the chain file.
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001390 with open(chainFile, 'wb') as fObj:
1391 # Most specific to least general.
1392 fObj.write(dump_certificate(FILETYPE_PEM, scert))
1393 fObj.write(dump_certificate(FILETYPE_PEM, icert))
1394 fObj.write(dump_certificate(FILETYPE_PEM, cacert))
1395
1396 with open(caFile, 'w') as fObj:
1397 fObj.write(dump_certificate(FILETYPE_PEM, cacert).decode('ascii'))
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001398
1399 serverContext = Context(TLSv1_METHOD)
1400 serverContext.use_certificate_chain_file(chainFile)
1401 serverContext.use_privatekey(skey)
1402
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001403 clientContext = Context(TLSv1_METHOD)
1404 clientContext.set_verify(
1405 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001406 clientContext.load_verify_locations(caFile)
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001407
1408 self._handshake_test(serverContext, clientContext)
1409
Alex Chan532b79e2017-01-24 15:14:52 +00001410 def test_use_certificate_chain_file_bytes(self, tmpfile):
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001411 """
1412 ``Context.use_certificate_chain_file`` accepts the name of a file (as
1413 an instance of ``bytes``) to specify additional certificates to use to
1414 construct and verify a trust chain.
1415 """
1416 self._use_certificate_chain_file_test(
Alex Chan532b79e2017-01-24 15:14:52 +00001417 tmpfile + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001418 )
1419
Alex Chan532b79e2017-01-24 15:14:52 +00001420 def test_use_certificate_chain_file_unicode(self, tmpfile):
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001421 """
1422 ``Context.use_certificate_chain_file`` accepts the name of a file (as
1423 an instance of ``unicode``) to specify additional certificates to use
1424 to construct and verify a trust chain.
1425 """
1426 self._use_certificate_chain_file_test(
Alex Chan532b79e2017-01-24 15:14:52 +00001427 tmpfile.decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001428 )
1429
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001430 def test_use_certificate_chain_file_wrong_args(self):
1431 """
Alex Chan532b79e2017-01-24 15:14:52 +00001432 `Context.use_certificate_chain_file` raises `TypeError` if passed a
1433 non-byte string single argument.
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001434 """
1435 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001436 with pytest.raises(TypeError):
1437 context.use_certificate_chain_file(object())
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001438
Alex Chan532b79e2017-01-24 15:14:52 +00001439 def test_use_certificate_chain_file_missing_file(self, tmpfile):
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001440 """
Alex Chan532b79e2017-01-24 15:14:52 +00001441 `Context.use_certificate_chain_file` raises `OpenSSL.SSL.Error` when
1442 passed a bad chain file name (for example, the name of a file which
1443 does not exist).
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001444 """
1445 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001446 with pytest.raises(Error):
1447 context.use_certificate_chain_file(tmpfile)
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001448
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001449 def test_set_verify_mode(self):
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001450 """
Alex Chan532b79e2017-01-24 15:14:52 +00001451 `Context.get_verify_mode` returns the verify mode flags previously
1452 passed to `Context.set_verify`.
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001453 """
1454 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001455 assert context.get_verify_mode() == 0
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001456 context.set_verify(
1457 VERIFY_PEER | VERIFY_CLIENT_ONCE, lambda *args: None)
Alex Chan532b79e2017-01-24 15:14:52 +00001458 assert context.get_verify_mode() == (VERIFY_PEER | VERIFY_CLIENT_ONCE)
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001459
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001460 @skip_if_py3
1461 def test_set_verify_mode_long(self):
1462 """
Alex Chan532b79e2017-01-24 15:14:52 +00001463 On Python 2 `Context.set_verify_mode` accepts values of type `long`
1464 as well as `int`.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001465 """
1466 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001467 assert context.get_verify_mode() == 0
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001468 context.set_verify(
Hynek Schlawackb4ceed32015-09-05 20:55:19 +02001469 long(VERIFY_PEER | VERIFY_CLIENT_ONCE), lambda *args: None
1470 ) # pragma: nocover
Alex Chan532b79e2017-01-24 15:14:52 +00001471 assert context.get_verify_mode() == (VERIFY_PEER | VERIFY_CLIENT_ONCE)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001472
Alex Chanfb078d82017-04-20 11:16:15 +01001473 @pytest.mark.parametrize('mode', [None, 1.0, object(), 'mode'])
1474 def test_set_verify_wrong_mode_arg(self, mode):
1475 """
1476 `Context.set_verify` raises `TypeError` if the first argument is
1477 not an integer.
1478 """
1479 context = Context(TLSv1_METHOD)
1480 with pytest.raises(TypeError):
1481 context.set_verify(mode=mode, callback=lambda *args: None)
1482
1483 @pytest.mark.parametrize('callback', [None, 1.0, 'mode', ('foo', 'bar')])
1484 def test_set_verify_wrong_callable_arg(self, callback):
1485 """
Alex Gaynor40bc0f12018-05-14 14:06:16 -04001486 `Context.set_verify` raises `TypeError` if the second argument
Alex Chanfb078d82017-04-20 11:16:15 +01001487 is not callable.
1488 """
1489 context = Context(TLSv1_METHOD)
1490 with pytest.raises(TypeError):
1491 context.set_verify(mode=VERIFY_PEER, callback=callback)
1492
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001493 def test_load_tmp_dh_wrong_args(self):
1494 """
Alex Chan532b79e2017-01-24 15:14:52 +00001495 `Context.load_tmp_dh` raises `TypeError` if called with a
1496 non-`str` argument.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001497 """
1498 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001499 with pytest.raises(TypeError):
1500 context.load_tmp_dh(object())
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001501
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001502 def test_load_tmp_dh_missing_file(self):
1503 """
Alex Chan532b79e2017-01-24 15:14:52 +00001504 `Context.load_tmp_dh` raises `OpenSSL.SSL.Error` if the
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001505 specified file does not exist.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001506 """
1507 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001508 with pytest.raises(Error):
1509 context.load_tmp_dh(b"hello")
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001510
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001511 def _load_tmp_dh_test(self, dhfilename):
Jean-Paul Calderone4e0c43f2015-04-13 10:15:17 -04001512 """
1513 Verify that calling ``Context.load_tmp_dh`` with the given filename
1514 does not raise an exception.
1515 """
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001516 context = Context(TLSv1_METHOD)
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001517 with open(dhfilename, "w") as dhfile:
1518 dhfile.write(dhparam)
1519
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001520 context.load_tmp_dh(dhfilename)
1521 # XXX What should I assert here? -exarkun
1522
Alex Chan532b79e2017-01-24 15:14:52 +00001523 def test_load_tmp_dh_bytes(self, tmpfile):
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001524 """
Alex Chan532b79e2017-01-24 15:14:52 +00001525 `Context.load_tmp_dh` loads Diffie-Hellman parameters from the
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001526 specified file (given as ``bytes``).
1527 """
1528 self._load_tmp_dh_test(
Alex Chan532b79e2017-01-24 15:14:52 +00001529 tmpfile + NON_ASCII.encode(getfilesystemencoding()),
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001530 )
1531
Alex Chan532b79e2017-01-24 15:14:52 +00001532 def test_load_tmp_dh_unicode(self, tmpfile):
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001533 """
Alex Chan532b79e2017-01-24 15:14:52 +00001534 `Context.load_tmp_dh` loads Diffie-Hellman parameters from the
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001535 specified file (given as ``unicode``).
1536 """
1537 self._load_tmp_dh_test(
Alex Chan532b79e2017-01-24 15:14:52 +00001538 tmpfile.decode(getfilesystemencoding()) + NON_ASCII,
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001539 )
1540
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001541 def test_set_tmp_ecdh(self):
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001542 """
Alex Chan532b79e2017-01-24 15:14:52 +00001543 `Context.set_tmp_ecdh` sets the elliptic curve for Diffie-Hellman to
1544 the specified curve.
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001545 """
1546 context = Context(TLSv1_METHOD)
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001547 for curve in get_elliptic_curves():
Hynek Schlawacka07fa8c2015-10-17 10:15:28 +02001548 if curve.name.startswith(u"Oakley-"):
Hynek Schlawack7408aff2015-10-17 09:51:16 +02001549 # Setting Oakley-EC2N-4 and Oakley-EC2N-3 adds
1550 # ('bignum routines', 'BN_mod_inverse', 'no inverse') to the
1551 # error queue on OpenSSL 1.0.2.
1552 continue
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001553 # The only easily "assertable" thing is that it does not raise an
1554 # exception.
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001555 context.set_tmp_ecdh(curve)
Alex Gaynor12dc0842014-01-17 12:51:31 -06001556
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001557 def test_set_session_cache_mode_wrong_args(self):
1558 """
Alex Chan532b79e2017-01-24 15:14:52 +00001559 `Context.set_session_cache_mode` raises `TypeError` if called with
1560 a non-integer argument.
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001561 called with other than one integer argument.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001562 """
1563 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001564 with pytest.raises(TypeError):
1565 context.set_session_cache_mode(object())
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001566
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001567 def test_session_cache_mode(self):
1568 """
Alex Chan532b79e2017-01-24 15:14:52 +00001569 `Context.set_session_cache_mode` specifies how sessions are cached.
1570 The setting can be retrieved via `Context.get_session_cache_mode`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001571 """
1572 context = Context(TLSv1_METHOD)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001573 context.set_session_cache_mode(SESS_CACHE_OFF)
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001574 off = context.set_session_cache_mode(SESS_CACHE_BOTH)
Alex Chan532b79e2017-01-24 15:14:52 +00001575 assert SESS_CACHE_OFF == off
1576 assert SESS_CACHE_BOTH == context.get_session_cache_mode()
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001577
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001578 @skip_if_py3
1579 def test_session_cache_mode_long(self):
1580 """
Alex Chan532b79e2017-01-24 15:14:52 +00001581 On Python 2 `Context.set_session_cache_mode` accepts values
1582 of type `long` as well as `int`.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001583 """
1584 context = Context(TLSv1_METHOD)
1585 context.set_session_cache_mode(long(SESS_CACHE_BOTH))
Alex Chan532b79e2017-01-24 15:14:52 +00001586 assert SESS_CACHE_BOTH == context.get_session_cache_mode()
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001587
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001588 def test_get_cert_store(self):
1589 """
Alex Chan532b79e2017-01-24 15:14:52 +00001590 `Context.get_cert_store` returns a `X509Store` instance.
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001591 """
1592 context = Context(TLSv1_METHOD)
1593 store = context.get_cert_store()
Alex Chan532b79e2017-01-24 15:14:52 +00001594 assert isinstance(store, X509Store)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001595
Jeremy Lainé02261ad2018-05-16 18:33:25 +02001596 def test_set_tlsext_use_srtp_not_bytes(self):
1597 """
1598 `Context.set_tlsext_use_srtp' enables negotiating SRTP keying material.
1599
1600 It raises a TypeError if the list of profiles is not a byte string.
1601 """
1602 context = Context(TLSv1_METHOD)
1603 with pytest.raises(TypeError):
1604 context.set_tlsext_use_srtp(text_type('SRTP_AES128_CM_SHA1_80'))
1605
1606 def test_set_tlsext_use_srtp_invalid_profile(self):
1607 """
1608 `Context.set_tlsext_use_srtp' enables negotiating SRTP keying material.
1609
1610 It raises an Error if the call to OpenSSL fails.
1611 """
1612 context = Context(TLSv1_METHOD)
1613 with pytest.raises(Error):
1614 context.set_tlsext_use_srtp(b'SRTP_BOGUS')
1615
1616 def test_set_tlsext_use_srtp_valid(self):
1617 """
1618 `Context.set_tlsext_use_srtp' enables negotiating SRTP keying material.
1619
1620 It does not return anything.
1621 """
1622 context = Context(TLSv1_METHOD)
1623 assert context.set_tlsext_use_srtp(b'SRTP_AES128_CM_SHA1_80') is None
1624
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001625
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001626class TestServerNameCallback(object):
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001627 """
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001628 Tests for `Context.set_tlsext_servername_callback` and its
1629 interaction with `Connection`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001630 """
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001631 def test_old_callback_forgotten(self):
1632 """
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001633 If `Context.set_tlsext_servername_callback` is used to specify
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001634 a new callback, the one it replaces is dereferenced.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001635 """
Alex Chanfb078d82017-04-20 11:16:15 +01001636 def callback(connection): # pragma: no cover
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001637 pass
1638
Alex Chanfb078d82017-04-20 11:16:15 +01001639 def replacement(connection): # pragma: no cover
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001640 pass
1641
1642 context = Context(TLSv1_METHOD)
1643 context.set_tlsext_servername_callback(callback)
1644
1645 tracker = ref(callback)
1646 del callback
1647
1648 context.set_tlsext_servername_callback(replacement)
Jean-Paul Calderoned4033eb2014-01-11 08:21:46 -05001649
1650 # One run of the garbage collector happens to work on CPython. PyPy
1651 # doesn't collect the underlying object until a second run for whatever
1652 # reason. That's fine, it still demonstrates our code has properly
1653 # dropped the reference.
1654 collect()
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001655 collect()
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001656
1657 callback = tracker()
1658 if callback is not None:
1659 referrers = get_referrers(callback)
Alex Chanfb078d82017-04-20 11:16:15 +01001660 if len(referrers) > 1: # pragma: nocover
1661 pytest.fail("Some references remain: %r" % (referrers,))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001662
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001663 def test_no_servername(self):
1664 """
1665 When a client specifies no server name, the callback passed to
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001666 `Context.set_tlsext_servername_callback` is invoked and the
1667 result of `Connection.get_servername` is `None`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001668 """
1669 args = []
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001670
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001671 def servername(conn):
1672 args.append((conn, conn.get_servername()))
1673 context = Context(TLSv1_METHOD)
1674 context.set_tlsext_servername_callback(servername)
1675
1676 # Lose our reference to it. The Context is responsible for keeping it
1677 # alive now.
1678 del servername
1679 collect()
1680
1681 # Necessary to actually accept the connection
1682 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001683 context.use_certificate(
1684 load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001685
1686 # Do a little connection to trigger the logic
1687 server = Connection(context, None)
1688 server.set_accept_state()
1689
1690 client = Connection(Context(TLSv1_METHOD), None)
1691 client.set_connect_state()
1692
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001693 interact_in_memory(server, client)
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001694
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001695 assert args == [(server, None)]
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001696
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001697 def test_servername(self):
1698 """
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001699 When a client specifies a server name in its hello message, the
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001700 callback passed to `Contexts.set_tlsext_servername_callback` is
1701 invoked and the result of `Connection.get_servername` is that
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001702 server name.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001703 """
1704 args = []
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001705
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001706 def servername(conn):
1707 args.append((conn, conn.get_servername()))
1708 context = Context(TLSv1_METHOD)
1709 context.set_tlsext_servername_callback(servername)
1710
1711 # Necessary to actually accept the connection
1712 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001713 context.use_certificate(
1714 load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001715
1716 # Do a little connection to trigger the logic
1717 server = Connection(context, None)
1718 server.set_accept_state()
1719
1720 client = Connection(Context(TLSv1_METHOD), None)
1721 client.set_connect_state()
Alex Gaynore7f51982016-09-11 11:48:14 -04001722 client.set_tlsext_host_name(b"foo1.example.com")
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001723
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001724 interact_in_memory(server, client)
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001725
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001726 assert args == [(server, b"foo1.example.com")]
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001727
1728
Alex Chan9e08b3e2016-11-10 12:18:54 +00001729class TestNextProtoNegotiation(object):
Cory Benfield84a121e2014-03-31 20:30:25 +01001730 """
1731 Test for Next Protocol Negotiation in PyOpenSSL.
1732 """
Alex Chan9e08b3e2016-11-10 12:18:54 +00001733 def test_npn_success(self):
1734 """
1735 Tests that clients and servers that agree on the negotiated next
1736 protocol can correct establish a connection, and that the agreed
1737 protocol is reported by the connections.
1738 """
1739 advertise_args = []
1740 select_args = []
1741
1742 def advertise(conn):
1743 advertise_args.append((conn,))
1744 return [b'http/1.1', b'spdy/2']
1745
1746 def select(conn, options):
1747 select_args.append((conn, options))
1748 return b'spdy/2'
1749
1750 server_context = Context(TLSv1_METHOD)
1751 server_context.set_npn_advertise_callback(advertise)
1752
1753 client_context = Context(TLSv1_METHOD)
1754 client_context.set_npn_select_callback(select)
1755
1756 # Necessary to actually accept the connection
1757 server_context.use_privatekey(
1758 load_privatekey(FILETYPE_PEM, server_key_pem))
1759 server_context.use_certificate(
1760 load_certificate(FILETYPE_PEM, server_cert_pem))
1761
1762 # Do a little connection to trigger the logic
1763 server = Connection(server_context, None)
1764 server.set_accept_state()
1765
1766 client = Connection(client_context, None)
1767 client.set_connect_state()
1768
1769 interact_in_memory(server, client)
1770
1771 assert advertise_args == [(server,)]
1772 assert select_args == [(client, [b'http/1.1', b'spdy/2'])]
1773
1774 assert server.get_next_proto_negotiated() == b'spdy/2'
1775 assert client.get_next_proto_negotiated() == b'spdy/2'
1776
1777 def test_npn_client_fail(self):
1778 """
1779 Tests that when clients and servers cannot agree on what protocol
1780 to use next that the TLS connection does not get established.
1781 """
1782 advertise_args = []
1783 select_args = []
1784
1785 def advertise(conn):
1786 advertise_args.append((conn,))
1787 return [b'http/1.1', b'spdy/2']
1788
1789 def select(conn, options):
1790 select_args.append((conn, options))
1791 return b''
1792
1793 server_context = Context(TLSv1_METHOD)
1794 server_context.set_npn_advertise_callback(advertise)
1795
1796 client_context = Context(TLSv1_METHOD)
1797 client_context.set_npn_select_callback(select)
1798
1799 # Necessary to actually accept the connection
1800 server_context.use_privatekey(
1801 load_privatekey(FILETYPE_PEM, server_key_pem))
1802 server_context.use_certificate(
1803 load_certificate(FILETYPE_PEM, server_cert_pem))
1804
1805 # Do a little connection to trigger the logic
1806 server = Connection(server_context, None)
1807 server.set_accept_state()
1808
1809 client = Connection(client_context, None)
1810 client.set_connect_state()
1811
1812 # If the client doesn't return anything, the connection will fail.
1813 with pytest.raises(Error):
1814 interact_in_memory(server, client)
1815
1816 assert advertise_args == [(server,)]
1817 assert select_args == [(client, [b'http/1.1', b'spdy/2'])]
1818
1819 def test_npn_select_error(self):
1820 """
1821 Test that we can handle exceptions in the select callback. If
1822 select fails it should be fatal to the connection.
1823 """
1824 advertise_args = []
1825
1826 def advertise(conn):
1827 advertise_args.append((conn,))
1828 return [b'http/1.1', b'spdy/2']
1829
1830 def select(conn, options):
1831 raise TypeError
1832
1833 server_context = Context(TLSv1_METHOD)
1834 server_context.set_npn_advertise_callback(advertise)
1835
1836 client_context = Context(TLSv1_METHOD)
1837 client_context.set_npn_select_callback(select)
1838
1839 # Necessary to actually accept the connection
1840 server_context.use_privatekey(
1841 load_privatekey(FILETYPE_PEM, server_key_pem))
1842 server_context.use_certificate(
1843 load_certificate(FILETYPE_PEM, server_cert_pem))
1844
1845 # Do a little connection to trigger the logic
1846 server = Connection(server_context, None)
1847 server.set_accept_state()
1848
1849 client = Connection(client_context, None)
1850 client.set_connect_state()
1851
1852 # If the callback throws an exception it should be raised here.
1853 with pytest.raises(TypeError):
1854 interact_in_memory(server, client)
1855 assert advertise_args == [(server,), ]
1856
1857 def test_npn_advertise_error(self):
1858 """
1859 Test that we can handle exceptions in the advertise callback. If
1860 advertise fails no NPN is advertised to the client.
1861 """
1862 select_args = []
1863
1864 def advertise(conn):
1865 raise TypeError
1866
1867 def select(conn, options): # pragma: nocover
Cory Benfieldba1820d2015-04-13 17:39:12 -04001868 """
Alex Chan9e08b3e2016-11-10 12:18:54 +00001869 Assert later that no args are actually appended.
Cory Benfieldba1820d2015-04-13 17:39:12 -04001870 """
Alex Chan9e08b3e2016-11-10 12:18:54 +00001871 select_args.append((conn, options))
1872 return b''
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001873
Alex Chan9e08b3e2016-11-10 12:18:54 +00001874 server_context = Context(TLSv1_METHOD)
1875 server_context.set_npn_advertise_callback(advertise)
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001876
Alex Chan9e08b3e2016-11-10 12:18:54 +00001877 client_context = Context(TLSv1_METHOD)
1878 client_context.set_npn_select_callback(select)
Cory Benfield84a121e2014-03-31 20:30:25 +01001879
Alex Chan9e08b3e2016-11-10 12:18:54 +00001880 # Necessary to actually accept the connection
1881 server_context.use_privatekey(
1882 load_privatekey(FILETYPE_PEM, server_key_pem))
1883 server_context.use_certificate(
1884 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield84a121e2014-03-31 20:30:25 +01001885
Alex Chan9e08b3e2016-11-10 12:18:54 +00001886 # Do a little connection to trigger the logic
1887 server = Connection(server_context, None)
1888 server.set_accept_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001889
Alex Chan9e08b3e2016-11-10 12:18:54 +00001890 client = Connection(client_context, None)
1891 client.set_connect_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001892
Alex Chan9e08b3e2016-11-10 12:18:54 +00001893 # If the client doesn't return anything, the connection will fail.
1894 with pytest.raises(TypeError):
1895 interact_in_memory(server, client)
1896 assert select_args == []
Cory Benfield0ea76e72015-03-22 09:05:28 +00001897
1898
Alex Chanec1e32d2016-11-10 14:11:45 +00001899class TestApplicationLayerProtoNegotiation(object):
Cory Benfield12eae892014-06-07 15:42:56 +01001900 """
1901 Tests for ALPN in PyOpenSSL.
1902 """
Cory Benfielde46fa842015-04-13 16:50:49 -04001903 # Skip tests on versions that don't support ALPN.
1904 if _lib.Cryptography_HAS_ALPN:
Cory Benfield12eae892014-06-07 15:42:56 +01001905
Cory Benfielde46fa842015-04-13 16:50:49 -04001906 def test_alpn_success(self):
1907 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04001908 Clients and servers that agree on the negotiated ALPN protocol can
1909 correct establish a connection, and the agreed protocol is reported
1910 by the connections.
Cory Benfielde46fa842015-04-13 16:50:49 -04001911 """
1912 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001913
Cory Benfielde46fa842015-04-13 16:50:49 -04001914 def select(conn, options):
1915 select_args.append((conn, options))
1916 return b'spdy/2'
Cory Benfield12eae892014-06-07 15:42:56 +01001917
Cory Benfielde46fa842015-04-13 16:50:49 -04001918 client_context = Context(TLSv1_METHOD)
1919 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfield12eae892014-06-07 15:42:56 +01001920
Cory Benfielde46fa842015-04-13 16:50:49 -04001921 server_context = Context(TLSv1_METHOD)
1922 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01001923
Cory Benfielde46fa842015-04-13 16:50:49 -04001924 # Necessary to actually accept the connection
1925 server_context.use_privatekey(
1926 load_privatekey(FILETYPE_PEM, server_key_pem))
1927 server_context.use_certificate(
1928 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield12eae892014-06-07 15:42:56 +01001929
Cory Benfielde46fa842015-04-13 16:50:49 -04001930 # Do a little connection to trigger the logic
1931 server = Connection(server_context, None)
1932 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001933
Cory Benfielde46fa842015-04-13 16:50:49 -04001934 client = Connection(client_context, None)
1935 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001936
Alex Chanec1e32d2016-11-10 14:11:45 +00001937 interact_in_memory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001938
Alex Chanec1e32d2016-11-10 14:11:45 +00001939 assert select_args == [(server, [b'http/1.1', b'spdy/2'])]
Cory Benfielde46fa842015-04-13 16:50:49 -04001940
Alex Chanec1e32d2016-11-10 14:11:45 +00001941 assert server.get_alpn_proto_negotiated() == b'spdy/2'
1942 assert client.get_alpn_proto_negotiated() == b'spdy/2'
Cory Benfield12eae892014-06-07 15:42:56 +01001943
Cory Benfielde46fa842015-04-13 16:50:49 -04001944 def test_alpn_set_on_connection(self):
1945 """
1946 The same as test_alpn_success, but setting the ALPN protocols on
1947 the connection rather than the context.
1948 """
1949 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001950
Cory Benfielde46fa842015-04-13 16:50:49 -04001951 def select(conn, options):
1952 select_args.append((conn, options))
1953 return b'spdy/2'
Cory Benfield12eae892014-06-07 15:42:56 +01001954
Cory Benfielde46fa842015-04-13 16:50:49 -04001955 # Setup the client context but don't set any ALPN protocols.
1956 client_context = Context(TLSv1_METHOD)
Cory Benfield12eae892014-06-07 15:42:56 +01001957
Cory Benfielde46fa842015-04-13 16:50:49 -04001958 server_context = Context(TLSv1_METHOD)
1959 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01001960
Cory Benfielde46fa842015-04-13 16:50:49 -04001961 # Necessary to actually accept the connection
1962 server_context.use_privatekey(
1963 load_privatekey(FILETYPE_PEM, server_key_pem))
1964 server_context.use_certificate(
1965 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield12eae892014-06-07 15:42:56 +01001966
Cory Benfielde46fa842015-04-13 16:50:49 -04001967 # Do a little connection to trigger the logic
1968 server = Connection(server_context, None)
1969 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001970
Cory Benfielde46fa842015-04-13 16:50:49 -04001971 # Set the ALPN protocols on the client connection.
1972 client = Connection(client_context, None)
1973 client.set_alpn_protos([b'http/1.1', b'spdy/2'])
1974 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001975
Alex Chanec1e32d2016-11-10 14:11:45 +00001976 interact_in_memory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001977
Alex Chanec1e32d2016-11-10 14:11:45 +00001978 assert select_args == [(server, [b'http/1.1', b'spdy/2'])]
Cory Benfield12eae892014-06-07 15:42:56 +01001979
Alex Chanec1e32d2016-11-10 14:11:45 +00001980 assert server.get_alpn_proto_negotiated() == b'spdy/2'
1981 assert client.get_alpn_proto_negotiated() == b'spdy/2'
Cory Benfield12eae892014-06-07 15:42:56 +01001982
Cory Benfielde46fa842015-04-13 16:50:49 -04001983 def test_alpn_server_fail(self):
1984 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04001985 When clients and servers cannot agree on what protocol to use next
1986 the TLS connection does not get established.
Cory Benfielde46fa842015-04-13 16:50:49 -04001987 """
1988 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001989
Cory Benfielde46fa842015-04-13 16:50:49 -04001990 def select(conn, options):
1991 select_args.append((conn, options))
1992 return b''
Cory Benfield12eae892014-06-07 15:42:56 +01001993
Cory Benfielde46fa842015-04-13 16:50:49 -04001994 client_context = Context(TLSv1_METHOD)
1995 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfield12eae892014-06-07 15:42:56 +01001996
Cory Benfielde46fa842015-04-13 16:50:49 -04001997 server_context = Context(TLSv1_METHOD)
1998 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01001999
Cory Benfielde46fa842015-04-13 16:50:49 -04002000 # Necessary to actually accept the connection
2001 server_context.use_privatekey(
2002 load_privatekey(FILETYPE_PEM, server_key_pem))
2003 server_context.use_certificate(
2004 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield12eae892014-06-07 15:42:56 +01002005
Cory Benfielde46fa842015-04-13 16:50:49 -04002006 # Do a little connection to trigger the logic
2007 server = Connection(server_context, None)
2008 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01002009
Cory Benfielde46fa842015-04-13 16:50:49 -04002010 client = Connection(client_context, None)
2011 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01002012
Cory Benfielde46fa842015-04-13 16:50:49 -04002013 # If the client doesn't return anything, the connection will fail.
Alex Chanec1e32d2016-11-10 14:11:45 +00002014 with pytest.raises(Error):
2015 interact_in_memory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01002016
Alex Chanec1e32d2016-11-10 14:11:45 +00002017 assert select_args == [(server, [b'http/1.1', b'spdy/2'])]
Cory Benfield12eae892014-06-07 15:42:56 +01002018
Cory Benfielde46fa842015-04-13 16:50:49 -04002019 def test_alpn_no_server(self):
2020 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04002021 When clients and servers cannot agree on what protocol to use next
2022 because the server doesn't offer ALPN, no protocol is negotiated.
Cory Benfielde46fa842015-04-13 16:50:49 -04002023 """
2024 client_context = Context(TLSv1_METHOD)
2025 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfielde3d57152015-04-11 17:57:35 -04002026
Cory Benfielde46fa842015-04-13 16:50:49 -04002027 server_context = Context(TLSv1_METHOD)
Cory Benfielde3d57152015-04-11 17:57:35 -04002028
Cory Benfielde46fa842015-04-13 16:50:49 -04002029 # Necessary to actually accept the connection
2030 server_context.use_privatekey(
2031 load_privatekey(FILETYPE_PEM, server_key_pem))
2032 server_context.use_certificate(
2033 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfielde3d57152015-04-11 17:57:35 -04002034
Cory Benfielde46fa842015-04-13 16:50:49 -04002035 # Do a little connection to trigger the logic
2036 server = Connection(server_context, None)
2037 server.set_accept_state()
Cory Benfielde3d57152015-04-11 17:57:35 -04002038
Cory Benfielde46fa842015-04-13 16:50:49 -04002039 client = Connection(client_context, None)
2040 client.set_connect_state()
Cory Benfielde3d57152015-04-11 17:57:35 -04002041
Cory Benfielde46fa842015-04-13 16:50:49 -04002042 # Do the dance.
Alex Chanec1e32d2016-11-10 14:11:45 +00002043 interact_in_memory(server, client)
Cory Benfielde3d57152015-04-11 17:57:35 -04002044
Alex Chanec1e32d2016-11-10 14:11:45 +00002045 assert client.get_alpn_proto_negotiated() == b''
Cory Benfielde3d57152015-04-11 17:57:35 -04002046
Cory Benfielde46fa842015-04-13 16:50:49 -04002047 def test_alpn_callback_exception(self):
2048 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04002049 We can handle exceptions in the ALPN select callback.
Cory Benfielde46fa842015-04-13 16:50:49 -04002050 """
2051 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002052
Cory Benfielde46fa842015-04-13 16:50:49 -04002053 def select(conn, options):
2054 select_args.append((conn, options))
Cory Benfieldef401452015-04-13 18:17:36 -04002055 raise TypeError()
Cory Benfieldf1177e72015-04-12 09:11:49 -04002056
Cory Benfielde46fa842015-04-13 16:50:49 -04002057 client_context = Context(TLSv1_METHOD)
2058 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfieldf1177e72015-04-12 09:11:49 -04002059
Cory Benfielde46fa842015-04-13 16:50:49 -04002060 server_context = Context(TLSv1_METHOD)
2061 server_context.set_alpn_select_callback(select)
Cory Benfieldf1177e72015-04-12 09:11:49 -04002062
Cory Benfielde46fa842015-04-13 16:50:49 -04002063 # Necessary to actually accept the connection
2064 server_context.use_privatekey(
2065 load_privatekey(FILETYPE_PEM, server_key_pem))
2066 server_context.use_certificate(
2067 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfieldf1177e72015-04-12 09:11:49 -04002068
Cory Benfielde46fa842015-04-13 16:50:49 -04002069 # Do a little connection to trigger the logic
2070 server = Connection(server_context, None)
2071 server.set_accept_state()
Cory Benfieldf1177e72015-04-12 09:11:49 -04002072
Cory Benfielde46fa842015-04-13 16:50:49 -04002073 client = Connection(client_context, None)
2074 client.set_connect_state()
Cory Benfieldf1177e72015-04-12 09:11:49 -04002075
Alex Chanec1e32d2016-11-10 14:11:45 +00002076 with pytest.raises(TypeError):
2077 interact_in_memory(server, client)
2078 assert select_args == [(server, [b'http/1.1', b'spdy/2'])]
Cory Benfieldf1177e72015-04-12 09:11:49 -04002079
Cory Benfield0f7b04c2015-04-13 17:51:12 -04002080 else:
2081 # No ALPN.
2082 def test_alpn_not_implemented(self):
Cory Benfieldef401452015-04-13 18:17:36 -04002083 """
2084 If ALPN is not in OpenSSL, we should raise NotImplementedError.
2085 """
Cory Benfield0f7b04c2015-04-13 17:51:12 -04002086 # Test the context methods first.
2087 context = Context(TLSv1_METHOD)
Alex Chanec1e32d2016-11-10 14:11:45 +00002088 with pytest.raises(NotImplementedError):
2089 context.set_alpn_protos(None)
2090 with pytest.raises(NotImplementedError):
2091 context.set_alpn_select_callback(None)
Cory Benfield0f7b04c2015-04-13 17:51:12 -04002092
2093 # Now test a connection.
2094 conn = Connection(context)
Alex Chanec1e32d2016-11-10 14:11:45 +00002095 with pytest.raises(NotImplementedError):
2096 conn.set_alpn_protos(None)
Cory Benfield0f7b04c2015-04-13 17:51:12 -04002097
Cory Benfieldf1177e72015-04-12 09:11:49 -04002098
Alex Chanec1e32d2016-11-10 14:11:45 +00002099class TestSession(object):
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05002100 """
2101 Unit tests for :py:obj:`OpenSSL.SSL.Session`.
2102 """
2103 def test_construction(self):
2104 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002105 :py:class:`Session` can be constructed with no arguments, creating
2106 a new instance of that type.
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05002107 """
2108 new_session = Session()
Alex Chanec1e32d2016-11-10 14:11:45 +00002109 assert isinstance(new_session, Session)
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05002110
2111
Alex Chan1c0cb662017-01-30 07:13:30 +00002112class TestConnection(object):
Rick Deane15b1472009-07-09 15:53:42 -05002113 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002114 Unit tests for `OpenSSL.SSL.Connection`.
Rick Deane15b1472009-07-09 15:53:42 -05002115 """
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04002116 # XXX get_peer_certificate -> None
2117 # XXX sock_shutdown
2118 # XXX master_key -> TypeError
2119 # XXX server_random -> TypeError
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04002120 # XXX connect -> TypeError
2121 # XXX connect_ex -> TypeError
2122 # XXX set_connect_state -> TypeError
2123 # XXX set_accept_state -> TypeError
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04002124 # XXX do_handshake -> TypeError
2125 # XXX bio_read -> TypeError
2126 # XXX recv -> TypeError
2127 # XXX send -> TypeError
2128 # XXX bio_write -> TypeError
2129
Rick Deane15b1472009-07-09 15:53:42 -05002130 def test_type(self):
2131 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002132 `Connection` and `ConnectionType` refer to the same type object and
2133 can be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -05002134 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002135 assert Connection is ConnectionType
Rick Deane15b1472009-07-09 15:53:42 -05002136 ctx = Context(TLSv1_METHOD)
Alex Chan1c0cb662017-01-30 07:13:30 +00002137 assert is_consistent_type(Connection, 'Connection', ctx, None)
Rick Deane15b1472009-07-09 15:53:42 -05002138
Alex Chanfb078d82017-04-20 11:16:15 +01002139 @pytest.mark.parametrize('bad_context', [object(), 'context', None, 1])
2140 def test_wrong_args(self, bad_context):
2141 """
2142 `Connection.__init__` raises `TypeError` if called with a non-`Context`
2143 instance argument.
2144 """
2145 with pytest.raises(TypeError):
2146 Connection(bad_context)
2147
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002148 def test_get_context(self):
2149 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002150 `Connection.get_context` returns the `Context` instance used to
2151 construct the `Connection` instance.
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002152 """
2153 context = Context(TLSv1_METHOD)
2154 connection = Connection(context, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002155 assert connection.get_context() is context
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002156
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002157 def test_set_context_wrong_args(self):
2158 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002159 `Connection.set_context` raises `TypeError` if called with a
Alex Chanfb078d82017-04-20 11:16:15 +01002160 non-`Context` instance argument.
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002161 """
2162 ctx = Context(TLSv1_METHOD)
2163 connection = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002164 with pytest.raises(TypeError):
2165 connection.set_context(object())
2166 with pytest.raises(TypeError):
2167 connection.set_context("hello")
2168 with pytest.raises(TypeError):
2169 connection.set_context(1)
2170 assert ctx is connection.get_context()
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002171
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002172 def test_set_context(self):
2173 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002174 `Connection.set_context` specifies a new `Context` instance to be
2175 used for the connection.
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002176 """
2177 original = Context(SSLv23_METHOD)
2178 replacement = Context(TLSv1_METHOD)
2179 connection = Connection(original, None)
2180 connection.set_context(replacement)
Alex Chan1c0cb662017-01-30 07:13:30 +00002181 assert replacement is connection.get_context()
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002182 # Lose our references to the contexts, just in case the Connection
2183 # isn't properly managing its own contributions to their reference
2184 # counts.
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002185 del original, replacement
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002186 collect()
2187
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002188 def test_set_tlsext_host_name_wrong_args(self):
2189 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002190 If `Connection.set_tlsext_host_name` is called with a non-byte string
2191 argument or a byte string with an embedded NUL, `TypeError` is raised.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002192 """
2193 conn = Connection(Context(TLSv1_METHOD), None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002194 with pytest.raises(TypeError):
2195 conn.set_tlsext_host_name(object())
2196 with pytest.raises(TypeError):
2197 conn.set_tlsext_host_name(b"with\0null")
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002198
Abraham Martinc5484ba2015-03-25 15:33:05 +00002199 if PY3:
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002200 # On Python 3.x, don't accidentally implicitly convert from text.
Alex Chan1c0cb662017-01-30 07:13:30 +00002201 with pytest.raises(TypeError):
2202 conn.set_tlsext_host_name(b"example.com".decode("ascii"))
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04002203
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002204 def test_pending(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002205 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002206 `Connection.pending` returns the number of bytes available for
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002207 immediate read.
2208 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002209 connection = Connection(Context(TLSv1_METHOD), None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002210 assert connection.pending() == 0
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002211
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002212 def test_peek(self):
2213 """
Hynek Schlawack3bcf3152017-02-18 08:25:34 +01002214 `Connection.recv` peeks into the connection if `socket.MSG_PEEK` is
2215 passed.
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002216 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002217 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002218 server.send(b'xy')
Alex Chan1c0cb662017-01-30 07:13:30 +00002219 assert client.recv(2, MSG_PEEK) == b'xy'
2220 assert client.recv(2, MSG_PEEK) == b'xy'
2221 assert client.recv(2) == b'xy'
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002222
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002223 def test_connect_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002224 """
Hynek Schlawack3bcf3152017-02-18 08:25:34 +01002225 `Connection.connect` raises `TypeError` if called with a non-address
2226 argument.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002227 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002228 connection = Connection(Context(TLSv1_METHOD), socket())
Alex Chan1c0cb662017-01-30 07:13:30 +00002229 with pytest.raises(TypeError):
2230 connection.connect(None)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002231
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002232 def test_connect_refused(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002233 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002234 `Connection.connect` raises `socket.error` if the underlying socket
2235 connect method raises it.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002236 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002237 client = socket()
2238 context = Context(TLSv1_METHOD)
2239 clientSSL = Connection(context, client)
Alex Gaynor122717b2015-09-05 14:14:18 -04002240 # pytest.raises here doesn't work because of a bug in py.test on Python
2241 # 2.6: https://github.com/pytest-dev/pytest/issues/988
Alex Gaynore69c2782015-09-05 14:07:48 -04002242 try:
Alex Gaynor1aabb2e2015-09-05 13:35:18 -04002243 clientSSL.connect(("127.0.0.1", 1))
Alex Gaynore69c2782015-09-05 14:07:48 -04002244 except error as e:
Alex Gaynor20a4c082015-09-05 14:24:15 -04002245 exc = e
2246 assert exc.args[0] == ECONNREFUSED
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002247
2248 def test_connect(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002249 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002250 `Connection.connect` establishes a connection to the specified address.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002251 """
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002252 port = socket()
2253 port.bind(('', 0))
2254 port.listen(3)
2255
2256 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002257 clientSSL.connect(('127.0.0.1', port.getsockname()[1]))
2258 # XXX An assertion? Or something?
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002259
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002260 @pytest.mark.skipif(
2261 platform == "darwin",
2262 reason="connect_ex sometimes causes a kernel panic on OS X 10.6.4"
2263 )
2264 def test_connect_ex(self):
2265 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002266 If there is a connection error, `Connection.connect_ex` returns the
2267 errno instead of raising an exception.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002268 """
2269 port = socket()
2270 port.bind(('', 0))
2271 port.listen(3)
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002272
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002273 clientSSL = Connection(Context(TLSv1_METHOD), socket())
2274 clientSSL.setblocking(False)
2275 result = clientSSL.connect_ex(port.getsockname())
2276 expected = (EINPROGRESS, EWOULDBLOCK)
Alex Chan1c0cb662017-01-30 07:13:30 +00002277 assert result in expected
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002278
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002279 def test_accept(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002280 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002281 `Connection.accept` accepts a pending connection attempt and returns a
2282 tuple of a new `Connection` (the accepted client) and the address the
2283 connection originated from.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002284 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002285 ctx = Context(TLSv1_METHOD)
2286 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2287 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002288 port = socket()
2289 portSSL = Connection(ctx, port)
2290 portSSL.bind(('', 0))
2291 portSSL.listen(3)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002292
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002293 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002294
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002295 # Calling portSSL.getsockname() here to get the server IP address
2296 # sounds great, but frequently fails on Windows.
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002297 clientSSL.connect(('127.0.0.1', portSSL.getsockname()[1]))
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002298
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002299 serverSSL, address = portSSL.accept()
2300
Alex Chan1c0cb662017-01-30 07:13:30 +00002301 assert isinstance(serverSSL, Connection)
2302 assert serverSSL.get_context() is ctx
2303 assert address == clientSSL.getsockname()
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002304
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002305 def test_shutdown_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002306 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002307 `Connection.set_shutdown` raises `TypeError` if called with arguments
2308 other than integers.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002309 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002310 connection = Connection(Context(TLSv1_METHOD), None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002311 with pytest.raises(TypeError):
2312 connection.set_shutdown(None)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002313
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002314 def test_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002315 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002316 `Connection.shutdown` performs an SSL-level connection shutdown.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002317 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002318 server, client = loopback()
2319 assert not server.shutdown()
2320 assert server.get_shutdown() == SENT_SHUTDOWN
2321 with pytest.raises(ZeroReturnError):
2322 client.recv(1024)
2323 assert client.get_shutdown() == RECEIVED_SHUTDOWN
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04002324 client.shutdown()
Alex Chan1c0cb662017-01-30 07:13:30 +00002325 assert client.get_shutdown() == (SENT_SHUTDOWN | RECEIVED_SHUTDOWN)
2326 with pytest.raises(ZeroReturnError):
2327 server.recv(1024)
2328 assert server.get_shutdown() == (SENT_SHUTDOWN | RECEIVED_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002329
Paul Aurichc85e0862015-01-08 08:34:33 -08002330 def test_shutdown_closed(self):
2331 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002332 If the underlying socket is closed, `Connection.shutdown` propagates
2333 the write error from the low level write call.
Paul Aurichc85e0862015-01-08 08:34:33 -08002334 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002335 server, client = loopback()
Paul Aurichc85e0862015-01-08 08:34:33 -08002336 server.sock_shutdown(2)
Alex Chan1c0cb662017-01-30 07:13:30 +00002337 with pytest.raises(SysCallError) as exc:
2338 server.shutdown()
Alex Chanfb078d82017-04-20 11:16:15 +01002339 if platform == "win32":
2340 assert exc.value.args[0] == ESHUTDOWN
2341 else:
2342 assert exc.value.args[0] == EPIPE
Paul Aurichc85e0862015-01-08 08:34:33 -08002343
Glyph89389472015-04-14 17:29:26 -04002344 def test_shutdown_truncated(self):
Glyph6064ec32015-04-14 16:38:22 -04002345 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002346 If the underlying connection is truncated, `Connection.shutdown`
2347 raises an `Error`.
Glyph6064ec32015-04-14 16:38:22 -04002348 """
Glyph89389472015-04-14 17:29:26 -04002349 server_ctx = Context(TLSv1_METHOD)
2350 client_ctx = Context(TLSv1_METHOD)
2351 server_ctx.use_privatekey(
2352 load_privatekey(FILETYPE_PEM, server_key_pem))
2353 server_ctx.use_certificate(
2354 load_certificate(FILETYPE_PEM, server_cert_pem))
2355 server = Connection(server_ctx, None)
2356 client = Connection(client_ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002357 handshake_in_memory(client, server)
2358 assert not server.shutdown()
2359 with pytest.raises(WantReadError):
2360 server.shutdown()
Glyph89389472015-04-14 17:29:26 -04002361 server.bio_shutdown()
Alex Chan1c0cb662017-01-30 07:13:30 +00002362 with pytest.raises(Error):
2363 server.shutdown()
Glyph6064ec32015-04-14 16:38:22 -04002364
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002365 def test_set_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002366 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002367 `Connection.set_shutdown` sets the state of the SSL connection
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002368 shutdown process.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002369 """
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002370 connection = Connection(Context(TLSv1_METHOD), socket())
2371 connection.set_shutdown(RECEIVED_SHUTDOWN)
Alex Chan1c0cb662017-01-30 07:13:30 +00002372 assert connection.get_shutdown() == RECEIVED_SHUTDOWN
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002373
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002374 @skip_if_py3
2375 def test_set_shutdown_long(self):
2376 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002377 On Python 2 `Connection.set_shutdown` accepts an argument
2378 of type `long` as well as `int`.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002379 """
2380 connection = Connection(Context(TLSv1_METHOD), socket())
2381 connection.set_shutdown(long(RECEIVED_SHUTDOWN))
Alex Chan1c0cb662017-01-30 07:13:30 +00002382 assert connection.get_shutdown() == RECEIVED_SHUTDOWN
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -05002383
kjavaf248592015-09-07 12:14:01 +01002384 def test_state_string(self):
2385 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002386 `Connection.state_string` verbosely describes the current state of
2387 the `Connection`.
kjavaf248592015-09-07 12:14:01 +01002388 """
Hynek Schlawackb0274ce2015-10-16 19:56:26 +02002389 server, client = socket_pair()
Alex Chan1c0cb662017-01-30 07:13:30 +00002390 server = loopback_server_factory(server)
2391 client = loopback_client_factory(client)
kjavaf248592015-09-07 12:14:01 +01002392
Alex Gaynor5af32d02016-09-24 01:52:21 -04002393 assert server.get_state_string() in [
2394 b"before/accept initialization", b"before SSL initialization"
2395 ]
2396 assert client.get_state_string() in [
2397 b"before/connect initialization", b"before SSL initialization"
2398 ]
kjavaf248592015-09-07 12:14:01 +01002399
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002400 def test_app_data(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002401 """
2402 Any object can be set as app data by passing it to
Alex Chan1c0cb662017-01-30 07:13:30 +00002403 `Connection.set_app_data` and later retrieved with
2404 `Connection.get_app_data`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002405 """
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002406 conn = Connection(Context(TLSv1_METHOD), None)
Todd Chapman4f73e4f2015-08-27 11:26:43 -04002407 assert None is conn.get_app_data()
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002408 app_data = object()
2409 conn.set_app_data(app_data)
Todd Chapman4f73e4f2015-08-27 11:26:43 -04002410 assert conn.get_app_data() is app_data
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002411
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002412 def test_makefile(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002413 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002414 `Connection.makefile` is not implemented and calling that
2415 method raises `NotImplementedError`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002416 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002417 conn = Connection(Context(TLSv1_METHOD), None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002418 with pytest.raises(NotImplementedError):
2419 conn.makefile()
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002420
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002421 def test_get_peer_cert_chain(self):
2422 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002423 `Connection.get_peer_cert_chain` returns a list of certificates
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002424 which the connected server returned for the certification verification.
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002425 """
2426 chain = _create_certificate_chain()
2427 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
2428
2429 serverContext = Context(TLSv1_METHOD)
2430 serverContext.use_privatekey(skey)
2431 serverContext.use_certificate(scert)
2432 serverContext.add_extra_chain_cert(icert)
2433 serverContext.add_extra_chain_cert(cacert)
2434 server = Connection(serverContext, None)
2435 server.set_accept_state()
2436
2437 # Create the client
2438 clientContext = Context(TLSv1_METHOD)
2439 clientContext.set_verify(VERIFY_NONE, verify_cb)
2440 client = Connection(clientContext, None)
2441 client.set_connect_state()
2442
Alex Chan1c0cb662017-01-30 07:13:30 +00002443 interact_in_memory(client, server)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002444
2445 chain = client.get_peer_cert_chain()
Alex Chan1c0cb662017-01-30 07:13:30 +00002446 assert len(chain) == 3
2447 assert "Server Certificate" == chain[0].get_subject().CN
2448 assert "Intermediate Certificate" == chain[1].get_subject().CN
2449 assert "Authority Certificate" == chain[2].get_subject().CN
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002450
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002451 def test_get_peer_cert_chain_none(self):
2452 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002453 `Connection.get_peer_cert_chain` returns `None` if the peer sends
2454 no certificate chain.
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002455 """
2456 ctx = Context(TLSv1_METHOD)
2457 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2458 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
2459 server = Connection(ctx, None)
2460 server.set_accept_state()
2461 client = Connection(Context(TLSv1_METHOD), None)
2462 client.set_connect_state()
Alex Chan1c0cb662017-01-30 07:13:30 +00002463 interact_in_memory(client, server)
2464 assert None is server.get_peer_cert_chain()
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002465
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002466 def test_get_session_unconnected(self):
2467 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002468 `Connection.get_session` returns `None` when used with an object
2469 which has not been connected.
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002470 """
2471 ctx = Context(TLSv1_METHOD)
2472 server = Connection(ctx, None)
2473 session = server.get_session()
Alex Chan1c0cb662017-01-30 07:13:30 +00002474 assert None is session
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002475
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002476 def test_server_get_session(self):
2477 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002478 On the server side of a connection, `Connection.get_session` returns a
2479 `Session` instance representing the SSL session for that connection.
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002480 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002481 server, client = loopback()
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002482 session = server.get_session()
Alex Chan1c0cb662017-01-30 07:13:30 +00002483 assert isinstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002484
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002485 def test_client_get_session(self):
2486 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002487 On the client side of a connection, `Connection.get_session`
2488 returns a `Session` instance representing the SSL session for
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002489 that connection.
2490 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002491 server, client = loopback()
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002492 session = client.get_session()
Alex Chan1c0cb662017-01-30 07:13:30 +00002493 assert isinstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002494
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002495 def test_set_session_wrong_args(self):
2496 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002497 `Connection.set_session` raises `TypeError` if called with an object
2498 that is not an instance of `Session`.
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002499 """
2500 ctx = Context(TLSv1_METHOD)
2501 connection = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002502 with pytest.raises(TypeError):
2503 connection.set_session(123)
2504 with pytest.raises(TypeError):
2505 connection.set_session("hello")
2506 with pytest.raises(TypeError):
2507 connection.set_session(object())
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002508
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002509 def test_client_set_session(self):
2510 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002511 `Connection.set_session`, when used prior to a connection being
2512 established, accepts a `Session` instance and causes an attempt to
2513 re-use the session it represents when the SSL handshake is performed.
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002514 """
2515 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2516 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
Alex Gaynor332848f2017-08-07 12:40:09 -04002517 ctx = Context(SSLv23_METHOD)
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002518 ctx.use_privatekey(key)
2519 ctx.use_certificate(cert)
2520 ctx.set_session_id("unity-test")
2521
2522 def makeServer(socket):
2523 server = Connection(ctx, socket)
2524 server.set_accept_state()
2525 return server
2526
Alex Chan1c0cb662017-01-30 07:13:30 +00002527 originalServer, originalClient = loopback(
2528 server_factory=makeServer)
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002529 originalSession = originalClient.get_session()
2530
2531 def makeClient(socket):
Alex Chan1c0cb662017-01-30 07:13:30 +00002532 client = loopback_client_factory(socket)
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002533 client.set_session(originalSession)
2534 return client
Alex Chan1c0cb662017-01-30 07:13:30 +00002535 resumedServer, resumedClient = loopback(
2536 server_factory=makeServer,
2537 client_factory=makeClient)
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002538
2539 # This is a proxy: in general, we have no access to any unique
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002540 # identifier for the session (new enough versions of OpenSSL expose
2541 # a hash which could be usable, but "new enough" is very, very new).
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002542 # Instead, exploit the fact that the master key is re-used if the
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002543 # session is re-used. As long as the master key for the two
2544 # connections is the same, the session was re-used!
Alex Chan1c0cb662017-01-30 07:13:30 +00002545 assert originalServer.master_key() == resumedServer.master_key()
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002546
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002547 def test_set_session_wrong_method(self):
2548 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002549 If `Connection.set_session` is passed a `Session` instance associated
2550 with a context using a different SSL method than the `Connection`
2551 is using, a `OpenSSL.SSL.Error` is raised.
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002552 """
Alex Gaynor5af32d02016-09-24 01:52:21 -04002553 # Make this work on both OpenSSL 1.0.0, which doesn't support TLSv1.2
2554 # and also on OpenSSL 1.1.0 which doesn't support SSLv3. (SSL_ST_INIT
2555 # is a way to check for 1.1.0)
Alex Gaynoraa32e712017-06-29 20:56:12 -07002556 if SSL_ST_INIT is None:
2557 v1 = TLSv1_2_METHOD
2558 v2 = TLSv1_METHOD
2559 elif hasattr(_lib, "SSLv3_method"):
Alex Gaynor5af32d02016-09-24 01:52:21 -04002560 v1 = TLSv1_METHOD
2561 v2 = SSLv3_METHOD
2562 else:
Alex Gaynoraa32e712017-06-29 20:56:12 -07002563 pytest.skip("Test requires either OpenSSL 1.1.0 or SSLv3")
Alex Gaynor5af32d02016-09-24 01:52:21 -04002564
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002565 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2566 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
Alex Gaynor5af32d02016-09-24 01:52:21 -04002567 ctx = Context(v1)
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002568 ctx.use_privatekey(key)
2569 ctx.use_certificate(cert)
2570 ctx.set_session_id("unity-test")
2571
2572 def makeServer(socket):
2573 server = Connection(ctx, socket)
2574 server.set_accept_state()
2575 return server
2576
Alex Gaynor5af32d02016-09-24 01:52:21 -04002577 def makeOriginalClient(socket):
2578 client = Connection(Context(v1), socket)
2579 client.set_connect_state()
2580 return client
2581
Alex Chan1c0cb662017-01-30 07:13:30 +00002582 originalServer, originalClient = loopback(
2583 server_factory=makeServer, client_factory=makeOriginalClient)
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002584 originalSession = originalClient.get_session()
2585
2586 def makeClient(socket):
2587 # Intentionally use a different, incompatible method here.
Alex Gaynor5af32d02016-09-24 01:52:21 -04002588 client = Connection(Context(v2), socket)
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002589 client.set_connect_state()
2590 client.set_session(originalSession)
2591 return client
2592
Alex Chan1c0cb662017-01-30 07:13:30 +00002593 with pytest.raises(Error):
2594 loopback(client_factory=makeClient, server_factory=makeServer)
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002595
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002596 def test_wantWriteError(self):
2597 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002598 `Connection` methods which generate output raise
2599 `OpenSSL.SSL.WantWriteError` if writing to the connection's BIO
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002600 fail indicating a should-write state.
2601 """
2602 client_socket, server_socket = socket_pair()
2603 # Fill up the client's send buffer so Connection won't be able to write
Jean-Paul Calderonebbff8b92014-03-22 14:20:30 -04002604 # anything. Only write a single byte at a time so we can be sure we
2605 # completely fill the buffer. Even though the socket API is allowed to
2606 # signal a short write via its return value it seems this doesn't
2607 # always happen on all platforms (FreeBSD and OS X particular) for the
2608 # very last bit of available buffer space.
2609 msg = b"x"
2610 for i in range(1024 * 1024 * 4):
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002611 try:
2612 client_socket.send(msg)
2613 except error as e:
2614 if e.errno == EWOULDBLOCK:
2615 break
2616 raise
2617 else:
Alex Chan1c0cb662017-01-30 07:13:30 +00002618 pytest.fail(
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002619 "Failed to fill socket buffer, cannot test BIO want write")
2620
2621 ctx = Context(TLSv1_METHOD)
2622 conn = Connection(ctx, client_socket)
2623 # Client's speak first, so make it an SSL client
2624 conn.set_connect_state()
Alex Chan1c0cb662017-01-30 07:13:30 +00002625 with pytest.raises(WantWriteError):
2626 conn.do_handshake()
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002627
2628 # XXX want_read
2629
Fedor Brunner416f4a12014-03-28 13:18:38 +01002630 def test_get_finished_before_connect(self):
Fedor Brunner5747b932014-03-05 14:22:34 +01002631 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002632 `Connection.get_finished` returns `None` before TLS handshake
2633 is completed.
Fedor Brunner5747b932014-03-05 14:22:34 +01002634 """
Fedor Brunner5747b932014-03-05 14:22:34 +01002635 ctx = Context(TLSv1_METHOD)
2636 connection = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002637 assert connection.get_finished() is None
Fedor Brunner416f4a12014-03-28 13:18:38 +01002638
2639 def test_get_peer_finished_before_connect(self):
2640 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002641 `Connection.get_peer_finished` returns `None` before TLS handshake
2642 is completed.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002643 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002644 ctx = Context(TLSv1_METHOD)
2645 connection = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002646 assert connection.get_peer_finished() is None
Fedor Brunner5747b932014-03-05 14:22:34 +01002647
Fedor Brunner416f4a12014-03-28 13:18:38 +01002648 def test_get_finished(self):
2649 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002650 `Connection.get_finished` method returns the TLS Finished message send
2651 from client, or server. Finished messages are send during
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002652 TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002653 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002654 server, client = loopback()
Fedor Brunner416f4a12014-03-28 13:18:38 +01002655
Alex Chan1c0cb662017-01-30 07:13:30 +00002656 assert server.get_finished() is not None
2657 assert len(server.get_finished()) > 0
Fedor Brunner416f4a12014-03-28 13:18:38 +01002658
2659 def test_get_peer_finished(self):
2660 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002661 `Connection.get_peer_finished` method returns the TLS Finished
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002662 message received from client, or server. Finished messages are send
2663 during TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002664 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002665 server, client = loopback()
Fedor Brunner416f4a12014-03-28 13:18:38 +01002666
Alex Chan1c0cb662017-01-30 07:13:30 +00002667 assert server.get_peer_finished() is not None
2668 assert len(server.get_peer_finished()) > 0
Fedor Brunner5747b932014-03-05 14:22:34 +01002669
Fedor Brunner416f4a12014-03-28 13:18:38 +01002670 def test_tls_finished_message_symmetry(self):
2671 """
Hynek Schlawackdddd1112015-09-05 21:12:30 +02002672 The TLS Finished message send by server must be the TLS Finished
2673 message received by client.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002674
Hynek Schlawackdddd1112015-09-05 21:12:30 +02002675 The TLS Finished message send by client must be the TLS Finished
2676 message received by server.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002677 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002678 server, client = loopback()
Fedor Brunner416f4a12014-03-28 13:18:38 +01002679
Alex Chan1c0cb662017-01-30 07:13:30 +00002680 assert server.get_finished() == client.get_peer_finished()
2681 assert client.get_finished() == server.get_peer_finished()
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002682
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002683 def test_get_cipher_name_before_connect(self):
2684 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002685 `Connection.get_cipher_name` returns `None` if no connection
2686 has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002687 """
2688 ctx = Context(TLSv1_METHOD)
2689 conn = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002690 assert conn.get_cipher_name() is None
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002691
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002692 def test_get_cipher_name(self):
2693 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002694 `Connection.get_cipher_name` returns a `unicode` string giving the
2695 name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002696 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002697 server, client = loopback()
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002698 server_cipher_name, client_cipher_name = \
2699 server.get_cipher_name(), client.get_cipher_name()
2700
Alex Chan1c0cb662017-01-30 07:13:30 +00002701 assert isinstance(server_cipher_name, text_type)
2702 assert isinstance(client_cipher_name, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002703
Alex Chan1c0cb662017-01-30 07:13:30 +00002704 assert server_cipher_name == client_cipher_name
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002705
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002706 def test_get_cipher_version_before_connect(self):
2707 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002708 `Connection.get_cipher_version` returns `None` if no connection
2709 has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002710 """
2711 ctx = Context(TLSv1_METHOD)
2712 conn = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002713 assert conn.get_cipher_version() is None
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002714
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002715 def test_get_cipher_version(self):
2716 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002717 `Connection.get_cipher_version` returns a `unicode` string giving
2718 the protocol name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002719 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002720 server, client = loopback()
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002721 server_cipher_version, client_cipher_version = \
2722 server.get_cipher_version(), client.get_cipher_version()
2723
Alex Chan1c0cb662017-01-30 07:13:30 +00002724 assert isinstance(server_cipher_version, text_type)
2725 assert isinstance(client_cipher_version, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002726
Alex Chan1c0cb662017-01-30 07:13:30 +00002727 assert server_cipher_version == client_cipher_version
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002728
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002729 def test_get_cipher_bits_before_connect(self):
2730 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002731 `Connection.get_cipher_bits` returns `None` if no connection has
2732 been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002733 """
2734 ctx = Context(TLSv1_METHOD)
2735 conn = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002736 assert conn.get_cipher_bits() is None
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002737
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002738 def test_get_cipher_bits(self):
2739 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002740 `Connection.get_cipher_bits` returns the number of secret bits
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002741 of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002742 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002743 server, client = loopback()
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002744 server_cipher_bits, client_cipher_bits = \
2745 server.get_cipher_bits(), client.get_cipher_bits()
2746
Alex Chan1c0cb662017-01-30 07:13:30 +00002747 assert isinstance(server_cipher_bits, int)
2748 assert isinstance(client_cipher_bits, int)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002749
Alex Chan1c0cb662017-01-30 07:13:30 +00002750 assert server_cipher_bits == client_cipher_bits
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002751
Jim Shaverabff1882015-05-27 09:15:55 -04002752 def test_get_protocol_version_name(self):
2753 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002754 `Connection.get_protocol_version_name()` returns a string giving the
2755 protocol version of the current connection.
Jim Shaverabff1882015-05-27 09:15:55 -04002756 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002757 server, client = loopback()
Jim Shaverabff1882015-05-27 09:15:55 -04002758 client_protocol_version_name = client.get_protocol_version_name()
2759 server_protocol_version_name = server.get_protocol_version_name()
2760
Alex Chan1c0cb662017-01-30 07:13:30 +00002761 assert isinstance(server_protocol_version_name, text_type)
2762 assert isinstance(client_protocol_version_name, text_type)
Jim Shaverabff1882015-05-27 09:15:55 -04002763
Alex Chan1c0cb662017-01-30 07:13:30 +00002764 assert server_protocol_version_name == client_protocol_version_name
Jim Shaverabff1882015-05-27 09:15:55 -04002765
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002766 def test_get_protocol_version(self):
2767 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002768 `Connection.get_protocol_version()` returns an integer
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002769 giving the protocol version of the current connection.
2770 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002771 server, client = loopback()
Jim Shaver85a4dff2015-04-27 17:42:46 -04002772 client_protocol_version = client.get_protocol_version()
2773 server_protocol_version = server.get_protocol_version()
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002774
Alex Chan1c0cb662017-01-30 07:13:30 +00002775 assert isinstance(server_protocol_version, int)
2776 assert isinstance(client_protocol_version, int)
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002777
Alex Chan1c0cb662017-01-30 07:13:30 +00002778 assert server_protocol_version == client_protocol_version
2779
2780 def test_wantReadError(self):
2781 """
2782 `Connection.bio_read` raises `OpenSSL.SSL.WantReadError` if there are
2783 no bytes available to be read from the BIO.
2784 """
2785 ctx = Context(TLSv1_METHOD)
2786 conn = Connection(ctx, None)
2787 with pytest.raises(WantReadError):
2788 conn.bio_read(1024)
2789
Alex Chanfb078d82017-04-20 11:16:15 +01002790 @pytest.mark.parametrize('bufsize', [1.0, None, object(), 'bufsize'])
2791 def test_bio_read_wrong_args(self, bufsize):
2792 """
2793 `Connection.bio_read` raises `TypeError` if passed a non-integer
2794 argument.
2795 """
2796 ctx = Context(TLSv1_METHOD)
2797 conn = Connection(ctx, None)
2798 with pytest.raises(TypeError):
2799 conn.bio_read(bufsize)
2800
Alex Chan1c0cb662017-01-30 07:13:30 +00002801 def test_buffer_size(self):
2802 """
2803 `Connection.bio_read` accepts an integer giving the maximum number
2804 of bytes to read and return.
2805 """
2806 ctx = Context(TLSv1_METHOD)
2807 conn = Connection(ctx, None)
2808 conn.set_connect_state()
2809 try:
2810 conn.do_handshake()
2811 except WantReadError:
2812 pass
2813 data = conn.bio_read(2)
2814 assert 2 == len(data)
2815
2816 @skip_if_py3
2817 def test_buffer_size_long(self):
2818 """
2819 On Python 2 `Connection.bio_read` accepts values of type `long` as
2820 well as `int`.
2821 """
2822 ctx = Context(TLSv1_METHOD)
2823 conn = Connection(ctx, None)
2824 conn.set_connect_state()
2825 try:
2826 conn.do_handshake()
2827 except WantReadError:
2828 pass
2829 data = conn.bio_read(long(2))
2830 assert 2 == len(data)
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002831
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002832
Alex Chanb7480992017-01-30 14:04:47 +00002833class TestConnectionGetCipherList(object):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002834 """
Alex Chanb7480992017-01-30 14:04:47 +00002835 Tests for `Connection.get_cipher_list`.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002836 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002837 def test_result(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002838 """
Alex Chanb7480992017-01-30 14:04:47 +00002839 `Connection.get_cipher_list` returns a list of `bytes` giving the
2840 names of the ciphers which might be used.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002841 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002842 connection = Connection(Context(TLSv1_METHOD), None)
2843 ciphers = connection.get_cipher_list()
Alex Chanb7480992017-01-30 14:04:47 +00002844 assert isinstance(ciphers, list)
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002845 for cipher in ciphers:
Alex Chanb7480992017-01-30 14:04:47 +00002846 assert isinstance(cipher, str)
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002847
2848
Maximilian Hils868dc3c2017-02-10 14:56:55 +01002849class VeryLarge(bytes):
2850 """
2851 Mock object so that we don't have to allocate 2**31 bytes
2852 """
2853 def __len__(self):
2854 return 2**31
2855
2856
Alex Chanb7480992017-01-30 14:04:47 +00002857class TestConnectionSend(object):
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002858 """
Alex Chanb7480992017-01-30 14:04:47 +00002859 Tests for `Connection.send`.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002860 """
2861 def test_wrong_args(self):
2862 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002863 When called with arguments other than string argument for its first
Alex Chanb7480992017-01-30 14:04:47 +00002864 parameter, `Connection.send` raises `TypeError`.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002865 """
2866 connection = Connection(Context(TLSv1_METHOD), None)
Alex Chanb7480992017-01-30 14:04:47 +00002867 with pytest.raises(TypeError):
2868 connection.send(object())
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002869
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002870 def test_short_bytes(self):
2871 """
Alex Chanb7480992017-01-30 14:04:47 +00002872 When passed a short byte string, `Connection.send` transmits all of it
2873 and returns the number of bytes sent.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002874 """
Alex Chanb7480992017-01-30 14:04:47 +00002875 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002876 count = server.send(b'xy')
Alex Chanb7480992017-01-30 14:04:47 +00002877 assert count == 2
2878 assert client.recv(2) == b'xy'
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002879
Abraham Martinef063482015-03-25 14:06:24 +00002880 def test_text(self):
2881 """
Alex Chanb7480992017-01-30 14:04:47 +00002882 When passed a text, `Connection.send` transmits all of it and
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002883 returns the number of bytes sent. It also raises a DeprecationWarning.
Abraham Martinef063482015-03-25 14:06:24 +00002884 """
Alex Chanb7480992017-01-30 14:04:47 +00002885 server, client = loopback()
2886 with pytest.warns(DeprecationWarning) as w:
Abraham Martinef063482015-03-25 14:06:24 +00002887 simplefilter("always")
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002888 count = server.send(b"xy".decode("ascii"))
Alex Chanb7480992017-01-30 14:04:47 +00002889 assert (
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002890 "{0} for buf is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002891 WARNING_TYPE_EXPECTED
Alex Chanb7480992017-01-30 14:04:47 +00002892 ) == str(w[-1].message))
2893 assert count == 2
2894 assert client.recv(2) == b'xy'
Abraham Martinef063482015-03-25 14:06:24 +00002895
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002896 def test_short_memoryview(self):
2897 """
2898 When passed a memoryview onto a small number of bytes,
Alex Chanb7480992017-01-30 14:04:47 +00002899 `Connection.send` transmits all of them and returns the number
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002900 of bytes sent.
2901 """
Alex Chanb7480992017-01-30 14:04:47 +00002902 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002903 count = server.send(memoryview(b'xy'))
Alex Chanb7480992017-01-30 14:04:47 +00002904 assert count == 2
2905 assert client.recv(2) == b'xy'
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002906
Hynek Schlawack8e94f1b2015-09-05 21:31:00 +02002907 @skip_if_py3
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002908 def test_short_buffer(self):
2909 """
2910 When passed a buffer containing a small number of bytes,
Alex Chanb7480992017-01-30 14:04:47 +00002911 `Connection.send` transmits all of them and returns the number
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002912 of bytes sent.
2913 """
Alex Chanb7480992017-01-30 14:04:47 +00002914 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002915 count = server.send(buffer(b'xy'))
Alex Chanb7480992017-01-30 14:04:47 +00002916 assert count == 2
2917 assert client.recv(2) == b'xy'
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02002918
Maximilian Hils868dc3c2017-02-10 14:56:55 +01002919 @pytest.mark.skipif(
2920 sys.maxsize < 2**31,
2921 reason="sys.maxsize < 2**31 - test requires 64 bit"
2922 )
2923 def test_buf_too_large(self):
2924 """
2925 When passed a buffer containing >= 2**31 bytes,
2926 `Connection.send` bails out as SSL_write only
2927 accepts an int for the buffer length.
2928 """
2929 connection = Connection(Context(TLSv1_METHOD), None)
2930 with pytest.raises(ValueError) as exc_info:
2931 connection.send(VeryLarge())
2932 exc_info.match(r"Cannot send more than .+ bytes at once")
2933
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05002934
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002935def _make_memoryview(size):
2936 """
2937 Create a new ``memoryview`` wrapped around a ``bytearray`` of the given
2938 size.
2939 """
2940 return memoryview(bytearray(size))
2941
2942
Alex Chanb7480992017-01-30 14:04:47 +00002943class TestConnectionRecvInto(object):
Cory Benfield62d10332014-06-15 10:03:41 +01002944 """
Alex Chanb7480992017-01-30 14:04:47 +00002945 Tests for `Connection.recv_into`.
Cory Benfield62d10332014-06-15 10:03:41 +01002946 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002947 def _no_length_test(self, factory):
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04002948 """
Alex Chanb7480992017-01-30 14:04:47 +00002949 Assert that when the given buffer is passed to `Connection.recv_into`,
2950 whatever bytes are available to be received that fit into that buffer
2951 are written into that buffer.
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04002952 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002953 output_buffer = factory(5)
2954
Alex Chanb7480992017-01-30 14:04:47 +00002955 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002956 server.send(b'xy')
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04002957
Alex Chanb7480992017-01-30 14:04:47 +00002958 assert client.recv_into(output_buffer) == 2
2959 assert output_buffer == bytearray(b'xy\x00\x00\x00')
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04002960
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002961 def test_bytearray_no_length(self):
Cory Benfield62d10332014-06-15 10:03:41 +01002962 """
Alex Chanb7480992017-01-30 14:04:47 +00002963 `Connection.recv_into` can be passed a `bytearray` instance and data
2964 in the receive buffer is written to it.
Cory Benfield62d10332014-06-15 10:03:41 +01002965 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002966 self._no_length_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01002967
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002968 def _respects_length_test(self, factory):
Cory Benfield62d10332014-06-15 10:03:41 +01002969 """
Alex Chanb7480992017-01-30 14:04:47 +00002970 Assert that when the given buffer is passed to `Connection.recv_into`
2971 along with a value for `nbytes` that is less than the size of that
2972 buffer, only `nbytes` bytes are written into the buffer.
Cory Benfield62d10332014-06-15 10:03:41 +01002973 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002974 output_buffer = factory(10)
2975
Alex Chanb7480992017-01-30 14:04:47 +00002976 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002977 server.send(b'abcdefghij')
Cory Benfield62d10332014-06-15 10:03:41 +01002978
Alex Chanb7480992017-01-30 14:04:47 +00002979 assert client.recv_into(output_buffer, 5) == 5
2980 assert output_buffer == bytearray(b'abcde\x00\x00\x00\x00\x00')
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002981
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002982 def test_bytearray_respects_length(self):
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002983 """
Alex Chanb7480992017-01-30 14:04:47 +00002984 When called with a `bytearray` instance, `Connection.recv_into`
2985 respects the `nbytes` parameter and doesn't copy in more than that
2986 number of bytes.
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002987 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002988 self._respects_length_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01002989
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002990 def _doesnt_overfill_test(self, factory):
Cory Benfield62d10332014-06-15 10:03:41 +01002991 """
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002992 Assert that if there are more bytes available to be read from the
2993 receive buffer than would fit into the buffer passed to
Alex Chanb7480992017-01-30 14:04:47 +00002994 `Connection.recv_into`, only as many as fit are written into it.
Cory Benfield62d10332014-06-15 10:03:41 +01002995 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002996 output_buffer = factory(5)
2997
Alex Chanb7480992017-01-30 14:04:47 +00002998 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002999 server.send(b'abcdefghij')
Cory Benfield62d10332014-06-15 10:03:41 +01003000
Alex Chanb7480992017-01-30 14:04:47 +00003001 assert client.recv_into(output_buffer) == 5
3002 assert output_buffer == bytearray(b'abcde')
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04003003 rest = client.recv(5)
Alex Chanb7480992017-01-30 14:04:47 +00003004 assert b'fghij' == rest
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04003005
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04003006 def test_bytearray_doesnt_overfill(self):
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04003007 """
Alex Chanb7480992017-01-30 14:04:47 +00003008 When called with a `bytearray` instance, `Connection.recv_into`
3009 respects the size of the array and doesn't write more bytes into it
3010 than will fit.
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04003011 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003012 self._doesnt_overfill_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01003013
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04003014 def test_bytearray_really_doesnt_overfill(self):
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003015 """
Alex Chanb7480992017-01-30 14:04:47 +00003016 When called with a `bytearray` instance and an `nbytes` value that is
3017 too large, `Connection.recv_into` respects the size of the array and
3018 not the `nbytes` value and doesn't write more bytes into the buffer
3019 than will fit.
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003020 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003021 self._doesnt_overfill_test(bytearray)
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003022
Maximilian Hils1d95dea2015-08-17 19:27:20 +02003023 def test_peek(self):
Alex Chanb7480992017-01-30 14:04:47 +00003024 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04003025 server.send(b'xy')
Maximilian Hils1d95dea2015-08-17 19:27:20 +02003026
3027 for _ in range(2):
3028 output_buffer = bytearray(5)
Alex Chanb7480992017-01-30 14:04:47 +00003029 assert client.recv_into(output_buffer, flags=MSG_PEEK) == 2
3030 assert output_buffer == bytearray(b'xy\x00\x00\x00')
Maximilian Hils1d95dea2015-08-17 19:27:20 +02003031
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003032 def test_memoryview_no_length(self):
3033 """
Alex Chanb7480992017-01-30 14:04:47 +00003034 `Connection.recv_into` can be passed a `memoryview` instance and data
3035 in the receive buffer is written to it.
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003036 """
3037 self._no_length_test(_make_memoryview)
Maximilian Hils1d95dea2015-08-17 19:27:20 +02003038
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003039 def test_memoryview_respects_length(self):
3040 """
Alex Chanb7480992017-01-30 14:04:47 +00003041 When called with a `memoryview` instance, `Connection.recv_into`
3042 respects the ``nbytes`` parameter and doesn't copy more than that
3043 number of bytes in.
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003044 """
3045 self._respects_length_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01003046
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003047 def test_memoryview_doesnt_overfill(self):
3048 """
Alex Chanb7480992017-01-30 14:04:47 +00003049 When called with a `memoryview` instance, `Connection.recv_into`
3050 respects the size of the array and doesn't write more bytes into it
3051 than will fit.
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003052 """
3053 self._doesnt_overfill_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01003054
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003055 def test_memoryview_really_doesnt_overfill(self):
3056 """
Alex Chanb7480992017-01-30 14:04:47 +00003057 When called with a `memoryview` instance and an `nbytes` value that is
3058 too large, `Connection.recv_into` respects the size of the array and
3059 not the `nbytes` value and doesn't write more bytes into the buffer
3060 than will fit.
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003061 """
3062 self._doesnt_overfill_test(_make_memoryview)
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003063
Cory Benfield62d10332014-06-15 10:03:41 +01003064
Alex Chanb7480992017-01-30 14:04:47 +00003065class TestConnectionSendall(object):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003066 """
Alex Chanb7480992017-01-30 14:04:47 +00003067 Tests for `Connection.sendall`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003068 """
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003069 def test_wrong_args(self):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003070 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003071 When called with arguments other than a string argument for its first
Alex Chanb7480992017-01-30 14:04:47 +00003072 parameter, `Connection.sendall` raises `TypeError`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003073 """
3074 connection = Connection(Context(TLSv1_METHOD), None)
Alex Chanb7480992017-01-30 14:04:47 +00003075 with pytest.raises(TypeError):
3076 connection.sendall(object())
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003077
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003078 def test_short(self):
3079 """
Alex Chanb7480992017-01-30 14:04:47 +00003080 `Connection.sendall` transmits all of the bytes in the string
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003081 passed to it.
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003082 """
Alex Chanb7480992017-01-30 14:04:47 +00003083 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04003084 server.sendall(b'x')
Alex Chanb7480992017-01-30 14:04:47 +00003085 assert client.recv(1) == b'x'
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003086
Abraham Martinef063482015-03-25 14:06:24 +00003087 def test_text(self):
3088 """
Alex Chanb7480992017-01-30 14:04:47 +00003089 `Connection.sendall` transmits all the content in the string passed
3090 to it, raising a DeprecationWarning in case of this being a text.
Abraham Martinef063482015-03-25 14:06:24 +00003091 """
Alex Chanb7480992017-01-30 14:04:47 +00003092 server, client = loopback()
3093 with pytest.warns(DeprecationWarning) as w:
Abraham Martinef063482015-03-25 14:06:24 +00003094 simplefilter("always")
Jean-Paul Calderone8dc37a12015-03-29 08:16:52 -04003095 server.sendall(b"x".decode("ascii"))
Alex Chanb7480992017-01-30 14:04:47 +00003096 assert (
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04003097 "{0} for buf is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04003098 WARNING_TYPE_EXPECTED
Alex Chanb7480992017-01-30 14:04:47 +00003099 ) == str(w[-1].message))
3100 assert client.recv(1) == b"x"
Abraham Martinef063482015-03-25 14:06:24 +00003101
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003102 def test_short_memoryview(self):
3103 """
3104 When passed a memoryview onto a small number of bytes,
Alex Chanb7480992017-01-30 14:04:47 +00003105 `Connection.sendall` transmits all of them.
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003106 """
Alex Chanb7480992017-01-30 14:04:47 +00003107 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04003108 server.sendall(memoryview(b'x'))
Alex Chanb7480992017-01-30 14:04:47 +00003109 assert client.recv(1) == b'x'
Abraham Martinef063482015-03-25 14:06:24 +00003110
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003111 @skip_if_py3
3112 def test_short_buffers(self):
3113 """
3114 When passed a buffer containing a small number of bytes,
Alex Chanb7480992017-01-30 14:04:47 +00003115 `Connection.sendall` transmits all of them.
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003116 """
Alex Chanb7480992017-01-30 14:04:47 +00003117 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04003118 server.sendall(buffer(b'x'))
Alex Chanb7480992017-01-30 14:04:47 +00003119 assert client.recv(1) == b'x'
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02003120
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003121 def test_long(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003122 """
Alex Chanb7480992017-01-30 14:04:47 +00003123 `Connection.sendall` transmits all the bytes in the string passed to it
3124 even if this requires multiple calls of an underlying write function.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003125 """
Alex Chanb7480992017-01-30 14:04:47 +00003126 server, client = loopback()
Jean-Paul Calderone6241c702010-09-16 19:59:24 -04003127 # Should be enough, underlying SSL_write should only do 16k at a time.
Hynek Schlawack35618382015-09-05 21:54:25 +02003128 # On Windows, after 32k of bytes the write will block (forever
3129 # - because no one is yet reading).
Alex Gaynore7f51982016-09-11 11:48:14 -04003130 message = b'x' * (1024 * 32 - 1) + b'y'
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003131 server.sendall(message)
3132 accum = []
3133 received = 0
3134 while received < len(message):
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04003135 data = client.recv(1024)
3136 accum.append(data)
3137 received += len(data)
Alex Chanb7480992017-01-30 14:04:47 +00003138 assert message == b''.join(accum)
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003139
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003140 def test_closed(self):
3141 """
Alex Chanb7480992017-01-30 14:04:47 +00003142 If the underlying socket is closed, `Connection.sendall` propagates the
3143 write error from the low level write call.
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003144 """
Alex Chanb7480992017-01-30 14:04:47 +00003145 server, client = loopback()
Jean-Paul Calderone05d43e82010-09-24 18:01:36 -04003146 server.sock_shutdown(2)
Alex Chanb7480992017-01-30 14:04:47 +00003147 with pytest.raises(SysCallError) as err:
3148 server.sendall(b"hello, world")
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +02003149 if platform == "win32":
Alex Chanb7480992017-01-30 14:04:47 +00003150 assert err.value.args[0] == ESHUTDOWN
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +02003151 else:
Alex Chanb7480992017-01-30 14:04:47 +00003152 assert err.value.args[0] == EPIPE
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003153
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003154
Alex Chanb7480992017-01-30 14:04:47 +00003155class TestConnectionRenegotiate(object):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003156 """
3157 Tests for SSL renegotiation APIs.
3158 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003159 def test_total_renegotiations(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003160 """
Alex Chanb7480992017-01-30 14:04:47 +00003161 `Connection.total_renegotiations` returns `0` before any renegotiations
3162 have happened.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003163 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003164 connection = Connection(Context(TLSv1_METHOD), None)
Alex Chanb7480992017-01-30 14:04:47 +00003165 assert connection.total_renegotiations() == 0
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003166
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003167 def test_renegotiate(self):
3168 """
3169 Go through a complete renegotiation cycle.
3170 """
Alex Chanb7480992017-01-30 14:04:47 +00003171 server, client = loopback()
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003172
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003173 server.send(b"hello world")
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003174
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003175 assert b"hello world" == client.recv(len(b"hello world"))
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003176
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003177 assert 0 == server.total_renegotiations()
3178 assert False is server.renegotiate_pending()
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003179
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003180 assert True is server.renegotiate()
3181
3182 assert True is server.renegotiate_pending()
3183
3184 server.setblocking(False)
3185 client.setblocking(False)
3186
3187 client.do_handshake()
3188 server.do_handshake()
3189
3190 assert 1 == server.total_renegotiations()
3191 while False is server.renegotiate_pending():
3192 pass
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003193
3194
Alex Chanb7480992017-01-30 14:04:47 +00003195class TestError(object):
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003196 """
Alex Chanb7480992017-01-30 14:04:47 +00003197 Unit tests for `OpenSSL.SSL.Error`.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003198 """
3199 def test_type(self):
3200 """
Alex Chanb7480992017-01-30 14:04:47 +00003201 `Error` is an exception type.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003202 """
Alex Chanb7480992017-01-30 14:04:47 +00003203 assert issubclass(Error, Exception)
3204 assert Error.__name__ == 'Error'
Rick Deane15b1472009-07-09 15:53:42 -05003205
3206
Alex Chanb7480992017-01-30 14:04:47 +00003207class TestConstants(object):
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003208 """
Alex Chanb7480992017-01-30 14:04:47 +00003209 Tests for the values of constants exposed in `OpenSSL.SSL`.
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003210
3211 These are values defined by OpenSSL intended only to be used as flags to
3212 OpenSSL APIs. The only assertions it seems can be made about them is
3213 their values.
3214 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003215 @pytest.mark.skipif(
3216 OP_NO_QUERY_MTU is None,
3217 reason="OP_NO_QUERY_MTU unavailable - OpenSSL version may be too old"
3218 )
3219 def test_op_no_query_mtu(self):
3220 """
Alex Chanb7480992017-01-30 14:04:47 +00003221 The value of `OpenSSL.SSL.OP_NO_QUERY_MTU` is 0x1000, the value
3222 of `SSL_OP_NO_QUERY_MTU` defined by `openssl/ssl.h`.
Hynek Schlawack35618382015-09-05 21:54:25 +02003223 """
Alex Chanb7480992017-01-30 14:04:47 +00003224 assert OP_NO_QUERY_MTU == 0x1000
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003225
Hynek Schlawack35618382015-09-05 21:54:25 +02003226 @pytest.mark.skipif(
3227 OP_COOKIE_EXCHANGE is None,
3228 reason="OP_COOKIE_EXCHANGE unavailable - "
3229 "OpenSSL version may be too old"
3230 )
3231 def test_op_cookie_exchange(self):
3232 """
Alex Chanb7480992017-01-30 14:04:47 +00003233 The value of `OpenSSL.SSL.OP_COOKIE_EXCHANGE` is 0x2000, the
3234 value of `SSL_OP_COOKIE_EXCHANGE` defined by `openssl/ssl.h`.
Hynek Schlawack35618382015-09-05 21:54:25 +02003235 """
Alex Chanb7480992017-01-30 14:04:47 +00003236 assert OP_COOKIE_EXCHANGE == 0x2000
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003237
Hynek Schlawack35618382015-09-05 21:54:25 +02003238 @pytest.mark.skipif(
3239 OP_NO_TICKET is None,
3240 reason="OP_NO_TICKET unavailable - OpenSSL version may be too old"
3241 )
3242 def test_op_no_ticket(self):
3243 """
Alex Chanb7480992017-01-30 14:04:47 +00003244 The value of `OpenSSL.SSL.OP_NO_TICKET` is 0x4000, the value of
3245 `SSL_OP_NO_TICKET` defined by `openssl/ssl.h`.
Hynek Schlawack35618382015-09-05 21:54:25 +02003246 """
Alex Chanb7480992017-01-30 14:04:47 +00003247 assert OP_NO_TICKET == 0x4000
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003248
Hynek Schlawack35618382015-09-05 21:54:25 +02003249 @pytest.mark.skipif(
3250 OP_NO_COMPRESSION is None,
3251 reason="OP_NO_COMPRESSION unavailable - OpenSSL version may be too old"
3252 )
3253 def test_op_no_compression(self):
3254 """
Alex Chanb7480992017-01-30 14:04:47 +00003255 The value of `OpenSSL.SSL.OP_NO_COMPRESSION` is 0x20000, the
3256 value of `SSL_OP_NO_COMPRESSION` defined by `openssl/ssl.h`.
Hynek Schlawack35618382015-09-05 21:54:25 +02003257 """
Alex Chanb7480992017-01-30 14:04:47 +00003258 assert OP_NO_COMPRESSION == 0x20000
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04003259
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003260 def test_sess_cache_off(self):
3261 """
Alex Chanb7480992017-01-30 14:04:47 +00003262 The value of `OpenSSL.SSL.SESS_CACHE_OFF` 0x0, the value of
3263 `SSL_SESS_CACHE_OFF` defined by `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003264 """
Alex Chanb7480992017-01-30 14:04:47 +00003265 assert 0x0 == SESS_CACHE_OFF
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003266
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003267 def test_sess_cache_client(self):
3268 """
Alex Chanb7480992017-01-30 14:04:47 +00003269 The value of `OpenSSL.SSL.SESS_CACHE_CLIENT` 0x1, the value of
3270 `SSL_SESS_CACHE_CLIENT` defined by `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003271 """
Alex Chanb7480992017-01-30 14:04:47 +00003272 assert 0x1 == SESS_CACHE_CLIENT
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003273
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003274 def test_sess_cache_server(self):
3275 """
Alex Chanb7480992017-01-30 14:04:47 +00003276 The value of `OpenSSL.SSL.SESS_CACHE_SERVER` 0x2, the value of
3277 `SSL_SESS_CACHE_SERVER` defined by `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003278 """
Alex Chanb7480992017-01-30 14:04:47 +00003279 assert 0x2 == SESS_CACHE_SERVER
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003280
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003281 def test_sess_cache_both(self):
3282 """
Alex Chanb7480992017-01-30 14:04:47 +00003283 The value of `OpenSSL.SSL.SESS_CACHE_BOTH` 0x3, the value of
3284 `SSL_SESS_CACHE_BOTH` defined by `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003285 """
Alex Chanb7480992017-01-30 14:04:47 +00003286 assert 0x3 == SESS_CACHE_BOTH
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003287
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003288 def test_sess_cache_no_auto_clear(self):
3289 """
Alex Chanb7480992017-01-30 14:04:47 +00003290 The value of `OpenSSL.SSL.SESS_CACHE_NO_AUTO_CLEAR` 0x80, the
3291 value of `SSL_SESS_CACHE_NO_AUTO_CLEAR` defined by
3292 `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003293 """
Alex Chanb7480992017-01-30 14:04:47 +00003294 assert 0x80 == SESS_CACHE_NO_AUTO_CLEAR
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003295
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003296 def test_sess_cache_no_internal_lookup(self):
3297 """
Alex Chanb7480992017-01-30 14:04:47 +00003298 The value of `OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_LOOKUP` 0x100,
3299 the value of `SSL_SESS_CACHE_NO_INTERNAL_LOOKUP` defined by
3300 `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003301 """
Alex Chanb7480992017-01-30 14:04:47 +00003302 assert 0x100 == SESS_CACHE_NO_INTERNAL_LOOKUP
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003303
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003304 def test_sess_cache_no_internal_store(self):
3305 """
Alex Chanb7480992017-01-30 14:04:47 +00003306 The value of `OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_STORE` 0x200,
3307 the value of `SSL_SESS_CACHE_NO_INTERNAL_STORE` defined by
3308 `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003309 """
Alex Chanb7480992017-01-30 14:04:47 +00003310 assert 0x200 == SESS_CACHE_NO_INTERNAL_STORE
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003311
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003312 def test_sess_cache_no_internal(self):
3313 """
Alex Chanb7480992017-01-30 14:04:47 +00003314 The value of `OpenSSL.SSL.SESS_CACHE_NO_INTERNAL` 0x300, the
3315 value of `SSL_SESS_CACHE_NO_INTERNAL` defined by
3316 `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003317 """
Alex Chanb7480992017-01-30 14:04:47 +00003318 assert 0x300 == SESS_CACHE_NO_INTERNAL
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003319
3320
Alex Chanb7480992017-01-30 14:04:47 +00003321class TestMemoryBIO(object):
Rick Deanb71c0d22009-04-01 14:09:23 -05003322 """
Alex Chanb7480992017-01-30 14:04:47 +00003323 Tests for `OpenSSL.SSL.Connection` using a memory BIO.
Rick Deanb71c0d22009-04-01 14:09:23 -05003324 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003325 def _server(self, sock):
3326 """
Alex Chanb7480992017-01-30 14:04:47 +00003327 Create a new server-side SSL `Connection` object wrapped around `sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003328 """
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003329 # Create the server side Connection. This is mostly setup boilerplate
3330 # - use TLSv1, use a particular certificate, etc.
3331 server_ctx = Context(TLSv1_METHOD)
Alex Gaynor43307782015-09-04 09:05:45 -04003332 server_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE)
Hynek Schlawack35618382015-09-05 21:54:25 +02003333 server_ctx.set_verify(
3334 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT | VERIFY_CLIENT_ONCE,
3335 verify_cb
3336 )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003337 server_store = server_ctx.get_cert_store()
Hynek Schlawack35618382015-09-05 21:54:25 +02003338 server_ctx.use_privatekey(
3339 load_privatekey(FILETYPE_PEM, server_key_pem))
3340 server_ctx.use_certificate(
3341 load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003342 server_ctx.check_privatekey()
3343 server_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Hynek Schlawack35618382015-09-05 21:54:25 +02003344 # Here the Connection is actually created. If None is passed as the
3345 # 2nd parameter, it indicates a memory BIO should be created.
Rick Deanb1ccd562009-07-09 23:52:39 -05003346 server_conn = Connection(server_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003347 server_conn.set_accept_state()
3348 return server_conn
3349
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003350 def _client(self, sock):
3351 """
Alex Chanb7480992017-01-30 14:04:47 +00003352 Create a new client-side SSL `Connection` object wrapped around `sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003353 """
3354 # Now create the client side Connection. Similar boilerplate to the
3355 # above.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003356 client_ctx = Context(TLSv1_METHOD)
Alex Gaynor43307782015-09-04 09:05:45 -04003357 client_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE)
Hynek Schlawack35618382015-09-05 21:54:25 +02003358 client_ctx.set_verify(
3359 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT | VERIFY_CLIENT_ONCE,
3360 verify_cb
3361 )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003362 client_store = client_ctx.get_cert_store()
Hynek Schlawack35618382015-09-05 21:54:25 +02003363 client_ctx.use_privatekey(
3364 load_privatekey(FILETYPE_PEM, client_key_pem))
3365 client_ctx.use_certificate(
3366 load_certificate(FILETYPE_PEM, client_cert_pem))
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003367 client_ctx.check_privatekey()
3368 client_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05003369 client_conn = Connection(client_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003370 client_conn.set_connect_state()
3371 return client_conn
3372
Alex Chanb7480992017-01-30 14:04:47 +00003373 def test_memory_connect(self):
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003374 """
Alex Chanb7480992017-01-30 14:04:47 +00003375 Two `Connection`s which use memory BIOs can be manually connected by
3376 reading from the output of each and writing those bytes to the input of
3377 the other and in this way establish a connection and exchange
3378 application-level bytes with each other.
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003379 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003380 server_conn = self._server(None)
3381 client_conn = self._client(None)
Rick Deanb71c0d22009-04-01 14:09:23 -05003382
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003383 # There should be no key or nonces yet.
Alex Chanb7480992017-01-30 14:04:47 +00003384 assert server_conn.master_key() is None
3385 assert server_conn.client_random() is None
3386 assert server_conn.server_random() is None
Rick Deanb71c0d22009-04-01 14:09:23 -05003387
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003388 # First, the handshake needs to happen. We'll deliver bytes back and
3389 # forth between the client and server until neither of them feels like
3390 # speaking any more.
Alex Chanb7480992017-01-30 14:04:47 +00003391 assert interact_in_memory(client_conn, server_conn) is None
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003392
3393 # Now that the handshake is done, there should be a key and nonces.
Alex Chanb7480992017-01-30 14:04:47 +00003394 assert server_conn.master_key() is not None
3395 assert server_conn.client_random() is not None
3396 assert server_conn.server_random() is not None
3397 assert server_conn.client_random() == client_conn.client_random()
3398 assert server_conn.server_random() == client_conn.server_random()
3399 assert server_conn.client_random() != server_conn.server_random()
3400 assert client_conn.client_random() != client_conn.server_random()
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003401
Paul Kehrerbdb76392017-12-01 04:54:32 +08003402 # Export key material for other uses.
3403 cekm = client_conn.export_keying_material(b'LABEL', 32)
3404 sekm = server_conn.export_keying_material(b'LABEL', 32)
3405 assert cekm is not None
3406 assert sekm is not None
3407 assert cekm == sekm
3408 assert len(sekm) == 32
3409
3410 # Export key material for other uses with additional context.
3411 cekmc = client_conn.export_keying_material(b'LABEL', 32, b'CONTEXT')
3412 sekmc = server_conn.export_keying_material(b'LABEL', 32, b'CONTEXT')
3413 assert cekmc is not None
3414 assert sekmc is not None
3415 assert cekmc == sekmc
3416 assert cekmc != cekm
3417 assert sekmc != sekm
3418 # Export with alternate label
3419 cekmt = client_conn.export_keying_material(b'test', 32, b'CONTEXT')
3420 sekmt = server_conn.export_keying_material(b'test', 32, b'CONTEXT')
3421 assert cekmc != cekmt
3422 assert sekmc != sekmt
3423
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003424 # Here are the bytes we'll try to send.
Alex Gaynore7f51982016-09-11 11:48:14 -04003425 important_message = b'One if by land, two if by sea.'
Rick Deanb71c0d22009-04-01 14:09:23 -05003426
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003427 server_conn.write(important_message)
Alex Chanb7480992017-01-30 14:04:47 +00003428 assert (
3429 interact_in_memory(client_conn, server_conn) ==
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003430 (client_conn, important_message))
3431
3432 client_conn.write(important_message[::-1])
Alex Chanb7480992017-01-30 14:04:47 +00003433 assert (
3434 interact_in_memory(client_conn, server_conn) ==
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003435 (server_conn, important_message[::-1]))
Rick Deanb71c0d22009-04-01 14:09:23 -05003436
Alex Chanb7480992017-01-30 14:04:47 +00003437 def test_socket_connect(self):
Rick Deanb1ccd562009-07-09 23:52:39 -05003438 """
Alex Chanb7480992017-01-30 14:04:47 +00003439 Just like `test_memory_connect` but with an actual socket.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003440
Hynek Schlawack35618382015-09-05 21:54:25 +02003441 This is primarily to rule out the memory BIO code as the source of any
Alex Chanb7480992017-01-30 14:04:47 +00003442 problems encountered while passing data over a `Connection` (if
Hynek Schlawack35618382015-09-05 21:54:25 +02003443 this test fails, there must be a problem outside the memory BIO code,
3444 as no memory BIO is involved here). Even though this isn't a memory
3445 BIO test, it's convenient to have it here.
Rick Deanb1ccd562009-07-09 23:52:39 -05003446 """
Alex Chanb7480992017-01-30 14:04:47 +00003447 server_conn, client_conn = loopback()
Rick Deanb1ccd562009-07-09 23:52:39 -05003448
Alex Gaynore7f51982016-09-11 11:48:14 -04003449 important_message = b"Help me Obi Wan Kenobi, you're my only hope."
Rick Deanb1ccd562009-07-09 23:52:39 -05003450 client_conn.send(important_message)
3451 msg = server_conn.recv(1024)
Alex Chanb7480992017-01-30 14:04:47 +00003452 assert msg == important_message
Rick Deanb1ccd562009-07-09 23:52:39 -05003453
3454 # Again in the other direction, just for fun.
3455 important_message = important_message[::-1]
3456 server_conn.send(important_message)
3457 msg = client_conn.recv(1024)
Alex Chanb7480992017-01-30 14:04:47 +00003458 assert msg == important_message
Rick Deanb1ccd562009-07-09 23:52:39 -05003459
Alex Chanb7480992017-01-30 14:04:47 +00003460 def test_socket_overrides_memory(self):
Rick Deanb71c0d22009-04-01 14:09:23 -05003461 """
Alex Chanb7480992017-01-30 14:04:47 +00003462 Test that `OpenSSL.SSL.bio_read` and `OpenSSL.SSL.bio_write` don't
3463 work on `OpenSSL.SSL.Connection`() that use sockets.
Rick Deanb71c0d22009-04-01 14:09:23 -05003464 """
Alex Gaynor51d424c2016-09-10 14:50:11 -04003465 context = Context(TLSv1_METHOD)
Rick Deanb71c0d22009-04-01 14:09:23 -05003466 client = socket()
3467 clientSSL = Connection(context, client)
Alex Chanb7480992017-01-30 14:04:47 +00003468 with pytest.raises(TypeError):
3469 clientSSL.bio_read(100)
3470 with pytest.raises(TypeError):
3471 clientSSL.bio_write("foo")
3472 with pytest.raises(TypeError):
3473 clientSSL.bio_shutdown()
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003474
Alex Chanb7480992017-01-30 14:04:47 +00003475 def test_outgoing_overflow(self):
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003476 """
3477 If more bytes than can be written to the memory BIO are passed to
Alex Chanb7480992017-01-30 14:04:47 +00003478 `Connection.send` at once, the number of bytes which were written is
3479 returned and that many bytes from the beginning of the input can be
3480 read from the other end of the connection.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003481 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003482 server = self._server(None)
3483 client = self._client(None)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003484
Alex Chanb7480992017-01-30 14:04:47 +00003485 interact_in_memory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003486
3487 size = 2 ** 15
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003488 sent = client.send(b"x" * size)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003489 # Sanity check. We're trying to test what happens when the entire
3490 # input can't be sent. If the entire input was sent, this test is
3491 # meaningless.
Alex Chanb7480992017-01-30 14:04:47 +00003492 assert sent < size
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003493
Alex Chanb7480992017-01-30 14:04:47 +00003494 receiver, received = interact_in_memory(client, server)
3495 assert receiver is server
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003496
3497 # We can rely on all of these bytes being received at once because
Alex Chanb7480992017-01-30 14:04:47 +00003498 # loopback passes 2 ** 16 to recv - more than 2 ** 15.
3499 assert len(received) == sent
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003500
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003501 def test_shutdown(self):
3502 """
Alex Chanb7480992017-01-30 14:04:47 +00003503 `Connection.bio_shutdown` signals the end of the data stream
3504 from which the `Connection` reads.
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003505 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003506 server = self._server(None)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003507 server.bio_shutdown()
Alex Chanb7480992017-01-30 14:04:47 +00003508 with pytest.raises(Error) as err:
3509 server.recv(1024)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003510 # We don't want WantReadError or ZeroReturnError or anything - it's a
3511 # handshake failure.
Alex Chanb7480992017-01-30 14:04:47 +00003512 assert type(err.value) in [Error, SysCallError]
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003513
Alex Chanb7480992017-01-30 14:04:47 +00003514 def test_unexpected_EOF(self):
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003515 """
3516 If the connection is lost before an orderly SSL shutdown occurs,
Alex Chanb7480992017-01-30 14:04:47 +00003517 `OpenSSL.SSL.SysCallError` is raised with a message of
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003518 "Unexpected EOF".
3519 """
Alex Chanb7480992017-01-30 14:04:47 +00003520 server_conn, client_conn = loopback()
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003521 client_conn.sock_shutdown(SHUT_RDWR)
Alex Chanb7480992017-01-30 14:04:47 +00003522 with pytest.raises(SysCallError) as err:
3523 server_conn.recv(1024)
3524 assert err.value.args == (-1, "Unexpected EOF")
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003525
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003526 def _check_client_ca_list(self, func):
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003527 """
Alex Chanb7480992017-01-30 14:04:47 +00003528 Verify the return value of the `get_client_ca_list` method for
Hynek Schlawack35618382015-09-05 21:54:25 +02003529 server and client connections.
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003530
Jonathan Ballet78b92a22011-07-16 08:07:26 +09003531 :param func: A function which will be called with the server context
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003532 before the client and server are connected to each other. This
3533 function should specify a list of CAs for the server to send to the
3534 client and return that same list. The list will be used to verify
Alex Chanb7480992017-01-30 14:04:47 +00003535 that `get_client_ca_list` returns the proper value at
Hynek Schlawack35618382015-09-05 21:54:25 +02003536 various times.
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003537 """
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003538 server = self._server(None)
3539 client = self._client(None)
Alex Chanb7480992017-01-30 14:04:47 +00003540 assert client.get_client_ca_list() == []
3541 assert server.get_client_ca_list() == []
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003542 ctx = server.get_context()
3543 expected = func(ctx)
Alex Chanb7480992017-01-30 14:04:47 +00003544 assert client.get_client_ca_list() == []
3545 assert server.get_client_ca_list() == expected
3546 interact_in_memory(client, server)
3547 assert client.get_client_ca_list() == expected
3548 assert server.get_client_ca_list() == expected
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003549
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003550 def test_set_client_ca_list_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003551 """
Alex Chanb7480992017-01-30 14:04:47 +00003552 `Context.set_client_ca_list` raises a `TypeError` if called with a
3553 non-list or a list that contains objects other than X509Names.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003554 """
3555 ctx = Context(TLSv1_METHOD)
Alex Chanb7480992017-01-30 14:04:47 +00003556 with pytest.raises(TypeError):
3557 ctx.set_client_ca_list("spam")
3558 with pytest.raises(TypeError):
3559 ctx.set_client_ca_list(["spam"])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003560
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003561 def test_set_empty_ca_list(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003562 """
Alex Chanb7480992017-01-30 14:04:47 +00003563 If passed an empty list, `Context.set_client_ca_list` configures the
3564 context to send no CA names to the client and, on both the server and
3565 client sides, `Connection.get_client_ca_list` returns an empty list
3566 after the connection is set up.
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003567 """
3568 def no_ca(ctx):
3569 ctx.set_client_ca_list([])
3570 return []
3571 self._check_client_ca_list(no_ca)
3572
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003573 def test_set_one_ca_list(self):
3574 """
3575 If passed a list containing a single X509Name,
Alex Chanb7480992017-01-30 14:04:47 +00003576 `Context.set_client_ca_list` configures the context to send
Hynek Schlawack35618382015-09-05 21:54:25 +02003577 that CA name to the client and, on both the server and client sides,
Alex Chanb7480992017-01-30 14:04:47 +00003578 `Connection.get_client_ca_list` returns a list containing that
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003579 X509Name after the connection is set up.
3580 """
3581 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3582 cadesc = cacert.get_subject()
Hynek Schlawack35618382015-09-05 21:54:25 +02003583
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003584 def single_ca(ctx):
3585 ctx.set_client_ca_list([cadesc])
3586 return [cadesc]
3587 self._check_client_ca_list(single_ca)
3588
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003589 def test_set_multiple_ca_list(self):
3590 """
3591 If passed a list containing multiple X509Name objects,
Alex Chanb7480992017-01-30 14:04:47 +00003592 `Context.set_client_ca_list` configures the context to send
Hynek Schlawack35618382015-09-05 21:54:25 +02003593 those CA names to the client and, on both the server and client sides,
Alex Chanb7480992017-01-30 14:04:47 +00003594 `Connection.get_client_ca_list` returns a list containing those
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003595 X509Names after the connection is set up.
3596 """
3597 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3598 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3599
3600 sedesc = secert.get_subject()
3601 cldesc = clcert.get_subject()
3602
3603 def multiple_ca(ctx):
3604 L = [sedesc, cldesc]
3605 ctx.set_client_ca_list(L)
3606 return L
3607 self._check_client_ca_list(multiple_ca)
3608
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003609 def test_reset_ca_list(self):
3610 """
3611 If called multiple times, only the X509Names passed to the final call
Alex Chanb7480992017-01-30 14:04:47 +00003612 of `Context.set_client_ca_list` are used to configure the CA
Hynek Schlawack35618382015-09-05 21:54:25 +02003613 names sent to the client.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003614 """
3615 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3616 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3617 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3618
3619 cadesc = cacert.get_subject()
3620 sedesc = secert.get_subject()
3621 cldesc = clcert.get_subject()
3622
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003623 def changed_ca(ctx):
3624 ctx.set_client_ca_list([sedesc, cldesc])
3625 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003626 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003627 self._check_client_ca_list(changed_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003628
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003629 def test_mutated_ca_list(self):
3630 """
Alex Chanb7480992017-01-30 14:04:47 +00003631 If the list passed to `Context.set_client_ca_list` is mutated
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003632 afterwards, this does not affect the list of CA names sent to the
3633 client.
3634 """
3635 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3636 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3637
3638 cadesc = cacert.get_subject()
3639 sedesc = secert.get_subject()
3640
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003641 def mutated_ca(ctx):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003642 L = [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003643 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003644 L.append(sedesc)
3645 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003646 self._check_client_ca_list(mutated_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003647
Alex Chanb7480992017-01-30 14:04:47 +00003648 def test_add_client_ca_wrong_args(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003649 """
Alex Chanb7480992017-01-30 14:04:47 +00003650 `Context.add_client_ca` raises `TypeError` if called with
3651 a non-X509 object.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003652 """
3653 ctx = Context(TLSv1_METHOD)
Alex Chanb7480992017-01-30 14:04:47 +00003654 with pytest.raises(TypeError):
3655 ctx.add_client_ca("spam")
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003656
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003657 def test_one_add_client_ca(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003658 """
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003659 A certificate's subject can be added as a CA to be sent to the client
Alex Chanb7480992017-01-30 14:04:47 +00003660 with `Context.add_client_ca`.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003661 """
3662 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3663 cadesc = cacert.get_subject()
Hynek Schlawack35618382015-09-05 21:54:25 +02003664
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003665 def single_ca(ctx):
3666 ctx.add_client_ca(cacert)
3667 return [cadesc]
3668 self._check_client_ca_list(single_ca)
3669
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003670 def test_multiple_add_client_ca(self):
3671 """
3672 Multiple CA names can be sent to the client by calling
Alex Chanb7480992017-01-30 14:04:47 +00003673 `Context.add_client_ca` with multiple X509 objects.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003674 """
3675 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3676 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3677
3678 cadesc = cacert.get_subject()
3679 sedesc = secert.get_subject()
3680
3681 def multiple_ca(ctx):
3682 ctx.add_client_ca(cacert)
3683 ctx.add_client_ca(secert)
3684 return [cadesc, sedesc]
3685 self._check_client_ca_list(multiple_ca)
3686
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003687 def test_set_and_add_client_ca(self):
3688 """
Alex Chanb7480992017-01-30 14:04:47 +00003689 A call to `Context.set_client_ca_list` followed by a call to
3690 `Context.add_client_ca` results in using the CA names from the
Hynek Schlawack35618382015-09-05 21:54:25 +02003691 first call and the CA name from the second call.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003692 """
3693 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3694 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3695 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3696
3697 cadesc = cacert.get_subject()
3698 sedesc = secert.get_subject()
3699 cldesc = clcert.get_subject()
3700
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003701 def mixed_set_add_ca(ctx):
3702 ctx.set_client_ca_list([cadesc, sedesc])
3703 ctx.add_client_ca(clcert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003704 return [cadesc, sedesc, cldesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003705 self._check_client_ca_list(mixed_set_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003706
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003707 def test_set_after_add_client_ca(self):
3708 """
Alex Chanb7480992017-01-30 14:04:47 +00003709 A call to `Context.set_client_ca_list` after a call to
3710 `Context.add_client_ca` replaces the CA name specified by the
Hynek Schlawack35618382015-09-05 21:54:25 +02003711 former call with the names specified by the latter call.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003712 """
3713 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3714 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3715 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3716
3717 cadesc = cacert.get_subject()
3718 sedesc = secert.get_subject()
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003719
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003720 def set_replaces_add_ca(ctx):
3721 ctx.add_client_ca(clcert)
3722 ctx.set_client_ca_list([cadesc])
3723 ctx.add_client_ca(secert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003724 return [cadesc, sedesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003725 self._check_client_ca_list(set_replaces_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003726
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003727
Alex Chanb7480992017-01-30 14:04:47 +00003728class TestInfoConstants(object):
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003729 """
3730 Tests for assorted constants exposed for use in info callbacks.
3731 """
3732 def test_integers(self):
3733 """
3734 All of the info constants are integers.
3735
3736 This is a very weak test. It would be nice to have one that actually
3737 verifies that as certain info events happen, the value passed to the
3738 info callback matches up with the constant exposed by OpenSSL.SSL.
3739 """
3740 for const in [
Alex Gaynor5af32d02016-09-24 01:52:21 -04003741 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK,
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003742 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
3743 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
3744 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
Hynek Schlawack35618382015-09-05 21:54:25 +02003745 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE
3746 ]:
Alex Gaynor5af32d02016-09-24 01:52:21 -04003747 assert isinstance(const, int)
3748
3749 # These constants don't exist on OpenSSL 1.1.0
3750 for const in [
3751 SSL_ST_INIT, SSL_ST_BEFORE, SSL_ST_OK, SSL_ST_RENEGOTIATE
3752 ]:
3753 assert const is None or isinstance(const, int)
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003754
Ziga Seilnacht44611bf2009-08-31 20:49:30 +02003755
Cory Benfield1d142142016-03-30 11:51:45 +01003756class TestRequires(object):
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003757 """
3758 Tests for the decorator factory used to conditionally raise
Cory Benfield1d142142016-03-30 11:51:45 +01003759 NotImplementedError when older OpenSSLs are used.
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003760 """
3761 def test_available(self):
3762 """
3763 When the OpenSSL functionality is available the decorated functions
3764 work appropriately.
3765 """
3766 feature_guard = _make_requires(True, "Error text")
3767 results = []
3768
3769 @feature_guard
3770 def inner():
3771 results.append(True)
3772 return True
3773
Cory Benfield2333e5e2016-03-30 14:24:16 +01003774 assert inner() is True
3775 assert [True] == results
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003776
3777 def test_unavailable(self):
3778 """
3779 When the OpenSSL functionality is not available the decorated function
3780 does not execute and NotImplementedError is raised.
3781 """
3782 feature_guard = _make_requires(False, "Error text")
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003783
3784 @feature_guard
Alex Chanfb078d82017-04-20 11:16:15 +01003785 def inner(): # pragma: nocover
3786 pytest.fail("Should not be called")
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003787
Cory Benfield1d142142016-03-30 11:51:45 +01003788 with pytest.raises(NotImplementedError) as e:
3789 inner()
3790
3791 assert "Error text" in str(e.value)
Cory Benfield496652a2017-01-24 11:42:56 +00003792
3793
Alex Chanb7480992017-01-30 14:04:47 +00003794class TestOCSP(object):
Cory Benfield496652a2017-01-24 11:42:56 +00003795 """
3796 Tests for PyOpenSSL's OCSP stapling support.
3797 """
3798 sample_ocsp_data = b"this is totally ocsp data"
3799
3800 def _client_connection(self, callback, data, request_ocsp=True):
3801 """
3802 Builds a client connection suitable for using OCSP.
3803
3804 :param callback: The callback to register for OCSP.
3805 :param data: The opaque data object that will be handed to the
3806 OCSP callback.
3807 :param request_ocsp: Whether the client will actually ask for OCSP
3808 stapling. Useful for testing only.
3809 """
3810 ctx = Context(SSLv23_METHOD)
3811 ctx.set_ocsp_client_callback(callback, data)
3812 client = Connection(ctx)
3813
3814 if request_ocsp:
3815 client.request_ocsp()
3816
3817 client.set_connect_state()
3818 return client
3819
3820 def _server_connection(self, callback, data):
3821 """
3822 Builds a server connection suitable for using OCSP.
3823
3824 :param callback: The callback to register for OCSP.
3825 :param data: The opaque data object that will be handed to the
3826 OCSP callback.
3827 """
3828 ctx = Context(SSLv23_METHOD)
3829 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
3830 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
3831 ctx.set_ocsp_server_callback(callback, data)
3832 server = Connection(ctx)
3833 server.set_accept_state()
3834 return server
3835
3836 def test_callbacks_arent_called_by_default(self):
3837 """
3838 If both the client and the server have registered OCSP callbacks, but
3839 the client does not send the OCSP request, neither callback gets
3840 called.
3841 """
Alex Chanfb078d82017-04-20 11:16:15 +01003842 def ocsp_callback(*args, **kwargs): # pragma: nocover
3843 pytest.fail("Should not be called")
Cory Benfield496652a2017-01-24 11:42:56 +00003844
3845 client = self._client_connection(
3846 callback=ocsp_callback, data=None, request_ocsp=False
3847 )
3848 server = self._server_connection(callback=ocsp_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00003849 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003850
Cory Benfield496652a2017-01-24 11:42:56 +00003851 def test_client_negotiates_without_server(self):
3852 """
3853 If the client wants to do OCSP but the server does not, the handshake
3854 succeeds, and the client callback fires with an empty byte string.
3855 """
3856 called = []
3857
3858 def ocsp_callback(conn, ocsp_data, ignored):
3859 called.append(ocsp_data)
3860 return True
3861
3862 client = self._client_connection(callback=ocsp_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00003863 server = loopback_server_factory(socket=None)
3864 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003865
3866 assert len(called) == 1
3867 assert called[0] == b''
3868
3869 def test_client_receives_servers_data(self):
3870 """
3871 The data the server sends in its callback is received by the client.
3872 """
3873 calls = []
3874
3875 def server_callback(*args, **kwargs):
3876 return self.sample_ocsp_data
3877
3878 def client_callback(conn, ocsp_data, ignored):
3879 calls.append(ocsp_data)
3880 return True
3881
3882 client = self._client_connection(callback=client_callback, data=None)
3883 server = self._server_connection(callback=server_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00003884 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003885
3886 assert len(calls) == 1
3887 assert calls[0] == self.sample_ocsp_data
3888
3889 def test_callbacks_are_invoked_with_connections(self):
3890 """
3891 The first arguments to both callbacks are their respective connections.
3892 """
3893 client_calls = []
3894 server_calls = []
3895
3896 def client_callback(conn, *args, **kwargs):
3897 client_calls.append(conn)
3898 return True
3899
3900 def server_callback(conn, *args, **kwargs):
3901 server_calls.append(conn)
3902 return self.sample_ocsp_data
3903
3904 client = self._client_connection(callback=client_callback, data=None)
3905 server = self._server_connection(callback=server_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00003906 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003907
3908 assert len(client_calls) == 1
3909 assert len(server_calls) == 1
3910 assert client_calls[0] is client
3911 assert server_calls[0] is server
3912
3913 def test_opaque_data_is_passed_through(self):
3914 """
3915 Both callbacks receive an opaque, user-provided piece of data in their
3916 callbacks as the final argument.
3917 """
3918 calls = []
3919
3920 def server_callback(*args):
3921 calls.append(args)
3922 return self.sample_ocsp_data
3923
3924 def client_callback(*args):
3925 calls.append(args)
3926 return True
3927
3928 sentinel = object()
3929
3930 client = self._client_connection(
3931 callback=client_callback, data=sentinel
3932 )
3933 server = self._server_connection(
3934 callback=server_callback, data=sentinel
3935 )
Alex Chanb7480992017-01-30 14:04:47 +00003936 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003937
3938 assert len(calls) == 2
3939 assert calls[0][-1] is sentinel
3940 assert calls[1][-1] is sentinel
3941
3942 def test_server_returns_empty_string(self):
3943 """
3944 If the server returns an empty bytestring from its callback, the
3945 client callback is called with the empty bytestring.
3946 """
3947 client_calls = []
3948
3949 def server_callback(*args):
3950 return b''
3951
3952 def client_callback(conn, ocsp_data, ignored):
3953 client_calls.append(ocsp_data)
3954 return True
3955
3956 client = self._client_connection(callback=client_callback, data=None)
3957 server = self._server_connection(callback=server_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00003958 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003959
3960 assert len(client_calls) == 1
3961 assert client_calls[0] == b''
3962
3963 def test_client_returns_false_terminates_handshake(self):
3964 """
3965 If the client returns False from its callback, the handshake fails.
3966 """
3967 def server_callback(*args):
3968 return self.sample_ocsp_data
3969
3970 def client_callback(*args):
3971 return False
3972
3973 client = self._client_connection(callback=client_callback, data=None)
3974 server = self._server_connection(callback=server_callback, data=None)
3975
3976 with pytest.raises(Error):
Alex Chanb7480992017-01-30 14:04:47 +00003977 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003978
3979 def test_exceptions_in_client_bubble_up(self):
3980 """
3981 The callbacks thrown in the client callback bubble up to the caller.
3982 """
3983 class SentinelException(Exception):
3984 pass
3985
3986 def server_callback(*args):
3987 return self.sample_ocsp_data
3988
3989 def client_callback(*args):
3990 raise SentinelException()
3991
3992 client = self._client_connection(callback=client_callback, data=None)
3993 server = self._server_connection(callback=server_callback, data=None)
3994
3995 with pytest.raises(SentinelException):
Alex Chanb7480992017-01-30 14:04:47 +00003996 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003997
3998 def test_exceptions_in_server_bubble_up(self):
3999 """
4000 The callbacks thrown in the server callback bubble up to the caller.
4001 """
4002 class SentinelException(Exception):
4003 pass
4004
4005 def server_callback(*args):
4006 raise SentinelException()
4007
Alex Chanfb078d82017-04-20 11:16:15 +01004008 def client_callback(*args): # pragma: nocover
Cory Benfield496652a2017-01-24 11:42:56 +00004009 pytest.fail("Should not be called")
4010
4011 client = self._client_connection(callback=client_callback, data=None)
4012 server = self._server_connection(callback=server_callback, data=None)
4013
4014 with pytest.raises(SentinelException):
Alex Chanb7480992017-01-30 14:04:47 +00004015 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00004016
4017 def test_server_must_return_bytes(self):
4018 """
4019 The server callback must return a bytestring, or a TypeError is thrown.
4020 """
4021 def server_callback(*args):
4022 return self.sample_ocsp_data.decode('ascii')
4023
Alex Chanfb078d82017-04-20 11:16:15 +01004024 def client_callback(*args): # pragma: nocover
Cory Benfield496652a2017-01-24 11:42:56 +00004025 pytest.fail("Should not be called")
4026
4027 client = self._client_connection(callback=client_callback, data=None)
4028 server = self._server_connection(callback=server_callback, data=None)
4029
4030 with pytest.raises(TypeError):
Alex Chanb7480992017-01-30 14:04:47 +00004031 handshake_in_memory(client, server)