blob: 362da5c1e7a7018b03f1a796f29f83aad7719cdc [file] [log] [blame]
Jean-Paul Calderone8671c852011-03-02 19:26:20 -05001# Copyright (C) Jean-Paul Calderone
2# See LICENSE for details.
Jean-Paul Calderone8b63d452008-03-21 18:31:12 -04003
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -04004"""
Hynek Schlawackf90e3682016-03-11 11:21:13 +01005Unit tests for :mod:`OpenSSL.SSL`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -04006"""
7
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01008import datetime
Maximilian Hils868dc3c2017-02-10 14:56:55 +01009import sys
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +010010import uuid
11
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -050012from gc import collect, get_referrers
David Benjamin1fbe0642019-04-15 17:05:13 -050013from errno import (
14 EAFNOSUPPORT, ECONNREFUSED, EINPROGRESS, EWOULDBLOCK, EPIPE, ESHUTDOWN)
Jeremy Lainé1ae7cb62018-03-21 14:49:42 +010015from sys import platform, getfilesystemencoding
David Benjamin1fbe0642019-04-15 17:05:13 -050016from socket import AF_INET, AF_INET6, MSG_PEEK, SHUT_RDWR, error, socket
Jean-Paul Calderonea65cf6c2009-07-19 10:26:52 -040017from os import makedirs
Jean-Paul Calderone1461c492013-10-03 16:05:00 -040018from os.path import join
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -040019from weakref import ref
Alex Chanb7480992017-01-30 14:04:47 +000020from warnings import simplefilter
Jean-Paul Calderone460cc1f2009-03-07 11:31:12 -050021
Hynek Schlawack734d3022015-09-05 19:19:32 +020022import pytest
23
Paul Kehrer55fb3412017-06-29 18:44:08 -050024from pretend import raiser
25
Hynek Schlawackf90e3682016-03-11 11:21:13 +010026from six import PY3, text_type
Jean-Paul Calderonec76c61c2014-01-18 13:21:52 -050027
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +010028from cryptography import x509
29from cryptography.hazmat.backends import default_backend
30from cryptography.hazmat.primitives import hashes
31from cryptography.hazmat.primitives import serialization
32from cryptography.hazmat.primitives.asymmetric import rsa
33from cryptography.x509.oid import NameOID
34
35
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040036from OpenSSL.crypto import TYPE_RSA, FILETYPE_PEM
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -080037from OpenSSL.crypto import PKey, X509, X509Extension, X509Store
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040038from OpenSSL.crypto import dump_privatekey, load_privatekey
39from OpenSSL.crypto import dump_certificate, load_certificate
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -040040from OpenSSL.crypto import get_elliptic_curves
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040041
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -040042from OpenSSL.SSL import OPENSSL_VERSION_NUMBER, SSLEAY_VERSION, SSLEAY_CFLAGS
43from OpenSSL.SSL import SSLEAY_PLATFORM, SSLEAY_DIR, SSLEAY_BUILT_ON
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -040044from OpenSSL.SSL import SENT_SHUTDOWN, RECEIVED_SHUTDOWN
Jean-Paul Calderone1461c492013-10-03 16:05:00 -040045from OpenSSL.SSL import (
46 SSLv2_METHOD, SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD,
47 TLSv1_1_METHOD, TLSv1_2_METHOD)
48from OpenSSL.SSL import OP_SINGLE_DH_USE, OP_NO_SSLv2, OP_NO_SSLv3
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040049from OpenSSL.SSL import (
50 VERIFY_PEER, VERIFY_FAIL_IF_NO_PEER_CERT, VERIFY_CLIENT_ONCE, VERIFY_NONE)
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040051
Paul Kehrer55fb3412017-06-29 18:44:08 -050052from OpenSSL import SSL
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040053from OpenSSL.SSL import (
Jean-Paul Calderone313bf012012-02-08 13:02:49 -050054 SESS_CACHE_OFF, SESS_CACHE_CLIENT, SESS_CACHE_SERVER, SESS_CACHE_BOTH,
55 SESS_CACHE_NO_AUTO_CLEAR, SESS_CACHE_NO_INTERNAL_LOOKUP,
56 SESS_CACHE_NO_INTERNAL_STORE, SESS_CACHE_NO_INTERNAL)
57
58from OpenSSL.SSL import (
Jean-Paul Calderoned899af02013-03-19 22:10:37 -070059 Error, SysCallError, WantReadError, WantWriteError, ZeroReturnError)
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -050060from OpenSSL.SSL import (
Alex Gaynor01f90a12019-02-07 09:14:48 -050061 Context, Session, Connection, SSLeay_version)
Cory Benfield0ba57ec2016-03-30 09:35:05 +010062from OpenSSL.SSL import _make_requires
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040063
Paul Kehrer55fb3412017-06-29 18:44:08 -050064from OpenSSL._util import ffi as _ffi, lib as _lib
Cory Benfieldba1820d2015-04-13 17:39:12 -040065
Alex Gaynord3b5d9b2016-07-31 10:54:24 -040066from OpenSSL.SSL import (
67 OP_NO_QUERY_MTU, OP_COOKIE_EXCHANGE, OP_NO_TICKET, OP_NO_COMPRESSION,
68 MODE_RELEASE_BUFFERS)
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040069
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -040070from OpenSSL.SSL import (
Alex Gaynor5af32d02016-09-24 01:52:21 -040071 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK,
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -040072 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
73 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
74 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
75 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE)
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -040076
Alex Gaynor5af32d02016-09-24 01:52:21 -040077try:
78 from OpenSSL.SSL import (
79 SSL_ST_INIT, SSL_ST_BEFORE, SSL_ST_OK, SSL_ST_RENEGOTIATE
80 )
81except ImportError:
82 SSL_ST_INIT = SSL_ST_BEFORE = SSL_ST_OK = SSL_ST_RENEGOTIATE = None
83
Alex Chanb7480992017-01-30 14:04:47 +000084from .util import WARNING_TYPE_EXPECTED, NON_ASCII, is_consistent_type
Hynek Schlawackf0e66852015-10-16 20:18:38 +020085from .test_crypto import (
86 cleartextCertificatePEM, cleartextPrivateKeyPEM,
87 client_cert_pem, client_key_pem, server_cert_pem, server_key_pem,
88 root_cert_pem)
89
Hynek Schlawackde00dd52015-09-05 19:09:26 +020090
Alex Gaynord0bdd2d2016-09-10 14:23:46 -040091# openssl dhparam 1024 -out dh-1024.pem (note that 1024 is a small number of
92# bits to use)
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -040093dhparam = """\
94-----BEGIN DH PARAMETERS-----
Alex Gaynord0bdd2d2016-09-10 14:23:46 -040095MIGHAoGBALdUMvn+C9MM+y5BWZs11mSeH6HHoEq0UVbzVq7UojC1hbsZUuGukQ3a
96Qh2/pwqb18BZFykrWB0zv/OkLa0kx4cuUgNrUVq1EFheBiX6YqryJ7t2sO09NQiO
97V7H54LmltOT/hEh6QWsJqb6BQgH65bswvV/XkYGja8/T0GzvbaVzAgEC
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -040098-----END DH PARAMETERS-----
99"""
100
101
Hynek Schlawackb4f02402015-09-05 20:48:34 +0200102skip_if_py3 = pytest.mark.skipif(PY3, reason="Python 2 only")
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200103
104
David Benjamin1fbe0642019-04-15 17:05:13 -0500105def socket_any_family():
106 try:
107 return socket(AF_INET)
108 except error as e:
109 if e.errno == EAFNOSUPPORT:
110 return socket(AF_INET6)
111 raise
112
113
114def loopback_address(socket):
115 if socket.family == AF_INET:
116 return "127.0.0.1"
117 else:
118 assert socket.family == AF_INET6
119 return "::1"
120
121
Jean-Paul Calderone05826732015-04-12 11:38:49 -0400122def join_bytes_or_unicode(prefix, suffix):
123 """
124 Join two path components of either ``bytes`` or ``unicode``.
125
126 The return type is the same as the type of ``prefix``.
127 """
128 # If the types are the same, nothing special is necessary.
129 if type(prefix) == type(suffix):
130 return join(prefix, suffix)
131
132 # Otherwise, coerce suffix to the type of prefix.
133 if isinstance(prefix, text_type):
134 return join(prefix, suffix.decode(getfilesystemencoding()))
135 else:
136 return join(prefix, suffix.encode(getfilesystemencoding()))
137
138
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400139def verify_cb(conn, cert, errnum, depth, ok):
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400140 return ok
141
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400142
Rick Deanb1ccd562009-07-09 23:52:39 -0500143def socket_pair():
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400144 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400145 Establish and return a pair of network sockets connected to each other.
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400146 """
147 # Connect a pair of sockets
David Benjamin1fbe0642019-04-15 17:05:13 -0500148 port = socket_any_family()
Rick Deanb1ccd562009-07-09 23:52:39 -0500149 port.bind(('', 0))
150 port.listen(1)
David Benjamin1fbe0642019-04-15 17:05:13 -0500151 client = socket(port.family)
Rick Deanb1ccd562009-07-09 23:52:39 -0500152 client.setblocking(False)
David Benjamin1fbe0642019-04-15 17:05:13 -0500153 client.connect_ex((loopback_address(port), port.getsockname()[1]))
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400154 client.setblocking(True)
Rick Deanb1ccd562009-07-09 23:52:39 -0500155 server = port.accept()[0]
Rick Deanb1ccd562009-07-09 23:52:39 -0500156
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400157 # Let's pass some unencrypted data to make sure our socket connection is
158 # fine. Just one byte, so we don't have to worry about buffers getting
159 # filled up or fragmentation.
Alex Gaynore7f51982016-09-11 11:48:14 -0400160 server.send(b"x")
161 assert client.recv(1024) == b"x"
162 client.send(b"y")
163 assert server.recv(1024) == b"y"
Rick Deanb1ccd562009-07-09 23:52:39 -0500164
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -0400165 # Most of our callers want non-blocking sockets, make it easy for them.
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400166 server.setblocking(False)
167 client.setblocking(False)
Jim Shaver46f28912015-05-29 19:32:16 -0400168
Rick Deanb1ccd562009-07-09 23:52:39 -0500169 return (server, client)
170
171
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400172def handshake(client, server):
173 conns = [client, server]
174 while conns:
175 for conn in conns:
176 try:
177 conn.do_handshake()
178 except WantReadError:
179 pass
180 else:
181 conns.remove(conn)
182
183
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400184def _create_certificate_chain():
185 """
186 Construct and return a chain of certificates.
187
188 1. A new self-signed certificate authority certificate (cacert)
189 2. A new intermediate certificate signed by cacert (icert)
190 3. A new server certificate signed by icert (scert)
191 """
Alex Gaynore7f51982016-09-11 11:48:14 -0400192 caext = X509Extension(b'basicConstraints', False, b'CA:true')
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400193
194 # Step 1
195 cakey = PKey()
Alex Gaynor0737a5e2016-09-10 14:35:09 -0400196 cakey.generate_key(TYPE_RSA, 1024)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400197 cacert = X509()
198 cacert.get_subject().commonName = "Authority Certificate"
199 cacert.set_issuer(cacert.get_subject())
200 cacert.set_pubkey(cakey)
Alex Gaynore7f51982016-09-11 11:48:14 -0400201 cacert.set_notBefore(b"20000101000000Z")
202 cacert.set_notAfter(b"20200101000000Z")
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400203 cacert.add_extensions([caext])
204 cacert.set_serial_number(0)
205 cacert.sign(cakey, "sha1")
206
207 # Step 2
208 ikey = PKey()
Alex Gaynor0737a5e2016-09-10 14:35:09 -0400209 ikey.generate_key(TYPE_RSA, 1024)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400210 icert = X509()
211 icert.get_subject().commonName = "Intermediate Certificate"
212 icert.set_issuer(cacert.get_subject())
213 icert.set_pubkey(ikey)
Alex Gaynore7f51982016-09-11 11:48:14 -0400214 icert.set_notBefore(b"20000101000000Z")
215 icert.set_notAfter(b"20200101000000Z")
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400216 icert.add_extensions([caext])
217 icert.set_serial_number(0)
218 icert.sign(cakey, "sha1")
219
220 # Step 3
221 skey = PKey()
Alex Gaynor0737a5e2016-09-10 14:35:09 -0400222 skey.generate_key(TYPE_RSA, 1024)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400223 scert = X509()
224 scert.get_subject().commonName = "Server Certificate"
225 scert.set_issuer(icert.get_subject())
226 scert.set_pubkey(skey)
Alex Gaynore7f51982016-09-11 11:48:14 -0400227 scert.set_notBefore(b"20000101000000Z")
228 scert.set_notAfter(b"20200101000000Z")
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400229 scert.add_extensions([
Alex Gaynore7f51982016-09-11 11:48:14 -0400230 X509Extension(b'basicConstraints', True, b'CA:false')])
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400231 scert.set_serial_number(0)
232 scert.sign(ikey, "sha1")
233
234 return [(cakey, cacert), (ikey, icert), (skey, scert)]
235
236
Paul Kehrer7d5a3bf2019-01-21 12:24:02 -0600237def loopback_client_factory(socket, version=SSLv23_METHOD):
238 client = Connection(Context(version), socket)
Alex Chan1c0cb662017-01-30 07:13:30 +0000239 client.set_connect_state()
240 return client
241
242
Paul Kehrer7d5a3bf2019-01-21 12:24:02 -0600243def loopback_server_factory(socket, version=SSLv23_METHOD):
244 ctx = Context(version)
Alex Chan1c0cb662017-01-30 07:13:30 +0000245 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
246 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
247 server = Connection(ctx, socket)
248 server.set_accept_state()
249 return server
250
251
252def loopback(server_factory=None, client_factory=None):
253 """
254 Create a connected socket pair and force two connected SSL sockets
255 to talk to each other via memory BIOs.
256 """
257 if server_factory is None:
258 server_factory = loopback_server_factory
259 if client_factory is None:
260 client_factory = loopback_client_factory
261
262 (server, client) = socket_pair()
263 server = server_factory(server)
264 client = client_factory(client)
265
266 handshake(client, server)
267
268 server.setblocking(True)
269 client.setblocking(True)
270 return server, client
271
272
Alex Chan1ca9e3a2016-11-05 13:01:51 +0000273def interact_in_memory(client_conn, server_conn):
274 """
275 Try to read application bytes from each of the two `Connection` objects.
276 Copy bytes back and forth between their send/receive buffers for as long
277 as there is anything to copy. When there is nothing more to copy,
278 return `None`. If one of them actually manages to deliver some application
279 bytes, return a two-tuple of the connection from which the bytes were read
280 and the bytes themselves.
281 """
282 wrote = True
283 while wrote:
284 # Loop until neither side has anything to say
285 wrote = False
286
287 # Copy stuff from each side's send buffer to the other side's
288 # receive buffer.
289 for (read, write) in [(client_conn, server_conn),
290 (server_conn, client_conn)]:
291
292 # Give the side a chance to generate some more bytes, or succeed.
293 try:
294 data = read.recv(2 ** 16)
295 except WantReadError:
296 # It didn't succeed, so we'll hope it generated some output.
297 pass
298 else:
299 # It did succeed, so we'll stop now and let the caller deal
300 # with it.
301 return (read, data)
302
303 while True:
304 # Keep copying as long as there's more stuff there.
305 try:
306 dirty = read.bio_read(4096)
307 except WantReadError:
308 # Okay, nothing more waiting to be sent. Stop
309 # processing this send buffer.
310 break
311 else:
312 # Keep track of the fact that someone generated some
313 # output.
314 wrote = True
315 write.bio_write(dirty)
316
317
Alex Chan532b79e2017-01-24 15:14:52 +0000318def handshake_in_memory(client_conn, server_conn):
319 """
320 Perform the TLS handshake between two `Connection` instances connected to
321 each other via memory BIOs.
322 """
323 client_conn.set_connect_state()
324 server_conn.set_accept_state()
325
326 for conn in [client_conn, server_conn]:
327 try:
328 conn.do_handshake()
329 except WantReadError:
330 pass
331
332 interact_in_memory(client_conn, server_conn)
333
334
Alex Chanb7480992017-01-30 14:04:47 +0000335class TestVersion(object):
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400336 """
Alex Chanb7480992017-01-30 14:04:47 +0000337 Tests for version information exposed by `OpenSSL.SSL.SSLeay_version` and
338 `OpenSSL.SSL.OPENSSL_VERSION_NUMBER`.
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400339 """
340 def test_OPENSSL_VERSION_NUMBER(self):
341 """
Alex Chanb7480992017-01-30 14:04:47 +0000342 `OPENSSL_VERSION_NUMBER` is an integer with status in the low byte and
343 the patch, fix, minor, and major versions in the nibbles above that.
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400344 """
Alex Chanb7480992017-01-30 14:04:47 +0000345 assert isinstance(OPENSSL_VERSION_NUMBER, int)
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400346
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400347 def test_SSLeay_version(self):
348 """
Alex Chanb7480992017-01-30 14:04:47 +0000349 `SSLeay_version` takes a version type indicator and returns one of a
350 number of version strings based on that indicator.
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400351 """
352 versions = {}
353 for t in [SSLEAY_VERSION, SSLEAY_CFLAGS, SSLEAY_BUILT_ON,
354 SSLEAY_PLATFORM, SSLEAY_DIR]:
355 version = SSLeay_version(t)
356 versions[version] = t
Alex Chanb7480992017-01-30 14:04:47 +0000357 assert isinstance(version, bytes)
358 assert len(versions) == 5
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400359
360
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100361@pytest.fixture
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100362def ca_file(tmpdir):
363 """
364 Create a valid PEM file with CA certificates and return the path.
365 """
366 key = rsa.generate_private_key(
367 public_exponent=65537,
368 key_size=2048,
369 backend=default_backend()
370 )
371 public_key = key.public_key()
372
373 builder = x509.CertificateBuilder()
374 builder = builder.subject_name(x509.Name([
375 x509.NameAttribute(NameOID.COMMON_NAME, u"pyopenssl.org"),
376 ]))
377 builder = builder.issuer_name(x509.Name([
378 x509.NameAttribute(NameOID.COMMON_NAME, u"pyopenssl.org"),
379 ]))
380 one_day = datetime.timedelta(1, 0, 0)
381 builder = builder.not_valid_before(datetime.datetime.today() - one_day)
382 builder = builder.not_valid_after(datetime.datetime.today() + one_day)
383 builder = builder.serial_number(int(uuid.uuid4()))
384 builder = builder.public_key(public_key)
385 builder = builder.add_extension(
386 x509.BasicConstraints(ca=True, path_length=None), critical=True,
387 )
388
389 certificate = builder.sign(
390 private_key=key, algorithm=hashes.SHA256(),
391 backend=default_backend()
392 )
393
394 ca_file = tmpdir.join("test.pem")
395 ca_file.write_binary(
396 certificate.public_bytes(
397 encoding=serialization.Encoding.PEM,
398 )
399 )
400
401 return str(ca_file).encode("ascii")
402
403
404@pytest.fixture
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100405def context():
406 """
407 A simple TLS 1.0 context.
408 """
409 return Context(TLSv1_METHOD)
410
411
412class TestContext(object):
Hynek Schlawackaa861212016-03-13 13:53:48 +0100413 """
Alex Chan532b79e2017-01-24 15:14:52 +0000414 Unit tests for `OpenSSL.SSL.Context`.
Hynek Schlawackaa861212016-03-13 13:53:48 +0100415 """
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100416 @pytest.mark.parametrize("cipher_string", [
417 b"hello world:AES128-SHA",
418 u"hello world:AES128-SHA",
419 ])
420 def test_set_cipher_list(self, context, cipher_string):
421 """
Alex Chan532b79e2017-01-24 15:14:52 +0000422 `Context.set_cipher_list` accepts both byte and unicode strings
Hynek Schlawacka7a63af2016-03-11 12:05:26 +0100423 for naming the ciphers which connections created with the context
424 object will be able to choose from.
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100425 """
426 context.set_cipher_list(cipher_string)
427 conn = Connection(context, None)
428
429 assert "AES128-SHA" in conn.get_cipher_list()
430
Mark Williamsdf2480d2019-02-14 19:30:07 -0800431 def test_set_cipher_list_wrong_type(self, context):
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100432 """
Alex Chan532b79e2017-01-24 15:14:52 +0000433 `Context.set_cipher_list` raises `TypeError` when passed a non-string
Mark Williamsdf2480d2019-02-14 19:30:07 -0800434 argument.
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100435 """
Mark Williamsdf2480d2019-02-14 19:30:07 -0800436 with pytest.raises(TypeError):
437 context.set_cipher_list(object())
438
439 def test_set_cipher_list_no_cipher_match(self, context):
440 """
441 `Context.set_cipher_list` raises `OpenSSL.SSL.Error` with a
442 `"no cipher match"` reason string regardless of the TLS
443 version.
444 """
445 with pytest.raises(Error) as excinfo:
446 context.set_cipher_list(b"imaginary-cipher")
447 assert excinfo.value.args == (
448 [
449 (
450 'SSL routines',
451 'SSL_CTX_set_cipher_list',
452 'no cipher match',
453 ),
454 ],
455 )
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100456
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100457 def test_load_client_ca(self, context, ca_file):
458 """
Alex Chan532b79e2017-01-24 15:14:52 +0000459 `Context.load_client_ca` works as far as we can tell.
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100460 """
461 context.load_client_ca(ca_file)
462
463 def test_load_client_ca_invalid(self, context, tmpdir):
464 """
Alex Chan532b79e2017-01-24 15:14:52 +0000465 `Context.load_client_ca` raises an Error if the ca file is invalid.
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100466 """
467 ca_file = tmpdir.join("test.pem")
468 ca_file.write("")
469
470 with pytest.raises(Error) as e:
471 context.load_client_ca(str(ca_file).encode("ascii"))
472
473 assert "PEM routines" == e.value.args[0][0][0]
474
475 def test_load_client_ca_unicode(self, context, ca_file):
476 """
477 Passing the path as unicode raises a warning but works.
478 """
479 pytest.deprecated_call(
480 context.load_client_ca, ca_file.decode("ascii")
481 )
482
483 def test_set_session_id(self, context):
484 """
Alex Chan532b79e2017-01-24 15:14:52 +0000485 `Context.set_session_id` works as far as we can tell.
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100486 """
487 context.set_session_id(b"abc")
488
489 def test_set_session_id_fail(self, context):
490 """
Alex Chan532b79e2017-01-24 15:14:52 +0000491 `Context.set_session_id` errors are propagated.
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100492 """
493 with pytest.raises(Error) as e:
494 context.set_session_id(b"abc" * 1000)
495
496 assert [
497 ("SSL routines",
498 "SSL_CTX_set_session_id_context",
499 "ssl session id context too long")
500 ] == e.value.args[0]
501
502 def test_set_session_id_unicode(self, context):
503 """
Alex Chan532b79e2017-01-24 15:14:52 +0000504 `Context.set_session_id` raises a warning if a unicode string is
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100505 passed.
506 """
507 pytest.deprecated_call(context.set_session_id, u"abc")
508
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400509 def test_method(self):
510 """
Alex Chan532b79e2017-01-24 15:14:52 +0000511 `Context` can be instantiated with one of `SSLv2_METHOD`,
512 `SSLv3_METHOD`, `SSLv23_METHOD`, `TLSv1_METHOD`, `TLSv1_1_METHOD`,
513 or `TLSv1_2_METHOD`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400514 """
Alex Gaynor5af32d02016-09-24 01:52:21 -0400515 methods = [SSLv23_METHOD, TLSv1_METHOD]
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400516 for meth in methods:
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400517 Context(meth)
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400518
Alex Gaynor5af32d02016-09-24 01:52:21 -0400519 maybe = [SSLv2_METHOD, SSLv3_METHOD, TLSv1_1_METHOD, TLSv1_2_METHOD]
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400520 for meth in maybe:
521 try:
522 Context(meth)
523 except (Error, ValueError):
524 # Some versions of OpenSSL have SSLv2 / TLSv1.1 / TLSv1.2, some
525 # don't. Difficult to say in advance.
526 pass
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400527
Alex Chan532b79e2017-01-24 15:14:52 +0000528 with pytest.raises(TypeError):
529 Context("")
530 with pytest.raises(ValueError):
531 Context(10)
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400532
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200533 @skip_if_py3
534 def test_method_long(self):
535 """
Alex Chan532b79e2017-01-24 15:14:52 +0000536 On Python 2 `Context` accepts values of type `long` as well as `int`.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200537 """
538 Context(long(TLSv1_METHOD))
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500539
Rick Deane15b1472009-07-09 15:53:42 -0500540 def test_type(self):
541 """
Alex Gaynor01f90a12019-02-07 09:14:48 -0500542 `Context` can be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -0500543 """
Alex Chan532b79e2017-01-24 15:14:52 +0000544 assert is_consistent_type(Context, 'Context', TLSv1_METHOD)
Rick Deane15b1472009-07-09 15:53:42 -0500545
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400546 def test_use_privatekey(self):
547 """
Alex Chan532b79e2017-01-24 15:14:52 +0000548 `Context.use_privatekey` takes an `OpenSSL.crypto.PKey` instance.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400549 """
550 key = PKey()
Alex Gaynor6e9f9762018-05-12 07:44:37 -0400551 key.generate_key(TYPE_RSA, 512)
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400552 ctx = Context(TLSv1_METHOD)
553 ctx.use_privatekey(key)
Alex Chan532b79e2017-01-24 15:14:52 +0000554 with pytest.raises(TypeError):
555 ctx.use_privatekey("")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400556
Alex Chan532b79e2017-01-24 15:14:52 +0000557 def test_use_privatekey_file_missing(self, tmpfile):
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800558 """
Alex Chan532b79e2017-01-24 15:14:52 +0000559 `Context.use_privatekey_file` raises `OpenSSL.SSL.Error` when passed
560 the name of a file which does not exist.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800561 """
562 ctx = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000563 with pytest.raises(Error):
564 ctx.use_privatekey_file(tmpfile)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800565
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400566 def _use_privatekey_file_test(self, pemfile, filetype):
567 """
568 Verify that calling ``Context.use_privatekey_file`` with the given
569 arguments does not raise an exception.
570 """
571 key = PKey()
Alex Gaynor6e9f9762018-05-12 07:44:37 -0400572 key.generate_key(TYPE_RSA, 512)
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400573
574 with open(pemfile, "wt") as pem:
575 pem.write(
576 dump_privatekey(FILETYPE_PEM, key).decode("ascii")
577 )
578
579 ctx = Context(TLSv1_METHOD)
580 ctx.use_privatekey_file(pemfile, filetype)
581
Alex Chanfb078d82017-04-20 11:16:15 +0100582 @pytest.mark.parametrize('filetype', [object(), "", None, 1.0])
583 def test_wrong_privatekey_file_wrong_args(self, tmpfile, filetype):
584 """
585 `Context.use_privatekey_file` raises `TypeError` when called with
586 a `filetype` which is not a valid file encoding.
587 """
588 ctx = Context(TLSv1_METHOD)
589 with pytest.raises(TypeError):
590 ctx.use_privatekey_file(tmpfile, filetype)
591
Alex Chan532b79e2017-01-24 15:14:52 +0000592 def test_use_privatekey_file_bytes(self, tmpfile):
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400593 """
594 A private key can be specified from a file by passing a ``bytes``
595 instance giving the file name to ``Context.use_privatekey_file``.
596 """
597 self._use_privatekey_file_test(
Alex Chan532b79e2017-01-24 15:14:52 +0000598 tmpfile + NON_ASCII.encode(getfilesystemencoding()),
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400599 FILETYPE_PEM,
600 )
601
Alex Chan532b79e2017-01-24 15:14:52 +0000602 def test_use_privatekey_file_unicode(self, tmpfile):
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400603 """
604 A private key can be specified from a file by passing a ``unicode``
605 instance giving the file name to ``Context.use_privatekey_file``.
606 """
607 self._use_privatekey_file_test(
Alex Chan532b79e2017-01-24 15:14:52 +0000608 tmpfile.decode(getfilesystemencoding()) + NON_ASCII,
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400609 FILETYPE_PEM,
610 )
611
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200612 @skip_if_py3
Alex Chan532b79e2017-01-24 15:14:52 +0000613 def test_use_privatekey_file_long(self, tmpfile):
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200614 """
Alex Chan532b79e2017-01-24 15:14:52 +0000615 On Python 2 `Context.use_privatekey_file` accepts a filetype of
616 type `long` as well as `int`.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200617 """
Alex Chan532b79e2017-01-24 15:14:52 +0000618 self._use_privatekey_file_test(tmpfile, long(FILETYPE_PEM))
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500619
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800620 def test_use_certificate_wrong_args(self):
621 """
Alex Chan532b79e2017-01-24 15:14:52 +0000622 `Context.use_certificate_wrong_args` raises `TypeError` when not passed
623 exactly one `OpenSSL.crypto.X509` instance as an argument.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800624 """
625 ctx = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000626 with pytest.raises(TypeError):
627 ctx.use_certificate("hello, world")
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800628
629 def test_use_certificate_uninitialized(self):
630 """
Alex Chan532b79e2017-01-24 15:14:52 +0000631 `Context.use_certificate` raises `OpenSSL.SSL.Error` when passed a
632 `OpenSSL.crypto.X509` instance which has not been initialized
633 (ie, which does not actually have any certificate data).
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800634 """
635 ctx = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000636 with pytest.raises(Error):
637 ctx.use_certificate(X509())
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800638
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800639 def test_use_certificate(self):
640 """
Alex Chan532b79e2017-01-24 15:14:52 +0000641 `Context.use_certificate` sets the certificate which will be
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800642 used to identify connections created using the context.
643 """
644 # TODO
645 # Hard to assert anything. But we could set a privatekey then ask
646 # OpenSSL if the cert and key agree using check_privatekey. Then as
647 # long as check_privatekey works right we're good...
648 ctx = Context(TLSv1_METHOD)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200649 ctx.use_certificate(
650 load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
651 )
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800652
653 def test_use_certificate_file_wrong_args(self):
654 """
Alex Chan532b79e2017-01-24 15:14:52 +0000655 `Context.use_certificate_file` raises `TypeError` if the first
656 argument is not a byte string or the second argument is not an integer.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800657 """
658 ctx = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000659 with pytest.raises(TypeError):
660 ctx.use_certificate_file(object(), FILETYPE_PEM)
661 with pytest.raises(TypeError):
662 ctx.use_certificate_file(b"somefile", object())
663 with pytest.raises(TypeError):
664 ctx.use_certificate_file(object(), FILETYPE_PEM)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800665
Alex Chan532b79e2017-01-24 15:14:52 +0000666 def test_use_certificate_file_missing(self, tmpfile):
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800667 """
Alex Chan532b79e2017-01-24 15:14:52 +0000668 `Context.use_certificate_file` raises `OpenSSL.SSL.Error` if passed
669 the name of a file which does not exist.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800670 """
671 ctx = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000672 with pytest.raises(Error):
673 ctx.use_certificate_file(tmpfile)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800674
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400675 def _use_certificate_file_test(self, certificate_file):
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800676 """
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400677 Verify that calling ``Context.use_certificate_file`` with the given
678 filename doesn't raise an exception.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800679 """
680 # TODO
681 # Hard to assert anything. But we could set a privatekey then ask
682 # OpenSSL if the cert and key agree using check_privatekey. Then as
683 # long as check_privatekey works right we're good...
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400684 with open(certificate_file, "wb") as pem_file:
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800685 pem_file.write(cleartextCertificatePEM)
686
687 ctx = Context(TLSv1_METHOD)
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400688 ctx.use_certificate_file(certificate_file)
689
Alex Chan532b79e2017-01-24 15:14:52 +0000690 def test_use_certificate_file_bytes(self, tmpfile):
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400691 """
Alex Chan532b79e2017-01-24 15:14:52 +0000692 `Context.use_certificate_file` sets the certificate (given as a
693 `bytes` filename) which will be used to identify connections created
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400694 using the context.
695 """
Alex Chan532b79e2017-01-24 15:14:52 +0000696 filename = tmpfile + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400697 self._use_certificate_file_test(filename)
698
Alex Chan532b79e2017-01-24 15:14:52 +0000699 def test_use_certificate_file_unicode(self, tmpfile):
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400700 """
Alex Chan532b79e2017-01-24 15:14:52 +0000701 `Context.use_certificate_file` sets the certificate (given as a
702 `bytes` filename) which will be used to identify connections created
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400703 using the context.
704 """
Alex Chan532b79e2017-01-24 15:14:52 +0000705 filename = tmpfile.decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400706 self._use_certificate_file_test(filename)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800707
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200708 @skip_if_py3
Alex Chan532b79e2017-01-24 15:14:52 +0000709 def test_use_certificate_file_long(self, tmpfile):
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200710 """
Alex Chan532b79e2017-01-24 15:14:52 +0000711 On Python 2 `Context.use_certificate_file` accepts a
712 filetype of type `long` as well as `int`.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200713 """
Alex Chan532b79e2017-01-24 15:14:52 +0000714 pem_filename = tmpfile
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200715 with open(pem_filename, "wb") as pem_file:
716 pem_file.write(cleartextCertificatePEM)
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500717
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200718 ctx = Context(TLSv1_METHOD)
719 ctx.use_certificate_file(pem_filename, long(FILETYPE_PEM))
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500720
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500721 def test_check_privatekey_valid(self):
722 """
Alex Chan532b79e2017-01-24 15:14:52 +0000723 `Context.check_privatekey` returns `None` if the `Context` instance
724 has been configured to use a matched key and certificate pair.
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500725 """
726 key = load_privatekey(FILETYPE_PEM, client_key_pem)
727 cert = load_certificate(FILETYPE_PEM, client_cert_pem)
728 context = Context(TLSv1_METHOD)
729 context.use_privatekey(key)
730 context.use_certificate(cert)
Alex Chan532b79e2017-01-24 15:14:52 +0000731 assert None is context.check_privatekey()
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500732
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500733 def test_check_privatekey_invalid(self):
734 """
Alex Chan532b79e2017-01-24 15:14:52 +0000735 `Context.check_privatekey` raises `Error` if the `Context` instance
736 has been configured to use a key and certificate pair which don't
737 relate to each other.
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500738 """
739 key = load_privatekey(FILETYPE_PEM, client_key_pem)
740 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
741 context = Context(TLSv1_METHOD)
742 context.use_privatekey(key)
743 context.use_certificate(cert)
Alex Chan532b79e2017-01-24 15:14:52 +0000744 with pytest.raises(Error):
745 context.check_privatekey()
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400746
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400747 def test_app_data(self):
748 """
Alex Chan532b79e2017-01-24 15:14:52 +0000749 `Context.set_app_data` stores an object for later retrieval
750 using `Context.get_app_data`.
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400751 """
752 app_data = object()
753 context = Context(TLSv1_METHOD)
754 context.set_app_data(app_data)
Alex Chan532b79e2017-01-24 15:14:52 +0000755 assert context.get_app_data() is app_data
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400756
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400757 def test_set_options_wrong_args(self):
758 """
Alex Chan532b79e2017-01-24 15:14:52 +0000759 `Context.set_options` raises `TypeError` if called with
760 a non-`int` argument.
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400761 """
762 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000763 with pytest.raises(TypeError):
764 context.set_options(None)
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400765
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500766 def test_set_options(self):
767 """
Alex Chan532b79e2017-01-24 15:14:52 +0000768 `Context.set_options` returns the new options value.
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500769 """
770 context = Context(TLSv1_METHOD)
771 options = context.set_options(OP_NO_SSLv2)
Alex Gaynor2310f8b2016-09-10 14:39:32 -0400772 assert options & OP_NO_SSLv2 == OP_NO_SSLv2
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500773
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200774 @skip_if_py3
775 def test_set_options_long(self):
776 """
Alex Chan532b79e2017-01-24 15:14:52 +0000777 On Python 2 `Context.set_options` accepts values of type
778 `long` as well as `int`.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200779 """
780 context = Context(TLSv1_METHOD)
781 options = context.set_options(long(OP_NO_SSLv2))
Alex Gaynor2310f8b2016-09-10 14:39:32 -0400782 assert options & OP_NO_SSLv2 == OP_NO_SSLv2
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500783
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300784 def test_set_mode_wrong_args(self):
785 """
Alex Chan532b79e2017-01-24 15:14:52 +0000786 `Context.set_mode` raises `TypeError` if called with
787 a non-`int` argument.
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300788 """
789 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000790 with pytest.raises(TypeError):
791 context.set_mode(None)
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300792
Alex Gaynord3b5d9b2016-07-31 10:54:24 -0400793 def test_set_mode(self):
794 """
Alex Chan532b79e2017-01-24 15:14:52 +0000795 `Context.set_mode` accepts a mode bitvector and returns the
Alex Gaynord3b5d9b2016-07-31 10:54:24 -0400796 newly set mode.
797 """
798 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000799 assert MODE_RELEASE_BUFFERS & context.set_mode(MODE_RELEASE_BUFFERS)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500800
Alex Gaynord3b5d9b2016-07-31 10:54:24 -0400801 @skip_if_py3
802 def test_set_mode_long(self):
803 """
Alex Chan532b79e2017-01-24 15:14:52 +0000804 On Python 2 `Context.set_mode` accepts values of type `long` as well
805 as `int`.
Alex Gaynord3b5d9b2016-07-31 10:54:24 -0400806 """
807 context = Context(TLSv1_METHOD)
808 mode = context.set_mode(long(MODE_RELEASE_BUFFERS))
Alex Chan532b79e2017-01-24 15:14:52 +0000809 assert MODE_RELEASE_BUFFERS & mode
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400810
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400811 def test_set_timeout_wrong_args(self):
812 """
Alex Chan532b79e2017-01-24 15:14:52 +0000813 `Context.set_timeout` raises `TypeError` if called with
814 a non-`int` argument.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400815 """
816 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000817 with pytest.raises(TypeError):
818 context.set_timeout(None)
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400819
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400820 def test_timeout(self):
821 """
Alex Chan532b79e2017-01-24 15:14:52 +0000822 `Context.set_timeout` sets the session timeout for all connections
823 created using the context object. `Context.get_timeout` retrieves
824 this value.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400825 """
826 context = Context(TLSv1_METHOD)
827 context.set_timeout(1234)
Alex Chan532b79e2017-01-24 15:14:52 +0000828 assert context.get_timeout() == 1234
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400829
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200830 @skip_if_py3
831 def test_timeout_long(self):
832 """
Alex Chan532b79e2017-01-24 15:14:52 +0000833 On Python 2 `Context.set_timeout` accepts values of type `long` as
834 well as int.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200835 """
836 context = Context(TLSv1_METHOD)
837 context.set_timeout(long(1234))
Alex Chan532b79e2017-01-24 15:14:52 +0000838 assert context.get_timeout() == 1234
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500839
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400840 def test_set_verify_depth_wrong_args(self):
841 """
Alex Chan532b79e2017-01-24 15:14:52 +0000842 `Context.set_verify_depth` raises `TypeError` if called with a
843 non-`int` argument.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400844 """
845 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000846 with pytest.raises(TypeError):
847 context.set_verify_depth(None)
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400848
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400849 def test_verify_depth(self):
850 """
Alex Chan532b79e2017-01-24 15:14:52 +0000851 `Context.set_verify_depth` sets the number of certificates in
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200852 a chain to follow before giving up. The value can be retrieved with
Alex Chan532b79e2017-01-24 15:14:52 +0000853 `Context.get_verify_depth`.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400854 """
855 context = Context(TLSv1_METHOD)
856 context.set_verify_depth(11)
Alex Chan532b79e2017-01-24 15:14:52 +0000857 assert context.get_verify_depth() == 11
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400858
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200859 @skip_if_py3
860 def test_verify_depth_long(self):
861 """
Alex Chan532b79e2017-01-24 15:14:52 +0000862 On Python 2 `Context.set_verify_depth` accepts values of type `long`
863 as well as int.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200864 """
865 context = Context(TLSv1_METHOD)
866 context.set_verify_depth(long(11))
Alex Chan532b79e2017-01-24 15:14:52 +0000867 assert context.get_verify_depth() == 11
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500868
Alex Chan532b79e2017-01-24 15:14:52 +0000869 def _write_encrypted_pem(self, passphrase, tmpfile):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400870 """
871 Write a new private key out to a new file, encrypted using the given
872 passphrase. Return the path to the new file.
873 """
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400874 key = PKey()
Alex Gaynor6e9f9762018-05-12 07:44:37 -0400875 key.generate_key(TYPE_RSA, 512)
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400876 pem = dump_privatekey(FILETYPE_PEM, key, "blowfish", passphrase)
Alex Chan532b79e2017-01-24 15:14:52 +0000877 with open(tmpfile, 'w') as fObj:
878 fObj.write(pem.decode('ascii'))
879 return tmpfile
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400880
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400881 def test_set_passwd_cb_wrong_args(self):
882 """
Alex Chan532b79e2017-01-24 15:14:52 +0000883 `Context.set_passwd_cb` raises `TypeError` if called with a
884 non-callable first argument.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400885 """
886 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000887 with pytest.raises(TypeError):
888 context.set_passwd_cb(None)
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400889
Alex Chan532b79e2017-01-24 15:14:52 +0000890 def test_set_passwd_cb(self, tmpfile):
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400891 """
Alex Chan532b79e2017-01-24 15:14:52 +0000892 `Context.set_passwd_cb` accepts a callable which will be invoked when
893 a private key is loaded from an encrypted PEM.
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400894 """
Alex Gaynore7f51982016-09-11 11:48:14 -0400895 passphrase = b"foobar"
Alex Chan532b79e2017-01-24 15:14:52 +0000896 pemFile = self._write_encrypted_pem(passphrase, tmpfile)
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400897 calledWith = []
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200898
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400899 def passphraseCallback(maxlen, verify, extra):
900 calledWith.append((maxlen, verify, extra))
901 return passphrase
902 context = Context(TLSv1_METHOD)
903 context.set_passwd_cb(passphraseCallback)
904 context.use_privatekey_file(pemFile)
Alex Chan532b79e2017-01-24 15:14:52 +0000905 assert len(calledWith) == 1
906 assert isinstance(calledWith[0][0], int)
907 assert isinstance(calledWith[0][1], int)
908 assert calledWith[0][2] is None
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400909
Alex Chan532b79e2017-01-24 15:14:52 +0000910 def test_passwd_callback_exception(self, tmpfile):
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400911 """
Alex Chan532b79e2017-01-24 15:14:52 +0000912 `Context.use_privatekey_file` propagates any exception raised
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200913 by the passphrase callback.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400914 """
Alex Chan532b79e2017-01-24 15:14:52 +0000915 pemFile = self._write_encrypted_pem(b"monkeys are nice", tmpfile)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200916
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400917 def passphraseCallback(maxlen, verify, extra):
918 raise RuntimeError("Sorry, I am a fail.")
919
920 context = Context(TLSv1_METHOD)
921 context.set_passwd_cb(passphraseCallback)
Alex Chan532b79e2017-01-24 15:14:52 +0000922 with pytest.raises(RuntimeError):
923 context.use_privatekey_file(pemFile)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400924
Alex Chan532b79e2017-01-24 15:14:52 +0000925 def test_passwd_callback_false(self, tmpfile):
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400926 """
Alex Chan532b79e2017-01-24 15:14:52 +0000927 `Context.use_privatekey_file` raises `OpenSSL.SSL.Error` if the
928 passphrase callback returns a false value.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400929 """
Alex Chan532b79e2017-01-24 15:14:52 +0000930 pemFile = self._write_encrypted_pem(b"monkeys are nice", tmpfile)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200931
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400932 def passphraseCallback(maxlen, verify, extra):
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500933 return b""
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400934
935 context = Context(TLSv1_METHOD)
936 context.set_passwd_cb(passphraseCallback)
Alex Chan532b79e2017-01-24 15:14:52 +0000937 with pytest.raises(Error):
938 context.use_privatekey_file(pemFile)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400939
Alex Chan532b79e2017-01-24 15:14:52 +0000940 def test_passwd_callback_non_string(self, tmpfile):
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400941 """
Alex Chan532b79e2017-01-24 15:14:52 +0000942 `Context.use_privatekey_file` raises `OpenSSL.SSL.Error` if the
943 passphrase callback returns a true non-string value.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400944 """
Alex Chan532b79e2017-01-24 15:14:52 +0000945 pemFile = self._write_encrypted_pem(b"monkeys are nice", tmpfile)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200946
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400947 def passphraseCallback(maxlen, verify, extra):
948 return 10
949
950 context = Context(TLSv1_METHOD)
951 context.set_passwd_cb(passphraseCallback)
Alex Chan532b79e2017-01-24 15:14:52 +0000952 # TODO: Surely this is the wrong error?
953 with pytest.raises(ValueError):
954 context.use_privatekey_file(pemFile)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400955
Alex Chan532b79e2017-01-24 15:14:52 +0000956 def test_passwd_callback_too_long(self, tmpfile):
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400957 """
958 If the passphrase returned by the passphrase callback returns a string
959 longer than the indicated maximum length, it is truncated.
960 """
961 # A priori knowledge!
Alex Gaynore7f51982016-09-11 11:48:14 -0400962 passphrase = b"x" * 1024
Alex Chan532b79e2017-01-24 15:14:52 +0000963 pemFile = self._write_encrypted_pem(passphrase, tmpfile)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200964
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400965 def passphraseCallback(maxlen, verify, extra):
966 assert maxlen == 1024
Alex Gaynore7f51982016-09-11 11:48:14 -0400967 return passphrase + b"y"
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400968
969 context = Context(TLSv1_METHOD)
970 context.set_passwd_cb(passphraseCallback)
971 # This shall succeed because the truncated result is the correct
972 # passphrase.
973 context.use_privatekey_file(pemFile)
974
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400975 def test_set_info_callback(self):
976 """
Alex Chan532b79e2017-01-24 15:14:52 +0000977 `Context.set_info_callback` accepts a callable which will be
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200978 invoked when certain information about an SSL connection is available.
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400979 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500980 (server, client) = socket_pair()
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400981
982 clientSSL = Connection(Context(TLSv1_METHOD), client)
983 clientSSL.set_connect_state()
984
985 called = []
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200986
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400987 def info(conn, where, ret):
988 called.append((conn, where, ret))
989 context = Context(TLSv1_METHOD)
990 context.set_info_callback(info)
991 context.use_certificate(
992 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
993 context.use_privatekey(
994 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
995
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400996 serverSSL = Connection(context, server)
997 serverSSL.set_accept_state()
998
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -0500999 handshake(clientSSL, serverSSL)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -04001000
Jean-Paul Calderone3835e522014-02-02 11:12:30 -05001001 # The callback must always be called with a Connection instance as the
1002 # first argument. It would probably be better to split this into
1003 # separate tests for client and server side info callbacks so we could
1004 # assert it is called with the right Connection instance. It would
1005 # also be good to assert *something* about `where` and `ret`.
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -05001006 notConnections = [
1007 conn for (conn, where, ret) in called
1008 if not isinstance(conn, Connection)]
Alex Chan532b79e2017-01-24 15:14:52 +00001009 assert [] == notConnections, (
1010 "Some info callback arguments were not Connection instances.")
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001011
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001012 def _load_verify_locations_test(self, *args):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001013 """
1014 Create a client context which will verify the peer certificate and call
Alex Chan532b79e2017-01-24 15:14:52 +00001015 its `load_verify_locations` method with the given arguments.
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04001016 Then connect it to a server and ensure that the handshake succeeds.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001017 """
Rick Deanb1ccd562009-07-09 23:52:39 -05001018 (server, client) = socket_pair()
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001019
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001020 clientContext = Context(TLSv1_METHOD)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001021 clientContext.load_verify_locations(*args)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001022 # Require that the server certificate verify properly or the
1023 # connection will fail.
1024 clientContext.set_verify(
1025 VERIFY_PEER,
1026 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
1027
1028 clientSSL = Connection(clientContext, client)
1029 clientSSL.set_connect_state()
1030
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001031 serverContext = Context(TLSv1_METHOD)
1032 serverContext.use_certificate(
1033 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1034 serverContext.use_privatekey(
1035 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1036
1037 serverSSL = Connection(serverContext, server)
1038 serverSSL.set_accept_state()
1039
Jean-Paul Calderonef8742032010-09-25 00:00:32 -04001040 # Without load_verify_locations above, the handshake
1041 # will fail:
1042 # Error: [('SSL routines', 'SSL3_GET_SERVER_CERTIFICATE',
1043 # 'certificate verify failed')]
1044 handshake(clientSSL, serverSSL)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001045
1046 cert = clientSSL.get_peer_certificate()
Alex Chan532b79e2017-01-24 15:14:52 +00001047 assert cert.get_subject().CN == 'Testing Root CA'
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -04001048
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001049 def _load_verify_cafile(self, cafile):
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001050 """
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001051 Verify that if path to a file containing a certificate is passed to
Alex Chan532b79e2017-01-24 15:14:52 +00001052 `Context.load_verify_locations` for the ``cafile`` parameter, that
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001053 certificate is used as a trust root for the purposes of verifying
Alex Chan532b79e2017-01-24 15:14:52 +00001054 connections created using that `Context`.
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001055 """
Alex Chan532b79e2017-01-24 15:14:52 +00001056 with open(cafile, 'w') as fObj:
1057 fObj.write(cleartextCertificatePEM.decode('ascii'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001058
1059 self._load_verify_locations_test(cafile)
1060
Alex Chan532b79e2017-01-24 15:14:52 +00001061 def test_load_verify_bytes_cafile(self, tmpfile):
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001062 """
Alex Chan532b79e2017-01-24 15:14:52 +00001063 `Context.load_verify_locations` accepts a file name as a `bytes`
1064 instance and uses the certificates within for verification purposes.
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001065 """
Alex Chan532b79e2017-01-24 15:14:52 +00001066 cafile = tmpfile + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001067 self._load_verify_cafile(cafile)
1068
Alex Chan532b79e2017-01-24 15:14:52 +00001069 def test_load_verify_unicode_cafile(self, tmpfile):
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001070 """
Alex Chan532b79e2017-01-24 15:14:52 +00001071 `Context.load_verify_locations` accepts a file name as a `unicode`
1072 instance and uses the certificates within for verification purposes.
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001073 """
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001074 self._load_verify_cafile(
Alex Chan532b79e2017-01-24 15:14:52 +00001075 tmpfile.decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001076 )
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001077
Alex Chan532b79e2017-01-24 15:14:52 +00001078 def test_load_verify_invalid_file(self, tmpfile):
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -04001079 """
Alex Chan532b79e2017-01-24 15:14:52 +00001080 `Context.load_verify_locations` raises `Error` when passed a
1081 non-existent cafile.
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -04001082 """
1083 clientContext = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001084 with pytest.raises(Error):
1085 clientContext.load_verify_locations(tmpfile)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001086
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001087 def _load_verify_directory_locations_capath(self, capath):
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001088 """
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001089 Verify that if path to a directory containing certificate files is
1090 passed to ``Context.load_verify_locations`` for the ``capath``
1091 parameter, those certificates are used as trust roots for the purposes
1092 of verifying connections created using that ``Context``.
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001093 """
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001094 makedirs(capath)
Jean-Paul Calderone24dfb332011-05-04 18:10:26 -04001095 # Hash values computed manually with c_rehash to avoid depending on
1096 # c_rehash in the test suite. One is from OpenSSL 0.9.8, the other
1097 # from OpenSSL 1.0.0.
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001098 for name in [b'c7adac82.0', b'c3705638.0']:
Jean-Paul Calderone05826732015-04-12 11:38:49 -04001099 cafile = join_bytes_or_unicode(capath, name)
1100 with open(cafile, 'w') as fObj:
1101 fObj.write(cleartextCertificatePEM.decode('ascii'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001102
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001103 self._load_verify_locations_test(None, capath)
1104
Alex Chan532b79e2017-01-24 15:14:52 +00001105 def test_load_verify_directory_bytes_capath(self, tmpfile):
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001106 """
Alex Chan532b79e2017-01-24 15:14:52 +00001107 `Context.load_verify_locations` accepts a directory name as a `bytes`
1108 instance and uses the certificates within for verification purposes.
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001109 """
1110 self._load_verify_directory_locations_capath(
Alex Chan532b79e2017-01-24 15:14:52 +00001111 tmpfile + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001112 )
1113
Alex Chan532b79e2017-01-24 15:14:52 +00001114 def test_load_verify_directory_unicode_capath(self, tmpfile):
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001115 """
Alex Chan532b79e2017-01-24 15:14:52 +00001116 `Context.load_verify_locations` accepts a directory name as a `unicode`
1117 instance and uses the certificates within for verification purposes.
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001118 """
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001119 self._load_verify_directory_locations_capath(
Alex Chan532b79e2017-01-24 15:14:52 +00001120 tmpfile.decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001121 )
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001122
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001123 def test_load_verify_locations_wrong_args(self):
1124 """
Alex Chan532b79e2017-01-24 15:14:52 +00001125 `Context.load_verify_locations` raises `TypeError` if with non-`str`
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001126 arguments.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001127 """
1128 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001129 with pytest.raises(TypeError):
1130 context.load_verify_locations(object())
1131 with pytest.raises(TypeError):
1132 context.load_verify_locations(object(), object())
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001133
Hynek Schlawack734d3022015-09-05 19:19:32 +02001134 @pytest.mark.skipif(
Paul Kehrer55fb3412017-06-29 18:44:08 -05001135 not platform.startswith("linux"),
1136 reason="Loading fallback paths is a linux-specific behavior to "
1137 "accommodate pyca/cryptography manylinux1 wheels"
1138 )
1139 def test_fallback_default_verify_paths(self, monkeypatch):
1140 """
1141 Test that we load certificates successfully on linux from the fallback
1142 path. To do this we set the _CRYPTOGRAPHY_MANYLINUX1_CA_FILE and
1143 _CRYPTOGRAPHY_MANYLINUX1_CA_DIR vars to be equal to whatever the
1144 current OpenSSL default is and we disable
1145 SSL_CTX_SET_default_verify_paths so that it can't find certs unless
1146 it loads via fallback.
1147 """
1148 context = Context(TLSv1_METHOD)
1149 monkeypatch.setattr(
1150 _lib, "SSL_CTX_set_default_verify_paths", lambda x: 1
1151 )
1152 monkeypatch.setattr(
1153 SSL,
1154 "_CRYPTOGRAPHY_MANYLINUX1_CA_FILE",
1155 _ffi.string(_lib.X509_get_default_cert_file())
1156 )
1157 monkeypatch.setattr(
1158 SSL,
1159 "_CRYPTOGRAPHY_MANYLINUX1_CA_DIR",
1160 _ffi.string(_lib.X509_get_default_cert_dir())
1161 )
1162 context.set_default_verify_paths()
1163 store = context.get_cert_store()
1164 sk_obj = _lib.X509_STORE_get0_objects(store._store)
1165 assert sk_obj != _ffi.NULL
1166 num = _lib.sk_X509_OBJECT_num(sk_obj)
1167 assert num != 0
1168
1169 def test_check_env_vars(self, monkeypatch):
1170 """
1171 Test that we return True/False appropriately if the env vars are set.
1172 """
1173 context = Context(TLSv1_METHOD)
1174 dir_var = "CUSTOM_DIR_VAR"
1175 file_var = "CUSTOM_FILE_VAR"
1176 assert context._check_env_vars_set(dir_var, file_var) is False
1177 monkeypatch.setenv(dir_var, "value")
1178 monkeypatch.setenv(file_var, "value")
1179 assert context._check_env_vars_set(dir_var, file_var) is True
1180 assert context._check_env_vars_set(dir_var, file_var) is True
1181
1182 def test_verify_no_fallback_if_env_vars_set(self, monkeypatch):
1183 """
1184 Test that we don't use the fallback path if env vars are set.
1185 """
1186 context = Context(TLSv1_METHOD)
1187 monkeypatch.setattr(
1188 _lib, "SSL_CTX_set_default_verify_paths", lambda x: 1
1189 )
1190 dir_env_var = _ffi.string(
1191 _lib.X509_get_default_cert_dir_env()
1192 ).decode("ascii")
1193 file_env_var = _ffi.string(
1194 _lib.X509_get_default_cert_file_env()
1195 ).decode("ascii")
1196 monkeypatch.setenv(dir_env_var, "value")
1197 monkeypatch.setenv(file_env_var, "value")
1198 context.set_default_verify_paths()
1199
1200 monkeypatch.setattr(
1201 context,
1202 "_fallback_default_verify_paths",
1203 raiser(SystemError)
1204 )
1205 context.set_default_verify_paths()
1206
1207 @pytest.mark.skipif(
Hynek Schlawack734d3022015-09-05 19:19:32 +02001208 platform == "win32",
1209 reason="set_default_verify_paths appears not to work on Windows. "
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -04001210 "See LP#404343 and LP#404344."
Hynek Schlawack734d3022015-09-05 19:19:32 +02001211 )
1212 def test_set_default_verify_paths(self):
1213 """
Alex Chan532b79e2017-01-24 15:14:52 +00001214 `Context.set_default_verify_paths` causes the platform-specific CA
1215 certificate locations to be used for verification purposes.
Hynek Schlawack734d3022015-09-05 19:19:32 +02001216 """
1217 # Testing this requires a server with a certificate signed by one
1218 # of the CAs in the platform CA location. Getting one of those
1219 # costs money. Fortunately (or unfortunately, depending on your
1220 # perspective), it's easy to think of a public server on the
1221 # internet which has such a certificate. Connecting to the network
1222 # in a unit test is bad, but it's the only way I can think of to
1223 # really test this. -exarkun
Hynek Schlawackbf887932015-10-21 17:13:47 +02001224 context = Context(SSLv23_METHOD)
Hynek Schlawack734d3022015-09-05 19:19:32 +02001225 context.set_default_verify_paths()
1226 context.set_verify(
1227 VERIFY_PEER,
1228 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001229
David Benjamin1fbe0642019-04-15 17:05:13 -05001230 client = socket_any_family()
Hynek Schlawackbf887932015-10-21 17:13:47 +02001231 client.connect(("encrypted.google.com", 443))
Hynek Schlawack734d3022015-09-05 19:19:32 +02001232 clientSSL = Connection(context, client)
1233 clientSSL.set_connect_state()
Alex Gaynor373926c2018-05-12 07:43:07 -04001234 clientSSL.set_tlsext_host_name(b"encrypted.google.com")
Hynek Schlawack734d3022015-09-05 19:19:32 +02001235 clientSSL.do_handshake()
1236 clientSSL.send(b"GET / HTTP/1.0\r\n\r\n")
Alex Chan532b79e2017-01-24 15:14:52 +00001237 assert clientSSL.recv(1024)
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05001238
Paul Kehrer55fb3412017-06-29 18:44:08 -05001239 def test_fallback_path_is_not_file_or_dir(self):
1240 """
1241 Test that when passed empty arrays or paths that do not exist no
1242 errors are raised.
1243 """
1244 context = Context(TLSv1_METHOD)
1245 context._fallback_default_verify_paths([], [])
1246 context._fallback_default_verify_paths(
1247 ["/not/a/file"], ["/not/a/dir"]
1248 )
1249
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001250 def test_add_extra_chain_cert_invalid_cert(self):
1251 """
Alex Chan532b79e2017-01-24 15:14:52 +00001252 `Context.add_extra_chain_cert` raises `TypeError` if called with an
1253 object which is not an instance of `X509`.
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001254 """
1255 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001256 with pytest.raises(TypeError):
1257 context.add_extra_chain_cert(object())
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001258
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001259 def _handshake_test(self, serverContext, clientContext):
1260 """
1261 Verify that a client and server created with the given contexts can
1262 successfully handshake and communicate.
1263 """
1264 serverSocket, clientSocket = socket_pair()
1265
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001266 server = Connection(serverContext, serverSocket)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001267 server.set_accept_state()
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001268
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001269 client = Connection(clientContext, clientSocket)
1270 client.set_connect_state()
1271
1272 # Make them talk to each other.
Alex Chan532b79e2017-01-24 15:14:52 +00001273 # interact_in_memory(client, server)
1274 for _ in range(3):
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001275 for s in [client, server]:
1276 try:
1277 s.do_handshake()
1278 except WantReadError:
1279 pass
1280
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001281 def test_set_verify_callback_connection_argument(self):
1282 """
1283 The first argument passed to the verify callback is the
Alex Chan532b79e2017-01-24 15:14:52 +00001284 `Connection` instance for which verification is taking place.
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001285 """
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 class VerifyCallback(object):
1294 def callback(self, connection, *args):
1295 self.connection = connection
1296 return 1
1297
1298 verify = VerifyCallback()
1299 clientContext = Context(TLSv1_METHOD)
1300 clientContext.set_verify(VERIFY_PEER, verify.callback)
1301 clientConnection = Connection(clientContext, None)
1302 clientConnection.set_connect_state()
1303
Alex Chan532b79e2017-01-24 15:14:52 +00001304 handshake_in_memory(clientConnection, serverConnection)
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001305
Alex Chan532b79e2017-01-24 15:14:52 +00001306 assert verify.connection is clientConnection
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001307
Paul Kehrere7381862017-11-30 20:55:25 +08001308 def test_x509_in_verify_works(self):
1309 """
1310 We had a bug where the X509 cert instantiated in the callback wrapper
1311 didn't __init__ so it was missing objects needed when calling
1312 get_subject. This test sets up a handshake where we call get_subject
1313 on the cert provided to the verify callback.
1314 """
1315 serverContext = Context(TLSv1_METHOD)
1316 serverContext.use_privatekey(
1317 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1318 serverContext.use_certificate(
1319 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1320 serverConnection = Connection(serverContext, None)
1321
1322 def verify_cb_get_subject(conn, cert, errnum, depth, ok):
1323 assert cert.get_subject()
1324 return 1
1325
1326 clientContext = Context(TLSv1_METHOD)
1327 clientContext.set_verify(VERIFY_PEER, verify_cb_get_subject)
1328 clientConnection = Connection(clientContext, None)
1329 clientConnection.set_connect_state()
1330
1331 handshake_in_memory(clientConnection, serverConnection)
1332
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001333 def test_set_verify_callback_exception(self):
1334 """
Alex Chan532b79e2017-01-24 15:14:52 +00001335 If the verify callback passed to `Context.set_verify` raises an
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001336 exception, verification fails and the exception is propagated to the
Alex Chan532b79e2017-01-24 15:14:52 +00001337 caller of `Connection.do_handshake`.
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001338 """
Paul Kehrer7d5a3bf2019-01-21 12:24:02 -06001339 serverContext = Context(TLSv1_2_METHOD)
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001340 serverContext.use_privatekey(
1341 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1342 serverContext.use_certificate(
1343 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1344
Paul Kehrer7d5a3bf2019-01-21 12:24:02 -06001345 clientContext = Context(TLSv1_2_METHOD)
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001346
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001347 def verify_callback(*args):
1348 raise Exception("silly verify failure")
1349 clientContext.set_verify(VERIFY_PEER, verify_callback)
1350
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01001351 with pytest.raises(Exception) as exc:
1352 self._handshake_test(serverContext, clientContext)
1353
Alex Chan532b79e2017-01-24 15:14:52 +00001354 assert "silly verify failure" == str(exc.value)
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001355
Alex Chan532b79e2017-01-24 15:14:52 +00001356 def test_add_extra_chain_cert(self, tmpdir):
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001357 """
Alex Chan532b79e2017-01-24 15:14:52 +00001358 `Context.add_extra_chain_cert` accepts an `X509`
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001359 instance to add to the certificate chain.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001360
Alex Chan532b79e2017-01-24 15:14:52 +00001361 See `_create_certificate_chain` for the details of the
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001362 certificate chain tested.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001363
1364 The chain is tested by starting a server with scert and connecting
1365 to it with a client which trusts cacert and requires verification to
1366 succeed.
1367 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001368 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001369 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1370
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001371 # Dump the CA certificate to a file because that's the only way to load
1372 # it as a trusted CA in the client context.
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001373 for cert, name in [(cacert, 'ca.pem'),
1374 (icert, 'i.pem'),
1375 (scert, 's.pem')]:
Alex Chan532b79e2017-01-24 15:14:52 +00001376 with tmpdir.join(name).open('w') as f:
Hynek Schlawacke90680f2015-04-16 15:09:27 -04001377 f.write(dump_certificate(FILETYPE_PEM, cert).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001378
Hynek Schlawack1902c012015-04-16 15:06:41 -04001379 for key, name in [(cakey, 'ca.key'),
1380 (ikey, 'i.key'),
1381 (skey, 's.key')]:
Alex Chan532b79e2017-01-24 15:14:52 +00001382 with tmpdir.join(name).open('w') as f:
Hynek Schlawacke90680f2015-04-16 15:09:27 -04001383 f.write(dump_privatekey(FILETYPE_PEM, key).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001384
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001385 # Create the server context
1386 serverContext = Context(TLSv1_METHOD)
1387 serverContext.use_privatekey(skey)
1388 serverContext.use_certificate(scert)
Jean-Paul Calderone16cf03d2010-09-08 18:53:39 -04001389 # The client already has cacert, we only need to give them icert.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001390 serverContext.add_extra_chain_cert(icert)
1391
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001392 # Create the client
1393 clientContext = Context(TLSv1_METHOD)
1394 clientContext.set_verify(
1395 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Alex Chan532b79e2017-01-24 15:14:52 +00001396 clientContext.load_verify_locations(str(tmpdir.join("ca.pem")))
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001397
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001398 # Try it out.
1399 self._handshake_test(serverContext, clientContext)
1400
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001401 def _use_certificate_chain_file_test(self, certdir):
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001402 """
Alex Chan532b79e2017-01-24 15:14:52 +00001403 Verify that `Context.use_certificate_chain_file` reads a
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001404 certificate chain from a specified file.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001405
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001406 The chain is tested by starting a server with scert and connecting to
1407 it with a client which trusts cacert and requires verification to
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001408 succeed.
1409 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001410 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001411 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1412
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001413 makedirs(certdir)
1414
Jean-Paul Calderone05826732015-04-12 11:38:49 -04001415 chainFile = join_bytes_or_unicode(certdir, "chain.pem")
1416 caFile = join_bytes_or_unicode(certdir, "ca.pem")
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001417
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001418 # Write out the chain file.
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001419 with open(chainFile, 'wb') as fObj:
1420 # Most specific to least general.
1421 fObj.write(dump_certificate(FILETYPE_PEM, scert))
1422 fObj.write(dump_certificate(FILETYPE_PEM, icert))
1423 fObj.write(dump_certificate(FILETYPE_PEM, cacert))
1424
1425 with open(caFile, 'w') as fObj:
1426 fObj.write(dump_certificate(FILETYPE_PEM, cacert).decode('ascii'))
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001427
1428 serverContext = Context(TLSv1_METHOD)
1429 serverContext.use_certificate_chain_file(chainFile)
1430 serverContext.use_privatekey(skey)
1431
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001432 clientContext = Context(TLSv1_METHOD)
1433 clientContext.set_verify(
1434 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001435 clientContext.load_verify_locations(caFile)
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001436
1437 self._handshake_test(serverContext, clientContext)
1438
Alex Chan532b79e2017-01-24 15:14:52 +00001439 def test_use_certificate_chain_file_bytes(self, tmpfile):
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001440 """
1441 ``Context.use_certificate_chain_file`` accepts the name of a file (as
1442 an instance of ``bytes``) to specify additional certificates to use to
1443 construct and verify a trust chain.
1444 """
1445 self._use_certificate_chain_file_test(
Alex Chan532b79e2017-01-24 15:14:52 +00001446 tmpfile + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001447 )
1448
Alex Chan532b79e2017-01-24 15:14:52 +00001449 def test_use_certificate_chain_file_unicode(self, tmpfile):
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001450 """
1451 ``Context.use_certificate_chain_file`` accepts the name of a file (as
1452 an instance of ``unicode``) to specify additional certificates to use
1453 to construct and verify a trust chain.
1454 """
1455 self._use_certificate_chain_file_test(
Alex Chan532b79e2017-01-24 15:14:52 +00001456 tmpfile.decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001457 )
1458
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001459 def test_use_certificate_chain_file_wrong_args(self):
1460 """
Alex Chan532b79e2017-01-24 15:14:52 +00001461 `Context.use_certificate_chain_file` raises `TypeError` if passed a
1462 non-byte string single argument.
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001463 """
1464 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001465 with pytest.raises(TypeError):
1466 context.use_certificate_chain_file(object())
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001467
Alex Chan532b79e2017-01-24 15:14:52 +00001468 def test_use_certificate_chain_file_missing_file(self, tmpfile):
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001469 """
Alex Chan532b79e2017-01-24 15:14:52 +00001470 `Context.use_certificate_chain_file` raises `OpenSSL.SSL.Error` when
1471 passed a bad chain file name (for example, the name of a file which
1472 does not exist).
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001473 """
1474 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001475 with pytest.raises(Error):
1476 context.use_certificate_chain_file(tmpfile)
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001477
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001478 def test_set_verify_mode(self):
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001479 """
Alex Chan532b79e2017-01-24 15:14:52 +00001480 `Context.get_verify_mode` returns the verify mode flags previously
1481 passed to `Context.set_verify`.
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001482 """
1483 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001484 assert context.get_verify_mode() == 0
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001485 context.set_verify(
1486 VERIFY_PEER | VERIFY_CLIENT_ONCE, lambda *args: None)
Alex Chan532b79e2017-01-24 15:14:52 +00001487 assert context.get_verify_mode() == (VERIFY_PEER | VERIFY_CLIENT_ONCE)
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001488
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001489 @skip_if_py3
1490 def test_set_verify_mode_long(self):
1491 """
Alex Chan532b79e2017-01-24 15:14:52 +00001492 On Python 2 `Context.set_verify_mode` accepts values of type `long`
1493 as well as `int`.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001494 """
1495 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001496 assert context.get_verify_mode() == 0
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001497 context.set_verify(
Hynek Schlawackb4ceed32015-09-05 20:55:19 +02001498 long(VERIFY_PEER | VERIFY_CLIENT_ONCE), lambda *args: None
1499 ) # pragma: nocover
Alex Chan532b79e2017-01-24 15:14:52 +00001500 assert context.get_verify_mode() == (VERIFY_PEER | VERIFY_CLIENT_ONCE)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001501
Alex Chanfb078d82017-04-20 11:16:15 +01001502 @pytest.mark.parametrize('mode', [None, 1.0, object(), 'mode'])
1503 def test_set_verify_wrong_mode_arg(self, mode):
1504 """
1505 `Context.set_verify` raises `TypeError` if the first argument is
1506 not an integer.
1507 """
1508 context = Context(TLSv1_METHOD)
1509 with pytest.raises(TypeError):
1510 context.set_verify(mode=mode, callback=lambda *args: None)
1511
1512 @pytest.mark.parametrize('callback', [None, 1.0, 'mode', ('foo', 'bar')])
1513 def test_set_verify_wrong_callable_arg(self, callback):
1514 """
Alex Gaynor40bc0f12018-05-14 14:06:16 -04001515 `Context.set_verify` raises `TypeError` if the second argument
Alex Chanfb078d82017-04-20 11:16:15 +01001516 is not callable.
1517 """
1518 context = Context(TLSv1_METHOD)
1519 with pytest.raises(TypeError):
1520 context.set_verify(mode=VERIFY_PEER, callback=callback)
1521
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001522 def test_load_tmp_dh_wrong_args(self):
1523 """
Alex Chan532b79e2017-01-24 15:14:52 +00001524 `Context.load_tmp_dh` raises `TypeError` if called with a
1525 non-`str` argument.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001526 """
1527 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001528 with pytest.raises(TypeError):
1529 context.load_tmp_dh(object())
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001530
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001531 def test_load_tmp_dh_missing_file(self):
1532 """
Alex Chan532b79e2017-01-24 15:14:52 +00001533 `Context.load_tmp_dh` raises `OpenSSL.SSL.Error` if the
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001534 specified file does not exist.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001535 """
1536 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001537 with pytest.raises(Error):
1538 context.load_tmp_dh(b"hello")
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001539
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001540 def _load_tmp_dh_test(self, dhfilename):
Jean-Paul Calderone4e0c43f2015-04-13 10:15:17 -04001541 """
1542 Verify that calling ``Context.load_tmp_dh`` with the given filename
1543 does not raise an exception.
1544 """
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001545 context = Context(TLSv1_METHOD)
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001546 with open(dhfilename, "w") as dhfile:
1547 dhfile.write(dhparam)
1548
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001549 context.load_tmp_dh(dhfilename)
1550 # XXX What should I assert here? -exarkun
1551
Alex Chan532b79e2017-01-24 15:14:52 +00001552 def test_load_tmp_dh_bytes(self, tmpfile):
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001553 """
Alex Chan532b79e2017-01-24 15:14:52 +00001554 `Context.load_tmp_dh` loads Diffie-Hellman parameters from the
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001555 specified file (given as ``bytes``).
1556 """
1557 self._load_tmp_dh_test(
Alex Chan532b79e2017-01-24 15:14:52 +00001558 tmpfile + NON_ASCII.encode(getfilesystemencoding()),
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001559 )
1560
Alex Chan532b79e2017-01-24 15:14:52 +00001561 def test_load_tmp_dh_unicode(self, tmpfile):
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001562 """
Alex Chan532b79e2017-01-24 15:14:52 +00001563 `Context.load_tmp_dh` loads Diffie-Hellman parameters from the
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001564 specified file (given as ``unicode``).
1565 """
1566 self._load_tmp_dh_test(
Alex Chan532b79e2017-01-24 15:14:52 +00001567 tmpfile.decode(getfilesystemencoding()) + NON_ASCII,
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001568 )
1569
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001570 def test_set_tmp_ecdh(self):
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001571 """
Alex Chan532b79e2017-01-24 15:14:52 +00001572 `Context.set_tmp_ecdh` sets the elliptic curve for Diffie-Hellman to
1573 the specified curve.
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001574 """
1575 context = Context(TLSv1_METHOD)
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001576 for curve in get_elliptic_curves():
Hynek Schlawacka07fa8c2015-10-17 10:15:28 +02001577 if curve.name.startswith(u"Oakley-"):
Hynek Schlawack7408aff2015-10-17 09:51:16 +02001578 # Setting Oakley-EC2N-4 and Oakley-EC2N-3 adds
1579 # ('bignum routines', 'BN_mod_inverse', 'no inverse') to the
1580 # error queue on OpenSSL 1.0.2.
1581 continue
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001582 # The only easily "assertable" thing is that it does not raise an
1583 # exception.
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001584 context.set_tmp_ecdh(curve)
Alex Gaynor12dc0842014-01-17 12:51:31 -06001585
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001586 def test_set_session_cache_mode_wrong_args(self):
1587 """
Alex Chan532b79e2017-01-24 15:14:52 +00001588 `Context.set_session_cache_mode` raises `TypeError` if called with
1589 a non-integer argument.
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001590 called with other than one integer argument.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001591 """
1592 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001593 with pytest.raises(TypeError):
1594 context.set_session_cache_mode(object())
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001595
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001596 def test_session_cache_mode(self):
1597 """
Alex Chan532b79e2017-01-24 15:14:52 +00001598 `Context.set_session_cache_mode` specifies how sessions are cached.
1599 The setting can be retrieved via `Context.get_session_cache_mode`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001600 """
1601 context = Context(TLSv1_METHOD)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001602 context.set_session_cache_mode(SESS_CACHE_OFF)
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001603 off = context.set_session_cache_mode(SESS_CACHE_BOTH)
Alex Chan532b79e2017-01-24 15:14:52 +00001604 assert SESS_CACHE_OFF == off
1605 assert SESS_CACHE_BOTH == context.get_session_cache_mode()
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001606
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001607 @skip_if_py3
1608 def test_session_cache_mode_long(self):
1609 """
Alex Chan532b79e2017-01-24 15:14:52 +00001610 On Python 2 `Context.set_session_cache_mode` accepts values
1611 of type `long` as well as `int`.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001612 """
1613 context = Context(TLSv1_METHOD)
1614 context.set_session_cache_mode(long(SESS_CACHE_BOTH))
Alex Chan532b79e2017-01-24 15:14:52 +00001615 assert SESS_CACHE_BOTH == context.get_session_cache_mode()
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001616
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001617 def test_get_cert_store(self):
1618 """
Alex Chan532b79e2017-01-24 15:14:52 +00001619 `Context.get_cert_store` returns a `X509Store` instance.
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001620 """
1621 context = Context(TLSv1_METHOD)
1622 store = context.get_cert_store()
Alex Chan532b79e2017-01-24 15:14:52 +00001623 assert isinstance(store, X509Store)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001624
Jeremy Lainé02261ad2018-05-16 18:33:25 +02001625 def test_set_tlsext_use_srtp_not_bytes(self):
1626 """
1627 `Context.set_tlsext_use_srtp' enables negotiating SRTP keying material.
1628
1629 It raises a TypeError if the list of profiles is not a byte string.
1630 """
1631 context = Context(TLSv1_METHOD)
1632 with pytest.raises(TypeError):
1633 context.set_tlsext_use_srtp(text_type('SRTP_AES128_CM_SHA1_80'))
1634
1635 def test_set_tlsext_use_srtp_invalid_profile(self):
1636 """
1637 `Context.set_tlsext_use_srtp' enables negotiating SRTP keying material.
1638
1639 It raises an Error if the call to OpenSSL fails.
1640 """
1641 context = Context(TLSv1_METHOD)
1642 with pytest.raises(Error):
1643 context.set_tlsext_use_srtp(b'SRTP_BOGUS')
1644
1645 def test_set_tlsext_use_srtp_valid(self):
1646 """
1647 `Context.set_tlsext_use_srtp' enables negotiating SRTP keying material.
1648
1649 It does not return anything.
1650 """
1651 context = Context(TLSv1_METHOD)
1652 assert context.set_tlsext_use_srtp(b'SRTP_AES128_CM_SHA1_80') is None
1653
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001654
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001655class TestServerNameCallback(object):
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001656 """
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001657 Tests for `Context.set_tlsext_servername_callback` and its
1658 interaction with `Connection`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001659 """
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001660 def test_old_callback_forgotten(self):
1661 """
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001662 If `Context.set_tlsext_servername_callback` is used to specify
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001663 a new callback, the one it replaces is dereferenced.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001664 """
Alex Chanfb078d82017-04-20 11:16:15 +01001665 def callback(connection): # pragma: no cover
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001666 pass
1667
Alex Chanfb078d82017-04-20 11:16:15 +01001668 def replacement(connection): # pragma: no cover
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001669 pass
1670
1671 context = Context(TLSv1_METHOD)
1672 context.set_tlsext_servername_callback(callback)
1673
1674 tracker = ref(callback)
1675 del callback
1676
1677 context.set_tlsext_servername_callback(replacement)
Jean-Paul Calderoned4033eb2014-01-11 08:21:46 -05001678
1679 # One run of the garbage collector happens to work on CPython. PyPy
1680 # doesn't collect the underlying object until a second run for whatever
1681 # reason. That's fine, it still demonstrates our code has properly
1682 # dropped the reference.
1683 collect()
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001684 collect()
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001685
1686 callback = tracker()
1687 if callback is not None:
1688 referrers = get_referrers(callback)
Alex Chanfb078d82017-04-20 11:16:15 +01001689 if len(referrers) > 1: # pragma: nocover
1690 pytest.fail("Some references remain: %r" % (referrers,))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001691
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001692 def test_no_servername(self):
1693 """
1694 When a client specifies no server name, the callback passed to
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001695 `Context.set_tlsext_servername_callback` is invoked and the
1696 result of `Connection.get_servername` is `None`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001697 """
1698 args = []
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001699
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001700 def servername(conn):
1701 args.append((conn, conn.get_servername()))
1702 context = Context(TLSv1_METHOD)
1703 context.set_tlsext_servername_callback(servername)
1704
1705 # Lose our reference to it. The Context is responsible for keeping it
1706 # alive now.
1707 del servername
1708 collect()
1709
1710 # Necessary to actually accept the connection
1711 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001712 context.use_certificate(
1713 load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001714
1715 # Do a little connection to trigger the logic
1716 server = Connection(context, None)
1717 server.set_accept_state()
1718
1719 client = Connection(Context(TLSv1_METHOD), None)
1720 client.set_connect_state()
1721
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001722 interact_in_memory(server, client)
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001723
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001724 assert args == [(server, None)]
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001725
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001726 def test_servername(self):
1727 """
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001728 When a client specifies a server name in its hello message, the
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001729 callback passed to `Contexts.set_tlsext_servername_callback` is
1730 invoked and the result of `Connection.get_servername` is that
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001731 server name.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001732 """
1733 args = []
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001734
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001735 def servername(conn):
1736 args.append((conn, conn.get_servername()))
1737 context = Context(TLSv1_METHOD)
1738 context.set_tlsext_servername_callback(servername)
1739
1740 # Necessary to actually accept the connection
1741 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001742 context.use_certificate(
1743 load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001744
1745 # Do a little connection to trigger the logic
1746 server = Connection(context, None)
1747 server.set_accept_state()
1748
1749 client = Connection(Context(TLSv1_METHOD), None)
1750 client.set_connect_state()
Alex Gaynore7f51982016-09-11 11:48:14 -04001751 client.set_tlsext_host_name(b"foo1.example.com")
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001752
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001753 interact_in_memory(server, client)
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001754
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001755 assert args == [(server, b"foo1.example.com")]
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001756
1757
Paul Kehrer4d575902019-02-26 21:42:12 +08001758@pytest.mark.skipif(
1759 not _lib.Cryptography_HAS_NEXTPROTONEG, reason="NPN is not available"
1760)
Alex Chan9e08b3e2016-11-10 12:18:54 +00001761class TestNextProtoNegotiation(object):
Cory Benfield84a121e2014-03-31 20:30:25 +01001762 """
1763 Test for Next Protocol Negotiation in PyOpenSSL.
1764 """
Alex Chan9e08b3e2016-11-10 12:18:54 +00001765 def test_npn_success(self):
1766 """
1767 Tests that clients and servers that agree on the negotiated next
1768 protocol can correct establish a connection, and that the agreed
1769 protocol is reported by the connections.
1770 """
1771 advertise_args = []
1772 select_args = []
1773
1774 def advertise(conn):
1775 advertise_args.append((conn,))
1776 return [b'http/1.1', b'spdy/2']
1777
1778 def select(conn, options):
1779 select_args.append((conn, options))
1780 return b'spdy/2'
1781
1782 server_context = Context(TLSv1_METHOD)
1783 server_context.set_npn_advertise_callback(advertise)
1784
1785 client_context = Context(TLSv1_METHOD)
1786 client_context.set_npn_select_callback(select)
1787
1788 # Necessary to actually accept the connection
1789 server_context.use_privatekey(
1790 load_privatekey(FILETYPE_PEM, server_key_pem))
1791 server_context.use_certificate(
1792 load_certificate(FILETYPE_PEM, server_cert_pem))
1793
1794 # Do a little connection to trigger the logic
1795 server = Connection(server_context, None)
1796 server.set_accept_state()
1797
1798 client = Connection(client_context, None)
1799 client.set_connect_state()
1800
1801 interact_in_memory(server, client)
1802
1803 assert advertise_args == [(server,)]
1804 assert select_args == [(client, [b'http/1.1', b'spdy/2'])]
1805
1806 assert server.get_next_proto_negotiated() == b'spdy/2'
1807 assert client.get_next_proto_negotiated() == b'spdy/2'
1808
1809 def test_npn_client_fail(self):
1810 """
1811 Tests that when clients and servers cannot agree on what protocol
1812 to use next that the TLS connection does not get established.
1813 """
1814 advertise_args = []
1815 select_args = []
1816
1817 def advertise(conn):
1818 advertise_args.append((conn,))
1819 return [b'http/1.1', b'spdy/2']
1820
1821 def select(conn, options):
1822 select_args.append((conn, options))
1823 return b''
1824
1825 server_context = Context(TLSv1_METHOD)
1826 server_context.set_npn_advertise_callback(advertise)
1827
1828 client_context = Context(TLSv1_METHOD)
1829 client_context.set_npn_select_callback(select)
1830
1831 # Necessary to actually accept the connection
1832 server_context.use_privatekey(
1833 load_privatekey(FILETYPE_PEM, server_key_pem))
1834 server_context.use_certificate(
1835 load_certificate(FILETYPE_PEM, server_cert_pem))
1836
1837 # Do a little connection to trigger the logic
1838 server = Connection(server_context, None)
1839 server.set_accept_state()
1840
1841 client = Connection(client_context, None)
1842 client.set_connect_state()
1843
1844 # If the client doesn't return anything, the connection will fail.
1845 with pytest.raises(Error):
1846 interact_in_memory(server, client)
1847
1848 assert advertise_args == [(server,)]
1849 assert select_args == [(client, [b'http/1.1', b'spdy/2'])]
1850
1851 def test_npn_select_error(self):
1852 """
1853 Test that we can handle exceptions in the select callback. If
1854 select fails it should be fatal to the connection.
1855 """
1856 advertise_args = []
1857
1858 def advertise(conn):
1859 advertise_args.append((conn,))
1860 return [b'http/1.1', b'spdy/2']
1861
1862 def select(conn, options):
1863 raise TypeError
1864
1865 server_context = Context(TLSv1_METHOD)
1866 server_context.set_npn_advertise_callback(advertise)
1867
1868 client_context = Context(TLSv1_METHOD)
1869 client_context.set_npn_select_callback(select)
1870
1871 # Necessary to actually accept the connection
1872 server_context.use_privatekey(
1873 load_privatekey(FILETYPE_PEM, server_key_pem))
1874 server_context.use_certificate(
1875 load_certificate(FILETYPE_PEM, server_cert_pem))
1876
1877 # Do a little connection to trigger the logic
1878 server = Connection(server_context, None)
1879 server.set_accept_state()
1880
1881 client = Connection(client_context, None)
1882 client.set_connect_state()
1883
1884 # If the callback throws an exception it should be raised here.
1885 with pytest.raises(TypeError):
1886 interact_in_memory(server, client)
1887 assert advertise_args == [(server,), ]
1888
1889 def test_npn_advertise_error(self):
1890 """
1891 Test that we can handle exceptions in the advertise callback. If
1892 advertise fails no NPN is advertised to the client.
1893 """
1894 select_args = []
1895
1896 def advertise(conn):
1897 raise TypeError
1898
1899 def select(conn, options): # pragma: nocover
Cory Benfieldba1820d2015-04-13 17:39:12 -04001900 """
Alex Chan9e08b3e2016-11-10 12:18:54 +00001901 Assert later that no args are actually appended.
Cory Benfieldba1820d2015-04-13 17:39:12 -04001902 """
Alex Chan9e08b3e2016-11-10 12:18:54 +00001903 select_args.append((conn, options))
1904 return b''
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001905
Alex Chan9e08b3e2016-11-10 12:18:54 +00001906 server_context = Context(TLSv1_METHOD)
1907 server_context.set_npn_advertise_callback(advertise)
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001908
Alex Chan9e08b3e2016-11-10 12:18:54 +00001909 client_context = Context(TLSv1_METHOD)
1910 client_context.set_npn_select_callback(select)
Cory Benfield84a121e2014-03-31 20:30:25 +01001911
Alex Chan9e08b3e2016-11-10 12:18:54 +00001912 # Necessary to actually accept the connection
1913 server_context.use_privatekey(
1914 load_privatekey(FILETYPE_PEM, server_key_pem))
1915 server_context.use_certificate(
1916 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield84a121e2014-03-31 20:30:25 +01001917
Alex Chan9e08b3e2016-11-10 12:18:54 +00001918 # Do a little connection to trigger the logic
1919 server = Connection(server_context, None)
1920 server.set_accept_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001921
Alex Chan9e08b3e2016-11-10 12:18:54 +00001922 client = Connection(client_context, None)
1923 client.set_connect_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001924
Alex Chan9e08b3e2016-11-10 12:18:54 +00001925 # If the client doesn't return anything, the connection will fail.
1926 with pytest.raises(TypeError):
1927 interact_in_memory(server, client)
1928 assert select_args == []
Cory Benfield0ea76e72015-03-22 09:05:28 +00001929
1930
Alex Chanec1e32d2016-11-10 14:11:45 +00001931class TestApplicationLayerProtoNegotiation(object):
Cory Benfield12eae892014-06-07 15:42:56 +01001932 """
1933 Tests for ALPN in PyOpenSSL.
1934 """
Cory Benfielde46fa842015-04-13 16:50:49 -04001935 # Skip tests on versions that don't support ALPN.
1936 if _lib.Cryptography_HAS_ALPN:
Cory Benfield12eae892014-06-07 15:42:56 +01001937
Cory Benfielde46fa842015-04-13 16:50:49 -04001938 def test_alpn_success(self):
1939 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04001940 Clients and servers that agree on the negotiated ALPN protocol can
1941 correct establish a connection, and the agreed protocol is reported
1942 by the connections.
Cory Benfielde46fa842015-04-13 16:50:49 -04001943 """
1944 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001945
Cory Benfielde46fa842015-04-13 16:50:49 -04001946 def select(conn, options):
1947 select_args.append((conn, options))
1948 return b'spdy/2'
Cory Benfield12eae892014-06-07 15:42:56 +01001949
Cory Benfielde46fa842015-04-13 16:50:49 -04001950 client_context = Context(TLSv1_METHOD)
1951 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfield12eae892014-06-07 15:42:56 +01001952
Cory Benfielde46fa842015-04-13 16:50:49 -04001953 server_context = Context(TLSv1_METHOD)
1954 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01001955
Cory Benfielde46fa842015-04-13 16:50:49 -04001956 # Necessary to actually accept the connection
1957 server_context.use_privatekey(
1958 load_privatekey(FILETYPE_PEM, server_key_pem))
1959 server_context.use_certificate(
1960 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield12eae892014-06-07 15:42:56 +01001961
Cory Benfielde46fa842015-04-13 16:50:49 -04001962 # Do a little connection to trigger the logic
1963 server = Connection(server_context, None)
1964 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001965
Cory Benfielde46fa842015-04-13 16:50:49 -04001966 client = Connection(client_context, None)
1967 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001968
Alex Chanec1e32d2016-11-10 14:11:45 +00001969 interact_in_memory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001970
Alex Chanec1e32d2016-11-10 14:11:45 +00001971 assert select_args == [(server, [b'http/1.1', b'spdy/2'])]
Cory Benfielde46fa842015-04-13 16:50:49 -04001972
Alex Chanec1e32d2016-11-10 14:11:45 +00001973 assert server.get_alpn_proto_negotiated() == b'spdy/2'
1974 assert client.get_alpn_proto_negotiated() == b'spdy/2'
Cory Benfield12eae892014-06-07 15:42:56 +01001975
Cory Benfielde46fa842015-04-13 16:50:49 -04001976 def test_alpn_set_on_connection(self):
1977 """
1978 The same as test_alpn_success, but setting the ALPN protocols on
1979 the connection rather than the context.
1980 """
1981 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001982
Cory Benfielde46fa842015-04-13 16:50:49 -04001983 def select(conn, options):
1984 select_args.append((conn, options))
1985 return b'spdy/2'
Cory Benfield12eae892014-06-07 15:42:56 +01001986
Cory Benfielde46fa842015-04-13 16:50:49 -04001987 # Setup the client context but don't set any ALPN protocols.
1988 client_context = Context(TLSv1_METHOD)
Cory Benfield12eae892014-06-07 15:42:56 +01001989
Cory Benfielde46fa842015-04-13 16:50:49 -04001990 server_context = Context(TLSv1_METHOD)
1991 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01001992
Cory Benfielde46fa842015-04-13 16:50:49 -04001993 # Necessary to actually accept the connection
1994 server_context.use_privatekey(
1995 load_privatekey(FILETYPE_PEM, server_key_pem))
1996 server_context.use_certificate(
1997 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield12eae892014-06-07 15:42:56 +01001998
Cory Benfielde46fa842015-04-13 16:50:49 -04001999 # Do a little connection to trigger the logic
2000 server = Connection(server_context, None)
2001 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01002002
Cory Benfielde46fa842015-04-13 16:50:49 -04002003 # Set the ALPN protocols on the client connection.
2004 client = Connection(client_context, None)
2005 client.set_alpn_protos([b'http/1.1', b'spdy/2'])
2006 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01002007
Alex Chanec1e32d2016-11-10 14:11:45 +00002008 interact_in_memory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01002009
Alex Chanec1e32d2016-11-10 14:11:45 +00002010 assert select_args == [(server, [b'http/1.1', b'spdy/2'])]
Cory Benfield12eae892014-06-07 15:42:56 +01002011
Alex Chanec1e32d2016-11-10 14:11:45 +00002012 assert server.get_alpn_proto_negotiated() == b'spdy/2'
2013 assert client.get_alpn_proto_negotiated() == b'spdy/2'
Cory Benfield12eae892014-06-07 15:42:56 +01002014
Cory Benfielde46fa842015-04-13 16:50:49 -04002015 def test_alpn_server_fail(self):
2016 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04002017 When clients and servers cannot agree on what protocol to use next
2018 the TLS connection does not get established.
Cory Benfielde46fa842015-04-13 16:50:49 -04002019 """
2020 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002021
Cory Benfielde46fa842015-04-13 16:50:49 -04002022 def select(conn, options):
2023 select_args.append((conn, options))
2024 return b''
Cory Benfield12eae892014-06-07 15:42:56 +01002025
Cory Benfielde46fa842015-04-13 16:50:49 -04002026 client_context = Context(TLSv1_METHOD)
2027 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfield12eae892014-06-07 15:42:56 +01002028
Cory Benfielde46fa842015-04-13 16:50:49 -04002029 server_context = Context(TLSv1_METHOD)
2030 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01002031
Cory Benfielde46fa842015-04-13 16:50:49 -04002032 # Necessary to actually accept the connection
2033 server_context.use_privatekey(
2034 load_privatekey(FILETYPE_PEM, server_key_pem))
2035 server_context.use_certificate(
2036 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield12eae892014-06-07 15:42:56 +01002037
Cory Benfielde46fa842015-04-13 16:50:49 -04002038 # Do a little connection to trigger the logic
2039 server = Connection(server_context, None)
2040 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01002041
Cory Benfielde46fa842015-04-13 16:50:49 -04002042 client = Connection(client_context, None)
2043 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01002044
Cory Benfielde46fa842015-04-13 16:50:49 -04002045 # If the client doesn't return anything, the connection will fail.
Alex Chanec1e32d2016-11-10 14:11:45 +00002046 with pytest.raises(Error):
2047 interact_in_memory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01002048
Alex Chanec1e32d2016-11-10 14:11:45 +00002049 assert select_args == [(server, [b'http/1.1', b'spdy/2'])]
Cory Benfield12eae892014-06-07 15:42:56 +01002050
Cory Benfielde46fa842015-04-13 16:50:49 -04002051 def test_alpn_no_server(self):
2052 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04002053 When clients and servers cannot agree on what protocol to use next
2054 because the server doesn't offer ALPN, no protocol is negotiated.
Cory Benfielde46fa842015-04-13 16:50:49 -04002055 """
2056 client_context = Context(TLSv1_METHOD)
2057 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfielde3d57152015-04-11 17:57:35 -04002058
Cory Benfielde46fa842015-04-13 16:50:49 -04002059 server_context = Context(TLSv1_METHOD)
Cory Benfielde3d57152015-04-11 17:57:35 -04002060
Cory Benfielde46fa842015-04-13 16:50:49 -04002061 # Necessary to actually accept the connection
2062 server_context.use_privatekey(
2063 load_privatekey(FILETYPE_PEM, server_key_pem))
2064 server_context.use_certificate(
2065 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfielde3d57152015-04-11 17:57:35 -04002066
Cory Benfielde46fa842015-04-13 16:50:49 -04002067 # Do a little connection to trigger the logic
2068 server = Connection(server_context, None)
2069 server.set_accept_state()
Cory Benfielde3d57152015-04-11 17:57:35 -04002070
Cory Benfielde46fa842015-04-13 16:50:49 -04002071 client = Connection(client_context, None)
2072 client.set_connect_state()
Cory Benfielde3d57152015-04-11 17:57:35 -04002073
Cory Benfielde46fa842015-04-13 16:50:49 -04002074 # Do the dance.
Alex Chanec1e32d2016-11-10 14:11:45 +00002075 interact_in_memory(server, client)
Cory Benfielde3d57152015-04-11 17:57:35 -04002076
Alex Chanec1e32d2016-11-10 14:11:45 +00002077 assert client.get_alpn_proto_negotiated() == b''
Cory Benfielde3d57152015-04-11 17:57:35 -04002078
Cory Benfielde46fa842015-04-13 16:50:49 -04002079 def test_alpn_callback_exception(self):
2080 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04002081 We can handle exceptions in the ALPN select callback.
Cory Benfielde46fa842015-04-13 16:50:49 -04002082 """
2083 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002084
Cory Benfielde46fa842015-04-13 16:50:49 -04002085 def select(conn, options):
2086 select_args.append((conn, options))
Cory Benfieldef401452015-04-13 18:17:36 -04002087 raise TypeError()
Cory Benfieldf1177e72015-04-12 09:11:49 -04002088
Cory Benfielde46fa842015-04-13 16:50:49 -04002089 client_context = Context(TLSv1_METHOD)
2090 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfieldf1177e72015-04-12 09:11:49 -04002091
Cory Benfielde46fa842015-04-13 16:50:49 -04002092 server_context = Context(TLSv1_METHOD)
2093 server_context.set_alpn_select_callback(select)
Cory Benfieldf1177e72015-04-12 09:11:49 -04002094
Cory Benfielde46fa842015-04-13 16:50:49 -04002095 # Necessary to actually accept the connection
2096 server_context.use_privatekey(
2097 load_privatekey(FILETYPE_PEM, server_key_pem))
2098 server_context.use_certificate(
2099 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfieldf1177e72015-04-12 09:11:49 -04002100
Cory Benfielde46fa842015-04-13 16:50:49 -04002101 # Do a little connection to trigger the logic
2102 server = Connection(server_context, None)
2103 server.set_accept_state()
Cory Benfieldf1177e72015-04-12 09:11:49 -04002104
Cory Benfielde46fa842015-04-13 16:50:49 -04002105 client = Connection(client_context, None)
2106 client.set_connect_state()
Cory Benfieldf1177e72015-04-12 09:11:49 -04002107
Alex Chanec1e32d2016-11-10 14:11:45 +00002108 with pytest.raises(TypeError):
2109 interact_in_memory(server, client)
2110 assert select_args == [(server, [b'http/1.1', b'spdy/2'])]
Cory Benfieldf1177e72015-04-12 09:11:49 -04002111
Cory Benfield0f7b04c2015-04-13 17:51:12 -04002112 else:
2113 # No ALPN.
2114 def test_alpn_not_implemented(self):
Cory Benfieldef401452015-04-13 18:17:36 -04002115 """
2116 If ALPN is not in OpenSSL, we should raise NotImplementedError.
2117 """
Cory Benfield0f7b04c2015-04-13 17:51:12 -04002118 # Test the context methods first.
2119 context = Context(TLSv1_METHOD)
Alex Chanec1e32d2016-11-10 14:11:45 +00002120 with pytest.raises(NotImplementedError):
2121 context.set_alpn_protos(None)
2122 with pytest.raises(NotImplementedError):
2123 context.set_alpn_select_callback(None)
Cory Benfield0f7b04c2015-04-13 17:51:12 -04002124
2125 # Now test a connection.
2126 conn = Connection(context)
Alex Chanec1e32d2016-11-10 14:11:45 +00002127 with pytest.raises(NotImplementedError):
2128 conn.set_alpn_protos(None)
Cory Benfield0f7b04c2015-04-13 17:51:12 -04002129
Cory Benfieldf1177e72015-04-12 09:11:49 -04002130
Alex Chanec1e32d2016-11-10 14:11:45 +00002131class TestSession(object):
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05002132 """
2133 Unit tests for :py:obj:`OpenSSL.SSL.Session`.
2134 """
2135 def test_construction(self):
2136 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002137 :py:class:`Session` can be constructed with no arguments, creating
2138 a new instance of that type.
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05002139 """
2140 new_session = Session()
Alex Chanec1e32d2016-11-10 14:11:45 +00002141 assert isinstance(new_session, Session)
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05002142
2143
Alex Chan1c0cb662017-01-30 07:13:30 +00002144class TestConnection(object):
Rick Deane15b1472009-07-09 15:53:42 -05002145 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002146 Unit tests for `OpenSSL.SSL.Connection`.
Rick Deane15b1472009-07-09 15:53:42 -05002147 """
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04002148 # XXX get_peer_certificate -> None
2149 # XXX sock_shutdown
2150 # XXX master_key -> TypeError
2151 # XXX server_random -> TypeError
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04002152 # XXX connect -> TypeError
2153 # XXX connect_ex -> TypeError
2154 # XXX set_connect_state -> TypeError
2155 # XXX set_accept_state -> TypeError
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04002156 # XXX do_handshake -> TypeError
2157 # XXX bio_read -> TypeError
2158 # XXX recv -> TypeError
2159 # XXX send -> TypeError
2160 # XXX bio_write -> TypeError
2161
Rick Deane15b1472009-07-09 15:53:42 -05002162 def test_type(self):
2163 """
Alex Gaynor01f90a12019-02-07 09:14:48 -05002164 `Connection` can be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -05002165 """
2166 ctx = Context(TLSv1_METHOD)
Alex Chan1c0cb662017-01-30 07:13:30 +00002167 assert is_consistent_type(Connection, 'Connection', ctx, None)
Rick Deane15b1472009-07-09 15:53:42 -05002168
Alex Chanfb078d82017-04-20 11:16:15 +01002169 @pytest.mark.parametrize('bad_context', [object(), 'context', None, 1])
2170 def test_wrong_args(self, bad_context):
2171 """
2172 `Connection.__init__` raises `TypeError` if called with a non-`Context`
2173 instance argument.
2174 """
2175 with pytest.raises(TypeError):
2176 Connection(bad_context)
2177
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002178 def test_get_context(self):
2179 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002180 `Connection.get_context` returns the `Context` instance used to
2181 construct the `Connection` instance.
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002182 """
2183 context = Context(TLSv1_METHOD)
2184 connection = Connection(context, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002185 assert connection.get_context() is context
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002186
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002187 def test_set_context_wrong_args(self):
2188 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002189 `Connection.set_context` raises `TypeError` if called with a
Alex Chanfb078d82017-04-20 11:16:15 +01002190 non-`Context` instance argument.
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002191 """
2192 ctx = Context(TLSv1_METHOD)
2193 connection = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002194 with pytest.raises(TypeError):
2195 connection.set_context(object())
2196 with pytest.raises(TypeError):
2197 connection.set_context("hello")
2198 with pytest.raises(TypeError):
2199 connection.set_context(1)
2200 assert ctx is connection.get_context()
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002201
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002202 def test_set_context(self):
2203 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002204 `Connection.set_context` specifies a new `Context` instance to be
2205 used for the connection.
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002206 """
2207 original = Context(SSLv23_METHOD)
2208 replacement = Context(TLSv1_METHOD)
2209 connection = Connection(original, None)
2210 connection.set_context(replacement)
Alex Chan1c0cb662017-01-30 07:13:30 +00002211 assert replacement is connection.get_context()
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002212 # Lose our references to the contexts, just in case the Connection
2213 # isn't properly managing its own contributions to their reference
2214 # counts.
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002215 del original, replacement
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002216 collect()
2217
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002218 def test_set_tlsext_host_name_wrong_args(self):
2219 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002220 If `Connection.set_tlsext_host_name` is called with a non-byte string
2221 argument or a byte string with an embedded NUL, `TypeError` is raised.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002222 """
2223 conn = Connection(Context(TLSv1_METHOD), None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002224 with pytest.raises(TypeError):
2225 conn.set_tlsext_host_name(object())
2226 with pytest.raises(TypeError):
2227 conn.set_tlsext_host_name(b"with\0null")
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002228
Abraham Martinc5484ba2015-03-25 15:33:05 +00002229 if PY3:
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002230 # On Python 3.x, don't accidentally implicitly convert from text.
Alex Chan1c0cb662017-01-30 07:13:30 +00002231 with pytest.raises(TypeError):
2232 conn.set_tlsext_host_name(b"example.com".decode("ascii"))
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04002233
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002234 def test_pending(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002235 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002236 `Connection.pending` returns the number of bytes available for
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002237 immediate read.
2238 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002239 connection = Connection(Context(TLSv1_METHOD), None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002240 assert connection.pending() == 0
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002241
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002242 def test_peek(self):
2243 """
Hynek Schlawack3bcf3152017-02-18 08:25:34 +01002244 `Connection.recv` peeks into the connection if `socket.MSG_PEEK` is
2245 passed.
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002246 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002247 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002248 server.send(b'xy')
Alex Chan1c0cb662017-01-30 07:13:30 +00002249 assert client.recv(2, MSG_PEEK) == b'xy'
2250 assert client.recv(2, MSG_PEEK) == b'xy'
2251 assert client.recv(2) == b'xy'
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002252
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002253 def test_connect_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002254 """
Hynek Schlawack3bcf3152017-02-18 08:25:34 +01002255 `Connection.connect` raises `TypeError` if called with a non-address
2256 argument.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002257 """
David Benjamin1fbe0642019-04-15 17:05:13 -05002258 connection = Connection(Context(TLSv1_METHOD), socket_any_family())
Alex Chan1c0cb662017-01-30 07:13:30 +00002259 with pytest.raises(TypeError):
2260 connection.connect(None)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002261
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002262 def test_connect_refused(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002263 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002264 `Connection.connect` raises `socket.error` if the underlying socket
2265 connect method raises it.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002266 """
David Benjamin1fbe0642019-04-15 17:05:13 -05002267 client = socket_any_family()
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002268 context = Context(TLSv1_METHOD)
2269 clientSSL = Connection(context, client)
Alex Gaynor122717b2015-09-05 14:14:18 -04002270 # pytest.raises here doesn't work because of a bug in py.test on Python
2271 # 2.6: https://github.com/pytest-dev/pytest/issues/988
Alex Gaynore69c2782015-09-05 14:07:48 -04002272 try:
David Benjamin1fbe0642019-04-15 17:05:13 -05002273 clientSSL.connect((loopback_address(client), 1))
Alex Gaynore69c2782015-09-05 14:07:48 -04002274 except error as e:
Alex Gaynor20a4c082015-09-05 14:24:15 -04002275 exc = e
2276 assert exc.args[0] == ECONNREFUSED
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002277
2278 def test_connect(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002279 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002280 `Connection.connect` establishes a connection to the specified address.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002281 """
David Benjamin1fbe0642019-04-15 17:05:13 -05002282 port = socket_any_family()
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002283 port.bind(('', 0))
2284 port.listen(3)
2285
David Benjamin1fbe0642019-04-15 17:05:13 -05002286 clientSSL = Connection(Context(TLSv1_METHOD), socket(port.family))
2287 clientSSL.connect((loopback_address(port), port.getsockname()[1]))
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002288 # XXX An assertion? Or something?
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002289
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002290 @pytest.mark.skipif(
2291 platform == "darwin",
2292 reason="connect_ex sometimes causes a kernel panic on OS X 10.6.4"
2293 )
2294 def test_connect_ex(self):
2295 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002296 If there is a connection error, `Connection.connect_ex` returns the
2297 errno instead of raising an exception.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002298 """
David Benjamin1fbe0642019-04-15 17:05:13 -05002299 port = socket_any_family()
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002300 port.bind(('', 0))
2301 port.listen(3)
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002302
David Benjamin1fbe0642019-04-15 17:05:13 -05002303 clientSSL = Connection(Context(TLSv1_METHOD), socket(port.family))
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002304 clientSSL.setblocking(False)
2305 result = clientSSL.connect_ex(port.getsockname())
2306 expected = (EINPROGRESS, EWOULDBLOCK)
Alex Chan1c0cb662017-01-30 07:13:30 +00002307 assert result in expected
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002308
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002309 def test_accept(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002310 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002311 `Connection.accept` accepts a pending connection attempt and returns a
2312 tuple of a new `Connection` (the accepted client) and the address the
2313 connection originated from.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002314 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002315 ctx = Context(TLSv1_METHOD)
2316 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2317 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
David Benjamin1fbe0642019-04-15 17:05:13 -05002318 port = socket_any_family()
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002319 portSSL = Connection(ctx, port)
2320 portSSL.bind(('', 0))
2321 portSSL.listen(3)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002322
David Benjamin1fbe0642019-04-15 17:05:13 -05002323 clientSSL = Connection(Context(TLSv1_METHOD), socket(port.family))
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002324
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002325 # Calling portSSL.getsockname() here to get the server IP address
2326 # sounds great, but frequently fails on Windows.
David Benjamin1fbe0642019-04-15 17:05:13 -05002327 clientSSL.connect((loopback_address(port), portSSL.getsockname()[1]))
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002328
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002329 serverSSL, address = portSSL.accept()
2330
Alex Chan1c0cb662017-01-30 07:13:30 +00002331 assert isinstance(serverSSL, Connection)
2332 assert serverSSL.get_context() is ctx
2333 assert address == clientSSL.getsockname()
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002334
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002335 def test_shutdown_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002336 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002337 `Connection.set_shutdown` raises `TypeError` if called with arguments
2338 other than integers.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002339 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002340 connection = Connection(Context(TLSv1_METHOD), None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002341 with pytest.raises(TypeError):
2342 connection.set_shutdown(None)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002343
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002344 def test_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002345 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002346 `Connection.shutdown` performs an SSL-level connection shutdown.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002347 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002348 server, client = loopback()
2349 assert not server.shutdown()
2350 assert server.get_shutdown() == SENT_SHUTDOWN
2351 with pytest.raises(ZeroReturnError):
2352 client.recv(1024)
2353 assert client.get_shutdown() == RECEIVED_SHUTDOWN
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04002354 client.shutdown()
Alex Chan1c0cb662017-01-30 07:13:30 +00002355 assert client.get_shutdown() == (SENT_SHUTDOWN | RECEIVED_SHUTDOWN)
2356 with pytest.raises(ZeroReturnError):
2357 server.recv(1024)
2358 assert server.get_shutdown() == (SENT_SHUTDOWN | RECEIVED_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002359
Paul Aurichc85e0862015-01-08 08:34:33 -08002360 def test_shutdown_closed(self):
2361 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002362 If the underlying socket is closed, `Connection.shutdown` propagates
2363 the write error from the low level write call.
Paul Aurichc85e0862015-01-08 08:34:33 -08002364 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002365 server, client = loopback()
Paul Aurichc85e0862015-01-08 08:34:33 -08002366 server.sock_shutdown(2)
Alex Chan1c0cb662017-01-30 07:13:30 +00002367 with pytest.raises(SysCallError) as exc:
2368 server.shutdown()
Alex Chanfb078d82017-04-20 11:16:15 +01002369 if platform == "win32":
2370 assert exc.value.args[0] == ESHUTDOWN
2371 else:
2372 assert exc.value.args[0] == EPIPE
Paul Aurichc85e0862015-01-08 08:34:33 -08002373
Glyph89389472015-04-14 17:29:26 -04002374 def test_shutdown_truncated(self):
Glyph6064ec32015-04-14 16:38:22 -04002375 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002376 If the underlying connection is truncated, `Connection.shutdown`
2377 raises an `Error`.
Glyph6064ec32015-04-14 16:38:22 -04002378 """
Glyph89389472015-04-14 17:29:26 -04002379 server_ctx = Context(TLSv1_METHOD)
2380 client_ctx = Context(TLSv1_METHOD)
2381 server_ctx.use_privatekey(
2382 load_privatekey(FILETYPE_PEM, server_key_pem))
2383 server_ctx.use_certificate(
2384 load_certificate(FILETYPE_PEM, server_cert_pem))
2385 server = Connection(server_ctx, None)
2386 client = Connection(client_ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002387 handshake_in_memory(client, server)
2388 assert not server.shutdown()
2389 with pytest.raises(WantReadError):
2390 server.shutdown()
Glyph89389472015-04-14 17:29:26 -04002391 server.bio_shutdown()
Alex Chan1c0cb662017-01-30 07:13:30 +00002392 with pytest.raises(Error):
2393 server.shutdown()
Glyph6064ec32015-04-14 16:38:22 -04002394
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002395 def test_set_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002396 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002397 `Connection.set_shutdown` sets the state of the SSL connection
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002398 shutdown process.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002399 """
David Benjamin1fbe0642019-04-15 17:05:13 -05002400 connection = Connection(Context(TLSv1_METHOD), socket_any_family())
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002401 connection.set_shutdown(RECEIVED_SHUTDOWN)
Alex Chan1c0cb662017-01-30 07:13:30 +00002402 assert connection.get_shutdown() == RECEIVED_SHUTDOWN
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002403
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002404 @skip_if_py3
2405 def test_set_shutdown_long(self):
2406 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002407 On Python 2 `Connection.set_shutdown` accepts an argument
2408 of type `long` as well as `int`.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002409 """
David Benjamin1fbe0642019-04-15 17:05:13 -05002410 connection = Connection(Context(TLSv1_METHOD), socket_any_family())
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002411 connection.set_shutdown(long(RECEIVED_SHUTDOWN))
Alex Chan1c0cb662017-01-30 07:13:30 +00002412 assert connection.get_shutdown() == RECEIVED_SHUTDOWN
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -05002413
kjavaf248592015-09-07 12:14:01 +01002414 def test_state_string(self):
2415 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002416 `Connection.state_string` verbosely describes the current state of
2417 the `Connection`.
kjavaf248592015-09-07 12:14:01 +01002418 """
Hynek Schlawackb0274ce2015-10-16 19:56:26 +02002419 server, client = socket_pair()
Alex Chan1c0cb662017-01-30 07:13:30 +00002420 server = loopback_server_factory(server)
2421 client = loopback_client_factory(client)
kjavaf248592015-09-07 12:14:01 +01002422
Alex Gaynor5af32d02016-09-24 01:52:21 -04002423 assert server.get_state_string() in [
2424 b"before/accept initialization", b"before SSL initialization"
2425 ]
2426 assert client.get_state_string() in [
2427 b"before/connect initialization", b"before SSL initialization"
2428 ]
kjavaf248592015-09-07 12:14:01 +01002429
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002430 def test_app_data(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002431 """
2432 Any object can be set as app data by passing it to
Alex Chan1c0cb662017-01-30 07:13:30 +00002433 `Connection.set_app_data` and later retrieved with
2434 `Connection.get_app_data`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002435 """
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002436 conn = Connection(Context(TLSv1_METHOD), None)
Todd Chapman4f73e4f2015-08-27 11:26:43 -04002437 assert None is conn.get_app_data()
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002438 app_data = object()
2439 conn.set_app_data(app_data)
Todd Chapman4f73e4f2015-08-27 11:26:43 -04002440 assert conn.get_app_data() is app_data
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002441
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002442 def test_makefile(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002443 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002444 `Connection.makefile` is not implemented and calling that
2445 method raises `NotImplementedError`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002446 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002447 conn = Connection(Context(TLSv1_METHOD), None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002448 with pytest.raises(NotImplementedError):
2449 conn.makefile()
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002450
Jeremy Lainé460a19d2018-05-16 19:44:19 +02002451 def test_get_certificate(self):
2452 """
2453 `Connection.get_certificate` returns the local certificate.
2454 """
2455 chain = _create_certificate_chain()
2456 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
2457
2458 context = Context(TLSv1_METHOD)
2459 context.use_certificate(scert)
2460 client = Connection(context, None)
2461 cert = client.get_certificate()
2462 assert cert is not None
2463 assert "Server Certificate" == cert.get_subject().CN
2464
2465 def test_get_certificate_none(self):
2466 """
2467 `Connection.get_certificate` returns the local certificate.
2468
2469 If there is no certificate, it returns None.
2470 """
2471 context = Context(TLSv1_METHOD)
2472 client = Connection(context, None)
2473 cert = client.get_certificate()
2474 assert cert is None
2475
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002476 def test_get_peer_cert_chain(self):
2477 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002478 `Connection.get_peer_cert_chain` returns a list of certificates
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002479 which the connected server returned for the certification verification.
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002480 """
2481 chain = _create_certificate_chain()
2482 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
2483
2484 serverContext = Context(TLSv1_METHOD)
2485 serverContext.use_privatekey(skey)
2486 serverContext.use_certificate(scert)
2487 serverContext.add_extra_chain_cert(icert)
2488 serverContext.add_extra_chain_cert(cacert)
2489 server = Connection(serverContext, None)
2490 server.set_accept_state()
2491
2492 # Create the client
2493 clientContext = Context(TLSv1_METHOD)
2494 clientContext.set_verify(VERIFY_NONE, verify_cb)
2495 client = Connection(clientContext, None)
2496 client.set_connect_state()
2497
Alex Chan1c0cb662017-01-30 07:13:30 +00002498 interact_in_memory(client, server)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002499
2500 chain = client.get_peer_cert_chain()
Alex Chan1c0cb662017-01-30 07:13:30 +00002501 assert len(chain) == 3
2502 assert "Server Certificate" == chain[0].get_subject().CN
2503 assert "Intermediate Certificate" == chain[1].get_subject().CN
2504 assert "Authority Certificate" == chain[2].get_subject().CN
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002505
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002506 def test_get_peer_cert_chain_none(self):
2507 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002508 `Connection.get_peer_cert_chain` returns `None` if the peer sends
2509 no certificate chain.
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002510 """
2511 ctx = Context(TLSv1_METHOD)
2512 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2513 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
2514 server = Connection(ctx, None)
2515 server.set_accept_state()
2516 client = Connection(Context(TLSv1_METHOD), None)
2517 client.set_connect_state()
Alex Chan1c0cb662017-01-30 07:13:30 +00002518 interact_in_memory(client, server)
2519 assert None is server.get_peer_cert_chain()
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002520
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002521 def test_get_session_unconnected(self):
2522 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002523 `Connection.get_session` returns `None` when used with an object
2524 which has not been connected.
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002525 """
2526 ctx = Context(TLSv1_METHOD)
2527 server = Connection(ctx, None)
2528 session = server.get_session()
Alex Chan1c0cb662017-01-30 07:13:30 +00002529 assert None is session
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002530
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002531 def test_server_get_session(self):
2532 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002533 On the server side of a connection, `Connection.get_session` returns a
2534 `Session` instance representing the SSL session for that connection.
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002535 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002536 server, client = loopback()
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002537 session = server.get_session()
Alex Chan1c0cb662017-01-30 07:13:30 +00002538 assert isinstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002539
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002540 def test_client_get_session(self):
2541 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002542 On the client side of a connection, `Connection.get_session`
2543 returns a `Session` instance representing the SSL session for
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002544 that connection.
2545 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002546 server, client = loopback()
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002547 session = client.get_session()
Alex Chan1c0cb662017-01-30 07:13:30 +00002548 assert isinstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002549
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002550 def test_set_session_wrong_args(self):
2551 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002552 `Connection.set_session` raises `TypeError` if called with an object
2553 that is not an instance of `Session`.
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002554 """
2555 ctx = Context(TLSv1_METHOD)
2556 connection = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002557 with pytest.raises(TypeError):
2558 connection.set_session(123)
2559 with pytest.raises(TypeError):
2560 connection.set_session("hello")
2561 with pytest.raises(TypeError):
2562 connection.set_session(object())
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002563
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002564 def test_client_set_session(self):
2565 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002566 `Connection.set_session`, when used prior to a connection being
2567 established, accepts a `Session` instance and causes an attempt to
2568 re-use the session it represents when the SSL handshake is performed.
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002569 """
2570 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2571 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
Paul Kehrer7d5a3bf2019-01-21 12:24:02 -06002572 ctx = Context(TLSv1_2_METHOD)
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002573 ctx.use_privatekey(key)
2574 ctx.use_certificate(cert)
2575 ctx.set_session_id("unity-test")
2576
2577 def makeServer(socket):
2578 server = Connection(ctx, socket)
2579 server.set_accept_state()
2580 return server
2581
Alex Chan1c0cb662017-01-30 07:13:30 +00002582 originalServer, originalClient = loopback(
2583 server_factory=makeServer)
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002584 originalSession = originalClient.get_session()
2585
2586 def makeClient(socket):
Alex Chan1c0cb662017-01-30 07:13:30 +00002587 client = loopback_client_factory(socket)
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002588 client.set_session(originalSession)
2589 return client
Alex Chan1c0cb662017-01-30 07:13:30 +00002590 resumedServer, resumedClient = loopback(
2591 server_factory=makeServer,
2592 client_factory=makeClient)
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002593
2594 # This is a proxy: in general, we have no access to any unique
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002595 # identifier for the session (new enough versions of OpenSSL expose
2596 # a hash which could be usable, but "new enough" is very, very new).
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002597 # Instead, exploit the fact that the master key is re-used if the
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002598 # session is re-used. As long as the master key for the two
2599 # connections is the same, the session was re-used!
Alex Chan1c0cb662017-01-30 07:13:30 +00002600 assert originalServer.master_key() == resumedServer.master_key()
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002601
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002602 def test_set_session_wrong_method(self):
2603 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002604 If `Connection.set_session` is passed a `Session` instance associated
2605 with a context using a different SSL method than the `Connection`
2606 is using, a `OpenSSL.SSL.Error` is raised.
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002607 """
Alex Gaynor5af32d02016-09-24 01:52:21 -04002608 # Make this work on both OpenSSL 1.0.0, which doesn't support TLSv1.2
2609 # and also on OpenSSL 1.1.0 which doesn't support SSLv3. (SSL_ST_INIT
2610 # is a way to check for 1.1.0)
Alex Gaynoraa32e712017-06-29 20:56:12 -07002611 if SSL_ST_INIT is None:
2612 v1 = TLSv1_2_METHOD
2613 v2 = TLSv1_METHOD
2614 elif hasattr(_lib, "SSLv3_method"):
Alex Gaynor5af32d02016-09-24 01:52:21 -04002615 v1 = TLSv1_METHOD
2616 v2 = SSLv3_METHOD
2617 else:
Alex Gaynoraa32e712017-06-29 20:56:12 -07002618 pytest.skip("Test requires either OpenSSL 1.1.0 or SSLv3")
Alex Gaynor5af32d02016-09-24 01:52:21 -04002619
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002620 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2621 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
Alex Gaynor5af32d02016-09-24 01:52:21 -04002622 ctx = Context(v1)
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002623 ctx.use_privatekey(key)
2624 ctx.use_certificate(cert)
2625 ctx.set_session_id("unity-test")
2626
2627 def makeServer(socket):
2628 server = Connection(ctx, socket)
2629 server.set_accept_state()
2630 return server
2631
Alex Gaynor5af32d02016-09-24 01:52:21 -04002632 def makeOriginalClient(socket):
2633 client = Connection(Context(v1), socket)
2634 client.set_connect_state()
2635 return client
2636
Alex Chan1c0cb662017-01-30 07:13:30 +00002637 originalServer, originalClient = loopback(
2638 server_factory=makeServer, client_factory=makeOriginalClient)
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002639 originalSession = originalClient.get_session()
2640
2641 def makeClient(socket):
2642 # Intentionally use a different, incompatible method here.
Alex Gaynor5af32d02016-09-24 01:52:21 -04002643 client = Connection(Context(v2), socket)
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002644 client.set_connect_state()
2645 client.set_session(originalSession)
2646 return client
2647
Alex Chan1c0cb662017-01-30 07:13:30 +00002648 with pytest.raises(Error):
2649 loopback(client_factory=makeClient, server_factory=makeServer)
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002650
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002651 def test_wantWriteError(self):
2652 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002653 `Connection` methods which generate output raise
2654 `OpenSSL.SSL.WantWriteError` if writing to the connection's BIO
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002655 fail indicating a should-write state.
2656 """
2657 client_socket, server_socket = socket_pair()
2658 # Fill up the client's send buffer so Connection won't be able to write
Jean-Paul Calderonebbff8b92014-03-22 14:20:30 -04002659 # anything. Only write a single byte at a time so we can be sure we
2660 # completely fill the buffer. Even though the socket API is allowed to
2661 # signal a short write via its return value it seems this doesn't
2662 # always happen on all platforms (FreeBSD and OS X particular) for the
2663 # very last bit of available buffer space.
2664 msg = b"x"
caternb2777a42018-08-09 15:38:13 -04002665 for i in range(1024 * 1024 * 64):
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002666 try:
2667 client_socket.send(msg)
2668 except error as e:
2669 if e.errno == EWOULDBLOCK:
2670 break
2671 raise
2672 else:
Alex Chan1c0cb662017-01-30 07:13:30 +00002673 pytest.fail(
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002674 "Failed to fill socket buffer, cannot test BIO want write")
2675
2676 ctx = Context(TLSv1_METHOD)
2677 conn = Connection(ctx, client_socket)
2678 # Client's speak first, so make it an SSL client
2679 conn.set_connect_state()
Alex Chan1c0cb662017-01-30 07:13:30 +00002680 with pytest.raises(WantWriteError):
2681 conn.do_handshake()
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002682
2683 # XXX want_read
2684
Fedor Brunner416f4a12014-03-28 13:18:38 +01002685 def test_get_finished_before_connect(self):
Fedor Brunner5747b932014-03-05 14:22:34 +01002686 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002687 `Connection.get_finished` returns `None` before TLS handshake
2688 is completed.
Fedor Brunner5747b932014-03-05 14:22:34 +01002689 """
Fedor Brunner5747b932014-03-05 14:22:34 +01002690 ctx = Context(TLSv1_METHOD)
2691 connection = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002692 assert connection.get_finished() is None
Fedor Brunner416f4a12014-03-28 13:18:38 +01002693
2694 def test_get_peer_finished_before_connect(self):
2695 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002696 `Connection.get_peer_finished` returns `None` before TLS handshake
2697 is completed.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002698 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002699 ctx = Context(TLSv1_METHOD)
2700 connection = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002701 assert connection.get_peer_finished() is None
Fedor Brunner5747b932014-03-05 14:22:34 +01002702
Fedor Brunner416f4a12014-03-28 13:18:38 +01002703 def test_get_finished(self):
2704 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002705 `Connection.get_finished` method returns the TLS Finished message send
2706 from client, or server. Finished messages are send during
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002707 TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002708 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002709 server, client = loopback()
Fedor Brunner416f4a12014-03-28 13:18:38 +01002710
Alex Chan1c0cb662017-01-30 07:13:30 +00002711 assert server.get_finished() is not None
2712 assert len(server.get_finished()) > 0
Fedor Brunner416f4a12014-03-28 13:18:38 +01002713
2714 def test_get_peer_finished(self):
2715 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002716 `Connection.get_peer_finished` method returns the TLS Finished
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002717 message received from client, or server. Finished messages are send
2718 during TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002719 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002720 server, client = loopback()
Fedor Brunner416f4a12014-03-28 13:18:38 +01002721
Alex Chan1c0cb662017-01-30 07:13:30 +00002722 assert server.get_peer_finished() is not None
2723 assert len(server.get_peer_finished()) > 0
Fedor Brunner5747b932014-03-05 14:22:34 +01002724
Fedor Brunner416f4a12014-03-28 13:18:38 +01002725 def test_tls_finished_message_symmetry(self):
2726 """
Hynek Schlawackdddd1112015-09-05 21:12:30 +02002727 The TLS Finished message send by server must be the TLS Finished
2728 message received by client.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002729
Hynek Schlawackdddd1112015-09-05 21:12:30 +02002730 The TLS Finished message send by client must be the TLS Finished
2731 message received by server.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002732 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002733 server, client = loopback()
Fedor Brunner416f4a12014-03-28 13:18:38 +01002734
Alex Chan1c0cb662017-01-30 07:13:30 +00002735 assert server.get_finished() == client.get_peer_finished()
2736 assert client.get_finished() == server.get_peer_finished()
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002737
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002738 def test_get_cipher_name_before_connect(self):
2739 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002740 `Connection.get_cipher_name` returns `None` if no connection
2741 has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002742 """
2743 ctx = Context(TLSv1_METHOD)
2744 conn = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002745 assert conn.get_cipher_name() is None
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002746
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002747 def test_get_cipher_name(self):
2748 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002749 `Connection.get_cipher_name` returns a `unicode` string giving the
2750 name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002751 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002752 server, client = loopback()
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002753 server_cipher_name, client_cipher_name = \
2754 server.get_cipher_name(), client.get_cipher_name()
2755
Alex Chan1c0cb662017-01-30 07:13:30 +00002756 assert isinstance(server_cipher_name, text_type)
2757 assert isinstance(client_cipher_name, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002758
Alex Chan1c0cb662017-01-30 07:13:30 +00002759 assert server_cipher_name == client_cipher_name
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002760
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002761 def test_get_cipher_version_before_connect(self):
2762 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002763 `Connection.get_cipher_version` returns `None` if no connection
2764 has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002765 """
2766 ctx = Context(TLSv1_METHOD)
2767 conn = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002768 assert conn.get_cipher_version() is None
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002769
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002770 def test_get_cipher_version(self):
2771 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002772 `Connection.get_cipher_version` returns a `unicode` string giving
2773 the protocol name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002774 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002775 server, client = loopback()
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002776 server_cipher_version, client_cipher_version = \
2777 server.get_cipher_version(), client.get_cipher_version()
2778
Alex Chan1c0cb662017-01-30 07:13:30 +00002779 assert isinstance(server_cipher_version, text_type)
2780 assert isinstance(client_cipher_version, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002781
Alex Chan1c0cb662017-01-30 07:13:30 +00002782 assert server_cipher_version == client_cipher_version
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002783
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002784 def test_get_cipher_bits_before_connect(self):
2785 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002786 `Connection.get_cipher_bits` returns `None` if no connection has
2787 been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002788 """
2789 ctx = Context(TLSv1_METHOD)
2790 conn = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002791 assert conn.get_cipher_bits() is None
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002792
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002793 def test_get_cipher_bits(self):
2794 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002795 `Connection.get_cipher_bits` returns the number of secret bits
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002796 of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002797 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002798 server, client = loopback()
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002799 server_cipher_bits, client_cipher_bits = \
2800 server.get_cipher_bits(), client.get_cipher_bits()
2801
Alex Chan1c0cb662017-01-30 07:13:30 +00002802 assert isinstance(server_cipher_bits, int)
2803 assert isinstance(client_cipher_bits, int)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002804
Alex Chan1c0cb662017-01-30 07:13:30 +00002805 assert server_cipher_bits == client_cipher_bits
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002806
Jim Shaverabff1882015-05-27 09:15:55 -04002807 def test_get_protocol_version_name(self):
2808 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002809 `Connection.get_protocol_version_name()` returns a string giving the
2810 protocol version of the current connection.
Jim Shaverabff1882015-05-27 09:15:55 -04002811 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002812 server, client = loopback()
Jim Shaverabff1882015-05-27 09:15:55 -04002813 client_protocol_version_name = client.get_protocol_version_name()
2814 server_protocol_version_name = server.get_protocol_version_name()
2815
Alex Chan1c0cb662017-01-30 07:13:30 +00002816 assert isinstance(server_protocol_version_name, text_type)
2817 assert isinstance(client_protocol_version_name, text_type)
Jim Shaverabff1882015-05-27 09:15:55 -04002818
Alex Chan1c0cb662017-01-30 07:13:30 +00002819 assert server_protocol_version_name == client_protocol_version_name
Jim Shaverabff1882015-05-27 09:15:55 -04002820
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002821 def test_get_protocol_version(self):
2822 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002823 `Connection.get_protocol_version()` returns an integer
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002824 giving the protocol version of the current connection.
2825 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002826 server, client = loopback()
Jim Shaver85a4dff2015-04-27 17:42:46 -04002827 client_protocol_version = client.get_protocol_version()
2828 server_protocol_version = server.get_protocol_version()
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002829
Alex Chan1c0cb662017-01-30 07:13:30 +00002830 assert isinstance(server_protocol_version, int)
2831 assert isinstance(client_protocol_version, int)
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002832
Alex Chan1c0cb662017-01-30 07:13:30 +00002833 assert server_protocol_version == client_protocol_version
2834
2835 def test_wantReadError(self):
2836 """
2837 `Connection.bio_read` raises `OpenSSL.SSL.WantReadError` if there are
2838 no bytes available to be read from the BIO.
2839 """
2840 ctx = Context(TLSv1_METHOD)
2841 conn = Connection(ctx, None)
2842 with pytest.raises(WantReadError):
2843 conn.bio_read(1024)
2844
Alex Chanfb078d82017-04-20 11:16:15 +01002845 @pytest.mark.parametrize('bufsize', [1.0, None, object(), 'bufsize'])
2846 def test_bio_read_wrong_args(self, bufsize):
2847 """
2848 `Connection.bio_read` raises `TypeError` if passed a non-integer
2849 argument.
2850 """
2851 ctx = Context(TLSv1_METHOD)
2852 conn = Connection(ctx, None)
2853 with pytest.raises(TypeError):
2854 conn.bio_read(bufsize)
2855
Alex Chan1c0cb662017-01-30 07:13:30 +00002856 def test_buffer_size(self):
2857 """
2858 `Connection.bio_read` accepts an integer giving the maximum number
2859 of bytes to read and return.
2860 """
2861 ctx = Context(TLSv1_METHOD)
2862 conn = Connection(ctx, None)
2863 conn.set_connect_state()
2864 try:
2865 conn.do_handshake()
2866 except WantReadError:
2867 pass
2868 data = conn.bio_read(2)
2869 assert 2 == len(data)
2870
2871 @skip_if_py3
2872 def test_buffer_size_long(self):
2873 """
2874 On Python 2 `Connection.bio_read` accepts values of type `long` as
2875 well as `int`.
2876 """
2877 ctx = Context(TLSv1_METHOD)
2878 conn = Connection(ctx, None)
2879 conn.set_connect_state()
2880 try:
2881 conn.do_handshake()
2882 except WantReadError:
2883 pass
2884 data = conn.bio_read(long(2))
2885 assert 2 == len(data)
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002886
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002887
Alex Chanb7480992017-01-30 14:04:47 +00002888class TestConnectionGetCipherList(object):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002889 """
Alex Chanb7480992017-01-30 14:04:47 +00002890 Tests for `Connection.get_cipher_list`.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002891 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002892 def test_result(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002893 """
Alex Chanb7480992017-01-30 14:04:47 +00002894 `Connection.get_cipher_list` returns a list of `bytes` giving the
2895 names of the ciphers which might be used.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002896 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002897 connection = Connection(Context(TLSv1_METHOD), None)
2898 ciphers = connection.get_cipher_list()
Alex Chanb7480992017-01-30 14:04:47 +00002899 assert isinstance(ciphers, list)
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002900 for cipher in ciphers:
Alex Chanb7480992017-01-30 14:04:47 +00002901 assert isinstance(cipher, str)
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002902
2903
Maximilian Hils868dc3c2017-02-10 14:56:55 +01002904class VeryLarge(bytes):
2905 """
2906 Mock object so that we don't have to allocate 2**31 bytes
2907 """
2908 def __len__(self):
2909 return 2**31
2910
2911
Alex Chanb7480992017-01-30 14:04:47 +00002912class TestConnectionSend(object):
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002913 """
Alex Chanb7480992017-01-30 14:04:47 +00002914 Tests for `Connection.send`.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002915 """
2916 def test_wrong_args(self):
2917 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002918 When called with arguments other than string argument for its first
Alex Chanb7480992017-01-30 14:04:47 +00002919 parameter, `Connection.send` raises `TypeError`.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002920 """
2921 connection = Connection(Context(TLSv1_METHOD), None)
Alex Chanb7480992017-01-30 14:04:47 +00002922 with pytest.raises(TypeError):
2923 connection.send(object())
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002924
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002925 def test_short_bytes(self):
2926 """
Alex Chanb7480992017-01-30 14:04:47 +00002927 When passed a short byte string, `Connection.send` transmits all of it
2928 and returns the number of bytes sent.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002929 """
Alex Chanb7480992017-01-30 14:04:47 +00002930 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002931 count = server.send(b'xy')
Alex Chanb7480992017-01-30 14:04:47 +00002932 assert count == 2
2933 assert client.recv(2) == b'xy'
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002934
Abraham Martinef063482015-03-25 14:06:24 +00002935 def test_text(self):
2936 """
Alex Chanb7480992017-01-30 14:04:47 +00002937 When passed a text, `Connection.send` transmits all of it and
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002938 returns the number of bytes sent. It also raises a DeprecationWarning.
Abraham Martinef063482015-03-25 14:06:24 +00002939 """
Alex Chanb7480992017-01-30 14:04:47 +00002940 server, client = loopback()
2941 with pytest.warns(DeprecationWarning) as w:
Abraham Martinef063482015-03-25 14:06:24 +00002942 simplefilter("always")
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002943 count = server.send(b"xy".decode("ascii"))
Alex Chanb7480992017-01-30 14:04:47 +00002944 assert (
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002945 "{0} for buf is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002946 WARNING_TYPE_EXPECTED
Alex Chanb7480992017-01-30 14:04:47 +00002947 ) == str(w[-1].message))
2948 assert count == 2
2949 assert client.recv(2) == b'xy'
Abraham Martinef063482015-03-25 14:06:24 +00002950
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002951 def test_short_memoryview(self):
2952 """
2953 When passed a memoryview onto a small number of bytes,
Alex Chanb7480992017-01-30 14:04:47 +00002954 `Connection.send` transmits all of them and returns the number
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002955 of bytes sent.
2956 """
Alex Chanb7480992017-01-30 14:04:47 +00002957 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002958 count = server.send(memoryview(b'xy'))
Alex Chanb7480992017-01-30 14:04:47 +00002959 assert count == 2
2960 assert client.recv(2) == b'xy'
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002961
Hynek Schlawack8e94f1b2015-09-05 21:31:00 +02002962 @skip_if_py3
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002963 def test_short_buffer(self):
2964 """
2965 When passed a buffer containing a small number of bytes,
Alex Chanb7480992017-01-30 14:04:47 +00002966 `Connection.send` transmits all of them and returns the number
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002967 of bytes sent.
2968 """
Alex Chanb7480992017-01-30 14:04:47 +00002969 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002970 count = server.send(buffer(b'xy'))
Alex Chanb7480992017-01-30 14:04:47 +00002971 assert count == 2
2972 assert client.recv(2) == b'xy'
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02002973
Maximilian Hils868dc3c2017-02-10 14:56:55 +01002974 @pytest.mark.skipif(
2975 sys.maxsize < 2**31,
2976 reason="sys.maxsize < 2**31 - test requires 64 bit"
2977 )
2978 def test_buf_too_large(self):
2979 """
2980 When passed a buffer containing >= 2**31 bytes,
2981 `Connection.send` bails out as SSL_write only
2982 accepts an int for the buffer length.
2983 """
2984 connection = Connection(Context(TLSv1_METHOD), None)
2985 with pytest.raises(ValueError) as exc_info:
2986 connection.send(VeryLarge())
2987 exc_info.match(r"Cannot send more than .+ bytes at once")
2988
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05002989
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002990def _make_memoryview(size):
2991 """
2992 Create a new ``memoryview`` wrapped around a ``bytearray`` of the given
2993 size.
2994 """
2995 return memoryview(bytearray(size))
2996
2997
Alex Chanb7480992017-01-30 14:04:47 +00002998class TestConnectionRecvInto(object):
Cory Benfield62d10332014-06-15 10:03:41 +01002999 """
Alex Chanb7480992017-01-30 14:04:47 +00003000 Tests for `Connection.recv_into`.
Cory Benfield62d10332014-06-15 10:03:41 +01003001 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003002 def _no_length_test(self, factory):
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04003003 """
Alex Chanb7480992017-01-30 14:04:47 +00003004 Assert that when the given buffer is passed to `Connection.recv_into`,
3005 whatever bytes are available to be received that fit into that buffer
3006 are written into that buffer.
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04003007 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003008 output_buffer = factory(5)
3009
Alex Chanb7480992017-01-30 14:04:47 +00003010 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04003011 server.send(b'xy')
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04003012
Alex Chanb7480992017-01-30 14:04:47 +00003013 assert client.recv_into(output_buffer) == 2
3014 assert output_buffer == bytearray(b'xy\x00\x00\x00')
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04003015
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04003016 def test_bytearray_no_length(self):
Cory Benfield62d10332014-06-15 10:03:41 +01003017 """
Alex Chanb7480992017-01-30 14:04:47 +00003018 `Connection.recv_into` can be passed a `bytearray` instance and data
3019 in the receive buffer is written to it.
Cory Benfield62d10332014-06-15 10:03:41 +01003020 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003021 self._no_length_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01003022
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003023 def _respects_length_test(self, factory):
Cory Benfield62d10332014-06-15 10:03:41 +01003024 """
Alex Chanb7480992017-01-30 14:04:47 +00003025 Assert that when the given buffer is passed to `Connection.recv_into`
3026 along with a value for `nbytes` that is less than the size of that
3027 buffer, only `nbytes` bytes are written into the buffer.
Cory Benfield62d10332014-06-15 10:03:41 +01003028 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003029 output_buffer = factory(10)
3030
Alex Chanb7480992017-01-30 14:04:47 +00003031 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04003032 server.send(b'abcdefghij')
Cory Benfield62d10332014-06-15 10:03:41 +01003033
Alex Chanb7480992017-01-30 14:04:47 +00003034 assert client.recv_into(output_buffer, 5) == 5
3035 assert output_buffer == bytearray(b'abcde\x00\x00\x00\x00\x00')
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04003036
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04003037 def test_bytearray_respects_length(self):
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04003038 """
Alex Chanb7480992017-01-30 14:04:47 +00003039 When called with a `bytearray` instance, `Connection.recv_into`
3040 respects the `nbytes` parameter and doesn't copy in more than that
3041 number of bytes.
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04003042 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003043 self._respects_length_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01003044
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003045 def _doesnt_overfill_test(self, factory):
Cory Benfield62d10332014-06-15 10:03:41 +01003046 """
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04003047 Assert that if there are more bytes available to be read from the
3048 receive buffer than would fit into the buffer passed to
Alex Chanb7480992017-01-30 14:04:47 +00003049 `Connection.recv_into`, only as many as fit are written into it.
Cory Benfield62d10332014-06-15 10:03:41 +01003050 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003051 output_buffer = factory(5)
3052
Alex Chanb7480992017-01-30 14:04:47 +00003053 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04003054 server.send(b'abcdefghij')
Cory Benfield62d10332014-06-15 10:03:41 +01003055
Alex Chanb7480992017-01-30 14:04:47 +00003056 assert client.recv_into(output_buffer) == 5
3057 assert output_buffer == bytearray(b'abcde')
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04003058 rest = client.recv(5)
Alex Chanb7480992017-01-30 14:04:47 +00003059 assert b'fghij' == rest
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04003060
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04003061 def test_bytearray_doesnt_overfill(self):
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04003062 """
Alex Chanb7480992017-01-30 14:04:47 +00003063 When called with a `bytearray` instance, `Connection.recv_into`
3064 respects the size of the array and doesn't write more bytes into it
3065 than will fit.
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04003066 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003067 self._doesnt_overfill_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01003068
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04003069 def test_bytearray_really_doesnt_overfill(self):
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003070 """
Alex Chanb7480992017-01-30 14:04:47 +00003071 When called with a `bytearray` instance and an `nbytes` value that is
3072 too large, `Connection.recv_into` respects the size of the array and
3073 not the `nbytes` value and doesn't write more bytes into the buffer
3074 than will fit.
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003075 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003076 self._doesnt_overfill_test(bytearray)
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003077
Maximilian Hils1d95dea2015-08-17 19:27:20 +02003078 def test_peek(self):
Alex Chanb7480992017-01-30 14:04:47 +00003079 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04003080 server.send(b'xy')
Maximilian Hils1d95dea2015-08-17 19:27:20 +02003081
3082 for _ in range(2):
3083 output_buffer = bytearray(5)
Alex Chanb7480992017-01-30 14:04:47 +00003084 assert client.recv_into(output_buffer, flags=MSG_PEEK) == 2
3085 assert output_buffer == bytearray(b'xy\x00\x00\x00')
Maximilian Hils1d95dea2015-08-17 19:27:20 +02003086
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003087 def test_memoryview_no_length(self):
3088 """
Alex Chanb7480992017-01-30 14:04:47 +00003089 `Connection.recv_into` can be passed a `memoryview` instance and data
3090 in the receive buffer is written to it.
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003091 """
3092 self._no_length_test(_make_memoryview)
Maximilian Hils1d95dea2015-08-17 19:27:20 +02003093
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003094 def test_memoryview_respects_length(self):
3095 """
Alex Chanb7480992017-01-30 14:04:47 +00003096 When called with a `memoryview` instance, `Connection.recv_into`
3097 respects the ``nbytes`` parameter and doesn't copy more than that
3098 number of bytes in.
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003099 """
3100 self._respects_length_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01003101
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003102 def test_memoryview_doesnt_overfill(self):
3103 """
Alex Chanb7480992017-01-30 14:04:47 +00003104 When called with a `memoryview` instance, `Connection.recv_into`
3105 respects the size of the array and doesn't write more bytes into it
3106 than will fit.
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003107 """
3108 self._doesnt_overfill_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01003109
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003110 def test_memoryview_really_doesnt_overfill(self):
3111 """
Alex Chanb7480992017-01-30 14:04:47 +00003112 When called with a `memoryview` instance and an `nbytes` value that is
3113 too large, `Connection.recv_into` respects the size of the array and
3114 not the `nbytes` value and doesn't write more bytes into the buffer
3115 than will fit.
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003116 """
3117 self._doesnt_overfill_test(_make_memoryview)
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003118
Cory Benfield62d10332014-06-15 10:03:41 +01003119
Alex Chanb7480992017-01-30 14:04:47 +00003120class TestConnectionSendall(object):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003121 """
Alex Chanb7480992017-01-30 14:04:47 +00003122 Tests for `Connection.sendall`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003123 """
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003124 def test_wrong_args(self):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003125 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003126 When called with arguments other than a string argument for its first
Alex Chanb7480992017-01-30 14:04:47 +00003127 parameter, `Connection.sendall` raises `TypeError`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003128 """
3129 connection = Connection(Context(TLSv1_METHOD), None)
Alex Chanb7480992017-01-30 14:04:47 +00003130 with pytest.raises(TypeError):
3131 connection.sendall(object())
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003132
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003133 def test_short(self):
3134 """
Alex Chanb7480992017-01-30 14:04:47 +00003135 `Connection.sendall` transmits all of the bytes in the string
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003136 passed to it.
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003137 """
Alex Chanb7480992017-01-30 14:04:47 +00003138 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04003139 server.sendall(b'x')
Alex Chanb7480992017-01-30 14:04:47 +00003140 assert client.recv(1) == b'x'
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003141
Abraham Martinef063482015-03-25 14:06:24 +00003142 def test_text(self):
3143 """
Alex Chanb7480992017-01-30 14:04:47 +00003144 `Connection.sendall` transmits all the content in the string passed
3145 to it, raising a DeprecationWarning in case of this being a text.
Abraham Martinef063482015-03-25 14:06:24 +00003146 """
Alex Chanb7480992017-01-30 14:04:47 +00003147 server, client = loopback()
3148 with pytest.warns(DeprecationWarning) as w:
Abraham Martinef063482015-03-25 14:06:24 +00003149 simplefilter("always")
Jean-Paul Calderone8dc37a12015-03-29 08:16:52 -04003150 server.sendall(b"x".decode("ascii"))
Alex Chanb7480992017-01-30 14:04:47 +00003151 assert (
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04003152 "{0} for buf is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04003153 WARNING_TYPE_EXPECTED
Alex Chanb7480992017-01-30 14:04:47 +00003154 ) == str(w[-1].message))
3155 assert client.recv(1) == b"x"
Abraham Martinef063482015-03-25 14:06:24 +00003156
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003157 def test_short_memoryview(self):
3158 """
3159 When passed a memoryview onto a small number of bytes,
Alex Chanb7480992017-01-30 14:04:47 +00003160 `Connection.sendall` transmits all of them.
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003161 """
Alex Chanb7480992017-01-30 14:04:47 +00003162 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04003163 server.sendall(memoryview(b'x'))
Alex Chanb7480992017-01-30 14:04:47 +00003164 assert client.recv(1) == b'x'
Abraham Martinef063482015-03-25 14:06:24 +00003165
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003166 @skip_if_py3
3167 def test_short_buffers(self):
3168 """
3169 When passed a buffer containing a small number of bytes,
Alex Chanb7480992017-01-30 14:04:47 +00003170 `Connection.sendall` transmits all of them.
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003171 """
Alex Chanb7480992017-01-30 14:04:47 +00003172 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04003173 server.sendall(buffer(b'x'))
Alex Chanb7480992017-01-30 14:04:47 +00003174 assert client.recv(1) == b'x'
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02003175
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003176 def test_long(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003177 """
Alex Chanb7480992017-01-30 14:04:47 +00003178 `Connection.sendall` transmits all the bytes in the string passed to it
3179 even if this requires multiple calls of an underlying write function.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003180 """
Alex Chanb7480992017-01-30 14:04:47 +00003181 server, client = loopback()
Jean-Paul Calderone6241c702010-09-16 19:59:24 -04003182 # Should be enough, underlying SSL_write should only do 16k at a time.
Hynek Schlawack35618382015-09-05 21:54:25 +02003183 # On Windows, after 32k of bytes the write will block (forever
3184 # - because no one is yet reading).
Alex Gaynore7f51982016-09-11 11:48:14 -04003185 message = b'x' * (1024 * 32 - 1) + b'y'
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003186 server.sendall(message)
3187 accum = []
3188 received = 0
3189 while received < len(message):
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04003190 data = client.recv(1024)
3191 accum.append(data)
3192 received += len(data)
Alex Chanb7480992017-01-30 14:04:47 +00003193 assert message == b''.join(accum)
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003194
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003195 def test_closed(self):
3196 """
Alex Chanb7480992017-01-30 14:04:47 +00003197 If the underlying socket is closed, `Connection.sendall` propagates the
3198 write error from the low level write call.
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003199 """
Alex Chanb7480992017-01-30 14:04:47 +00003200 server, client = loopback()
Jean-Paul Calderone05d43e82010-09-24 18:01:36 -04003201 server.sock_shutdown(2)
Alex Chanb7480992017-01-30 14:04:47 +00003202 with pytest.raises(SysCallError) as err:
3203 server.sendall(b"hello, world")
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +02003204 if platform == "win32":
Alex Chanb7480992017-01-30 14:04:47 +00003205 assert err.value.args[0] == ESHUTDOWN
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +02003206 else:
Alex Chanb7480992017-01-30 14:04:47 +00003207 assert err.value.args[0] == EPIPE
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003208
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003209
Alex Chanb7480992017-01-30 14:04:47 +00003210class TestConnectionRenegotiate(object):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003211 """
3212 Tests for SSL renegotiation APIs.
3213 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003214 def test_total_renegotiations(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003215 """
Alex Chanb7480992017-01-30 14:04:47 +00003216 `Connection.total_renegotiations` returns `0` before any renegotiations
3217 have happened.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003218 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003219 connection = Connection(Context(TLSv1_METHOD), None)
Alex Chanb7480992017-01-30 14:04:47 +00003220 assert connection.total_renegotiations() == 0
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003221
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003222 def test_renegotiate(self):
3223 """
3224 Go through a complete renegotiation cycle.
3225 """
Paul Kehrer7d5a3bf2019-01-21 12:24:02 -06003226 server, client = loopback(
3227 lambda s: loopback_server_factory(s, TLSv1_2_METHOD),
3228 lambda s: loopback_client_factory(s, TLSv1_2_METHOD),
3229 )
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003230
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003231 server.send(b"hello world")
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003232
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003233 assert b"hello world" == client.recv(len(b"hello world"))
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003234
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003235 assert 0 == server.total_renegotiations()
3236 assert False is server.renegotiate_pending()
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003237
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003238 assert True is server.renegotiate()
3239
3240 assert True is server.renegotiate_pending()
3241
3242 server.setblocking(False)
3243 client.setblocking(False)
3244
3245 client.do_handshake()
3246 server.do_handshake()
3247
3248 assert 1 == server.total_renegotiations()
3249 while False is server.renegotiate_pending():
3250 pass
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003251
3252
Alex Chanb7480992017-01-30 14:04:47 +00003253class TestError(object):
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003254 """
Alex Chanb7480992017-01-30 14:04:47 +00003255 Unit tests for `OpenSSL.SSL.Error`.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003256 """
3257 def test_type(self):
3258 """
Alex Chanb7480992017-01-30 14:04:47 +00003259 `Error` is an exception type.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003260 """
Alex Chanb7480992017-01-30 14:04:47 +00003261 assert issubclass(Error, Exception)
3262 assert Error.__name__ == 'Error'
Rick Deane15b1472009-07-09 15:53:42 -05003263
3264
Alex Chanb7480992017-01-30 14:04:47 +00003265class TestConstants(object):
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003266 """
Alex Chanb7480992017-01-30 14:04:47 +00003267 Tests for the values of constants exposed in `OpenSSL.SSL`.
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003268
3269 These are values defined by OpenSSL intended only to be used as flags to
3270 OpenSSL APIs. The only assertions it seems can be made about them is
3271 their values.
3272 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003273 @pytest.mark.skipif(
3274 OP_NO_QUERY_MTU is None,
3275 reason="OP_NO_QUERY_MTU unavailable - OpenSSL version may be too old"
3276 )
3277 def test_op_no_query_mtu(self):
3278 """
Alex Chanb7480992017-01-30 14:04:47 +00003279 The value of `OpenSSL.SSL.OP_NO_QUERY_MTU` is 0x1000, the value
3280 of `SSL_OP_NO_QUERY_MTU` defined by `openssl/ssl.h`.
Hynek Schlawack35618382015-09-05 21:54:25 +02003281 """
Alex Chanb7480992017-01-30 14:04:47 +00003282 assert OP_NO_QUERY_MTU == 0x1000
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003283
Hynek Schlawack35618382015-09-05 21:54:25 +02003284 @pytest.mark.skipif(
3285 OP_COOKIE_EXCHANGE is None,
3286 reason="OP_COOKIE_EXCHANGE unavailable - "
3287 "OpenSSL version may be too old"
3288 )
3289 def test_op_cookie_exchange(self):
3290 """
Alex Chanb7480992017-01-30 14:04:47 +00003291 The value of `OpenSSL.SSL.OP_COOKIE_EXCHANGE` is 0x2000, the
3292 value of `SSL_OP_COOKIE_EXCHANGE` defined by `openssl/ssl.h`.
Hynek Schlawack35618382015-09-05 21:54:25 +02003293 """
Alex Chanb7480992017-01-30 14:04:47 +00003294 assert OP_COOKIE_EXCHANGE == 0x2000
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003295
Hynek Schlawack35618382015-09-05 21:54:25 +02003296 @pytest.mark.skipif(
3297 OP_NO_TICKET is None,
3298 reason="OP_NO_TICKET unavailable - OpenSSL version may be too old"
3299 )
3300 def test_op_no_ticket(self):
3301 """
Alex Chanb7480992017-01-30 14:04:47 +00003302 The value of `OpenSSL.SSL.OP_NO_TICKET` is 0x4000, the value of
3303 `SSL_OP_NO_TICKET` defined by `openssl/ssl.h`.
Hynek Schlawack35618382015-09-05 21:54:25 +02003304 """
Alex Chanb7480992017-01-30 14:04:47 +00003305 assert OP_NO_TICKET == 0x4000
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003306
Hynek Schlawack35618382015-09-05 21:54:25 +02003307 @pytest.mark.skipif(
3308 OP_NO_COMPRESSION is None,
3309 reason="OP_NO_COMPRESSION unavailable - OpenSSL version may be too old"
3310 )
3311 def test_op_no_compression(self):
3312 """
Alex Chanb7480992017-01-30 14:04:47 +00003313 The value of `OpenSSL.SSL.OP_NO_COMPRESSION` is 0x20000, the
3314 value of `SSL_OP_NO_COMPRESSION` defined by `openssl/ssl.h`.
Hynek Schlawack35618382015-09-05 21:54:25 +02003315 """
Alex Chanb7480992017-01-30 14:04:47 +00003316 assert OP_NO_COMPRESSION == 0x20000
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04003317
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003318 def test_sess_cache_off(self):
3319 """
Alex Chanb7480992017-01-30 14:04:47 +00003320 The value of `OpenSSL.SSL.SESS_CACHE_OFF` 0x0, the value of
3321 `SSL_SESS_CACHE_OFF` defined by `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003322 """
Alex Chanb7480992017-01-30 14:04:47 +00003323 assert 0x0 == SESS_CACHE_OFF
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003324
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003325 def test_sess_cache_client(self):
3326 """
Alex Chanb7480992017-01-30 14:04:47 +00003327 The value of `OpenSSL.SSL.SESS_CACHE_CLIENT` 0x1, the value of
3328 `SSL_SESS_CACHE_CLIENT` defined by `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003329 """
Alex Chanb7480992017-01-30 14:04:47 +00003330 assert 0x1 == SESS_CACHE_CLIENT
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003331
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003332 def test_sess_cache_server(self):
3333 """
Alex Chanb7480992017-01-30 14:04:47 +00003334 The value of `OpenSSL.SSL.SESS_CACHE_SERVER` 0x2, the value of
3335 `SSL_SESS_CACHE_SERVER` defined by `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003336 """
Alex Chanb7480992017-01-30 14:04:47 +00003337 assert 0x2 == SESS_CACHE_SERVER
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003338
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003339 def test_sess_cache_both(self):
3340 """
Alex Chanb7480992017-01-30 14:04:47 +00003341 The value of `OpenSSL.SSL.SESS_CACHE_BOTH` 0x3, the value of
3342 `SSL_SESS_CACHE_BOTH` defined by `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003343 """
Alex Chanb7480992017-01-30 14:04:47 +00003344 assert 0x3 == SESS_CACHE_BOTH
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003345
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003346 def test_sess_cache_no_auto_clear(self):
3347 """
Alex Chanb7480992017-01-30 14:04:47 +00003348 The value of `OpenSSL.SSL.SESS_CACHE_NO_AUTO_CLEAR` 0x80, the
3349 value of `SSL_SESS_CACHE_NO_AUTO_CLEAR` defined by
3350 `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003351 """
Alex Chanb7480992017-01-30 14:04:47 +00003352 assert 0x80 == SESS_CACHE_NO_AUTO_CLEAR
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003353
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003354 def test_sess_cache_no_internal_lookup(self):
3355 """
Alex Chanb7480992017-01-30 14:04:47 +00003356 The value of `OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_LOOKUP` 0x100,
3357 the value of `SSL_SESS_CACHE_NO_INTERNAL_LOOKUP` defined by
3358 `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003359 """
Alex Chanb7480992017-01-30 14:04:47 +00003360 assert 0x100 == SESS_CACHE_NO_INTERNAL_LOOKUP
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003361
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003362 def test_sess_cache_no_internal_store(self):
3363 """
Alex Chanb7480992017-01-30 14:04:47 +00003364 The value of `OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_STORE` 0x200,
3365 the value of `SSL_SESS_CACHE_NO_INTERNAL_STORE` defined by
3366 `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003367 """
Alex Chanb7480992017-01-30 14:04:47 +00003368 assert 0x200 == SESS_CACHE_NO_INTERNAL_STORE
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003369
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003370 def test_sess_cache_no_internal(self):
3371 """
Alex Chanb7480992017-01-30 14:04:47 +00003372 The value of `OpenSSL.SSL.SESS_CACHE_NO_INTERNAL` 0x300, the
3373 value of `SSL_SESS_CACHE_NO_INTERNAL` defined by
3374 `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003375 """
Alex Chanb7480992017-01-30 14:04:47 +00003376 assert 0x300 == SESS_CACHE_NO_INTERNAL
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003377
3378
Alex Chanb7480992017-01-30 14:04:47 +00003379class TestMemoryBIO(object):
Rick Deanb71c0d22009-04-01 14:09:23 -05003380 """
Alex Chanb7480992017-01-30 14:04:47 +00003381 Tests for `OpenSSL.SSL.Connection` using a memory BIO.
Rick Deanb71c0d22009-04-01 14:09:23 -05003382 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003383 def _server(self, sock):
3384 """
Alex Chanb7480992017-01-30 14:04:47 +00003385 Create a new server-side SSL `Connection` object wrapped around `sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003386 """
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003387 # Create the server side Connection. This is mostly setup boilerplate
3388 # - use TLSv1, use a particular certificate, etc.
3389 server_ctx = Context(TLSv1_METHOD)
Alex Gaynor43307782015-09-04 09:05:45 -04003390 server_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE)
Hynek Schlawack35618382015-09-05 21:54:25 +02003391 server_ctx.set_verify(
3392 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT | VERIFY_CLIENT_ONCE,
3393 verify_cb
3394 )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003395 server_store = server_ctx.get_cert_store()
Hynek Schlawack35618382015-09-05 21:54:25 +02003396 server_ctx.use_privatekey(
3397 load_privatekey(FILETYPE_PEM, server_key_pem))
3398 server_ctx.use_certificate(
3399 load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003400 server_ctx.check_privatekey()
3401 server_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Hynek Schlawack35618382015-09-05 21:54:25 +02003402 # Here the Connection is actually created. If None is passed as the
3403 # 2nd parameter, it indicates a memory BIO should be created.
Rick Deanb1ccd562009-07-09 23:52:39 -05003404 server_conn = Connection(server_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003405 server_conn.set_accept_state()
3406 return server_conn
3407
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003408 def _client(self, sock):
3409 """
Alex Chanb7480992017-01-30 14:04:47 +00003410 Create a new client-side SSL `Connection` object wrapped around `sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003411 """
3412 # Now create the client side Connection. Similar boilerplate to the
3413 # above.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003414 client_ctx = Context(TLSv1_METHOD)
Alex Gaynor43307782015-09-04 09:05:45 -04003415 client_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE)
Hynek Schlawack35618382015-09-05 21:54:25 +02003416 client_ctx.set_verify(
3417 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT | VERIFY_CLIENT_ONCE,
3418 verify_cb
3419 )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003420 client_store = client_ctx.get_cert_store()
Hynek Schlawack35618382015-09-05 21:54:25 +02003421 client_ctx.use_privatekey(
3422 load_privatekey(FILETYPE_PEM, client_key_pem))
3423 client_ctx.use_certificate(
3424 load_certificate(FILETYPE_PEM, client_cert_pem))
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003425 client_ctx.check_privatekey()
3426 client_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05003427 client_conn = Connection(client_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003428 client_conn.set_connect_state()
3429 return client_conn
3430
Alex Chanb7480992017-01-30 14:04:47 +00003431 def test_memory_connect(self):
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003432 """
Alex Chanb7480992017-01-30 14:04:47 +00003433 Two `Connection`s which use memory BIOs can be manually connected by
3434 reading from the output of each and writing those bytes to the input of
3435 the other and in this way establish a connection and exchange
3436 application-level bytes with each other.
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003437 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003438 server_conn = self._server(None)
3439 client_conn = self._client(None)
Rick Deanb71c0d22009-04-01 14:09:23 -05003440
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003441 # There should be no key or nonces yet.
Alex Chanb7480992017-01-30 14:04:47 +00003442 assert server_conn.master_key() is None
3443 assert server_conn.client_random() is None
3444 assert server_conn.server_random() is None
Rick Deanb71c0d22009-04-01 14:09:23 -05003445
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003446 # First, the handshake needs to happen. We'll deliver bytes back and
3447 # forth between the client and server until neither of them feels like
3448 # speaking any more.
Alex Chanb7480992017-01-30 14:04:47 +00003449 assert interact_in_memory(client_conn, server_conn) is None
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003450
3451 # Now that the handshake is done, there should be a key and nonces.
Alex Chanb7480992017-01-30 14:04:47 +00003452 assert server_conn.master_key() is not None
3453 assert server_conn.client_random() is not None
3454 assert server_conn.server_random() is not None
3455 assert server_conn.client_random() == client_conn.client_random()
3456 assert server_conn.server_random() == client_conn.server_random()
3457 assert server_conn.client_random() != server_conn.server_random()
3458 assert client_conn.client_random() != client_conn.server_random()
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003459
Paul Kehrerbdb76392017-12-01 04:54:32 +08003460 # Export key material for other uses.
3461 cekm = client_conn.export_keying_material(b'LABEL', 32)
3462 sekm = server_conn.export_keying_material(b'LABEL', 32)
3463 assert cekm is not None
3464 assert sekm is not None
3465 assert cekm == sekm
3466 assert len(sekm) == 32
3467
3468 # Export key material for other uses with additional context.
3469 cekmc = client_conn.export_keying_material(b'LABEL', 32, b'CONTEXT')
3470 sekmc = server_conn.export_keying_material(b'LABEL', 32, b'CONTEXT')
3471 assert cekmc is not None
3472 assert sekmc is not None
3473 assert cekmc == sekmc
3474 assert cekmc != cekm
3475 assert sekmc != sekm
3476 # Export with alternate label
3477 cekmt = client_conn.export_keying_material(b'test', 32, b'CONTEXT')
3478 sekmt = server_conn.export_keying_material(b'test', 32, b'CONTEXT')
3479 assert cekmc != cekmt
3480 assert sekmc != sekmt
3481
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003482 # Here are the bytes we'll try to send.
Alex Gaynore7f51982016-09-11 11:48:14 -04003483 important_message = b'One if by land, two if by sea.'
Rick Deanb71c0d22009-04-01 14:09:23 -05003484
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003485 server_conn.write(important_message)
Alex Chanb7480992017-01-30 14:04:47 +00003486 assert (
3487 interact_in_memory(client_conn, server_conn) ==
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003488 (client_conn, important_message))
3489
3490 client_conn.write(important_message[::-1])
Alex Chanb7480992017-01-30 14:04:47 +00003491 assert (
3492 interact_in_memory(client_conn, server_conn) ==
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003493 (server_conn, important_message[::-1]))
Rick Deanb71c0d22009-04-01 14:09:23 -05003494
Alex Chanb7480992017-01-30 14:04:47 +00003495 def test_socket_connect(self):
Rick Deanb1ccd562009-07-09 23:52:39 -05003496 """
Alex Chanb7480992017-01-30 14:04:47 +00003497 Just like `test_memory_connect` but with an actual socket.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003498
Hynek Schlawack35618382015-09-05 21:54:25 +02003499 This is primarily to rule out the memory BIO code as the source of any
Alex Chanb7480992017-01-30 14:04:47 +00003500 problems encountered while passing data over a `Connection` (if
Hynek Schlawack35618382015-09-05 21:54:25 +02003501 this test fails, there must be a problem outside the memory BIO code,
3502 as no memory BIO is involved here). Even though this isn't a memory
3503 BIO test, it's convenient to have it here.
Rick Deanb1ccd562009-07-09 23:52:39 -05003504 """
Alex Chanb7480992017-01-30 14:04:47 +00003505 server_conn, client_conn = loopback()
Rick Deanb1ccd562009-07-09 23:52:39 -05003506
Alex Gaynore7f51982016-09-11 11:48:14 -04003507 important_message = b"Help me Obi Wan Kenobi, you're my only hope."
Rick Deanb1ccd562009-07-09 23:52:39 -05003508 client_conn.send(important_message)
3509 msg = server_conn.recv(1024)
Alex Chanb7480992017-01-30 14:04:47 +00003510 assert msg == important_message
Rick Deanb1ccd562009-07-09 23:52:39 -05003511
3512 # Again in the other direction, just for fun.
3513 important_message = important_message[::-1]
3514 server_conn.send(important_message)
3515 msg = client_conn.recv(1024)
Alex Chanb7480992017-01-30 14:04:47 +00003516 assert msg == important_message
Rick Deanb1ccd562009-07-09 23:52:39 -05003517
Alex Chanb7480992017-01-30 14:04:47 +00003518 def test_socket_overrides_memory(self):
Rick Deanb71c0d22009-04-01 14:09:23 -05003519 """
Alex Chanb7480992017-01-30 14:04:47 +00003520 Test that `OpenSSL.SSL.bio_read` and `OpenSSL.SSL.bio_write` don't
3521 work on `OpenSSL.SSL.Connection`() that use sockets.
Rick Deanb71c0d22009-04-01 14:09:23 -05003522 """
Alex Gaynor51d424c2016-09-10 14:50:11 -04003523 context = Context(TLSv1_METHOD)
David Benjamin1fbe0642019-04-15 17:05:13 -05003524 client = socket_any_family()
Rick Deanb71c0d22009-04-01 14:09:23 -05003525 clientSSL = Connection(context, client)
Alex Chanb7480992017-01-30 14:04:47 +00003526 with pytest.raises(TypeError):
3527 clientSSL.bio_read(100)
3528 with pytest.raises(TypeError):
3529 clientSSL.bio_write("foo")
3530 with pytest.raises(TypeError):
3531 clientSSL.bio_shutdown()
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003532
Alex Chanb7480992017-01-30 14:04:47 +00003533 def test_outgoing_overflow(self):
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003534 """
3535 If more bytes than can be written to the memory BIO are passed to
Alex Chanb7480992017-01-30 14:04:47 +00003536 `Connection.send` at once, the number of bytes which were written is
3537 returned and that many bytes from the beginning of the input can be
3538 read from the other end of the connection.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003539 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003540 server = self._server(None)
3541 client = self._client(None)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003542
Alex Chanb7480992017-01-30 14:04:47 +00003543 interact_in_memory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003544
3545 size = 2 ** 15
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003546 sent = client.send(b"x" * size)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003547 # Sanity check. We're trying to test what happens when the entire
3548 # input can't be sent. If the entire input was sent, this test is
3549 # meaningless.
Alex Chanb7480992017-01-30 14:04:47 +00003550 assert sent < size
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003551
Alex Chanb7480992017-01-30 14:04:47 +00003552 receiver, received = interact_in_memory(client, server)
3553 assert receiver is server
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003554
3555 # We can rely on all of these bytes being received at once because
Alex Chanb7480992017-01-30 14:04:47 +00003556 # loopback passes 2 ** 16 to recv - more than 2 ** 15.
3557 assert len(received) == sent
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003558
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003559 def test_shutdown(self):
3560 """
Alex Chanb7480992017-01-30 14:04:47 +00003561 `Connection.bio_shutdown` signals the end of the data stream
3562 from which the `Connection` reads.
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003563 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003564 server = self._server(None)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003565 server.bio_shutdown()
Alex Chanb7480992017-01-30 14:04:47 +00003566 with pytest.raises(Error) as err:
3567 server.recv(1024)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003568 # We don't want WantReadError or ZeroReturnError or anything - it's a
3569 # handshake failure.
Alex Chanb7480992017-01-30 14:04:47 +00003570 assert type(err.value) in [Error, SysCallError]
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003571
Alex Chanb7480992017-01-30 14:04:47 +00003572 def test_unexpected_EOF(self):
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003573 """
3574 If the connection is lost before an orderly SSL shutdown occurs,
Alex Chanb7480992017-01-30 14:04:47 +00003575 `OpenSSL.SSL.SysCallError` is raised with a message of
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003576 "Unexpected EOF".
3577 """
Alex Chanb7480992017-01-30 14:04:47 +00003578 server_conn, client_conn = loopback()
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003579 client_conn.sock_shutdown(SHUT_RDWR)
Alex Chanb7480992017-01-30 14:04:47 +00003580 with pytest.raises(SysCallError) as err:
3581 server_conn.recv(1024)
3582 assert err.value.args == (-1, "Unexpected EOF")
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003583
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003584 def _check_client_ca_list(self, func):
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003585 """
Alex Chanb7480992017-01-30 14:04:47 +00003586 Verify the return value of the `get_client_ca_list` method for
Hynek Schlawack35618382015-09-05 21:54:25 +02003587 server and client connections.
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003588
Jonathan Ballet78b92a22011-07-16 08:07:26 +09003589 :param func: A function which will be called with the server context
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003590 before the client and server are connected to each other. This
3591 function should specify a list of CAs for the server to send to the
3592 client and return that same list. The list will be used to verify
Alex Chanb7480992017-01-30 14:04:47 +00003593 that `get_client_ca_list` returns the proper value at
Hynek Schlawack35618382015-09-05 21:54:25 +02003594 various times.
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003595 """
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003596 server = self._server(None)
3597 client = self._client(None)
Alex Chanb7480992017-01-30 14:04:47 +00003598 assert client.get_client_ca_list() == []
3599 assert server.get_client_ca_list() == []
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003600 ctx = server.get_context()
3601 expected = func(ctx)
Alex Chanb7480992017-01-30 14:04:47 +00003602 assert client.get_client_ca_list() == []
3603 assert server.get_client_ca_list() == expected
3604 interact_in_memory(client, server)
3605 assert client.get_client_ca_list() == expected
3606 assert server.get_client_ca_list() == expected
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003607
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003608 def test_set_client_ca_list_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003609 """
Alex Chanb7480992017-01-30 14:04:47 +00003610 `Context.set_client_ca_list` raises a `TypeError` if called with a
3611 non-list or a list that contains objects other than X509Names.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003612 """
3613 ctx = Context(TLSv1_METHOD)
Alex Chanb7480992017-01-30 14:04:47 +00003614 with pytest.raises(TypeError):
3615 ctx.set_client_ca_list("spam")
3616 with pytest.raises(TypeError):
3617 ctx.set_client_ca_list(["spam"])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003618
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003619 def test_set_empty_ca_list(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003620 """
Alex Chanb7480992017-01-30 14:04:47 +00003621 If passed an empty list, `Context.set_client_ca_list` configures the
3622 context to send no CA names to the client and, on both the server and
3623 client sides, `Connection.get_client_ca_list` returns an empty list
3624 after the connection is set up.
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003625 """
3626 def no_ca(ctx):
3627 ctx.set_client_ca_list([])
3628 return []
3629 self._check_client_ca_list(no_ca)
3630
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003631 def test_set_one_ca_list(self):
3632 """
3633 If passed a list containing a single X509Name,
Alex Chanb7480992017-01-30 14:04:47 +00003634 `Context.set_client_ca_list` configures the context to send
Hynek Schlawack35618382015-09-05 21:54:25 +02003635 that CA name to the client and, on both the server and client sides,
Alex Chanb7480992017-01-30 14:04:47 +00003636 `Connection.get_client_ca_list` returns a list containing that
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003637 X509Name after the connection is set up.
3638 """
3639 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3640 cadesc = cacert.get_subject()
Hynek Schlawack35618382015-09-05 21:54:25 +02003641
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003642 def single_ca(ctx):
3643 ctx.set_client_ca_list([cadesc])
3644 return [cadesc]
3645 self._check_client_ca_list(single_ca)
3646
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003647 def test_set_multiple_ca_list(self):
3648 """
3649 If passed a list containing multiple X509Name objects,
Alex Chanb7480992017-01-30 14:04:47 +00003650 `Context.set_client_ca_list` configures the context to send
Hynek Schlawack35618382015-09-05 21:54:25 +02003651 those CA names to the client and, on both the server and client sides,
Alex Chanb7480992017-01-30 14:04:47 +00003652 `Connection.get_client_ca_list` returns a list containing those
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003653 X509Names after the connection is set up.
3654 """
3655 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3656 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3657
3658 sedesc = secert.get_subject()
3659 cldesc = clcert.get_subject()
3660
3661 def multiple_ca(ctx):
3662 L = [sedesc, cldesc]
3663 ctx.set_client_ca_list(L)
3664 return L
3665 self._check_client_ca_list(multiple_ca)
3666
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003667 def test_reset_ca_list(self):
3668 """
3669 If called multiple times, only the X509Names passed to the final call
Alex Chanb7480992017-01-30 14:04:47 +00003670 of `Context.set_client_ca_list` are used to configure the CA
Hynek Schlawack35618382015-09-05 21:54:25 +02003671 names sent to the client.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003672 """
3673 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3674 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3675 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3676
3677 cadesc = cacert.get_subject()
3678 sedesc = secert.get_subject()
3679 cldesc = clcert.get_subject()
3680
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003681 def changed_ca(ctx):
3682 ctx.set_client_ca_list([sedesc, cldesc])
3683 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003684 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003685 self._check_client_ca_list(changed_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003686
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003687 def test_mutated_ca_list(self):
3688 """
Alex Chanb7480992017-01-30 14:04:47 +00003689 If the list passed to `Context.set_client_ca_list` is mutated
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003690 afterwards, this does not affect the list of CA names sent to the
3691 client.
3692 """
3693 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3694 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3695
3696 cadesc = cacert.get_subject()
3697 sedesc = secert.get_subject()
3698
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003699 def mutated_ca(ctx):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003700 L = [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003701 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003702 L.append(sedesc)
3703 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003704 self._check_client_ca_list(mutated_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003705
Alex Chanb7480992017-01-30 14:04:47 +00003706 def test_add_client_ca_wrong_args(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003707 """
Alex Chanb7480992017-01-30 14:04:47 +00003708 `Context.add_client_ca` raises `TypeError` if called with
3709 a non-X509 object.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003710 """
3711 ctx = Context(TLSv1_METHOD)
Alex Chanb7480992017-01-30 14:04:47 +00003712 with pytest.raises(TypeError):
3713 ctx.add_client_ca("spam")
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003714
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003715 def test_one_add_client_ca(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003716 """
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003717 A certificate's subject can be added as a CA to be sent to the client
Alex Chanb7480992017-01-30 14:04:47 +00003718 with `Context.add_client_ca`.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003719 """
3720 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3721 cadesc = cacert.get_subject()
Hynek Schlawack35618382015-09-05 21:54:25 +02003722
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003723 def single_ca(ctx):
3724 ctx.add_client_ca(cacert)
3725 return [cadesc]
3726 self._check_client_ca_list(single_ca)
3727
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003728 def test_multiple_add_client_ca(self):
3729 """
3730 Multiple CA names can be sent to the client by calling
Alex Chanb7480992017-01-30 14:04:47 +00003731 `Context.add_client_ca` with multiple X509 objects.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003732 """
3733 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3734 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3735
3736 cadesc = cacert.get_subject()
3737 sedesc = secert.get_subject()
3738
3739 def multiple_ca(ctx):
3740 ctx.add_client_ca(cacert)
3741 ctx.add_client_ca(secert)
3742 return [cadesc, sedesc]
3743 self._check_client_ca_list(multiple_ca)
3744
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003745 def test_set_and_add_client_ca(self):
3746 """
Alex Chanb7480992017-01-30 14:04:47 +00003747 A call to `Context.set_client_ca_list` followed by a call to
3748 `Context.add_client_ca` results in using the CA names from the
Hynek Schlawack35618382015-09-05 21:54:25 +02003749 first call and the CA name from the second call.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003750 """
3751 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3752 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3753 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3754
3755 cadesc = cacert.get_subject()
3756 sedesc = secert.get_subject()
3757 cldesc = clcert.get_subject()
3758
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003759 def mixed_set_add_ca(ctx):
3760 ctx.set_client_ca_list([cadesc, sedesc])
3761 ctx.add_client_ca(clcert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003762 return [cadesc, sedesc, cldesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003763 self._check_client_ca_list(mixed_set_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003764
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003765 def test_set_after_add_client_ca(self):
3766 """
Alex Chanb7480992017-01-30 14:04:47 +00003767 A call to `Context.set_client_ca_list` after a call to
3768 `Context.add_client_ca` replaces the CA name specified by the
Hynek Schlawack35618382015-09-05 21:54:25 +02003769 former call with the names specified by the latter call.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003770 """
3771 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3772 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3773 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3774
3775 cadesc = cacert.get_subject()
3776 sedesc = secert.get_subject()
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003777
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003778 def set_replaces_add_ca(ctx):
3779 ctx.add_client_ca(clcert)
3780 ctx.set_client_ca_list([cadesc])
3781 ctx.add_client_ca(secert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003782 return [cadesc, sedesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003783 self._check_client_ca_list(set_replaces_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003784
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003785
Alex Chanb7480992017-01-30 14:04:47 +00003786class TestInfoConstants(object):
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003787 """
3788 Tests for assorted constants exposed for use in info callbacks.
3789 """
3790 def test_integers(self):
3791 """
3792 All of the info constants are integers.
3793
3794 This is a very weak test. It would be nice to have one that actually
3795 verifies that as certain info events happen, the value passed to the
3796 info callback matches up with the constant exposed by OpenSSL.SSL.
3797 """
3798 for const in [
Alex Gaynor5af32d02016-09-24 01:52:21 -04003799 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK,
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003800 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
3801 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
3802 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
Hynek Schlawack35618382015-09-05 21:54:25 +02003803 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE
3804 ]:
Alex Gaynor5af32d02016-09-24 01:52:21 -04003805 assert isinstance(const, int)
3806
3807 # These constants don't exist on OpenSSL 1.1.0
3808 for const in [
3809 SSL_ST_INIT, SSL_ST_BEFORE, SSL_ST_OK, SSL_ST_RENEGOTIATE
3810 ]:
3811 assert const is None or isinstance(const, int)
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003812
Ziga Seilnacht44611bf2009-08-31 20:49:30 +02003813
Cory Benfield1d142142016-03-30 11:51:45 +01003814class TestRequires(object):
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003815 """
3816 Tests for the decorator factory used to conditionally raise
Cory Benfield1d142142016-03-30 11:51:45 +01003817 NotImplementedError when older OpenSSLs are used.
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003818 """
3819 def test_available(self):
3820 """
3821 When the OpenSSL functionality is available the decorated functions
3822 work appropriately.
3823 """
3824 feature_guard = _make_requires(True, "Error text")
3825 results = []
3826
3827 @feature_guard
3828 def inner():
3829 results.append(True)
3830 return True
3831
Cory Benfield2333e5e2016-03-30 14:24:16 +01003832 assert inner() is True
3833 assert [True] == results
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003834
3835 def test_unavailable(self):
3836 """
3837 When the OpenSSL functionality is not available the decorated function
3838 does not execute and NotImplementedError is raised.
3839 """
3840 feature_guard = _make_requires(False, "Error text")
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003841
3842 @feature_guard
Alex Chanfb078d82017-04-20 11:16:15 +01003843 def inner(): # pragma: nocover
3844 pytest.fail("Should not be called")
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003845
Cory Benfield1d142142016-03-30 11:51:45 +01003846 with pytest.raises(NotImplementedError) as e:
3847 inner()
3848
3849 assert "Error text" in str(e.value)
Cory Benfield496652a2017-01-24 11:42:56 +00003850
3851
Alex Chanb7480992017-01-30 14:04:47 +00003852class TestOCSP(object):
Cory Benfield496652a2017-01-24 11:42:56 +00003853 """
3854 Tests for PyOpenSSL's OCSP stapling support.
3855 """
3856 sample_ocsp_data = b"this is totally ocsp data"
3857
3858 def _client_connection(self, callback, data, request_ocsp=True):
3859 """
3860 Builds a client connection suitable for using OCSP.
3861
3862 :param callback: The callback to register for OCSP.
3863 :param data: The opaque data object that will be handed to the
3864 OCSP callback.
3865 :param request_ocsp: Whether the client will actually ask for OCSP
3866 stapling. Useful for testing only.
3867 """
3868 ctx = Context(SSLv23_METHOD)
3869 ctx.set_ocsp_client_callback(callback, data)
3870 client = Connection(ctx)
3871
3872 if request_ocsp:
3873 client.request_ocsp()
3874
3875 client.set_connect_state()
3876 return client
3877
3878 def _server_connection(self, callback, data):
3879 """
3880 Builds a server connection suitable for using OCSP.
3881
3882 :param callback: The callback to register for OCSP.
3883 :param data: The opaque data object that will be handed to the
3884 OCSP callback.
3885 """
3886 ctx = Context(SSLv23_METHOD)
3887 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
3888 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
3889 ctx.set_ocsp_server_callback(callback, data)
3890 server = Connection(ctx)
3891 server.set_accept_state()
3892 return server
3893
3894 def test_callbacks_arent_called_by_default(self):
3895 """
3896 If both the client and the server have registered OCSP callbacks, but
3897 the client does not send the OCSP request, neither callback gets
3898 called.
3899 """
Alex Chanfb078d82017-04-20 11:16:15 +01003900 def ocsp_callback(*args, **kwargs): # pragma: nocover
3901 pytest.fail("Should not be called")
Cory Benfield496652a2017-01-24 11:42:56 +00003902
3903 client = self._client_connection(
3904 callback=ocsp_callback, data=None, request_ocsp=False
3905 )
3906 server = self._server_connection(callback=ocsp_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00003907 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003908
Cory Benfield496652a2017-01-24 11:42:56 +00003909 def test_client_negotiates_without_server(self):
3910 """
3911 If the client wants to do OCSP but the server does not, the handshake
3912 succeeds, and the client callback fires with an empty byte string.
3913 """
3914 called = []
3915
3916 def ocsp_callback(conn, ocsp_data, ignored):
3917 called.append(ocsp_data)
3918 return True
3919
3920 client = self._client_connection(callback=ocsp_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00003921 server = loopback_server_factory(socket=None)
3922 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003923
3924 assert len(called) == 1
3925 assert called[0] == b''
3926
3927 def test_client_receives_servers_data(self):
3928 """
3929 The data the server sends in its callback is received by the client.
3930 """
3931 calls = []
3932
3933 def server_callback(*args, **kwargs):
3934 return self.sample_ocsp_data
3935
3936 def client_callback(conn, ocsp_data, ignored):
3937 calls.append(ocsp_data)
3938 return True
3939
3940 client = self._client_connection(callback=client_callback, data=None)
3941 server = self._server_connection(callback=server_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00003942 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003943
3944 assert len(calls) == 1
3945 assert calls[0] == self.sample_ocsp_data
3946
3947 def test_callbacks_are_invoked_with_connections(self):
3948 """
3949 The first arguments to both callbacks are their respective connections.
3950 """
3951 client_calls = []
3952 server_calls = []
3953
3954 def client_callback(conn, *args, **kwargs):
3955 client_calls.append(conn)
3956 return True
3957
3958 def server_callback(conn, *args, **kwargs):
3959 server_calls.append(conn)
3960 return self.sample_ocsp_data
3961
3962 client = self._client_connection(callback=client_callback, data=None)
3963 server = self._server_connection(callback=server_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00003964 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003965
3966 assert len(client_calls) == 1
3967 assert len(server_calls) == 1
3968 assert client_calls[0] is client
3969 assert server_calls[0] is server
3970
3971 def test_opaque_data_is_passed_through(self):
3972 """
3973 Both callbacks receive an opaque, user-provided piece of data in their
3974 callbacks as the final argument.
3975 """
3976 calls = []
3977
3978 def server_callback(*args):
3979 calls.append(args)
3980 return self.sample_ocsp_data
3981
3982 def client_callback(*args):
3983 calls.append(args)
3984 return True
3985
3986 sentinel = object()
3987
3988 client = self._client_connection(
3989 callback=client_callback, data=sentinel
3990 )
3991 server = self._server_connection(
3992 callback=server_callback, data=sentinel
3993 )
Alex Chanb7480992017-01-30 14:04:47 +00003994 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003995
3996 assert len(calls) == 2
3997 assert calls[0][-1] is sentinel
3998 assert calls[1][-1] is sentinel
3999
4000 def test_server_returns_empty_string(self):
4001 """
4002 If the server returns an empty bytestring from its callback, the
4003 client callback is called with the empty bytestring.
4004 """
4005 client_calls = []
4006
4007 def server_callback(*args):
4008 return b''
4009
4010 def client_callback(conn, ocsp_data, ignored):
4011 client_calls.append(ocsp_data)
4012 return True
4013
4014 client = self._client_connection(callback=client_callback, data=None)
4015 server = self._server_connection(callback=server_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00004016 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00004017
4018 assert len(client_calls) == 1
4019 assert client_calls[0] == b''
4020
4021 def test_client_returns_false_terminates_handshake(self):
4022 """
4023 If the client returns False from its callback, the handshake fails.
4024 """
4025 def server_callback(*args):
4026 return self.sample_ocsp_data
4027
4028 def client_callback(*args):
4029 return False
4030
4031 client = self._client_connection(callback=client_callback, data=None)
4032 server = self._server_connection(callback=server_callback, data=None)
4033
4034 with pytest.raises(Error):
Alex Chanb7480992017-01-30 14:04:47 +00004035 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00004036
4037 def test_exceptions_in_client_bubble_up(self):
4038 """
4039 The callbacks thrown in the client callback bubble up to the caller.
4040 """
4041 class SentinelException(Exception):
4042 pass
4043
4044 def server_callback(*args):
4045 return self.sample_ocsp_data
4046
4047 def client_callback(*args):
4048 raise SentinelException()
4049
4050 client = self._client_connection(callback=client_callback, data=None)
4051 server = self._server_connection(callback=server_callback, data=None)
4052
4053 with pytest.raises(SentinelException):
Alex Chanb7480992017-01-30 14:04:47 +00004054 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00004055
4056 def test_exceptions_in_server_bubble_up(self):
4057 """
4058 The callbacks thrown in the server callback bubble up to the caller.
4059 """
4060 class SentinelException(Exception):
4061 pass
4062
4063 def server_callback(*args):
4064 raise SentinelException()
4065
Alex Chanfb078d82017-04-20 11:16:15 +01004066 def client_callback(*args): # pragma: nocover
Cory Benfield496652a2017-01-24 11:42:56 +00004067 pytest.fail("Should not be called")
4068
4069 client = self._client_connection(callback=client_callback, data=None)
4070 server = self._server_connection(callback=server_callback, data=None)
4071
4072 with pytest.raises(SentinelException):
Alex Chanb7480992017-01-30 14:04:47 +00004073 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00004074
4075 def test_server_must_return_bytes(self):
4076 """
4077 The server callback must return a bytestring, or a TypeError is thrown.
4078 """
4079 def server_callback(*args):
4080 return self.sample_ocsp_data.decode('ascii')
4081
Alex Chanfb078d82017-04-20 11:16:15 +01004082 def client_callback(*args): # pragma: nocover
Cory Benfield496652a2017-01-24 11:42:56 +00004083 pytest.fail("Should not be called")
4084
4085 client = self._client_connection(callback=client_callback, data=None)
4086 server = self._server_connection(callback=server_callback, data=None)
4087
4088 with pytest.raises(TypeError):
Alex Chanb7480992017-01-30 14:04:47 +00004089 handshake_in_memory(client, server)