blob: 96efec8fd0f1d1d80a45e8c1df44eaa9d11c0e81 [file] [log] [blame]
Jean-Paul Calderone8671c852011-03-02 19:26:20 -05001# Copyright (C) Jean-Paul Calderone
2# See LICENSE for details.
Jean-Paul Calderone8b63d452008-03-21 18:31:12 -04003
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -04004"""
Hynek Schlawackf90e3682016-03-11 11:21:13 +01005Unit tests for :mod:`OpenSSL.SSL`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -04006"""
7
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01008import datetime
Maximilian Hils868dc3c2017-02-10 14:56:55 +01009import sys
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +010010import uuid
11
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -050012from gc import collect, get_referrers
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +020013from errno import ECONNREFUSED, EINPROGRESS, EWOULDBLOCK, EPIPE, ESHUTDOWN
Hynek Schlawackf8979a52015-09-05 21:25:25 +020014from sys import platform, getfilesystemencoding, version_info
Maximilian Hils1d95dea2015-08-17 19:27:20 +020015from socket import MSG_PEEK, SHUT_RDWR, error, socket
Jean-Paul Calderonea65cf6c2009-07-19 10:26:52 -040016from os import makedirs
Jean-Paul Calderone1461c492013-10-03 16:05:00 -040017from os.path import join
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -040018from weakref import ref
Alex Chanb7480992017-01-30 14:04:47 +000019from warnings import simplefilter
Jean-Paul Calderone460cc1f2009-03-07 11:31:12 -050020
Hynek Schlawack734d3022015-09-05 19:19:32 +020021import pytest
22
Hynek Schlawackf90e3682016-03-11 11:21:13 +010023from six import PY3, text_type
Jean-Paul Calderonec76c61c2014-01-18 13:21:52 -050024
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +010025from cryptography import x509
26from cryptography.hazmat.backends import default_backend
27from cryptography.hazmat.primitives import hashes
28from cryptography.hazmat.primitives import serialization
29from cryptography.hazmat.primitives.asymmetric import rsa
30from cryptography.x509.oid import NameOID
31
32
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040033from OpenSSL.crypto import TYPE_RSA, FILETYPE_PEM
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -080034from OpenSSL.crypto import PKey, X509, X509Extension, X509Store
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040035from OpenSSL.crypto import dump_privatekey, load_privatekey
36from OpenSSL.crypto import dump_certificate, load_certificate
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -040037from OpenSSL.crypto import get_elliptic_curves
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040038
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -040039from OpenSSL.SSL import OPENSSL_VERSION_NUMBER, SSLEAY_VERSION, SSLEAY_CFLAGS
40from OpenSSL.SSL import SSLEAY_PLATFORM, SSLEAY_DIR, SSLEAY_BUILT_ON
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -040041from OpenSSL.SSL import SENT_SHUTDOWN, RECEIVED_SHUTDOWN
Jean-Paul Calderone1461c492013-10-03 16:05:00 -040042from OpenSSL.SSL import (
43 SSLv2_METHOD, SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD,
44 TLSv1_1_METHOD, TLSv1_2_METHOD)
45from OpenSSL.SSL import OP_SINGLE_DH_USE, OP_NO_SSLv2, OP_NO_SSLv3
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040046from OpenSSL.SSL import (
47 VERIFY_PEER, VERIFY_FAIL_IF_NO_PEER_CERT, VERIFY_CLIENT_ONCE, VERIFY_NONE)
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040048
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040049from OpenSSL.SSL import (
Jean-Paul Calderone313bf012012-02-08 13:02:49 -050050 SESS_CACHE_OFF, SESS_CACHE_CLIENT, SESS_CACHE_SERVER, SESS_CACHE_BOTH,
51 SESS_CACHE_NO_AUTO_CLEAR, SESS_CACHE_NO_INTERNAL_LOOKUP,
52 SESS_CACHE_NO_INTERNAL_STORE, SESS_CACHE_NO_INTERNAL)
53
54from OpenSSL.SSL import (
Jean-Paul Calderoned899af02013-03-19 22:10:37 -070055 Error, SysCallError, WantReadError, WantWriteError, ZeroReturnError)
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -050056from OpenSSL.SSL import (
Jean-Paul Calderoned899af02013-03-19 22:10:37 -070057 Context, ContextType, Session, Connection, ConnectionType, SSLeay_version)
Cory Benfield0ba57ec2016-03-30 09:35:05 +010058from OpenSSL.SSL import _make_requires
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040059
Cory Benfieldba1820d2015-04-13 17:39:12 -040060from OpenSSL._util import lib as _lib
61
Alex Gaynord3b5d9b2016-07-31 10:54:24 -040062from OpenSSL.SSL import (
63 OP_NO_QUERY_MTU, OP_COOKIE_EXCHANGE, OP_NO_TICKET, OP_NO_COMPRESSION,
64 MODE_RELEASE_BUFFERS)
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040065
Jean-Paul Calderone1461c492013-10-03 16:05:00 -040066try:
67 from OpenSSL.SSL import OP_NO_TLSv1, OP_NO_TLSv1_1, OP_NO_TLSv1_2
68except ImportError:
69 OP_NO_TLSv1 = OP_NO_TLSv1_1 = OP_NO_TLSv1_2 = None
70
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -040071from OpenSSL.SSL import (
Alex Gaynor5af32d02016-09-24 01:52:21 -040072 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK,
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -040073 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
74 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
75 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
76 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE)
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -040077
Alex Gaynor5af32d02016-09-24 01:52:21 -040078try:
79 from OpenSSL.SSL import (
80 SSL_ST_INIT, SSL_ST_BEFORE, SSL_ST_OK, SSL_ST_RENEGOTIATE
81 )
82except ImportError:
83 SSL_ST_INIT = SSL_ST_BEFORE = SSL_ST_OK = SSL_ST_RENEGOTIATE = None
84
Alex Chanb7480992017-01-30 14:04:47 +000085from .util import WARNING_TYPE_EXPECTED, NON_ASCII, is_consistent_type
Hynek Schlawackf0e66852015-10-16 20:18:38 +020086from .test_crypto import (
87 cleartextCertificatePEM, cleartextPrivateKeyPEM,
88 client_cert_pem, client_key_pem, server_cert_pem, server_key_pem,
89 root_cert_pem)
90
Hynek Schlawackde00dd52015-09-05 19:09:26 +020091
Alex Gaynord0bdd2d2016-09-10 14:23:46 -040092# openssl dhparam 1024 -out dh-1024.pem (note that 1024 is a small number of
93# bits to use)
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -040094dhparam = """\
95-----BEGIN DH PARAMETERS-----
Alex Gaynord0bdd2d2016-09-10 14:23:46 -040096MIGHAoGBALdUMvn+C9MM+y5BWZs11mSeH6HHoEq0UVbzVq7UojC1hbsZUuGukQ3a
97Qh2/pwqb18BZFykrWB0zv/OkLa0kx4cuUgNrUVq1EFheBiX6YqryJ7t2sO09NQiO
98V7H54LmltOT/hEh6QWsJqb6BQgH65bswvV/XkYGja8/T0GzvbaVzAgEC
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -040099-----END DH PARAMETERS-----
100"""
101
102
Hynek Schlawackb4f02402015-09-05 20:48:34 +0200103skip_if_py3 = pytest.mark.skipif(PY3, reason="Python 2 only")
Hynek Schlawackf8979a52015-09-05 21:25:25 +0200104skip_if_py26 = pytest.mark.skipif(
105 version_info[0:2] == (2, 6),
106 reason="Python 2.7 and later only"
107)
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200108
109
Jean-Paul Calderone05826732015-04-12 11:38:49 -0400110def join_bytes_or_unicode(prefix, suffix):
111 """
112 Join two path components of either ``bytes`` or ``unicode``.
113
114 The return type is the same as the type of ``prefix``.
115 """
116 # If the types are the same, nothing special is necessary.
117 if type(prefix) == type(suffix):
118 return join(prefix, suffix)
119
120 # Otherwise, coerce suffix to the type of prefix.
121 if isinstance(prefix, text_type):
122 return join(prefix, suffix.decode(getfilesystemencoding()))
123 else:
124 return join(prefix, suffix.encode(getfilesystemencoding()))
125
126
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400127def verify_cb(conn, cert, errnum, depth, ok):
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400128 return ok
129
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400130
Rick Deanb1ccd562009-07-09 23:52:39 -0500131def socket_pair():
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400132 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400133 Establish and return a pair of network sockets connected to each other.
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400134 """
135 # Connect a pair of sockets
Rick Deanb1ccd562009-07-09 23:52:39 -0500136 port = socket()
137 port.bind(('', 0))
138 port.listen(1)
139 client = socket()
140 client.setblocking(False)
Jean-Paul Calderonef23c5d92009-07-23 17:58:15 -0400141 client.connect_ex(("127.0.0.1", port.getsockname()[1]))
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400142 client.setblocking(True)
Rick Deanb1ccd562009-07-09 23:52:39 -0500143 server = port.accept()[0]
Rick Deanb1ccd562009-07-09 23:52:39 -0500144
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400145 # Let's pass some unencrypted data to make sure our socket connection is
146 # fine. Just one byte, so we don't have to worry about buffers getting
147 # filled up or fragmentation.
Alex Gaynore7f51982016-09-11 11:48:14 -0400148 server.send(b"x")
149 assert client.recv(1024) == b"x"
150 client.send(b"y")
151 assert server.recv(1024) == b"y"
Rick Deanb1ccd562009-07-09 23:52:39 -0500152
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -0400153 # Most of our callers want non-blocking sockets, make it easy for them.
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400154 server.setblocking(False)
155 client.setblocking(False)
Jim Shaver46f28912015-05-29 19:32:16 -0400156
Rick Deanb1ccd562009-07-09 23:52:39 -0500157 return (server, client)
158
159
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400160def handshake(client, server):
161 conns = [client, server]
162 while conns:
163 for conn in conns:
164 try:
165 conn.do_handshake()
166 except WantReadError:
167 pass
168 else:
169 conns.remove(conn)
170
171
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400172def _create_certificate_chain():
173 """
174 Construct and return a chain of certificates.
175
176 1. A new self-signed certificate authority certificate (cacert)
177 2. A new intermediate certificate signed by cacert (icert)
178 3. A new server certificate signed by icert (scert)
179 """
Alex Gaynore7f51982016-09-11 11:48:14 -0400180 caext = X509Extension(b'basicConstraints', False, b'CA:true')
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400181
182 # Step 1
183 cakey = PKey()
Alex Gaynor0737a5e2016-09-10 14:35:09 -0400184 cakey.generate_key(TYPE_RSA, 1024)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400185 cacert = X509()
186 cacert.get_subject().commonName = "Authority Certificate"
187 cacert.set_issuer(cacert.get_subject())
188 cacert.set_pubkey(cakey)
Alex Gaynore7f51982016-09-11 11:48:14 -0400189 cacert.set_notBefore(b"20000101000000Z")
190 cacert.set_notAfter(b"20200101000000Z")
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400191 cacert.add_extensions([caext])
192 cacert.set_serial_number(0)
193 cacert.sign(cakey, "sha1")
194
195 # Step 2
196 ikey = PKey()
Alex Gaynor0737a5e2016-09-10 14:35:09 -0400197 ikey.generate_key(TYPE_RSA, 1024)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400198 icert = X509()
199 icert.get_subject().commonName = "Intermediate Certificate"
200 icert.set_issuer(cacert.get_subject())
201 icert.set_pubkey(ikey)
Alex Gaynore7f51982016-09-11 11:48:14 -0400202 icert.set_notBefore(b"20000101000000Z")
203 icert.set_notAfter(b"20200101000000Z")
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400204 icert.add_extensions([caext])
205 icert.set_serial_number(0)
206 icert.sign(cakey, "sha1")
207
208 # Step 3
209 skey = PKey()
Alex Gaynor0737a5e2016-09-10 14:35:09 -0400210 skey.generate_key(TYPE_RSA, 1024)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400211 scert = X509()
212 scert.get_subject().commonName = "Server Certificate"
213 scert.set_issuer(icert.get_subject())
214 scert.set_pubkey(skey)
Alex Gaynore7f51982016-09-11 11:48:14 -0400215 scert.set_notBefore(b"20000101000000Z")
216 scert.set_notAfter(b"20200101000000Z")
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400217 scert.add_extensions([
Alex Gaynore7f51982016-09-11 11:48:14 -0400218 X509Extension(b'basicConstraints', True, b'CA:false')])
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400219 scert.set_serial_number(0)
220 scert.sign(ikey, "sha1")
221
222 return [(cakey, cacert), (ikey, icert), (skey, scert)]
223
224
Alex Chan1c0cb662017-01-30 07:13:30 +0000225def loopback_client_factory(socket):
226 client = Connection(Context(TLSv1_METHOD), socket)
227 client.set_connect_state()
228 return client
229
230
231def loopback_server_factory(socket):
232 ctx = Context(TLSv1_METHOD)
233 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
234 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
235 server = Connection(ctx, socket)
236 server.set_accept_state()
237 return server
238
239
240def loopback(server_factory=None, client_factory=None):
241 """
242 Create a connected socket pair and force two connected SSL sockets
243 to talk to each other via memory BIOs.
244 """
245 if server_factory is None:
246 server_factory = loopback_server_factory
247 if client_factory is None:
248 client_factory = loopback_client_factory
249
250 (server, client) = socket_pair()
251 server = server_factory(server)
252 client = client_factory(client)
253
254 handshake(client, server)
255
256 server.setblocking(True)
257 client.setblocking(True)
258 return server, client
259
260
Alex Chan1ca9e3a2016-11-05 13:01:51 +0000261def interact_in_memory(client_conn, server_conn):
262 """
263 Try to read application bytes from each of the two `Connection` objects.
264 Copy bytes back and forth between their send/receive buffers for as long
265 as there is anything to copy. When there is nothing more to copy,
266 return `None`. If one of them actually manages to deliver some application
267 bytes, return a two-tuple of the connection from which the bytes were read
268 and the bytes themselves.
269 """
270 wrote = True
271 while wrote:
272 # Loop until neither side has anything to say
273 wrote = False
274
275 # Copy stuff from each side's send buffer to the other side's
276 # receive buffer.
277 for (read, write) in [(client_conn, server_conn),
278 (server_conn, client_conn)]:
279
280 # Give the side a chance to generate some more bytes, or succeed.
281 try:
282 data = read.recv(2 ** 16)
283 except WantReadError:
284 # It didn't succeed, so we'll hope it generated some output.
285 pass
286 else:
287 # It did succeed, so we'll stop now and let the caller deal
288 # with it.
289 return (read, data)
290
291 while True:
292 # Keep copying as long as there's more stuff there.
293 try:
294 dirty = read.bio_read(4096)
295 except WantReadError:
296 # Okay, nothing more waiting to be sent. Stop
297 # processing this send buffer.
298 break
299 else:
300 # Keep track of the fact that someone generated some
301 # output.
302 wrote = True
303 write.bio_write(dirty)
304
305
Alex Chan532b79e2017-01-24 15:14:52 +0000306def handshake_in_memory(client_conn, server_conn):
307 """
308 Perform the TLS handshake between two `Connection` instances connected to
309 each other via memory BIOs.
310 """
311 client_conn.set_connect_state()
312 server_conn.set_accept_state()
313
314 for conn in [client_conn, server_conn]:
315 try:
316 conn.do_handshake()
317 except WantReadError:
318 pass
319
320 interact_in_memory(client_conn, server_conn)
321
322
Alex Chanb7480992017-01-30 14:04:47 +0000323class TestVersion(object):
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400324 """
Alex Chanb7480992017-01-30 14:04:47 +0000325 Tests for version information exposed by `OpenSSL.SSL.SSLeay_version` and
326 `OpenSSL.SSL.OPENSSL_VERSION_NUMBER`.
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400327 """
328 def test_OPENSSL_VERSION_NUMBER(self):
329 """
Alex Chanb7480992017-01-30 14:04:47 +0000330 `OPENSSL_VERSION_NUMBER` is an integer with status in the low byte and
331 the patch, fix, minor, and major versions in the nibbles above that.
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400332 """
Alex Chanb7480992017-01-30 14:04:47 +0000333 assert isinstance(OPENSSL_VERSION_NUMBER, int)
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400334
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400335 def test_SSLeay_version(self):
336 """
Alex Chanb7480992017-01-30 14:04:47 +0000337 `SSLeay_version` takes a version type indicator and returns one of a
338 number of version strings based on that indicator.
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400339 """
340 versions = {}
341 for t in [SSLEAY_VERSION, SSLEAY_CFLAGS, SSLEAY_BUILT_ON,
342 SSLEAY_PLATFORM, SSLEAY_DIR]:
343 version = SSLeay_version(t)
344 versions[version] = t
Alex Chanb7480992017-01-30 14:04:47 +0000345 assert isinstance(version, bytes)
346 assert len(versions) == 5
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400347
348
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100349@pytest.fixture
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100350def ca_file(tmpdir):
351 """
352 Create a valid PEM file with CA certificates and return the path.
353 """
354 key = rsa.generate_private_key(
355 public_exponent=65537,
356 key_size=2048,
357 backend=default_backend()
358 )
359 public_key = key.public_key()
360
361 builder = x509.CertificateBuilder()
362 builder = builder.subject_name(x509.Name([
363 x509.NameAttribute(NameOID.COMMON_NAME, u"pyopenssl.org"),
364 ]))
365 builder = builder.issuer_name(x509.Name([
366 x509.NameAttribute(NameOID.COMMON_NAME, u"pyopenssl.org"),
367 ]))
368 one_day = datetime.timedelta(1, 0, 0)
369 builder = builder.not_valid_before(datetime.datetime.today() - one_day)
370 builder = builder.not_valid_after(datetime.datetime.today() + one_day)
371 builder = builder.serial_number(int(uuid.uuid4()))
372 builder = builder.public_key(public_key)
373 builder = builder.add_extension(
374 x509.BasicConstraints(ca=True, path_length=None), critical=True,
375 )
376
377 certificate = builder.sign(
378 private_key=key, algorithm=hashes.SHA256(),
379 backend=default_backend()
380 )
381
382 ca_file = tmpdir.join("test.pem")
383 ca_file.write_binary(
384 certificate.public_bytes(
385 encoding=serialization.Encoding.PEM,
386 )
387 )
388
389 return str(ca_file).encode("ascii")
390
391
392@pytest.fixture
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100393def context():
394 """
395 A simple TLS 1.0 context.
396 """
397 return Context(TLSv1_METHOD)
398
399
400class TestContext(object):
Hynek Schlawackaa861212016-03-13 13:53:48 +0100401 """
Alex Chan532b79e2017-01-24 15:14:52 +0000402 Unit tests for `OpenSSL.SSL.Context`.
Hynek Schlawackaa861212016-03-13 13:53:48 +0100403 """
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100404 @pytest.mark.parametrize("cipher_string", [
405 b"hello world:AES128-SHA",
406 u"hello world:AES128-SHA",
407 ])
408 def test_set_cipher_list(self, context, cipher_string):
409 """
Alex Chan532b79e2017-01-24 15:14:52 +0000410 `Context.set_cipher_list` accepts both byte and unicode strings
Hynek Schlawacka7a63af2016-03-11 12:05:26 +0100411 for naming the ciphers which connections created with the context
412 object will be able to choose from.
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100413 """
414 context.set_cipher_list(cipher_string)
415 conn = Connection(context, None)
416
417 assert "AES128-SHA" in conn.get_cipher_list()
418
419 @pytest.mark.parametrize("cipher_list,error", [
420 (object(), TypeError),
421 ("imaginary-cipher", Error),
422 ])
423 def test_set_cipher_list_wrong_args(self, context, cipher_list, error):
424 """
Alex Chan532b79e2017-01-24 15:14:52 +0000425 `Context.set_cipher_list` raises `TypeError` when passed a non-string
426 argument and raises `OpenSSL.SSL.Error` when passed an incorrect cipher
427 list string.
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100428 """
429 with pytest.raises(error):
430 context.set_cipher_list(cipher_list)
431
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100432 def test_load_client_ca(self, context, ca_file):
433 """
Alex Chan532b79e2017-01-24 15:14:52 +0000434 `Context.load_client_ca` works as far as we can tell.
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100435 """
436 context.load_client_ca(ca_file)
437
438 def test_load_client_ca_invalid(self, context, tmpdir):
439 """
Alex Chan532b79e2017-01-24 15:14:52 +0000440 `Context.load_client_ca` raises an Error if the ca file is invalid.
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100441 """
442 ca_file = tmpdir.join("test.pem")
443 ca_file.write("")
444
445 with pytest.raises(Error) as e:
446 context.load_client_ca(str(ca_file).encode("ascii"))
447
448 assert "PEM routines" == e.value.args[0][0][0]
449
450 def test_load_client_ca_unicode(self, context, ca_file):
451 """
452 Passing the path as unicode raises a warning but works.
453 """
454 pytest.deprecated_call(
455 context.load_client_ca, ca_file.decode("ascii")
456 )
457
458 def test_set_session_id(self, context):
459 """
Alex Chan532b79e2017-01-24 15:14:52 +0000460 `Context.set_session_id` works as far as we can tell.
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100461 """
462 context.set_session_id(b"abc")
463
464 def test_set_session_id_fail(self, context):
465 """
Alex Chan532b79e2017-01-24 15:14:52 +0000466 `Context.set_session_id` errors are propagated.
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100467 """
468 with pytest.raises(Error) as e:
469 context.set_session_id(b"abc" * 1000)
470
471 assert [
472 ("SSL routines",
473 "SSL_CTX_set_session_id_context",
474 "ssl session id context too long")
475 ] == e.value.args[0]
476
477 def test_set_session_id_unicode(self, context):
478 """
Alex Chan532b79e2017-01-24 15:14:52 +0000479 `Context.set_session_id` raises a warning if a unicode string is
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100480 passed.
481 """
482 pytest.deprecated_call(context.set_session_id, u"abc")
483
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400484 def test_method(self):
485 """
Alex Chan532b79e2017-01-24 15:14:52 +0000486 `Context` can be instantiated with one of `SSLv2_METHOD`,
487 `SSLv3_METHOD`, `SSLv23_METHOD`, `TLSv1_METHOD`, `TLSv1_1_METHOD`,
488 or `TLSv1_2_METHOD`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400489 """
Alex Gaynor5af32d02016-09-24 01:52:21 -0400490 methods = [SSLv23_METHOD, TLSv1_METHOD]
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400491 for meth in methods:
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400492 Context(meth)
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400493
Alex Gaynor5af32d02016-09-24 01:52:21 -0400494 maybe = [SSLv2_METHOD, SSLv3_METHOD, TLSv1_1_METHOD, TLSv1_2_METHOD]
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400495 for meth in maybe:
496 try:
497 Context(meth)
498 except (Error, ValueError):
499 # Some versions of OpenSSL have SSLv2 / TLSv1.1 / TLSv1.2, some
500 # don't. Difficult to say in advance.
501 pass
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400502
Alex Chan532b79e2017-01-24 15:14:52 +0000503 with pytest.raises(TypeError):
504 Context("")
505 with pytest.raises(ValueError):
506 Context(10)
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400507
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200508 @skip_if_py3
509 def test_method_long(self):
510 """
Alex Chan532b79e2017-01-24 15:14:52 +0000511 On Python 2 `Context` accepts values of type `long` as well as `int`.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200512 """
513 Context(long(TLSv1_METHOD))
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500514
Rick Deane15b1472009-07-09 15:53:42 -0500515 def test_type(self):
516 """
Alex Chan532b79e2017-01-24 15:14:52 +0000517 `Context` and `ContextType` refer to the same type object and can
518 be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -0500519 """
Alex Chan532b79e2017-01-24 15:14:52 +0000520 assert Context is ContextType
521 assert is_consistent_type(Context, 'Context', TLSv1_METHOD)
Rick Deane15b1472009-07-09 15:53:42 -0500522
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400523 def test_use_privatekey(self):
524 """
Alex Chan532b79e2017-01-24 15:14:52 +0000525 `Context.use_privatekey` takes an `OpenSSL.crypto.PKey` instance.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400526 """
527 key = PKey()
528 key.generate_key(TYPE_RSA, 128)
529 ctx = Context(TLSv1_METHOD)
530 ctx.use_privatekey(key)
Alex Chan532b79e2017-01-24 15:14:52 +0000531 with pytest.raises(TypeError):
532 ctx.use_privatekey("")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400533
Alex Chan532b79e2017-01-24 15:14:52 +0000534 def test_use_privatekey_file_missing(self, tmpfile):
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800535 """
Alex Chan532b79e2017-01-24 15:14:52 +0000536 `Context.use_privatekey_file` raises `OpenSSL.SSL.Error` when passed
537 the name of a file which does not exist.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800538 """
539 ctx = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000540 with pytest.raises(Error):
541 ctx.use_privatekey_file(tmpfile)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800542
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400543 def _use_privatekey_file_test(self, pemfile, filetype):
544 """
545 Verify that calling ``Context.use_privatekey_file`` with the given
546 arguments does not raise an exception.
547 """
548 key = PKey()
549 key.generate_key(TYPE_RSA, 128)
550
551 with open(pemfile, "wt") as pem:
552 pem.write(
553 dump_privatekey(FILETYPE_PEM, key).decode("ascii")
554 )
555
556 ctx = Context(TLSv1_METHOD)
557 ctx.use_privatekey_file(pemfile, filetype)
558
Alex Chanfb078d82017-04-20 11:16:15 +0100559 @pytest.mark.parametrize('filetype', [object(), "", None, 1.0])
560 def test_wrong_privatekey_file_wrong_args(self, tmpfile, filetype):
561 """
562 `Context.use_privatekey_file` raises `TypeError` when called with
563 a `filetype` which is not a valid file encoding.
564 """
565 ctx = Context(TLSv1_METHOD)
566 with pytest.raises(TypeError):
567 ctx.use_privatekey_file(tmpfile, filetype)
568
Alex Chan532b79e2017-01-24 15:14:52 +0000569 def test_use_privatekey_file_bytes(self, tmpfile):
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400570 """
571 A private key can be specified from a file by passing a ``bytes``
572 instance giving the file name to ``Context.use_privatekey_file``.
573 """
574 self._use_privatekey_file_test(
Alex Chan532b79e2017-01-24 15:14:52 +0000575 tmpfile + NON_ASCII.encode(getfilesystemencoding()),
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400576 FILETYPE_PEM,
577 )
578
Alex Chan532b79e2017-01-24 15:14:52 +0000579 def test_use_privatekey_file_unicode(self, tmpfile):
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400580 """
581 A private key can be specified from a file by passing a ``unicode``
582 instance giving the file name to ``Context.use_privatekey_file``.
583 """
584 self._use_privatekey_file_test(
Alex Chan532b79e2017-01-24 15:14:52 +0000585 tmpfile.decode(getfilesystemencoding()) + NON_ASCII,
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400586 FILETYPE_PEM,
587 )
588
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200589 @skip_if_py3
Alex Chan532b79e2017-01-24 15:14:52 +0000590 def test_use_privatekey_file_long(self, tmpfile):
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200591 """
Alex Chan532b79e2017-01-24 15:14:52 +0000592 On Python 2 `Context.use_privatekey_file` accepts a filetype of
593 type `long` as well as `int`.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200594 """
Alex Chan532b79e2017-01-24 15:14:52 +0000595 self._use_privatekey_file_test(tmpfile, long(FILETYPE_PEM))
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500596
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800597 def test_use_certificate_wrong_args(self):
598 """
Alex Chan532b79e2017-01-24 15:14:52 +0000599 `Context.use_certificate_wrong_args` raises `TypeError` when not passed
600 exactly one `OpenSSL.crypto.X509` instance as an argument.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800601 """
602 ctx = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000603 with pytest.raises(TypeError):
604 ctx.use_certificate("hello, world")
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800605
606 def test_use_certificate_uninitialized(self):
607 """
Alex Chan532b79e2017-01-24 15:14:52 +0000608 `Context.use_certificate` raises `OpenSSL.SSL.Error` when passed a
609 `OpenSSL.crypto.X509` instance which has not been initialized
610 (ie, which does not actually have any certificate data).
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800611 """
612 ctx = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000613 with pytest.raises(Error):
614 ctx.use_certificate(X509())
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800615
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800616 def test_use_certificate(self):
617 """
Alex Chan532b79e2017-01-24 15:14:52 +0000618 `Context.use_certificate` sets the certificate which will be
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800619 used to identify connections created using the context.
620 """
621 # TODO
622 # Hard to assert anything. But we could set a privatekey then ask
623 # OpenSSL if the cert and key agree using check_privatekey. Then as
624 # long as check_privatekey works right we're good...
625 ctx = Context(TLSv1_METHOD)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200626 ctx.use_certificate(
627 load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
628 )
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800629
630 def test_use_certificate_file_wrong_args(self):
631 """
Alex Chan532b79e2017-01-24 15:14:52 +0000632 `Context.use_certificate_file` raises `TypeError` if the first
633 argument is not a byte string or the second argument is not an integer.
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(TypeError):
637 ctx.use_certificate_file(object(), FILETYPE_PEM)
638 with pytest.raises(TypeError):
639 ctx.use_certificate_file(b"somefile", object())
640 with pytest.raises(TypeError):
641 ctx.use_certificate_file(object(), FILETYPE_PEM)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800642
Alex Chan532b79e2017-01-24 15:14:52 +0000643 def test_use_certificate_file_missing(self, tmpfile):
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800644 """
Alex Chan532b79e2017-01-24 15:14:52 +0000645 `Context.use_certificate_file` raises `OpenSSL.SSL.Error` if passed
646 the name of a file which does not exist.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800647 """
648 ctx = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000649 with pytest.raises(Error):
650 ctx.use_certificate_file(tmpfile)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800651
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400652 def _use_certificate_file_test(self, certificate_file):
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800653 """
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400654 Verify that calling ``Context.use_certificate_file`` with the given
655 filename doesn't raise an exception.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800656 """
657 # TODO
658 # Hard to assert anything. But we could set a privatekey then ask
659 # OpenSSL if the cert and key agree using check_privatekey. Then as
660 # long as check_privatekey works right we're good...
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400661 with open(certificate_file, "wb") as pem_file:
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800662 pem_file.write(cleartextCertificatePEM)
663
664 ctx = Context(TLSv1_METHOD)
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400665 ctx.use_certificate_file(certificate_file)
666
Alex Chan532b79e2017-01-24 15:14:52 +0000667 def test_use_certificate_file_bytes(self, tmpfile):
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400668 """
Alex Chan532b79e2017-01-24 15:14:52 +0000669 `Context.use_certificate_file` sets the certificate (given as a
670 `bytes` filename) which will be used to identify connections created
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400671 using the context.
672 """
Alex Chan532b79e2017-01-24 15:14:52 +0000673 filename = tmpfile + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400674 self._use_certificate_file_test(filename)
675
Alex Chan532b79e2017-01-24 15:14:52 +0000676 def test_use_certificate_file_unicode(self, tmpfile):
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400677 """
Alex Chan532b79e2017-01-24 15:14:52 +0000678 `Context.use_certificate_file` sets the certificate (given as a
679 `bytes` filename) which will be used to identify connections created
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400680 using the context.
681 """
Alex Chan532b79e2017-01-24 15:14:52 +0000682 filename = tmpfile.decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400683 self._use_certificate_file_test(filename)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800684
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200685 @skip_if_py3
Alex Chan532b79e2017-01-24 15:14:52 +0000686 def test_use_certificate_file_long(self, tmpfile):
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200687 """
Alex Chan532b79e2017-01-24 15:14:52 +0000688 On Python 2 `Context.use_certificate_file` accepts a
689 filetype of type `long` as well as `int`.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200690 """
Alex Chan532b79e2017-01-24 15:14:52 +0000691 pem_filename = tmpfile
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200692 with open(pem_filename, "wb") as pem_file:
693 pem_file.write(cleartextCertificatePEM)
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500694
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200695 ctx = Context(TLSv1_METHOD)
696 ctx.use_certificate_file(pem_filename, long(FILETYPE_PEM))
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500697
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500698 def test_check_privatekey_valid(self):
699 """
Alex Chan532b79e2017-01-24 15:14:52 +0000700 `Context.check_privatekey` returns `None` if the `Context` instance
701 has been configured to use a matched key and certificate pair.
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500702 """
703 key = load_privatekey(FILETYPE_PEM, client_key_pem)
704 cert = load_certificate(FILETYPE_PEM, client_cert_pem)
705 context = Context(TLSv1_METHOD)
706 context.use_privatekey(key)
707 context.use_certificate(cert)
Alex Chan532b79e2017-01-24 15:14:52 +0000708 assert None is context.check_privatekey()
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500709
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500710 def test_check_privatekey_invalid(self):
711 """
Alex Chan532b79e2017-01-24 15:14:52 +0000712 `Context.check_privatekey` raises `Error` if the `Context` instance
713 has been configured to use a key and certificate pair which don't
714 relate to each other.
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500715 """
716 key = load_privatekey(FILETYPE_PEM, client_key_pem)
717 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
718 context = Context(TLSv1_METHOD)
719 context.use_privatekey(key)
720 context.use_certificate(cert)
Alex Chan532b79e2017-01-24 15:14:52 +0000721 with pytest.raises(Error):
722 context.check_privatekey()
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400723
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400724 def test_app_data(self):
725 """
Alex Chan532b79e2017-01-24 15:14:52 +0000726 `Context.set_app_data` stores an object for later retrieval
727 using `Context.get_app_data`.
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400728 """
729 app_data = object()
730 context = Context(TLSv1_METHOD)
731 context.set_app_data(app_data)
Alex Chan532b79e2017-01-24 15:14:52 +0000732 assert context.get_app_data() is app_data
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400733
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400734 def test_set_options_wrong_args(self):
735 """
Alex Chan532b79e2017-01-24 15:14:52 +0000736 `Context.set_options` raises `TypeError` if called with
737 a non-`int` argument.
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400738 """
739 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000740 with pytest.raises(TypeError):
741 context.set_options(None)
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400742
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500743 def test_set_options(self):
744 """
Alex Chan532b79e2017-01-24 15:14:52 +0000745 `Context.set_options` returns the new options value.
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500746 """
747 context = Context(TLSv1_METHOD)
748 options = context.set_options(OP_NO_SSLv2)
Alex Gaynor2310f8b2016-09-10 14:39:32 -0400749 assert options & OP_NO_SSLv2 == OP_NO_SSLv2
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500750
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200751 @skip_if_py3
752 def test_set_options_long(self):
753 """
Alex Chan532b79e2017-01-24 15:14:52 +0000754 On Python 2 `Context.set_options` accepts values of type
755 `long` as well as `int`.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200756 """
757 context = Context(TLSv1_METHOD)
758 options = context.set_options(long(OP_NO_SSLv2))
Alex Gaynor2310f8b2016-09-10 14:39:32 -0400759 assert options & OP_NO_SSLv2 == OP_NO_SSLv2
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500760
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300761 def test_set_mode_wrong_args(self):
762 """
Alex Chan532b79e2017-01-24 15:14:52 +0000763 `Context.set_mode` raises `TypeError` if called with
764 a non-`int` argument.
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300765 """
766 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000767 with pytest.raises(TypeError):
768 context.set_mode(None)
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300769
Alex Gaynord3b5d9b2016-07-31 10:54:24 -0400770 def test_set_mode(self):
771 """
Alex Chan532b79e2017-01-24 15:14:52 +0000772 `Context.set_mode` accepts a mode bitvector and returns the
Alex Gaynord3b5d9b2016-07-31 10:54:24 -0400773 newly set mode.
774 """
775 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000776 assert MODE_RELEASE_BUFFERS & context.set_mode(MODE_RELEASE_BUFFERS)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500777
Alex Gaynord3b5d9b2016-07-31 10:54:24 -0400778 @skip_if_py3
779 def test_set_mode_long(self):
780 """
Alex Chan532b79e2017-01-24 15:14:52 +0000781 On Python 2 `Context.set_mode` accepts values of type `long` as well
782 as `int`.
Alex Gaynord3b5d9b2016-07-31 10:54:24 -0400783 """
784 context = Context(TLSv1_METHOD)
785 mode = context.set_mode(long(MODE_RELEASE_BUFFERS))
Alex Chan532b79e2017-01-24 15:14:52 +0000786 assert MODE_RELEASE_BUFFERS & mode
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400787
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400788 def test_set_timeout_wrong_args(self):
789 """
Alex Chan532b79e2017-01-24 15:14:52 +0000790 `Context.set_timeout` raises `TypeError` if called with
791 a non-`int` argument.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400792 """
793 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000794 with pytest.raises(TypeError):
795 context.set_timeout(None)
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400796
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400797 def test_timeout(self):
798 """
Alex Chan532b79e2017-01-24 15:14:52 +0000799 `Context.set_timeout` sets the session timeout for all connections
800 created using the context object. `Context.get_timeout` retrieves
801 this value.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400802 """
803 context = Context(TLSv1_METHOD)
804 context.set_timeout(1234)
Alex Chan532b79e2017-01-24 15:14:52 +0000805 assert context.get_timeout() == 1234
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400806
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200807 @skip_if_py3
808 def test_timeout_long(self):
809 """
Alex Chan532b79e2017-01-24 15:14:52 +0000810 On Python 2 `Context.set_timeout` accepts values of type `long` as
811 well as int.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200812 """
813 context = Context(TLSv1_METHOD)
814 context.set_timeout(long(1234))
Alex Chan532b79e2017-01-24 15:14:52 +0000815 assert context.get_timeout() == 1234
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500816
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400817 def test_set_verify_depth_wrong_args(self):
818 """
Alex Chan532b79e2017-01-24 15:14:52 +0000819 `Context.set_verify_depth` raises `TypeError` if called with a
820 non-`int` argument.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400821 """
822 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000823 with pytest.raises(TypeError):
824 context.set_verify_depth(None)
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400825
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400826 def test_verify_depth(self):
827 """
Alex Chan532b79e2017-01-24 15:14:52 +0000828 `Context.set_verify_depth` sets the number of certificates in
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200829 a chain to follow before giving up. The value can be retrieved with
Alex Chan532b79e2017-01-24 15:14:52 +0000830 `Context.get_verify_depth`.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400831 """
832 context = Context(TLSv1_METHOD)
833 context.set_verify_depth(11)
Alex Chan532b79e2017-01-24 15:14:52 +0000834 assert context.get_verify_depth() == 11
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400835
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200836 @skip_if_py3
837 def test_verify_depth_long(self):
838 """
Alex Chan532b79e2017-01-24 15:14:52 +0000839 On Python 2 `Context.set_verify_depth` accepts values of type `long`
840 as well as int.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200841 """
842 context = Context(TLSv1_METHOD)
843 context.set_verify_depth(long(11))
Alex Chan532b79e2017-01-24 15:14:52 +0000844 assert context.get_verify_depth() == 11
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500845
Alex Chan532b79e2017-01-24 15:14:52 +0000846 def _write_encrypted_pem(self, passphrase, tmpfile):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400847 """
848 Write a new private key out to a new file, encrypted using the given
849 passphrase. Return the path to the new file.
850 """
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400851 key = PKey()
852 key.generate_key(TYPE_RSA, 128)
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400853 pem = dump_privatekey(FILETYPE_PEM, key, "blowfish", passphrase)
Alex Chan532b79e2017-01-24 15:14:52 +0000854 with open(tmpfile, 'w') as fObj:
855 fObj.write(pem.decode('ascii'))
856 return tmpfile
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400857
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400858 def test_set_passwd_cb_wrong_args(self):
859 """
Alex Chan532b79e2017-01-24 15:14:52 +0000860 `Context.set_passwd_cb` raises `TypeError` if called with a
861 non-callable first argument.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400862 """
863 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000864 with pytest.raises(TypeError):
865 context.set_passwd_cb(None)
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400866
Alex Chan532b79e2017-01-24 15:14:52 +0000867 def test_set_passwd_cb(self, tmpfile):
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400868 """
Alex Chan532b79e2017-01-24 15:14:52 +0000869 `Context.set_passwd_cb` accepts a callable which will be invoked when
870 a private key is loaded from an encrypted PEM.
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400871 """
Alex Gaynore7f51982016-09-11 11:48:14 -0400872 passphrase = b"foobar"
Alex Chan532b79e2017-01-24 15:14:52 +0000873 pemFile = self._write_encrypted_pem(passphrase, tmpfile)
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400874 calledWith = []
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200875
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400876 def passphraseCallback(maxlen, verify, extra):
877 calledWith.append((maxlen, verify, extra))
878 return passphrase
879 context = Context(TLSv1_METHOD)
880 context.set_passwd_cb(passphraseCallback)
881 context.use_privatekey_file(pemFile)
Alex Chan532b79e2017-01-24 15:14:52 +0000882 assert len(calledWith) == 1
883 assert isinstance(calledWith[0][0], int)
884 assert isinstance(calledWith[0][1], int)
885 assert calledWith[0][2] is None
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400886
Alex Chan532b79e2017-01-24 15:14:52 +0000887 def test_passwd_callback_exception(self, tmpfile):
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400888 """
Alex Chan532b79e2017-01-24 15:14:52 +0000889 `Context.use_privatekey_file` propagates any exception raised
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200890 by the passphrase callback.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400891 """
Alex Chan532b79e2017-01-24 15:14:52 +0000892 pemFile = self._write_encrypted_pem(b"monkeys are nice", tmpfile)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200893
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400894 def passphraseCallback(maxlen, verify, extra):
895 raise RuntimeError("Sorry, I am a fail.")
896
897 context = Context(TLSv1_METHOD)
898 context.set_passwd_cb(passphraseCallback)
Alex Chan532b79e2017-01-24 15:14:52 +0000899 with pytest.raises(RuntimeError):
900 context.use_privatekey_file(pemFile)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400901
Alex Chan532b79e2017-01-24 15:14:52 +0000902 def test_passwd_callback_false(self, tmpfile):
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400903 """
Alex Chan532b79e2017-01-24 15:14:52 +0000904 `Context.use_privatekey_file` raises `OpenSSL.SSL.Error` if the
905 passphrase callback returns a false value.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400906 """
Alex Chan532b79e2017-01-24 15:14:52 +0000907 pemFile = self._write_encrypted_pem(b"monkeys are nice", tmpfile)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200908
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400909 def passphraseCallback(maxlen, verify, extra):
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500910 return b""
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400911
912 context = Context(TLSv1_METHOD)
913 context.set_passwd_cb(passphraseCallback)
Alex Chan532b79e2017-01-24 15:14:52 +0000914 with pytest.raises(Error):
915 context.use_privatekey_file(pemFile)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400916
Alex Chan532b79e2017-01-24 15:14:52 +0000917 def test_passwd_callback_non_string(self, tmpfile):
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400918 """
Alex Chan532b79e2017-01-24 15:14:52 +0000919 `Context.use_privatekey_file` raises `OpenSSL.SSL.Error` if the
920 passphrase callback returns a true non-string value.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400921 """
Alex Chan532b79e2017-01-24 15:14:52 +0000922 pemFile = self._write_encrypted_pem(b"monkeys are nice", tmpfile)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200923
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400924 def passphraseCallback(maxlen, verify, extra):
925 return 10
926
927 context = Context(TLSv1_METHOD)
928 context.set_passwd_cb(passphraseCallback)
Alex Chan532b79e2017-01-24 15:14:52 +0000929 # TODO: Surely this is the wrong error?
930 with pytest.raises(ValueError):
931 context.use_privatekey_file(pemFile)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400932
Alex Chan532b79e2017-01-24 15:14:52 +0000933 def test_passwd_callback_too_long(self, tmpfile):
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400934 """
935 If the passphrase returned by the passphrase callback returns a string
936 longer than the indicated maximum length, it is truncated.
937 """
938 # A priori knowledge!
Alex Gaynore7f51982016-09-11 11:48:14 -0400939 passphrase = b"x" * 1024
Alex Chan532b79e2017-01-24 15:14:52 +0000940 pemFile = self._write_encrypted_pem(passphrase, tmpfile)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200941
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400942 def passphraseCallback(maxlen, verify, extra):
943 assert maxlen == 1024
Alex Gaynore7f51982016-09-11 11:48:14 -0400944 return passphrase + b"y"
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400945
946 context = Context(TLSv1_METHOD)
947 context.set_passwd_cb(passphraseCallback)
948 # This shall succeed because the truncated result is the correct
949 # passphrase.
950 context.use_privatekey_file(pemFile)
951
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400952 def test_set_info_callback(self):
953 """
Alex Chan532b79e2017-01-24 15:14:52 +0000954 `Context.set_info_callback` accepts a callable which will be
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200955 invoked when certain information about an SSL connection is available.
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400956 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500957 (server, client) = socket_pair()
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400958
959 clientSSL = Connection(Context(TLSv1_METHOD), client)
960 clientSSL.set_connect_state()
961
962 called = []
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200963
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400964 def info(conn, where, ret):
965 called.append((conn, where, ret))
966 context = Context(TLSv1_METHOD)
967 context.set_info_callback(info)
968 context.use_certificate(
969 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
970 context.use_privatekey(
971 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
972
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400973 serverSSL = Connection(context, server)
974 serverSSL.set_accept_state()
975
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -0500976 handshake(clientSSL, serverSSL)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400977
Jean-Paul Calderone3835e522014-02-02 11:12:30 -0500978 # The callback must always be called with a Connection instance as the
979 # first argument. It would probably be better to split this into
980 # separate tests for client and server side info callbacks so we could
981 # assert it is called with the right Connection instance. It would
982 # also be good to assert *something* about `where` and `ret`.
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -0500983 notConnections = [
984 conn for (conn, where, ret) in called
985 if not isinstance(conn, Connection)]
Alex Chan532b79e2017-01-24 15:14:52 +0000986 assert [] == notConnections, (
987 "Some info callback arguments were not Connection instances.")
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400988
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400989 def _load_verify_locations_test(self, *args):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400990 """
991 Create a client context which will verify the peer certificate and call
Alex Chan532b79e2017-01-24 15:14:52 +0000992 its `load_verify_locations` method with the given arguments.
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -0400993 Then connect it to a server and ensure that the handshake succeeds.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400994 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500995 (server, client) = socket_pair()
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400996
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400997 clientContext = Context(TLSv1_METHOD)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400998 clientContext.load_verify_locations(*args)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400999 # Require that the server certificate verify properly or the
1000 # connection will fail.
1001 clientContext.set_verify(
1002 VERIFY_PEER,
1003 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
1004
1005 clientSSL = Connection(clientContext, client)
1006 clientSSL.set_connect_state()
1007
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001008 serverContext = Context(TLSv1_METHOD)
1009 serverContext.use_certificate(
1010 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1011 serverContext.use_privatekey(
1012 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1013
1014 serverSSL = Connection(serverContext, server)
1015 serverSSL.set_accept_state()
1016
Jean-Paul Calderonef8742032010-09-25 00:00:32 -04001017 # Without load_verify_locations above, the handshake
1018 # will fail:
1019 # Error: [('SSL routines', 'SSL3_GET_SERVER_CERTIFICATE',
1020 # 'certificate verify failed')]
1021 handshake(clientSSL, serverSSL)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001022
1023 cert = clientSSL.get_peer_certificate()
Alex Chan532b79e2017-01-24 15:14:52 +00001024 assert cert.get_subject().CN == 'Testing Root CA'
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -04001025
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001026 def _load_verify_cafile(self, cafile):
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001027 """
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001028 Verify that if path to a file containing a certificate is passed to
Alex Chan532b79e2017-01-24 15:14:52 +00001029 `Context.load_verify_locations` for the ``cafile`` parameter, that
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001030 certificate is used as a trust root for the purposes of verifying
Alex Chan532b79e2017-01-24 15:14:52 +00001031 connections created using that `Context`.
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001032 """
Alex Chan532b79e2017-01-24 15:14:52 +00001033 with open(cafile, 'w') as fObj:
1034 fObj.write(cleartextCertificatePEM.decode('ascii'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001035
1036 self._load_verify_locations_test(cafile)
1037
Alex Chan532b79e2017-01-24 15:14:52 +00001038 def test_load_verify_bytes_cafile(self, tmpfile):
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001039 """
Alex Chan532b79e2017-01-24 15:14:52 +00001040 `Context.load_verify_locations` accepts a file name as a `bytes`
1041 instance and uses the certificates within for verification purposes.
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001042 """
Alex Chan532b79e2017-01-24 15:14:52 +00001043 cafile = tmpfile + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001044 self._load_verify_cafile(cafile)
1045
Alex Chan532b79e2017-01-24 15:14:52 +00001046 def test_load_verify_unicode_cafile(self, tmpfile):
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001047 """
Alex Chan532b79e2017-01-24 15:14:52 +00001048 `Context.load_verify_locations` accepts a file name as a `unicode`
1049 instance and uses the certificates within for verification purposes.
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001050 """
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001051 self._load_verify_cafile(
Alex Chan532b79e2017-01-24 15:14:52 +00001052 tmpfile.decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001053 )
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001054
Alex Chan532b79e2017-01-24 15:14:52 +00001055 def test_load_verify_invalid_file(self, tmpfile):
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -04001056 """
Alex Chan532b79e2017-01-24 15:14:52 +00001057 `Context.load_verify_locations` raises `Error` when passed a
1058 non-existent cafile.
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -04001059 """
1060 clientContext = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001061 with pytest.raises(Error):
1062 clientContext.load_verify_locations(tmpfile)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001063
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001064 def _load_verify_directory_locations_capath(self, capath):
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001065 """
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001066 Verify that if path to a directory containing certificate files is
1067 passed to ``Context.load_verify_locations`` for the ``capath``
1068 parameter, those certificates are used as trust roots for the purposes
1069 of verifying connections created using that ``Context``.
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001070 """
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001071 makedirs(capath)
Jean-Paul Calderone24dfb332011-05-04 18:10:26 -04001072 # Hash values computed manually with c_rehash to avoid depending on
1073 # c_rehash in the test suite. One is from OpenSSL 0.9.8, the other
1074 # from OpenSSL 1.0.0.
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001075 for name in [b'c7adac82.0', b'c3705638.0']:
Jean-Paul Calderone05826732015-04-12 11:38:49 -04001076 cafile = join_bytes_or_unicode(capath, name)
1077 with open(cafile, 'w') as fObj:
1078 fObj.write(cleartextCertificatePEM.decode('ascii'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001079
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001080 self._load_verify_locations_test(None, capath)
1081
Alex Chan532b79e2017-01-24 15:14:52 +00001082 def test_load_verify_directory_bytes_capath(self, tmpfile):
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001083 """
Alex Chan532b79e2017-01-24 15:14:52 +00001084 `Context.load_verify_locations` accepts a directory name as a `bytes`
1085 instance and uses the certificates within for verification purposes.
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001086 """
1087 self._load_verify_directory_locations_capath(
Alex Chan532b79e2017-01-24 15:14:52 +00001088 tmpfile + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001089 )
1090
Alex Chan532b79e2017-01-24 15:14:52 +00001091 def test_load_verify_directory_unicode_capath(self, tmpfile):
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001092 """
Alex Chan532b79e2017-01-24 15:14:52 +00001093 `Context.load_verify_locations` accepts a directory name as a `unicode`
1094 instance and uses the certificates within for verification purposes.
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001095 """
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001096 self._load_verify_directory_locations_capath(
Alex Chan532b79e2017-01-24 15:14:52 +00001097 tmpfile.decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001098 )
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001099
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001100 def test_load_verify_locations_wrong_args(self):
1101 """
Alex Chan532b79e2017-01-24 15:14:52 +00001102 `Context.load_verify_locations` raises `TypeError` if with non-`str`
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001103 arguments.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001104 """
1105 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001106 with pytest.raises(TypeError):
1107 context.load_verify_locations(object())
1108 with pytest.raises(TypeError):
1109 context.load_verify_locations(object(), object())
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001110
Hynek Schlawack734d3022015-09-05 19:19:32 +02001111 @pytest.mark.skipif(
1112 platform == "win32",
1113 reason="set_default_verify_paths appears not to work on Windows. "
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -04001114 "See LP#404343 and LP#404344."
Hynek Schlawack734d3022015-09-05 19:19:32 +02001115 )
1116 def test_set_default_verify_paths(self):
1117 """
Alex Chan532b79e2017-01-24 15:14:52 +00001118 `Context.set_default_verify_paths` causes the platform-specific CA
1119 certificate locations to be used for verification purposes.
Hynek Schlawack734d3022015-09-05 19:19:32 +02001120 """
1121 # Testing this requires a server with a certificate signed by one
1122 # of the CAs in the platform CA location. Getting one of those
1123 # costs money. Fortunately (or unfortunately, depending on your
1124 # perspective), it's easy to think of a public server on the
1125 # internet which has such a certificate. Connecting to the network
1126 # in a unit test is bad, but it's the only way I can think of to
1127 # really test this. -exarkun
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001128
Hynek Schlawack734d3022015-09-05 19:19:32 +02001129 # Arg, verisign.com doesn't speak anything newer than TLS 1.0
Hynek Schlawackbf887932015-10-21 17:13:47 +02001130 context = Context(SSLv23_METHOD)
Hynek Schlawack734d3022015-09-05 19:19:32 +02001131 context.set_default_verify_paths()
1132 context.set_verify(
1133 VERIFY_PEER,
1134 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001135
Hynek Schlawack734d3022015-09-05 19:19:32 +02001136 client = socket()
Hynek Schlawackbf887932015-10-21 17:13:47 +02001137 client.connect(("encrypted.google.com", 443))
Hynek Schlawack734d3022015-09-05 19:19:32 +02001138 clientSSL = Connection(context, client)
1139 clientSSL.set_connect_state()
1140 clientSSL.do_handshake()
1141 clientSSL.send(b"GET / HTTP/1.0\r\n\r\n")
Alex Chan532b79e2017-01-24 15:14:52 +00001142 assert clientSSL.recv(1024)
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05001143
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001144 def test_add_extra_chain_cert_invalid_cert(self):
1145 """
Alex Chan532b79e2017-01-24 15:14:52 +00001146 `Context.add_extra_chain_cert` raises `TypeError` if called with an
1147 object which is not an instance of `X509`.
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001148 """
1149 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001150 with pytest.raises(TypeError):
1151 context.add_extra_chain_cert(object())
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001152
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001153 def _handshake_test(self, serverContext, clientContext):
1154 """
1155 Verify that a client and server created with the given contexts can
1156 successfully handshake and communicate.
1157 """
1158 serverSocket, clientSocket = socket_pair()
1159
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001160 server = Connection(serverContext, serverSocket)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001161 server.set_accept_state()
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001162
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001163 client = Connection(clientContext, clientSocket)
1164 client.set_connect_state()
1165
1166 # Make them talk to each other.
Alex Chan532b79e2017-01-24 15:14:52 +00001167 # interact_in_memory(client, server)
1168 for _ in range(3):
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001169 for s in [client, server]:
1170 try:
1171 s.do_handshake()
1172 except WantReadError:
1173 pass
1174
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001175 def test_set_verify_callback_connection_argument(self):
1176 """
1177 The first argument passed to the verify callback is the
Alex Chan532b79e2017-01-24 15:14:52 +00001178 `Connection` instance for which verification is taking place.
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001179 """
1180 serverContext = Context(TLSv1_METHOD)
1181 serverContext.use_privatekey(
1182 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1183 serverContext.use_certificate(
1184 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1185 serverConnection = Connection(serverContext, None)
1186
1187 class VerifyCallback(object):
1188 def callback(self, connection, *args):
1189 self.connection = connection
1190 return 1
1191
1192 verify = VerifyCallback()
1193 clientContext = Context(TLSv1_METHOD)
1194 clientContext.set_verify(VERIFY_PEER, verify.callback)
1195 clientConnection = Connection(clientContext, None)
1196 clientConnection.set_connect_state()
1197
Alex Chan532b79e2017-01-24 15:14:52 +00001198 handshake_in_memory(clientConnection, serverConnection)
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001199
Alex Chan532b79e2017-01-24 15:14:52 +00001200 assert verify.connection is clientConnection
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001201
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001202 def test_set_verify_callback_exception(self):
1203 """
Alex Chan532b79e2017-01-24 15:14:52 +00001204 If the verify callback passed to `Context.set_verify` raises an
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001205 exception, verification fails and the exception is propagated to the
Alex Chan532b79e2017-01-24 15:14:52 +00001206 caller of `Connection.do_handshake`.
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001207 """
1208 serverContext = Context(TLSv1_METHOD)
1209 serverContext.use_privatekey(
1210 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1211 serverContext.use_certificate(
1212 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1213
1214 clientContext = Context(TLSv1_METHOD)
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001215
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001216 def verify_callback(*args):
1217 raise Exception("silly verify failure")
1218 clientContext.set_verify(VERIFY_PEER, verify_callback)
1219
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01001220 with pytest.raises(Exception) as exc:
1221 self._handshake_test(serverContext, clientContext)
1222
Alex Chan532b79e2017-01-24 15:14:52 +00001223 assert "silly verify failure" == str(exc.value)
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001224
Alex Chan532b79e2017-01-24 15:14:52 +00001225 def test_add_extra_chain_cert(self, tmpdir):
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001226 """
Alex Chan532b79e2017-01-24 15:14:52 +00001227 `Context.add_extra_chain_cert` accepts an `X509`
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001228 instance to add to the certificate chain.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001229
Alex Chan532b79e2017-01-24 15:14:52 +00001230 See `_create_certificate_chain` for the details of the
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001231 certificate chain tested.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001232
1233 The chain is tested by starting a server with scert and connecting
1234 to it with a client which trusts cacert and requires verification to
1235 succeed.
1236 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001237 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001238 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1239
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001240 # Dump the CA certificate to a file because that's the only way to load
1241 # it as a trusted CA in the client context.
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001242 for cert, name in [(cacert, 'ca.pem'),
1243 (icert, 'i.pem'),
1244 (scert, 's.pem')]:
Alex Chan532b79e2017-01-24 15:14:52 +00001245 with tmpdir.join(name).open('w') as f:
Hynek Schlawacke90680f2015-04-16 15:09:27 -04001246 f.write(dump_certificate(FILETYPE_PEM, cert).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001247
Hynek Schlawack1902c012015-04-16 15:06:41 -04001248 for key, name in [(cakey, 'ca.key'),
1249 (ikey, 'i.key'),
1250 (skey, 's.key')]:
Alex Chan532b79e2017-01-24 15:14:52 +00001251 with tmpdir.join(name).open('w') as f:
Hynek Schlawacke90680f2015-04-16 15:09:27 -04001252 f.write(dump_privatekey(FILETYPE_PEM, key).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001253
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001254 # Create the server context
1255 serverContext = Context(TLSv1_METHOD)
1256 serverContext.use_privatekey(skey)
1257 serverContext.use_certificate(scert)
Jean-Paul Calderone16cf03d2010-09-08 18:53:39 -04001258 # The client already has cacert, we only need to give them icert.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001259 serverContext.add_extra_chain_cert(icert)
1260
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001261 # Create the client
1262 clientContext = Context(TLSv1_METHOD)
1263 clientContext.set_verify(
1264 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Alex Chan532b79e2017-01-24 15:14:52 +00001265 clientContext.load_verify_locations(str(tmpdir.join("ca.pem")))
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001266
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001267 # Try it out.
1268 self._handshake_test(serverContext, clientContext)
1269
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001270 def _use_certificate_chain_file_test(self, certdir):
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001271 """
Alex Chan532b79e2017-01-24 15:14:52 +00001272 Verify that `Context.use_certificate_chain_file` reads a
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001273 certificate chain from a specified file.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001274
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001275 The chain is tested by starting a server with scert and connecting to
1276 it with a client which trusts cacert and requires verification to
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001277 succeed.
1278 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001279 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001280 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1281
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001282 makedirs(certdir)
1283
Jean-Paul Calderone05826732015-04-12 11:38:49 -04001284 chainFile = join_bytes_or_unicode(certdir, "chain.pem")
1285 caFile = join_bytes_or_unicode(certdir, "ca.pem")
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001286
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001287 # Write out the chain file.
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001288 with open(chainFile, 'wb') as fObj:
1289 # Most specific to least general.
1290 fObj.write(dump_certificate(FILETYPE_PEM, scert))
1291 fObj.write(dump_certificate(FILETYPE_PEM, icert))
1292 fObj.write(dump_certificate(FILETYPE_PEM, cacert))
1293
1294 with open(caFile, 'w') as fObj:
1295 fObj.write(dump_certificate(FILETYPE_PEM, cacert).decode('ascii'))
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001296
1297 serverContext = Context(TLSv1_METHOD)
1298 serverContext.use_certificate_chain_file(chainFile)
1299 serverContext.use_privatekey(skey)
1300
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001301 clientContext = Context(TLSv1_METHOD)
1302 clientContext.set_verify(
1303 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001304 clientContext.load_verify_locations(caFile)
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001305
1306 self._handshake_test(serverContext, clientContext)
1307
Alex Chan532b79e2017-01-24 15:14:52 +00001308 def test_use_certificate_chain_file_bytes(self, tmpfile):
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001309 """
1310 ``Context.use_certificate_chain_file`` accepts the name of a file (as
1311 an instance of ``bytes``) to specify additional certificates to use to
1312 construct and verify a trust chain.
1313 """
1314 self._use_certificate_chain_file_test(
Alex Chan532b79e2017-01-24 15:14:52 +00001315 tmpfile + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001316 )
1317
Alex Chan532b79e2017-01-24 15:14:52 +00001318 def test_use_certificate_chain_file_unicode(self, tmpfile):
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001319 """
1320 ``Context.use_certificate_chain_file`` accepts the name of a file (as
1321 an instance of ``unicode``) to specify additional certificates to use
1322 to construct and verify a trust chain.
1323 """
1324 self._use_certificate_chain_file_test(
Alex Chan532b79e2017-01-24 15:14:52 +00001325 tmpfile.decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001326 )
1327
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001328 def test_use_certificate_chain_file_wrong_args(self):
1329 """
Alex Chan532b79e2017-01-24 15:14:52 +00001330 `Context.use_certificate_chain_file` raises `TypeError` if passed a
1331 non-byte string single argument.
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001332 """
1333 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001334 with pytest.raises(TypeError):
1335 context.use_certificate_chain_file(object())
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001336
Alex Chan532b79e2017-01-24 15:14:52 +00001337 def test_use_certificate_chain_file_missing_file(self, tmpfile):
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001338 """
Alex Chan532b79e2017-01-24 15:14:52 +00001339 `Context.use_certificate_chain_file` raises `OpenSSL.SSL.Error` when
1340 passed a bad chain file name (for example, the name of a file which
1341 does not exist).
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001342 """
1343 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001344 with pytest.raises(Error):
1345 context.use_certificate_chain_file(tmpfile)
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001346
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001347 def test_set_verify_mode(self):
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001348 """
Alex Chan532b79e2017-01-24 15:14:52 +00001349 `Context.get_verify_mode` returns the verify mode flags previously
1350 passed to `Context.set_verify`.
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001351 """
1352 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001353 assert context.get_verify_mode() == 0
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001354 context.set_verify(
1355 VERIFY_PEER | VERIFY_CLIENT_ONCE, lambda *args: None)
Alex Chan532b79e2017-01-24 15:14:52 +00001356 assert context.get_verify_mode() == (VERIFY_PEER | VERIFY_CLIENT_ONCE)
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001357
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001358 @skip_if_py3
1359 def test_set_verify_mode_long(self):
1360 """
Alex Chan532b79e2017-01-24 15:14:52 +00001361 On Python 2 `Context.set_verify_mode` accepts values of type `long`
1362 as well as `int`.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001363 """
1364 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001365 assert context.get_verify_mode() == 0
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001366 context.set_verify(
Hynek Schlawackb4ceed32015-09-05 20:55:19 +02001367 long(VERIFY_PEER | VERIFY_CLIENT_ONCE), lambda *args: None
1368 ) # pragma: nocover
Alex Chan532b79e2017-01-24 15:14:52 +00001369 assert context.get_verify_mode() == (VERIFY_PEER | VERIFY_CLIENT_ONCE)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001370
Alex Chanfb078d82017-04-20 11:16:15 +01001371 @pytest.mark.parametrize('mode', [None, 1.0, object(), 'mode'])
1372 def test_set_verify_wrong_mode_arg(self, mode):
1373 """
1374 `Context.set_verify` raises `TypeError` if the first argument is
1375 not an integer.
1376 """
1377 context = Context(TLSv1_METHOD)
1378 with pytest.raises(TypeError):
1379 context.set_verify(mode=mode, callback=lambda *args: None)
1380
1381 @pytest.mark.parametrize('callback', [None, 1.0, 'mode', ('foo', 'bar')])
1382 def test_set_verify_wrong_callable_arg(self, callback):
1383 """
1384 `Context.set_verify` raises `TypeError` if the the second argument
1385 is not callable.
1386 """
1387 context = Context(TLSv1_METHOD)
1388 with pytest.raises(TypeError):
1389 context.set_verify(mode=VERIFY_PEER, callback=callback)
1390
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001391 def test_load_tmp_dh_wrong_args(self):
1392 """
Alex Chan532b79e2017-01-24 15:14:52 +00001393 `Context.load_tmp_dh` raises `TypeError` if called with a
1394 non-`str` argument.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001395 """
1396 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001397 with pytest.raises(TypeError):
1398 context.load_tmp_dh(object())
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001399
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001400 def test_load_tmp_dh_missing_file(self):
1401 """
Alex Chan532b79e2017-01-24 15:14:52 +00001402 `Context.load_tmp_dh` raises `OpenSSL.SSL.Error` if the
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001403 specified file does not exist.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001404 """
1405 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001406 with pytest.raises(Error):
1407 context.load_tmp_dh(b"hello")
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001408
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001409 def _load_tmp_dh_test(self, dhfilename):
Jean-Paul Calderone4e0c43f2015-04-13 10:15:17 -04001410 """
1411 Verify that calling ``Context.load_tmp_dh`` with the given filename
1412 does not raise an exception.
1413 """
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001414 context = Context(TLSv1_METHOD)
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001415 with open(dhfilename, "w") as dhfile:
1416 dhfile.write(dhparam)
1417
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001418 context.load_tmp_dh(dhfilename)
1419 # XXX What should I assert here? -exarkun
1420
Alex Chan532b79e2017-01-24 15:14:52 +00001421 def test_load_tmp_dh_bytes(self, tmpfile):
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001422 """
Alex Chan532b79e2017-01-24 15:14:52 +00001423 `Context.load_tmp_dh` loads Diffie-Hellman parameters from the
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001424 specified file (given as ``bytes``).
1425 """
1426 self._load_tmp_dh_test(
Alex Chan532b79e2017-01-24 15:14:52 +00001427 tmpfile + NON_ASCII.encode(getfilesystemencoding()),
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001428 )
1429
Alex Chan532b79e2017-01-24 15:14:52 +00001430 def test_load_tmp_dh_unicode(self, tmpfile):
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001431 """
Alex Chan532b79e2017-01-24 15:14:52 +00001432 `Context.load_tmp_dh` loads Diffie-Hellman parameters from the
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001433 specified file (given as ``unicode``).
1434 """
1435 self._load_tmp_dh_test(
Alex Chan532b79e2017-01-24 15:14:52 +00001436 tmpfile.decode(getfilesystemencoding()) + NON_ASCII,
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001437 )
1438
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001439 def test_set_tmp_ecdh(self):
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001440 """
Alex Chan532b79e2017-01-24 15:14:52 +00001441 `Context.set_tmp_ecdh` sets the elliptic curve for Diffie-Hellman to
1442 the specified curve.
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001443 """
1444 context = Context(TLSv1_METHOD)
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001445 for curve in get_elliptic_curves():
Hynek Schlawacka07fa8c2015-10-17 10:15:28 +02001446 if curve.name.startswith(u"Oakley-"):
Hynek Schlawack7408aff2015-10-17 09:51:16 +02001447 # Setting Oakley-EC2N-4 and Oakley-EC2N-3 adds
1448 # ('bignum routines', 'BN_mod_inverse', 'no inverse') to the
1449 # error queue on OpenSSL 1.0.2.
1450 continue
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001451 # The only easily "assertable" thing is that it does not raise an
1452 # exception.
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001453 context.set_tmp_ecdh(curve)
Alex Gaynor12dc0842014-01-17 12:51:31 -06001454
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001455 def test_set_session_cache_mode_wrong_args(self):
1456 """
Alex Chan532b79e2017-01-24 15:14:52 +00001457 `Context.set_session_cache_mode` raises `TypeError` if called with
1458 a non-integer argument.
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001459 called with other than one integer argument.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001460 """
1461 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001462 with pytest.raises(TypeError):
1463 context.set_session_cache_mode(object())
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001464
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001465 def test_session_cache_mode(self):
1466 """
Alex Chan532b79e2017-01-24 15:14:52 +00001467 `Context.set_session_cache_mode` specifies how sessions are cached.
1468 The setting can be retrieved via `Context.get_session_cache_mode`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001469 """
1470 context = Context(TLSv1_METHOD)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001471 context.set_session_cache_mode(SESS_CACHE_OFF)
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001472 off = context.set_session_cache_mode(SESS_CACHE_BOTH)
Alex Chan532b79e2017-01-24 15:14:52 +00001473 assert SESS_CACHE_OFF == off
1474 assert SESS_CACHE_BOTH == context.get_session_cache_mode()
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001475
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001476 @skip_if_py3
1477 def test_session_cache_mode_long(self):
1478 """
Alex Chan532b79e2017-01-24 15:14:52 +00001479 On Python 2 `Context.set_session_cache_mode` accepts values
1480 of type `long` as well as `int`.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001481 """
1482 context = Context(TLSv1_METHOD)
1483 context.set_session_cache_mode(long(SESS_CACHE_BOTH))
Alex Chan532b79e2017-01-24 15:14:52 +00001484 assert SESS_CACHE_BOTH == context.get_session_cache_mode()
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001485
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001486 def test_get_cert_store(self):
1487 """
Alex Chan532b79e2017-01-24 15:14:52 +00001488 `Context.get_cert_store` returns a `X509Store` instance.
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001489 """
1490 context = Context(TLSv1_METHOD)
1491 store = context.get_cert_store()
Alex Chan532b79e2017-01-24 15:14:52 +00001492 assert isinstance(store, X509Store)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001493
1494
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001495class TestServerNameCallback(object):
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001496 """
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001497 Tests for `Context.set_tlsext_servername_callback` and its
1498 interaction with `Connection`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001499 """
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001500 def test_old_callback_forgotten(self):
1501 """
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001502 If `Context.set_tlsext_servername_callback` is used to specify
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001503 a new callback, the one it replaces is dereferenced.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001504 """
Alex Chanfb078d82017-04-20 11:16:15 +01001505 def callback(connection): # pragma: no cover
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001506 pass
1507
Alex Chanfb078d82017-04-20 11:16:15 +01001508 def replacement(connection): # pragma: no cover
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001509 pass
1510
1511 context = Context(TLSv1_METHOD)
1512 context.set_tlsext_servername_callback(callback)
1513
1514 tracker = ref(callback)
1515 del callback
1516
1517 context.set_tlsext_servername_callback(replacement)
Jean-Paul Calderoned4033eb2014-01-11 08:21:46 -05001518
1519 # One run of the garbage collector happens to work on CPython. PyPy
1520 # doesn't collect the underlying object until a second run for whatever
1521 # reason. That's fine, it still demonstrates our code has properly
1522 # dropped the reference.
1523 collect()
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001524 collect()
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001525
1526 callback = tracker()
1527 if callback is not None:
1528 referrers = get_referrers(callback)
Alex Chanfb078d82017-04-20 11:16:15 +01001529 if len(referrers) > 1: # pragma: nocover
1530 pytest.fail("Some references remain: %r" % (referrers,))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001531
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001532 def test_no_servername(self):
1533 """
1534 When a client specifies no server name, the callback passed to
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001535 `Context.set_tlsext_servername_callback` is invoked and the
1536 result of `Connection.get_servername` is `None`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001537 """
1538 args = []
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001539
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001540 def servername(conn):
1541 args.append((conn, conn.get_servername()))
1542 context = Context(TLSv1_METHOD)
1543 context.set_tlsext_servername_callback(servername)
1544
1545 # Lose our reference to it. The Context is responsible for keeping it
1546 # alive now.
1547 del servername
1548 collect()
1549
1550 # Necessary to actually accept the connection
1551 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001552 context.use_certificate(
1553 load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001554
1555 # Do a little connection to trigger the logic
1556 server = Connection(context, None)
1557 server.set_accept_state()
1558
1559 client = Connection(Context(TLSv1_METHOD), None)
1560 client.set_connect_state()
1561
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001562 interact_in_memory(server, client)
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001563
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001564 assert args == [(server, None)]
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001565
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001566 def test_servername(self):
1567 """
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001568 When a client specifies a server name in its hello message, the
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001569 callback passed to `Contexts.set_tlsext_servername_callback` is
1570 invoked and the result of `Connection.get_servername` is that
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001571 server name.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001572 """
1573 args = []
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001574
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001575 def servername(conn):
1576 args.append((conn, conn.get_servername()))
1577 context = Context(TLSv1_METHOD)
1578 context.set_tlsext_servername_callback(servername)
1579
1580 # Necessary to actually accept the connection
1581 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001582 context.use_certificate(
1583 load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001584
1585 # Do a little connection to trigger the logic
1586 server = Connection(context, None)
1587 server.set_accept_state()
1588
1589 client = Connection(Context(TLSv1_METHOD), None)
1590 client.set_connect_state()
Alex Gaynore7f51982016-09-11 11:48:14 -04001591 client.set_tlsext_host_name(b"foo1.example.com")
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001592
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001593 interact_in_memory(server, client)
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001594
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001595 assert args == [(server, b"foo1.example.com")]
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001596
1597
Alex Chan9e08b3e2016-11-10 12:18:54 +00001598class TestNextProtoNegotiation(object):
Cory Benfield84a121e2014-03-31 20:30:25 +01001599 """
1600 Test for Next Protocol Negotiation in PyOpenSSL.
1601 """
Alex Chan9e08b3e2016-11-10 12:18:54 +00001602 def test_npn_success(self):
1603 """
1604 Tests that clients and servers that agree on the negotiated next
1605 protocol can correct establish a connection, and that the agreed
1606 protocol is reported by the connections.
1607 """
1608 advertise_args = []
1609 select_args = []
1610
1611 def advertise(conn):
1612 advertise_args.append((conn,))
1613 return [b'http/1.1', b'spdy/2']
1614
1615 def select(conn, options):
1616 select_args.append((conn, options))
1617 return b'spdy/2'
1618
1619 server_context = Context(TLSv1_METHOD)
1620 server_context.set_npn_advertise_callback(advertise)
1621
1622 client_context = Context(TLSv1_METHOD)
1623 client_context.set_npn_select_callback(select)
1624
1625 # Necessary to actually accept the connection
1626 server_context.use_privatekey(
1627 load_privatekey(FILETYPE_PEM, server_key_pem))
1628 server_context.use_certificate(
1629 load_certificate(FILETYPE_PEM, server_cert_pem))
1630
1631 # Do a little connection to trigger the logic
1632 server = Connection(server_context, None)
1633 server.set_accept_state()
1634
1635 client = Connection(client_context, None)
1636 client.set_connect_state()
1637
1638 interact_in_memory(server, client)
1639
1640 assert advertise_args == [(server,)]
1641 assert select_args == [(client, [b'http/1.1', b'spdy/2'])]
1642
1643 assert server.get_next_proto_negotiated() == b'spdy/2'
1644 assert client.get_next_proto_negotiated() == b'spdy/2'
1645
1646 def test_npn_client_fail(self):
1647 """
1648 Tests that when clients and servers cannot agree on what protocol
1649 to use next that the TLS connection does not get established.
1650 """
1651 advertise_args = []
1652 select_args = []
1653
1654 def advertise(conn):
1655 advertise_args.append((conn,))
1656 return [b'http/1.1', b'spdy/2']
1657
1658 def select(conn, options):
1659 select_args.append((conn, options))
1660 return b''
1661
1662 server_context = Context(TLSv1_METHOD)
1663 server_context.set_npn_advertise_callback(advertise)
1664
1665 client_context = Context(TLSv1_METHOD)
1666 client_context.set_npn_select_callback(select)
1667
1668 # Necessary to actually accept the connection
1669 server_context.use_privatekey(
1670 load_privatekey(FILETYPE_PEM, server_key_pem))
1671 server_context.use_certificate(
1672 load_certificate(FILETYPE_PEM, server_cert_pem))
1673
1674 # Do a little connection to trigger the logic
1675 server = Connection(server_context, None)
1676 server.set_accept_state()
1677
1678 client = Connection(client_context, None)
1679 client.set_connect_state()
1680
1681 # If the client doesn't return anything, the connection will fail.
1682 with pytest.raises(Error):
1683 interact_in_memory(server, client)
1684
1685 assert advertise_args == [(server,)]
1686 assert select_args == [(client, [b'http/1.1', b'spdy/2'])]
1687
1688 def test_npn_select_error(self):
1689 """
1690 Test that we can handle exceptions in the select callback. If
1691 select fails it should be fatal to the connection.
1692 """
1693 advertise_args = []
1694
1695 def advertise(conn):
1696 advertise_args.append((conn,))
1697 return [b'http/1.1', b'spdy/2']
1698
1699 def select(conn, options):
1700 raise TypeError
1701
1702 server_context = Context(TLSv1_METHOD)
1703 server_context.set_npn_advertise_callback(advertise)
1704
1705 client_context = Context(TLSv1_METHOD)
1706 client_context.set_npn_select_callback(select)
1707
1708 # Necessary to actually accept the connection
1709 server_context.use_privatekey(
1710 load_privatekey(FILETYPE_PEM, server_key_pem))
1711 server_context.use_certificate(
1712 load_certificate(FILETYPE_PEM, server_cert_pem))
1713
1714 # Do a little connection to trigger the logic
1715 server = Connection(server_context, None)
1716 server.set_accept_state()
1717
1718 client = Connection(client_context, None)
1719 client.set_connect_state()
1720
1721 # If the callback throws an exception it should be raised here.
1722 with pytest.raises(TypeError):
1723 interact_in_memory(server, client)
1724 assert advertise_args == [(server,), ]
1725
1726 def test_npn_advertise_error(self):
1727 """
1728 Test that we can handle exceptions in the advertise callback. If
1729 advertise fails no NPN is advertised to the client.
1730 """
1731 select_args = []
1732
1733 def advertise(conn):
1734 raise TypeError
1735
1736 def select(conn, options): # pragma: nocover
Cory Benfieldba1820d2015-04-13 17:39:12 -04001737 """
Alex Chan9e08b3e2016-11-10 12:18:54 +00001738 Assert later that no args are actually appended.
Cory Benfieldba1820d2015-04-13 17:39:12 -04001739 """
Alex Chan9e08b3e2016-11-10 12:18:54 +00001740 select_args.append((conn, options))
1741 return b''
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001742
Alex Chan9e08b3e2016-11-10 12:18:54 +00001743 server_context = Context(TLSv1_METHOD)
1744 server_context.set_npn_advertise_callback(advertise)
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001745
Alex Chan9e08b3e2016-11-10 12:18:54 +00001746 client_context = Context(TLSv1_METHOD)
1747 client_context.set_npn_select_callback(select)
Cory Benfield84a121e2014-03-31 20:30:25 +01001748
Alex Chan9e08b3e2016-11-10 12:18:54 +00001749 # Necessary to actually accept the connection
1750 server_context.use_privatekey(
1751 load_privatekey(FILETYPE_PEM, server_key_pem))
1752 server_context.use_certificate(
1753 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield84a121e2014-03-31 20:30:25 +01001754
Alex Chan9e08b3e2016-11-10 12:18:54 +00001755 # Do a little connection to trigger the logic
1756 server = Connection(server_context, None)
1757 server.set_accept_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001758
Alex Chan9e08b3e2016-11-10 12:18:54 +00001759 client = Connection(client_context, None)
1760 client.set_connect_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001761
Alex Chan9e08b3e2016-11-10 12:18:54 +00001762 # If the client doesn't return anything, the connection will fail.
1763 with pytest.raises(TypeError):
1764 interact_in_memory(server, client)
1765 assert select_args == []
Cory Benfield0ea76e72015-03-22 09:05:28 +00001766
1767
Alex Chanec1e32d2016-11-10 14:11:45 +00001768class TestApplicationLayerProtoNegotiation(object):
Cory Benfield12eae892014-06-07 15:42:56 +01001769 """
1770 Tests for ALPN in PyOpenSSL.
1771 """
Cory Benfielde46fa842015-04-13 16:50:49 -04001772 # Skip tests on versions that don't support ALPN.
1773 if _lib.Cryptography_HAS_ALPN:
Cory Benfield12eae892014-06-07 15:42:56 +01001774
Cory Benfielde46fa842015-04-13 16:50:49 -04001775 def test_alpn_success(self):
1776 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04001777 Clients and servers that agree on the negotiated ALPN protocol can
1778 correct establish a connection, and the agreed protocol is reported
1779 by the connections.
Cory Benfielde46fa842015-04-13 16:50:49 -04001780 """
1781 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001782
Cory Benfielde46fa842015-04-13 16:50:49 -04001783 def select(conn, options):
1784 select_args.append((conn, options))
1785 return b'spdy/2'
Cory Benfield12eae892014-06-07 15:42:56 +01001786
Cory Benfielde46fa842015-04-13 16:50:49 -04001787 client_context = Context(TLSv1_METHOD)
1788 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfield12eae892014-06-07 15:42:56 +01001789
Cory Benfielde46fa842015-04-13 16:50:49 -04001790 server_context = Context(TLSv1_METHOD)
1791 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01001792
Cory Benfielde46fa842015-04-13 16:50:49 -04001793 # Necessary to actually accept the connection
1794 server_context.use_privatekey(
1795 load_privatekey(FILETYPE_PEM, server_key_pem))
1796 server_context.use_certificate(
1797 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield12eae892014-06-07 15:42:56 +01001798
Cory Benfielde46fa842015-04-13 16:50:49 -04001799 # Do a little connection to trigger the logic
1800 server = Connection(server_context, None)
1801 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001802
Cory Benfielde46fa842015-04-13 16:50:49 -04001803 client = Connection(client_context, None)
1804 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001805
Alex Chanec1e32d2016-11-10 14:11:45 +00001806 interact_in_memory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001807
Alex Chanec1e32d2016-11-10 14:11:45 +00001808 assert select_args == [(server, [b'http/1.1', b'spdy/2'])]
Cory Benfielde46fa842015-04-13 16:50:49 -04001809
Alex Chanec1e32d2016-11-10 14:11:45 +00001810 assert server.get_alpn_proto_negotiated() == b'spdy/2'
1811 assert client.get_alpn_proto_negotiated() == b'spdy/2'
Cory Benfield12eae892014-06-07 15:42:56 +01001812
Cory Benfielde46fa842015-04-13 16:50:49 -04001813 def test_alpn_set_on_connection(self):
1814 """
1815 The same as test_alpn_success, but setting the ALPN protocols on
1816 the connection rather than the context.
1817 """
1818 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001819
Cory Benfielde46fa842015-04-13 16:50:49 -04001820 def select(conn, options):
1821 select_args.append((conn, options))
1822 return b'spdy/2'
Cory Benfield12eae892014-06-07 15:42:56 +01001823
Cory Benfielde46fa842015-04-13 16:50:49 -04001824 # Setup the client context but don't set any ALPN protocols.
1825 client_context = Context(TLSv1_METHOD)
Cory Benfield12eae892014-06-07 15:42:56 +01001826
Cory Benfielde46fa842015-04-13 16:50:49 -04001827 server_context = Context(TLSv1_METHOD)
1828 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01001829
Cory Benfielde46fa842015-04-13 16:50:49 -04001830 # Necessary to actually accept the connection
1831 server_context.use_privatekey(
1832 load_privatekey(FILETYPE_PEM, server_key_pem))
1833 server_context.use_certificate(
1834 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield12eae892014-06-07 15:42:56 +01001835
Cory Benfielde46fa842015-04-13 16:50:49 -04001836 # Do a little connection to trigger the logic
1837 server = Connection(server_context, None)
1838 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001839
Cory Benfielde46fa842015-04-13 16:50:49 -04001840 # Set the ALPN protocols on the client connection.
1841 client = Connection(client_context, None)
1842 client.set_alpn_protos([b'http/1.1', b'spdy/2'])
1843 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001844
Alex Chanec1e32d2016-11-10 14:11:45 +00001845 interact_in_memory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001846
Alex Chanec1e32d2016-11-10 14:11:45 +00001847 assert select_args == [(server, [b'http/1.1', b'spdy/2'])]
Cory Benfield12eae892014-06-07 15:42:56 +01001848
Alex Chanec1e32d2016-11-10 14:11:45 +00001849 assert server.get_alpn_proto_negotiated() == b'spdy/2'
1850 assert client.get_alpn_proto_negotiated() == b'spdy/2'
Cory Benfield12eae892014-06-07 15:42:56 +01001851
Cory Benfielde46fa842015-04-13 16:50:49 -04001852 def test_alpn_server_fail(self):
1853 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04001854 When clients and servers cannot agree on what protocol to use next
1855 the TLS connection does not get established.
Cory Benfielde46fa842015-04-13 16:50:49 -04001856 """
1857 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001858
Cory Benfielde46fa842015-04-13 16:50:49 -04001859 def select(conn, options):
1860 select_args.append((conn, options))
1861 return b''
Cory Benfield12eae892014-06-07 15:42:56 +01001862
Cory Benfielde46fa842015-04-13 16:50:49 -04001863 client_context = Context(TLSv1_METHOD)
1864 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfield12eae892014-06-07 15:42:56 +01001865
Cory Benfielde46fa842015-04-13 16:50:49 -04001866 server_context = Context(TLSv1_METHOD)
1867 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01001868
Cory Benfielde46fa842015-04-13 16:50:49 -04001869 # Necessary to actually accept the connection
1870 server_context.use_privatekey(
1871 load_privatekey(FILETYPE_PEM, server_key_pem))
1872 server_context.use_certificate(
1873 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield12eae892014-06-07 15:42:56 +01001874
Cory Benfielde46fa842015-04-13 16:50:49 -04001875 # Do a little connection to trigger the logic
1876 server = Connection(server_context, None)
1877 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001878
Cory Benfielde46fa842015-04-13 16:50:49 -04001879 client = Connection(client_context, None)
1880 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001881
Cory Benfielde46fa842015-04-13 16:50:49 -04001882 # If the client doesn't return anything, the connection will fail.
Alex Chanec1e32d2016-11-10 14:11:45 +00001883 with pytest.raises(Error):
1884 interact_in_memory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001885
Alex Chanec1e32d2016-11-10 14:11:45 +00001886 assert select_args == [(server, [b'http/1.1', b'spdy/2'])]
Cory Benfield12eae892014-06-07 15:42:56 +01001887
Cory Benfielde46fa842015-04-13 16:50:49 -04001888 def test_alpn_no_server(self):
1889 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04001890 When clients and servers cannot agree on what protocol to use next
1891 because the server doesn't offer ALPN, no protocol is negotiated.
Cory Benfielde46fa842015-04-13 16:50:49 -04001892 """
1893 client_context = Context(TLSv1_METHOD)
1894 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfielde3d57152015-04-11 17:57:35 -04001895
Cory Benfielde46fa842015-04-13 16:50:49 -04001896 server_context = Context(TLSv1_METHOD)
Cory Benfielde3d57152015-04-11 17:57:35 -04001897
Cory Benfielde46fa842015-04-13 16:50:49 -04001898 # Necessary to actually accept the connection
1899 server_context.use_privatekey(
1900 load_privatekey(FILETYPE_PEM, server_key_pem))
1901 server_context.use_certificate(
1902 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfielde3d57152015-04-11 17:57:35 -04001903
Cory Benfielde46fa842015-04-13 16:50:49 -04001904 # Do a little connection to trigger the logic
1905 server = Connection(server_context, None)
1906 server.set_accept_state()
Cory Benfielde3d57152015-04-11 17:57:35 -04001907
Cory Benfielde46fa842015-04-13 16:50:49 -04001908 client = Connection(client_context, None)
1909 client.set_connect_state()
Cory Benfielde3d57152015-04-11 17:57:35 -04001910
Cory Benfielde46fa842015-04-13 16:50:49 -04001911 # Do the dance.
Alex Chanec1e32d2016-11-10 14:11:45 +00001912 interact_in_memory(server, client)
Cory Benfielde3d57152015-04-11 17:57:35 -04001913
Alex Chanec1e32d2016-11-10 14:11:45 +00001914 assert client.get_alpn_proto_negotiated() == b''
Cory Benfielde3d57152015-04-11 17:57:35 -04001915
Cory Benfielde46fa842015-04-13 16:50:49 -04001916 def test_alpn_callback_exception(self):
1917 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04001918 We can handle exceptions in the ALPN select callback.
Cory Benfielde46fa842015-04-13 16:50:49 -04001919 """
1920 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001921
Cory Benfielde46fa842015-04-13 16:50:49 -04001922 def select(conn, options):
1923 select_args.append((conn, options))
Cory Benfieldef401452015-04-13 18:17:36 -04001924 raise TypeError()
Cory Benfieldf1177e72015-04-12 09:11:49 -04001925
Cory Benfielde46fa842015-04-13 16:50:49 -04001926 client_context = Context(TLSv1_METHOD)
1927 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfieldf1177e72015-04-12 09:11:49 -04001928
Cory Benfielde46fa842015-04-13 16:50:49 -04001929 server_context = Context(TLSv1_METHOD)
1930 server_context.set_alpn_select_callback(select)
Cory Benfieldf1177e72015-04-12 09:11:49 -04001931
Cory Benfielde46fa842015-04-13 16:50:49 -04001932 # Necessary to actually accept the connection
1933 server_context.use_privatekey(
1934 load_privatekey(FILETYPE_PEM, server_key_pem))
1935 server_context.use_certificate(
1936 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfieldf1177e72015-04-12 09:11:49 -04001937
Cory Benfielde46fa842015-04-13 16:50:49 -04001938 # Do a little connection to trigger the logic
1939 server = Connection(server_context, None)
1940 server.set_accept_state()
Cory Benfieldf1177e72015-04-12 09:11:49 -04001941
Cory Benfielde46fa842015-04-13 16:50:49 -04001942 client = Connection(client_context, None)
1943 client.set_connect_state()
Cory Benfieldf1177e72015-04-12 09:11:49 -04001944
Alex Chanec1e32d2016-11-10 14:11:45 +00001945 with pytest.raises(TypeError):
1946 interact_in_memory(server, client)
1947 assert select_args == [(server, [b'http/1.1', b'spdy/2'])]
Cory Benfieldf1177e72015-04-12 09:11:49 -04001948
Cory Benfield0f7b04c2015-04-13 17:51:12 -04001949 else:
1950 # No ALPN.
1951 def test_alpn_not_implemented(self):
Cory Benfieldef401452015-04-13 18:17:36 -04001952 """
1953 If ALPN is not in OpenSSL, we should raise NotImplementedError.
1954 """
Cory Benfield0f7b04c2015-04-13 17:51:12 -04001955 # Test the context methods first.
1956 context = Context(TLSv1_METHOD)
Alex Chanec1e32d2016-11-10 14:11:45 +00001957 with pytest.raises(NotImplementedError):
1958 context.set_alpn_protos(None)
1959 with pytest.raises(NotImplementedError):
1960 context.set_alpn_select_callback(None)
Cory Benfield0f7b04c2015-04-13 17:51:12 -04001961
1962 # Now test a connection.
1963 conn = Connection(context)
Alex Chanec1e32d2016-11-10 14:11:45 +00001964 with pytest.raises(NotImplementedError):
1965 conn.set_alpn_protos(None)
Cory Benfield0f7b04c2015-04-13 17:51:12 -04001966
Cory Benfieldf1177e72015-04-12 09:11:49 -04001967
Alex Chanec1e32d2016-11-10 14:11:45 +00001968class TestSession(object):
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05001969 """
1970 Unit tests for :py:obj:`OpenSSL.SSL.Session`.
1971 """
1972 def test_construction(self):
1973 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001974 :py:class:`Session` can be constructed with no arguments, creating
1975 a new instance of that type.
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05001976 """
1977 new_session = Session()
Alex Chanec1e32d2016-11-10 14:11:45 +00001978 assert isinstance(new_session, Session)
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05001979
1980
Alex Chan1c0cb662017-01-30 07:13:30 +00001981class TestConnection(object):
Rick Deane15b1472009-07-09 15:53:42 -05001982 """
Alex Chan1c0cb662017-01-30 07:13:30 +00001983 Unit tests for `OpenSSL.SSL.Connection`.
Rick Deane15b1472009-07-09 15:53:42 -05001984 """
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04001985 # XXX get_peer_certificate -> None
1986 # XXX sock_shutdown
1987 # XXX master_key -> TypeError
1988 # XXX server_random -> TypeError
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04001989 # XXX connect -> TypeError
1990 # XXX connect_ex -> TypeError
1991 # XXX set_connect_state -> TypeError
1992 # XXX set_accept_state -> TypeError
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04001993 # XXX do_handshake -> TypeError
1994 # XXX bio_read -> TypeError
1995 # XXX recv -> TypeError
1996 # XXX send -> TypeError
1997 # XXX bio_write -> TypeError
1998
Rick Deane15b1472009-07-09 15:53:42 -05001999 def test_type(self):
2000 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002001 `Connection` and `ConnectionType` refer to the same type object and
2002 can be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -05002003 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002004 assert Connection is ConnectionType
Rick Deane15b1472009-07-09 15:53:42 -05002005 ctx = Context(TLSv1_METHOD)
Alex Chan1c0cb662017-01-30 07:13:30 +00002006 assert is_consistent_type(Connection, 'Connection', ctx, None)
Rick Deane15b1472009-07-09 15:53:42 -05002007
Alex Chanfb078d82017-04-20 11:16:15 +01002008 @pytest.mark.parametrize('bad_context', [object(), 'context', None, 1])
2009 def test_wrong_args(self, bad_context):
2010 """
2011 `Connection.__init__` raises `TypeError` if called with a non-`Context`
2012 instance argument.
2013 """
2014 with pytest.raises(TypeError):
2015 Connection(bad_context)
2016
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002017 def test_get_context(self):
2018 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002019 `Connection.get_context` returns the `Context` instance used to
2020 construct the `Connection` instance.
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002021 """
2022 context = Context(TLSv1_METHOD)
2023 connection = Connection(context, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002024 assert connection.get_context() is context
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002025
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002026 def test_set_context_wrong_args(self):
2027 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002028 `Connection.set_context` raises `TypeError` if called with a
Alex Chanfb078d82017-04-20 11:16:15 +01002029 non-`Context` instance argument.
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002030 """
2031 ctx = Context(TLSv1_METHOD)
2032 connection = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002033 with pytest.raises(TypeError):
2034 connection.set_context(object())
2035 with pytest.raises(TypeError):
2036 connection.set_context("hello")
2037 with pytest.raises(TypeError):
2038 connection.set_context(1)
2039 assert ctx is connection.get_context()
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002040
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002041 def test_set_context(self):
2042 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002043 `Connection.set_context` specifies a new `Context` instance to be
2044 used for the connection.
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002045 """
2046 original = Context(SSLv23_METHOD)
2047 replacement = Context(TLSv1_METHOD)
2048 connection = Connection(original, None)
2049 connection.set_context(replacement)
Alex Chan1c0cb662017-01-30 07:13:30 +00002050 assert replacement is connection.get_context()
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002051 # Lose our references to the contexts, just in case the Connection
2052 # isn't properly managing its own contributions to their reference
2053 # counts.
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002054 del original, replacement
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002055 collect()
2056
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002057 def test_set_tlsext_host_name_wrong_args(self):
2058 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002059 If `Connection.set_tlsext_host_name` is called with a non-byte string
2060 argument or a byte string with an embedded NUL, `TypeError` is raised.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002061 """
2062 conn = Connection(Context(TLSv1_METHOD), None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002063 with pytest.raises(TypeError):
2064 conn.set_tlsext_host_name(object())
2065 with pytest.raises(TypeError):
2066 conn.set_tlsext_host_name(b"with\0null")
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002067
Abraham Martinc5484ba2015-03-25 15:33:05 +00002068 if PY3:
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002069 # On Python 3.x, don't accidentally implicitly convert from text.
Alex Chan1c0cb662017-01-30 07:13:30 +00002070 with pytest.raises(TypeError):
2071 conn.set_tlsext_host_name(b"example.com".decode("ascii"))
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04002072
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002073 def test_pending(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002074 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002075 `Connection.pending` returns the number of bytes available for
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002076 immediate read.
2077 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002078 connection = Connection(Context(TLSv1_METHOD), None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002079 assert connection.pending() == 0
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002080
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002081 def test_peek(self):
2082 """
Hynek Schlawack3bcf3152017-02-18 08:25:34 +01002083 `Connection.recv` peeks into the connection if `socket.MSG_PEEK` is
2084 passed.
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002085 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002086 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002087 server.send(b'xy')
Alex Chan1c0cb662017-01-30 07:13:30 +00002088 assert client.recv(2, MSG_PEEK) == b'xy'
2089 assert client.recv(2, MSG_PEEK) == b'xy'
2090 assert client.recv(2) == b'xy'
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002091
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002092 def test_connect_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002093 """
Hynek Schlawack3bcf3152017-02-18 08:25:34 +01002094 `Connection.connect` raises `TypeError` if called with a non-address
2095 argument.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002096 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002097 connection = Connection(Context(TLSv1_METHOD), socket())
Alex Chan1c0cb662017-01-30 07:13:30 +00002098 with pytest.raises(TypeError):
2099 connection.connect(None)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002100
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002101 def test_connect_refused(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002102 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002103 `Connection.connect` raises `socket.error` if the underlying socket
2104 connect method raises it.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002105 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002106 client = socket()
2107 context = Context(TLSv1_METHOD)
2108 clientSSL = Connection(context, client)
Alex Gaynor122717b2015-09-05 14:14:18 -04002109 # pytest.raises here doesn't work because of a bug in py.test on Python
2110 # 2.6: https://github.com/pytest-dev/pytest/issues/988
Alex Gaynore69c2782015-09-05 14:07:48 -04002111 try:
Alex Gaynor1aabb2e2015-09-05 13:35:18 -04002112 clientSSL.connect(("127.0.0.1", 1))
Alex Gaynore69c2782015-09-05 14:07:48 -04002113 except error as e:
Alex Gaynor20a4c082015-09-05 14:24:15 -04002114 exc = e
2115 assert exc.args[0] == ECONNREFUSED
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002116
2117 def test_connect(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002118 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002119 `Connection.connect` establishes a connection to the specified address.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002120 """
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002121 port = socket()
2122 port.bind(('', 0))
2123 port.listen(3)
2124
2125 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002126 clientSSL.connect(('127.0.0.1', port.getsockname()[1]))
2127 # XXX An assertion? Or something?
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002128
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002129 @pytest.mark.skipif(
2130 platform == "darwin",
2131 reason="connect_ex sometimes causes a kernel panic on OS X 10.6.4"
2132 )
2133 def test_connect_ex(self):
2134 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002135 If there is a connection error, `Connection.connect_ex` returns the
2136 errno instead of raising an exception.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002137 """
2138 port = socket()
2139 port.bind(('', 0))
2140 port.listen(3)
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002141
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002142 clientSSL = Connection(Context(TLSv1_METHOD), socket())
2143 clientSSL.setblocking(False)
2144 result = clientSSL.connect_ex(port.getsockname())
2145 expected = (EINPROGRESS, EWOULDBLOCK)
Alex Chan1c0cb662017-01-30 07:13:30 +00002146 assert result in expected
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002147
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002148 def test_accept(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002149 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002150 `Connection.accept` accepts a pending connection attempt and returns a
2151 tuple of a new `Connection` (the accepted client) and the address the
2152 connection originated from.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002153 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002154 ctx = Context(TLSv1_METHOD)
2155 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2156 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002157 port = socket()
2158 portSSL = Connection(ctx, port)
2159 portSSL.bind(('', 0))
2160 portSSL.listen(3)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002161
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002162 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002163
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002164 # Calling portSSL.getsockname() here to get the server IP address
2165 # sounds great, but frequently fails on Windows.
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002166 clientSSL.connect(('127.0.0.1', portSSL.getsockname()[1]))
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002167
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002168 serverSSL, address = portSSL.accept()
2169
Alex Chan1c0cb662017-01-30 07:13:30 +00002170 assert isinstance(serverSSL, Connection)
2171 assert serverSSL.get_context() is ctx
2172 assert address == clientSSL.getsockname()
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002173
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002174 def test_shutdown_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002175 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002176 `Connection.set_shutdown` raises `TypeError` if called with arguments
2177 other than integers.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002178 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002179 connection = Connection(Context(TLSv1_METHOD), None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002180 with pytest.raises(TypeError):
2181 connection.set_shutdown(None)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002182
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002183 def test_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002184 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002185 `Connection.shutdown` performs an SSL-level connection shutdown.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002186 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002187 server, client = loopback()
2188 assert not server.shutdown()
2189 assert server.get_shutdown() == SENT_SHUTDOWN
2190 with pytest.raises(ZeroReturnError):
2191 client.recv(1024)
2192 assert client.get_shutdown() == RECEIVED_SHUTDOWN
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04002193 client.shutdown()
Alex Chan1c0cb662017-01-30 07:13:30 +00002194 assert client.get_shutdown() == (SENT_SHUTDOWN | RECEIVED_SHUTDOWN)
2195 with pytest.raises(ZeroReturnError):
2196 server.recv(1024)
2197 assert server.get_shutdown() == (SENT_SHUTDOWN | RECEIVED_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002198
Paul Aurichc85e0862015-01-08 08:34:33 -08002199 def test_shutdown_closed(self):
2200 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002201 If the underlying socket is closed, `Connection.shutdown` propagates
2202 the write error from the low level write call.
Paul Aurichc85e0862015-01-08 08:34:33 -08002203 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002204 server, client = loopback()
Paul Aurichc85e0862015-01-08 08:34:33 -08002205 server.sock_shutdown(2)
Alex Chan1c0cb662017-01-30 07:13:30 +00002206 with pytest.raises(SysCallError) as exc:
2207 server.shutdown()
Alex Chanfb078d82017-04-20 11:16:15 +01002208 if platform == "win32":
2209 assert exc.value.args[0] == ESHUTDOWN
2210 else:
2211 assert exc.value.args[0] == EPIPE
Paul Aurichc85e0862015-01-08 08:34:33 -08002212
Glyph89389472015-04-14 17:29:26 -04002213 def test_shutdown_truncated(self):
Glyph6064ec32015-04-14 16:38:22 -04002214 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002215 If the underlying connection is truncated, `Connection.shutdown`
2216 raises an `Error`.
Glyph6064ec32015-04-14 16:38:22 -04002217 """
Glyph89389472015-04-14 17:29:26 -04002218 server_ctx = Context(TLSv1_METHOD)
2219 client_ctx = Context(TLSv1_METHOD)
2220 server_ctx.use_privatekey(
2221 load_privatekey(FILETYPE_PEM, server_key_pem))
2222 server_ctx.use_certificate(
2223 load_certificate(FILETYPE_PEM, server_cert_pem))
2224 server = Connection(server_ctx, None)
2225 client = Connection(client_ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002226 handshake_in_memory(client, server)
2227 assert not server.shutdown()
2228 with pytest.raises(WantReadError):
2229 server.shutdown()
Glyph89389472015-04-14 17:29:26 -04002230 server.bio_shutdown()
Alex Chan1c0cb662017-01-30 07:13:30 +00002231 with pytest.raises(Error):
2232 server.shutdown()
Glyph6064ec32015-04-14 16:38:22 -04002233
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002234 def test_set_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002235 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002236 `Connection.set_shutdown` sets the state of the SSL connection
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002237 shutdown process.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002238 """
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002239 connection = Connection(Context(TLSv1_METHOD), socket())
2240 connection.set_shutdown(RECEIVED_SHUTDOWN)
Alex Chan1c0cb662017-01-30 07:13:30 +00002241 assert connection.get_shutdown() == RECEIVED_SHUTDOWN
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002242
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002243 @skip_if_py3
2244 def test_set_shutdown_long(self):
2245 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002246 On Python 2 `Connection.set_shutdown` accepts an argument
2247 of type `long` as well as `int`.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002248 """
2249 connection = Connection(Context(TLSv1_METHOD), socket())
2250 connection.set_shutdown(long(RECEIVED_SHUTDOWN))
Alex Chan1c0cb662017-01-30 07:13:30 +00002251 assert connection.get_shutdown() == RECEIVED_SHUTDOWN
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -05002252
kjavaf248592015-09-07 12:14:01 +01002253 def test_state_string(self):
2254 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002255 `Connection.state_string` verbosely describes the current state of
2256 the `Connection`.
kjavaf248592015-09-07 12:14:01 +01002257 """
Hynek Schlawackb0274ce2015-10-16 19:56:26 +02002258 server, client = socket_pair()
Alex Chan1c0cb662017-01-30 07:13:30 +00002259 server = loopback_server_factory(server)
2260 client = loopback_client_factory(client)
kjavaf248592015-09-07 12:14:01 +01002261
Alex Gaynor5af32d02016-09-24 01:52:21 -04002262 assert server.get_state_string() in [
2263 b"before/accept initialization", b"before SSL initialization"
2264 ]
2265 assert client.get_state_string() in [
2266 b"before/connect initialization", b"before SSL initialization"
2267 ]
kjavaf248592015-09-07 12:14:01 +01002268
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002269 def test_app_data(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002270 """
2271 Any object can be set as app data by passing it to
Alex Chan1c0cb662017-01-30 07:13:30 +00002272 `Connection.set_app_data` and later retrieved with
2273 `Connection.get_app_data`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002274 """
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002275 conn = Connection(Context(TLSv1_METHOD), None)
Todd Chapman4f73e4f2015-08-27 11:26:43 -04002276 assert None is conn.get_app_data()
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002277 app_data = object()
2278 conn.set_app_data(app_data)
Todd Chapman4f73e4f2015-08-27 11:26:43 -04002279 assert conn.get_app_data() is app_data
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002280
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002281 def test_makefile(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002282 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002283 `Connection.makefile` is not implemented and calling that
2284 method raises `NotImplementedError`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002285 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002286 conn = Connection(Context(TLSv1_METHOD), None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002287 with pytest.raises(NotImplementedError):
2288 conn.makefile()
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002289
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002290 def test_get_peer_cert_chain(self):
2291 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002292 `Connection.get_peer_cert_chain` returns a list of certificates
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002293 which the connected server returned for the certification verification.
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002294 """
2295 chain = _create_certificate_chain()
2296 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
2297
2298 serverContext = Context(TLSv1_METHOD)
2299 serverContext.use_privatekey(skey)
2300 serverContext.use_certificate(scert)
2301 serverContext.add_extra_chain_cert(icert)
2302 serverContext.add_extra_chain_cert(cacert)
2303 server = Connection(serverContext, None)
2304 server.set_accept_state()
2305
2306 # Create the client
2307 clientContext = Context(TLSv1_METHOD)
2308 clientContext.set_verify(VERIFY_NONE, verify_cb)
2309 client = Connection(clientContext, None)
2310 client.set_connect_state()
2311
Alex Chan1c0cb662017-01-30 07:13:30 +00002312 interact_in_memory(client, server)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002313
2314 chain = client.get_peer_cert_chain()
Alex Chan1c0cb662017-01-30 07:13:30 +00002315 assert len(chain) == 3
2316 assert "Server Certificate" == chain[0].get_subject().CN
2317 assert "Intermediate Certificate" == chain[1].get_subject().CN
2318 assert "Authority Certificate" == chain[2].get_subject().CN
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002319
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002320 def test_get_peer_cert_chain_none(self):
2321 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002322 `Connection.get_peer_cert_chain` returns `None` if the peer sends
2323 no certificate chain.
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002324 """
2325 ctx = Context(TLSv1_METHOD)
2326 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2327 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
2328 server = Connection(ctx, None)
2329 server.set_accept_state()
2330 client = Connection(Context(TLSv1_METHOD), None)
2331 client.set_connect_state()
Alex Chan1c0cb662017-01-30 07:13:30 +00002332 interact_in_memory(client, server)
2333 assert None is server.get_peer_cert_chain()
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002334
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002335 def test_get_session_unconnected(self):
2336 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002337 `Connection.get_session` returns `None` when used with an object
2338 which has not been connected.
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002339 """
2340 ctx = Context(TLSv1_METHOD)
2341 server = Connection(ctx, None)
2342 session = server.get_session()
Alex Chan1c0cb662017-01-30 07:13:30 +00002343 assert None is session
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002344
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002345 def test_server_get_session(self):
2346 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002347 On the server side of a connection, `Connection.get_session` returns a
2348 `Session` instance representing the SSL session for that connection.
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002349 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002350 server, client = loopback()
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002351 session = server.get_session()
Alex Chan1c0cb662017-01-30 07:13:30 +00002352 assert isinstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002353
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002354 def test_client_get_session(self):
2355 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002356 On the client side of a connection, `Connection.get_session`
2357 returns a `Session` instance representing the SSL session for
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002358 that connection.
2359 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002360 server, client = loopback()
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002361 session = client.get_session()
Alex Chan1c0cb662017-01-30 07:13:30 +00002362 assert isinstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002363
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002364 def test_set_session_wrong_args(self):
2365 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002366 `Connection.set_session` raises `TypeError` if called with an object
2367 that is not an instance of `Session`.
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002368 """
2369 ctx = Context(TLSv1_METHOD)
2370 connection = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002371 with pytest.raises(TypeError):
2372 connection.set_session(123)
2373 with pytest.raises(TypeError):
2374 connection.set_session("hello")
2375 with pytest.raises(TypeError):
2376 connection.set_session(object())
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002377
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002378 def test_client_set_session(self):
2379 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002380 `Connection.set_session`, when used prior to a connection being
2381 established, accepts a `Session` instance and causes an attempt to
2382 re-use the session it represents when the SSL handshake is performed.
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002383 """
2384 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2385 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
2386 ctx = Context(TLSv1_METHOD)
2387 ctx.use_privatekey(key)
2388 ctx.use_certificate(cert)
2389 ctx.set_session_id("unity-test")
2390
2391 def makeServer(socket):
2392 server = Connection(ctx, socket)
2393 server.set_accept_state()
2394 return server
2395
Alex Chan1c0cb662017-01-30 07:13:30 +00002396 originalServer, originalClient = loopback(
2397 server_factory=makeServer)
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002398 originalSession = originalClient.get_session()
2399
2400 def makeClient(socket):
Alex Chan1c0cb662017-01-30 07:13:30 +00002401 client = loopback_client_factory(socket)
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002402 client.set_session(originalSession)
2403 return client
Alex Chan1c0cb662017-01-30 07:13:30 +00002404 resumedServer, resumedClient = loopback(
2405 server_factory=makeServer,
2406 client_factory=makeClient)
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002407
2408 # This is a proxy: in general, we have no access to any unique
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002409 # identifier for the session (new enough versions of OpenSSL expose
2410 # a hash which could be usable, but "new enough" is very, very new).
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002411 # Instead, exploit the fact that the master key is re-used if the
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002412 # session is re-used. As long as the master key for the two
2413 # connections is the same, the session was re-used!
Alex Chan1c0cb662017-01-30 07:13:30 +00002414 assert originalServer.master_key() == resumedServer.master_key()
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002415
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002416 def test_set_session_wrong_method(self):
2417 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002418 If `Connection.set_session` is passed a `Session` instance associated
2419 with a context using a different SSL method than the `Connection`
2420 is using, a `OpenSSL.SSL.Error` is raised.
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002421 """
Alex Gaynor5af32d02016-09-24 01:52:21 -04002422 # Make this work on both OpenSSL 1.0.0, which doesn't support TLSv1.2
2423 # and also on OpenSSL 1.1.0 which doesn't support SSLv3. (SSL_ST_INIT
2424 # is a way to check for 1.1.0)
2425 if SSL_ST_INIT is not None:
2426 v1 = TLSv1_METHOD
2427 v2 = SSLv3_METHOD
2428 else:
2429 v1 = TLSv1_2_METHOD
2430 v2 = TLSv1_METHOD
2431
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002432 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2433 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
Alex Gaynor5af32d02016-09-24 01:52:21 -04002434 ctx = Context(v1)
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002435 ctx.use_privatekey(key)
2436 ctx.use_certificate(cert)
2437 ctx.set_session_id("unity-test")
2438
2439 def makeServer(socket):
2440 server = Connection(ctx, socket)
2441 server.set_accept_state()
2442 return server
2443
Alex Gaynor5af32d02016-09-24 01:52:21 -04002444 def makeOriginalClient(socket):
2445 client = Connection(Context(v1), socket)
2446 client.set_connect_state()
2447 return client
2448
Alex Chan1c0cb662017-01-30 07:13:30 +00002449 originalServer, originalClient = loopback(
2450 server_factory=makeServer, client_factory=makeOriginalClient)
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002451 originalSession = originalClient.get_session()
2452
2453 def makeClient(socket):
2454 # Intentionally use a different, incompatible method here.
Alex Gaynor5af32d02016-09-24 01:52:21 -04002455 client = Connection(Context(v2), socket)
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002456 client.set_connect_state()
2457 client.set_session(originalSession)
2458 return client
2459
Alex Chan1c0cb662017-01-30 07:13:30 +00002460 with pytest.raises(Error):
2461 loopback(client_factory=makeClient, server_factory=makeServer)
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002462
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002463 def test_wantWriteError(self):
2464 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002465 `Connection` methods which generate output raise
2466 `OpenSSL.SSL.WantWriteError` if writing to the connection's BIO
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002467 fail indicating a should-write state.
2468 """
2469 client_socket, server_socket = socket_pair()
2470 # Fill up the client's send buffer so Connection won't be able to write
Jean-Paul Calderonebbff8b92014-03-22 14:20:30 -04002471 # anything. Only write a single byte at a time so we can be sure we
2472 # completely fill the buffer. Even though the socket API is allowed to
2473 # signal a short write via its return value it seems this doesn't
2474 # always happen on all platforms (FreeBSD and OS X particular) for the
2475 # very last bit of available buffer space.
2476 msg = b"x"
2477 for i in range(1024 * 1024 * 4):
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002478 try:
2479 client_socket.send(msg)
2480 except error as e:
2481 if e.errno == EWOULDBLOCK:
2482 break
2483 raise
2484 else:
Alex Chan1c0cb662017-01-30 07:13:30 +00002485 pytest.fail(
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002486 "Failed to fill socket buffer, cannot test BIO want write")
2487
2488 ctx = Context(TLSv1_METHOD)
2489 conn = Connection(ctx, client_socket)
2490 # Client's speak first, so make it an SSL client
2491 conn.set_connect_state()
Alex Chan1c0cb662017-01-30 07:13:30 +00002492 with pytest.raises(WantWriteError):
2493 conn.do_handshake()
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002494
2495 # XXX want_read
2496
Fedor Brunner416f4a12014-03-28 13:18:38 +01002497 def test_get_finished_before_connect(self):
Fedor Brunner5747b932014-03-05 14:22:34 +01002498 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002499 `Connection.get_finished` returns `None` before TLS handshake
2500 is completed.
Fedor Brunner5747b932014-03-05 14:22:34 +01002501 """
Fedor Brunner5747b932014-03-05 14:22:34 +01002502 ctx = Context(TLSv1_METHOD)
2503 connection = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002504 assert connection.get_finished() is None
Fedor Brunner416f4a12014-03-28 13:18:38 +01002505
2506 def test_get_peer_finished_before_connect(self):
2507 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002508 `Connection.get_peer_finished` returns `None` before TLS handshake
2509 is completed.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002510 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002511 ctx = Context(TLSv1_METHOD)
2512 connection = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002513 assert connection.get_peer_finished() is None
Fedor Brunner5747b932014-03-05 14:22:34 +01002514
Fedor Brunner416f4a12014-03-28 13:18:38 +01002515 def test_get_finished(self):
2516 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002517 `Connection.get_finished` method returns the TLS Finished message send
2518 from client, or server. Finished messages are send during
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002519 TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002520 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002521 server, client = loopback()
Fedor Brunner416f4a12014-03-28 13:18:38 +01002522
Alex Chan1c0cb662017-01-30 07:13:30 +00002523 assert server.get_finished() is not None
2524 assert len(server.get_finished()) > 0
Fedor Brunner416f4a12014-03-28 13:18:38 +01002525
2526 def test_get_peer_finished(self):
2527 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002528 `Connection.get_peer_finished` method returns the TLS Finished
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002529 message received from client, or server. Finished messages are send
2530 during TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002531 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002532 server, client = loopback()
Fedor Brunner416f4a12014-03-28 13:18:38 +01002533
Alex Chan1c0cb662017-01-30 07:13:30 +00002534 assert server.get_peer_finished() is not None
2535 assert len(server.get_peer_finished()) > 0
Fedor Brunner5747b932014-03-05 14:22:34 +01002536
Fedor Brunner416f4a12014-03-28 13:18:38 +01002537 def test_tls_finished_message_symmetry(self):
2538 """
Hynek Schlawackdddd1112015-09-05 21:12:30 +02002539 The TLS Finished message send by server must be the TLS Finished
2540 message received by client.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002541
Hynek Schlawackdddd1112015-09-05 21:12:30 +02002542 The TLS Finished message send by client must be the TLS Finished
2543 message received by server.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002544 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002545 server, client = loopback()
Fedor Brunner416f4a12014-03-28 13:18:38 +01002546
Alex Chan1c0cb662017-01-30 07:13:30 +00002547 assert server.get_finished() == client.get_peer_finished()
2548 assert client.get_finished() == server.get_peer_finished()
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002549
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002550 def test_get_cipher_name_before_connect(self):
2551 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002552 `Connection.get_cipher_name` returns `None` if no connection
2553 has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002554 """
2555 ctx = Context(TLSv1_METHOD)
2556 conn = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002557 assert conn.get_cipher_name() is None
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002558
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002559 def test_get_cipher_name(self):
2560 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002561 `Connection.get_cipher_name` returns a `unicode` string giving the
2562 name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002563 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002564 server, client = loopback()
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002565 server_cipher_name, client_cipher_name = \
2566 server.get_cipher_name(), client.get_cipher_name()
2567
Alex Chan1c0cb662017-01-30 07:13:30 +00002568 assert isinstance(server_cipher_name, text_type)
2569 assert isinstance(client_cipher_name, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002570
Alex Chan1c0cb662017-01-30 07:13:30 +00002571 assert server_cipher_name == client_cipher_name
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002572
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002573 def test_get_cipher_version_before_connect(self):
2574 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002575 `Connection.get_cipher_version` returns `None` if no connection
2576 has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002577 """
2578 ctx = Context(TLSv1_METHOD)
2579 conn = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002580 assert conn.get_cipher_version() is None
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002581
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002582 def test_get_cipher_version(self):
2583 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002584 `Connection.get_cipher_version` returns a `unicode` string giving
2585 the protocol name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002586 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002587 server, client = loopback()
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002588 server_cipher_version, client_cipher_version = \
2589 server.get_cipher_version(), client.get_cipher_version()
2590
Alex Chan1c0cb662017-01-30 07:13:30 +00002591 assert isinstance(server_cipher_version, text_type)
2592 assert isinstance(client_cipher_version, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002593
Alex Chan1c0cb662017-01-30 07:13:30 +00002594 assert server_cipher_version == client_cipher_version
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002595
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002596 def test_get_cipher_bits_before_connect(self):
2597 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002598 `Connection.get_cipher_bits` returns `None` if no connection has
2599 been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002600 """
2601 ctx = Context(TLSv1_METHOD)
2602 conn = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002603 assert conn.get_cipher_bits() is None
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002604
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002605 def test_get_cipher_bits(self):
2606 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002607 `Connection.get_cipher_bits` returns the number of secret bits
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002608 of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002609 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002610 server, client = loopback()
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002611 server_cipher_bits, client_cipher_bits = \
2612 server.get_cipher_bits(), client.get_cipher_bits()
2613
Alex Chan1c0cb662017-01-30 07:13:30 +00002614 assert isinstance(server_cipher_bits, int)
2615 assert isinstance(client_cipher_bits, int)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002616
Alex Chan1c0cb662017-01-30 07:13:30 +00002617 assert server_cipher_bits == client_cipher_bits
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002618
Jim Shaverabff1882015-05-27 09:15:55 -04002619 def test_get_protocol_version_name(self):
2620 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002621 `Connection.get_protocol_version_name()` returns a string giving the
2622 protocol version of the current connection.
Jim Shaverabff1882015-05-27 09:15:55 -04002623 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002624 server, client = loopback()
Jim Shaverabff1882015-05-27 09:15:55 -04002625 client_protocol_version_name = client.get_protocol_version_name()
2626 server_protocol_version_name = server.get_protocol_version_name()
2627
Alex Chan1c0cb662017-01-30 07:13:30 +00002628 assert isinstance(server_protocol_version_name, text_type)
2629 assert isinstance(client_protocol_version_name, text_type)
Jim Shaverabff1882015-05-27 09:15:55 -04002630
Alex Chan1c0cb662017-01-30 07:13:30 +00002631 assert server_protocol_version_name == client_protocol_version_name
Jim Shaverabff1882015-05-27 09:15:55 -04002632
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002633 def test_get_protocol_version(self):
2634 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002635 `Connection.get_protocol_version()` returns an integer
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002636 giving the protocol version of the current connection.
2637 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002638 server, client = loopback()
Jim Shaver85a4dff2015-04-27 17:42:46 -04002639 client_protocol_version = client.get_protocol_version()
2640 server_protocol_version = server.get_protocol_version()
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002641
Alex Chan1c0cb662017-01-30 07:13:30 +00002642 assert isinstance(server_protocol_version, int)
2643 assert isinstance(client_protocol_version, int)
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002644
Alex Chan1c0cb662017-01-30 07:13:30 +00002645 assert server_protocol_version == client_protocol_version
2646
2647 def test_wantReadError(self):
2648 """
2649 `Connection.bio_read` raises `OpenSSL.SSL.WantReadError` if there are
2650 no bytes available to be read from the BIO.
2651 """
2652 ctx = Context(TLSv1_METHOD)
2653 conn = Connection(ctx, None)
2654 with pytest.raises(WantReadError):
2655 conn.bio_read(1024)
2656
Alex Chanfb078d82017-04-20 11:16:15 +01002657 @pytest.mark.parametrize('bufsize', [1.0, None, object(), 'bufsize'])
2658 def test_bio_read_wrong_args(self, bufsize):
2659 """
2660 `Connection.bio_read` raises `TypeError` if passed a non-integer
2661 argument.
2662 """
2663 ctx = Context(TLSv1_METHOD)
2664 conn = Connection(ctx, None)
2665 with pytest.raises(TypeError):
2666 conn.bio_read(bufsize)
2667
Alex Chan1c0cb662017-01-30 07:13:30 +00002668 def test_buffer_size(self):
2669 """
2670 `Connection.bio_read` accepts an integer giving the maximum number
2671 of bytes to read and return.
2672 """
2673 ctx = Context(TLSv1_METHOD)
2674 conn = Connection(ctx, None)
2675 conn.set_connect_state()
2676 try:
2677 conn.do_handshake()
2678 except WantReadError:
2679 pass
2680 data = conn.bio_read(2)
2681 assert 2 == len(data)
2682
2683 @skip_if_py3
2684 def test_buffer_size_long(self):
2685 """
2686 On Python 2 `Connection.bio_read` accepts values of type `long` as
2687 well as `int`.
2688 """
2689 ctx = Context(TLSv1_METHOD)
2690 conn = Connection(ctx, None)
2691 conn.set_connect_state()
2692 try:
2693 conn.do_handshake()
2694 except WantReadError:
2695 pass
2696 data = conn.bio_read(long(2))
2697 assert 2 == len(data)
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002698
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002699
Alex Chanb7480992017-01-30 14:04:47 +00002700class TestConnectionGetCipherList(object):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002701 """
Alex Chanb7480992017-01-30 14:04:47 +00002702 Tests for `Connection.get_cipher_list`.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002703 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002704 def test_result(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002705 """
Alex Chanb7480992017-01-30 14:04:47 +00002706 `Connection.get_cipher_list` returns a list of `bytes` giving the
2707 names of the ciphers which might be used.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002708 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002709 connection = Connection(Context(TLSv1_METHOD), None)
2710 ciphers = connection.get_cipher_list()
Alex Chanb7480992017-01-30 14:04:47 +00002711 assert isinstance(ciphers, list)
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002712 for cipher in ciphers:
Alex Chanb7480992017-01-30 14:04:47 +00002713 assert isinstance(cipher, str)
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002714
2715
Maximilian Hils868dc3c2017-02-10 14:56:55 +01002716class VeryLarge(bytes):
2717 """
2718 Mock object so that we don't have to allocate 2**31 bytes
2719 """
2720 def __len__(self):
2721 return 2**31
2722
2723
Alex Chanb7480992017-01-30 14:04:47 +00002724class TestConnectionSend(object):
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002725 """
Alex Chanb7480992017-01-30 14:04:47 +00002726 Tests for `Connection.send`.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002727 """
2728 def test_wrong_args(self):
2729 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002730 When called with arguments other than string argument for its first
Alex Chanb7480992017-01-30 14:04:47 +00002731 parameter, `Connection.send` raises `TypeError`.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002732 """
2733 connection = Connection(Context(TLSv1_METHOD), None)
Alex Chanb7480992017-01-30 14:04:47 +00002734 with pytest.raises(TypeError):
2735 connection.send(object())
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002736
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002737 def test_short_bytes(self):
2738 """
Alex Chanb7480992017-01-30 14:04:47 +00002739 When passed a short byte string, `Connection.send` transmits all of it
2740 and returns the number of bytes sent.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002741 """
Alex Chanb7480992017-01-30 14:04:47 +00002742 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002743 count = server.send(b'xy')
Alex Chanb7480992017-01-30 14:04:47 +00002744 assert count == 2
2745 assert client.recv(2) == b'xy'
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002746
Abraham Martinef063482015-03-25 14:06:24 +00002747 def test_text(self):
2748 """
Alex Chanb7480992017-01-30 14:04:47 +00002749 When passed a text, `Connection.send` transmits all of it and
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002750 returns the number of bytes sent. It also raises a DeprecationWarning.
Abraham Martinef063482015-03-25 14:06:24 +00002751 """
Alex Chanb7480992017-01-30 14:04:47 +00002752 server, client = loopback()
2753 with pytest.warns(DeprecationWarning) as w:
Abraham Martinef063482015-03-25 14:06:24 +00002754 simplefilter("always")
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002755 count = server.send(b"xy".decode("ascii"))
Alex Chanb7480992017-01-30 14:04:47 +00002756 assert (
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002757 "{0} for buf is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002758 WARNING_TYPE_EXPECTED
Alex Chanb7480992017-01-30 14:04:47 +00002759 ) == str(w[-1].message))
2760 assert count == 2
2761 assert client.recv(2) == b'xy'
Abraham Martinef063482015-03-25 14:06:24 +00002762
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002763 @skip_if_py26
2764 def test_short_memoryview(self):
2765 """
2766 When passed a memoryview onto a small number of bytes,
Alex Chanb7480992017-01-30 14:04:47 +00002767 `Connection.send` transmits all of them and returns the number
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002768 of bytes sent.
2769 """
Alex Chanb7480992017-01-30 14:04:47 +00002770 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002771 count = server.send(memoryview(b'xy'))
Alex Chanb7480992017-01-30 14:04:47 +00002772 assert count == 2
2773 assert client.recv(2) == b'xy'
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002774
Hynek Schlawack8e94f1b2015-09-05 21:31:00 +02002775 @skip_if_py3
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002776 def test_short_buffer(self):
2777 """
2778 When passed a buffer containing a small number of bytes,
Alex Chanb7480992017-01-30 14:04:47 +00002779 `Connection.send` transmits all of them and returns the number
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002780 of bytes sent.
2781 """
Alex Chanb7480992017-01-30 14:04:47 +00002782 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002783 count = server.send(buffer(b'xy'))
Alex Chanb7480992017-01-30 14:04:47 +00002784 assert count == 2
2785 assert client.recv(2) == b'xy'
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02002786
Maximilian Hils868dc3c2017-02-10 14:56:55 +01002787 @pytest.mark.skipif(
2788 sys.maxsize < 2**31,
2789 reason="sys.maxsize < 2**31 - test requires 64 bit"
2790 )
2791 def test_buf_too_large(self):
2792 """
2793 When passed a buffer containing >= 2**31 bytes,
2794 `Connection.send` bails out as SSL_write only
2795 accepts an int for the buffer length.
2796 """
2797 connection = Connection(Context(TLSv1_METHOD), None)
2798 with pytest.raises(ValueError) as exc_info:
2799 connection.send(VeryLarge())
2800 exc_info.match(r"Cannot send more than .+ bytes at once")
2801
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05002802
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002803def _make_memoryview(size):
2804 """
2805 Create a new ``memoryview`` wrapped around a ``bytearray`` of the given
2806 size.
2807 """
2808 return memoryview(bytearray(size))
2809
2810
Alex Chanb7480992017-01-30 14:04:47 +00002811class TestConnectionRecvInto(object):
Cory Benfield62d10332014-06-15 10:03:41 +01002812 """
Alex Chanb7480992017-01-30 14:04:47 +00002813 Tests for `Connection.recv_into`.
Cory Benfield62d10332014-06-15 10:03:41 +01002814 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002815 def _no_length_test(self, factory):
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04002816 """
Alex Chanb7480992017-01-30 14:04:47 +00002817 Assert that when the given buffer is passed to `Connection.recv_into`,
2818 whatever bytes are available to be received that fit into that buffer
2819 are written into that buffer.
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04002820 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002821 output_buffer = factory(5)
2822
Alex Chanb7480992017-01-30 14:04:47 +00002823 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002824 server.send(b'xy')
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04002825
Alex Chanb7480992017-01-30 14:04:47 +00002826 assert client.recv_into(output_buffer) == 2
2827 assert output_buffer == bytearray(b'xy\x00\x00\x00')
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04002828
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002829 def test_bytearray_no_length(self):
Cory Benfield62d10332014-06-15 10:03:41 +01002830 """
Alex Chanb7480992017-01-30 14:04:47 +00002831 `Connection.recv_into` can be passed a `bytearray` instance and data
2832 in the receive buffer is written to it.
Cory Benfield62d10332014-06-15 10:03:41 +01002833 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002834 self._no_length_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01002835
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002836 def _respects_length_test(self, factory):
Cory Benfield62d10332014-06-15 10:03:41 +01002837 """
Alex Chanb7480992017-01-30 14:04:47 +00002838 Assert that when the given buffer is passed to `Connection.recv_into`
2839 along with a value for `nbytes` that is less than the size of that
2840 buffer, only `nbytes` bytes are written into the buffer.
Cory Benfield62d10332014-06-15 10:03:41 +01002841 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002842 output_buffer = factory(10)
2843
Alex Chanb7480992017-01-30 14:04:47 +00002844 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002845 server.send(b'abcdefghij')
Cory Benfield62d10332014-06-15 10:03:41 +01002846
Alex Chanb7480992017-01-30 14:04:47 +00002847 assert client.recv_into(output_buffer, 5) == 5
2848 assert output_buffer == bytearray(b'abcde\x00\x00\x00\x00\x00')
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002849
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002850 def test_bytearray_respects_length(self):
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002851 """
Alex Chanb7480992017-01-30 14:04:47 +00002852 When called with a `bytearray` instance, `Connection.recv_into`
2853 respects the `nbytes` parameter and doesn't copy in more than that
2854 number of bytes.
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002855 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002856 self._respects_length_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01002857
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002858 def _doesnt_overfill_test(self, factory):
Cory Benfield62d10332014-06-15 10:03:41 +01002859 """
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002860 Assert that if there are more bytes available to be read from the
2861 receive buffer than would fit into the buffer passed to
Alex Chanb7480992017-01-30 14:04:47 +00002862 `Connection.recv_into`, only as many as fit are written into it.
Cory Benfield62d10332014-06-15 10:03:41 +01002863 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002864 output_buffer = factory(5)
2865
Alex Chanb7480992017-01-30 14:04:47 +00002866 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002867 server.send(b'abcdefghij')
Cory Benfield62d10332014-06-15 10:03:41 +01002868
Alex Chanb7480992017-01-30 14:04:47 +00002869 assert client.recv_into(output_buffer) == 5
2870 assert output_buffer == bytearray(b'abcde')
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002871 rest = client.recv(5)
Alex Chanb7480992017-01-30 14:04:47 +00002872 assert b'fghij' == rest
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002873
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002874 def test_bytearray_doesnt_overfill(self):
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002875 """
Alex Chanb7480992017-01-30 14:04:47 +00002876 When called with a `bytearray` instance, `Connection.recv_into`
2877 respects the size of the array and doesn't write more bytes into it
2878 than will fit.
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002879 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002880 self._doesnt_overfill_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01002881
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002882 def test_bytearray_really_doesnt_overfill(self):
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04002883 """
Alex Chanb7480992017-01-30 14:04:47 +00002884 When called with a `bytearray` instance and an `nbytes` value that is
2885 too large, `Connection.recv_into` respects the size of the array and
2886 not the `nbytes` value and doesn't write more bytes into the buffer
2887 than will fit.
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04002888 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002889 self._doesnt_overfill_test(bytearray)
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04002890
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002891 def test_peek(self):
Alex Chanb7480992017-01-30 14:04:47 +00002892 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002893 server.send(b'xy')
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002894
2895 for _ in range(2):
2896 output_buffer = bytearray(5)
Alex Chanb7480992017-01-30 14:04:47 +00002897 assert client.recv_into(output_buffer, flags=MSG_PEEK) == 2
2898 assert output_buffer == bytearray(b'xy\x00\x00\x00')
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002899
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002900 @skip_if_py26
2901 def test_memoryview_no_length(self):
2902 """
Alex Chanb7480992017-01-30 14:04:47 +00002903 `Connection.recv_into` can be passed a `memoryview` instance and data
2904 in the receive buffer is written to it.
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002905 """
2906 self._no_length_test(_make_memoryview)
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002907
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002908 @skip_if_py26
2909 def test_memoryview_respects_length(self):
2910 """
Alex Chanb7480992017-01-30 14:04:47 +00002911 When called with a `memoryview` instance, `Connection.recv_into`
2912 respects the ``nbytes`` parameter and doesn't copy more than that
2913 number of bytes in.
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002914 """
2915 self._respects_length_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01002916
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002917 @skip_if_py26
2918 def test_memoryview_doesnt_overfill(self):
2919 """
Alex Chanb7480992017-01-30 14:04:47 +00002920 When called with a `memoryview` instance, `Connection.recv_into`
2921 respects the size of the array and doesn't write more bytes into it
2922 than will fit.
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002923 """
2924 self._doesnt_overfill_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01002925
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002926 @skip_if_py26
2927 def test_memoryview_really_doesnt_overfill(self):
2928 """
Alex Chanb7480992017-01-30 14:04:47 +00002929 When called with a `memoryview` instance and an `nbytes` value that is
2930 too large, `Connection.recv_into` respects the size of the array and
2931 not the `nbytes` value and doesn't write more bytes into the buffer
2932 than will fit.
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002933 """
2934 self._doesnt_overfill_test(_make_memoryview)
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04002935
Cory Benfield62d10332014-06-15 10:03:41 +01002936
Alex Chanb7480992017-01-30 14:04:47 +00002937class TestConnectionSendall(object):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002938 """
Alex Chanb7480992017-01-30 14:04:47 +00002939 Tests for `Connection.sendall`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002940 """
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002941 def test_wrong_args(self):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002942 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002943 When called with arguments other than a string argument for its first
Alex Chanb7480992017-01-30 14:04:47 +00002944 parameter, `Connection.sendall` raises `TypeError`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002945 """
2946 connection = Connection(Context(TLSv1_METHOD), None)
Alex Chanb7480992017-01-30 14:04:47 +00002947 with pytest.raises(TypeError):
2948 connection.sendall(object())
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002949
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002950 def test_short(self):
2951 """
Alex Chanb7480992017-01-30 14:04:47 +00002952 `Connection.sendall` transmits all of the bytes in the string
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02002953 passed to it.
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002954 """
Alex Chanb7480992017-01-30 14:04:47 +00002955 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002956 server.sendall(b'x')
Alex Chanb7480992017-01-30 14:04:47 +00002957 assert client.recv(1) == b'x'
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002958
Abraham Martinef063482015-03-25 14:06:24 +00002959 def test_text(self):
2960 """
Alex Chanb7480992017-01-30 14:04:47 +00002961 `Connection.sendall` transmits all the content in the string passed
2962 to it, raising a DeprecationWarning in case of this being a text.
Abraham Martinef063482015-03-25 14:06:24 +00002963 """
Alex Chanb7480992017-01-30 14:04:47 +00002964 server, client = loopback()
2965 with pytest.warns(DeprecationWarning) as w:
Abraham Martinef063482015-03-25 14:06:24 +00002966 simplefilter("always")
Jean-Paul Calderone8dc37a12015-03-29 08:16:52 -04002967 server.sendall(b"x".decode("ascii"))
Alex Chanb7480992017-01-30 14:04:47 +00002968 assert (
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002969 "{0} for buf is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002970 WARNING_TYPE_EXPECTED
Alex Chanb7480992017-01-30 14:04:47 +00002971 ) == str(w[-1].message))
2972 assert client.recv(1) == b"x"
Abraham Martinef063482015-03-25 14:06:24 +00002973
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02002974 @skip_if_py26
2975 def test_short_memoryview(self):
2976 """
2977 When passed a memoryview onto a small number of bytes,
Alex Chanb7480992017-01-30 14:04:47 +00002978 `Connection.sendall` transmits all of them.
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02002979 """
Alex Chanb7480992017-01-30 14:04:47 +00002980 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002981 server.sendall(memoryview(b'x'))
Alex Chanb7480992017-01-30 14:04:47 +00002982 assert client.recv(1) == b'x'
Abraham Martinef063482015-03-25 14:06:24 +00002983
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02002984 @skip_if_py3
2985 def test_short_buffers(self):
2986 """
2987 When passed a buffer containing a small number of bytes,
Alex Chanb7480992017-01-30 14:04:47 +00002988 `Connection.sendall` transmits all of them.
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02002989 """
Alex Chanb7480992017-01-30 14:04:47 +00002990 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002991 server.sendall(buffer(b'x'))
Alex Chanb7480992017-01-30 14:04:47 +00002992 assert client.recv(1) == b'x'
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02002993
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002994 def test_long(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002995 """
Alex Chanb7480992017-01-30 14:04:47 +00002996 `Connection.sendall` transmits all the bytes in the string passed to it
2997 even if this requires multiple calls of an underlying write function.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002998 """
Alex Chanb7480992017-01-30 14:04:47 +00002999 server, client = loopback()
Jean-Paul Calderone6241c702010-09-16 19:59:24 -04003000 # Should be enough, underlying SSL_write should only do 16k at a time.
Hynek Schlawack35618382015-09-05 21:54:25 +02003001 # On Windows, after 32k of bytes the write will block (forever
3002 # - because no one is yet reading).
Alex Gaynore7f51982016-09-11 11:48:14 -04003003 message = b'x' * (1024 * 32 - 1) + b'y'
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003004 server.sendall(message)
3005 accum = []
3006 received = 0
3007 while received < len(message):
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04003008 data = client.recv(1024)
3009 accum.append(data)
3010 received += len(data)
Alex Chanb7480992017-01-30 14:04:47 +00003011 assert message == b''.join(accum)
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003012
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003013 def test_closed(self):
3014 """
Alex Chanb7480992017-01-30 14:04:47 +00003015 If the underlying socket is closed, `Connection.sendall` propagates the
3016 write error from the low level write call.
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003017 """
Alex Chanb7480992017-01-30 14:04:47 +00003018 server, client = loopback()
Jean-Paul Calderone05d43e82010-09-24 18:01:36 -04003019 server.sock_shutdown(2)
Alex Chanb7480992017-01-30 14:04:47 +00003020 with pytest.raises(SysCallError) as err:
3021 server.sendall(b"hello, world")
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +02003022 if platform == "win32":
Alex Chanb7480992017-01-30 14:04:47 +00003023 assert err.value.args[0] == ESHUTDOWN
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +02003024 else:
Alex Chanb7480992017-01-30 14:04:47 +00003025 assert err.value.args[0] == EPIPE
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003026
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003027
Alex Chanb7480992017-01-30 14:04:47 +00003028class TestConnectionRenegotiate(object):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003029 """
3030 Tests for SSL renegotiation APIs.
3031 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003032 def test_total_renegotiations(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003033 """
Alex Chanb7480992017-01-30 14:04:47 +00003034 `Connection.total_renegotiations` returns `0` before any renegotiations
3035 have happened.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003036 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003037 connection = Connection(Context(TLSv1_METHOD), None)
Alex Chanb7480992017-01-30 14:04:47 +00003038 assert connection.total_renegotiations() == 0
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003039
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003040 def test_renegotiate(self):
3041 """
3042 Go through a complete renegotiation cycle.
3043 """
Alex Chanb7480992017-01-30 14:04:47 +00003044 server, client = loopback()
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003045
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003046 server.send(b"hello world")
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003047
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003048 assert b"hello world" == client.recv(len(b"hello world"))
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003049
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003050 assert 0 == server.total_renegotiations()
3051 assert False is server.renegotiate_pending()
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003052
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003053 assert True is server.renegotiate()
3054
3055 assert True is server.renegotiate_pending()
3056
3057 server.setblocking(False)
3058 client.setblocking(False)
3059
3060 client.do_handshake()
3061 server.do_handshake()
3062
3063 assert 1 == server.total_renegotiations()
3064 while False is server.renegotiate_pending():
3065 pass
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003066
3067
Alex Chanb7480992017-01-30 14:04:47 +00003068class TestError(object):
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003069 """
Alex Chanb7480992017-01-30 14:04:47 +00003070 Unit tests for `OpenSSL.SSL.Error`.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003071 """
3072 def test_type(self):
3073 """
Alex Chanb7480992017-01-30 14:04:47 +00003074 `Error` is an exception type.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003075 """
Alex Chanb7480992017-01-30 14:04:47 +00003076 assert issubclass(Error, Exception)
3077 assert Error.__name__ == 'Error'
Rick Deane15b1472009-07-09 15:53:42 -05003078
3079
Alex Chanb7480992017-01-30 14:04:47 +00003080class TestConstants(object):
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003081 """
Alex Chanb7480992017-01-30 14:04:47 +00003082 Tests for the values of constants exposed in `OpenSSL.SSL`.
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003083
3084 These are values defined by OpenSSL intended only to be used as flags to
3085 OpenSSL APIs. The only assertions it seems can be made about them is
3086 their values.
3087 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003088 @pytest.mark.skipif(
3089 OP_NO_QUERY_MTU is None,
3090 reason="OP_NO_QUERY_MTU unavailable - OpenSSL version may be too old"
3091 )
3092 def test_op_no_query_mtu(self):
3093 """
Alex Chanb7480992017-01-30 14:04:47 +00003094 The value of `OpenSSL.SSL.OP_NO_QUERY_MTU` is 0x1000, the value
3095 of `SSL_OP_NO_QUERY_MTU` defined by `openssl/ssl.h`.
Hynek Schlawack35618382015-09-05 21:54:25 +02003096 """
Alex Chanb7480992017-01-30 14:04:47 +00003097 assert OP_NO_QUERY_MTU == 0x1000
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003098
Hynek Schlawack35618382015-09-05 21:54:25 +02003099 @pytest.mark.skipif(
3100 OP_COOKIE_EXCHANGE is None,
3101 reason="OP_COOKIE_EXCHANGE unavailable - "
3102 "OpenSSL version may be too old"
3103 )
3104 def test_op_cookie_exchange(self):
3105 """
Alex Chanb7480992017-01-30 14:04:47 +00003106 The value of `OpenSSL.SSL.OP_COOKIE_EXCHANGE` is 0x2000, the
3107 value of `SSL_OP_COOKIE_EXCHANGE` defined by `openssl/ssl.h`.
Hynek Schlawack35618382015-09-05 21:54:25 +02003108 """
Alex Chanb7480992017-01-30 14:04:47 +00003109 assert OP_COOKIE_EXCHANGE == 0x2000
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003110
Hynek Schlawack35618382015-09-05 21:54:25 +02003111 @pytest.mark.skipif(
3112 OP_NO_TICKET is None,
3113 reason="OP_NO_TICKET unavailable - OpenSSL version may be too old"
3114 )
3115 def test_op_no_ticket(self):
3116 """
Alex Chanb7480992017-01-30 14:04:47 +00003117 The value of `OpenSSL.SSL.OP_NO_TICKET` is 0x4000, the value of
3118 `SSL_OP_NO_TICKET` defined by `openssl/ssl.h`.
Hynek Schlawack35618382015-09-05 21:54:25 +02003119 """
Alex Chanb7480992017-01-30 14:04:47 +00003120 assert OP_NO_TICKET == 0x4000
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003121
Hynek Schlawack35618382015-09-05 21:54:25 +02003122 @pytest.mark.skipif(
3123 OP_NO_COMPRESSION is None,
3124 reason="OP_NO_COMPRESSION unavailable - OpenSSL version may be too old"
3125 )
3126 def test_op_no_compression(self):
3127 """
Alex Chanb7480992017-01-30 14:04:47 +00003128 The value of `OpenSSL.SSL.OP_NO_COMPRESSION` is 0x20000, the
3129 value of `SSL_OP_NO_COMPRESSION` defined by `openssl/ssl.h`.
Hynek Schlawack35618382015-09-05 21:54:25 +02003130 """
Alex Chanb7480992017-01-30 14:04:47 +00003131 assert OP_NO_COMPRESSION == 0x20000
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04003132
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003133 def test_sess_cache_off(self):
3134 """
Alex Chanb7480992017-01-30 14:04:47 +00003135 The value of `OpenSSL.SSL.SESS_CACHE_OFF` 0x0, the value of
3136 `SSL_SESS_CACHE_OFF` defined by `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003137 """
Alex Chanb7480992017-01-30 14:04:47 +00003138 assert 0x0 == SESS_CACHE_OFF
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003139
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003140 def test_sess_cache_client(self):
3141 """
Alex Chanb7480992017-01-30 14:04:47 +00003142 The value of `OpenSSL.SSL.SESS_CACHE_CLIENT` 0x1, the value of
3143 `SSL_SESS_CACHE_CLIENT` defined by `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003144 """
Alex Chanb7480992017-01-30 14:04:47 +00003145 assert 0x1 == SESS_CACHE_CLIENT
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003146
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003147 def test_sess_cache_server(self):
3148 """
Alex Chanb7480992017-01-30 14:04:47 +00003149 The value of `OpenSSL.SSL.SESS_CACHE_SERVER` 0x2, the value of
3150 `SSL_SESS_CACHE_SERVER` defined by `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003151 """
Alex Chanb7480992017-01-30 14:04:47 +00003152 assert 0x2 == SESS_CACHE_SERVER
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003153
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003154 def test_sess_cache_both(self):
3155 """
Alex Chanb7480992017-01-30 14:04:47 +00003156 The value of `OpenSSL.SSL.SESS_CACHE_BOTH` 0x3, the value of
3157 `SSL_SESS_CACHE_BOTH` defined by `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003158 """
Alex Chanb7480992017-01-30 14:04:47 +00003159 assert 0x3 == SESS_CACHE_BOTH
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003160
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003161 def test_sess_cache_no_auto_clear(self):
3162 """
Alex Chanb7480992017-01-30 14:04:47 +00003163 The value of `OpenSSL.SSL.SESS_CACHE_NO_AUTO_CLEAR` 0x80, the
3164 value of `SSL_SESS_CACHE_NO_AUTO_CLEAR` defined by
3165 `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003166 """
Alex Chanb7480992017-01-30 14:04:47 +00003167 assert 0x80 == SESS_CACHE_NO_AUTO_CLEAR
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003168
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003169 def test_sess_cache_no_internal_lookup(self):
3170 """
Alex Chanb7480992017-01-30 14:04:47 +00003171 The value of `OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_LOOKUP` 0x100,
3172 the value of `SSL_SESS_CACHE_NO_INTERNAL_LOOKUP` defined by
3173 `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003174 """
Alex Chanb7480992017-01-30 14:04:47 +00003175 assert 0x100 == SESS_CACHE_NO_INTERNAL_LOOKUP
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003176
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003177 def test_sess_cache_no_internal_store(self):
3178 """
Alex Chanb7480992017-01-30 14:04:47 +00003179 The value of `OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_STORE` 0x200,
3180 the value of `SSL_SESS_CACHE_NO_INTERNAL_STORE` defined by
3181 `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003182 """
Alex Chanb7480992017-01-30 14:04:47 +00003183 assert 0x200 == SESS_CACHE_NO_INTERNAL_STORE
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003184
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003185 def test_sess_cache_no_internal(self):
3186 """
Alex Chanb7480992017-01-30 14:04:47 +00003187 The value of `OpenSSL.SSL.SESS_CACHE_NO_INTERNAL` 0x300, the
3188 value of `SSL_SESS_CACHE_NO_INTERNAL` defined by
3189 `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003190 """
Alex Chanb7480992017-01-30 14:04:47 +00003191 assert 0x300 == SESS_CACHE_NO_INTERNAL
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003192
3193
Alex Chanb7480992017-01-30 14:04:47 +00003194class TestMemoryBIO(object):
Rick Deanb71c0d22009-04-01 14:09:23 -05003195 """
Alex Chanb7480992017-01-30 14:04:47 +00003196 Tests for `OpenSSL.SSL.Connection` using a memory BIO.
Rick Deanb71c0d22009-04-01 14:09:23 -05003197 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003198 def _server(self, sock):
3199 """
Alex Chanb7480992017-01-30 14:04:47 +00003200 Create a new server-side SSL `Connection` object wrapped around `sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003201 """
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003202 # Create the server side Connection. This is mostly setup boilerplate
3203 # - use TLSv1, use a particular certificate, etc.
3204 server_ctx = Context(TLSv1_METHOD)
Alex Gaynor43307782015-09-04 09:05:45 -04003205 server_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE)
Hynek Schlawack35618382015-09-05 21:54:25 +02003206 server_ctx.set_verify(
3207 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT | VERIFY_CLIENT_ONCE,
3208 verify_cb
3209 )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003210 server_store = server_ctx.get_cert_store()
Hynek Schlawack35618382015-09-05 21:54:25 +02003211 server_ctx.use_privatekey(
3212 load_privatekey(FILETYPE_PEM, server_key_pem))
3213 server_ctx.use_certificate(
3214 load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003215 server_ctx.check_privatekey()
3216 server_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Hynek Schlawack35618382015-09-05 21:54:25 +02003217 # Here the Connection is actually created. If None is passed as the
3218 # 2nd parameter, it indicates a memory BIO should be created.
Rick Deanb1ccd562009-07-09 23:52:39 -05003219 server_conn = Connection(server_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003220 server_conn.set_accept_state()
3221 return server_conn
3222
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003223 def _client(self, sock):
3224 """
Alex Chanb7480992017-01-30 14:04:47 +00003225 Create a new client-side SSL `Connection` object wrapped around `sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003226 """
3227 # Now create the client side Connection. Similar boilerplate to the
3228 # above.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003229 client_ctx = Context(TLSv1_METHOD)
Alex Gaynor43307782015-09-04 09:05:45 -04003230 client_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE)
Hynek Schlawack35618382015-09-05 21:54:25 +02003231 client_ctx.set_verify(
3232 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT | VERIFY_CLIENT_ONCE,
3233 verify_cb
3234 )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003235 client_store = client_ctx.get_cert_store()
Hynek Schlawack35618382015-09-05 21:54:25 +02003236 client_ctx.use_privatekey(
3237 load_privatekey(FILETYPE_PEM, client_key_pem))
3238 client_ctx.use_certificate(
3239 load_certificate(FILETYPE_PEM, client_cert_pem))
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003240 client_ctx.check_privatekey()
3241 client_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05003242 client_conn = Connection(client_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003243 client_conn.set_connect_state()
3244 return client_conn
3245
Alex Chanb7480992017-01-30 14:04:47 +00003246 def test_memory_connect(self):
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003247 """
Alex Chanb7480992017-01-30 14:04:47 +00003248 Two `Connection`s which use memory BIOs can be manually connected by
3249 reading from the output of each and writing those bytes to the input of
3250 the other and in this way establish a connection and exchange
3251 application-level bytes with each other.
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003252 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003253 server_conn = self._server(None)
3254 client_conn = self._client(None)
Rick Deanb71c0d22009-04-01 14:09:23 -05003255
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003256 # There should be no key or nonces yet.
Alex Chanb7480992017-01-30 14:04:47 +00003257 assert server_conn.master_key() is None
3258 assert server_conn.client_random() is None
3259 assert server_conn.server_random() is None
Rick Deanb71c0d22009-04-01 14:09:23 -05003260
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003261 # First, the handshake needs to happen. We'll deliver bytes back and
3262 # forth between the client and server until neither of them feels like
3263 # speaking any more.
Alex Chanb7480992017-01-30 14:04:47 +00003264 assert interact_in_memory(client_conn, server_conn) is None
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003265
3266 # Now that the handshake is done, there should be a key and nonces.
Alex Chanb7480992017-01-30 14:04:47 +00003267 assert server_conn.master_key() is not None
3268 assert server_conn.client_random() is not None
3269 assert server_conn.server_random() is not None
3270 assert server_conn.client_random() == client_conn.client_random()
3271 assert server_conn.server_random() == client_conn.server_random()
3272 assert server_conn.client_random() != server_conn.server_random()
3273 assert client_conn.client_random() != client_conn.server_random()
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003274
3275 # Here are the bytes we'll try to send.
Alex Gaynore7f51982016-09-11 11:48:14 -04003276 important_message = b'One if by land, two if by sea.'
Rick Deanb71c0d22009-04-01 14:09:23 -05003277
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003278 server_conn.write(important_message)
Alex Chanb7480992017-01-30 14:04:47 +00003279 assert (
3280 interact_in_memory(client_conn, server_conn) ==
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003281 (client_conn, important_message))
3282
3283 client_conn.write(important_message[::-1])
Alex Chanb7480992017-01-30 14:04:47 +00003284 assert (
3285 interact_in_memory(client_conn, server_conn) ==
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003286 (server_conn, important_message[::-1]))
Rick Deanb71c0d22009-04-01 14:09:23 -05003287
Alex Chanb7480992017-01-30 14:04:47 +00003288 def test_socket_connect(self):
Rick Deanb1ccd562009-07-09 23:52:39 -05003289 """
Alex Chanb7480992017-01-30 14:04:47 +00003290 Just like `test_memory_connect` but with an actual socket.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003291
Hynek Schlawack35618382015-09-05 21:54:25 +02003292 This is primarily to rule out the memory BIO code as the source of any
Alex Chanb7480992017-01-30 14:04:47 +00003293 problems encountered while passing data over a `Connection` (if
Hynek Schlawack35618382015-09-05 21:54:25 +02003294 this test fails, there must be a problem outside the memory BIO code,
3295 as no memory BIO is involved here). Even though this isn't a memory
3296 BIO test, it's convenient to have it here.
Rick Deanb1ccd562009-07-09 23:52:39 -05003297 """
Alex Chanb7480992017-01-30 14:04:47 +00003298 server_conn, client_conn = loopback()
Rick Deanb1ccd562009-07-09 23:52:39 -05003299
Alex Gaynore7f51982016-09-11 11:48:14 -04003300 important_message = b"Help me Obi Wan Kenobi, you're my only hope."
Rick Deanb1ccd562009-07-09 23:52:39 -05003301 client_conn.send(important_message)
3302 msg = server_conn.recv(1024)
Alex Chanb7480992017-01-30 14:04:47 +00003303 assert msg == important_message
Rick Deanb1ccd562009-07-09 23:52:39 -05003304
3305 # Again in the other direction, just for fun.
3306 important_message = important_message[::-1]
3307 server_conn.send(important_message)
3308 msg = client_conn.recv(1024)
Alex Chanb7480992017-01-30 14:04:47 +00003309 assert msg == important_message
Rick Deanb1ccd562009-07-09 23:52:39 -05003310
Alex Chanb7480992017-01-30 14:04:47 +00003311 def test_socket_overrides_memory(self):
Rick Deanb71c0d22009-04-01 14:09:23 -05003312 """
Alex Chanb7480992017-01-30 14:04:47 +00003313 Test that `OpenSSL.SSL.bio_read` and `OpenSSL.SSL.bio_write` don't
3314 work on `OpenSSL.SSL.Connection`() that use sockets.
Rick Deanb71c0d22009-04-01 14:09:23 -05003315 """
Alex Gaynor51d424c2016-09-10 14:50:11 -04003316 context = Context(TLSv1_METHOD)
Rick Deanb71c0d22009-04-01 14:09:23 -05003317 client = socket()
3318 clientSSL = Connection(context, client)
Alex Chanb7480992017-01-30 14:04:47 +00003319 with pytest.raises(TypeError):
3320 clientSSL.bio_read(100)
3321 with pytest.raises(TypeError):
3322 clientSSL.bio_write("foo")
3323 with pytest.raises(TypeError):
3324 clientSSL.bio_shutdown()
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003325
Alex Chanb7480992017-01-30 14:04:47 +00003326 def test_outgoing_overflow(self):
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003327 """
3328 If more bytes than can be written to the memory BIO are passed to
Alex Chanb7480992017-01-30 14:04:47 +00003329 `Connection.send` at once, the number of bytes which were written is
3330 returned and that many bytes from the beginning of the input can be
3331 read from the other end of the connection.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003332 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003333 server = self._server(None)
3334 client = self._client(None)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003335
Alex Chanb7480992017-01-30 14:04:47 +00003336 interact_in_memory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003337
3338 size = 2 ** 15
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003339 sent = client.send(b"x" * size)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003340 # Sanity check. We're trying to test what happens when the entire
3341 # input can't be sent. If the entire input was sent, this test is
3342 # meaningless.
Alex Chanb7480992017-01-30 14:04:47 +00003343 assert sent < size
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003344
Alex Chanb7480992017-01-30 14:04:47 +00003345 receiver, received = interact_in_memory(client, server)
3346 assert receiver is server
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003347
3348 # We can rely on all of these bytes being received at once because
Alex Chanb7480992017-01-30 14:04:47 +00003349 # loopback passes 2 ** 16 to recv - more than 2 ** 15.
3350 assert len(received) == sent
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003351
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003352 def test_shutdown(self):
3353 """
Alex Chanb7480992017-01-30 14:04:47 +00003354 `Connection.bio_shutdown` signals the end of the data stream
3355 from which the `Connection` reads.
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003356 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003357 server = self._server(None)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003358 server.bio_shutdown()
Alex Chanb7480992017-01-30 14:04:47 +00003359 with pytest.raises(Error) as err:
3360 server.recv(1024)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003361 # We don't want WantReadError or ZeroReturnError or anything - it's a
3362 # handshake failure.
Alex Chanb7480992017-01-30 14:04:47 +00003363 assert type(err.value) in [Error, SysCallError]
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003364
Alex Chanb7480992017-01-30 14:04:47 +00003365 def test_unexpected_EOF(self):
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003366 """
3367 If the connection is lost before an orderly SSL shutdown occurs,
Alex Chanb7480992017-01-30 14:04:47 +00003368 `OpenSSL.SSL.SysCallError` is raised with a message of
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003369 "Unexpected EOF".
3370 """
Alex Chanb7480992017-01-30 14:04:47 +00003371 server_conn, client_conn = loopback()
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003372 client_conn.sock_shutdown(SHUT_RDWR)
Alex Chanb7480992017-01-30 14:04:47 +00003373 with pytest.raises(SysCallError) as err:
3374 server_conn.recv(1024)
3375 assert err.value.args == (-1, "Unexpected EOF")
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003376
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003377 def _check_client_ca_list(self, func):
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003378 """
Alex Chanb7480992017-01-30 14:04:47 +00003379 Verify the return value of the `get_client_ca_list` method for
Hynek Schlawack35618382015-09-05 21:54:25 +02003380 server and client connections.
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003381
Jonathan Ballet78b92a22011-07-16 08:07:26 +09003382 :param func: A function which will be called with the server context
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003383 before the client and server are connected to each other. This
3384 function should specify a list of CAs for the server to send to the
3385 client and return that same list. The list will be used to verify
Alex Chanb7480992017-01-30 14:04:47 +00003386 that `get_client_ca_list` returns the proper value at
Hynek Schlawack35618382015-09-05 21:54:25 +02003387 various times.
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003388 """
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003389 server = self._server(None)
3390 client = self._client(None)
Alex Chanb7480992017-01-30 14:04:47 +00003391 assert client.get_client_ca_list() == []
3392 assert server.get_client_ca_list() == []
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003393 ctx = server.get_context()
3394 expected = func(ctx)
Alex Chanb7480992017-01-30 14:04:47 +00003395 assert client.get_client_ca_list() == []
3396 assert server.get_client_ca_list() == expected
3397 interact_in_memory(client, server)
3398 assert client.get_client_ca_list() == expected
3399 assert server.get_client_ca_list() == expected
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003400
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003401 def test_set_client_ca_list_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003402 """
Alex Chanb7480992017-01-30 14:04:47 +00003403 `Context.set_client_ca_list` raises a `TypeError` if called with a
3404 non-list or a list that contains objects other than X509Names.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003405 """
3406 ctx = Context(TLSv1_METHOD)
Alex Chanb7480992017-01-30 14:04:47 +00003407 with pytest.raises(TypeError):
3408 ctx.set_client_ca_list("spam")
3409 with pytest.raises(TypeError):
3410 ctx.set_client_ca_list(["spam"])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003411
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003412 def test_set_empty_ca_list(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003413 """
Alex Chanb7480992017-01-30 14:04:47 +00003414 If passed an empty list, `Context.set_client_ca_list` configures the
3415 context to send no CA names to the client and, on both the server and
3416 client sides, `Connection.get_client_ca_list` returns an empty list
3417 after the connection is set up.
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003418 """
3419 def no_ca(ctx):
3420 ctx.set_client_ca_list([])
3421 return []
3422 self._check_client_ca_list(no_ca)
3423
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003424 def test_set_one_ca_list(self):
3425 """
3426 If passed a list containing a single X509Name,
Alex Chanb7480992017-01-30 14:04:47 +00003427 `Context.set_client_ca_list` configures the context to send
Hynek Schlawack35618382015-09-05 21:54:25 +02003428 that CA name to the client and, on both the server and client sides,
Alex Chanb7480992017-01-30 14:04:47 +00003429 `Connection.get_client_ca_list` returns a list containing that
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003430 X509Name after the connection is set up.
3431 """
3432 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3433 cadesc = cacert.get_subject()
Hynek Schlawack35618382015-09-05 21:54:25 +02003434
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003435 def single_ca(ctx):
3436 ctx.set_client_ca_list([cadesc])
3437 return [cadesc]
3438 self._check_client_ca_list(single_ca)
3439
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003440 def test_set_multiple_ca_list(self):
3441 """
3442 If passed a list containing multiple X509Name objects,
Alex Chanb7480992017-01-30 14:04:47 +00003443 `Context.set_client_ca_list` configures the context to send
Hynek Schlawack35618382015-09-05 21:54:25 +02003444 those CA names to the client and, on both the server and client sides,
Alex Chanb7480992017-01-30 14:04:47 +00003445 `Connection.get_client_ca_list` returns a list containing those
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003446 X509Names after the connection is set up.
3447 """
3448 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3449 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3450
3451 sedesc = secert.get_subject()
3452 cldesc = clcert.get_subject()
3453
3454 def multiple_ca(ctx):
3455 L = [sedesc, cldesc]
3456 ctx.set_client_ca_list(L)
3457 return L
3458 self._check_client_ca_list(multiple_ca)
3459
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003460 def test_reset_ca_list(self):
3461 """
3462 If called multiple times, only the X509Names passed to the final call
Alex Chanb7480992017-01-30 14:04:47 +00003463 of `Context.set_client_ca_list` are used to configure the CA
Hynek Schlawack35618382015-09-05 21:54:25 +02003464 names sent to the client.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003465 """
3466 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3467 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3468 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3469
3470 cadesc = cacert.get_subject()
3471 sedesc = secert.get_subject()
3472 cldesc = clcert.get_subject()
3473
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003474 def changed_ca(ctx):
3475 ctx.set_client_ca_list([sedesc, cldesc])
3476 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003477 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003478 self._check_client_ca_list(changed_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003479
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003480 def test_mutated_ca_list(self):
3481 """
Alex Chanb7480992017-01-30 14:04:47 +00003482 If the list passed to `Context.set_client_ca_list` is mutated
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003483 afterwards, this does not affect the list of CA names sent to the
3484 client.
3485 """
3486 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3487 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3488
3489 cadesc = cacert.get_subject()
3490 sedesc = secert.get_subject()
3491
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003492 def mutated_ca(ctx):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003493 L = [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003494 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003495 L.append(sedesc)
3496 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003497 self._check_client_ca_list(mutated_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003498
Alex Chanb7480992017-01-30 14:04:47 +00003499 def test_add_client_ca_wrong_args(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003500 """
Alex Chanb7480992017-01-30 14:04:47 +00003501 `Context.add_client_ca` raises `TypeError` if called with
3502 a non-X509 object.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003503 """
3504 ctx = Context(TLSv1_METHOD)
Alex Chanb7480992017-01-30 14:04:47 +00003505 with pytest.raises(TypeError):
3506 ctx.add_client_ca("spam")
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003507
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003508 def test_one_add_client_ca(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003509 """
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003510 A certificate's subject can be added as a CA to be sent to the client
Alex Chanb7480992017-01-30 14:04:47 +00003511 with `Context.add_client_ca`.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003512 """
3513 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3514 cadesc = cacert.get_subject()
Hynek Schlawack35618382015-09-05 21:54:25 +02003515
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003516 def single_ca(ctx):
3517 ctx.add_client_ca(cacert)
3518 return [cadesc]
3519 self._check_client_ca_list(single_ca)
3520
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003521 def test_multiple_add_client_ca(self):
3522 """
3523 Multiple CA names can be sent to the client by calling
Alex Chanb7480992017-01-30 14:04:47 +00003524 `Context.add_client_ca` with multiple X509 objects.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003525 """
3526 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3527 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3528
3529 cadesc = cacert.get_subject()
3530 sedesc = secert.get_subject()
3531
3532 def multiple_ca(ctx):
3533 ctx.add_client_ca(cacert)
3534 ctx.add_client_ca(secert)
3535 return [cadesc, sedesc]
3536 self._check_client_ca_list(multiple_ca)
3537
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003538 def test_set_and_add_client_ca(self):
3539 """
Alex Chanb7480992017-01-30 14:04:47 +00003540 A call to `Context.set_client_ca_list` followed by a call to
3541 `Context.add_client_ca` results in using the CA names from the
Hynek Schlawack35618382015-09-05 21:54:25 +02003542 first call and the CA name from the second call.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003543 """
3544 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3545 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3546 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3547
3548 cadesc = cacert.get_subject()
3549 sedesc = secert.get_subject()
3550 cldesc = clcert.get_subject()
3551
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003552 def mixed_set_add_ca(ctx):
3553 ctx.set_client_ca_list([cadesc, sedesc])
3554 ctx.add_client_ca(clcert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003555 return [cadesc, sedesc, cldesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003556 self._check_client_ca_list(mixed_set_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003557
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003558 def test_set_after_add_client_ca(self):
3559 """
Alex Chanb7480992017-01-30 14:04:47 +00003560 A call to `Context.set_client_ca_list` after a call to
3561 `Context.add_client_ca` replaces the CA name specified by the
Hynek Schlawack35618382015-09-05 21:54:25 +02003562 former call with the names specified by the latter call.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003563 """
3564 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3565 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3566 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3567
3568 cadesc = cacert.get_subject()
3569 sedesc = secert.get_subject()
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003570
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003571 def set_replaces_add_ca(ctx):
3572 ctx.add_client_ca(clcert)
3573 ctx.set_client_ca_list([cadesc])
3574 ctx.add_client_ca(secert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003575 return [cadesc, sedesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003576 self._check_client_ca_list(set_replaces_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003577
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003578
Alex Chanb7480992017-01-30 14:04:47 +00003579class TestInfoConstants(object):
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003580 """
3581 Tests for assorted constants exposed for use in info callbacks.
3582 """
3583 def test_integers(self):
3584 """
3585 All of the info constants are integers.
3586
3587 This is a very weak test. It would be nice to have one that actually
3588 verifies that as certain info events happen, the value passed to the
3589 info callback matches up with the constant exposed by OpenSSL.SSL.
3590 """
3591 for const in [
Alex Gaynor5af32d02016-09-24 01:52:21 -04003592 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK,
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003593 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
3594 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
3595 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
Hynek Schlawack35618382015-09-05 21:54:25 +02003596 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE
3597 ]:
Alex Gaynor5af32d02016-09-24 01:52:21 -04003598 assert isinstance(const, int)
3599
3600 # These constants don't exist on OpenSSL 1.1.0
3601 for const in [
3602 SSL_ST_INIT, SSL_ST_BEFORE, SSL_ST_OK, SSL_ST_RENEGOTIATE
3603 ]:
3604 assert const is None or isinstance(const, int)
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003605
Ziga Seilnacht44611bf2009-08-31 20:49:30 +02003606
Cory Benfield1d142142016-03-30 11:51:45 +01003607class TestRequires(object):
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003608 """
3609 Tests for the decorator factory used to conditionally raise
Cory Benfield1d142142016-03-30 11:51:45 +01003610 NotImplementedError when older OpenSSLs are used.
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003611 """
3612 def test_available(self):
3613 """
3614 When the OpenSSL functionality is available the decorated functions
3615 work appropriately.
3616 """
3617 feature_guard = _make_requires(True, "Error text")
3618 results = []
3619
3620 @feature_guard
3621 def inner():
3622 results.append(True)
3623 return True
3624
Cory Benfield2333e5e2016-03-30 14:24:16 +01003625 assert inner() is True
3626 assert [True] == results
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003627
3628 def test_unavailable(self):
3629 """
3630 When the OpenSSL functionality is not available the decorated function
3631 does not execute and NotImplementedError is raised.
3632 """
3633 feature_guard = _make_requires(False, "Error text")
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003634
3635 @feature_guard
Alex Chanfb078d82017-04-20 11:16:15 +01003636 def inner(): # pragma: nocover
3637 pytest.fail("Should not be called")
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003638
Cory Benfield1d142142016-03-30 11:51:45 +01003639 with pytest.raises(NotImplementedError) as e:
3640 inner()
3641
3642 assert "Error text" in str(e.value)
Cory Benfield496652a2017-01-24 11:42:56 +00003643
3644
Alex Chanb7480992017-01-30 14:04:47 +00003645class TestOCSP(object):
Cory Benfield496652a2017-01-24 11:42:56 +00003646 """
3647 Tests for PyOpenSSL's OCSP stapling support.
3648 """
3649 sample_ocsp_data = b"this is totally ocsp data"
3650
3651 def _client_connection(self, callback, data, request_ocsp=True):
3652 """
3653 Builds a client connection suitable for using OCSP.
3654
3655 :param callback: The callback to register for OCSP.
3656 :param data: The opaque data object that will be handed to the
3657 OCSP callback.
3658 :param request_ocsp: Whether the client will actually ask for OCSP
3659 stapling. Useful for testing only.
3660 """
3661 ctx = Context(SSLv23_METHOD)
3662 ctx.set_ocsp_client_callback(callback, data)
3663 client = Connection(ctx)
3664
3665 if request_ocsp:
3666 client.request_ocsp()
3667
3668 client.set_connect_state()
3669 return client
3670
3671 def _server_connection(self, callback, data):
3672 """
3673 Builds a server connection suitable for using OCSP.
3674
3675 :param callback: The callback to register for OCSP.
3676 :param data: The opaque data object that will be handed to the
3677 OCSP callback.
3678 """
3679 ctx = Context(SSLv23_METHOD)
3680 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
3681 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
3682 ctx.set_ocsp_server_callback(callback, data)
3683 server = Connection(ctx)
3684 server.set_accept_state()
3685 return server
3686
3687 def test_callbacks_arent_called_by_default(self):
3688 """
3689 If both the client and the server have registered OCSP callbacks, but
3690 the client does not send the OCSP request, neither callback gets
3691 called.
3692 """
Alex Chanfb078d82017-04-20 11:16:15 +01003693 def ocsp_callback(*args, **kwargs): # pragma: nocover
3694 pytest.fail("Should not be called")
Cory Benfield496652a2017-01-24 11:42:56 +00003695
3696 client = self._client_connection(
3697 callback=ocsp_callback, data=None, request_ocsp=False
3698 )
3699 server = self._server_connection(callback=ocsp_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00003700 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003701
Cory Benfield496652a2017-01-24 11:42:56 +00003702 def test_client_negotiates_without_server(self):
3703 """
3704 If the client wants to do OCSP but the server does not, the handshake
3705 succeeds, and the client callback fires with an empty byte string.
3706 """
3707 called = []
3708
3709 def ocsp_callback(conn, ocsp_data, ignored):
3710 called.append(ocsp_data)
3711 return True
3712
3713 client = self._client_connection(callback=ocsp_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00003714 server = loopback_server_factory(socket=None)
3715 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003716
3717 assert len(called) == 1
3718 assert called[0] == b''
3719
3720 def test_client_receives_servers_data(self):
3721 """
3722 The data the server sends in its callback is received by the client.
3723 """
3724 calls = []
3725
3726 def server_callback(*args, **kwargs):
3727 return self.sample_ocsp_data
3728
3729 def client_callback(conn, ocsp_data, ignored):
3730 calls.append(ocsp_data)
3731 return True
3732
3733 client = self._client_connection(callback=client_callback, data=None)
3734 server = self._server_connection(callback=server_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00003735 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003736
3737 assert len(calls) == 1
3738 assert calls[0] == self.sample_ocsp_data
3739
3740 def test_callbacks_are_invoked_with_connections(self):
3741 """
3742 The first arguments to both callbacks are their respective connections.
3743 """
3744 client_calls = []
3745 server_calls = []
3746
3747 def client_callback(conn, *args, **kwargs):
3748 client_calls.append(conn)
3749 return True
3750
3751 def server_callback(conn, *args, **kwargs):
3752 server_calls.append(conn)
3753 return self.sample_ocsp_data
3754
3755 client = self._client_connection(callback=client_callback, data=None)
3756 server = self._server_connection(callback=server_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00003757 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003758
3759 assert len(client_calls) == 1
3760 assert len(server_calls) == 1
3761 assert client_calls[0] is client
3762 assert server_calls[0] is server
3763
3764 def test_opaque_data_is_passed_through(self):
3765 """
3766 Both callbacks receive an opaque, user-provided piece of data in their
3767 callbacks as the final argument.
3768 """
3769 calls = []
3770
3771 def server_callback(*args):
3772 calls.append(args)
3773 return self.sample_ocsp_data
3774
3775 def client_callback(*args):
3776 calls.append(args)
3777 return True
3778
3779 sentinel = object()
3780
3781 client = self._client_connection(
3782 callback=client_callback, data=sentinel
3783 )
3784 server = self._server_connection(
3785 callback=server_callback, data=sentinel
3786 )
Alex Chanb7480992017-01-30 14:04:47 +00003787 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003788
3789 assert len(calls) == 2
3790 assert calls[0][-1] is sentinel
3791 assert calls[1][-1] is sentinel
3792
3793 def test_server_returns_empty_string(self):
3794 """
3795 If the server returns an empty bytestring from its callback, the
3796 client callback is called with the empty bytestring.
3797 """
3798 client_calls = []
3799
3800 def server_callback(*args):
3801 return b''
3802
3803 def client_callback(conn, ocsp_data, ignored):
3804 client_calls.append(ocsp_data)
3805 return True
3806
3807 client = self._client_connection(callback=client_callback, data=None)
3808 server = self._server_connection(callback=server_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00003809 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003810
3811 assert len(client_calls) == 1
3812 assert client_calls[0] == b''
3813
3814 def test_client_returns_false_terminates_handshake(self):
3815 """
3816 If the client returns False from its callback, the handshake fails.
3817 """
3818 def server_callback(*args):
3819 return self.sample_ocsp_data
3820
3821 def client_callback(*args):
3822 return False
3823
3824 client = self._client_connection(callback=client_callback, data=None)
3825 server = self._server_connection(callback=server_callback, data=None)
3826
3827 with pytest.raises(Error):
Alex Chanb7480992017-01-30 14:04:47 +00003828 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003829
3830 def test_exceptions_in_client_bubble_up(self):
3831 """
3832 The callbacks thrown in the client callback bubble up to the caller.
3833 """
3834 class SentinelException(Exception):
3835 pass
3836
3837 def server_callback(*args):
3838 return self.sample_ocsp_data
3839
3840 def client_callback(*args):
3841 raise SentinelException()
3842
3843 client = self._client_connection(callback=client_callback, data=None)
3844 server = self._server_connection(callback=server_callback, data=None)
3845
3846 with pytest.raises(SentinelException):
Alex Chanb7480992017-01-30 14:04:47 +00003847 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003848
3849 def test_exceptions_in_server_bubble_up(self):
3850 """
3851 The callbacks thrown in the server callback bubble up to the caller.
3852 """
3853 class SentinelException(Exception):
3854 pass
3855
3856 def server_callback(*args):
3857 raise SentinelException()
3858
Alex Chanfb078d82017-04-20 11:16:15 +01003859 def client_callback(*args): # pragma: nocover
Cory Benfield496652a2017-01-24 11:42:56 +00003860 pytest.fail("Should not be called")
3861
3862 client = self._client_connection(callback=client_callback, data=None)
3863 server = self._server_connection(callback=server_callback, data=None)
3864
3865 with pytest.raises(SentinelException):
Alex Chanb7480992017-01-30 14:04:47 +00003866 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003867
3868 def test_server_must_return_bytes(self):
3869 """
3870 The server callback must return a bytestring, or a TypeError is thrown.
3871 """
3872 def server_callback(*args):
3873 return self.sample_ocsp_data.decode('ascii')
3874
Alex Chanfb078d82017-04-20 11:16:15 +01003875 def client_callback(*args): # pragma: nocover
Cory Benfield496652a2017-01-24 11:42:56 +00003876 pytest.fail("Should not be called")
3877
3878 client = self._client_connection(callback=client_callback, data=None)
3879 server = self._server_connection(callback=server_callback, data=None)
3880
3881 with pytest.raises(TypeError):
Alex Chanb7480992017-01-30 14:04:47 +00003882 handshake_in_memory(client, server)