blob: adefb1d52142617926adca6745eb6746b9dc7776 [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 Chan532b79e2017-01-24 15:14:52 +0000559 def test_use_privatekey_file_bytes(self, tmpfile):
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400560 """
561 A private key can be specified from a file by passing a ``bytes``
562 instance giving the file name to ``Context.use_privatekey_file``.
563 """
564 self._use_privatekey_file_test(
Alex Chan532b79e2017-01-24 15:14:52 +0000565 tmpfile + NON_ASCII.encode(getfilesystemencoding()),
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400566 FILETYPE_PEM,
567 )
568
Alex Chan532b79e2017-01-24 15:14:52 +0000569 def test_use_privatekey_file_unicode(self, tmpfile):
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400570 """
571 A private key can be specified from a file by passing a ``unicode``
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.decode(getfilesystemencoding()) + NON_ASCII,
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400576 FILETYPE_PEM,
577 )
578
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200579 @skip_if_py3
Alex Chan532b79e2017-01-24 15:14:52 +0000580 def test_use_privatekey_file_long(self, tmpfile):
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200581 """
Alex Chan532b79e2017-01-24 15:14:52 +0000582 On Python 2 `Context.use_privatekey_file` accepts a filetype of
583 type `long` as well as `int`.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200584 """
Alex Chan532b79e2017-01-24 15:14:52 +0000585 self._use_privatekey_file_test(tmpfile, long(FILETYPE_PEM))
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500586
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800587 def test_use_certificate_wrong_args(self):
588 """
Alex Chan532b79e2017-01-24 15:14:52 +0000589 `Context.use_certificate_wrong_args` raises `TypeError` when not passed
590 exactly one `OpenSSL.crypto.X509` instance as an argument.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800591 """
592 ctx = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000593 with pytest.raises(TypeError):
594 ctx.use_certificate("hello, world")
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800595
596 def test_use_certificate_uninitialized(self):
597 """
Alex Chan532b79e2017-01-24 15:14:52 +0000598 `Context.use_certificate` raises `OpenSSL.SSL.Error` when passed a
599 `OpenSSL.crypto.X509` instance which has not been initialized
600 (ie, which does not actually have any certificate data).
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(Error):
604 ctx.use_certificate(X509())
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800605
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800606 def test_use_certificate(self):
607 """
Alex Chan532b79e2017-01-24 15:14:52 +0000608 `Context.use_certificate` sets the certificate which will be
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800609 used to identify connections created using the context.
610 """
611 # TODO
612 # Hard to assert anything. But we could set a privatekey then ask
613 # OpenSSL if the cert and key agree using check_privatekey. Then as
614 # long as check_privatekey works right we're good...
615 ctx = Context(TLSv1_METHOD)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200616 ctx.use_certificate(
617 load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
618 )
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800619
620 def test_use_certificate_file_wrong_args(self):
621 """
Alex Chan532b79e2017-01-24 15:14:52 +0000622 `Context.use_certificate_file` raises `TypeError` if the first
623 argument is not a byte string or the second argument is not an integer.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800624 """
625 ctx = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000626 with pytest.raises(TypeError):
627 ctx.use_certificate_file(object(), FILETYPE_PEM)
628 with pytest.raises(TypeError):
629 ctx.use_certificate_file(b"somefile", object())
630 with pytest.raises(TypeError):
631 ctx.use_certificate_file(object(), FILETYPE_PEM)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800632
Alex Chan532b79e2017-01-24 15:14:52 +0000633 def test_use_certificate_file_missing(self, tmpfile):
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800634 """
Alex Chan532b79e2017-01-24 15:14:52 +0000635 `Context.use_certificate_file` raises `OpenSSL.SSL.Error` if passed
636 the name of a file which does not exist.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800637 """
638 ctx = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000639 with pytest.raises(Error):
640 ctx.use_certificate_file(tmpfile)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800641
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400642 def _use_certificate_file_test(self, certificate_file):
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800643 """
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400644 Verify that calling ``Context.use_certificate_file`` with the given
645 filename doesn't raise an exception.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800646 """
647 # TODO
648 # Hard to assert anything. But we could set a privatekey then ask
649 # OpenSSL if the cert and key agree using check_privatekey. Then as
650 # long as check_privatekey works right we're good...
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400651 with open(certificate_file, "wb") as pem_file:
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800652 pem_file.write(cleartextCertificatePEM)
653
654 ctx = Context(TLSv1_METHOD)
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400655 ctx.use_certificate_file(certificate_file)
656
Alex Chan532b79e2017-01-24 15:14:52 +0000657 def test_use_certificate_file_bytes(self, tmpfile):
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400658 """
Alex Chan532b79e2017-01-24 15:14:52 +0000659 `Context.use_certificate_file` sets the certificate (given as a
660 `bytes` filename) which will be used to identify connections created
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400661 using the context.
662 """
Alex Chan532b79e2017-01-24 15:14:52 +0000663 filename = tmpfile + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400664 self._use_certificate_file_test(filename)
665
Alex Chan532b79e2017-01-24 15:14:52 +0000666 def test_use_certificate_file_unicode(self, tmpfile):
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400667 """
Alex Chan532b79e2017-01-24 15:14:52 +0000668 `Context.use_certificate_file` sets the certificate (given as a
669 `bytes` filename) which will be used to identify connections created
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400670 using the context.
671 """
Alex Chan532b79e2017-01-24 15:14:52 +0000672 filename = tmpfile.decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400673 self._use_certificate_file_test(filename)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800674
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200675 @skip_if_py3
Alex Chan532b79e2017-01-24 15:14:52 +0000676 def test_use_certificate_file_long(self, tmpfile):
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200677 """
Alex Chan532b79e2017-01-24 15:14:52 +0000678 On Python 2 `Context.use_certificate_file` accepts a
679 filetype of type `long` as well as `int`.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200680 """
Alex Chan532b79e2017-01-24 15:14:52 +0000681 pem_filename = tmpfile
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200682 with open(pem_filename, "wb") as pem_file:
683 pem_file.write(cleartextCertificatePEM)
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500684
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200685 ctx = Context(TLSv1_METHOD)
686 ctx.use_certificate_file(pem_filename, long(FILETYPE_PEM))
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500687
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500688 def test_check_privatekey_valid(self):
689 """
Alex Chan532b79e2017-01-24 15:14:52 +0000690 `Context.check_privatekey` returns `None` if the `Context` instance
691 has been configured to use a matched key and certificate pair.
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500692 """
693 key = load_privatekey(FILETYPE_PEM, client_key_pem)
694 cert = load_certificate(FILETYPE_PEM, client_cert_pem)
695 context = Context(TLSv1_METHOD)
696 context.use_privatekey(key)
697 context.use_certificate(cert)
Alex Chan532b79e2017-01-24 15:14:52 +0000698 assert None is context.check_privatekey()
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500699
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500700 def test_check_privatekey_invalid(self):
701 """
Alex Chan532b79e2017-01-24 15:14:52 +0000702 `Context.check_privatekey` raises `Error` if the `Context` instance
703 has been configured to use a key and certificate pair which don't
704 relate to each other.
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500705 """
706 key = load_privatekey(FILETYPE_PEM, client_key_pem)
707 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
708 context = Context(TLSv1_METHOD)
709 context.use_privatekey(key)
710 context.use_certificate(cert)
Alex Chan532b79e2017-01-24 15:14:52 +0000711 with pytest.raises(Error):
712 context.check_privatekey()
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400713
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400714 def test_app_data(self):
715 """
Alex Chan532b79e2017-01-24 15:14:52 +0000716 `Context.set_app_data` stores an object for later retrieval
717 using `Context.get_app_data`.
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400718 """
719 app_data = object()
720 context = Context(TLSv1_METHOD)
721 context.set_app_data(app_data)
Alex Chan532b79e2017-01-24 15:14:52 +0000722 assert context.get_app_data() is app_data
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400723
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400724 def test_set_options_wrong_args(self):
725 """
Alex Chan532b79e2017-01-24 15:14:52 +0000726 `Context.set_options` raises `TypeError` if called with
727 a non-`int` argument.
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400728 """
729 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000730 with pytest.raises(TypeError):
731 context.set_options(None)
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400732
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500733 def test_set_options(self):
734 """
Alex Chan532b79e2017-01-24 15:14:52 +0000735 `Context.set_options` returns the new options value.
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500736 """
737 context = Context(TLSv1_METHOD)
738 options = context.set_options(OP_NO_SSLv2)
Alex Gaynor2310f8b2016-09-10 14:39:32 -0400739 assert options & OP_NO_SSLv2 == OP_NO_SSLv2
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500740
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200741 @skip_if_py3
742 def test_set_options_long(self):
743 """
Alex Chan532b79e2017-01-24 15:14:52 +0000744 On Python 2 `Context.set_options` accepts values of type
745 `long` as well as `int`.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200746 """
747 context = Context(TLSv1_METHOD)
748 options = context.set_options(long(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
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300751 def test_set_mode_wrong_args(self):
752 """
Alex Chan532b79e2017-01-24 15:14:52 +0000753 `Context.set_mode` raises `TypeError` if called with
754 a non-`int` argument.
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300755 """
756 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000757 with pytest.raises(TypeError):
758 context.set_mode(None)
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300759
Alex Gaynord3b5d9b2016-07-31 10:54:24 -0400760 def test_set_mode(self):
761 """
Alex Chan532b79e2017-01-24 15:14:52 +0000762 `Context.set_mode` accepts a mode bitvector and returns the
Alex Gaynord3b5d9b2016-07-31 10:54:24 -0400763 newly set mode.
764 """
765 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000766 assert MODE_RELEASE_BUFFERS & context.set_mode(MODE_RELEASE_BUFFERS)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500767
Alex Gaynord3b5d9b2016-07-31 10:54:24 -0400768 @skip_if_py3
769 def test_set_mode_long(self):
770 """
Alex Chan532b79e2017-01-24 15:14:52 +0000771 On Python 2 `Context.set_mode` accepts values of type `long` as well
772 as `int`.
Alex Gaynord3b5d9b2016-07-31 10:54:24 -0400773 """
774 context = Context(TLSv1_METHOD)
775 mode = context.set_mode(long(MODE_RELEASE_BUFFERS))
Alex Chan532b79e2017-01-24 15:14:52 +0000776 assert MODE_RELEASE_BUFFERS & mode
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400777
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400778 def test_set_timeout_wrong_args(self):
779 """
Alex Chan532b79e2017-01-24 15:14:52 +0000780 `Context.set_timeout` raises `TypeError` if called with
781 a non-`int` argument.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400782 """
783 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000784 with pytest.raises(TypeError):
785 context.set_timeout(None)
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400786
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400787 def test_timeout(self):
788 """
Alex Chan532b79e2017-01-24 15:14:52 +0000789 `Context.set_timeout` sets the session timeout for all connections
790 created using the context object. `Context.get_timeout` retrieves
791 this value.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400792 """
793 context = Context(TLSv1_METHOD)
794 context.set_timeout(1234)
Alex Chan532b79e2017-01-24 15:14:52 +0000795 assert context.get_timeout() == 1234
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400796
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200797 @skip_if_py3
798 def test_timeout_long(self):
799 """
Alex Chan532b79e2017-01-24 15:14:52 +0000800 On Python 2 `Context.set_timeout` accepts values of type `long` as
801 well as int.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200802 """
803 context = Context(TLSv1_METHOD)
804 context.set_timeout(long(1234))
Alex Chan532b79e2017-01-24 15:14:52 +0000805 assert context.get_timeout() == 1234
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500806
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400807 def test_set_verify_depth_wrong_args(self):
808 """
Alex Chan532b79e2017-01-24 15:14:52 +0000809 `Context.set_verify_depth` raises `TypeError` if called with a
810 non-`int` argument.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400811 """
812 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000813 with pytest.raises(TypeError):
814 context.set_verify_depth(None)
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400815
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400816 def test_verify_depth(self):
817 """
Alex Chan532b79e2017-01-24 15:14:52 +0000818 `Context.set_verify_depth` sets the number of certificates in
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200819 a chain to follow before giving up. The value can be retrieved with
Alex Chan532b79e2017-01-24 15:14:52 +0000820 `Context.get_verify_depth`.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400821 """
822 context = Context(TLSv1_METHOD)
823 context.set_verify_depth(11)
Alex Chan532b79e2017-01-24 15:14:52 +0000824 assert context.get_verify_depth() == 11
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400825
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200826 @skip_if_py3
827 def test_verify_depth_long(self):
828 """
Alex Chan532b79e2017-01-24 15:14:52 +0000829 On Python 2 `Context.set_verify_depth` accepts values of type `long`
830 as well as int.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200831 """
832 context = Context(TLSv1_METHOD)
833 context.set_verify_depth(long(11))
Alex Chan532b79e2017-01-24 15:14:52 +0000834 assert context.get_verify_depth() == 11
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500835
Alex Chan532b79e2017-01-24 15:14:52 +0000836 def _write_encrypted_pem(self, passphrase, tmpfile):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400837 """
838 Write a new private key out to a new file, encrypted using the given
839 passphrase. Return the path to the new file.
840 """
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400841 key = PKey()
842 key.generate_key(TYPE_RSA, 128)
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400843 pem = dump_privatekey(FILETYPE_PEM, key, "blowfish", passphrase)
Alex Chan532b79e2017-01-24 15:14:52 +0000844 with open(tmpfile, 'w') as fObj:
845 fObj.write(pem.decode('ascii'))
846 return tmpfile
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400847
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400848 def test_set_passwd_cb_wrong_args(self):
849 """
Alex Chan532b79e2017-01-24 15:14:52 +0000850 `Context.set_passwd_cb` raises `TypeError` if called with a
851 non-callable first argument.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400852 """
853 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000854 with pytest.raises(TypeError):
855 context.set_passwd_cb(None)
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400856
Alex Chan532b79e2017-01-24 15:14:52 +0000857 def test_set_passwd_cb(self, tmpfile):
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400858 """
Alex Chan532b79e2017-01-24 15:14:52 +0000859 `Context.set_passwd_cb` accepts a callable which will be invoked when
860 a private key is loaded from an encrypted PEM.
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400861 """
Alex Gaynore7f51982016-09-11 11:48:14 -0400862 passphrase = b"foobar"
Alex Chan532b79e2017-01-24 15:14:52 +0000863 pemFile = self._write_encrypted_pem(passphrase, tmpfile)
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400864 calledWith = []
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200865
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400866 def passphraseCallback(maxlen, verify, extra):
867 calledWith.append((maxlen, verify, extra))
868 return passphrase
869 context = Context(TLSv1_METHOD)
870 context.set_passwd_cb(passphraseCallback)
871 context.use_privatekey_file(pemFile)
Alex Chan532b79e2017-01-24 15:14:52 +0000872 assert len(calledWith) == 1
873 assert isinstance(calledWith[0][0], int)
874 assert isinstance(calledWith[0][1], int)
875 assert calledWith[0][2] is None
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400876
Alex Chan532b79e2017-01-24 15:14:52 +0000877 def test_passwd_callback_exception(self, tmpfile):
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400878 """
Alex Chan532b79e2017-01-24 15:14:52 +0000879 `Context.use_privatekey_file` propagates any exception raised
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200880 by the passphrase callback.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400881 """
Alex Chan532b79e2017-01-24 15:14:52 +0000882 pemFile = self._write_encrypted_pem(b"monkeys are nice", tmpfile)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200883
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400884 def passphraseCallback(maxlen, verify, extra):
885 raise RuntimeError("Sorry, I am a fail.")
886
887 context = Context(TLSv1_METHOD)
888 context.set_passwd_cb(passphraseCallback)
Alex Chan532b79e2017-01-24 15:14:52 +0000889 with pytest.raises(RuntimeError):
890 context.use_privatekey_file(pemFile)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400891
Alex Chan532b79e2017-01-24 15:14:52 +0000892 def test_passwd_callback_false(self, tmpfile):
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400893 """
Alex Chan532b79e2017-01-24 15:14:52 +0000894 `Context.use_privatekey_file` raises `OpenSSL.SSL.Error` if the
895 passphrase callback returns a false value.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400896 """
Alex Chan532b79e2017-01-24 15:14:52 +0000897 pemFile = self._write_encrypted_pem(b"monkeys are nice", tmpfile)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200898
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400899 def passphraseCallback(maxlen, verify, extra):
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500900 return b""
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400901
902 context = Context(TLSv1_METHOD)
903 context.set_passwd_cb(passphraseCallback)
Alex Chan532b79e2017-01-24 15:14:52 +0000904 with pytest.raises(Error):
905 context.use_privatekey_file(pemFile)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400906
Alex Chan532b79e2017-01-24 15:14:52 +0000907 def test_passwd_callback_non_string(self, tmpfile):
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400908 """
Alex Chan532b79e2017-01-24 15:14:52 +0000909 `Context.use_privatekey_file` raises `OpenSSL.SSL.Error` if the
910 passphrase callback returns a true non-string value.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400911 """
Alex Chan532b79e2017-01-24 15:14:52 +0000912 pemFile = self._write_encrypted_pem(b"monkeys are nice", tmpfile)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200913
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400914 def passphraseCallback(maxlen, verify, extra):
915 return 10
916
917 context = Context(TLSv1_METHOD)
918 context.set_passwd_cb(passphraseCallback)
Alex Chan532b79e2017-01-24 15:14:52 +0000919 # TODO: Surely this is the wrong error?
920 with pytest.raises(ValueError):
921 context.use_privatekey_file(pemFile)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400922
Alex Chan532b79e2017-01-24 15:14:52 +0000923 def test_passwd_callback_too_long(self, tmpfile):
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400924 """
925 If the passphrase returned by the passphrase callback returns a string
926 longer than the indicated maximum length, it is truncated.
927 """
928 # A priori knowledge!
Alex Gaynore7f51982016-09-11 11:48:14 -0400929 passphrase = b"x" * 1024
Alex Chan532b79e2017-01-24 15:14:52 +0000930 pemFile = self._write_encrypted_pem(passphrase, tmpfile)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200931
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400932 def passphraseCallback(maxlen, verify, extra):
933 assert maxlen == 1024
Alex Gaynore7f51982016-09-11 11:48:14 -0400934 return passphrase + b"y"
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400935
936 context = Context(TLSv1_METHOD)
937 context.set_passwd_cb(passphraseCallback)
938 # This shall succeed because the truncated result is the correct
939 # passphrase.
940 context.use_privatekey_file(pemFile)
941
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400942 def test_set_info_callback(self):
943 """
Alex Chan532b79e2017-01-24 15:14:52 +0000944 `Context.set_info_callback` accepts a callable which will be
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200945 invoked when certain information about an SSL connection is available.
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400946 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500947 (server, client) = socket_pair()
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400948
949 clientSSL = Connection(Context(TLSv1_METHOD), client)
950 clientSSL.set_connect_state()
951
952 called = []
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200953
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400954 def info(conn, where, ret):
955 called.append((conn, where, ret))
956 context = Context(TLSv1_METHOD)
957 context.set_info_callback(info)
958 context.use_certificate(
959 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
960 context.use_privatekey(
961 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
962
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400963 serverSSL = Connection(context, server)
964 serverSSL.set_accept_state()
965
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -0500966 handshake(clientSSL, serverSSL)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400967
Jean-Paul Calderone3835e522014-02-02 11:12:30 -0500968 # The callback must always be called with a Connection instance as the
969 # first argument. It would probably be better to split this into
970 # separate tests for client and server side info callbacks so we could
971 # assert it is called with the right Connection instance. It would
972 # also be good to assert *something* about `where` and `ret`.
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -0500973 notConnections = [
974 conn for (conn, where, ret) in called
975 if not isinstance(conn, Connection)]
Alex Chan532b79e2017-01-24 15:14:52 +0000976 assert [] == notConnections, (
977 "Some info callback arguments were not Connection instances.")
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400978
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400979 def _load_verify_locations_test(self, *args):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400980 """
981 Create a client context which will verify the peer certificate and call
Alex Chan532b79e2017-01-24 15:14:52 +0000982 its `load_verify_locations` method with the given arguments.
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -0400983 Then connect it to a server and ensure that the handshake succeeds.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400984 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500985 (server, client) = socket_pair()
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400986
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400987 clientContext = Context(TLSv1_METHOD)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400988 clientContext.load_verify_locations(*args)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400989 # Require that the server certificate verify properly or the
990 # connection will fail.
991 clientContext.set_verify(
992 VERIFY_PEER,
993 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
994
995 clientSSL = Connection(clientContext, client)
996 clientSSL.set_connect_state()
997
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400998 serverContext = Context(TLSv1_METHOD)
999 serverContext.use_certificate(
1000 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1001 serverContext.use_privatekey(
1002 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1003
1004 serverSSL = Connection(serverContext, server)
1005 serverSSL.set_accept_state()
1006
Jean-Paul Calderonef8742032010-09-25 00:00:32 -04001007 # Without load_verify_locations above, the handshake
1008 # will fail:
1009 # Error: [('SSL routines', 'SSL3_GET_SERVER_CERTIFICATE',
1010 # 'certificate verify failed')]
1011 handshake(clientSSL, serverSSL)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001012
1013 cert = clientSSL.get_peer_certificate()
Alex Chan532b79e2017-01-24 15:14:52 +00001014 assert cert.get_subject().CN == 'Testing Root CA'
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -04001015
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001016 def _load_verify_cafile(self, cafile):
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001017 """
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001018 Verify that if path to a file containing a certificate is passed to
Alex Chan532b79e2017-01-24 15:14:52 +00001019 `Context.load_verify_locations` for the ``cafile`` parameter, that
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001020 certificate is used as a trust root for the purposes of verifying
Alex Chan532b79e2017-01-24 15:14:52 +00001021 connections created using that `Context`.
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001022 """
Alex Chan532b79e2017-01-24 15:14:52 +00001023 with open(cafile, 'w') as fObj:
1024 fObj.write(cleartextCertificatePEM.decode('ascii'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001025
1026 self._load_verify_locations_test(cafile)
1027
Alex Chan532b79e2017-01-24 15:14:52 +00001028 def test_load_verify_bytes_cafile(self, tmpfile):
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001029 """
Alex Chan532b79e2017-01-24 15:14:52 +00001030 `Context.load_verify_locations` accepts a file name as a `bytes`
1031 instance and uses the certificates within for verification purposes.
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001032 """
Alex Chan532b79e2017-01-24 15:14:52 +00001033 cafile = tmpfile + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001034 self._load_verify_cafile(cafile)
1035
Alex Chan532b79e2017-01-24 15:14:52 +00001036 def test_load_verify_unicode_cafile(self, tmpfile):
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001037 """
Alex Chan532b79e2017-01-24 15:14:52 +00001038 `Context.load_verify_locations` accepts a file name as a `unicode`
1039 instance and uses the certificates within for verification purposes.
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001040 """
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001041 self._load_verify_cafile(
Alex Chan532b79e2017-01-24 15:14:52 +00001042 tmpfile.decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001043 )
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001044
Alex Chan532b79e2017-01-24 15:14:52 +00001045 def test_load_verify_invalid_file(self, tmpfile):
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -04001046 """
Alex Chan532b79e2017-01-24 15:14:52 +00001047 `Context.load_verify_locations` raises `Error` when passed a
1048 non-existent cafile.
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -04001049 """
1050 clientContext = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001051 with pytest.raises(Error):
1052 clientContext.load_verify_locations(tmpfile)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001053
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001054 def _load_verify_directory_locations_capath(self, capath):
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001055 """
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001056 Verify that if path to a directory containing certificate files is
1057 passed to ``Context.load_verify_locations`` for the ``capath``
1058 parameter, those certificates are used as trust roots for the purposes
1059 of verifying connections created using that ``Context``.
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001060 """
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001061 makedirs(capath)
Jean-Paul Calderone24dfb332011-05-04 18:10:26 -04001062 # Hash values computed manually with c_rehash to avoid depending on
1063 # c_rehash in the test suite. One is from OpenSSL 0.9.8, the other
1064 # from OpenSSL 1.0.0.
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001065 for name in [b'c7adac82.0', b'c3705638.0']:
Jean-Paul Calderone05826732015-04-12 11:38:49 -04001066 cafile = join_bytes_or_unicode(capath, name)
1067 with open(cafile, 'w') as fObj:
1068 fObj.write(cleartextCertificatePEM.decode('ascii'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001069
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001070 self._load_verify_locations_test(None, capath)
1071
Alex Chan532b79e2017-01-24 15:14:52 +00001072 def test_load_verify_directory_bytes_capath(self, tmpfile):
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001073 """
Alex Chan532b79e2017-01-24 15:14:52 +00001074 `Context.load_verify_locations` accepts a directory name as a `bytes`
1075 instance and uses the certificates within for verification purposes.
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001076 """
1077 self._load_verify_directory_locations_capath(
Alex Chan532b79e2017-01-24 15:14:52 +00001078 tmpfile + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001079 )
1080
Alex Chan532b79e2017-01-24 15:14:52 +00001081 def test_load_verify_directory_unicode_capath(self, tmpfile):
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001082 """
Alex Chan532b79e2017-01-24 15:14:52 +00001083 `Context.load_verify_locations` accepts a directory name as a `unicode`
1084 instance and uses the certificates within for verification purposes.
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001085 """
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001086 self._load_verify_directory_locations_capath(
Alex Chan532b79e2017-01-24 15:14:52 +00001087 tmpfile.decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001088 )
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001089
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001090 def test_load_verify_locations_wrong_args(self):
1091 """
Alex Chan532b79e2017-01-24 15:14:52 +00001092 `Context.load_verify_locations` raises `TypeError` if with non-`str`
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001093 arguments.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001094 """
1095 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001096 with pytest.raises(TypeError):
1097 context.load_verify_locations(object())
1098 with pytest.raises(TypeError):
1099 context.load_verify_locations(object(), object())
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001100
Hynek Schlawack734d3022015-09-05 19:19:32 +02001101 @pytest.mark.skipif(
1102 platform == "win32",
1103 reason="set_default_verify_paths appears not to work on Windows. "
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -04001104 "See LP#404343 and LP#404344."
Hynek Schlawack734d3022015-09-05 19:19:32 +02001105 )
1106 def test_set_default_verify_paths(self):
1107 """
Alex Chan532b79e2017-01-24 15:14:52 +00001108 `Context.set_default_verify_paths` causes the platform-specific CA
1109 certificate locations to be used for verification purposes.
Hynek Schlawack734d3022015-09-05 19:19:32 +02001110 """
1111 # Testing this requires a server with a certificate signed by one
1112 # of the CAs in the platform CA location. Getting one of those
1113 # costs money. Fortunately (or unfortunately, depending on your
1114 # perspective), it's easy to think of a public server on the
1115 # internet which has such a certificate. Connecting to the network
1116 # in a unit test is bad, but it's the only way I can think of to
1117 # really test this. -exarkun
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001118
Hynek Schlawack734d3022015-09-05 19:19:32 +02001119 # Arg, verisign.com doesn't speak anything newer than TLS 1.0
Hynek Schlawackbf887932015-10-21 17:13:47 +02001120 context = Context(SSLv23_METHOD)
Hynek Schlawack734d3022015-09-05 19:19:32 +02001121 context.set_default_verify_paths()
1122 context.set_verify(
1123 VERIFY_PEER,
1124 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001125
Hynek Schlawack734d3022015-09-05 19:19:32 +02001126 client = socket()
Hynek Schlawackbf887932015-10-21 17:13:47 +02001127 client.connect(("encrypted.google.com", 443))
Hynek Schlawack734d3022015-09-05 19:19:32 +02001128 clientSSL = Connection(context, client)
1129 clientSSL.set_connect_state()
1130 clientSSL.do_handshake()
1131 clientSSL.send(b"GET / HTTP/1.0\r\n\r\n")
Alex Chan532b79e2017-01-24 15:14:52 +00001132 assert clientSSL.recv(1024)
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05001133
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001134 def test_add_extra_chain_cert_invalid_cert(self):
1135 """
Alex Chan532b79e2017-01-24 15:14:52 +00001136 `Context.add_extra_chain_cert` raises `TypeError` if called with an
1137 object which is not an instance of `X509`.
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001138 """
1139 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001140 with pytest.raises(TypeError):
1141 context.add_extra_chain_cert(object())
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001142
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001143 def _handshake_test(self, serverContext, clientContext):
1144 """
1145 Verify that a client and server created with the given contexts can
1146 successfully handshake and communicate.
1147 """
1148 serverSocket, clientSocket = socket_pair()
1149
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001150 server = Connection(serverContext, serverSocket)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001151 server.set_accept_state()
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001152
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001153 client = Connection(clientContext, clientSocket)
1154 client.set_connect_state()
1155
1156 # Make them talk to each other.
Alex Chan532b79e2017-01-24 15:14:52 +00001157 # interact_in_memory(client, server)
1158 for _ in range(3):
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001159 for s in [client, server]:
1160 try:
1161 s.do_handshake()
1162 except WantReadError:
1163 pass
1164
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001165 def test_set_verify_callback_connection_argument(self):
1166 """
1167 The first argument passed to the verify callback is the
Alex Chan532b79e2017-01-24 15:14:52 +00001168 `Connection` instance for which verification is taking place.
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001169 """
1170 serverContext = Context(TLSv1_METHOD)
1171 serverContext.use_privatekey(
1172 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1173 serverContext.use_certificate(
1174 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1175 serverConnection = Connection(serverContext, None)
1176
1177 class VerifyCallback(object):
1178 def callback(self, connection, *args):
1179 self.connection = connection
1180 return 1
1181
1182 verify = VerifyCallback()
1183 clientContext = Context(TLSv1_METHOD)
1184 clientContext.set_verify(VERIFY_PEER, verify.callback)
1185 clientConnection = Connection(clientContext, None)
1186 clientConnection.set_connect_state()
1187
Alex Chan532b79e2017-01-24 15:14:52 +00001188 handshake_in_memory(clientConnection, serverConnection)
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001189
Alex Chan532b79e2017-01-24 15:14:52 +00001190 assert verify.connection is clientConnection
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001191
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001192 def test_set_verify_callback_exception(self):
1193 """
Alex Chan532b79e2017-01-24 15:14:52 +00001194 If the verify callback passed to `Context.set_verify` raises an
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001195 exception, verification fails and the exception is propagated to the
Alex Chan532b79e2017-01-24 15:14:52 +00001196 caller of `Connection.do_handshake`.
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001197 """
1198 serverContext = Context(TLSv1_METHOD)
1199 serverContext.use_privatekey(
1200 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1201 serverContext.use_certificate(
1202 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1203
1204 clientContext = Context(TLSv1_METHOD)
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001205
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001206 def verify_callback(*args):
1207 raise Exception("silly verify failure")
1208 clientContext.set_verify(VERIFY_PEER, verify_callback)
1209
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01001210 with pytest.raises(Exception) as exc:
1211 self._handshake_test(serverContext, clientContext)
1212
Alex Chan532b79e2017-01-24 15:14:52 +00001213 assert "silly verify failure" == str(exc.value)
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001214
Alex Chan532b79e2017-01-24 15:14:52 +00001215 def test_add_extra_chain_cert(self, tmpdir):
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001216 """
Alex Chan532b79e2017-01-24 15:14:52 +00001217 `Context.add_extra_chain_cert` accepts an `X509`
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001218 instance to add to the certificate chain.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001219
Alex Chan532b79e2017-01-24 15:14:52 +00001220 See `_create_certificate_chain` for the details of the
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001221 certificate chain tested.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001222
1223 The chain is tested by starting a server with scert and connecting
1224 to it with a client which trusts cacert and requires verification to
1225 succeed.
1226 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001227 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001228 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1229
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001230 # Dump the CA certificate to a file because that's the only way to load
1231 # it as a trusted CA in the client context.
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001232 for cert, name in [(cacert, 'ca.pem'),
1233 (icert, 'i.pem'),
1234 (scert, 's.pem')]:
Alex Chan532b79e2017-01-24 15:14:52 +00001235 with tmpdir.join(name).open('w') as f:
Hynek Schlawacke90680f2015-04-16 15:09:27 -04001236 f.write(dump_certificate(FILETYPE_PEM, cert).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001237
Hynek Schlawack1902c012015-04-16 15:06:41 -04001238 for key, name in [(cakey, 'ca.key'),
1239 (ikey, 'i.key'),
1240 (skey, 's.key')]:
Alex Chan532b79e2017-01-24 15:14:52 +00001241 with tmpdir.join(name).open('w') as f:
Hynek Schlawacke90680f2015-04-16 15:09:27 -04001242 f.write(dump_privatekey(FILETYPE_PEM, key).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001243
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001244 # Create the server context
1245 serverContext = Context(TLSv1_METHOD)
1246 serverContext.use_privatekey(skey)
1247 serverContext.use_certificate(scert)
Jean-Paul Calderone16cf03d2010-09-08 18:53:39 -04001248 # The client already has cacert, we only need to give them icert.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001249 serverContext.add_extra_chain_cert(icert)
1250
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001251 # Create the client
1252 clientContext = Context(TLSv1_METHOD)
1253 clientContext.set_verify(
1254 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Alex Chan532b79e2017-01-24 15:14:52 +00001255 clientContext.load_verify_locations(str(tmpdir.join("ca.pem")))
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001256
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001257 # Try it out.
1258 self._handshake_test(serverContext, clientContext)
1259
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001260 def _use_certificate_chain_file_test(self, certdir):
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001261 """
Alex Chan532b79e2017-01-24 15:14:52 +00001262 Verify that `Context.use_certificate_chain_file` reads a
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001263 certificate chain from a specified file.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001264
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001265 The chain is tested by starting a server with scert and connecting to
1266 it with a client which trusts cacert and requires verification to
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001267 succeed.
1268 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001269 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001270 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1271
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001272 makedirs(certdir)
1273
Jean-Paul Calderone05826732015-04-12 11:38:49 -04001274 chainFile = join_bytes_or_unicode(certdir, "chain.pem")
1275 caFile = join_bytes_or_unicode(certdir, "ca.pem")
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001276
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001277 # Write out the chain file.
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001278 with open(chainFile, 'wb') as fObj:
1279 # Most specific to least general.
1280 fObj.write(dump_certificate(FILETYPE_PEM, scert))
1281 fObj.write(dump_certificate(FILETYPE_PEM, icert))
1282 fObj.write(dump_certificate(FILETYPE_PEM, cacert))
1283
1284 with open(caFile, 'w') as fObj:
1285 fObj.write(dump_certificate(FILETYPE_PEM, cacert).decode('ascii'))
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001286
1287 serverContext = Context(TLSv1_METHOD)
1288 serverContext.use_certificate_chain_file(chainFile)
1289 serverContext.use_privatekey(skey)
1290
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001291 clientContext = Context(TLSv1_METHOD)
1292 clientContext.set_verify(
1293 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001294 clientContext.load_verify_locations(caFile)
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001295
1296 self._handshake_test(serverContext, clientContext)
1297
Alex Chan532b79e2017-01-24 15:14:52 +00001298 def test_use_certificate_chain_file_bytes(self, tmpfile):
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001299 """
1300 ``Context.use_certificate_chain_file`` accepts the name of a file (as
1301 an instance of ``bytes``) to specify additional certificates to use to
1302 construct and verify a trust chain.
1303 """
1304 self._use_certificate_chain_file_test(
Alex Chan532b79e2017-01-24 15:14:52 +00001305 tmpfile + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001306 )
1307
Alex Chan532b79e2017-01-24 15:14:52 +00001308 def test_use_certificate_chain_file_unicode(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 ``unicode``) to specify additional certificates to use
1312 to construct and verify a trust chain.
1313 """
1314 self._use_certificate_chain_file_test(
Alex Chan532b79e2017-01-24 15:14:52 +00001315 tmpfile.decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001316 )
1317
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001318 def test_use_certificate_chain_file_wrong_args(self):
1319 """
Alex Chan532b79e2017-01-24 15:14:52 +00001320 `Context.use_certificate_chain_file` raises `TypeError` if passed a
1321 non-byte string single argument.
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001322 """
1323 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001324 with pytest.raises(TypeError):
1325 context.use_certificate_chain_file(object())
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001326
Alex Chan532b79e2017-01-24 15:14:52 +00001327 def test_use_certificate_chain_file_missing_file(self, tmpfile):
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001328 """
Alex Chan532b79e2017-01-24 15:14:52 +00001329 `Context.use_certificate_chain_file` raises `OpenSSL.SSL.Error` when
1330 passed a bad chain file name (for example, the name of a file which
1331 does not exist).
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001332 """
1333 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001334 with pytest.raises(Error):
1335 context.use_certificate_chain_file(tmpfile)
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001336
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001337 def test_set_verify_mode(self):
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001338 """
Alex Chan532b79e2017-01-24 15:14:52 +00001339 `Context.get_verify_mode` returns the verify mode flags previously
1340 passed to `Context.set_verify`.
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001341 """
1342 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001343 assert context.get_verify_mode() == 0
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001344 context.set_verify(
1345 VERIFY_PEER | VERIFY_CLIENT_ONCE, lambda *args: None)
Alex Chan532b79e2017-01-24 15:14:52 +00001346 assert context.get_verify_mode() == (VERIFY_PEER | VERIFY_CLIENT_ONCE)
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001347
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001348 @skip_if_py3
1349 def test_set_verify_mode_long(self):
1350 """
Alex Chan532b79e2017-01-24 15:14:52 +00001351 On Python 2 `Context.set_verify_mode` accepts values of type `long`
1352 as well as `int`.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001353 """
1354 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001355 assert context.get_verify_mode() == 0
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001356 context.set_verify(
Hynek Schlawackb4ceed32015-09-05 20:55:19 +02001357 long(VERIFY_PEER | VERIFY_CLIENT_ONCE), lambda *args: None
1358 ) # pragma: nocover
Alex Chan532b79e2017-01-24 15:14:52 +00001359 assert context.get_verify_mode() == (VERIFY_PEER | VERIFY_CLIENT_ONCE)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001360
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001361 def test_load_tmp_dh_wrong_args(self):
1362 """
Alex Chan532b79e2017-01-24 15:14:52 +00001363 `Context.load_tmp_dh` raises `TypeError` if called with a
1364 non-`str` argument.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001365 """
1366 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001367 with pytest.raises(TypeError):
1368 context.load_tmp_dh(object())
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001369
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001370 def test_load_tmp_dh_missing_file(self):
1371 """
Alex Chan532b79e2017-01-24 15:14:52 +00001372 `Context.load_tmp_dh` raises `OpenSSL.SSL.Error` if the
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001373 specified file does not exist.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001374 """
1375 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001376 with pytest.raises(Error):
1377 context.load_tmp_dh(b"hello")
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001378
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001379 def _load_tmp_dh_test(self, dhfilename):
Jean-Paul Calderone4e0c43f2015-04-13 10:15:17 -04001380 """
1381 Verify that calling ``Context.load_tmp_dh`` with the given filename
1382 does not raise an exception.
1383 """
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001384 context = Context(TLSv1_METHOD)
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001385 with open(dhfilename, "w") as dhfile:
1386 dhfile.write(dhparam)
1387
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001388 context.load_tmp_dh(dhfilename)
1389 # XXX What should I assert here? -exarkun
1390
Alex Chan532b79e2017-01-24 15:14:52 +00001391 def test_load_tmp_dh_bytes(self, tmpfile):
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001392 """
Alex Chan532b79e2017-01-24 15:14:52 +00001393 `Context.load_tmp_dh` loads Diffie-Hellman parameters from the
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001394 specified file (given as ``bytes``).
1395 """
1396 self._load_tmp_dh_test(
Alex Chan532b79e2017-01-24 15:14:52 +00001397 tmpfile + NON_ASCII.encode(getfilesystemencoding()),
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001398 )
1399
Alex Chan532b79e2017-01-24 15:14:52 +00001400 def test_load_tmp_dh_unicode(self, tmpfile):
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001401 """
Alex Chan532b79e2017-01-24 15:14:52 +00001402 `Context.load_tmp_dh` loads Diffie-Hellman parameters from the
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001403 specified file (given as ``unicode``).
1404 """
1405 self._load_tmp_dh_test(
Alex Chan532b79e2017-01-24 15:14:52 +00001406 tmpfile.decode(getfilesystemencoding()) + NON_ASCII,
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001407 )
1408
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001409 def test_set_tmp_ecdh(self):
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001410 """
Alex Chan532b79e2017-01-24 15:14:52 +00001411 `Context.set_tmp_ecdh` sets the elliptic curve for Diffie-Hellman to
1412 the specified curve.
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001413 """
1414 context = Context(TLSv1_METHOD)
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001415 for curve in get_elliptic_curves():
Hynek Schlawacka07fa8c2015-10-17 10:15:28 +02001416 if curve.name.startswith(u"Oakley-"):
Hynek Schlawack7408aff2015-10-17 09:51:16 +02001417 # Setting Oakley-EC2N-4 and Oakley-EC2N-3 adds
1418 # ('bignum routines', 'BN_mod_inverse', 'no inverse') to the
1419 # error queue on OpenSSL 1.0.2.
1420 continue
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001421 # The only easily "assertable" thing is that it does not raise an
1422 # exception.
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001423 context.set_tmp_ecdh(curve)
Alex Gaynor12dc0842014-01-17 12:51:31 -06001424
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001425 def test_set_session_cache_mode_wrong_args(self):
1426 """
Alex Chan532b79e2017-01-24 15:14:52 +00001427 `Context.set_session_cache_mode` raises `TypeError` if called with
1428 a non-integer argument.
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001429 called with other than one integer argument.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001430 """
1431 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001432 with pytest.raises(TypeError):
1433 context.set_session_cache_mode(object())
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001434
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001435 def test_session_cache_mode(self):
1436 """
Alex Chan532b79e2017-01-24 15:14:52 +00001437 `Context.set_session_cache_mode` specifies how sessions are cached.
1438 The setting can be retrieved via `Context.get_session_cache_mode`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001439 """
1440 context = Context(TLSv1_METHOD)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001441 context.set_session_cache_mode(SESS_CACHE_OFF)
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001442 off = context.set_session_cache_mode(SESS_CACHE_BOTH)
Alex Chan532b79e2017-01-24 15:14:52 +00001443 assert SESS_CACHE_OFF == off
1444 assert SESS_CACHE_BOTH == context.get_session_cache_mode()
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001445
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001446 @skip_if_py3
1447 def test_session_cache_mode_long(self):
1448 """
Alex Chan532b79e2017-01-24 15:14:52 +00001449 On Python 2 `Context.set_session_cache_mode` accepts values
1450 of type `long` as well as `int`.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001451 """
1452 context = Context(TLSv1_METHOD)
1453 context.set_session_cache_mode(long(SESS_CACHE_BOTH))
Alex Chan532b79e2017-01-24 15:14:52 +00001454 assert SESS_CACHE_BOTH == context.get_session_cache_mode()
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001455
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001456 def test_get_cert_store(self):
1457 """
Alex Chan532b79e2017-01-24 15:14:52 +00001458 `Context.get_cert_store` returns a `X509Store` instance.
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001459 """
1460 context = Context(TLSv1_METHOD)
1461 store = context.get_cert_store()
Alex Chan532b79e2017-01-24 15:14:52 +00001462 assert isinstance(store, X509Store)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001463
1464
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001465class TestServerNameCallback(object):
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001466 """
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001467 Tests for `Context.set_tlsext_servername_callback` and its
1468 interaction with `Connection`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001469 """
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001470 def test_old_callback_forgotten(self):
1471 """
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001472 If `Context.set_tlsext_servername_callback` is used to specify
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001473 a new callback, the one it replaces is dereferenced.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001474 """
1475 def callback(connection):
1476 pass
1477
1478 def replacement(connection):
1479 pass
1480
1481 context = Context(TLSv1_METHOD)
1482 context.set_tlsext_servername_callback(callback)
1483
1484 tracker = ref(callback)
1485 del callback
1486
1487 context.set_tlsext_servername_callback(replacement)
Jean-Paul Calderoned4033eb2014-01-11 08:21:46 -05001488
1489 # One run of the garbage collector happens to work on CPython. PyPy
1490 # doesn't collect the underlying object until a second run for whatever
1491 # reason. That's fine, it still demonstrates our code has properly
1492 # dropped the reference.
1493 collect()
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001494 collect()
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001495
1496 callback = tracker()
1497 if callback is not None:
1498 referrers = get_referrers(callback)
Jean-Paul Calderone7de39562014-01-11 08:17:59 -05001499 if len(referrers) > 1:
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001500 self.fail("Some references remain: %r" % (referrers,))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001501
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001502 def test_no_servername(self):
1503 """
1504 When a client specifies no server name, the callback passed to
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001505 `Context.set_tlsext_servername_callback` is invoked and the
1506 result of `Connection.get_servername` is `None`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001507 """
1508 args = []
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001509
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001510 def servername(conn):
1511 args.append((conn, conn.get_servername()))
1512 context = Context(TLSv1_METHOD)
1513 context.set_tlsext_servername_callback(servername)
1514
1515 # Lose our reference to it. The Context is responsible for keeping it
1516 # alive now.
1517 del servername
1518 collect()
1519
1520 # Necessary to actually accept the connection
1521 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001522 context.use_certificate(
1523 load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001524
1525 # Do a little connection to trigger the logic
1526 server = Connection(context, None)
1527 server.set_accept_state()
1528
1529 client = Connection(Context(TLSv1_METHOD), None)
1530 client.set_connect_state()
1531
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001532 interact_in_memory(server, client)
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001533
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001534 assert args == [(server, None)]
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001535
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001536 def test_servername(self):
1537 """
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001538 When a client specifies a server name in its hello message, the
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001539 callback passed to `Contexts.set_tlsext_servername_callback` is
1540 invoked and the result of `Connection.get_servername` is that
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001541 server name.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001542 """
1543 args = []
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001544
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001545 def servername(conn):
1546 args.append((conn, conn.get_servername()))
1547 context = Context(TLSv1_METHOD)
1548 context.set_tlsext_servername_callback(servername)
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()
Alex Gaynore7f51982016-09-11 11:48:14 -04001561 client.set_tlsext_host_name(b"foo1.example.com")
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001562
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001563 interact_in_memory(server, client)
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001564
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001565 assert args == [(server, b"foo1.example.com")]
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001566
1567
Alex Chan9e08b3e2016-11-10 12:18:54 +00001568class TestNextProtoNegotiation(object):
Cory Benfield84a121e2014-03-31 20:30:25 +01001569 """
1570 Test for Next Protocol Negotiation in PyOpenSSL.
1571 """
Alex Chan9e08b3e2016-11-10 12:18:54 +00001572 def test_npn_success(self):
1573 """
1574 Tests that clients and servers that agree on the negotiated next
1575 protocol can correct establish a connection, and that the agreed
1576 protocol is reported by the connections.
1577 """
1578 advertise_args = []
1579 select_args = []
1580
1581 def advertise(conn):
1582 advertise_args.append((conn,))
1583 return [b'http/1.1', b'spdy/2']
1584
1585 def select(conn, options):
1586 select_args.append((conn, options))
1587 return b'spdy/2'
1588
1589 server_context = Context(TLSv1_METHOD)
1590 server_context.set_npn_advertise_callback(advertise)
1591
1592 client_context = Context(TLSv1_METHOD)
1593 client_context.set_npn_select_callback(select)
1594
1595 # Necessary to actually accept the connection
1596 server_context.use_privatekey(
1597 load_privatekey(FILETYPE_PEM, server_key_pem))
1598 server_context.use_certificate(
1599 load_certificate(FILETYPE_PEM, server_cert_pem))
1600
1601 # Do a little connection to trigger the logic
1602 server = Connection(server_context, None)
1603 server.set_accept_state()
1604
1605 client = Connection(client_context, None)
1606 client.set_connect_state()
1607
1608 interact_in_memory(server, client)
1609
1610 assert advertise_args == [(server,)]
1611 assert select_args == [(client, [b'http/1.1', b'spdy/2'])]
1612
1613 assert server.get_next_proto_negotiated() == b'spdy/2'
1614 assert client.get_next_proto_negotiated() == b'spdy/2'
1615
1616 def test_npn_client_fail(self):
1617 """
1618 Tests that when clients and servers cannot agree on what protocol
1619 to use next that the TLS connection does not get established.
1620 """
1621 advertise_args = []
1622 select_args = []
1623
1624 def advertise(conn):
1625 advertise_args.append((conn,))
1626 return [b'http/1.1', b'spdy/2']
1627
1628 def select(conn, options):
1629 select_args.append((conn, options))
1630 return b''
1631
1632 server_context = Context(TLSv1_METHOD)
1633 server_context.set_npn_advertise_callback(advertise)
1634
1635 client_context = Context(TLSv1_METHOD)
1636 client_context.set_npn_select_callback(select)
1637
1638 # Necessary to actually accept the connection
1639 server_context.use_privatekey(
1640 load_privatekey(FILETYPE_PEM, server_key_pem))
1641 server_context.use_certificate(
1642 load_certificate(FILETYPE_PEM, server_cert_pem))
1643
1644 # Do a little connection to trigger the logic
1645 server = Connection(server_context, None)
1646 server.set_accept_state()
1647
1648 client = Connection(client_context, None)
1649 client.set_connect_state()
1650
1651 # If the client doesn't return anything, the connection will fail.
1652 with pytest.raises(Error):
1653 interact_in_memory(server, client)
1654
1655 assert advertise_args == [(server,)]
1656 assert select_args == [(client, [b'http/1.1', b'spdy/2'])]
1657
1658 def test_npn_select_error(self):
1659 """
1660 Test that we can handle exceptions in the select callback. If
1661 select fails it should be fatal to the connection.
1662 """
1663 advertise_args = []
1664
1665 def advertise(conn):
1666 advertise_args.append((conn,))
1667 return [b'http/1.1', b'spdy/2']
1668
1669 def select(conn, options):
1670 raise TypeError
1671
1672 server_context = Context(TLSv1_METHOD)
1673 server_context.set_npn_advertise_callback(advertise)
1674
1675 client_context = Context(TLSv1_METHOD)
1676 client_context.set_npn_select_callback(select)
1677
1678 # Necessary to actually accept the connection
1679 server_context.use_privatekey(
1680 load_privatekey(FILETYPE_PEM, server_key_pem))
1681 server_context.use_certificate(
1682 load_certificate(FILETYPE_PEM, server_cert_pem))
1683
1684 # Do a little connection to trigger the logic
1685 server = Connection(server_context, None)
1686 server.set_accept_state()
1687
1688 client = Connection(client_context, None)
1689 client.set_connect_state()
1690
1691 # If the callback throws an exception it should be raised here.
1692 with pytest.raises(TypeError):
1693 interact_in_memory(server, client)
1694 assert advertise_args == [(server,), ]
1695
1696 def test_npn_advertise_error(self):
1697 """
1698 Test that we can handle exceptions in the advertise callback. If
1699 advertise fails no NPN is advertised to the client.
1700 """
1701 select_args = []
1702
1703 def advertise(conn):
1704 raise TypeError
1705
1706 def select(conn, options): # pragma: nocover
Cory Benfieldba1820d2015-04-13 17:39:12 -04001707 """
Alex Chan9e08b3e2016-11-10 12:18:54 +00001708 Assert later that no args are actually appended.
Cory Benfieldba1820d2015-04-13 17:39:12 -04001709 """
Alex Chan9e08b3e2016-11-10 12:18:54 +00001710 select_args.append((conn, options))
1711 return b''
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001712
Alex Chan9e08b3e2016-11-10 12:18:54 +00001713 server_context = Context(TLSv1_METHOD)
1714 server_context.set_npn_advertise_callback(advertise)
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001715
Alex Chan9e08b3e2016-11-10 12:18:54 +00001716 client_context = Context(TLSv1_METHOD)
1717 client_context.set_npn_select_callback(select)
Cory Benfield84a121e2014-03-31 20:30:25 +01001718
Alex Chan9e08b3e2016-11-10 12:18:54 +00001719 # Necessary to actually accept the connection
1720 server_context.use_privatekey(
1721 load_privatekey(FILETYPE_PEM, server_key_pem))
1722 server_context.use_certificate(
1723 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield84a121e2014-03-31 20:30:25 +01001724
Alex Chan9e08b3e2016-11-10 12:18:54 +00001725 # Do a little connection to trigger the logic
1726 server = Connection(server_context, None)
1727 server.set_accept_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001728
Alex Chan9e08b3e2016-11-10 12:18:54 +00001729 client = Connection(client_context, None)
1730 client.set_connect_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001731
Alex Chan9e08b3e2016-11-10 12:18:54 +00001732 # If the client doesn't return anything, the connection will fail.
1733 with pytest.raises(TypeError):
1734 interact_in_memory(server, client)
1735 assert select_args == []
Cory Benfield0ea76e72015-03-22 09:05:28 +00001736
1737
Alex Chanec1e32d2016-11-10 14:11:45 +00001738class TestApplicationLayerProtoNegotiation(object):
Cory Benfield12eae892014-06-07 15:42:56 +01001739 """
1740 Tests for ALPN in PyOpenSSL.
1741 """
Cory Benfielde46fa842015-04-13 16:50:49 -04001742 # Skip tests on versions that don't support ALPN.
1743 if _lib.Cryptography_HAS_ALPN:
Cory Benfield12eae892014-06-07 15:42:56 +01001744
Cory Benfielde46fa842015-04-13 16:50:49 -04001745 def test_alpn_success(self):
1746 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04001747 Clients and servers that agree on the negotiated ALPN protocol can
1748 correct establish a connection, and the agreed protocol is reported
1749 by the connections.
Cory Benfielde46fa842015-04-13 16:50:49 -04001750 """
1751 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001752
Cory Benfielde46fa842015-04-13 16:50:49 -04001753 def select(conn, options):
1754 select_args.append((conn, options))
1755 return b'spdy/2'
Cory Benfield12eae892014-06-07 15:42:56 +01001756
Cory Benfielde46fa842015-04-13 16:50:49 -04001757 client_context = Context(TLSv1_METHOD)
1758 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfield12eae892014-06-07 15:42:56 +01001759
Cory Benfielde46fa842015-04-13 16:50:49 -04001760 server_context = Context(TLSv1_METHOD)
1761 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01001762
Cory Benfielde46fa842015-04-13 16:50:49 -04001763 # Necessary to actually accept the connection
1764 server_context.use_privatekey(
1765 load_privatekey(FILETYPE_PEM, server_key_pem))
1766 server_context.use_certificate(
1767 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield12eae892014-06-07 15:42:56 +01001768
Cory Benfielde46fa842015-04-13 16:50:49 -04001769 # Do a little connection to trigger the logic
1770 server = Connection(server_context, None)
1771 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001772
Cory Benfielde46fa842015-04-13 16:50:49 -04001773 client = Connection(client_context, None)
1774 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001775
Alex Chanec1e32d2016-11-10 14:11:45 +00001776 interact_in_memory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001777
Alex Chanec1e32d2016-11-10 14:11:45 +00001778 assert select_args == [(server, [b'http/1.1', b'spdy/2'])]
Cory Benfielde46fa842015-04-13 16:50:49 -04001779
Alex Chanec1e32d2016-11-10 14:11:45 +00001780 assert server.get_alpn_proto_negotiated() == b'spdy/2'
1781 assert client.get_alpn_proto_negotiated() == b'spdy/2'
Cory Benfield12eae892014-06-07 15:42:56 +01001782
Cory Benfielde46fa842015-04-13 16:50:49 -04001783 def test_alpn_set_on_connection(self):
1784 """
1785 The same as test_alpn_success, but setting the ALPN protocols on
1786 the connection rather than the context.
1787 """
1788 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001789
Cory Benfielde46fa842015-04-13 16:50:49 -04001790 def select(conn, options):
1791 select_args.append((conn, options))
1792 return b'spdy/2'
Cory Benfield12eae892014-06-07 15:42:56 +01001793
Cory Benfielde46fa842015-04-13 16:50:49 -04001794 # Setup the client context but don't set any ALPN protocols.
1795 client_context = Context(TLSv1_METHOD)
Cory Benfield12eae892014-06-07 15:42:56 +01001796
Cory Benfielde46fa842015-04-13 16:50:49 -04001797 server_context = Context(TLSv1_METHOD)
1798 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01001799
Cory Benfielde46fa842015-04-13 16:50:49 -04001800 # Necessary to actually accept the connection
1801 server_context.use_privatekey(
1802 load_privatekey(FILETYPE_PEM, server_key_pem))
1803 server_context.use_certificate(
1804 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield12eae892014-06-07 15:42:56 +01001805
Cory Benfielde46fa842015-04-13 16:50:49 -04001806 # Do a little connection to trigger the logic
1807 server = Connection(server_context, None)
1808 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001809
Cory Benfielde46fa842015-04-13 16:50:49 -04001810 # Set the ALPN protocols on the client connection.
1811 client = Connection(client_context, None)
1812 client.set_alpn_protos([b'http/1.1', b'spdy/2'])
1813 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001814
Alex Chanec1e32d2016-11-10 14:11:45 +00001815 interact_in_memory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001816
Alex Chanec1e32d2016-11-10 14:11:45 +00001817 assert select_args == [(server, [b'http/1.1', b'spdy/2'])]
Cory Benfield12eae892014-06-07 15:42:56 +01001818
Alex Chanec1e32d2016-11-10 14:11:45 +00001819 assert server.get_alpn_proto_negotiated() == b'spdy/2'
1820 assert client.get_alpn_proto_negotiated() == b'spdy/2'
Cory Benfield12eae892014-06-07 15:42:56 +01001821
Cory Benfielde46fa842015-04-13 16:50:49 -04001822 def test_alpn_server_fail(self):
1823 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04001824 When clients and servers cannot agree on what protocol to use next
1825 the TLS connection does not get established.
Cory Benfielde46fa842015-04-13 16:50:49 -04001826 """
1827 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001828
Cory Benfielde46fa842015-04-13 16:50:49 -04001829 def select(conn, options):
1830 select_args.append((conn, options))
1831 return b''
Cory Benfield12eae892014-06-07 15:42:56 +01001832
Cory Benfielde46fa842015-04-13 16:50:49 -04001833 client_context = Context(TLSv1_METHOD)
1834 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfield12eae892014-06-07 15:42:56 +01001835
Cory Benfielde46fa842015-04-13 16:50:49 -04001836 server_context = Context(TLSv1_METHOD)
1837 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01001838
Cory Benfielde46fa842015-04-13 16:50:49 -04001839 # Necessary to actually accept the connection
1840 server_context.use_privatekey(
1841 load_privatekey(FILETYPE_PEM, server_key_pem))
1842 server_context.use_certificate(
1843 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield12eae892014-06-07 15:42:56 +01001844
Cory Benfielde46fa842015-04-13 16:50:49 -04001845 # Do a little connection to trigger the logic
1846 server = Connection(server_context, None)
1847 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001848
Cory Benfielde46fa842015-04-13 16:50:49 -04001849 client = Connection(client_context, None)
1850 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001851
Cory Benfielde46fa842015-04-13 16:50:49 -04001852 # If the client doesn't return anything, the connection will fail.
Alex Chanec1e32d2016-11-10 14:11:45 +00001853 with pytest.raises(Error):
1854 interact_in_memory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001855
Alex Chanec1e32d2016-11-10 14:11:45 +00001856 assert select_args == [(server, [b'http/1.1', b'spdy/2'])]
Cory Benfield12eae892014-06-07 15:42:56 +01001857
Cory Benfielde46fa842015-04-13 16:50:49 -04001858 def test_alpn_no_server(self):
1859 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04001860 When clients and servers cannot agree on what protocol to use next
1861 because the server doesn't offer ALPN, no protocol is negotiated.
Cory Benfielde46fa842015-04-13 16:50:49 -04001862 """
1863 client_context = Context(TLSv1_METHOD)
1864 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfielde3d57152015-04-11 17:57:35 -04001865
Cory Benfielde46fa842015-04-13 16:50:49 -04001866 server_context = Context(TLSv1_METHOD)
Cory Benfielde3d57152015-04-11 17:57:35 -04001867
Cory Benfielde46fa842015-04-13 16:50:49 -04001868 # Necessary to actually accept the connection
1869 server_context.use_privatekey(
1870 load_privatekey(FILETYPE_PEM, server_key_pem))
1871 server_context.use_certificate(
1872 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfielde3d57152015-04-11 17:57:35 -04001873
Cory Benfielde46fa842015-04-13 16:50:49 -04001874 # Do a little connection to trigger the logic
1875 server = Connection(server_context, None)
1876 server.set_accept_state()
Cory Benfielde3d57152015-04-11 17:57:35 -04001877
Cory Benfielde46fa842015-04-13 16:50:49 -04001878 client = Connection(client_context, None)
1879 client.set_connect_state()
Cory Benfielde3d57152015-04-11 17:57:35 -04001880
Cory Benfielde46fa842015-04-13 16:50:49 -04001881 # Do the dance.
Alex Chanec1e32d2016-11-10 14:11:45 +00001882 interact_in_memory(server, client)
Cory Benfielde3d57152015-04-11 17:57:35 -04001883
Alex Chanec1e32d2016-11-10 14:11:45 +00001884 assert client.get_alpn_proto_negotiated() == b''
Cory Benfielde3d57152015-04-11 17:57:35 -04001885
Cory Benfielde46fa842015-04-13 16:50:49 -04001886 def test_alpn_callback_exception(self):
1887 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04001888 We can handle exceptions in the ALPN select callback.
Cory Benfielde46fa842015-04-13 16:50:49 -04001889 """
1890 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001891
Cory Benfielde46fa842015-04-13 16:50:49 -04001892 def select(conn, options):
1893 select_args.append((conn, options))
Cory Benfieldef401452015-04-13 18:17:36 -04001894 raise TypeError()
Cory Benfieldf1177e72015-04-12 09:11:49 -04001895
Cory Benfielde46fa842015-04-13 16:50:49 -04001896 client_context = Context(TLSv1_METHOD)
1897 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfieldf1177e72015-04-12 09:11:49 -04001898
Cory Benfielde46fa842015-04-13 16:50:49 -04001899 server_context = Context(TLSv1_METHOD)
1900 server_context.set_alpn_select_callback(select)
Cory Benfieldf1177e72015-04-12 09:11:49 -04001901
Cory Benfielde46fa842015-04-13 16:50:49 -04001902 # Necessary to actually accept the connection
1903 server_context.use_privatekey(
1904 load_privatekey(FILETYPE_PEM, server_key_pem))
1905 server_context.use_certificate(
1906 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfieldf1177e72015-04-12 09:11:49 -04001907
Cory Benfielde46fa842015-04-13 16:50:49 -04001908 # Do a little connection to trigger the logic
1909 server = Connection(server_context, None)
1910 server.set_accept_state()
Cory Benfieldf1177e72015-04-12 09:11:49 -04001911
Cory Benfielde46fa842015-04-13 16:50:49 -04001912 client = Connection(client_context, None)
1913 client.set_connect_state()
Cory Benfieldf1177e72015-04-12 09:11:49 -04001914
Alex Chanec1e32d2016-11-10 14:11:45 +00001915 with pytest.raises(TypeError):
1916 interact_in_memory(server, client)
1917 assert select_args == [(server, [b'http/1.1', b'spdy/2'])]
Cory Benfieldf1177e72015-04-12 09:11:49 -04001918
Cory Benfield0f7b04c2015-04-13 17:51:12 -04001919 else:
1920 # No ALPN.
1921 def test_alpn_not_implemented(self):
Cory Benfieldef401452015-04-13 18:17:36 -04001922 """
1923 If ALPN is not in OpenSSL, we should raise NotImplementedError.
1924 """
Cory Benfield0f7b04c2015-04-13 17:51:12 -04001925 # Test the context methods first.
1926 context = Context(TLSv1_METHOD)
Alex Chanec1e32d2016-11-10 14:11:45 +00001927 with pytest.raises(NotImplementedError):
1928 context.set_alpn_protos(None)
1929 with pytest.raises(NotImplementedError):
1930 context.set_alpn_select_callback(None)
Cory Benfield0f7b04c2015-04-13 17:51:12 -04001931
1932 # Now test a connection.
1933 conn = Connection(context)
Alex Chanec1e32d2016-11-10 14:11:45 +00001934 with pytest.raises(NotImplementedError):
1935 conn.set_alpn_protos(None)
Cory Benfield0f7b04c2015-04-13 17:51:12 -04001936
Cory Benfieldf1177e72015-04-12 09:11:49 -04001937
Alex Chanec1e32d2016-11-10 14:11:45 +00001938class TestSession(object):
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05001939 """
1940 Unit tests for :py:obj:`OpenSSL.SSL.Session`.
1941 """
1942 def test_construction(self):
1943 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001944 :py:class:`Session` can be constructed with no arguments, creating
1945 a new instance of that type.
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05001946 """
1947 new_session = Session()
Alex Chanec1e32d2016-11-10 14:11:45 +00001948 assert isinstance(new_session, Session)
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05001949
1950
Alex Chan1c0cb662017-01-30 07:13:30 +00001951class TestConnection(object):
Rick Deane15b1472009-07-09 15:53:42 -05001952 """
Alex Chan1c0cb662017-01-30 07:13:30 +00001953 Unit tests for `OpenSSL.SSL.Connection`.
Rick Deane15b1472009-07-09 15:53:42 -05001954 """
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04001955 # XXX get_peer_certificate -> None
1956 # XXX sock_shutdown
1957 # XXX master_key -> TypeError
1958 # XXX server_random -> TypeError
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04001959 # XXX connect -> TypeError
1960 # XXX connect_ex -> TypeError
1961 # XXX set_connect_state -> TypeError
1962 # XXX set_accept_state -> TypeError
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04001963 # XXX do_handshake -> TypeError
1964 # XXX bio_read -> TypeError
1965 # XXX recv -> TypeError
1966 # XXX send -> TypeError
1967 # XXX bio_write -> TypeError
1968
Rick Deane15b1472009-07-09 15:53:42 -05001969 def test_type(self):
1970 """
Alex Chan1c0cb662017-01-30 07:13:30 +00001971 `Connection` and `ConnectionType` refer to the same type object and
1972 can be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -05001973 """
Alex Chan1c0cb662017-01-30 07:13:30 +00001974 assert Connection is ConnectionType
Rick Deane15b1472009-07-09 15:53:42 -05001975 ctx = Context(TLSv1_METHOD)
Alex Chan1c0cb662017-01-30 07:13:30 +00001976 assert is_consistent_type(Connection, 'Connection', ctx, None)
Rick Deane15b1472009-07-09 15:53:42 -05001977
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05001978 def test_get_context(self):
1979 """
Alex Chan1c0cb662017-01-30 07:13:30 +00001980 `Connection.get_context` returns the `Context` instance used to
1981 construct the `Connection` instance.
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05001982 """
1983 context = Context(TLSv1_METHOD)
1984 connection = Connection(context, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00001985 assert connection.get_context() is context
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05001986
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04001987 def test_set_context_wrong_args(self):
1988 """
Alex Chan1c0cb662017-01-30 07:13:30 +00001989 `Connection.set_context` raises `TypeError` if called with a
1990 non-`Context` instance argument,
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04001991 """
1992 ctx = Context(TLSv1_METHOD)
1993 connection = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00001994 with pytest.raises(TypeError):
1995 connection.set_context(object())
1996 with pytest.raises(TypeError):
1997 connection.set_context("hello")
1998 with pytest.raises(TypeError):
1999 connection.set_context(1)
2000 assert ctx is connection.get_context()
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002001
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002002 def test_set_context(self):
2003 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002004 `Connection.set_context` specifies a new `Context` instance to be
2005 used for the connection.
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002006 """
2007 original = Context(SSLv23_METHOD)
2008 replacement = Context(TLSv1_METHOD)
2009 connection = Connection(original, None)
2010 connection.set_context(replacement)
Alex Chan1c0cb662017-01-30 07:13:30 +00002011 assert replacement is connection.get_context()
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002012 # Lose our references to the contexts, just in case the Connection
2013 # isn't properly managing its own contributions to their reference
2014 # counts.
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002015 del original, replacement
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002016 collect()
2017
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002018 def test_set_tlsext_host_name_wrong_args(self):
2019 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002020 If `Connection.set_tlsext_host_name` is called with a non-byte string
2021 argument or a byte string with an embedded NUL, `TypeError` is raised.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002022 """
2023 conn = Connection(Context(TLSv1_METHOD), None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002024 with pytest.raises(TypeError):
2025 conn.set_tlsext_host_name(object())
2026 with pytest.raises(TypeError):
2027 conn.set_tlsext_host_name(b"with\0null")
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002028
Abraham Martinc5484ba2015-03-25 15:33:05 +00002029 if PY3:
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002030 # On Python 3.x, don't accidentally implicitly convert from text.
Alex Chan1c0cb662017-01-30 07:13:30 +00002031 with pytest.raises(TypeError):
2032 conn.set_tlsext_host_name(b"example.com".decode("ascii"))
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04002033
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002034 def test_pending(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002035 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002036 `Connection.pending` returns the number of bytes available for
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002037 immediate read.
2038 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002039 connection = Connection(Context(TLSv1_METHOD), None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002040 assert connection.pending() == 0
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002041
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002042 def test_peek(self):
2043 """
Hynek Schlawack3bcf3152017-02-18 08:25:34 +01002044 `Connection.recv` peeks into the connection if `socket.MSG_PEEK` is
2045 passed.
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002046 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002047 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002048 server.send(b'xy')
Alex Chan1c0cb662017-01-30 07:13:30 +00002049 assert client.recv(2, MSG_PEEK) == b'xy'
2050 assert client.recv(2, MSG_PEEK) == b'xy'
2051 assert client.recv(2) == b'xy'
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002052
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002053 def test_connect_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002054 """
Hynek Schlawack3bcf3152017-02-18 08:25:34 +01002055 `Connection.connect` raises `TypeError` if called with a non-address
2056 argument.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002057 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002058 connection = Connection(Context(TLSv1_METHOD), socket())
Alex Chan1c0cb662017-01-30 07:13:30 +00002059 with pytest.raises(TypeError):
2060 connection.connect(None)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002061
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002062 def test_connect_refused(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002063 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002064 `Connection.connect` raises `socket.error` if the underlying socket
2065 connect method raises it.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002066 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002067 client = socket()
2068 context = Context(TLSv1_METHOD)
2069 clientSSL = Connection(context, client)
Alex Gaynor122717b2015-09-05 14:14:18 -04002070 # pytest.raises here doesn't work because of a bug in py.test on Python
2071 # 2.6: https://github.com/pytest-dev/pytest/issues/988
Alex Gaynore69c2782015-09-05 14:07:48 -04002072 try:
Alex Gaynor1aabb2e2015-09-05 13:35:18 -04002073 clientSSL.connect(("127.0.0.1", 1))
Alex Gaynore69c2782015-09-05 14:07:48 -04002074 except error as e:
Alex Gaynor20a4c082015-09-05 14:24:15 -04002075 exc = e
2076 assert exc.args[0] == ECONNREFUSED
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002077
2078 def test_connect(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002079 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002080 `Connection.connect` establishes a connection to the specified address.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002081 """
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002082 port = socket()
2083 port.bind(('', 0))
2084 port.listen(3)
2085
2086 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002087 clientSSL.connect(('127.0.0.1', port.getsockname()[1]))
2088 # XXX An assertion? Or something?
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002089
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002090 @pytest.mark.skipif(
2091 platform == "darwin",
2092 reason="connect_ex sometimes causes a kernel panic on OS X 10.6.4"
2093 )
2094 def test_connect_ex(self):
2095 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002096 If there is a connection error, `Connection.connect_ex` returns the
2097 errno instead of raising an exception.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002098 """
2099 port = socket()
2100 port.bind(('', 0))
2101 port.listen(3)
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002102
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002103 clientSSL = Connection(Context(TLSv1_METHOD), socket())
2104 clientSSL.setblocking(False)
2105 result = clientSSL.connect_ex(port.getsockname())
2106 expected = (EINPROGRESS, EWOULDBLOCK)
Alex Chan1c0cb662017-01-30 07:13:30 +00002107 assert result in expected
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002108
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002109 def test_accept(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002110 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002111 `Connection.accept` accepts a pending connection attempt and returns a
2112 tuple of a new `Connection` (the accepted client) and the address the
2113 connection originated from.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002114 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002115 ctx = Context(TLSv1_METHOD)
2116 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2117 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002118 port = socket()
2119 portSSL = Connection(ctx, port)
2120 portSSL.bind(('', 0))
2121 portSSL.listen(3)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002122
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002123 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002124
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002125 # Calling portSSL.getsockname() here to get the server IP address
2126 # sounds great, but frequently fails on Windows.
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002127 clientSSL.connect(('127.0.0.1', portSSL.getsockname()[1]))
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002128
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002129 serverSSL, address = portSSL.accept()
2130
Alex Chan1c0cb662017-01-30 07:13:30 +00002131 assert isinstance(serverSSL, Connection)
2132 assert serverSSL.get_context() is ctx
2133 assert address == clientSSL.getsockname()
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002134
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002135 def test_shutdown_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002136 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002137 `Connection.set_shutdown` raises `TypeError` if called with arguments
2138 other than integers.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002139 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002140 connection = Connection(Context(TLSv1_METHOD), None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002141 with pytest.raises(TypeError):
2142 connection.set_shutdown(None)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002143
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002144 def test_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002145 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002146 `Connection.shutdown` performs an SSL-level connection shutdown.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002147 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002148 server, client = loopback()
2149 assert not server.shutdown()
2150 assert server.get_shutdown() == SENT_SHUTDOWN
2151 with pytest.raises(ZeroReturnError):
2152 client.recv(1024)
2153 assert client.get_shutdown() == RECEIVED_SHUTDOWN
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04002154 client.shutdown()
Alex Chan1c0cb662017-01-30 07:13:30 +00002155 assert client.get_shutdown() == (SENT_SHUTDOWN | RECEIVED_SHUTDOWN)
2156 with pytest.raises(ZeroReturnError):
2157 server.recv(1024)
2158 assert server.get_shutdown() == (SENT_SHUTDOWN | RECEIVED_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002159
Paul Aurichc85e0862015-01-08 08:34:33 -08002160 def test_shutdown_closed(self):
2161 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002162 If the underlying socket is closed, `Connection.shutdown` propagates
2163 the write error from the low level write call.
Paul Aurichc85e0862015-01-08 08:34:33 -08002164 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002165 server, client = loopback()
Paul Aurichc85e0862015-01-08 08:34:33 -08002166 server.sock_shutdown(2)
Alex Chan1c0cb662017-01-30 07:13:30 +00002167 with pytest.raises(SysCallError) as exc:
2168 server.shutdown()
2169 if platform == "win32":
2170 assert exc.value.args[0] == ESHUTDOWN
2171 else:
2172 assert exc.value.args[0] == EPIPE
Paul Aurichc85e0862015-01-08 08:34:33 -08002173
Glyph89389472015-04-14 17:29:26 -04002174 def test_shutdown_truncated(self):
Glyph6064ec32015-04-14 16:38:22 -04002175 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002176 If the underlying connection is truncated, `Connection.shutdown`
2177 raises an `Error`.
Glyph6064ec32015-04-14 16:38:22 -04002178 """
Glyph89389472015-04-14 17:29:26 -04002179 server_ctx = Context(TLSv1_METHOD)
2180 client_ctx = Context(TLSv1_METHOD)
2181 server_ctx.use_privatekey(
2182 load_privatekey(FILETYPE_PEM, server_key_pem))
2183 server_ctx.use_certificate(
2184 load_certificate(FILETYPE_PEM, server_cert_pem))
2185 server = Connection(server_ctx, None)
2186 client = Connection(client_ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002187 handshake_in_memory(client, server)
2188 assert not server.shutdown()
2189 with pytest.raises(WantReadError):
2190 server.shutdown()
Glyph89389472015-04-14 17:29:26 -04002191 server.bio_shutdown()
Alex Chan1c0cb662017-01-30 07:13:30 +00002192 with pytest.raises(Error):
2193 server.shutdown()
Glyph6064ec32015-04-14 16:38:22 -04002194
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002195 def test_set_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002196 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002197 `Connection.set_shutdown` sets the state of the SSL connection
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002198 shutdown process.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002199 """
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002200 connection = Connection(Context(TLSv1_METHOD), socket())
2201 connection.set_shutdown(RECEIVED_SHUTDOWN)
Alex Chan1c0cb662017-01-30 07:13:30 +00002202 assert connection.get_shutdown() == RECEIVED_SHUTDOWN
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002203
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002204 @skip_if_py3
2205 def test_set_shutdown_long(self):
2206 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002207 On Python 2 `Connection.set_shutdown` accepts an argument
2208 of type `long` as well as `int`.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002209 """
2210 connection = Connection(Context(TLSv1_METHOD), socket())
2211 connection.set_shutdown(long(RECEIVED_SHUTDOWN))
Alex Chan1c0cb662017-01-30 07:13:30 +00002212 assert connection.get_shutdown() == RECEIVED_SHUTDOWN
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -05002213
kjavaf248592015-09-07 12:14:01 +01002214 def test_state_string(self):
2215 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002216 `Connection.state_string` verbosely describes the current state of
2217 the `Connection`.
kjavaf248592015-09-07 12:14:01 +01002218 """
Hynek Schlawackb0274ce2015-10-16 19:56:26 +02002219 server, client = socket_pair()
Alex Chan1c0cb662017-01-30 07:13:30 +00002220 server = loopback_server_factory(server)
2221 client = loopback_client_factory(client)
kjavaf248592015-09-07 12:14:01 +01002222
Alex Gaynor5af32d02016-09-24 01:52:21 -04002223 assert server.get_state_string() in [
2224 b"before/accept initialization", b"before SSL initialization"
2225 ]
2226 assert client.get_state_string() in [
2227 b"before/connect initialization", b"before SSL initialization"
2228 ]
kjavaf248592015-09-07 12:14:01 +01002229
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002230 def test_app_data(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002231 """
2232 Any object can be set as app data by passing it to
Alex Chan1c0cb662017-01-30 07:13:30 +00002233 `Connection.set_app_data` and later retrieved with
2234 `Connection.get_app_data`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002235 """
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002236 conn = Connection(Context(TLSv1_METHOD), None)
Todd Chapman4f73e4f2015-08-27 11:26:43 -04002237 assert None is conn.get_app_data()
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002238 app_data = object()
2239 conn.set_app_data(app_data)
Todd Chapman4f73e4f2015-08-27 11:26:43 -04002240 assert conn.get_app_data() is app_data
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002241
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002242 def test_makefile(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002243 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002244 `Connection.makefile` is not implemented and calling that
2245 method raises `NotImplementedError`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002246 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002247 conn = Connection(Context(TLSv1_METHOD), None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002248 with pytest.raises(NotImplementedError):
2249 conn.makefile()
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002250
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002251 def test_get_peer_cert_chain(self):
2252 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002253 `Connection.get_peer_cert_chain` returns a list of certificates
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002254 which the connected server returned for the certification verification.
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002255 """
2256 chain = _create_certificate_chain()
2257 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
2258
2259 serverContext = Context(TLSv1_METHOD)
2260 serverContext.use_privatekey(skey)
2261 serverContext.use_certificate(scert)
2262 serverContext.add_extra_chain_cert(icert)
2263 serverContext.add_extra_chain_cert(cacert)
2264 server = Connection(serverContext, None)
2265 server.set_accept_state()
2266
2267 # Create the client
2268 clientContext = Context(TLSv1_METHOD)
2269 clientContext.set_verify(VERIFY_NONE, verify_cb)
2270 client = Connection(clientContext, None)
2271 client.set_connect_state()
2272
Alex Chan1c0cb662017-01-30 07:13:30 +00002273 interact_in_memory(client, server)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002274
2275 chain = client.get_peer_cert_chain()
Alex Chan1c0cb662017-01-30 07:13:30 +00002276 assert len(chain) == 3
2277 assert "Server Certificate" == chain[0].get_subject().CN
2278 assert "Intermediate Certificate" == chain[1].get_subject().CN
2279 assert "Authority Certificate" == chain[2].get_subject().CN
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002280
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002281 def test_get_peer_cert_chain_none(self):
2282 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002283 `Connection.get_peer_cert_chain` returns `None` if the peer sends
2284 no certificate chain.
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002285 """
2286 ctx = Context(TLSv1_METHOD)
2287 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2288 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
2289 server = Connection(ctx, None)
2290 server.set_accept_state()
2291 client = Connection(Context(TLSv1_METHOD), None)
2292 client.set_connect_state()
Alex Chan1c0cb662017-01-30 07:13:30 +00002293 interact_in_memory(client, server)
2294 assert None is server.get_peer_cert_chain()
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002295
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002296 def test_get_session_unconnected(self):
2297 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002298 `Connection.get_session` returns `None` when used with an object
2299 which has not been connected.
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002300 """
2301 ctx = Context(TLSv1_METHOD)
2302 server = Connection(ctx, None)
2303 session = server.get_session()
Alex Chan1c0cb662017-01-30 07:13:30 +00002304 assert None is session
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002305
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002306 def test_server_get_session(self):
2307 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002308 On the server side of a connection, `Connection.get_session` returns a
2309 `Session` instance representing the SSL session for that connection.
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002310 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002311 server, client = loopback()
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002312 session = server.get_session()
Alex Chan1c0cb662017-01-30 07:13:30 +00002313 assert isinstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002314
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002315 def test_client_get_session(self):
2316 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002317 On the client side of a connection, `Connection.get_session`
2318 returns a `Session` instance representing the SSL session for
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002319 that connection.
2320 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002321 server, client = loopback()
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002322 session = client.get_session()
Alex Chan1c0cb662017-01-30 07:13:30 +00002323 assert isinstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002324
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002325 def test_set_session_wrong_args(self):
2326 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002327 `Connection.set_session` raises `TypeError` if called with an object
2328 that is not an instance of `Session`.
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002329 """
2330 ctx = Context(TLSv1_METHOD)
2331 connection = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002332 with pytest.raises(TypeError):
2333 connection.set_session(123)
2334 with pytest.raises(TypeError):
2335 connection.set_session("hello")
2336 with pytest.raises(TypeError):
2337 connection.set_session(object())
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002338
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002339 def test_client_set_session(self):
2340 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002341 `Connection.set_session`, when used prior to a connection being
2342 established, accepts a `Session` instance and causes an attempt to
2343 re-use the session it represents when the SSL handshake is performed.
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002344 """
2345 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2346 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
2347 ctx = Context(TLSv1_METHOD)
2348 ctx.use_privatekey(key)
2349 ctx.use_certificate(cert)
2350 ctx.set_session_id("unity-test")
2351
2352 def makeServer(socket):
2353 server = Connection(ctx, socket)
2354 server.set_accept_state()
2355 return server
2356
Alex Chan1c0cb662017-01-30 07:13:30 +00002357 originalServer, originalClient = loopback(
2358 server_factory=makeServer)
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002359 originalSession = originalClient.get_session()
2360
2361 def makeClient(socket):
Alex Chan1c0cb662017-01-30 07:13:30 +00002362 client = loopback_client_factory(socket)
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002363 client.set_session(originalSession)
2364 return client
Alex Chan1c0cb662017-01-30 07:13:30 +00002365 resumedServer, resumedClient = loopback(
2366 server_factory=makeServer,
2367 client_factory=makeClient)
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002368
2369 # This is a proxy: in general, we have no access to any unique
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002370 # identifier for the session (new enough versions of OpenSSL expose
2371 # a hash which could be usable, but "new enough" is very, very new).
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002372 # Instead, exploit the fact that the master key is re-used if the
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002373 # session is re-used. As long as the master key for the two
2374 # connections is the same, the session was re-used!
Alex Chan1c0cb662017-01-30 07:13:30 +00002375 assert originalServer.master_key() == resumedServer.master_key()
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002376
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002377 def test_set_session_wrong_method(self):
2378 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002379 If `Connection.set_session` is passed a `Session` instance associated
2380 with a context using a different SSL method than the `Connection`
2381 is using, a `OpenSSL.SSL.Error` is raised.
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002382 """
Alex Gaynor5af32d02016-09-24 01:52:21 -04002383 # Make this work on both OpenSSL 1.0.0, which doesn't support TLSv1.2
2384 # and also on OpenSSL 1.1.0 which doesn't support SSLv3. (SSL_ST_INIT
2385 # is a way to check for 1.1.0)
2386 if SSL_ST_INIT is not None:
2387 v1 = TLSv1_METHOD
2388 v2 = SSLv3_METHOD
2389 else:
2390 v1 = TLSv1_2_METHOD
2391 v2 = TLSv1_METHOD
2392
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002393 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2394 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
Alex Gaynor5af32d02016-09-24 01:52:21 -04002395 ctx = Context(v1)
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002396 ctx.use_privatekey(key)
2397 ctx.use_certificate(cert)
2398 ctx.set_session_id("unity-test")
2399
2400 def makeServer(socket):
2401 server = Connection(ctx, socket)
2402 server.set_accept_state()
2403 return server
2404
Alex Gaynor5af32d02016-09-24 01:52:21 -04002405 def makeOriginalClient(socket):
2406 client = Connection(Context(v1), socket)
2407 client.set_connect_state()
2408 return client
2409
Alex Chan1c0cb662017-01-30 07:13:30 +00002410 originalServer, originalClient = loopback(
2411 server_factory=makeServer, client_factory=makeOriginalClient)
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002412 originalSession = originalClient.get_session()
2413
2414 def makeClient(socket):
2415 # Intentionally use a different, incompatible method here.
Alex Gaynor5af32d02016-09-24 01:52:21 -04002416 client = Connection(Context(v2), socket)
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002417 client.set_connect_state()
2418 client.set_session(originalSession)
2419 return client
2420
Alex Chan1c0cb662017-01-30 07:13:30 +00002421 with pytest.raises(Error):
2422 loopback(client_factory=makeClient, server_factory=makeServer)
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002423
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002424 def test_wantWriteError(self):
2425 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002426 `Connection` methods which generate output raise
2427 `OpenSSL.SSL.WantWriteError` if writing to the connection's BIO
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002428 fail indicating a should-write state.
2429 """
2430 client_socket, server_socket = socket_pair()
2431 # Fill up the client's send buffer so Connection won't be able to write
Jean-Paul Calderonebbff8b92014-03-22 14:20:30 -04002432 # anything. Only write a single byte at a time so we can be sure we
2433 # completely fill the buffer. Even though the socket API is allowed to
2434 # signal a short write via its return value it seems this doesn't
2435 # always happen on all platforms (FreeBSD and OS X particular) for the
2436 # very last bit of available buffer space.
2437 msg = b"x"
2438 for i in range(1024 * 1024 * 4):
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002439 try:
2440 client_socket.send(msg)
2441 except error as e:
2442 if e.errno == EWOULDBLOCK:
2443 break
2444 raise
2445 else:
Alex Chan1c0cb662017-01-30 07:13:30 +00002446 pytest.fail(
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002447 "Failed to fill socket buffer, cannot test BIO want write")
2448
2449 ctx = Context(TLSv1_METHOD)
2450 conn = Connection(ctx, client_socket)
2451 # Client's speak first, so make it an SSL client
2452 conn.set_connect_state()
Alex Chan1c0cb662017-01-30 07:13:30 +00002453 with pytest.raises(WantWriteError):
2454 conn.do_handshake()
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002455
2456 # XXX want_read
2457
Fedor Brunner416f4a12014-03-28 13:18:38 +01002458 def test_get_finished_before_connect(self):
Fedor Brunner5747b932014-03-05 14:22:34 +01002459 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002460 `Connection.get_finished` returns `None` before TLS handshake
2461 is completed.
Fedor Brunner5747b932014-03-05 14:22:34 +01002462 """
Fedor Brunner5747b932014-03-05 14:22:34 +01002463 ctx = Context(TLSv1_METHOD)
2464 connection = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002465 assert connection.get_finished() is None
Fedor Brunner416f4a12014-03-28 13:18:38 +01002466
2467 def test_get_peer_finished_before_connect(self):
2468 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002469 `Connection.get_peer_finished` returns `None` before TLS handshake
2470 is completed.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002471 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002472 ctx = Context(TLSv1_METHOD)
2473 connection = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002474 assert connection.get_peer_finished() is None
Fedor Brunner5747b932014-03-05 14:22:34 +01002475
Fedor Brunner416f4a12014-03-28 13:18:38 +01002476 def test_get_finished(self):
2477 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002478 `Connection.get_finished` method returns the TLS Finished message send
2479 from client, or server. Finished messages are send during
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002480 TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002481 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002482 server, client = loopback()
Fedor Brunner416f4a12014-03-28 13:18:38 +01002483
Alex Chan1c0cb662017-01-30 07:13:30 +00002484 assert server.get_finished() is not None
2485 assert len(server.get_finished()) > 0
Fedor Brunner416f4a12014-03-28 13:18:38 +01002486
2487 def test_get_peer_finished(self):
2488 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002489 `Connection.get_peer_finished` method returns the TLS Finished
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002490 message received from client, or server. Finished messages are send
2491 during TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002492 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002493 server, client = loopback()
Fedor Brunner416f4a12014-03-28 13:18:38 +01002494
Alex Chan1c0cb662017-01-30 07:13:30 +00002495 assert server.get_peer_finished() is not None
2496 assert len(server.get_peer_finished()) > 0
Fedor Brunner5747b932014-03-05 14:22:34 +01002497
Fedor Brunner416f4a12014-03-28 13:18:38 +01002498 def test_tls_finished_message_symmetry(self):
2499 """
Hynek Schlawackdddd1112015-09-05 21:12:30 +02002500 The TLS Finished message send by server must be the TLS Finished
2501 message received by client.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002502
Hynek Schlawackdddd1112015-09-05 21:12:30 +02002503 The TLS Finished message send by client must be the TLS Finished
2504 message received by server.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002505 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002506 server, client = loopback()
Fedor Brunner416f4a12014-03-28 13:18:38 +01002507
Alex Chan1c0cb662017-01-30 07:13:30 +00002508 assert server.get_finished() == client.get_peer_finished()
2509 assert client.get_finished() == server.get_peer_finished()
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002510
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002511 def test_get_cipher_name_before_connect(self):
2512 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002513 `Connection.get_cipher_name` returns `None` if no connection
2514 has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002515 """
2516 ctx = Context(TLSv1_METHOD)
2517 conn = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002518 assert conn.get_cipher_name() is None
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002519
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002520 def test_get_cipher_name(self):
2521 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002522 `Connection.get_cipher_name` returns a `unicode` string giving the
2523 name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002524 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002525 server, client = loopback()
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002526 server_cipher_name, client_cipher_name = \
2527 server.get_cipher_name(), client.get_cipher_name()
2528
Alex Chan1c0cb662017-01-30 07:13:30 +00002529 assert isinstance(server_cipher_name, text_type)
2530 assert isinstance(client_cipher_name, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002531
Alex Chan1c0cb662017-01-30 07:13:30 +00002532 assert server_cipher_name == client_cipher_name
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002533
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002534 def test_get_cipher_version_before_connect(self):
2535 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002536 `Connection.get_cipher_version` returns `None` if no connection
2537 has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002538 """
2539 ctx = Context(TLSv1_METHOD)
2540 conn = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002541 assert conn.get_cipher_version() is None
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002542
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002543 def test_get_cipher_version(self):
2544 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002545 `Connection.get_cipher_version` returns a `unicode` string giving
2546 the protocol name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002547 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002548 server, client = loopback()
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002549 server_cipher_version, client_cipher_version = \
2550 server.get_cipher_version(), client.get_cipher_version()
2551
Alex Chan1c0cb662017-01-30 07:13:30 +00002552 assert isinstance(server_cipher_version, text_type)
2553 assert isinstance(client_cipher_version, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002554
Alex Chan1c0cb662017-01-30 07:13:30 +00002555 assert server_cipher_version == client_cipher_version
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002556
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002557 def test_get_cipher_bits_before_connect(self):
2558 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002559 `Connection.get_cipher_bits` returns `None` if no connection has
2560 been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002561 """
2562 ctx = Context(TLSv1_METHOD)
2563 conn = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002564 assert conn.get_cipher_bits() is None
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002565
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002566 def test_get_cipher_bits(self):
2567 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002568 `Connection.get_cipher_bits` returns the number of secret bits
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002569 of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002570 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002571 server, client = loopback()
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002572 server_cipher_bits, client_cipher_bits = \
2573 server.get_cipher_bits(), client.get_cipher_bits()
2574
Alex Chan1c0cb662017-01-30 07:13:30 +00002575 assert isinstance(server_cipher_bits, int)
2576 assert isinstance(client_cipher_bits, int)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002577
Alex Chan1c0cb662017-01-30 07:13:30 +00002578 assert server_cipher_bits == client_cipher_bits
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002579
Jim Shaverabff1882015-05-27 09:15:55 -04002580 def test_get_protocol_version_name(self):
2581 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002582 `Connection.get_protocol_version_name()` returns a string giving the
2583 protocol version of the current connection.
Jim Shaverabff1882015-05-27 09:15:55 -04002584 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002585 server, client = loopback()
Jim Shaverabff1882015-05-27 09:15:55 -04002586 client_protocol_version_name = client.get_protocol_version_name()
2587 server_protocol_version_name = server.get_protocol_version_name()
2588
Alex Chan1c0cb662017-01-30 07:13:30 +00002589 assert isinstance(server_protocol_version_name, text_type)
2590 assert isinstance(client_protocol_version_name, text_type)
Jim Shaverabff1882015-05-27 09:15:55 -04002591
Alex Chan1c0cb662017-01-30 07:13:30 +00002592 assert server_protocol_version_name == client_protocol_version_name
Jim Shaverabff1882015-05-27 09:15:55 -04002593
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002594 def test_get_protocol_version(self):
2595 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002596 `Connection.get_protocol_version()` returns an integer
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002597 giving the protocol version of the current connection.
2598 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002599 server, client = loopback()
Jim Shaver85a4dff2015-04-27 17:42:46 -04002600 client_protocol_version = client.get_protocol_version()
2601 server_protocol_version = server.get_protocol_version()
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002602
Alex Chan1c0cb662017-01-30 07:13:30 +00002603 assert isinstance(server_protocol_version, int)
2604 assert isinstance(client_protocol_version, int)
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002605
Alex Chan1c0cb662017-01-30 07:13:30 +00002606 assert server_protocol_version == client_protocol_version
2607
2608 def test_wantReadError(self):
2609 """
2610 `Connection.bio_read` raises `OpenSSL.SSL.WantReadError` if there are
2611 no bytes available to be read from the BIO.
2612 """
2613 ctx = Context(TLSv1_METHOD)
2614 conn = Connection(ctx, None)
2615 with pytest.raises(WantReadError):
2616 conn.bio_read(1024)
2617
2618 def test_buffer_size(self):
2619 """
2620 `Connection.bio_read` accepts an integer giving the maximum number
2621 of bytes to read and return.
2622 """
2623 ctx = Context(TLSv1_METHOD)
2624 conn = Connection(ctx, None)
2625 conn.set_connect_state()
2626 try:
2627 conn.do_handshake()
2628 except WantReadError:
2629 pass
2630 data = conn.bio_read(2)
2631 assert 2 == len(data)
2632
2633 @skip_if_py3
2634 def test_buffer_size_long(self):
2635 """
2636 On Python 2 `Connection.bio_read` accepts values of type `long` as
2637 well as `int`.
2638 """
2639 ctx = Context(TLSv1_METHOD)
2640 conn = Connection(ctx, None)
2641 conn.set_connect_state()
2642 try:
2643 conn.do_handshake()
2644 except WantReadError:
2645 pass
2646 data = conn.bio_read(long(2))
2647 assert 2 == len(data)
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002648
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002649
Alex Chanb7480992017-01-30 14:04:47 +00002650class TestConnectionGetCipherList(object):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002651 """
Alex Chanb7480992017-01-30 14:04:47 +00002652 Tests for `Connection.get_cipher_list`.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002653 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002654 def test_result(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002655 """
Alex Chanb7480992017-01-30 14:04:47 +00002656 `Connection.get_cipher_list` returns a list of `bytes` giving the
2657 names of the ciphers which might be used.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002658 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002659 connection = Connection(Context(TLSv1_METHOD), None)
2660 ciphers = connection.get_cipher_list()
Alex Chanb7480992017-01-30 14:04:47 +00002661 assert isinstance(ciphers, list)
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002662 for cipher in ciphers:
Alex Chanb7480992017-01-30 14:04:47 +00002663 assert isinstance(cipher, str)
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002664
2665
Maximilian Hils868dc3c2017-02-10 14:56:55 +01002666class VeryLarge(bytes):
2667 """
2668 Mock object so that we don't have to allocate 2**31 bytes
2669 """
2670 def __len__(self):
2671 return 2**31
2672
2673
Alex Chanb7480992017-01-30 14:04:47 +00002674class TestConnectionSend(object):
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002675 """
Alex Chanb7480992017-01-30 14:04:47 +00002676 Tests for `Connection.send`.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002677 """
2678 def test_wrong_args(self):
2679 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002680 When called with arguments other than string argument for its first
Alex Chanb7480992017-01-30 14:04:47 +00002681 parameter, `Connection.send` raises `TypeError`.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002682 """
2683 connection = Connection(Context(TLSv1_METHOD), None)
Alex Chanb7480992017-01-30 14:04:47 +00002684 with pytest.raises(TypeError):
2685 connection.send(object())
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002686
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002687 def test_short_bytes(self):
2688 """
Alex Chanb7480992017-01-30 14:04:47 +00002689 When passed a short byte string, `Connection.send` transmits all of it
2690 and returns the number of bytes sent.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002691 """
Alex Chanb7480992017-01-30 14:04:47 +00002692 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002693 count = server.send(b'xy')
Alex Chanb7480992017-01-30 14:04:47 +00002694 assert count == 2
2695 assert client.recv(2) == b'xy'
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002696
Abraham Martinef063482015-03-25 14:06:24 +00002697 def test_text(self):
2698 """
Alex Chanb7480992017-01-30 14:04:47 +00002699 When passed a text, `Connection.send` transmits all of it and
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002700 returns the number of bytes sent. It also raises a DeprecationWarning.
Abraham Martinef063482015-03-25 14:06:24 +00002701 """
Alex Chanb7480992017-01-30 14:04:47 +00002702 server, client = loopback()
2703 with pytest.warns(DeprecationWarning) as w:
Abraham Martinef063482015-03-25 14:06:24 +00002704 simplefilter("always")
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002705 count = server.send(b"xy".decode("ascii"))
Alex Chanb7480992017-01-30 14:04:47 +00002706 assert (
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002707 "{0} for buf is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002708 WARNING_TYPE_EXPECTED
Alex Chanb7480992017-01-30 14:04:47 +00002709 ) == str(w[-1].message))
2710 assert count == 2
2711 assert client.recv(2) == b'xy'
Abraham Martinef063482015-03-25 14:06:24 +00002712
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002713 @skip_if_py26
2714 def test_short_memoryview(self):
2715 """
2716 When passed a memoryview onto a small number of bytes,
Alex Chanb7480992017-01-30 14:04:47 +00002717 `Connection.send` transmits all of them and returns the number
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002718 of bytes sent.
2719 """
Alex Chanb7480992017-01-30 14:04:47 +00002720 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002721 count = server.send(memoryview(b'xy'))
Alex Chanb7480992017-01-30 14:04:47 +00002722 assert count == 2
2723 assert client.recv(2) == b'xy'
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002724
Hynek Schlawack8e94f1b2015-09-05 21:31:00 +02002725 @skip_if_py3
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002726 def test_short_buffer(self):
2727 """
2728 When passed a buffer containing a small number of bytes,
Alex Chanb7480992017-01-30 14:04:47 +00002729 `Connection.send` transmits all of them and returns the number
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002730 of bytes sent.
2731 """
Alex Chanb7480992017-01-30 14:04:47 +00002732 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002733 count = server.send(buffer(b'xy'))
Alex Chanb7480992017-01-30 14:04:47 +00002734 assert count == 2
2735 assert client.recv(2) == b'xy'
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02002736
Maximilian Hils868dc3c2017-02-10 14:56:55 +01002737 @pytest.mark.skipif(
2738 sys.maxsize < 2**31,
2739 reason="sys.maxsize < 2**31 - test requires 64 bit"
2740 )
2741 def test_buf_too_large(self):
2742 """
2743 When passed a buffer containing >= 2**31 bytes,
2744 `Connection.send` bails out as SSL_write only
2745 accepts an int for the buffer length.
2746 """
2747 connection = Connection(Context(TLSv1_METHOD), None)
2748 with pytest.raises(ValueError) as exc_info:
2749 connection.send(VeryLarge())
2750 exc_info.match(r"Cannot send more than .+ bytes at once")
2751
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05002752
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002753def _make_memoryview(size):
2754 """
2755 Create a new ``memoryview`` wrapped around a ``bytearray`` of the given
2756 size.
2757 """
2758 return memoryview(bytearray(size))
2759
2760
Alex Chanb7480992017-01-30 14:04:47 +00002761class TestConnectionRecvInto(object):
Cory Benfield62d10332014-06-15 10:03:41 +01002762 """
Alex Chanb7480992017-01-30 14:04:47 +00002763 Tests for `Connection.recv_into`.
Cory Benfield62d10332014-06-15 10:03:41 +01002764 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002765 def _no_length_test(self, factory):
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04002766 """
Alex Chanb7480992017-01-30 14:04:47 +00002767 Assert that when the given buffer is passed to `Connection.recv_into`,
2768 whatever bytes are available to be received that fit into that buffer
2769 are written into that buffer.
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04002770 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002771 output_buffer = factory(5)
2772
Alex Chanb7480992017-01-30 14:04:47 +00002773 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002774 server.send(b'xy')
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04002775
Alex Chanb7480992017-01-30 14:04:47 +00002776 assert client.recv_into(output_buffer) == 2
2777 assert output_buffer == bytearray(b'xy\x00\x00\x00')
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04002778
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002779 def test_bytearray_no_length(self):
Cory Benfield62d10332014-06-15 10:03:41 +01002780 """
Alex Chanb7480992017-01-30 14:04:47 +00002781 `Connection.recv_into` can be passed a `bytearray` instance and data
2782 in the receive buffer is written to it.
Cory Benfield62d10332014-06-15 10:03:41 +01002783 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002784 self._no_length_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01002785
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002786 def _respects_length_test(self, factory):
Cory Benfield62d10332014-06-15 10:03:41 +01002787 """
Alex Chanb7480992017-01-30 14:04:47 +00002788 Assert that when the given buffer is passed to `Connection.recv_into`
2789 along with a value for `nbytes` that is less than the size of that
2790 buffer, only `nbytes` bytes are written into the buffer.
Cory Benfield62d10332014-06-15 10:03:41 +01002791 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002792 output_buffer = factory(10)
2793
Alex Chanb7480992017-01-30 14:04:47 +00002794 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002795 server.send(b'abcdefghij')
Cory Benfield62d10332014-06-15 10:03:41 +01002796
Alex Chanb7480992017-01-30 14:04:47 +00002797 assert client.recv_into(output_buffer, 5) == 5
2798 assert output_buffer == bytearray(b'abcde\x00\x00\x00\x00\x00')
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002799
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002800 def test_bytearray_respects_length(self):
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002801 """
Alex Chanb7480992017-01-30 14:04:47 +00002802 When called with a `bytearray` instance, `Connection.recv_into`
2803 respects the `nbytes` parameter and doesn't copy in more than that
2804 number of bytes.
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002805 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002806 self._respects_length_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01002807
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002808 def _doesnt_overfill_test(self, factory):
Cory Benfield62d10332014-06-15 10:03:41 +01002809 """
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002810 Assert that if there are more bytes available to be read from the
2811 receive buffer than would fit into the buffer passed to
Alex Chanb7480992017-01-30 14:04:47 +00002812 `Connection.recv_into`, only as many as fit are written into it.
Cory Benfield62d10332014-06-15 10:03:41 +01002813 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002814 output_buffer = factory(5)
2815
Alex Chanb7480992017-01-30 14:04:47 +00002816 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002817 server.send(b'abcdefghij')
Cory Benfield62d10332014-06-15 10:03:41 +01002818
Alex Chanb7480992017-01-30 14:04:47 +00002819 assert client.recv_into(output_buffer) == 5
2820 assert output_buffer == bytearray(b'abcde')
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002821 rest = client.recv(5)
Alex Chanb7480992017-01-30 14:04:47 +00002822 assert b'fghij' == rest
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002823
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002824 def test_bytearray_doesnt_overfill(self):
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002825 """
Alex Chanb7480992017-01-30 14:04:47 +00002826 When called with a `bytearray` instance, `Connection.recv_into`
2827 respects the size of the array and doesn't write more bytes into it
2828 than will fit.
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002829 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002830 self._doesnt_overfill_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01002831
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002832 def test_bytearray_really_doesnt_overfill(self):
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04002833 """
Alex Chanb7480992017-01-30 14:04:47 +00002834 When called with a `bytearray` instance and an `nbytes` value that is
2835 too large, `Connection.recv_into` respects the size of the array and
2836 not the `nbytes` value and doesn't write more bytes into the buffer
2837 than will fit.
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04002838 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002839 self._doesnt_overfill_test(bytearray)
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04002840
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002841 def test_peek(self):
Alex Chanb7480992017-01-30 14:04:47 +00002842 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002843 server.send(b'xy')
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002844
2845 for _ in range(2):
2846 output_buffer = bytearray(5)
Alex Chanb7480992017-01-30 14:04:47 +00002847 assert client.recv_into(output_buffer, flags=MSG_PEEK) == 2
2848 assert output_buffer == bytearray(b'xy\x00\x00\x00')
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002849
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002850 @skip_if_py26
2851 def test_memoryview_no_length(self):
2852 """
Alex Chanb7480992017-01-30 14:04:47 +00002853 `Connection.recv_into` can be passed a `memoryview` instance and data
2854 in the receive buffer is written to it.
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002855 """
2856 self._no_length_test(_make_memoryview)
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002857
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002858 @skip_if_py26
2859 def test_memoryview_respects_length(self):
2860 """
Alex Chanb7480992017-01-30 14:04:47 +00002861 When called with a `memoryview` instance, `Connection.recv_into`
2862 respects the ``nbytes`` parameter and doesn't copy more than that
2863 number of bytes in.
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002864 """
2865 self._respects_length_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01002866
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002867 @skip_if_py26
2868 def test_memoryview_doesnt_overfill(self):
2869 """
Alex Chanb7480992017-01-30 14:04:47 +00002870 When called with a `memoryview` instance, `Connection.recv_into`
2871 respects the size of the array and doesn't write more bytes into it
2872 than will fit.
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002873 """
2874 self._doesnt_overfill_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01002875
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002876 @skip_if_py26
2877 def test_memoryview_really_doesnt_overfill(self):
2878 """
Alex Chanb7480992017-01-30 14:04:47 +00002879 When called with a `memoryview` instance and an `nbytes` value that is
2880 too large, `Connection.recv_into` respects the size of the array and
2881 not the `nbytes` value and doesn't write more bytes into the buffer
2882 than will fit.
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002883 """
2884 self._doesnt_overfill_test(_make_memoryview)
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04002885
Cory Benfield62d10332014-06-15 10:03:41 +01002886
Alex Chanb7480992017-01-30 14:04:47 +00002887class TestConnectionSendall(object):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002888 """
Alex Chanb7480992017-01-30 14:04:47 +00002889 Tests for `Connection.sendall`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002890 """
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002891 def test_wrong_args(self):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002892 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002893 When called with arguments other than a string argument for its first
Alex Chanb7480992017-01-30 14:04:47 +00002894 parameter, `Connection.sendall` raises `TypeError`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002895 """
2896 connection = Connection(Context(TLSv1_METHOD), None)
Alex Chanb7480992017-01-30 14:04:47 +00002897 with pytest.raises(TypeError):
2898 connection.sendall(object())
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002899
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002900 def test_short(self):
2901 """
Alex Chanb7480992017-01-30 14:04:47 +00002902 `Connection.sendall` transmits all of the bytes in the string
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02002903 passed to it.
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002904 """
Alex Chanb7480992017-01-30 14:04:47 +00002905 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002906 server.sendall(b'x')
Alex Chanb7480992017-01-30 14:04:47 +00002907 assert client.recv(1) == b'x'
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002908
Abraham Martinef063482015-03-25 14:06:24 +00002909 def test_text(self):
2910 """
Alex Chanb7480992017-01-30 14:04:47 +00002911 `Connection.sendall` transmits all the content in the string passed
2912 to it, raising a DeprecationWarning in case of this being a text.
Abraham Martinef063482015-03-25 14:06:24 +00002913 """
Alex Chanb7480992017-01-30 14:04:47 +00002914 server, client = loopback()
2915 with pytest.warns(DeprecationWarning) as w:
Abraham Martinef063482015-03-25 14:06:24 +00002916 simplefilter("always")
Jean-Paul Calderone8dc37a12015-03-29 08:16:52 -04002917 server.sendall(b"x".decode("ascii"))
Alex Chanb7480992017-01-30 14:04:47 +00002918 assert (
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002919 "{0} for buf is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002920 WARNING_TYPE_EXPECTED
Alex Chanb7480992017-01-30 14:04:47 +00002921 ) == str(w[-1].message))
2922 assert client.recv(1) == b"x"
Abraham Martinef063482015-03-25 14:06:24 +00002923
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02002924 @skip_if_py26
2925 def test_short_memoryview(self):
2926 """
2927 When passed a memoryview onto a small number of bytes,
Alex Chanb7480992017-01-30 14:04:47 +00002928 `Connection.sendall` transmits all of them.
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02002929 """
Alex Chanb7480992017-01-30 14:04:47 +00002930 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002931 server.sendall(memoryview(b'x'))
Alex Chanb7480992017-01-30 14:04:47 +00002932 assert client.recv(1) == b'x'
Abraham Martinef063482015-03-25 14:06:24 +00002933
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02002934 @skip_if_py3
2935 def test_short_buffers(self):
2936 """
2937 When passed a buffer containing a small number of bytes,
Alex Chanb7480992017-01-30 14:04:47 +00002938 `Connection.sendall` transmits all of them.
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02002939 """
Alex Chanb7480992017-01-30 14:04:47 +00002940 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002941 server.sendall(buffer(b'x'))
Alex Chanb7480992017-01-30 14:04:47 +00002942 assert client.recv(1) == b'x'
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02002943
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002944 def test_long(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002945 """
Alex Chanb7480992017-01-30 14:04:47 +00002946 `Connection.sendall` transmits all the bytes in the string passed to it
2947 even if this requires multiple calls of an underlying write function.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002948 """
Alex Chanb7480992017-01-30 14:04:47 +00002949 server, client = loopback()
Jean-Paul Calderone6241c702010-09-16 19:59:24 -04002950 # Should be enough, underlying SSL_write should only do 16k at a time.
Hynek Schlawack35618382015-09-05 21:54:25 +02002951 # On Windows, after 32k of bytes the write will block (forever
2952 # - because no one is yet reading).
Alex Gaynore7f51982016-09-11 11:48:14 -04002953 message = b'x' * (1024 * 32 - 1) + b'y'
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002954 server.sendall(message)
2955 accum = []
2956 received = 0
2957 while received < len(message):
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04002958 data = client.recv(1024)
2959 accum.append(data)
2960 received += len(data)
Alex Chanb7480992017-01-30 14:04:47 +00002961 assert message == b''.join(accum)
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002962
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04002963 def test_closed(self):
2964 """
Alex Chanb7480992017-01-30 14:04:47 +00002965 If the underlying socket is closed, `Connection.sendall` propagates the
2966 write error from the low level write call.
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04002967 """
Alex Chanb7480992017-01-30 14:04:47 +00002968 server, client = loopback()
Jean-Paul Calderone05d43e82010-09-24 18:01:36 -04002969 server.sock_shutdown(2)
Alex Chanb7480992017-01-30 14:04:47 +00002970 with pytest.raises(SysCallError) as err:
2971 server.sendall(b"hello, world")
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +02002972 if platform == "win32":
Alex Chanb7480992017-01-30 14:04:47 +00002973 assert err.value.args[0] == ESHUTDOWN
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +02002974 else:
Alex Chanb7480992017-01-30 14:04:47 +00002975 assert err.value.args[0] == EPIPE
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04002976
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002977
Alex Chanb7480992017-01-30 14:04:47 +00002978class TestConnectionRenegotiate(object):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002979 """
2980 Tests for SSL renegotiation APIs.
2981 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002982 def test_total_renegotiations(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002983 """
Alex Chanb7480992017-01-30 14:04:47 +00002984 `Connection.total_renegotiations` returns `0` before any renegotiations
2985 have happened.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002986 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002987 connection = Connection(Context(TLSv1_METHOD), None)
Alex Chanb7480992017-01-30 14:04:47 +00002988 assert connection.total_renegotiations() == 0
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002989
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01002990 def test_renegotiate(self):
2991 """
2992 Go through a complete renegotiation cycle.
2993 """
Alex Chanb7480992017-01-30 14:04:47 +00002994 server, client = loopback()
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002995
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01002996 server.send(b"hello world")
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002997
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01002998 assert b"hello world" == client.recv(len(b"hello world"))
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002999
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003000 assert 0 == server.total_renegotiations()
3001 assert False is server.renegotiate_pending()
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003002
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003003 assert True is server.renegotiate()
3004
3005 assert True is server.renegotiate_pending()
3006
3007 server.setblocking(False)
3008 client.setblocking(False)
3009
3010 client.do_handshake()
3011 server.do_handshake()
3012
3013 assert 1 == server.total_renegotiations()
3014 while False is server.renegotiate_pending():
3015 pass
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003016
3017
Alex Chanb7480992017-01-30 14:04:47 +00003018class TestError(object):
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003019 """
Alex Chanb7480992017-01-30 14:04:47 +00003020 Unit tests for `OpenSSL.SSL.Error`.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003021 """
3022 def test_type(self):
3023 """
Alex Chanb7480992017-01-30 14:04:47 +00003024 `Error` is an exception type.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003025 """
Alex Chanb7480992017-01-30 14:04:47 +00003026 assert issubclass(Error, Exception)
3027 assert Error.__name__ == 'Error'
Rick Deane15b1472009-07-09 15:53:42 -05003028
3029
Alex Chanb7480992017-01-30 14:04:47 +00003030class TestConstants(object):
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003031 """
Alex Chanb7480992017-01-30 14:04:47 +00003032 Tests for the values of constants exposed in `OpenSSL.SSL`.
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003033
3034 These are values defined by OpenSSL intended only to be used as flags to
3035 OpenSSL APIs. The only assertions it seems can be made about them is
3036 their values.
3037 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003038 @pytest.mark.skipif(
3039 OP_NO_QUERY_MTU is None,
3040 reason="OP_NO_QUERY_MTU unavailable - OpenSSL version may be too old"
3041 )
3042 def test_op_no_query_mtu(self):
3043 """
Alex Chanb7480992017-01-30 14:04:47 +00003044 The value of `OpenSSL.SSL.OP_NO_QUERY_MTU` is 0x1000, the value
3045 of `SSL_OP_NO_QUERY_MTU` defined by `openssl/ssl.h`.
Hynek Schlawack35618382015-09-05 21:54:25 +02003046 """
Alex Chanb7480992017-01-30 14:04:47 +00003047 assert OP_NO_QUERY_MTU == 0x1000
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003048
Hynek Schlawack35618382015-09-05 21:54:25 +02003049 @pytest.mark.skipif(
3050 OP_COOKIE_EXCHANGE is None,
3051 reason="OP_COOKIE_EXCHANGE unavailable - "
3052 "OpenSSL version may be too old"
3053 )
3054 def test_op_cookie_exchange(self):
3055 """
Alex Chanb7480992017-01-30 14:04:47 +00003056 The value of `OpenSSL.SSL.OP_COOKIE_EXCHANGE` is 0x2000, the
3057 value of `SSL_OP_COOKIE_EXCHANGE` defined by `openssl/ssl.h`.
Hynek Schlawack35618382015-09-05 21:54:25 +02003058 """
Alex Chanb7480992017-01-30 14:04:47 +00003059 assert OP_COOKIE_EXCHANGE == 0x2000
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003060
Hynek Schlawack35618382015-09-05 21:54:25 +02003061 @pytest.mark.skipif(
3062 OP_NO_TICKET is None,
3063 reason="OP_NO_TICKET unavailable - OpenSSL version may be too old"
3064 )
3065 def test_op_no_ticket(self):
3066 """
Alex Chanb7480992017-01-30 14:04:47 +00003067 The value of `OpenSSL.SSL.OP_NO_TICKET` is 0x4000, the value of
3068 `SSL_OP_NO_TICKET` defined by `openssl/ssl.h`.
Hynek Schlawack35618382015-09-05 21:54:25 +02003069 """
Alex Chanb7480992017-01-30 14:04:47 +00003070 assert OP_NO_TICKET == 0x4000
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003071
Hynek Schlawack35618382015-09-05 21:54:25 +02003072 @pytest.mark.skipif(
3073 OP_NO_COMPRESSION is None,
3074 reason="OP_NO_COMPRESSION unavailable - OpenSSL version may be too old"
3075 )
3076 def test_op_no_compression(self):
3077 """
Alex Chanb7480992017-01-30 14:04:47 +00003078 The value of `OpenSSL.SSL.OP_NO_COMPRESSION` is 0x20000, the
3079 value of `SSL_OP_NO_COMPRESSION` defined by `openssl/ssl.h`.
Hynek Schlawack35618382015-09-05 21:54:25 +02003080 """
Alex Chanb7480992017-01-30 14:04:47 +00003081 assert OP_NO_COMPRESSION == 0x20000
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04003082
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003083 def test_sess_cache_off(self):
3084 """
Alex Chanb7480992017-01-30 14:04:47 +00003085 The value of `OpenSSL.SSL.SESS_CACHE_OFF` 0x0, the value of
3086 `SSL_SESS_CACHE_OFF` defined by `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003087 """
Alex Chanb7480992017-01-30 14:04:47 +00003088 assert 0x0 == SESS_CACHE_OFF
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003089
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003090 def test_sess_cache_client(self):
3091 """
Alex Chanb7480992017-01-30 14:04:47 +00003092 The value of `OpenSSL.SSL.SESS_CACHE_CLIENT` 0x1, the value of
3093 `SSL_SESS_CACHE_CLIENT` defined by `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003094 """
Alex Chanb7480992017-01-30 14:04:47 +00003095 assert 0x1 == SESS_CACHE_CLIENT
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003096
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003097 def test_sess_cache_server(self):
3098 """
Alex Chanb7480992017-01-30 14:04:47 +00003099 The value of `OpenSSL.SSL.SESS_CACHE_SERVER` 0x2, the value of
3100 `SSL_SESS_CACHE_SERVER` defined by `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003101 """
Alex Chanb7480992017-01-30 14:04:47 +00003102 assert 0x2 == SESS_CACHE_SERVER
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003103
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003104 def test_sess_cache_both(self):
3105 """
Alex Chanb7480992017-01-30 14:04:47 +00003106 The value of `OpenSSL.SSL.SESS_CACHE_BOTH` 0x3, the value of
3107 `SSL_SESS_CACHE_BOTH` defined by `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003108 """
Alex Chanb7480992017-01-30 14:04:47 +00003109 assert 0x3 == SESS_CACHE_BOTH
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003110
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003111 def test_sess_cache_no_auto_clear(self):
3112 """
Alex Chanb7480992017-01-30 14:04:47 +00003113 The value of `OpenSSL.SSL.SESS_CACHE_NO_AUTO_CLEAR` 0x80, the
3114 value of `SSL_SESS_CACHE_NO_AUTO_CLEAR` defined by
3115 `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003116 """
Alex Chanb7480992017-01-30 14:04:47 +00003117 assert 0x80 == SESS_CACHE_NO_AUTO_CLEAR
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003118
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003119 def test_sess_cache_no_internal_lookup(self):
3120 """
Alex Chanb7480992017-01-30 14:04:47 +00003121 The value of `OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_LOOKUP` 0x100,
3122 the value of `SSL_SESS_CACHE_NO_INTERNAL_LOOKUP` defined by
3123 `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003124 """
Alex Chanb7480992017-01-30 14:04:47 +00003125 assert 0x100 == SESS_CACHE_NO_INTERNAL_LOOKUP
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003126
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003127 def test_sess_cache_no_internal_store(self):
3128 """
Alex Chanb7480992017-01-30 14:04:47 +00003129 The value of `OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_STORE` 0x200,
3130 the value of `SSL_SESS_CACHE_NO_INTERNAL_STORE` defined by
3131 `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003132 """
Alex Chanb7480992017-01-30 14:04:47 +00003133 assert 0x200 == SESS_CACHE_NO_INTERNAL_STORE
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003134
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003135 def test_sess_cache_no_internal(self):
3136 """
Alex Chanb7480992017-01-30 14:04:47 +00003137 The value of `OpenSSL.SSL.SESS_CACHE_NO_INTERNAL` 0x300, the
3138 value of `SSL_SESS_CACHE_NO_INTERNAL` defined by
3139 `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003140 """
Alex Chanb7480992017-01-30 14:04:47 +00003141 assert 0x300 == SESS_CACHE_NO_INTERNAL
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003142
3143
Alex Chanb7480992017-01-30 14:04:47 +00003144class TestMemoryBIO(object):
Rick Deanb71c0d22009-04-01 14:09:23 -05003145 """
Alex Chanb7480992017-01-30 14:04:47 +00003146 Tests for `OpenSSL.SSL.Connection` using a memory BIO.
Rick Deanb71c0d22009-04-01 14:09:23 -05003147 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003148 def _server(self, sock):
3149 """
Alex Chanb7480992017-01-30 14:04:47 +00003150 Create a new server-side SSL `Connection` object wrapped around `sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003151 """
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003152 # Create the server side Connection. This is mostly setup boilerplate
3153 # - use TLSv1, use a particular certificate, etc.
3154 server_ctx = Context(TLSv1_METHOD)
Alex Gaynor43307782015-09-04 09:05:45 -04003155 server_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE)
Hynek Schlawack35618382015-09-05 21:54:25 +02003156 server_ctx.set_verify(
3157 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT | VERIFY_CLIENT_ONCE,
3158 verify_cb
3159 )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003160 server_store = server_ctx.get_cert_store()
Hynek Schlawack35618382015-09-05 21:54:25 +02003161 server_ctx.use_privatekey(
3162 load_privatekey(FILETYPE_PEM, server_key_pem))
3163 server_ctx.use_certificate(
3164 load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003165 server_ctx.check_privatekey()
3166 server_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Hynek Schlawack35618382015-09-05 21:54:25 +02003167 # Here the Connection is actually created. If None is passed as the
3168 # 2nd parameter, it indicates a memory BIO should be created.
Rick Deanb1ccd562009-07-09 23:52:39 -05003169 server_conn = Connection(server_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003170 server_conn.set_accept_state()
3171 return server_conn
3172
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003173 def _client(self, sock):
3174 """
Alex Chanb7480992017-01-30 14:04:47 +00003175 Create a new client-side SSL `Connection` object wrapped around `sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003176 """
3177 # Now create the client side Connection. Similar boilerplate to the
3178 # above.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003179 client_ctx = Context(TLSv1_METHOD)
Alex Gaynor43307782015-09-04 09:05:45 -04003180 client_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE)
Hynek Schlawack35618382015-09-05 21:54:25 +02003181 client_ctx.set_verify(
3182 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT | VERIFY_CLIENT_ONCE,
3183 verify_cb
3184 )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003185 client_store = client_ctx.get_cert_store()
Hynek Schlawack35618382015-09-05 21:54:25 +02003186 client_ctx.use_privatekey(
3187 load_privatekey(FILETYPE_PEM, client_key_pem))
3188 client_ctx.use_certificate(
3189 load_certificate(FILETYPE_PEM, client_cert_pem))
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003190 client_ctx.check_privatekey()
3191 client_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05003192 client_conn = Connection(client_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003193 client_conn.set_connect_state()
3194 return client_conn
3195
Alex Chanb7480992017-01-30 14:04:47 +00003196 def test_memory_connect(self):
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003197 """
Alex Chanb7480992017-01-30 14:04:47 +00003198 Two `Connection`s which use memory BIOs can be manually connected by
3199 reading from the output of each and writing those bytes to the input of
3200 the other and in this way establish a connection and exchange
3201 application-level bytes with each other.
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003202 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003203 server_conn = self._server(None)
3204 client_conn = self._client(None)
Rick Deanb71c0d22009-04-01 14:09:23 -05003205
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003206 # There should be no key or nonces yet.
Alex Chanb7480992017-01-30 14:04:47 +00003207 assert server_conn.master_key() is None
3208 assert server_conn.client_random() is None
3209 assert server_conn.server_random() is None
Rick Deanb71c0d22009-04-01 14:09:23 -05003210
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003211 # First, the handshake needs to happen. We'll deliver bytes back and
3212 # forth between the client and server until neither of them feels like
3213 # speaking any more.
Alex Chanb7480992017-01-30 14:04:47 +00003214 assert interact_in_memory(client_conn, server_conn) is None
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003215
3216 # Now that the handshake is done, there should be a key and nonces.
Alex Chanb7480992017-01-30 14:04:47 +00003217 assert server_conn.master_key() is not None
3218 assert server_conn.client_random() is not None
3219 assert server_conn.server_random() is not None
3220 assert server_conn.client_random() == client_conn.client_random()
3221 assert server_conn.server_random() == client_conn.server_random()
3222 assert server_conn.client_random() != server_conn.server_random()
3223 assert client_conn.client_random() != client_conn.server_random()
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003224
3225 # Here are the bytes we'll try to send.
Alex Gaynore7f51982016-09-11 11:48:14 -04003226 important_message = b'One if by land, two if by sea.'
Rick Deanb71c0d22009-04-01 14:09:23 -05003227
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003228 server_conn.write(important_message)
Alex Chanb7480992017-01-30 14:04:47 +00003229 assert (
3230 interact_in_memory(client_conn, server_conn) ==
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003231 (client_conn, important_message))
3232
3233 client_conn.write(important_message[::-1])
Alex Chanb7480992017-01-30 14:04:47 +00003234 assert (
3235 interact_in_memory(client_conn, server_conn) ==
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003236 (server_conn, important_message[::-1]))
Rick Deanb71c0d22009-04-01 14:09:23 -05003237
Alex Chanb7480992017-01-30 14:04:47 +00003238 def test_socket_connect(self):
Rick Deanb1ccd562009-07-09 23:52:39 -05003239 """
Alex Chanb7480992017-01-30 14:04:47 +00003240 Just like `test_memory_connect` but with an actual socket.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003241
Hynek Schlawack35618382015-09-05 21:54:25 +02003242 This is primarily to rule out the memory BIO code as the source of any
Alex Chanb7480992017-01-30 14:04:47 +00003243 problems encountered while passing data over a `Connection` (if
Hynek Schlawack35618382015-09-05 21:54:25 +02003244 this test fails, there must be a problem outside the memory BIO code,
3245 as no memory BIO is involved here). Even though this isn't a memory
3246 BIO test, it's convenient to have it here.
Rick Deanb1ccd562009-07-09 23:52:39 -05003247 """
Alex Chanb7480992017-01-30 14:04:47 +00003248 server_conn, client_conn = loopback()
Rick Deanb1ccd562009-07-09 23:52:39 -05003249
Alex Gaynore7f51982016-09-11 11:48:14 -04003250 important_message = b"Help me Obi Wan Kenobi, you're my only hope."
Rick Deanb1ccd562009-07-09 23:52:39 -05003251 client_conn.send(important_message)
3252 msg = server_conn.recv(1024)
Alex Chanb7480992017-01-30 14:04:47 +00003253 assert msg == important_message
Rick Deanb1ccd562009-07-09 23:52:39 -05003254
3255 # Again in the other direction, just for fun.
3256 important_message = important_message[::-1]
3257 server_conn.send(important_message)
3258 msg = client_conn.recv(1024)
Alex Chanb7480992017-01-30 14:04:47 +00003259 assert msg == important_message
Rick Deanb1ccd562009-07-09 23:52:39 -05003260
Alex Chanb7480992017-01-30 14:04:47 +00003261 def test_socket_overrides_memory(self):
Rick Deanb71c0d22009-04-01 14:09:23 -05003262 """
Alex Chanb7480992017-01-30 14:04:47 +00003263 Test that `OpenSSL.SSL.bio_read` and `OpenSSL.SSL.bio_write` don't
3264 work on `OpenSSL.SSL.Connection`() that use sockets.
Rick Deanb71c0d22009-04-01 14:09:23 -05003265 """
Alex Gaynor51d424c2016-09-10 14:50:11 -04003266 context = Context(TLSv1_METHOD)
Rick Deanb71c0d22009-04-01 14:09:23 -05003267 client = socket()
3268 clientSSL = Connection(context, client)
Alex Chanb7480992017-01-30 14:04:47 +00003269 with pytest.raises(TypeError):
3270 clientSSL.bio_read(100)
3271 with pytest.raises(TypeError):
3272 clientSSL.bio_write("foo")
3273 with pytest.raises(TypeError):
3274 clientSSL.bio_shutdown()
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003275
Alex Chanb7480992017-01-30 14:04:47 +00003276 def test_outgoing_overflow(self):
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003277 """
3278 If more bytes than can be written to the memory BIO are passed to
Alex Chanb7480992017-01-30 14:04:47 +00003279 `Connection.send` at once, the number of bytes which were written is
3280 returned and that many bytes from the beginning of the input can be
3281 read from the other end of the connection.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003282 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003283 server = self._server(None)
3284 client = self._client(None)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003285
Alex Chanb7480992017-01-30 14:04:47 +00003286 interact_in_memory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003287
3288 size = 2 ** 15
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003289 sent = client.send(b"x" * size)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003290 # Sanity check. We're trying to test what happens when the entire
3291 # input can't be sent. If the entire input was sent, this test is
3292 # meaningless.
Alex Chanb7480992017-01-30 14:04:47 +00003293 assert sent < size
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003294
Alex Chanb7480992017-01-30 14:04:47 +00003295 receiver, received = interact_in_memory(client, server)
3296 assert receiver is server
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003297
3298 # We can rely on all of these bytes being received at once because
Alex Chanb7480992017-01-30 14:04:47 +00003299 # loopback passes 2 ** 16 to recv - more than 2 ** 15.
3300 assert len(received) == sent
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003301
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003302 def test_shutdown(self):
3303 """
Alex Chanb7480992017-01-30 14:04:47 +00003304 `Connection.bio_shutdown` signals the end of the data stream
3305 from which the `Connection` reads.
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003306 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003307 server = self._server(None)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003308 server.bio_shutdown()
Alex Chanb7480992017-01-30 14:04:47 +00003309 with pytest.raises(Error) as err:
3310 server.recv(1024)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003311 # We don't want WantReadError or ZeroReturnError or anything - it's a
3312 # handshake failure.
Alex Chanb7480992017-01-30 14:04:47 +00003313 assert type(err.value) in [Error, SysCallError]
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003314
Alex Chanb7480992017-01-30 14:04:47 +00003315 def test_unexpected_EOF(self):
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003316 """
3317 If the connection is lost before an orderly SSL shutdown occurs,
Alex Chanb7480992017-01-30 14:04:47 +00003318 `OpenSSL.SSL.SysCallError` is raised with a message of
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003319 "Unexpected EOF".
3320 """
Alex Chanb7480992017-01-30 14:04:47 +00003321 server_conn, client_conn = loopback()
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003322 client_conn.sock_shutdown(SHUT_RDWR)
Alex Chanb7480992017-01-30 14:04:47 +00003323 with pytest.raises(SysCallError) as err:
3324 server_conn.recv(1024)
3325 assert err.value.args == (-1, "Unexpected EOF")
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003326
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003327 def _check_client_ca_list(self, func):
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003328 """
Alex Chanb7480992017-01-30 14:04:47 +00003329 Verify the return value of the `get_client_ca_list` method for
Hynek Schlawack35618382015-09-05 21:54:25 +02003330 server and client connections.
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003331
Jonathan Ballet78b92a22011-07-16 08:07:26 +09003332 :param func: A function which will be called with the server context
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003333 before the client and server are connected to each other. This
3334 function should specify a list of CAs for the server to send to the
3335 client and return that same list. The list will be used to verify
Alex Chanb7480992017-01-30 14:04:47 +00003336 that `get_client_ca_list` returns the proper value at
Hynek Schlawack35618382015-09-05 21:54:25 +02003337 various times.
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003338 """
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003339 server = self._server(None)
3340 client = self._client(None)
Alex Chanb7480992017-01-30 14:04:47 +00003341 assert client.get_client_ca_list() == []
3342 assert server.get_client_ca_list() == []
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003343 ctx = server.get_context()
3344 expected = func(ctx)
Alex Chanb7480992017-01-30 14:04:47 +00003345 assert client.get_client_ca_list() == []
3346 assert server.get_client_ca_list() == expected
3347 interact_in_memory(client, server)
3348 assert client.get_client_ca_list() == expected
3349 assert server.get_client_ca_list() == expected
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003350
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003351 def test_set_client_ca_list_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003352 """
Alex Chanb7480992017-01-30 14:04:47 +00003353 `Context.set_client_ca_list` raises a `TypeError` if called with a
3354 non-list or a list that contains objects other than X509Names.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003355 """
3356 ctx = Context(TLSv1_METHOD)
Alex Chanb7480992017-01-30 14:04:47 +00003357 with pytest.raises(TypeError):
3358 ctx.set_client_ca_list("spam")
3359 with pytest.raises(TypeError):
3360 ctx.set_client_ca_list(["spam"])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003361
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003362 def test_set_empty_ca_list(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003363 """
Alex Chanb7480992017-01-30 14:04:47 +00003364 If passed an empty list, `Context.set_client_ca_list` configures the
3365 context to send no CA names to the client and, on both the server and
3366 client sides, `Connection.get_client_ca_list` returns an empty list
3367 after the connection is set up.
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003368 """
3369 def no_ca(ctx):
3370 ctx.set_client_ca_list([])
3371 return []
3372 self._check_client_ca_list(no_ca)
3373
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003374 def test_set_one_ca_list(self):
3375 """
3376 If passed a list containing a single X509Name,
Alex Chanb7480992017-01-30 14:04:47 +00003377 `Context.set_client_ca_list` configures the context to send
Hynek Schlawack35618382015-09-05 21:54:25 +02003378 that CA name to the client and, on both the server and client sides,
Alex Chanb7480992017-01-30 14:04:47 +00003379 `Connection.get_client_ca_list` returns a list containing that
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003380 X509Name after the connection is set up.
3381 """
3382 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3383 cadesc = cacert.get_subject()
Hynek Schlawack35618382015-09-05 21:54:25 +02003384
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003385 def single_ca(ctx):
3386 ctx.set_client_ca_list([cadesc])
3387 return [cadesc]
3388 self._check_client_ca_list(single_ca)
3389
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003390 def test_set_multiple_ca_list(self):
3391 """
3392 If passed a list containing multiple X509Name objects,
Alex Chanb7480992017-01-30 14:04:47 +00003393 `Context.set_client_ca_list` configures the context to send
Hynek Schlawack35618382015-09-05 21:54:25 +02003394 those CA names to the client and, on both the server and client sides,
Alex Chanb7480992017-01-30 14:04:47 +00003395 `Connection.get_client_ca_list` returns a list containing those
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003396 X509Names after the connection is set up.
3397 """
3398 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3399 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3400
3401 sedesc = secert.get_subject()
3402 cldesc = clcert.get_subject()
3403
3404 def multiple_ca(ctx):
3405 L = [sedesc, cldesc]
3406 ctx.set_client_ca_list(L)
3407 return L
3408 self._check_client_ca_list(multiple_ca)
3409
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003410 def test_reset_ca_list(self):
3411 """
3412 If called multiple times, only the X509Names passed to the final call
Alex Chanb7480992017-01-30 14:04:47 +00003413 of `Context.set_client_ca_list` are used to configure the CA
Hynek Schlawack35618382015-09-05 21:54:25 +02003414 names sent to the client.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003415 """
3416 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3417 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3418 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3419
3420 cadesc = cacert.get_subject()
3421 sedesc = secert.get_subject()
3422 cldesc = clcert.get_subject()
3423
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003424 def changed_ca(ctx):
3425 ctx.set_client_ca_list([sedesc, cldesc])
3426 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003427 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003428 self._check_client_ca_list(changed_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003429
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003430 def test_mutated_ca_list(self):
3431 """
Alex Chanb7480992017-01-30 14:04:47 +00003432 If the list passed to `Context.set_client_ca_list` is mutated
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003433 afterwards, this does not affect the list of CA names sent to the
3434 client.
3435 """
3436 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3437 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3438
3439 cadesc = cacert.get_subject()
3440 sedesc = secert.get_subject()
3441
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003442 def mutated_ca(ctx):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003443 L = [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003444 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003445 L.append(sedesc)
3446 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003447 self._check_client_ca_list(mutated_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003448
Alex Chanb7480992017-01-30 14:04:47 +00003449 def test_add_client_ca_wrong_args(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003450 """
Alex Chanb7480992017-01-30 14:04:47 +00003451 `Context.add_client_ca` raises `TypeError` if called with
3452 a non-X509 object.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003453 """
3454 ctx = Context(TLSv1_METHOD)
Alex Chanb7480992017-01-30 14:04:47 +00003455 with pytest.raises(TypeError):
3456 ctx.add_client_ca("spam")
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003457
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003458 def test_one_add_client_ca(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003459 """
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003460 A certificate's subject can be added as a CA to be sent to the client
Alex Chanb7480992017-01-30 14:04:47 +00003461 with `Context.add_client_ca`.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003462 """
3463 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3464 cadesc = cacert.get_subject()
Hynek Schlawack35618382015-09-05 21:54:25 +02003465
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003466 def single_ca(ctx):
3467 ctx.add_client_ca(cacert)
3468 return [cadesc]
3469 self._check_client_ca_list(single_ca)
3470
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003471 def test_multiple_add_client_ca(self):
3472 """
3473 Multiple CA names can be sent to the client by calling
Alex Chanb7480992017-01-30 14:04:47 +00003474 `Context.add_client_ca` with multiple X509 objects.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003475 """
3476 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3477 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3478
3479 cadesc = cacert.get_subject()
3480 sedesc = secert.get_subject()
3481
3482 def multiple_ca(ctx):
3483 ctx.add_client_ca(cacert)
3484 ctx.add_client_ca(secert)
3485 return [cadesc, sedesc]
3486 self._check_client_ca_list(multiple_ca)
3487
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003488 def test_set_and_add_client_ca(self):
3489 """
Alex Chanb7480992017-01-30 14:04:47 +00003490 A call to `Context.set_client_ca_list` followed by a call to
3491 `Context.add_client_ca` results in using the CA names from the
Hynek Schlawack35618382015-09-05 21:54:25 +02003492 first call and the CA name from the second call.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003493 """
3494 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3495 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3496 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3497
3498 cadesc = cacert.get_subject()
3499 sedesc = secert.get_subject()
3500 cldesc = clcert.get_subject()
3501
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003502 def mixed_set_add_ca(ctx):
3503 ctx.set_client_ca_list([cadesc, sedesc])
3504 ctx.add_client_ca(clcert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003505 return [cadesc, sedesc, cldesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003506 self._check_client_ca_list(mixed_set_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003507
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003508 def test_set_after_add_client_ca(self):
3509 """
Alex Chanb7480992017-01-30 14:04:47 +00003510 A call to `Context.set_client_ca_list` after a call to
3511 `Context.add_client_ca` replaces the CA name specified by the
Hynek Schlawack35618382015-09-05 21:54:25 +02003512 former call with the names specified by the latter call.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003513 """
3514 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3515 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3516 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3517
3518 cadesc = cacert.get_subject()
3519 sedesc = secert.get_subject()
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003520
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003521 def set_replaces_add_ca(ctx):
3522 ctx.add_client_ca(clcert)
3523 ctx.set_client_ca_list([cadesc])
3524 ctx.add_client_ca(secert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003525 return [cadesc, sedesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003526 self._check_client_ca_list(set_replaces_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003527
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003528
Alex Chanb7480992017-01-30 14:04:47 +00003529class TestInfoConstants(object):
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003530 """
3531 Tests for assorted constants exposed for use in info callbacks.
3532 """
3533 def test_integers(self):
3534 """
3535 All of the info constants are integers.
3536
3537 This is a very weak test. It would be nice to have one that actually
3538 verifies that as certain info events happen, the value passed to the
3539 info callback matches up with the constant exposed by OpenSSL.SSL.
3540 """
3541 for const in [
Alex Gaynor5af32d02016-09-24 01:52:21 -04003542 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK,
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003543 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
3544 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
3545 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
Hynek Schlawack35618382015-09-05 21:54:25 +02003546 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE
3547 ]:
Alex Gaynor5af32d02016-09-24 01:52:21 -04003548 assert isinstance(const, int)
3549
3550 # These constants don't exist on OpenSSL 1.1.0
3551 for const in [
3552 SSL_ST_INIT, SSL_ST_BEFORE, SSL_ST_OK, SSL_ST_RENEGOTIATE
3553 ]:
3554 assert const is None or isinstance(const, int)
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003555
Ziga Seilnacht44611bf2009-08-31 20:49:30 +02003556
Cory Benfield1d142142016-03-30 11:51:45 +01003557class TestRequires(object):
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003558 """
3559 Tests for the decorator factory used to conditionally raise
Cory Benfield1d142142016-03-30 11:51:45 +01003560 NotImplementedError when older OpenSSLs are used.
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003561 """
3562 def test_available(self):
3563 """
3564 When the OpenSSL functionality is available the decorated functions
3565 work appropriately.
3566 """
3567 feature_guard = _make_requires(True, "Error text")
3568 results = []
3569
3570 @feature_guard
3571 def inner():
3572 results.append(True)
3573 return True
3574
Cory Benfield2333e5e2016-03-30 14:24:16 +01003575 assert inner() is True
3576 assert [True] == results
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003577
3578 def test_unavailable(self):
3579 """
3580 When the OpenSSL functionality is not available the decorated function
3581 does not execute and NotImplementedError is raised.
3582 """
3583 feature_guard = _make_requires(False, "Error text")
3584 results = []
3585
3586 @feature_guard
3587 def inner():
3588 results.append(True)
3589 return True
3590
Cory Benfield1d142142016-03-30 11:51:45 +01003591 with pytest.raises(NotImplementedError) as e:
3592 inner()
3593
3594 assert "Error text" in str(e.value)
Cory Benfield2333e5e2016-03-30 14:24:16 +01003595 assert results == []
Cory Benfield496652a2017-01-24 11:42:56 +00003596
3597
Alex Chanb7480992017-01-30 14:04:47 +00003598class TestOCSP(object):
Cory Benfield496652a2017-01-24 11:42:56 +00003599 """
3600 Tests for PyOpenSSL's OCSP stapling support.
3601 """
3602 sample_ocsp_data = b"this is totally ocsp data"
3603
3604 def _client_connection(self, callback, data, request_ocsp=True):
3605 """
3606 Builds a client connection suitable for using OCSP.
3607
3608 :param callback: The callback to register for OCSP.
3609 :param data: The opaque data object that will be handed to the
3610 OCSP callback.
3611 :param request_ocsp: Whether the client will actually ask for OCSP
3612 stapling. Useful for testing only.
3613 """
3614 ctx = Context(SSLv23_METHOD)
3615 ctx.set_ocsp_client_callback(callback, data)
3616 client = Connection(ctx)
3617
3618 if request_ocsp:
3619 client.request_ocsp()
3620
3621 client.set_connect_state()
3622 return client
3623
3624 def _server_connection(self, callback, data):
3625 """
3626 Builds a server connection suitable for using OCSP.
3627
3628 :param callback: The callback to register for OCSP.
3629 :param data: The opaque data object that will be handed to the
3630 OCSP callback.
3631 """
3632 ctx = Context(SSLv23_METHOD)
3633 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
3634 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
3635 ctx.set_ocsp_server_callback(callback, data)
3636 server = Connection(ctx)
3637 server.set_accept_state()
3638 return server
3639
3640 def test_callbacks_arent_called_by_default(self):
3641 """
3642 If both the client and the server have registered OCSP callbacks, but
3643 the client does not send the OCSP request, neither callback gets
3644 called.
3645 """
3646 called = []
3647
3648 def ocsp_callback(*args, **kwargs):
3649 called.append((args, kwargs))
3650
3651 client = self._client_connection(
3652 callback=ocsp_callback, data=None, request_ocsp=False
3653 )
3654 server = self._server_connection(callback=ocsp_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00003655 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003656
3657 assert not called
3658
3659 def test_client_negotiates_without_server(self):
3660 """
3661 If the client wants to do OCSP but the server does not, the handshake
3662 succeeds, and the client callback fires with an empty byte string.
3663 """
3664 called = []
3665
3666 def ocsp_callback(conn, ocsp_data, ignored):
3667 called.append(ocsp_data)
3668 return True
3669
3670 client = self._client_connection(callback=ocsp_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00003671 server = loopback_server_factory(socket=None)
3672 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003673
3674 assert len(called) == 1
3675 assert called[0] == b''
3676
3677 def test_client_receives_servers_data(self):
3678 """
3679 The data the server sends in its callback is received by the client.
3680 """
3681 calls = []
3682
3683 def server_callback(*args, **kwargs):
3684 return self.sample_ocsp_data
3685
3686 def client_callback(conn, ocsp_data, ignored):
3687 calls.append(ocsp_data)
3688 return True
3689
3690 client = self._client_connection(callback=client_callback, data=None)
3691 server = self._server_connection(callback=server_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00003692 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003693
3694 assert len(calls) == 1
3695 assert calls[0] == self.sample_ocsp_data
3696
3697 def test_callbacks_are_invoked_with_connections(self):
3698 """
3699 The first arguments to both callbacks are their respective connections.
3700 """
3701 client_calls = []
3702 server_calls = []
3703
3704 def client_callback(conn, *args, **kwargs):
3705 client_calls.append(conn)
3706 return True
3707
3708 def server_callback(conn, *args, **kwargs):
3709 server_calls.append(conn)
3710 return self.sample_ocsp_data
3711
3712 client = self._client_connection(callback=client_callback, data=None)
3713 server = self._server_connection(callback=server_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00003714 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003715
3716 assert len(client_calls) == 1
3717 assert len(server_calls) == 1
3718 assert client_calls[0] is client
3719 assert server_calls[0] is server
3720
3721 def test_opaque_data_is_passed_through(self):
3722 """
3723 Both callbacks receive an opaque, user-provided piece of data in their
3724 callbacks as the final argument.
3725 """
3726 calls = []
3727
3728 def server_callback(*args):
3729 calls.append(args)
3730 return self.sample_ocsp_data
3731
3732 def client_callback(*args):
3733 calls.append(args)
3734 return True
3735
3736 sentinel = object()
3737
3738 client = self._client_connection(
3739 callback=client_callback, data=sentinel
3740 )
3741 server = self._server_connection(
3742 callback=server_callback, data=sentinel
3743 )
Alex Chanb7480992017-01-30 14:04:47 +00003744 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003745
3746 assert len(calls) == 2
3747 assert calls[0][-1] is sentinel
3748 assert calls[1][-1] is sentinel
3749
3750 def test_server_returns_empty_string(self):
3751 """
3752 If the server returns an empty bytestring from its callback, the
3753 client callback is called with the empty bytestring.
3754 """
3755 client_calls = []
3756
3757 def server_callback(*args):
3758 return b''
3759
3760 def client_callback(conn, ocsp_data, ignored):
3761 client_calls.append(ocsp_data)
3762 return True
3763
3764 client = self._client_connection(callback=client_callback, data=None)
3765 server = self._server_connection(callback=server_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00003766 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003767
3768 assert len(client_calls) == 1
3769 assert client_calls[0] == b''
3770
3771 def test_client_returns_false_terminates_handshake(self):
3772 """
3773 If the client returns False from its callback, the handshake fails.
3774 """
3775 def server_callback(*args):
3776 return self.sample_ocsp_data
3777
3778 def client_callback(*args):
3779 return False
3780
3781 client = self._client_connection(callback=client_callback, data=None)
3782 server = self._server_connection(callback=server_callback, data=None)
3783
3784 with pytest.raises(Error):
Alex Chanb7480992017-01-30 14:04:47 +00003785 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003786
3787 def test_exceptions_in_client_bubble_up(self):
3788 """
3789 The callbacks thrown in the client callback bubble up to the caller.
3790 """
3791 class SentinelException(Exception):
3792 pass
3793
3794 def server_callback(*args):
3795 return self.sample_ocsp_data
3796
3797 def client_callback(*args):
3798 raise SentinelException()
3799
3800 client = self._client_connection(callback=client_callback, data=None)
3801 server = self._server_connection(callback=server_callback, data=None)
3802
3803 with pytest.raises(SentinelException):
Alex Chanb7480992017-01-30 14:04:47 +00003804 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003805
3806 def test_exceptions_in_server_bubble_up(self):
3807 """
3808 The callbacks thrown in the server callback bubble up to the caller.
3809 """
3810 class SentinelException(Exception):
3811 pass
3812
3813 def server_callback(*args):
3814 raise SentinelException()
3815
3816 def client_callback(*args):
3817 pytest.fail("Should not be called")
3818
3819 client = self._client_connection(callback=client_callback, data=None)
3820 server = self._server_connection(callback=server_callback, data=None)
3821
3822 with pytest.raises(SentinelException):
Alex Chanb7480992017-01-30 14:04:47 +00003823 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003824
3825 def test_server_must_return_bytes(self):
3826 """
3827 The server callback must return a bytestring, or a TypeError is thrown.
3828 """
3829 def server_callback(*args):
3830 return self.sample_ocsp_data.decode('ascii')
3831
3832 def client_callback(*args):
3833 pytest.fail("Should not be called")
3834
3835 client = self._client_connection(callback=client_callback, data=None)
3836 server = self._server_connection(callback=server_callback, data=None)
3837
3838 with pytest.raises(TypeError):
Alex Chanb7480992017-01-30 14:04:47 +00003839 handshake_in_memory(client, server)