blob: d2a56b79850dffe30cc6588b3922fa8fab276207 [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
9import uuid
10
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -050011from gc import collect, get_referrers
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +020012from errno import ECONNREFUSED, EINPROGRESS, EWOULDBLOCK, EPIPE, ESHUTDOWN
Hynek Schlawackf8979a52015-09-05 21:25:25 +020013from sys import platform, getfilesystemencoding, version_info
Maximilian Hils1d95dea2015-08-17 19:27:20 +020014from socket import MSG_PEEK, SHUT_RDWR, error, socket
Jean-Paul Calderonea65cf6c2009-07-19 10:26:52 -040015from os import makedirs
Jean-Paul Calderone1461c492013-10-03 16:05:00 -040016from os.path import join
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -040017from weakref import ref
Alex Chanb7480992017-01-30 14:04:47 +000018from warnings import simplefilter
Jean-Paul Calderone460cc1f2009-03-07 11:31:12 -050019
Hynek Schlawack734d3022015-09-05 19:19:32 +020020import pytest
21
Hynek Schlawackf90e3682016-03-11 11:21:13 +010022from six import PY3, text_type
Jean-Paul Calderonec76c61c2014-01-18 13:21:52 -050023
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +010024from cryptography import x509
25from cryptography.hazmat.backends import default_backend
26from cryptography.hazmat.primitives import hashes
27from cryptography.hazmat.primitives import serialization
28from cryptography.hazmat.primitives.asymmetric import rsa
29from cryptography.x509.oid import NameOID
30
31
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040032from OpenSSL.crypto import TYPE_RSA, FILETYPE_PEM
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -080033from OpenSSL.crypto import PKey, X509, X509Extension, X509Store
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040034from OpenSSL.crypto import dump_privatekey, load_privatekey
35from OpenSSL.crypto import dump_certificate, load_certificate
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -040036from OpenSSL.crypto import get_elliptic_curves
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040037
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -040038from OpenSSL.SSL import OPENSSL_VERSION_NUMBER, SSLEAY_VERSION, SSLEAY_CFLAGS
39from OpenSSL.SSL import SSLEAY_PLATFORM, SSLEAY_DIR, SSLEAY_BUILT_ON
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -040040from OpenSSL.SSL import SENT_SHUTDOWN, RECEIVED_SHUTDOWN
Jean-Paul Calderone1461c492013-10-03 16:05:00 -040041from OpenSSL.SSL import (
42 SSLv2_METHOD, SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD,
43 TLSv1_1_METHOD, TLSv1_2_METHOD)
44from OpenSSL.SSL import OP_SINGLE_DH_USE, OP_NO_SSLv2, OP_NO_SSLv3
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040045from OpenSSL.SSL import (
46 VERIFY_PEER, VERIFY_FAIL_IF_NO_PEER_CERT, VERIFY_CLIENT_ONCE, VERIFY_NONE)
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040047
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040048from OpenSSL.SSL import (
Jean-Paul Calderone313bf012012-02-08 13:02:49 -050049 SESS_CACHE_OFF, SESS_CACHE_CLIENT, SESS_CACHE_SERVER, SESS_CACHE_BOTH,
50 SESS_CACHE_NO_AUTO_CLEAR, SESS_CACHE_NO_INTERNAL_LOOKUP,
51 SESS_CACHE_NO_INTERNAL_STORE, SESS_CACHE_NO_INTERNAL)
52
53from OpenSSL.SSL import (
Jean-Paul Calderoned899af02013-03-19 22:10:37 -070054 Error, SysCallError, WantReadError, WantWriteError, ZeroReturnError)
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -050055from OpenSSL.SSL import (
Jean-Paul Calderoned899af02013-03-19 22:10:37 -070056 Context, ContextType, Session, Connection, ConnectionType, SSLeay_version)
Cory Benfield0ba57ec2016-03-30 09:35:05 +010057from OpenSSL.SSL import _make_requires
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040058
Cory Benfieldba1820d2015-04-13 17:39:12 -040059from OpenSSL._util import lib as _lib
60
Alex Gaynord3b5d9b2016-07-31 10:54:24 -040061from OpenSSL.SSL import (
62 OP_NO_QUERY_MTU, OP_COOKIE_EXCHANGE, OP_NO_TICKET, OP_NO_COMPRESSION,
63 MODE_RELEASE_BUFFERS)
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040064
Jean-Paul Calderone1461c492013-10-03 16:05:00 -040065try:
66 from OpenSSL.SSL import OP_NO_TLSv1, OP_NO_TLSv1_1, OP_NO_TLSv1_2
67except ImportError:
68 OP_NO_TLSv1 = OP_NO_TLSv1_1 = OP_NO_TLSv1_2 = None
69
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -040070from OpenSSL.SSL import (
Alex Gaynor5af32d02016-09-24 01:52:21 -040071 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK,
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -040072 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
73 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
74 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
75 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE)
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -040076
Alex Gaynor5af32d02016-09-24 01:52:21 -040077try:
78 from OpenSSL.SSL import (
79 SSL_ST_INIT, SSL_ST_BEFORE, SSL_ST_OK, SSL_ST_RENEGOTIATE
80 )
81except ImportError:
82 SSL_ST_INIT = SSL_ST_BEFORE = SSL_ST_OK = SSL_ST_RENEGOTIATE = None
83
Alex Chanb7480992017-01-30 14:04:47 +000084from .util import WARNING_TYPE_EXPECTED, NON_ASCII, is_consistent_type
Hynek Schlawackf0e66852015-10-16 20:18:38 +020085from .test_crypto import (
86 cleartextCertificatePEM, cleartextPrivateKeyPEM,
87 client_cert_pem, client_key_pem, server_cert_pem, server_key_pem,
88 root_cert_pem)
89
Hynek Schlawackde00dd52015-09-05 19:09:26 +020090
Alex Gaynord0bdd2d2016-09-10 14:23:46 -040091# openssl dhparam 1024 -out dh-1024.pem (note that 1024 is a small number of
92# bits to use)
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -040093dhparam = """\
94-----BEGIN DH PARAMETERS-----
Alex Gaynord0bdd2d2016-09-10 14:23:46 -040095MIGHAoGBALdUMvn+C9MM+y5BWZs11mSeH6HHoEq0UVbzVq7UojC1hbsZUuGukQ3a
96Qh2/pwqb18BZFykrWB0zv/OkLa0kx4cuUgNrUVq1EFheBiX6YqryJ7t2sO09NQiO
97V7H54LmltOT/hEh6QWsJqb6BQgH65bswvV/XkYGja8/T0GzvbaVzAgEC
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -040098-----END DH PARAMETERS-----
99"""
100
101
Hynek Schlawackb4f02402015-09-05 20:48:34 +0200102skip_if_py3 = pytest.mark.skipif(PY3, reason="Python 2 only")
Hynek Schlawackf8979a52015-09-05 21:25:25 +0200103skip_if_py26 = pytest.mark.skipif(
104 version_info[0:2] == (2, 6),
105 reason="Python 2.7 and later only"
106)
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200107
108
Jean-Paul Calderone05826732015-04-12 11:38:49 -0400109def join_bytes_or_unicode(prefix, suffix):
110 """
111 Join two path components of either ``bytes`` or ``unicode``.
112
113 The return type is the same as the type of ``prefix``.
114 """
115 # If the types are the same, nothing special is necessary.
116 if type(prefix) == type(suffix):
117 return join(prefix, suffix)
118
119 # Otherwise, coerce suffix to the type of prefix.
120 if isinstance(prefix, text_type):
121 return join(prefix, suffix.decode(getfilesystemencoding()))
122 else:
123 return join(prefix, suffix.encode(getfilesystemencoding()))
124
125
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400126def verify_cb(conn, cert, errnum, depth, ok):
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400127 return ok
128
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400129
Rick Deanb1ccd562009-07-09 23:52:39 -0500130def socket_pair():
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400131 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400132 Establish and return a pair of network sockets connected to each other.
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400133 """
134 # Connect a pair of sockets
Rick Deanb1ccd562009-07-09 23:52:39 -0500135 port = socket()
136 port.bind(('', 0))
137 port.listen(1)
138 client = socket()
139 client.setblocking(False)
Jean-Paul Calderonef23c5d92009-07-23 17:58:15 -0400140 client.connect_ex(("127.0.0.1", port.getsockname()[1]))
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400141 client.setblocking(True)
Rick Deanb1ccd562009-07-09 23:52:39 -0500142 server = port.accept()[0]
Rick Deanb1ccd562009-07-09 23:52:39 -0500143
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400144 # Let's pass some unencrypted data to make sure our socket connection is
145 # fine. Just one byte, so we don't have to worry about buffers getting
146 # filled up or fragmentation.
Alex Gaynore7f51982016-09-11 11:48:14 -0400147 server.send(b"x")
148 assert client.recv(1024) == b"x"
149 client.send(b"y")
150 assert server.recv(1024) == b"y"
Rick Deanb1ccd562009-07-09 23:52:39 -0500151
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -0400152 # Most of our callers want non-blocking sockets, make it easy for them.
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400153 server.setblocking(False)
154 client.setblocking(False)
Jim Shaver46f28912015-05-29 19:32:16 -0400155
Rick Deanb1ccd562009-07-09 23:52:39 -0500156 return (server, client)
157
158
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400159def handshake(client, server):
160 conns = [client, server]
161 while conns:
162 for conn in conns:
163 try:
164 conn.do_handshake()
165 except WantReadError:
166 pass
167 else:
168 conns.remove(conn)
169
170
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400171def _create_certificate_chain():
172 """
173 Construct and return a chain of certificates.
174
175 1. A new self-signed certificate authority certificate (cacert)
176 2. A new intermediate certificate signed by cacert (icert)
177 3. A new server certificate signed by icert (scert)
178 """
Alex Gaynore7f51982016-09-11 11:48:14 -0400179 caext = X509Extension(b'basicConstraints', False, b'CA:true')
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400180
181 # Step 1
182 cakey = PKey()
Alex Gaynor0737a5e2016-09-10 14:35:09 -0400183 cakey.generate_key(TYPE_RSA, 1024)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400184 cacert = X509()
185 cacert.get_subject().commonName = "Authority Certificate"
186 cacert.set_issuer(cacert.get_subject())
187 cacert.set_pubkey(cakey)
Alex Gaynore7f51982016-09-11 11:48:14 -0400188 cacert.set_notBefore(b"20000101000000Z")
189 cacert.set_notAfter(b"20200101000000Z")
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400190 cacert.add_extensions([caext])
191 cacert.set_serial_number(0)
192 cacert.sign(cakey, "sha1")
193
194 # Step 2
195 ikey = PKey()
Alex Gaynor0737a5e2016-09-10 14:35:09 -0400196 ikey.generate_key(TYPE_RSA, 1024)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400197 icert = X509()
198 icert.get_subject().commonName = "Intermediate Certificate"
199 icert.set_issuer(cacert.get_subject())
200 icert.set_pubkey(ikey)
Alex Gaynore7f51982016-09-11 11:48:14 -0400201 icert.set_notBefore(b"20000101000000Z")
202 icert.set_notAfter(b"20200101000000Z")
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400203 icert.add_extensions([caext])
204 icert.set_serial_number(0)
205 icert.sign(cakey, "sha1")
206
207 # Step 3
208 skey = PKey()
Alex Gaynor0737a5e2016-09-10 14:35:09 -0400209 skey.generate_key(TYPE_RSA, 1024)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400210 scert = X509()
211 scert.get_subject().commonName = "Server Certificate"
212 scert.set_issuer(icert.get_subject())
213 scert.set_pubkey(skey)
Alex Gaynore7f51982016-09-11 11:48:14 -0400214 scert.set_notBefore(b"20000101000000Z")
215 scert.set_notAfter(b"20200101000000Z")
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400216 scert.add_extensions([
Alex Gaynore7f51982016-09-11 11:48:14 -0400217 X509Extension(b'basicConstraints', True, b'CA:false')])
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400218 scert.set_serial_number(0)
219 scert.sign(ikey, "sha1")
220
221 return [(cakey, cacert), (ikey, icert), (skey, scert)]
222
223
Alex Chan1c0cb662017-01-30 07:13:30 +0000224def loopback_client_factory(socket):
225 client = Connection(Context(TLSv1_METHOD), socket)
226 client.set_connect_state()
227 return client
228
229
230def loopback_server_factory(socket):
231 ctx = Context(TLSv1_METHOD)
232 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
233 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
234 server = Connection(ctx, socket)
235 server.set_accept_state()
236 return server
237
238
239def loopback(server_factory=None, client_factory=None):
240 """
241 Create a connected socket pair and force two connected SSL sockets
242 to talk to each other via memory BIOs.
243 """
244 if server_factory is None:
245 server_factory = loopback_server_factory
246 if client_factory is None:
247 client_factory = loopback_client_factory
248
249 (server, client) = socket_pair()
250 server = server_factory(server)
251 client = client_factory(client)
252
253 handshake(client, server)
254
255 server.setblocking(True)
256 client.setblocking(True)
257 return server, client
258
259
Alex Chan1ca9e3a2016-11-05 13:01:51 +0000260def interact_in_memory(client_conn, server_conn):
261 """
262 Try to read application bytes from each of the two `Connection` objects.
263 Copy bytes back and forth between their send/receive buffers for as long
264 as there is anything to copy. When there is nothing more to copy,
265 return `None`. If one of them actually manages to deliver some application
266 bytes, return a two-tuple of the connection from which the bytes were read
267 and the bytes themselves.
268 """
269 wrote = True
270 while wrote:
271 # Loop until neither side has anything to say
272 wrote = False
273
274 # Copy stuff from each side's send buffer to the other side's
275 # receive buffer.
276 for (read, write) in [(client_conn, server_conn),
277 (server_conn, client_conn)]:
278
279 # Give the side a chance to generate some more bytes, or succeed.
280 try:
281 data = read.recv(2 ** 16)
282 except WantReadError:
283 # It didn't succeed, so we'll hope it generated some output.
284 pass
285 else:
286 # It did succeed, so we'll stop now and let the caller deal
287 # with it.
288 return (read, data)
289
290 while True:
291 # Keep copying as long as there's more stuff there.
292 try:
293 dirty = read.bio_read(4096)
294 except WantReadError:
295 # Okay, nothing more waiting to be sent. Stop
296 # processing this send buffer.
297 break
298 else:
299 # Keep track of the fact that someone generated some
300 # output.
301 wrote = True
302 write.bio_write(dirty)
303
304
Alex Chan532b79e2017-01-24 15:14:52 +0000305def handshake_in_memory(client_conn, server_conn):
306 """
307 Perform the TLS handshake between two `Connection` instances connected to
308 each other via memory BIOs.
309 """
310 client_conn.set_connect_state()
311 server_conn.set_accept_state()
312
313 for conn in [client_conn, server_conn]:
314 try:
315 conn.do_handshake()
316 except WantReadError:
317 pass
318
319 interact_in_memory(client_conn, server_conn)
320
321
Alex Chanb7480992017-01-30 14:04:47 +0000322class TestVersion(object):
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400323 """
Alex Chanb7480992017-01-30 14:04:47 +0000324 Tests for version information exposed by `OpenSSL.SSL.SSLeay_version` and
325 `OpenSSL.SSL.OPENSSL_VERSION_NUMBER`.
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400326 """
327 def test_OPENSSL_VERSION_NUMBER(self):
328 """
Alex Chanb7480992017-01-30 14:04:47 +0000329 `OPENSSL_VERSION_NUMBER` is an integer with status in the low byte and
330 the patch, fix, minor, and major versions in the nibbles above that.
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400331 """
Alex Chanb7480992017-01-30 14:04:47 +0000332 assert isinstance(OPENSSL_VERSION_NUMBER, int)
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400333
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400334 def test_SSLeay_version(self):
335 """
Alex Chanb7480992017-01-30 14:04:47 +0000336 `SSLeay_version` takes a version type indicator and returns one of a
337 number of version strings based on that indicator.
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400338 """
339 versions = {}
340 for t in [SSLEAY_VERSION, SSLEAY_CFLAGS, SSLEAY_BUILT_ON,
341 SSLEAY_PLATFORM, SSLEAY_DIR]:
342 version = SSLeay_version(t)
343 versions[version] = t
Alex Chanb7480992017-01-30 14:04:47 +0000344 assert isinstance(version, bytes)
345 assert len(versions) == 5
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400346
347
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100348@pytest.fixture
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100349def ca_file(tmpdir):
350 """
351 Create a valid PEM file with CA certificates and return the path.
352 """
353 key = rsa.generate_private_key(
354 public_exponent=65537,
355 key_size=2048,
356 backend=default_backend()
357 )
358 public_key = key.public_key()
359
360 builder = x509.CertificateBuilder()
361 builder = builder.subject_name(x509.Name([
362 x509.NameAttribute(NameOID.COMMON_NAME, u"pyopenssl.org"),
363 ]))
364 builder = builder.issuer_name(x509.Name([
365 x509.NameAttribute(NameOID.COMMON_NAME, u"pyopenssl.org"),
366 ]))
367 one_day = datetime.timedelta(1, 0, 0)
368 builder = builder.not_valid_before(datetime.datetime.today() - one_day)
369 builder = builder.not_valid_after(datetime.datetime.today() + one_day)
370 builder = builder.serial_number(int(uuid.uuid4()))
371 builder = builder.public_key(public_key)
372 builder = builder.add_extension(
373 x509.BasicConstraints(ca=True, path_length=None), critical=True,
374 )
375
376 certificate = builder.sign(
377 private_key=key, algorithm=hashes.SHA256(),
378 backend=default_backend()
379 )
380
381 ca_file = tmpdir.join("test.pem")
382 ca_file.write_binary(
383 certificate.public_bytes(
384 encoding=serialization.Encoding.PEM,
385 )
386 )
387
388 return str(ca_file).encode("ascii")
389
390
391@pytest.fixture
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100392def context():
393 """
394 A simple TLS 1.0 context.
395 """
396 return Context(TLSv1_METHOD)
397
398
399class TestContext(object):
Hynek Schlawackaa861212016-03-13 13:53:48 +0100400 """
Alex Chan532b79e2017-01-24 15:14:52 +0000401 Unit tests for `OpenSSL.SSL.Context`.
Hynek Schlawackaa861212016-03-13 13:53:48 +0100402 """
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100403 @pytest.mark.parametrize("cipher_string", [
404 b"hello world:AES128-SHA",
405 u"hello world:AES128-SHA",
406 ])
407 def test_set_cipher_list(self, context, cipher_string):
408 """
Alex Chan532b79e2017-01-24 15:14:52 +0000409 `Context.set_cipher_list` accepts both byte and unicode strings
Hynek Schlawacka7a63af2016-03-11 12:05:26 +0100410 for naming the ciphers which connections created with the context
411 object will be able to choose from.
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100412 """
413 context.set_cipher_list(cipher_string)
414 conn = Connection(context, None)
415
416 assert "AES128-SHA" in conn.get_cipher_list()
417
418 @pytest.mark.parametrize("cipher_list,error", [
419 (object(), TypeError),
420 ("imaginary-cipher", Error),
421 ])
422 def test_set_cipher_list_wrong_args(self, context, cipher_list, error):
423 """
Alex Chan532b79e2017-01-24 15:14:52 +0000424 `Context.set_cipher_list` raises `TypeError` when passed a non-string
425 argument and raises `OpenSSL.SSL.Error` when passed an incorrect cipher
426 list string.
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100427 """
428 with pytest.raises(error):
429 context.set_cipher_list(cipher_list)
430
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100431 def test_load_client_ca(self, context, ca_file):
432 """
Alex Chan532b79e2017-01-24 15:14:52 +0000433 `Context.load_client_ca` works as far as we can tell.
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100434 """
435 context.load_client_ca(ca_file)
436
437 def test_load_client_ca_invalid(self, context, tmpdir):
438 """
Alex Chan532b79e2017-01-24 15:14:52 +0000439 `Context.load_client_ca` raises an Error if the ca file is invalid.
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100440 """
441 ca_file = tmpdir.join("test.pem")
442 ca_file.write("")
443
444 with pytest.raises(Error) as e:
445 context.load_client_ca(str(ca_file).encode("ascii"))
446
447 assert "PEM routines" == e.value.args[0][0][0]
448
449 def test_load_client_ca_unicode(self, context, ca_file):
450 """
451 Passing the path as unicode raises a warning but works.
452 """
453 pytest.deprecated_call(
454 context.load_client_ca, ca_file.decode("ascii")
455 )
456
457 def test_set_session_id(self, context):
458 """
Alex Chan532b79e2017-01-24 15:14:52 +0000459 `Context.set_session_id` works as far as we can tell.
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100460 """
461 context.set_session_id(b"abc")
462
463 def test_set_session_id_fail(self, context):
464 """
Alex Chan532b79e2017-01-24 15:14:52 +0000465 `Context.set_session_id` errors are propagated.
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100466 """
467 with pytest.raises(Error) as e:
468 context.set_session_id(b"abc" * 1000)
469
470 assert [
471 ("SSL routines",
472 "SSL_CTX_set_session_id_context",
473 "ssl session id context too long")
474 ] == e.value.args[0]
475
476 def test_set_session_id_unicode(self, context):
477 """
Alex Chan532b79e2017-01-24 15:14:52 +0000478 `Context.set_session_id` raises a warning if a unicode string is
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100479 passed.
480 """
481 pytest.deprecated_call(context.set_session_id, u"abc")
482
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400483 def test_method(self):
484 """
Alex Chan532b79e2017-01-24 15:14:52 +0000485 `Context` can be instantiated with one of `SSLv2_METHOD`,
486 `SSLv3_METHOD`, `SSLv23_METHOD`, `TLSv1_METHOD`, `TLSv1_1_METHOD`,
487 or `TLSv1_2_METHOD`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400488 """
Alex Gaynor5af32d02016-09-24 01:52:21 -0400489 methods = [SSLv23_METHOD, TLSv1_METHOD]
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400490 for meth in methods:
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400491 Context(meth)
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400492
Alex Gaynor5af32d02016-09-24 01:52:21 -0400493 maybe = [SSLv2_METHOD, SSLv3_METHOD, TLSv1_1_METHOD, TLSv1_2_METHOD]
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400494 for meth in maybe:
495 try:
496 Context(meth)
497 except (Error, ValueError):
498 # Some versions of OpenSSL have SSLv2 / TLSv1.1 / TLSv1.2, some
499 # don't. Difficult to say in advance.
500 pass
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400501
Alex Chan532b79e2017-01-24 15:14:52 +0000502 with pytest.raises(TypeError):
503 Context("")
504 with pytest.raises(ValueError):
505 Context(10)
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400506
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200507 @skip_if_py3
508 def test_method_long(self):
509 """
Alex Chan532b79e2017-01-24 15:14:52 +0000510 On Python 2 `Context` accepts values of type `long` as well as `int`.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200511 """
512 Context(long(TLSv1_METHOD))
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500513
Rick Deane15b1472009-07-09 15:53:42 -0500514 def test_type(self):
515 """
Alex Chan532b79e2017-01-24 15:14:52 +0000516 `Context` and `ContextType` refer to the same type object and can
517 be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -0500518 """
Alex Chan532b79e2017-01-24 15:14:52 +0000519 assert Context is ContextType
520 assert is_consistent_type(Context, 'Context', TLSv1_METHOD)
Rick Deane15b1472009-07-09 15:53:42 -0500521
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400522 def test_use_privatekey(self):
523 """
Alex Chan532b79e2017-01-24 15:14:52 +0000524 `Context.use_privatekey` takes an `OpenSSL.crypto.PKey` instance.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400525 """
526 key = PKey()
527 key.generate_key(TYPE_RSA, 128)
528 ctx = Context(TLSv1_METHOD)
529 ctx.use_privatekey(key)
Alex Chan532b79e2017-01-24 15:14:52 +0000530 with pytest.raises(TypeError):
531 ctx.use_privatekey("")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400532
Alex Chan532b79e2017-01-24 15:14:52 +0000533 def test_use_privatekey_file_missing(self, tmpfile):
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800534 """
Alex Chan532b79e2017-01-24 15:14:52 +0000535 `Context.use_privatekey_file` raises `OpenSSL.SSL.Error` when passed
536 the name of a file which does not exist.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800537 """
538 ctx = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000539 with pytest.raises(Error):
540 ctx.use_privatekey_file(tmpfile)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800541
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400542 def _use_privatekey_file_test(self, pemfile, filetype):
543 """
544 Verify that calling ``Context.use_privatekey_file`` with the given
545 arguments does not raise an exception.
546 """
547 key = PKey()
548 key.generate_key(TYPE_RSA, 128)
549
550 with open(pemfile, "wt") as pem:
551 pem.write(
552 dump_privatekey(FILETYPE_PEM, key).decode("ascii")
553 )
554
555 ctx = Context(TLSv1_METHOD)
556 ctx.use_privatekey_file(pemfile, filetype)
557
Alex Chan532b79e2017-01-24 15:14:52 +0000558 def test_use_privatekey_file_bytes(self, tmpfile):
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400559 """
560 A private key can be specified from a file by passing a ``bytes``
561 instance giving the file name to ``Context.use_privatekey_file``.
562 """
563 self._use_privatekey_file_test(
Alex Chan532b79e2017-01-24 15:14:52 +0000564 tmpfile + NON_ASCII.encode(getfilesystemencoding()),
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400565 FILETYPE_PEM,
566 )
567
Alex Chan532b79e2017-01-24 15:14:52 +0000568 def test_use_privatekey_file_unicode(self, tmpfile):
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400569 """
570 A private key can be specified from a file by passing a ``unicode``
571 instance giving the file name to ``Context.use_privatekey_file``.
572 """
573 self._use_privatekey_file_test(
Alex Chan532b79e2017-01-24 15:14:52 +0000574 tmpfile.decode(getfilesystemencoding()) + NON_ASCII,
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400575 FILETYPE_PEM,
576 )
577
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200578 @skip_if_py3
Alex Chan532b79e2017-01-24 15:14:52 +0000579 def test_use_privatekey_file_long(self, tmpfile):
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200580 """
Alex Chan532b79e2017-01-24 15:14:52 +0000581 On Python 2 `Context.use_privatekey_file` accepts a filetype of
582 type `long` as well as `int`.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200583 """
Alex Chan532b79e2017-01-24 15:14:52 +0000584 self._use_privatekey_file_test(tmpfile, long(FILETYPE_PEM))
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500585
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800586 def test_use_certificate_wrong_args(self):
587 """
Alex Chan532b79e2017-01-24 15:14:52 +0000588 `Context.use_certificate_wrong_args` raises `TypeError` when not passed
589 exactly one `OpenSSL.crypto.X509` instance as an argument.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800590 """
591 ctx = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000592 with pytest.raises(TypeError):
593 ctx.use_certificate("hello, world")
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800594
595 def test_use_certificate_uninitialized(self):
596 """
Alex Chan532b79e2017-01-24 15:14:52 +0000597 `Context.use_certificate` raises `OpenSSL.SSL.Error` when passed a
598 `OpenSSL.crypto.X509` instance which has not been initialized
599 (ie, which does not actually have any certificate data).
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800600 """
601 ctx = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000602 with pytest.raises(Error):
603 ctx.use_certificate(X509())
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800604
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800605 def test_use_certificate(self):
606 """
Alex Chan532b79e2017-01-24 15:14:52 +0000607 `Context.use_certificate` sets the certificate which will be
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800608 used to identify connections created using the context.
609 """
610 # TODO
611 # Hard to assert anything. But we could set a privatekey then ask
612 # OpenSSL if the cert and key agree using check_privatekey. Then as
613 # long as check_privatekey works right we're good...
614 ctx = Context(TLSv1_METHOD)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200615 ctx.use_certificate(
616 load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
617 )
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800618
619 def test_use_certificate_file_wrong_args(self):
620 """
Alex Chan532b79e2017-01-24 15:14:52 +0000621 `Context.use_certificate_file` raises `TypeError` if the first
622 argument is not a byte string or the second argument is not an integer.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800623 """
624 ctx = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000625 with pytest.raises(TypeError):
626 ctx.use_certificate_file(object(), FILETYPE_PEM)
627 with pytest.raises(TypeError):
628 ctx.use_certificate_file(b"somefile", object())
629 with pytest.raises(TypeError):
630 ctx.use_certificate_file(object(), FILETYPE_PEM)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800631
Alex Chan532b79e2017-01-24 15:14:52 +0000632 def test_use_certificate_file_missing(self, tmpfile):
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800633 """
Alex Chan532b79e2017-01-24 15:14:52 +0000634 `Context.use_certificate_file` raises `OpenSSL.SSL.Error` if passed
635 the name of a file which does not exist.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800636 """
637 ctx = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000638 with pytest.raises(Error):
639 ctx.use_certificate_file(tmpfile)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800640
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400641 def _use_certificate_file_test(self, certificate_file):
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800642 """
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400643 Verify that calling ``Context.use_certificate_file`` with the given
644 filename doesn't raise an exception.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800645 """
646 # TODO
647 # Hard to assert anything. But we could set a privatekey then ask
648 # OpenSSL if the cert and key agree using check_privatekey. Then as
649 # long as check_privatekey works right we're good...
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400650 with open(certificate_file, "wb") as pem_file:
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800651 pem_file.write(cleartextCertificatePEM)
652
653 ctx = Context(TLSv1_METHOD)
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400654 ctx.use_certificate_file(certificate_file)
655
Alex Chan532b79e2017-01-24 15:14:52 +0000656 def test_use_certificate_file_bytes(self, tmpfile):
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400657 """
Alex Chan532b79e2017-01-24 15:14:52 +0000658 `Context.use_certificate_file` sets the certificate (given as a
659 `bytes` filename) which will be used to identify connections created
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400660 using the context.
661 """
Alex Chan532b79e2017-01-24 15:14:52 +0000662 filename = tmpfile + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400663 self._use_certificate_file_test(filename)
664
Alex Chan532b79e2017-01-24 15:14:52 +0000665 def test_use_certificate_file_unicode(self, tmpfile):
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400666 """
Alex Chan532b79e2017-01-24 15:14:52 +0000667 `Context.use_certificate_file` sets the certificate (given as a
668 `bytes` filename) which will be used to identify connections created
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400669 using the context.
670 """
Alex Chan532b79e2017-01-24 15:14:52 +0000671 filename = tmpfile.decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400672 self._use_certificate_file_test(filename)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800673
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200674 @skip_if_py3
Alex Chan532b79e2017-01-24 15:14:52 +0000675 def test_use_certificate_file_long(self, tmpfile):
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200676 """
Alex Chan532b79e2017-01-24 15:14:52 +0000677 On Python 2 `Context.use_certificate_file` accepts a
678 filetype of type `long` as well as `int`.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200679 """
Alex Chan532b79e2017-01-24 15:14:52 +0000680 pem_filename = tmpfile
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200681 with open(pem_filename, "wb") as pem_file:
682 pem_file.write(cleartextCertificatePEM)
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500683
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200684 ctx = Context(TLSv1_METHOD)
685 ctx.use_certificate_file(pem_filename, long(FILETYPE_PEM))
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500686
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500687 def test_check_privatekey_valid(self):
688 """
Alex Chan532b79e2017-01-24 15:14:52 +0000689 `Context.check_privatekey` returns `None` if the `Context` instance
690 has been configured to use a matched key and certificate pair.
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500691 """
692 key = load_privatekey(FILETYPE_PEM, client_key_pem)
693 cert = load_certificate(FILETYPE_PEM, client_cert_pem)
694 context = Context(TLSv1_METHOD)
695 context.use_privatekey(key)
696 context.use_certificate(cert)
Alex Chan532b79e2017-01-24 15:14:52 +0000697 assert None is context.check_privatekey()
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500698
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500699 def test_check_privatekey_invalid(self):
700 """
Alex Chan532b79e2017-01-24 15:14:52 +0000701 `Context.check_privatekey` raises `Error` if the `Context` instance
702 has been configured to use a key and certificate pair which don't
703 relate to each other.
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500704 """
705 key = load_privatekey(FILETYPE_PEM, client_key_pem)
706 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
707 context = Context(TLSv1_METHOD)
708 context.use_privatekey(key)
709 context.use_certificate(cert)
Alex Chan532b79e2017-01-24 15:14:52 +0000710 with pytest.raises(Error):
711 context.check_privatekey()
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400712
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400713 def test_app_data(self):
714 """
Alex Chan532b79e2017-01-24 15:14:52 +0000715 `Context.set_app_data` stores an object for later retrieval
716 using `Context.get_app_data`.
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400717 """
718 app_data = object()
719 context = Context(TLSv1_METHOD)
720 context.set_app_data(app_data)
Alex Chan532b79e2017-01-24 15:14:52 +0000721 assert context.get_app_data() is app_data
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400722
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400723 def test_set_options_wrong_args(self):
724 """
Alex Chan532b79e2017-01-24 15:14:52 +0000725 `Context.set_options` raises `TypeError` if called with
726 a non-`int` argument.
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400727 """
728 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000729 with pytest.raises(TypeError):
730 context.set_options(None)
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400731
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500732 def test_set_options(self):
733 """
Alex Chan532b79e2017-01-24 15:14:52 +0000734 `Context.set_options` returns the new options value.
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500735 """
736 context = Context(TLSv1_METHOD)
737 options = context.set_options(OP_NO_SSLv2)
Alex Gaynor2310f8b2016-09-10 14:39:32 -0400738 assert options & OP_NO_SSLv2 == OP_NO_SSLv2
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500739
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200740 @skip_if_py3
741 def test_set_options_long(self):
742 """
Alex Chan532b79e2017-01-24 15:14:52 +0000743 On Python 2 `Context.set_options` accepts values of type
744 `long` as well as `int`.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200745 """
746 context = Context(TLSv1_METHOD)
747 options = context.set_options(long(OP_NO_SSLv2))
Alex Gaynor2310f8b2016-09-10 14:39:32 -0400748 assert options & OP_NO_SSLv2 == OP_NO_SSLv2
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500749
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300750 def test_set_mode_wrong_args(self):
751 """
Alex Chan532b79e2017-01-24 15:14:52 +0000752 `Context.set_mode` raises `TypeError` if called with
753 a non-`int` argument.
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300754 """
755 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000756 with pytest.raises(TypeError):
757 context.set_mode(None)
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300758
Alex Gaynord3b5d9b2016-07-31 10:54:24 -0400759 def test_set_mode(self):
760 """
Alex Chan532b79e2017-01-24 15:14:52 +0000761 `Context.set_mode` accepts a mode bitvector and returns the
Alex Gaynord3b5d9b2016-07-31 10:54:24 -0400762 newly set mode.
763 """
764 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000765 assert MODE_RELEASE_BUFFERS & context.set_mode(MODE_RELEASE_BUFFERS)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500766
Alex Gaynord3b5d9b2016-07-31 10:54:24 -0400767 @skip_if_py3
768 def test_set_mode_long(self):
769 """
Alex Chan532b79e2017-01-24 15:14:52 +0000770 On Python 2 `Context.set_mode` accepts values of type `long` as well
771 as `int`.
Alex Gaynord3b5d9b2016-07-31 10:54:24 -0400772 """
773 context = Context(TLSv1_METHOD)
774 mode = context.set_mode(long(MODE_RELEASE_BUFFERS))
Alex Chan532b79e2017-01-24 15:14:52 +0000775 assert MODE_RELEASE_BUFFERS & mode
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400776
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400777 def test_set_timeout_wrong_args(self):
778 """
Alex Chan532b79e2017-01-24 15:14:52 +0000779 `Context.set_timeout` raises `TypeError` if called with
780 a non-`int` argument.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400781 """
782 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000783 with pytest.raises(TypeError):
784 context.set_timeout(None)
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400785
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400786 def test_timeout(self):
787 """
Alex Chan532b79e2017-01-24 15:14:52 +0000788 `Context.set_timeout` sets the session timeout for all connections
789 created using the context object. `Context.get_timeout` retrieves
790 this value.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400791 """
792 context = Context(TLSv1_METHOD)
793 context.set_timeout(1234)
Alex Chan532b79e2017-01-24 15:14:52 +0000794 assert context.get_timeout() == 1234
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400795
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200796 @skip_if_py3
797 def test_timeout_long(self):
798 """
Alex Chan532b79e2017-01-24 15:14:52 +0000799 On Python 2 `Context.set_timeout` accepts values of type `long` as
800 well as int.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200801 """
802 context = Context(TLSv1_METHOD)
803 context.set_timeout(long(1234))
Alex Chan532b79e2017-01-24 15:14:52 +0000804 assert context.get_timeout() == 1234
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500805
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400806 def test_set_verify_depth_wrong_args(self):
807 """
Alex Chan532b79e2017-01-24 15:14:52 +0000808 `Context.set_verify_depth` raises `TypeError` if called with a
809 non-`int` argument.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400810 """
811 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000812 with pytest.raises(TypeError):
813 context.set_verify_depth(None)
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400814
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400815 def test_verify_depth(self):
816 """
Alex Chan532b79e2017-01-24 15:14:52 +0000817 `Context.set_verify_depth` sets the number of certificates in
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200818 a chain to follow before giving up. The value can be retrieved with
Alex Chan532b79e2017-01-24 15:14:52 +0000819 `Context.get_verify_depth`.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400820 """
821 context = Context(TLSv1_METHOD)
822 context.set_verify_depth(11)
Alex Chan532b79e2017-01-24 15:14:52 +0000823 assert context.get_verify_depth() == 11
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400824
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200825 @skip_if_py3
826 def test_verify_depth_long(self):
827 """
Alex Chan532b79e2017-01-24 15:14:52 +0000828 On Python 2 `Context.set_verify_depth` accepts values of type `long`
829 as well as int.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200830 """
831 context = Context(TLSv1_METHOD)
832 context.set_verify_depth(long(11))
Alex Chan532b79e2017-01-24 15:14:52 +0000833 assert context.get_verify_depth() == 11
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500834
Alex Chan532b79e2017-01-24 15:14:52 +0000835 def _write_encrypted_pem(self, passphrase, tmpfile):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400836 """
837 Write a new private key out to a new file, encrypted using the given
838 passphrase. Return the path to the new file.
839 """
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400840 key = PKey()
841 key.generate_key(TYPE_RSA, 128)
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400842 pem = dump_privatekey(FILETYPE_PEM, key, "blowfish", passphrase)
Alex Chan532b79e2017-01-24 15:14:52 +0000843 with open(tmpfile, 'w') as fObj:
844 fObj.write(pem.decode('ascii'))
845 return tmpfile
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400846
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400847 def test_set_passwd_cb_wrong_args(self):
848 """
Alex Chan532b79e2017-01-24 15:14:52 +0000849 `Context.set_passwd_cb` raises `TypeError` if called with a
850 non-callable first argument.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400851 """
852 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000853 with pytest.raises(TypeError):
854 context.set_passwd_cb(None)
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400855
Alex Chan532b79e2017-01-24 15:14:52 +0000856 def test_set_passwd_cb(self, tmpfile):
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400857 """
Alex Chan532b79e2017-01-24 15:14:52 +0000858 `Context.set_passwd_cb` accepts a callable which will be invoked when
859 a private key is loaded from an encrypted PEM.
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400860 """
Alex Gaynore7f51982016-09-11 11:48:14 -0400861 passphrase = b"foobar"
Alex Chan532b79e2017-01-24 15:14:52 +0000862 pemFile = self._write_encrypted_pem(passphrase, tmpfile)
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400863 calledWith = []
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200864
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400865 def passphraseCallback(maxlen, verify, extra):
866 calledWith.append((maxlen, verify, extra))
867 return passphrase
868 context = Context(TLSv1_METHOD)
869 context.set_passwd_cb(passphraseCallback)
870 context.use_privatekey_file(pemFile)
Alex Chan532b79e2017-01-24 15:14:52 +0000871 assert len(calledWith) == 1
872 assert isinstance(calledWith[0][0], int)
873 assert isinstance(calledWith[0][1], int)
874 assert calledWith[0][2] is None
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400875
Alex Chan532b79e2017-01-24 15:14:52 +0000876 def test_passwd_callback_exception(self, tmpfile):
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400877 """
Alex Chan532b79e2017-01-24 15:14:52 +0000878 `Context.use_privatekey_file` propagates any exception raised
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200879 by the passphrase callback.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400880 """
Alex Chan532b79e2017-01-24 15:14:52 +0000881 pemFile = self._write_encrypted_pem(b"monkeys are nice", tmpfile)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200882
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400883 def passphraseCallback(maxlen, verify, extra):
884 raise RuntimeError("Sorry, I am a fail.")
885
886 context = Context(TLSv1_METHOD)
887 context.set_passwd_cb(passphraseCallback)
Alex Chan532b79e2017-01-24 15:14:52 +0000888 with pytest.raises(RuntimeError):
889 context.use_privatekey_file(pemFile)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400890
Alex Chan532b79e2017-01-24 15:14:52 +0000891 def test_passwd_callback_false(self, tmpfile):
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400892 """
Alex Chan532b79e2017-01-24 15:14:52 +0000893 `Context.use_privatekey_file` raises `OpenSSL.SSL.Error` if the
894 passphrase callback returns a false value.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400895 """
Alex Chan532b79e2017-01-24 15:14:52 +0000896 pemFile = self._write_encrypted_pem(b"monkeys are nice", tmpfile)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200897
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400898 def passphraseCallback(maxlen, verify, extra):
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500899 return b""
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400900
901 context = Context(TLSv1_METHOD)
902 context.set_passwd_cb(passphraseCallback)
Alex Chan532b79e2017-01-24 15:14:52 +0000903 with pytest.raises(Error):
904 context.use_privatekey_file(pemFile)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400905
Alex Chan532b79e2017-01-24 15:14:52 +0000906 def test_passwd_callback_non_string(self, tmpfile):
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400907 """
Alex Chan532b79e2017-01-24 15:14:52 +0000908 `Context.use_privatekey_file` raises `OpenSSL.SSL.Error` if the
909 passphrase callback returns a true non-string value.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400910 """
Alex Chan532b79e2017-01-24 15:14:52 +0000911 pemFile = self._write_encrypted_pem(b"monkeys are nice", tmpfile)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200912
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400913 def passphraseCallback(maxlen, verify, extra):
914 return 10
915
916 context = Context(TLSv1_METHOD)
917 context.set_passwd_cb(passphraseCallback)
Alex Chan532b79e2017-01-24 15:14:52 +0000918 # TODO: Surely this is the wrong error?
919 with pytest.raises(ValueError):
920 context.use_privatekey_file(pemFile)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400921
Alex Chan532b79e2017-01-24 15:14:52 +0000922 def test_passwd_callback_too_long(self, tmpfile):
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400923 """
924 If the passphrase returned by the passphrase callback returns a string
925 longer than the indicated maximum length, it is truncated.
926 """
927 # A priori knowledge!
Alex Gaynore7f51982016-09-11 11:48:14 -0400928 passphrase = b"x" * 1024
Alex Chan532b79e2017-01-24 15:14:52 +0000929 pemFile = self._write_encrypted_pem(passphrase, tmpfile)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200930
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400931 def passphraseCallback(maxlen, verify, extra):
932 assert maxlen == 1024
Alex Gaynore7f51982016-09-11 11:48:14 -0400933 return passphrase + b"y"
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400934
935 context = Context(TLSv1_METHOD)
936 context.set_passwd_cb(passphraseCallback)
937 # This shall succeed because the truncated result is the correct
938 # passphrase.
939 context.use_privatekey_file(pemFile)
940
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400941 def test_set_info_callback(self):
942 """
Alex Chan532b79e2017-01-24 15:14:52 +0000943 `Context.set_info_callback` accepts a callable which will be
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200944 invoked when certain information about an SSL connection is available.
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400945 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500946 (server, client) = socket_pair()
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400947
948 clientSSL = Connection(Context(TLSv1_METHOD), client)
949 clientSSL.set_connect_state()
950
951 called = []
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200952
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400953 def info(conn, where, ret):
954 called.append((conn, where, ret))
955 context = Context(TLSv1_METHOD)
956 context.set_info_callback(info)
957 context.use_certificate(
958 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
959 context.use_privatekey(
960 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
961
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400962 serverSSL = Connection(context, server)
963 serverSSL.set_accept_state()
964
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -0500965 handshake(clientSSL, serverSSL)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400966
Jean-Paul Calderone3835e522014-02-02 11:12:30 -0500967 # The callback must always be called with a Connection instance as the
968 # first argument. It would probably be better to split this into
969 # separate tests for client and server side info callbacks so we could
970 # assert it is called with the right Connection instance. It would
971 # also be good to assert *something* about `where` and `ret`.
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -0500972 notConnections = [
973 conn for (conn, where, ret) in called
974 if not isinstance(conn, Connection)]
Alex Chan532b79e2017-01-24 15:14:52 +0000975 assert [] == notConnections, (
976 "Some info callback arguments were not Connection instances.")
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400977
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400978 def _load_verify_locations_test(self, *args):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400979 """
980 Create a client context which will verify the peer certificate and call
Alex Chan532b79e2017-01-24 15:14:52 +0000981 its `load_verify_locations` method with the given arguments.
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -0400982 Then connect it to a server and ensure that the handshake succeeds.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400983 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500984 (server, client) = socket_pair()
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400985
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400986 clientContext = Context(TLSv1_METHOD)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400987 clientContext.load_verify_locations(*args)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400988 # Require that the server certificate verify properly or the
989 # connection will fail.
990 clientContext.set_verify(
991 VERIFY_PEER,
992 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
993
994 clientSSL = Connection(clientContext, client)
995 clientSSL.set_connect_state()
996
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400997 serverContext = Context(TLSv1_METHOD)
998 serverContext.use_certificate(
999 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1000 serverContext.use_privatekey(
1001 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1002
1003 serverSSL = Connection(serverContext, server)
1004 serverSSL.set_accept_state()
1005
Jean-Paul Calderonef8742032010-09-25 00:00:32 -04001006 # Without load_verify_locations above, the handshake
1007 # will fail:
1008 # Error: [('SSL routines', 'SSL3_GET_SERVER_CERTIFICATE',
1009 # 'certificate verify failed')]
1010 handshake(clientSSL, serverSSL)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001011
1012 cert = clientSSL.get_peer_certificate()
Alex Chan532b79e2017-01-24 15:14:52 +00001013 assert cert.get_subject().CN == 'Testing Root CA'
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -04001014
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001015 def _load_verify_cafile(self, cafile):
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001016 """
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001017 Verify that if path to a file containing a certificate is passed to
Alex Chan532b79e2017-01-24 15:14:52 +00001018 `Context.load_verify_locations` for the ``cafile`` parameter, that
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001019 certificate is used as a trust root for the purposes of verifying
Alex Chan532b79e2017-01-24 15:14:52 +00001020 connections created using that `Context`.
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001021 """
Alex Chan532b79e2017-01-24 15:14:52 +00001022 with open(cafile, 'w') as fObj:
1023 fObj.write(cleartextCertificatePEM.decode('ascii'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001024
1025 self._load_verify_locations_test(cafile)
1026
Alex Chan532b79e2017-01-24 15:14:52 +00001027 def test_load_verify_bytes_cafile(self, tmpfile):
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001028 """
Alex Chan532b79e2017-01-24 15:14:52 +00001029 `Context.load_verify_locations` accepts a file name as a `bytes`
1030 instance and uses the certificates within for verification purposes.
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001031 """
Alex Chan532b79e2017-01-24 15:14:52 +00001032 cafile = tmpfile + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001033 self._load_verify_cafile(cafile)
1034
Alex Chan532b79e2017-01-24 15:14:52 +00001035 def test_load_verify_unicode_cafile(self, tmpfile):
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001036 """
Alex Chan532b79e2017-01-24 15:14:52 +00001037 `Context.load_verify_locations` accepts a file name as a `unicode`
1038 instance and uses the certificates within for verification purposes.
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001039 """
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001040 self._load_verify_cafile(
Alex Chan532b79e2017-01-24 15:14:52 +00001041 tmpfile.decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001042 )
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001043
Alex Chan532b79e2017-01-24 15:14:52 +00001044 def test_load_verify_invalid_file(self, tmpfile):
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -04001045 """
Alex Chan532b79e2017-01-24 15:14:52 +00001046 `Context.load_verify_locations` raises `Error` when passed a
1047 non-existent cafile.
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -04001048 """
1049 clientContext = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001050 with pytest.raises(Error):
1051 clientContext.load_verify_locations(tmpfile)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001052
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001053 def _load_verify_directory_locations_capath(self, capath):
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001054 """
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001055 Verify that if path to a directory containing certificate files is
1056 passed to ``Context.load_verify_locations`` for the ``capath``
1057 parameter, those certificates are used as trust roots for the purposes
1058 of verifying connections created using that ``Context``.
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001059 """
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001060 makedirs(capath)
Jean-Paul Calderone24dfb332011-05-04 18:10:26 -04001061 # Hash values computed manually with c_rehash to avoid depending on
1062 # c_rehash in the test suite. One is from OpenSSL 0.9.8, the other
1063 # from OpenSSL 1.0.0.
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001064 for name in [b'c7adac82.0', b'c3705638.0']:
Jean-Paul Calderone05826732015-04-12 11:38:49 -04001065 cafile = join_bytes_or_unicode(capath, name)
1066 with open(cafile, 'w') as fObj:
1067 fObj.write(cleartextCertificatePEM.decode('ascii'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001068
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001069 self._load_verify_locations_test(None, capath)
1070
Alex Chan532b79e2017-01-24 15:14:52 +00001071 def test_load_verify_directory_bytes_capath(self, tmpfile):
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001072 """
Alex Chan532b79e2017-01-24 15:14:52 +00001073 `Context.load_verify_locations` accepts a directory name as a `bytes`
1074 instance and uses the certificates within for verification purposes.
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001075 """
1076 self._load_verify_directory_locations_capath(
Alex Chan532b79e2017-01-24 15:14:52 +00001077 tmpfile + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001078 )
1079
Alex Chan532b79e2017-01-24 15:14:52 +00001080 def test_load_verify_directory_unicode_capath(self, tmpfile):
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001081 """
Alex Chan532b79e2017-01-24 15:14:52 +00001082 `Context.load_verify_locations` accepts a directory name as a `unicode`
1083 instance and uses the certificates within for verification purposes.
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001084 """
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001085 self._load_verify_directory_locations_capath(
Alex Chan532b79e2017-01-24 15:14:52 +00001086 tmpfile.decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001087 )
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001088
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001089 def test_load_verify_locations_wrong_args(self):
1090 """
Alex Chan532b79e2017-01-24 15:14:52 +00001091 `Context.load_verify_locations` raises `TypeError` if with non-`str`
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001092 arguments.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001093 """
1094 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001095 with pytest.raises(TypeError):
1096 context.load_verify_locations(object())
1097 with pytest.raises(TypeError):
1098 context.load_verify_locations(object(), object())
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001099
Hynek Schlawack734d3022015-09-05 19:19:32 +02001100 @pytest.mark.skipif(
1101 platform == "win32",
1102 reason="set_default_verify_paths appears not to work on Windows. "
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -04001103 "See LP#404343 and LP#404344."
Hynek Schlawack734d3022015-09-05 19:19:32 +02001104 )
1105 def test_set_default_verify_paths(self):
1106 """
Alex Chan532b79e2017-01-24 15:14:52 +00001107 `Context.set_default_verify_paths` causes the platform-specific CA
1108 certificate locations to be used for verification purposes.
Hynek Schlawack734d3022015-09-05 19:19:32 +02001109 """
1110 # Testing this requires a server with a certificate signed by one
1111 # of the CAs in the platform CA location. Getting one of those
1112 # costs money. Fortunately (or unfortunately, depending on your
1113 # perspective), it's easy to think of a public server on the
1114 # internet which has such a certificate. Connecting to the network
1115 # in a unit test is bad, but it's the only way I can think of to
1116 # really test this. -exarkun
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001117
Hynek Schlawack734d3022015-09-05 19:19:32 +02001118 # Arg, verisign.com doesn't speak anything newer than TLS 1.0
Hynek Schlawackbf887932015-10-21 17:13:47 +02001119 context = Context(SSLv23_METHOD)
Hynek Schlawack734d3022015-09-05 19:19:32 +02001120 context.set_default_verify_paths()
1121 context.set_verify(
1122 VERIFY_PEER,
1123 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001124
Hynek Schlawack734d3022015-09-05 19:19:32 +02001125 client = socket()
Hynek Schlawackbf887932015-10-21 17:13:47 +02001126 client.connect(("encrypted.google.com", 443))
Hynek Schlawack734d3022015-09-05 19:19:32 +02001127 clientSSL = Connection(context, client)
1128 clientSSL.set_connect_state()
1129 clientSSL.do_handshake()
1130 clientSSL.send(b"GET / HTTP/1.0\r\n\r\n")
Alex Chan532b79e2017-01-24 15:14:52 +00001131 assert clientSSL.recv(1024)
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05001132
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001133 def test_add_extra_chain_cert_invalid_cert(self):
1134 """
Alex Chan532b79e2017-01-24 15:14:52 +00001135 `Context.add_extra_chain_cert` raises `TypeError` if called with an
1136 object which is not an instance of `X509`.
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001137 """
1138 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001139 with pytest.raises(TypeError):
1140 context.add_extra_chain_cert(object())
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001141
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001142 def _handshake_test(self, serverContext, clientContext):
1143 """
1144 Verify that a client and server created with the given contexts can
1145 successfully handshake and communicate.
1146 """
1147 serverSocket, clientSocket = socket_pair()
1148
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001149 server = Connection(serverContext, serverSocket)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001150 server.set_accept_state()
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001151
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001152 client = Connection(clientContext, clientSocket)
1153 client.set_connect_state()
1154
1155 # Make them talk to each other.
Alex Chan532b79e2017-01-24 15:14:52 +00001156 # interact_in_memory(client, server)
1157 for _ in range(3):
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001158 for s in [client, server]:
1159 try:
1160 s.do_handshake()
1161 except WantReadError:
1162 pass
1163
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001164 def test_set_verify_callback_connection_argument(self):
1165 """
1166 The first argument passed to the verify callback is the
Alex Chan532b79e2017-01-24 15:14:52 +00001167 `Connection` instance for which verification is taking place.
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001168 """
1169 serverContext = Context(TLSv1_METHOD)
1170 serverContext.use_privatekey(
1171 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1172 serverContext.use_certificate(
1173 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1174 serverConnection = Connection(serverContext, None)
1175
1176 class VerifyCallback(object):
1177 def callback(self, connection, *args):
1178 self.connection = connection
1179 return 1
1180
1181 verify = VerifyCallback()
1182 clientContext = Context(TLSv1_METHOD)
1183 clientContext.set_verify(VERIFY_PEER, verify.callback)
1184 clientConnection = Connection(clientContext, None)
1185 clientConnection.set_connect_state()
1186
Alex Chan532b79e2017-01-24 15:14:52 +00001187 handshake_in_memory(clientConnection, serverConnection)
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001188
Alex Chan532b79e2017-01-24 15:14:52 +00001189 assert verify.connection is clientConnection
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001190
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001191 def test_set_verify_callback_exception(self):
1192 """
Alex Chan532b79e2017-01-24 15:14:52 +00001193 If the verify callback passed to `Context.set_verify` raises an
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001194 exception, verification fails and the exception is propagated to the
Alex Chan532b79e2017-01-24 15:14:52 +00001195 caller of `Connection.do_handshake`.
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001196 """
1197 serverContext = Context(TLSv1_METHOD)
1198 serverContext.use_privatekey(
1199 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1200 serverContext.use_certificate(
1201 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1202
1203 clientContext = Context(TLSv1_METHOD)
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001204
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001205 def verify_callback(*args):
1206 raise Exception("silly verify failure")
1207 clientContext.set_verify(VERIFY_PEER, verify_callback)
1208
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01001209 with pytest.raises(Exception) as exc:
1210 self._handshake_test(serverContext, clientContext)
1211
Alex Chan532b79e2017-01-24 15:14:52 +00001212 assert "silly verify failure" == str(exc.value)
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001213
Alex Chan532b79e2017-01-24 15:14:52 +00001214 def test_add_extra_chain_cert(self, tmpdir):
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001215 """
Alex Chan532b79e2017-01-24 15:14:52 +00001216 `Context.add_extra_chain_cert` accepts an `X509`
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001217 instance to add to the certificate chain.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001218
Alex Chan532b79e2017-01-24 15:14:52 +00001219 See `_create_certificate_chain` for the details of the
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001220 certificate chain tested.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001221
1222 The chain is tested by starting a server with scert and connecting
1223 to it with a client which trusts cacert and requires verification to
1224 succeed.
1225 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001226 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001227 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1228
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001229 # Dump the CA certificate to a file because that's the only way to load
1230 # it as a trusted CA in the client context.
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001231 for cert, name in [(cacert, 'ca.pem'),
1232 (icert, 'i.pem'),
1233 (scert, 's.pem')]:
Alex Chan532b79e2017-01-24 15:14:52 +00001234 with tmpdir.join(name).open('w') as f:
Hynek Schlawacke90680f2015-04-16 15:09:27 -04001235 f.write(dump_certificate(FILETYPE_PEM, cert).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001236
Hynek Schlawack1902c012015-04-16 15:06:41 -04001237 for key, name in [(cakey, 'ca.key'),
1238 (ikey, 'i.key'),
1239 (skey, 's.key')]:
Alex Chan532b79e2017-01-24 15:14:52 +00001240 with tmpdir.join(name).open('w') as f:
Hynek Schlawacke90680f2015-04-16 15:09:27 -04001241 f.write(dump_privatekey(FILETYPE_PEM, key).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001242
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001243 # Create the server context
1244 serverContext = Context(TLSv1_METHOD)
1245 serverContext.use_privatekey(skey)
1246 serverContext.use_certificate(scert)
Jean-Paul Calderone16cf03d2010-09-08 18:53:39 -04001247 # The client already has cacert, we only need to give them icert.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001248 serverContext.add_extra_chain_cert(icert)
1249
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001250 # Create the client
1251 clientContext = Context(TLSv1_METHOD)
1252 clientContext.set_verify(
1253 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Alex Chan532b79e2017-01-24 15:14:52 +00001254 clientContext.load_verify_locations(str(tmpdir.join("ca.pem")))
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001255
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001256 # Try it out.
1257 self._handshake_test(serverContext, clientContext)
1258
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001259 def _use_certificate_chain_file_test(self, certdir):
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001260 """
Alex Chan532b79e2017-01-24 15:14:52 +00001261 Verify that `Context.use_certificate_chain_file` reads a
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001262 certificate chain from a specified file.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001263
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001264 The chain is tested by starting a server with scert and connecting to
1265 it with a client which trusts cacert and requires verification to
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001266 succeed.
1267 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001268 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001269 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1270
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001271 makedirs(certdir)
1272
Jean-Paul Calderone05826732015-04-12 11:38:49 -04001273 chainFile = join_bytes_or_unicode(certdir, "chain.pem")
1274 caFile = join_bytes_or_unicode(certdir, "ca.pem")
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001275
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001276 # Write out the chain file.
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001277 with open(chainFile, 'wb') as fObj:
1278 # Most specific to least general.
1279 fObj.write(dump_certificate(FILETYPE_PEM, scert))
1280 fObj.write(dump_certificate(FILETYPE_PEM, icert))
1281 fObj.write(dump_certificate(FILETYPE_PEM, cacert))
1282
1283 with open(caFile, 'w') as fObj:
1284 fObj.write(dump_certificate(FILETYPE_PEM, cacert).decode('ascii'))
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001285
1286 serverContext = Context(TLSv1_METHOD)
1287 serverContext.use_certificate_chain_file(chainFile)
1288 serverContext.use_privatekey(skey)
1289
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001290 clientContext = Context(TLSv1_METHOD)
1291 clientContext.set_verify(
1292 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001293 clientContext.load_verify_locations(caFile)
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001294
1295 self._handshake_test(serverContext, clientContext)
1296
Alex Chan532b79e2017-01-24 15:14:52 +00001297 def test_use_certificate_chain_file_bytes(self, tmpfile):
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001298 """
1299 ``Context.use_certificate_chain_file`` accepts the name of a file (as
1300 an instance of ``bytes``) to specify additional certificates to use to
1301 construct and verify a trust chain.
1302 """
1303 self._use_certificate_chain_file_test(
Alex Chan532b79e2017-01-24 15:14:52 +00001304 tmpfile + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001305 )
1306
Alex Chan532b79e2017-01-24 15:14:52 +00001307 def test_use_certificate_chain_file_unicode(self, tmpfile):
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001308 """
1309 ``Context.use_certificate_chain_file`` accepts the name of a file (as
1310 an instance of ``unicode``) to specify additional certificates to use
1311 to construct and verify a trust chain.
1312 """
1313 self._use_certificate_chain_file_test(
Alex Chan532b79e2017-01-24 15:14:52 +00001314 tmpfile.decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001315 )
1316
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001317 def test_use_certificate_chain_file_wrong_args(self):
1318 """
Alex Chan532b79e2017-01-24 15:14:52 +00001319 `Context.use_certificate_chain_file` raises `TypeError` if passed a
1320 non-byte string single argument.
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001321 """
1322 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001323 with pytest.raises(TypeError):
1324 context.use_certificate_chain_file(object())
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001325
Alex Chan532b79e2017-01-24 15:14:52 +00001326 def test_use_certificate_chain_file_missing_file(self, tmpfile):
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001327 """
Alex Chan532b79e2017-01-24 15:14:52 +00001328 `Context.use_certificate_chain_file` raises `OpenSSL.SSL.Error` when
1329 passed a bad chain file name (for example, the name of a file which
1330 does not exist).
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001331 """
1332 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001333 with pytest.raises(Error):
1334 context.use_certificate_chain_file(tmpfile)
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001335
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001336 def test_set_verify_mode(self):
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001337 """
Alex Chan532b79e2017-01-24 15:14:52 +00001338 `Context.get_verify_mode` returns the verify mode flags previously
1339 passed to `Context.set_verify`.
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001340 """
1341 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001342 assert context.get_verify_mode() == 0
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001343 context.set_verify(
1344 VERIFY_PEER | VERIFY_CLIENT_ONCE, lambda *args: None)
Alex Chan532b79e2017-01-24 15:14:52 +00001345 assert context.get_verify_mode() == (VERIFY_PEER | VERIFY_CLIENT_ONCE)
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001346
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001347 @skip_if_py3
1348 def test_set_verify_mode_long(self):
1349 """
Alex Chan532b79e2017-01-24 15:14:52 +00001350 On Python 2 `Context.set_verify_mode` accepts values of type `long`
1351 as well as `int`.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001352 """
1353 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001354 assert context.get_verify_mode() == 0
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001355 context.set_verify(
Hynek Schlawackb4ceed32015-09-05 20:55:19 +02001356 long(VERIFY_PEER | VERIFY_CLIENT_ONCE), lambda *args: None
1357 ) # pragma: nocover
Alex Chan532b79e2017-01-24 15:14:52 +00001358 assert context.get_verify_mode() == (VERIFY_PEER | VERIFY_CLIENT_ONCE)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001359
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001360 def test_load_tmp_dh_wrong_args(self):
1361 """
Alex Chan532b79e2017-01-24 15:14:52 +00001362 `Context.load_tmp_dh` raises `TypeError` if called with a
1363 non-`str` argument.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001364 """
1365 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001366 with pytest.raises(TypeError):
1367 context.load_tmp_dh(object())
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001368
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001369 def test_load_tmp_dh_missing_file(self):
1370 """
Alex Chan532b79e2017-01-24 15:14:52 +00001371 `Context.load_tmp_dh` raises `OpenSSL.SSL.Error` if the
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001372 specified file does not exist.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001373 """
1374 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001375 with pytest.raises(Error):
1376 context.load_tmp_dh(b"hello")
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001377
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001378 def _load_tmp_dh_test(self, dhfilename):
Jean-Paul Calderone4e0c43f2015-04-13 10:15:17 -04001379 """
1380 Verify that calling ``Context.load_tmp_dh`` with the given filename
1381 does not raise an exception.
1382 """
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001383 context = Context(TLSv1_METHOD)
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001384 with open(dhfilename, "w") as dhfile:
1385 dhfile.write(dhparam)
1386
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001387 context.load_tmp_dh(dhfilename)
1388 # XXX What should I assert here? -exarkun
1389
Alex Chan532b79e2017-01-24 15:14:52 +00001390 def test_load_tmp_dh_bytes(self, tmpfile):
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001391 """
Alex Chan532b79e2017-01-24 15:14:52 +00001392 `Context.load_tmp_dh` loads Diffie-Hellman parameters from the
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001393 specified file (given as ``bytes``).
1394 """
1395 self._load_tmp_dh_test(
Alex Chan532b79e2017-01-24 15:14:52 +00001396 tmpfile + NON_ASCII.encode(getfilesystemencoding()),
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001397 )
1398
Alex Chan532b79e2017-01-24 15:14:52 +00001399 def test_load_tmp_dh_unicode(self, tmpfile):
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001400 """
Alex Chan532b79e2017-01-24 15:14:52 +00001401 `Context.load_tmp_dh` loads Diffie-Hellman parameters from the
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001402 specified file (given as ``unicode``).
1403 """
1404 self._load_tmp_dh_test(
Alex Chan532b79e2017-01-24 15:14:52 +00001405 tmpfile.decode(getfilesystemencoding()) + NON_ASCII,
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001406 )
1407
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001408 def test_set_tmp_ecdh(self):
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001409 """
Alex Chan532b79e2017-01-24 15:14:52 +00001410 `Context.set_tmp_ecdh` sets the elliptic curve for Diffie-Hellman to
1411 the specified curve.
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001412 """
1413 context = Context(TLSv1_METHOD)
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001414 for curve in get_elliptic_curves():
Hynek Schlawacka07fa8c2015-10-17 10:15:28 +02001415 if curve.name.startswith(u"Oakley-"):
Hynek Schlawack7408aff2015-10-17 09:51:16 +02001416 # Setting Oakley-EC2N-4 and Oakley-EC2N-3 adds
1417 # ('bignum routines', 'BN_mod_inverse', 'no inverse') to the
1418 # error queue on OpenSSL 1.0.2.
1419 continue
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001420 # The only easily "assertable" thing is that it does not raise an
1421 # exception.
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001422 context.set_tmp_ecdh(curve)
Alex Gaynor12dc0842014-01-17 12:51:31 -06001423
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001424 def test_set_session_cache_mode_wrong_args(self):
1425 """
Alex Chan532b79e2017-01-24 15:14:52 +00001426 `Context.set_session_cache_mode` raises `TypeError` if called with
1427 a non-integer argument.
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001428 called with other than one integer argument.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001429 """
1430 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001431 with pytest.raises(TypeError):
1432 context.set_session_cache_mode(object())
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001433
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001434 def test_session_cache_mode(self):
1435 """
Alex Chan532b79e2017-01-24 15:14:52 +00001436 `Context.set_session_cache_mode` specifies how sessions are cached.
1437 The setting can be retrieved via `Context.get_session_cache_mode`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001438 """
1439 context = Context(TLSv1_METHOD)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001440 context.set_session_cache_mode(SESS_CACHE_OFF)
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001441 off = context.set_session_cache_mode(SESS_CACHE_BOTH)
Alex Chan532b79e2017-01-24 15:14:52 +00001442 assert SESS_CACHE_OFF == off
1443 assert SESS_CACHE_BOTH == context.get_session_cache_mode()
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001444
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001445 @skip_if_py3
1446 def test_session_cache_mode_long(self):
1447 """
Alex Chan532b79e2017-01-24 15:14:52 +00001448 On Python 2 `Context.set_session_cache_mode` accepts values
1449 of type `long` as well as `int`.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001450 """
1451 context = Context(TLSv1_METHOD)
1452 context.set_session_cache_mode(long(SESS_CACHE_BOTH))
Alex Chan532b79e2017-01-24 15:14:52 +00001453 assert SESS_CACHE_BOTH == context.get_session_cache_mode()
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001454
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001455 def test_get_cert_store(self):
1456 """
Alex Chan532b79e2017-01-24 15:14:52 +00001457 `Context.get_cert_store` returns a `X509Store` instance.
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001458 """
1459 context = Context(TLSv1_METHOD)
1460 store = context.get_cert_store()
Alex Chan532b79e2017-01-24 15:14:52 +00001461 assert isinstance(store, X509Store)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001462
1463
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001464class TestServerNameCallback(object):
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001465 """
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001466 Tests for `Context.set_tlsext_servername_callback` and its
1467 interaction with `Connection`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001468 """
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001469 def test_old_callback_forgotten(self):
1470 """
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001471 If `Context.set_tlsext_servername_callback` is used to specify
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001472 a new callback, the one it replaces is dereferenced.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001473 """
1474 def callback(connection):
1475 pass
1476
1477 def replacement(connection):
1478 pass
1479
1480 context = Context(TLSv1_METHOD)
1481 context.set_tlsext_servername_callback(callback)
1482
1483 tracker = ref(callback)
1484 del callback
1485
1486 context.set_tlsext_servername_callback(replacement)
Jean-Paul Calderoned4033eb2014-01-11 08:21:46 -05001487
1488 # One run of the garbage collector happens to work on CPython. PyPy
1489 # doesn't collect the underlying object until a second run for whatever
1490 # reason. That's fine, it still demonstrates our code has properly
1491 # dropped the reference.
1492 collect()
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001493 collect()
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001494
1495 callback = tracker()
1496 if callback is not None:
1497 referrers = get_referrers(callback)
Jean-Paul Calderone7de39562014-01-11 08:17:59 -05001498 if len(referrers) > 1:
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001499 self.fail("Some references remain: %r" % (referrers,))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001500
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001501 def test_no_servername(self):
1502 """
1503 When a client specifies no server name, the callback passed to
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001504 `Context.set_tlsext_servername_callback` is invoked and the
1505 result of `Connection.get_servername` is `None`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001506 """
1507 args = []
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001508
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001509 def servername(conn):
1510 args.append((conn, conn.get_servername()))
1511 context = Context(TLSv1_METHOD)
1512 context.set_tlsext_servername_callback(servername)
1513
1514 # Lose our reference to it. The Context is responsible for keeping it
1515 # alive now.
1516 del servername
1517 collect()
1518
1519 # Necessary to actually accept the connection
1520 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001521 context.use_certificate(
1522 load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001523
1524 # Do a little connection to trigger the logic
1525 server = Connection(context, None)
1526 server.set_accept_state()
1527
1528 client = Connection(Context(TLSv1_METHOD), None)
1529 client.set_connect_state()
1530
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001531 interact_in_memory(server, client)
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001532
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001533 assert args == [(server, None)]
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001534
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001535 def test_servername(self):
1536 """
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001537 When a client specifies a server name in its hello message, the
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001538 callback passed to `Contexts.set_tlsext_servername_callback` is
1539 invoked and the result of `Connection.get_servername` is that
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001540 server name.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001541 """
1542 args = []
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001543
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001544 def servername(conn):
1545 args.append((conn, conn.get_servername()))
1546 context = Context(TLSv1_METHOD)
1547 context.set_tlsext_servername_callback(servername)
1548
1549 # Necessary to actually accept the connection
1550 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001551 context.use_certificate(
1552 load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001553
1554 # Do a little connection to trigger the logic
1555 server = Connection(context, None)
1556 server.set_accept_state()
1557
1558 client = Connection(Context(TLSv1_METHOD), None)
1559 client.set_connect_state()
Alex Gaynore7f51982016-09-11 11:48:14 -04001560 client.set_tlsext_host_name(b"foo1.example.com")
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001561
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001562 interact_in_memory(server, client)
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001563
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001564 assert args == [(server, b"foo1.example.com")]
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001565
1566
Alex Chan9e08b3e2016-11-10 12:18:54 +00001567class TestNextProtoNegotiation(object):
Cory Benfield84a121e2014-03-31 20:30:25 +01001568 """
1569 Test for Next Protocol Negotiation in PyOpenSSL.
1570 """
Alex Chan9e08b3e2016-11-10 12:18:54 +00001571 def test_npn_success(self):
1572 """
1573 Tests that clients and servers that agree on the negotiated next
1574 protocol can correct establish a connection, and that the agreed
1575 protocol is reported by the connections.
1576 """
1577 advertise_args = []
1578 select_args = []
1579
1580 def advertise(conn):
1581 advertise_args.append((conn,))
1582 return [b'http/1.1', b'spdy/2']
1583
1584 def select(conn, options):
1585 select_args.append((conn, options))
1586 return b'spdy/2'
1587
1588 server_context = Context(TLSv1_METHOD)
1589 server_context.set_npn_advertise_callback(advertise)
1590
1591 client_context = Context(TLSv1_METHOD)
1592 client_context.set_npn_select_callback(select)
1593
1594 # Necessary to actually accept the connection
1595 server_context.use_privatekey(
1596 load_privatekey(FILETYPE_PEM, server_key_pem))
1597 server_context.use_certificate(
1598 load_certificate(FILETYPE_PEM, server_cert_pem))
1599
1600 # Do a little connection to trigger the logic
1601 server = Connection(server_context, None)
1602 server.set_accept_state()
1603
1604 client = Connection(client_context, None)
1605 client.set_connect_state()
1606
1607 interact_in_memory(server, client)
1608
1609 assert advertise_args == [(server,)]
1610 assert select_args == [(client, [b'http/1.1', b'spdy/2'])]
1611
1612 assert server.get_next_proto_negotiated() == b'spdy/2'
1613 assert client.get_next_proto_negotiated() == b'spdy/2'
1614
1615 def test_npn_client_fail(self):
1616 """
1617 Tests that when clients and servers cannot agree on what protocol
1618 to use next that the TLS connection does not get established.
1619 """
1620 advertise_args = []
1621 select_args = []
1622
1623 def advertise(conn):
1624 advertise_args.append((conn,))
1625 return [b'http/1.1', b'spdy/2']
1626
1627 def select(conn, options):
1628 select_args.append((conn, options))
1629 return b''
1630
1631 server_context = Context(TLSv1_METHOD)
1632 server_context.set_npn_advertise_callback(advertise)
1633
1634 client_context = Context(TLSv1_METHOD)
1635 client_context.set_npn_select_callback(select)
1636
1637 # Necessary to actually accept the connection
1638 server_context.use_privatekey(
1639 load_privatekey(FILETYPE_PEM, server_key_pem))
1640 server_context.use_certificate(
1641 load_certificate(FILETYPE_PEM, server_cert_pem))
1642
1643 # Do a little connection to trigger the logic
1644 server = Connection(server_context, None)
1645 server.set_accept_state()
1646
1647 client = Connection(client_context, None)
1648 client.set_connect_state()
1649
1650 # If the client doesn't return anything, the connection will fail.
1651 with pytest.raises(Error):
1652 interact_in_memory(server, client)
1653
1654 assert advertise_args == [(server,)]
1655 assert select_args == [(client, [b'http/1.1', b'spdy/2'])]
1656
1657 def test_npn_select_error(self):
1658 """
1659 Test that we can handle exceptions in the select callback. If
1660 select fails it should be fatal to the connection.
1661 """
1662 advertise_args = []
1663
1664 def advertise(conn):
1665 advertise_args.append((conn,))
1666 return [b'http/1.1', b'spdy/2']
1667
1668 def select(conn, options):
1669 raise TypeError
1670
1671 server_context = Context(TLSv1_METHOD)
1672 server_context.set_npn_advertise_callback(advertise)
1673
1674 client_context = Context(TLSv1_METHOD)
1675 client_context.set_npn_select_callback(select)
1676
1677 # Necessary to actually accept the connection
1678 server_context.use_privatekey(
1679 load_privatekey(FILETYPE_PEM, server_key_pem))
1680 server_context.use_certificate(
1681 load_certificate(FILETYPE_PEM, server_cert_pem))
1682
1683 # Do a little connection to trigger the logic
1684 server = Connection(server_context, None)
1685 server.set_accept_state()
1686
1687 client = Connection(client_context, None)
1688 client.set_connect_state()
1689
1690 # If the callback throws an exception it should be raised here.
1691 with pytest.raises(TypeError):
1692 interact_in_memory(server, client)
1693 assert advertise_args == [(server,), ]
1694
1695 def test_npn_advertise_error(self):
1696 """
1697 Test that we can handle exceptions in the advertise callback. If
1698 advertise fails no NPN is advertised to the client.
1699 """
1700 select_args = []
1701
1702 def advertise(conn):
1703 raise TypeError
1704
1705 def select(conn, options): # pragma: nocover
Cory Benfieldba1820d2015-04-13 17:39:12 -04001706 """
Alex Chan9e08b3e2016-11-10 12:18:54 +00001707 Assert later that no args are actually appended.
Cory Benfieldba1820d2015-04-13 17:39:12 -04001708 """
Alex Chan9e08b3e2016-11-10 12:18:54 +00001709 select_args.append((conn, options))
1710 return b''
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001711
Alex Chan9e08b3e2016-11-10 12:18:54 +00001712 server_context = Context(TLSv1_METHOD)
1713 server_context.set_npn_advertise_callback(advertise)
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001714
Alex Chan9e08b3e2016-11-10 12:18:54 +00001715 client_context = Context(TLSv1_METHOD)
1716 client_context.set_npn_select_callback(select)
Cory Benfield84a121e2014-03-31 20:30:25 +01001717
Alex Chan9e08b3e2016-11-10 12:18:54 +00001718 # Necessary to actually accept the connection
1719 server_context.use_privatekey(
1720 load_privatekey(FILETYPE_PEM, server_key_pem))
1721 server_context.use_certificate(
1722 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield84a121e2014-03-31 20:30:25 +01001723
Alex Chan9e08b3e2016-11-10 12:18:54 +00001724 # Do a little connection to trigger the logic
1725 server = Connection(server_context, None)
1726 server.set_accept_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001727
Alex Chan9e08b3e2016-11-10 12:18:54 +00001728 client = Connection(client_context, None)
1729 client.set_connect_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001730
Alex Chan9e08b3e2016-11-10 12:18:54 +00001731 # If the client doesn't return anything, the connection will fail.
1732 with pytest.raises(TypeError):
1733 interact_in_memory(server, client)
1734 assert select_args == []
Cory Benfield0ea76e72015-03-22 09:05:28 +00001735
1736
Alex Chanec1e32d2016-11-10 14:11:45 +00001737class TestApplicationLayerProtoNegotiation(object):
Cory Benfield12eae892014-06-07 15:42:56 +01001738 """
1739 Tests for ALPN in PyOpenSSL.
1740 """
Cory Benfielde46fa842015-04-13 16:50:49 -04001741 # Skip tests on versions that don't support ALPN.
1742 if _lib.Cryptography_HAS_ALPN:
Cory Benfield12eae892014-06-07 15:42:56 +01001743
Cory Benfielde46fa842015-04-13 16:50:49 -04001744 def test_alpn_success(self):
1745 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04001746 Clients and servers that agree on the negotiated ALPN protocol can
1747 correct establish a connection, and the agreed protocol is reported
1748 by the connections.
Cory Benfielde46fa842015-04-13 16:50:49 -04001749 """
1750 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001751
Cory Benfielde46fa842015-04-13 16:50:49 -04001752 def select(conn, options):
1753 select_args.append((conn, options))
1754 return b'spdy/2'
Cory Benfield12eae892014-06-07 15:42:56 +01001755
Cory Benfielde46fa842015-04-13 16:50:49 -04001756 client_context = Context(TLSv1_METHOD)
1757 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfield12eae892014-06-07 15:42:56 +01001758
Cory Benfielde46fa842015-04-13 16:50:49 -04001759 server_context = Context(TLSv1_METHOD)
1760 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01001761
Cory Benfielde46fa842015-04-13 16:50:49 -04001762 # Necessary to actually accept the connection
1763 server_context.use_privatekey(
1764 load_privatekey(FILETYPE_PEM, server_key_pem))
1765 server_context.use_certificate(
1766 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield12eae892014-06-07 15:42:56 +01001767
Cory Benfielde46fa842015-04-13 16:50:49 -04001768 # Do a little connection to trigger the logic
1769 server = Connection(server_context, None)
1770 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001771
Cory Benfielde46fa842015-04-13 16:50:49 -04001772 client = Connection(client_context, None)
1773 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001774
Alex Chanec1e32d2016-11-10 14:11:45 +00001775 interact_in_memory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001776
Alex Chanec1e32d2016-11-10 14:11:45 +00001777 assert select_args == [(server, [b'http/1.1', b'spdy/2'])]
Cory Benfielde46fa842015-04-13 16:50:49 -04001778
Alex Chanec1e32d2016-11-10 14:11:45 +00001779 assert server.get_alpn_proto_negotiated() == b'spdy/2'
1780 assert client.get_alpn_proto_negotiated() == b'spdy/2'
Cory Benfield12eae892014-06-07 15:42:56 +01001781
Cory Benfielde46fa842015-04-13 16:50:49 -04001782 def test_alpn_set_on_connection(self):
1783 """
1784 The same as test_alpn_success, but setting the ALPN protocols on
1785 the connection rather than the context.
1786 """
1787 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001788
Cory Benfielde46fa842015-04-13 16:50:49 -04001789 def select(conn, options):
1790 select_args.append((conn, options))
1791 return b'spdy/2'
Cory Benfield12eae892014-06-07 15:42:56 +01001792
Cory Benfielde46fa842015-04-13 16:50:49 -04001793 # Setup the client context but don't set any ALPN protocols.
1794 client_context = Context(TLSv1_METHOD)
Cory Benfield12eae892014-06-07 15:42:56 +01001795
Cory Benfielde46fa842015-04-13 16:50:49 -04001796 server_context = Context(TLSv1_METHOD)
1797 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01001798
Cory Benfielde46fa842015-04-13 16:50:49 -04001799 # Necessary to actually accept the connection
1800 server_context.use_privatekey(
1801 load_privatekey(FILETYPE_PEM, server_key_pem))
1802 server_context.use_certificate(
1803 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield12eae892014-06-07 15:42:56 +01001804
Cory Benfielde46fa842015-04-13 16:50:49 -04001805 # Do a little connection to trigger the logic
1806 server = Connection(server_context, None)
1807 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001808
Cory Benfielde46fa842015-04-13 16:50:49 -04001809 # Set the ALPN protocols on the client connection.
1810 client = Connection(client_context, None)
1811 client.set_alpn_protos([b'http/1.1', b'spdy/2'])
1812 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001813
Alex Chanec1e32d2016-11-10 14:11:45 +00001814 interact_in_memory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001815
Alex Chanec1e32d2016-11-10 14:11:45 +00001816 assert select_args == [(server, [b'http/1.1', b'spdy/2'])]
Cory Benfield12eae892014-06-07 15:42:56 +01001817
Alex Chanec1e32d2016-11-10 14:11:45 +00001818 assert server.get_alpn_proto_negotiated() == b'spdy/2'
1819 assert client.get_alpn_proto_negotiated() == b'spdy/2'
Cory Benfield12eae892014-06-07 15:42:56 +01001820
Cory Benfielde46fa842015-04-13 16:50:49 -04001821 def test_alpn_server_fail(self):
1822 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04001823 When clients and servers cannot agree on what protocol to use next
1824 the TLS connection does not get established.
Cory Benfielde46fa842015-04-13 16:50:49 -04001825 """
1826 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001827
Cory Benfielde46fa842015-04-13 16:50:49 -04001828 def select(conn, options):
1829 select_args.append((conn, options))
1830 return b''
Cory Benfield12eae892014-06-07 15:42:56 +01001831
Cory Benfielde46fa842015-04-13 16:50:49 -04001832 client_context = Context(TLSv1_METHOD)
1833 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfield12eae892014-06-07 15:42:56 +01001834
Cory Benfielde46fa842015-04-13 16:50:49 -04001835 server_context = Context(TLSv1_METHOD)
1836 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01001837
Cory Benfielde46fa842015-04-13 16:50:49 -04001838 # Necessary to actually accept the connection
1839 server_context.use_privatekey(
1840 load_privatekey(FILETYPE_PEM, server_key_pem))
1841 server_context.use_certificate(
1842 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield12eae892014-06-07 15:42:56 +01001843
Cory Benfielde46fa842015-04-13 16:50:49 -04001844 # Do a little connection to trigger the logic
1845 server = Connection(server_context, None)
1846 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001847
Cory Benfielde46fa842015-04-13 16:50:49 -04001848 client = Connection(client_context, None)
1849 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001850
Cory Benfielde46fa842015-04-13 16:50:49 -04001851 # If the client doesn't return anything, the connection will fail.
Alex Chanec1e32d2016-11-10 14:11:45 +00001852 with pytest.raises(Error):
1853 interact_in_memory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001854
Alex Chanec1e32d2016-11-10 14:11:45 +00001855 assert select_args == [(server, [b'http/1.1', b'spdy/2'])]
Cory Benfield12eae892014-06-07 15:42:56 +01001856
Cory Benfielde46fa842015-04-13 16:50:49 -04001857 def test_alpn_no_server(self):
1858 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04001859 When clients and servers cannot agree on what protocol to use next
1860 because the server doesn't offer ALPN, no protocol is negotiated.
Cory Benfielde46fa842015-04-13 16:50:49 -04001861 """
1862 client_context = Context(TLSv1_METHOD)
1863 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfielde3d57152015-04-11 17:57:35 -04001864
Cory Benfielde46fa842015-04-13 16:50:49 -04001865 server_context = Context(TLSv1_METHOD)
Cory Benfielde3d57152015-04-11 17:57:35 -04001866
Cory Benfielde46fa842015-04-13 16:50:49 -04001867 # Necessary to actually accept the connection
1868 server_context.use_privatekey(
1869 load_privatekey(FILETYPE_PEM, server_key_pem))
1870 server_context.use_certificate(
1871 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfielde3d57152015-04-11 17:57:35 -04001872
Cory Benfielde46fa842015-04-13 16:50:49 -04001873 # Do a little connection to trigger the logic
1874 server = Connection(server_context, None)
1875 server.set_accept_state()
Cory Benfielde3d57152015-04-11 17:57:35 -04001876
Cory Benfielde46fa842015-04-13 16:50:49 -04001877 client = Connection(client_context, None)
1878 client.set_connect_state()
Cory Benfielde3d57152015-04-11 17:57:35 -04001879
Cory Benfielde46fa842015-04-13 16:50:49 -04001880 # Do the dance.
Alex Chanec1e32d2016-11-10 14:11:45 +00001881 interact_in_memory(server, client)
Cory Benfielde3d57152015-04-11 17:57:35 -04001882
Alex Chanec1e32d2016-11-10 14:11:45 +00001883 assert client.get_alpn_proto_negotiated() == b''
Cory Benfielde3d57152015-04-11 17:57:35 -04001884
Cory Benfielde46fa842015-04-13 16:50:49 -04001885 def test_alpn_callback_exception(self):
1886 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04001887 We can handle exceptions in the ALPN select callback.
Cory Benfielde46fa842015-04-13 16:50:49 -04001888 """
1889 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001890
Cory Benfielde46fa842015-04-13 16:50:49 -04001891 def select(conn, options):
1892 select_args.append((conn, options))
Cory Benfieldef401452015-04-13 18:17:36 -04001893 raise TypeError()
Cory Benfieldf1177e72015-04-12 09:11:49 -04001894
Cory Benfielde46fa842015-04-13 16:50:49 -04001895 client_context = Context(TLSv1_METHOD)
1896 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfieldf1177e72015-04-12 09:11:49 -04001897
Cory Benfielde46fa842015-04-13 16:50:49 -04001898 server_context = Context(TLSv1_METHOD)
1899 server_context.set_alpn_select_callback(select)
Cory Benfieldf1177e72015-04-12 09:11:49 -04001900
Cory Benfielde46fa842015-04-13 16:50:49 -04001901 # Necessary to actually accept the connection
1902 server_context.use_privatekey(
1903 load_privatekey(FILETYPE_PEM, server_key_pem))
1904 server_context.use_certificate(
1905 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfieldf1177e72015-04-12 09:11:49 -04001906
Cory Benfielde46fa842015-04-13 16:50:49 -04001907 # Do a little connection to trigger the logic
1908 server = Connection(server_context, None)
1909 server.set_accept_state()
Cory Benfieldf1177e72015-04-12 09:11:49 -04001910
Cory Benfielde46fa842015-04-13 16:50:49 -04001911 client = Connection(client_context, None)
1912 client.set_connect_state()
Cory Benfieldf1177e72015-04-12 09:11:49 -04001913
Alex Chanec1e32d2016-11-10 14:11:45 +00001914 with pytest.raises(TypeError):
1915 interact_in_memory(server, client)
1916 assert select_args == [(server, [b'http/1.1', b'spdy/2'])]
Cory Benfieldf1177e72015-04-12 09:11:49 -04001917
Cory Benfield0f7b04c2015-04-13 17:51:12 -04001918 else:
1919 # No ALPN.
1920 def test_alpn_not_implemented(self):
Cory Benfieldef401452015-04-13 18:17:36 -04001921 """
1922 If ALPN is not in OpenSSL, we should raise NotImplementedError.
1923 """
Cory Benfield0f7b04c2015-04-13 17:51:12 -04001924 # Test the context methods first.
1925 context = Context(TLSv1_METHOD)
Alex Chanec1e32d2016-11-10 14:11:45 +00001926 with pytest.raises(NotImplementedError):
1927 context.set_alpn_protos(None)
1928 with pytest.raises(NotImplementedError):
1929 context.set_alpn_select_callback(None)
Cory Benfield0f7b04c2015-04-13 17:51:12 -04001930
1931 # Now test a connection.
1932 conn = Connection(context)
Alex Chanec1e32d2016-11-10 14:11:45 +00001933 with pytest.raises(NotImplementedError):
1934 conn.set_alpn_protos(None)
Cory Benfield0f7b04c2015-04-13 17:51:12 -04001935
Cory Benfieldf1177e72015-04-12 09:11:49 -04001936
Alex Chanec1e32d2016-11-10 14:11:45 +00001937class TestSession(object):
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05001938 """
1939 Unit tests for :py:obj:`OpenSSL.SSL.Session`.
1940 """
1941 def test_construction(self):
1942 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001943 :py:class:`Session` can be constructed with no arguments, creating
1944 a new instance of that type.
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05001945 """
1946 new_session = Session()
Alex Chanec1e32d2016-11-10 14:11:45 +00001947 assert isinstance(new_session, Session)
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05001948
1949
Alex Chan1c0cb662017-01-30 07:13:30 +00001950class TestConnection(object):
Rick Deane15b1472009-07-09 15:53:42 -05001951 """
Alex Chan1c0cb662017-01-30 07:13:30 +00001952 Unit tests for `OpenSSL.SSL.Connection`.
Rick Deane15b1472009-07-09 15:53:42 -05001953 """
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04001954 # XXX get_peer_certificate -> None
1955 # XXX sock_shutdown
1956 # XXX master_key -> TypeError
1957 # XXX server_random -> TypeError
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04001958 # XXX connect -> TypeError
1959 # XXX connect_ex -> TypeError
1960 # XXX set_connect_state -> TypeError
1961 # XXX set_accept_state -> TypeError
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04001962 # XXX do_handshake -> TypeError
1963 # XXX bio_read -> TypeError
1964 # XXX recv -> TypeError
1965 # XXX send -> TypeError
1966 # XXX bio_write -> TypeError
1967
Rick Deane15b1472009-07-09 15:53:42 -05001968 def test_type(self):
1969 """
Alex Chan1c0cb662017-01-30 07:13:30 +00001970 `Connection` and `ConnectionType` refer to the same type object and
1971 can be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -05001972 """
Alex Chan1c0cb662017-01-30 07:13:30 +00001973 assert Connection is ConnectionType
Rick Deane15b1472009-07-09 15:53:42 -05001974 ctx = Context(TLSv1_METHOD)
Alex Chan1c0cb662017-01-30 07:13:30 +00001975 assert is_consistent_type(Connection, 'Connection', ctx, None)
Rick Deane15b1472009-07-09 15:53:42 -05001976
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05001977 def test_get_context(self):
1978 """
Alex Chan1c0cb662017-01-30 07:13:30 +00001979 `Connection.get_context` returns the `Context` instance used to
1980 construct the `Connection` instance.
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05001981 """
1982 context = Context(TLSv1_METHOD)
1983 connection = Connection(context, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00001984 assert connection.get_context() is context
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05001985
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04001986 def test_set_context_wrong_args(self):
1987 """
Alex Chan1c0cb662017-01-30 07:13:30 +00001988 `Connection.set_context` raises `TypeError` if called with a
1989 non-`Context` instance argument,
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04001990 """
1991 ctx = Context(TLSv1_METHOD)
1992 connection = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00001993 with pytest.raises(TypeError):
1994 connection.set_context(object())
1995 with pytest.raises(TypeError):
1996 connection.set_context("hello")
1997 with pytest.raises(TypeError):
1998 connection.set_context(1)
1999 assert ctx is connection.get_context()
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002000
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002001 def test_set_context(self):
2002 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002003 `Connection.set_context` specifies a new `Context` instance to be
2004 used for the connection.
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002005 """
2006 original = Context(SSLv23_METHOD)
2007 replacement = Context(TLSv1_METHOD)
2008 connection = Connection(original, None)
2009 connection.set_context(replacement)
Alex Chan1c0cb662017-01-30 07:13:30 +00002010 assert replacement is connection.get_context()
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002011 # Lose our references to the contexts, just in case the Connection
2012 # isn't properly managing its own contributions to their reference
2013 # counts.
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002014 del original, replacement
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002015 collect()
2016
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002017 def test_set_tlsext_host_name_wrong_args(self):
2018 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002019 If `Connection.set_tlsext_host_name` is called with a non-byte string
2020 argument or a byte string with an embedded NUL, `TypeError` is raised.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002021 """
2022 conn = Connection(Context(TLSv1_METHOD), None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002023 with pytest.raises(TypeError):
2024 conn.set_tlsext_host_name(object())
2025 with pytest.raises(TypeError):
2026 conn.set_tlsext_host_name(b"with\0null")
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002027
Abraham Martinc5484ba2015-03-25 15:33:05 +00002028 if PY3:
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002029 # On Python 3.x, don't accidentally implicitly convert from text.
Alex Chan1c0cb662017-01-30 07:13:30 +00002030 with pytest.raises(TypeError):
2031 conn.set_tlsext_host_name(b"example.com".decode("ascii"))
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04002032
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002033 def test_pending(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002034 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002035 `Connection.pending` returns the number of bytes available for
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002036 immediate read.
2037 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002038 connection = Connection(Context(TLSv1_METHOD), None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002039 assert connection.pending() == 0
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002040
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002041 def test_peek(self):
2042 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002043 `Connection.recv` peeks into the connection if `socket.MSG_PEEK`
2044 is passed.
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002045 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002046 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002047 server.send(b'xy')
Alex Chan1c0cb662017-01-30 07:13:30 +00002048 assert client.recv(2, MSG_PEEK) == b'xy'
2049 assert client.recv(2, MSG_PEEK) == b'xy'
2050 assert client.recv(2) == b'xy'
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002051
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002052 def test_connect_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002053 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002054 `Connection.connect` raises `TypeError` if called with
2055 a non-address argument.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002056 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002057 connection = Connection(Context(TLSv1_METHOD), socket())
Alex Chan1c0cb662017-01-30 07:13:30 +00002058 with pytest.raises(TypeError):
2059 connection.connect(None)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002060
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002061 def test_connect_refused(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002062 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002063 `Connection.connect` raises `socket.error` if the underlying socket
2064 connect method raises it.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002065 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002066 client = socket()
2067 context = Context(TLSv1_METHOD)
2068 clientSSL = Connection(context, client)
Alex Gaynor122717b2015-09-05 14:14:18 -04002069 # pytest.raises here doesn't work because of a bug in py.test on Python
2070 # 2.6: https://github.com/pytest-dev/pytest/issues/988
Alex Gaynore69c2782015-09-05 14:07:48 -04002071 try:
Alex Gaynor1aabb2e2015-09-05 13:35:18 -04002072 clientSSL.connect(("127.0.0.1", 1))
Alex Gaynore69c2782015-09-05 14:07:48 -04002073 except error as e:
Alex Gaynor20a4c082015-09-05 14:24:15 -04002074 exc = e
2075 assert exc.args[0] == ECONNREFUSED
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002076
2077 def test_connect(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002078 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002079 `Connection.connect` establishes a connection to the specified address.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002080 """
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002081 port = socket()
2082 port.bind(('', 0))
2083 port.listen(3)
2084
2085 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002086 clientSSL.connect(('127.0.0.1', port.getsockname()[1]))
2087 # XXX An assertion? Or something?
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002088
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002089 @pytest.mark.skipif(
2090 platform == "darwin",
2091 reason="connect_ex sometimes causes a kernel panic on OS X 10.6.4"
2092 )
2093 def test_connect_ex(self):
2094 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002095 If there is a connection error, `Connection.connect_ex` returns the
2096 errno instead of raising an exception.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002097 """
2098 port = socket()
2099 port.bind(('', 0))
2100 port.listen(3)
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002101
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002102 clientSSL = Connection(Context(TLSv1_METHOD), socket())
2103 clientSSL.setblocking(False)
2104 result = clientSSL.connect_ex(port.getsockname())
2105 expected = (EINPROGRESS, EWOULDBLOCK)
Alex Chan1c0cb662017-01-30 07:13:30 +00002106 assert result in expected
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002107
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002108 def test_accept(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002109 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002110 `Connection.accept` accepts a pending connection attempt and returns a
2111 tuple of a new `Connection` (the accepted client) and the address the
2112 connection originated from.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002113 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002114 ctx = Context(TLSv1_METHOD)
2115 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2116 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002117 port = socket()
2118 portSSL = Connection(ctx, port)
2119 portSSL.bind(('', 0))
2120 portSSL.listen(3)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002121
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002122 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002123
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002124 # Calling portSSL.getsockname() here to get the server IP address
2125 # sounds great, but frequently fails on Windows.
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002126 clientSSL.connect(('127.0.0.1', portSSL.getsockname()[1]))
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002127
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002128 serverSSL, address = portSSL.accept()
2129
Alex Chan1c0cb662017-01-30 07:13:30 +00002130 assert isinstance(serverSSL, Connection)
2131 assert serverSSL.get_context() is ctx
2132 assert address == clientSSL.getsockname()
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002133
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002134 def test_shutdown_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002135 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002136 `Connection.set_shutdown` raises `TypeError` if called with arguments
2137 other than integers.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002138 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002139 connection = Connection(Context(TLSv1_METHOD), None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002140 with pytest.raises(TypeError):
2141 connection.set_shutdown(None)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002142
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002143 def test_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002144 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002145 `Connection.shutdown` performs an SSL-level connection shutdown.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002146 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002147 server, client = loopback()
2148 assert not server.shutdown()
2149 assert server.get_shutdown() == SENT_SHUTDOWN
2150 with pytest.raises(ZeroReturnError):
2151 client.recv(1024)
2152 assert client.get_shutdown() == RECEIVED_SHUTDOWN
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04002153 client.shutdown()
Alex Chan1c0cb662017-01-30 07:13:30 +00002154 assert client.get_shutdown() == (SENT_SHUTDOWN | RECEIVED_SHUTDOWN)
2155 with pytest.raises(ZeroReturnError):
2156 server.recv(1024)
2157 assert server.get_shutdown() == (SENT_SHUTDOWN | RECEIVED_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002158
Paul Aurichc85e0862015-01-08 08:34:33 -08002159 def test_shutdown_closed(self):
2160 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002161 If the underlying socket is closed, `Connection.shutdown` propagates
2162 the write error from the low level write call.
Paul Aurichc85e0862015-01-08 08:34:33 -08002163 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002164 server, client = loopback()
Paul Aurichc85e0862015-01-08 08:34:33 -08002165 server.sock_shutdown(2)
Alex Chan1c0cb662017-01-30 07:13:30 +00002166 with pytest.raises(SysCallError) as exc:
2167 server.shutdown()
2168 if platform == "win32":
2169 assert exc.value.args[0] == ESHUTDOWN
2170 else:
2171 assert exc.value.args[0] == EPIPE
Paul Aurichc85e0862015-01-08 08:34:33 -08002172
Glyph89389472015-04-14 17:29:26 -04002173 def test_shutdown_truncated(self):
Glyph6064ec32015-04-14 16:38:22 -04002174 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002175 If the underlying connection is truncated, `Connection.shutdown`
2176 raises an `Error`.
Glyph6064ec32015-04-14 16:38:22 -04002177 """
Glyph89389472015-04-14 17:29:26 -04002178 server_ctx = Context(TLSv1_METHOD)
2179 client_ctx = Context(TLSv1_METHOD)
2180 server_ctx.use_privatekey(
2181 load_privatekey(FILETYPE_PEM, server_key_pem))
2182 server_ctx.use_certificate(
2183 load_certificate(FILETYPE_PEM, server_cert_pem))
2184 server = Connection(server_ctx, None)
2185 client = Connection(client_ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002186 handshake_in_memory(client, server)
2187 assert not server.shutdown()
2188 with pytest.raises(WantReadError):
2189 server.shutdown()
Glyph89389472015-04-14 17:29:26 -04002190 server.bio_shutdown()
Alex Chan1c0cb662017-01-30 07:13:30 +00002191 with pytest.raises(Error):
2192 server.shutdown()
Glyph6064ec32015-04-14 16:38:22 -04002193
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002194 def test_set_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002195 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002196 `Connection.set_shutdown` sets the state of the SSL connection
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002197 shutdown process.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002198 """
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002199 connection = Connection(Context(TLSv1_METHOD), socket())
2200 connection.set_shutdown(RECEIVED_SHUTDOWN)
Alex Chan1c0cb662017-01-30 07:13:30 +00002201 assert connection.get_shutdown() == RECEIVED_SHUTDOWN
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002202
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002203 @skip_if_py3
2204 def test_set_shutdown_long(self):
2205 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002206 On Python 2 `Connection.set_shutdown` accepts an argument
2207 of type `long` as well as `int`.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002208 """
2209 connection = Connection(Context(TLSv1_METHOD), socket())
2210 connection.set_shutdown(long(RECEIVED_SHUTDOWN))
Alex Chan1c0cb662017-01-30 07:13:30 +00002211 assert connection.get_shutdown() == RECEIVED_SHUTDOWN
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -05002212
kjavaf248592015-09-07 12:14:01 +01002213 def test_state_string(self):
2214 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002215 `Connection.state_string` verbosely describes the current state of
2216 the `Connection`.
kjavaf248592015-09-07 12:14:01 +01002217 """
Hynek Schlawackb0274ce2015-10-16 19:56:26 +02002218 server, client = socket_pair()
Alex Chan1c0cb662017-01-30 07:13:30 +00002219 server = loopback_server_factory(server)
2220 client = loopback_client_factory(client)
kjavaf248592015-09-07 12:14:01 +01002221
Alex Gaynor5af32d02016-09-24 01:52:21 -04002222 assert server.get_state_string() in [
2223 b"before/accept initialization", b"before SSL initialization"
2224 ]
2225 assert client.get_state_string() in [
2226 b"before/connect initialization", b"before SSL initialization"
2227 ]
kjavaf248592015-09-07 12:14:01 +01002228
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002229 def test_app_data(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002230 """
2231 Any object can be set as app data by passing it to
Alex Chan1c0cb662017-01-30 07:13:30 +00002232 `Connection.set_app_data` and later retrieved with
2233 `Connection.get_app_data`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002234 """
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002235 conn = Connection(Context(TLSv1_METHOD), None)
Todd Chapman4f73e4f2015-08-27 11:26:43 -04002236 assert None is conn.get_app_data()
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002237 app_data = object()
2238 conn.set_app_data(app_data)
Todd Chapman4f73e4f2015-08-27 11:26:43 -04002239 assert conn.get_app_data() is app_data
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002240
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002241 def test_makefile(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002242 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002243 `Connection.makefile` is not implemented and calling that
2244 method raises `NotImplementedError`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002245 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002246 conn = Connection(Context(TLSv1_METHOD), None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002247 with pytest.raises(NotImplementedError):
2248 conn.makefile()
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002249
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002250 def test_get_peer_cert_chain(self):
2251 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002252 `Connection.get_peer_cert_chain` returns a list of certificates
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002253 which the connected server returned for the certification verification.
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002254 """
2255 chain = _create_certificate_chain()
2256 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
2257
2258 serverContext = Context(TLSv1_METHOD)
2259 serverContext.use_privatekey(skey)
2260 serverContext.use_certificate(scert)
2261 serverContext.add_extra_chain_cert(icert)
2262 serverContext.add_extra_chain_cert(cacert)
2263 server = Connection(serverContext, None)
2264 server.set_accept_state()
2265
2266 # Create the client
2267 clientContext = Context(TLSv1_METHOD)
2268 clientContext.set_verify(VERIFY_NONE, verify_cb)
2269 client = Connection(clientContext, None)
2270 client.set_connect_state()
2271
Alex Chan1c0cb662017-01-30 07:13:30 +00002272 interact_in_memory(client, server)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002273
2274 chain = client.get_peer_cert_chain()
Alex Chan1c0cb662017-01-30 07:13:30 +00002275 assert len(chain) == 3
2276 assert "Server Certificate" == chain[0].get_subject().CN
2277 assert "Intermediate Certificate" == chain[1].get_subject().CN
2278 assert "Authority Certificate" == chain[2].get_subject().CN
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002279
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002280 def test_get_peer_cert_chain_none(self):
2281 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002282 `Connection.get_peer_cert_chain` returns `None` if the peer sends
2283 no certificate chain.
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002284 """
2285 ctx = Context(TLSv1_METHOD)
2286 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2287 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
2288 server = Connection(ctx, None)
2289 server.set_accept_state()
2290 client = Connection(Context(TLSv1_METHOD), None)
2291 client.set_connect_state()
Alex Chan1c0cb662017-01-30 07:13:30 +00002292 interact_in_memory(client, server)
2293 assert None is server.get_peer_cert_chain()
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002294
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002295 def test_get_session_unconnected(self):
2296 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002297 `Connection.get_session` returns `None` when used with an object
2298 which has not been connected.
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002299 """
2300 ctx = Context(TLSv1_METHOD)
2301 server = Connection(ctx, None)
2302 session = server.get_session()
Alex Chan1c0cb662017-01-30 07:13:30 +00002303 assert None is session
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002304
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002305 def test_server_get_session(self):
2306 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002307 On the server side of a connection, `Connection.get_session` returns a
2308 `Session` instance representing the SSL session for that connection.
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002309 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002310 server, client = loopback()
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002311 session = server.get_session()
Alex Chan1c0cb662017-01-30 07:13:30 +00002312 assert isinstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002313
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002314 def test_client_get_session(self):
2315 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002316 On the client side of a connection, `Connection.get_session`
2317 returns a `Session` instance representing the SSL session for
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002318 that connection.
2319 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002320 server, client = loopback()
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002321 session = client.get_session()
Alex Chan1c0cb662017-01-30 07:13:30 +00002322 assert isinstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002323
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002324 def test_set_session_wrong_args(self):
2325 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002326 `Connection.set_session` raises `TypeError` if called with an object
2327 that is not an instance of `Session`.
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002328 """
2329 ctx = Context(TLSv1_METHOD)
2330 connection = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002331 with pytest.raises(TypeError):
2332 connection.set_session(123)
2333 with pytest.raises(TypeError):
2334 connection.set_session("hello")
2335 with pytest.raises(TypeError):
2336 connection.set_session(object())
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002337
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002338 def test_client_set_session(self):
2339 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002340 `Connection.set_session`, when used prior to a connection being
2341 established, accepts a `Session` instance and causes an attempt to
2342 re-use the session it represents when the SSL handshake is performed.
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002343 """
2344 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2345 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
2346 ctx = Context(TLSv1_METHOD)
2347 ctx.use_privatekey(key)
2348 ctx.use_certificate(cert)
2349 ctx.set_session_id("unity-test")
2350
2351 def makeServer(socket):
2352 server = Connection(ctx, socket)
2353 server.set_accept_state()
2354 return server
2355
Alex Chan1c0cb662017-01-30 07:13:30 +00002356 originalServer, originalClient = loopback(
2357 server_factory=makeServer)
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002358 originalSession = originalClient.get_session()
2359
2360 def makeClient(socket):
Alex Chan1c0cb662017-01-30 07:13:30 +00002361 client = loopback_client_factory(socket)
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002362 client.set_session(originalSession)
2363 return client
Alex Chan1c0cb662017-01-30 07:13:30 +00002364 resumedServer, resumedClient = loopback(
2365 server_factory=makeServer,
2366 client_factory=makeClient)
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002367
2368 # This is a proxy: in general, we have no access to any unique
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002369 # identifier for the session (new enough versions of OpenSSL expose
2370 # a hash which could be usable, but "new enough" is very, very new).
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002371 # Instead, exploit the fact that the master key is re-used if the
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002372 # session is re-used. As long as the master key for the two
2373 # connections is the same, the session was re-used!
Alex Chan1c0cb662017-01-30 07:13:30 +00002374 assert originalServer.master_key() == resumedServer.master_key()
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002375
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002376 def test_set_session_wrong_method(self):
2377 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002378 If `Connection.set_session` is passed a `Session` instance associated
2379 with a context using a different SSL method than the `Connection`
2380 is using, a `OpenSSL.SSL.Error` is raised.
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002381 """
Alex Gaynor5af32d02016-09-24 01:52:21 -04002382 # Make this work on both OpenSSL 1.0.0, which doesn't support TLSv1.2
2383 # and also on OpenSSL 1.1.0 which doesn't support SSLv3. (SSL_ST_INIT
2384 # is a way to check for 1.1.0)
2385 if SSL_ST_INIT is not None:
2386 v1 = TLSv1_METHOD
2387 v2 = SSLv3_METHOD
2388 else:
2389 v1 = TLSv1_2_METHOD
2390 v2 = TLSv1_METHOD
2391
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002392 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2393 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
Alex Gaynor5af32d02016-09-24 01:52:21 -04002394 ctx = Context(v1)
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002395 ctx.use_privatekey(key)
2396 ctx.use_certificate(cert)
2397 ctx.set_session_id("unity-test")
2398
2399 def makeServer(socket):
2400 server = Connection(ctx, socket)
2401 server.set_accept_state()
2402 return server
2403
Alex Gaynor5af32d02016-09-24 01:52:21 -04002404 def makeOriginalClient(socket):
2405 client = Connection(Context(v1), socket)
2406 client.set_connect_state()
2407 return client
2408
Alex Chan1c0cb662017-01-30 07:13:30 +00002409 originalServer, originalClient = loopback(
2410 server_factory=makeServer, client_factory=makeOriginalClient)
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002411 originalSession = originalClient.get_session()
2412
2413 def makeClient(socket):
2414 # Intentionally use a different, incompatible method here.
Alex Gaynor5af32d02016-09-24 01:52:21 -04002415 client = Connection(Context(v2), socket)
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002416 client.set_connect_state()
2417 client.set_session(originalSession)
2418 return client
2419
Alex Chan1c0cb662017-01-30 07:13:30 +00002420 with pytest.raises(Error):
2421 loopback(client_factory=makeClient, server_factory=makeServer)
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002422
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002423 def test_wantWriteError(self):
2424 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002425 `Connection` methods which generate output raise
2426 `OpenSSL.SSL.WantWriteError` if writing to the connection's BIO
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002427 fail indicating a should-write state.
2428 """
2429 client_socket, server_socket = socket_pair()
2430 # Fill up the client's send buffer so Connection won't be able to write
Jean-Paul Calderonebbff8b92014-03-22 14:20:30 -04002431 # anything. Only write a single byte at a time so we can be sure we
2432 # completely fill the buffer. Even though the socket API is allowed to
2433 # signal a short write via its return value it seems this doesn't
2434 # always happen on all platforms (FreeBSD and OS X particular) for the
2435 # very last bit of available buffer space.
2436 msg = b"x"
2437 for i in range(1024 * 1024 * 4):
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002438 try:
2439 client_socket.send(msg)
2440 except error as e:
2441 if e.errno == EWOULDBLOCK:
2442 break
2443 raise
2444 else:
Alex Chan1c0cb662017-01-30 07:13:30 +00002445 pytest.fail(
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002446 "Failed to fill socket buffer, cannot test BIO want write")
2447
2448 ctx = Context(TLSv1_METHOD)
2449 conn = Connection(ctx, client_socket)
2450 # Client's speak first, so make it an SSL client
2451 conn.set_connect_state()
Alex Chan1c0cb662017-01-30 07:13:30 +00002452 with pytest.raises(WantWriteError):
2453 conn.do_handshake()
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002454
2455 # XXX want_read
2456
Fedor Brunner416f4a12014-03-28 13:18:38 +01002457 def test_get_finished_before_connect(self):
Fedor Brunner5747b932014-03-05 14:22:34 +01002458 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002459 `Connection.get_finished` returns `None` before TLS handshake
2460 is completed.
Fedor Brunner5747b932014-03-05 14:22:34 +01002461 """
Fedor Brunner5747b932014-03-05 14:22:34 +01002462 ctx = Context(TLSv1_METHOD)
2463 connection = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002464 assert connection.get_finished() is None
Fedor Brunner416f4a12014-03-28 13:18:38 +01002465
2466 def test_get_peer_finished_before_connect(self):
2467 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002468 `Connection.get_peer_finished` returns `None` before TLS handshake
2469 is completed.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002470 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002471 ctx = Context(TLSv1_METHOD)
2472 connection = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002473 assert connection.get_peer_finished() is None
Fedor Brunner5747b932014-03-05 14:22:34 +01002474
Fedor Brunner416f4a12014-03-28 13:18:38 +01002475 def test_get_finished(self):
2476 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002477 `Connection.get_finished` method returns the TLS Finished message send
2478 from client, or server. Finished messages are send during
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002479 TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002480 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002481 server, client = loopback()
Fedor Brunner416f4a12014-03-28 13:18:38 +01002482
Alex Chan1c0cb662017-01-30 07:13:30 +00002483 assert server.get_finished() is not None
2484 assert len(server.get_finished()) > 0
Fedor Brunner416f4a12014-03-28 13:18:38 +01002485
2486 def test_get_peer_finished(self):
2487 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002488 `Connection.get_peer_finished` method returns the TLS Finished
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002489 message received from client, or server. Finished messages are send
2490 during TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002491 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002492 server, client = loopback()
Fedor Brunner416f4a12014-03-28 13:18:38 +01002493
Alex Chan1c0cb662017-01-30 07:13:30 +00002494 assert server.get_peer_finished() is not None
2495 assert len(server.get_peer_finished()) > 0
Fedor Brunner5747b932014-03-05 14:22:34 +01002496
Fedor Brunner416f4a12014-03-28 13:18:38 +01002497 def test_tls_finished_message_symmetry(self):
2498 """
Hynek Schlawackdddd1112015-09-05 21:12:30 +02002499 The TLS Finished message send by server must be the TLS Finished
2500 message received by client.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002501
Hynek Schlawackdddd1112015-09-05 21:12:30 +02002502 The TLS Finished message send by client must be the TLS Finished
2503 message received by server.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002504 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002505 server, client = loopback()
Fedor Brunner416f4a12014-03-28 13:18:38 +01002506
Alex Chan1c0cb662017-01-30 07:13:30 +00002507 assert server.get_finished() == client.get_peer_finished()
2508 assert client.get_finished() == server.get_peer_finished()
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002509
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002510 def test_get_cipher_name_before_connect(self):
2511 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002512 `Connection.get_cipher_name` returns `None` if no connection
2513 has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002514 """
2515 ctx = Context(TLSv1_METHOD)
2516 conn = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002517 assert conn.get_cipher_name() is None
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002518
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002519 def test_get_cipher_name(self):
2520 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002521 `Connection.get_cipher_name` returns a `unicode` string giving the
2522 name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002523 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002524 server, client = loopback()
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002525 server_cipher_name, client_cipher_name = \
2526 server.get_cipher_name(), client.get_cipher_name()
2527
Alex Chan1c0cb662017-01-30 07:13:30 +00002528 assert isinstance(server_cipher_name, text_type)
2529 assert isinstance(client_cipher_name, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002530
Alex Chan1c0cb662017-01-30 07:13:30 +00002531 assert server_cipher_name == client_cipher_name
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002532
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002533 def test_get_cipher_version_before_connect(self):
2534 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002535 `Connection.get_cipher_version` returns `None` if no connection
2536 has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002537 """
2538 ctx = Context(TLSv1_METHOD)
2539 conn = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002540 assert conn.get_cipher_version() is None
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002541
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002542 def test_get_cipher_version(self):
2543 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002544 `Connection.get_cipher_version` returns a `unicode` string giving
2545 the protocol name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002546 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002547 server, client = loopback()
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002548 server_cipher_version, client_cipher_version = \
2549 server.get_cipher_version(), client.get_cipher_version()
2550
Alex Chan1c0cb662017-01-30 07:13:30 +00002551 assert isinstance(server_cipher_version, text_type)
2552 assert isinstance(client_cipher_version, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002553
Alex Chan1c0cb662017-01-30 07:13:30 +00002554 assert server_cipher_version == client_cipher_version
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002555
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002556 def test_get_cipher_bits_before_connect(self):
2557 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002558 `Connection.get_cipher_bits` returns `None` if no connection has
2559 been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002560 """
2561 ctx = Context(TLSv1_METHOD)
2562 conn = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002563 assert conn.get_cipher_bits() is None
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002564
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002565 def test_get_cipher_bits(self):
2566 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002567 `Connection.get_cipher_bits` returns the number of secret bits
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002568 of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002569 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002570 server, client = loopback()
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002571 server_cipher_bits, client_cipher_bits = \
2572 server.get_cipher_bits(), client.get_cipher_bits()
2573
Alex Chan1c0cb662017-01-30 07:13:30 +00002574 assert isinstance(server_cipher_bits, int)
2575 assert isinstance(client_cipher_bits, int)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002576
Alex Chan1c0cb662017-01-30 07:13:30 +00002577 assert server_cipher_bits == client_cipher_bits
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002578
Jim Shaverabff1882015-05-27 09:15:55 -04002579 def test_get_protocol_version_name(self):
2580 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002581 `Connection.get_protocol_version_name()` returns a string giving the
2582 protocol version of the current connection.
Jim Shaverabff1882015-05-27 09:15:55 -04002583 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002584 server, client = loopback()
Jim Shaverabff1882015-05-27 09:15:55 -04002585 client_protocol_version_name = client.get_protocol_version_name()
2586 server_protocol_version_name = server.get_protocol_version_name()
2587
Alex Chan1c0cb662017-01-30 07:13:30 +00002588 assert isinstance(server_protocol_version_name, text_type)
2589 assert isinstance(client_protocol_version_name, text_type)
Jim Shaverabff1882015-05-27 09:15:55 -04002590
Alex Chan1c0cb662017-01-30 07:13:30 +00002591 assert server_protocol_version_name == client_protocol_version_name
Jim Shaverabff1882015-05-27 09:15:55 -04002592
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002593 def test_get_protocol_version(self):
2594 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002595 `Connection.get_protocol_version()` returns an integer
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002596 giving the protocol version of the current connection.
2597 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002598 server, client = loopback()
Jim Shaver85a4dff2015-04-27 17:42:46 -04002599 client_protocol_version = client.get_protocol_version()
2600 server_protocol_version = server.get_protocol_version()
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002601
Alex Chan1c0cb662017-01-30 07:13:30 +00002602 assert isinstance(server_protocol_version, int)
2603 assert isinstance(client_protocol_version, int)
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002604
Alex Chan1c0cb662017-01-30 07:13:30 +00002605 assert server_protocol_version == client_protocol_version
2606
2607 def test_wantReadError(self):
2608 """
2609 `Connection.bio_read` raises `OpenSSL.SSL.WantReadError` if there are
2610 no bytes available to be read from the BIO.
2611 """
2612 ctx = Context(TLSv1_METHOD)
2613 conn = Connection(ctx, None)
2614 with pytest.raises(WantReadError):
2615 conn.bio_read(1024)
2616
2617 def test_buffer_size(self):
2618 """
2619 `Connection.bio_read` accepts an integer giving the maximum number
2620 of bytes to read and return.
2621 """
2622 ctx = Context(TLSv1_METHOD)
2623 conn = Connection(ctx, None)
2624 conn.set_connect_state()
2625 try:
2626 conn.do_handshake()
2627 except WantReadError:
2628 pass
2629 data = conn.bio_read(2)
2630 assert 2 == len(data)
2631
2632 @skip_if_py3
2633 def test_buffer_size_long(self):
2634 """
2635 On Python 2 `Connection.bio_read` accepts values of type `long` as
2636 well as `int`.
2637 """
2638 ctx = Context(TLSv1_METHOD)
2639 conn = Connection(ctx, None)
2640 conn.set_connect_state()
2641 try:
2642 conn.do_handshake()
2643 except WantReadError:
2644 pass
2645 data = conn.bio_read(long(2))
2646 assert 2 == len(data)
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002647
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002648
Alex Chanb7480992017-01-30 14:04:47 +00002649class TestConnectionGetCipherList(object):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002650 """
Alex Chanb7480992017-01-30 14:04:47 +00002651 Tests for `Connection.get_cipher_list`.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002652 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002653 def test_result(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002654 """
Alex Chanb7480992017-01-30 14:04:47 +00002655 `Connection.get_cipher_list` returns a list of `bytes` giving the
2656 names of the ciphers which might be used.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002657 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002658 connection = Connection(Context(TLSv1_METHOD), None)
2659 ciphers = connection.get_cipher_list()
Alex Chanb7480992017-01-30 14:04:47 +00002660 assert isinstance(ciphers, list)
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002661 for cipher in ciphers:
Alex Chanb7480992017-01-30 14:04:47 +00002662 assert isinstance(cipher, str)
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002663
2664
Alex Chanb7480992017-01-30 14:04:47 +00002665class TestConnectionSend(object):
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002666 """
Alex Chanb7480992017-01-30 14:04:47 +00002667 Tests for `Connection.send`.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002668 """
2669 def test_wrong_args(self):
2670 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002671 When called with arguments other than string argument for its first
Alex Chanb7480992017-01-30 14:04:47 +00002672 parameter, `Connection.send` raises `TypeError`.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002673 """
2674 connection = Connection(Context(TLSv1_METHOD), None)
Alex Chanb7480992017-01-30 14:04:47 +00002675 with pytest.raises(TypeError):
2676 connection.send(object())
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002677
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002678 def test_short_bytes(self):
2679 """
Alex Chanb7480992017-01-30 14:04:47 +00002680 When passed a short byte string, `Connection.send` transmits all of it
2681 and returns the number of bytes sent.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002682 """
Alex Chanb7480992017-01-30 14:04:47 +00002683 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002684 count = server.send(b'xy')
Alex Chanb7480992017-01-30 14:04:47 +00002685 assert count == 2
2686 assert client.recv(2) == b'xy'
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002687
Abraham Martinef063482015-03-25 14:06:24 +00002688 def test_text(self):
2689 """
Alex Chanb7480992017-01-30 14:04:47 +00002690 When passed a text, `Connection.send` transmits all of it and
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002691 returns the number of bytes sent. It also raises a DeprecationWarning.
Abraham Martinef063482015-03-25 14:06:24 +00002692 """
Alex Chanb7480992017-01-30 14:04:47 +00002693 server, client = loopback()
2694 with pytest.warns(DeprecationWarning) as w:
Abraham Martinef063482015-03-25 14:06:24 +00002695 simplefilter("always")
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002696 count = server.send(b"xy".decode("ascii"))
Alex Chanb7480992017-01-30 14:04:47 +00002697 assert (
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002698 "{0} for buf is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002699 WARNING_TYPE_EXPECTED
Alex Chanb7480992017-01-30 14:04:47 +00002700 ) == str(w[-1].message))
2701 assert count == 2
2702 assert client.recv(2) == b'xy'
Abraham Martinef063482015-03-25 14:06:24 +00002703
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002704 @skip_if_py26
2705 def test_short_memoryview(self):
2706 """
2707 When passed a memoryview onto a small number of bytes,
Alex Chanb7480992017-01-30 14:04:47 +00002708 `Connection.send` transmits all of them and returns the number
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002709 of bytes sent.
2710 """
Alex Chanb7480992017-01-30 14:04:47 +00002711 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002712 count = server.send(memoryview(b'xy'))
Alex Chanb7480992017-01-30 14:04:47 +00002713 assert count == 2
2714 assert client.recv(2) == b'xy'
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002715
Hynek Schlawack8e94f1b2015-09-05 21:31:00 +02002716 @skip_if_py3
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002717 def test_short_buffer(self):
2718 """
2719 When passed a buffer containing a small number of bytes,
Alex Chanb7480992017-01-30 14:04:47 +00002720 `Connection.send` transmits all of them and returns the number
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002721 of bytes sent.
2722 """
Alex Chanb7480992017-01-30 14:04:47 +00002723 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002724 count = server.send(buffer(b'xy'))
Alex Chanb7480992017-01-30 14:04:47 +00002725 assert count == 2
2726 assert client.recv(2) == b'xy'
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02002727
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05002728
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002729def _make_memoryview(size):
2730 """
2731 Create a new ``memoryview`` wrapped around a ``bytearray`` of the given
2732 size.
2733 """
2734 return memoryview(bytearray(size))
2735
2736
Alex Chanb7480992017-01-30 14:04:47 +00002737class TestConnectionRecvInto(object):
Cory Benfield62d10332014-06-15 10:03:41 +01002738 """
Alex Chanb7480992017-01-30 14:04:47 +00002739 Tests for `Connection.recv_into`.
Cory Benfield62d10332014-06-15 10:03:41 +01002740 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002741 def _no_length_test(self, factory):
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04002742 """
Alex Chanb7480992017-01-30 14:04:47 +00002743 Assert that when the given buffer is passed to `Connection.recv_into`,
2744 whatever bytes are available to be received that fit into that buffer
2745 are written into that buffer.
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04002746 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002747 output_buffer = factory(5)
2748
Alex Chanb7480992017-01-30 14:04:47 +00002749 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002750 server.send(b'xy')
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04002751
Alex Chanb7480992017-01-30 14:04:47 +00002752 assert client.recv_into(output_buffer) == 2
2753 assert output_buffer == bytearray(b'xy\x00\x00\x00')
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04002754
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002755 def test_bytearray_no_length(self):
Cory Benfield62d10332014-06-15 10:03:41 +01002756 """
Alex Chanb7480992017-01-30 14:04:47 +00002757 `Connection.recv_into` can be passed a `bytearray` instance and data
2758 in the receive buffer is written to it.
Cory Benfield62d10332014-06-15 10:03:41 +01002759 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002760 self._no_length_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01002761
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002762 def _respects_length_test(self, factory):
Cory Benfield62d10332014-06-15 10:03:41 +01002763 """
Alex Chanb7480992017-01-30 14:04:47 +00002764 Assert that when the given buffer is passed to `Connection.recv_into`
2765 along with a value for `nbytes` that is less than the size of that
2766 buffer, only `nbytes` bytes are written into the buffer.
Cory Benfield62d10332014-06-15 10:03:41 +01002767 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002768 output_buffer = factory(10)
2769
Alex Chanb7480992017-01-30 14:04:47 +00002770 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002771 server.send(b'abcdefghij')
Cory Benfield62d10332014-06-15 10:03:41 +01002772
Alex Chanb7480992017-01-30 14:04:47 +00002773 assert client.recv_into(output_buffer, 5) == 5
2774 assert output_buffer == bytearray(b'abcde\x00\x00\x00\x00\x00')
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002775
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002776 def test_bytearray_respects_length(self):
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002777 """
Alex Chanb7480992017-01-30 14:04:47 +00002778 When called with a `bytearray` instance, `Connection.recv_into`
2779 respects the `nbytes` parameter and doesn't copy in more than that
2780 number of bytes.
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002781 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002782 self._respects_length_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01002783
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002784 def _doesnt_overfill_test(self, factory):
Cory Benfield62d10332014-06-15 10:03:41 +01002785 """
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002786 Assert that if there are more bytes available to be read from the
2787 receive buffer than would fit into the buffer passed to
Alex Chanb7480992017-01-30 14:04:47 +00002788 `Connection.recv_into`, only as many as fit are written into it.
Cory Benfield62d10332014-06-15 10:03:41 +01002789 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002790 output_buffer = factory(5)
2791
Alex Chanb7480992017-01-30 14:04:47 +00002792 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002793 server.send(b'abcdefghij')
Cory Benfield62d10332014-06-15 10:03:41 +01002794
Alex Chanb7480992017-01-30 14:04:47 +00002795 assert client.recv_into(output_buffer) == 5
2796 assert output_buffer == bytearray(b'abcde')
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002797 rest = client.recv(5)
Alex Chanb7480992017-01-30 14:04:47 +00002798 assert b'fghij' == rest
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002799
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002800 def test_bytearray_doesnt_overfill(self):
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002801 """
Alex Chanb7480992017-01-30 14:04:47 +00002802 When called with a `bytearray` instance, `Connection.recv_into`
2803 respects the size of the array and doesn't write more bytes into it
2804 than will fit.
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002805 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002806 self._doesnt_overfill_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01002807
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002808 def test_bytearray_really_doesnt_overfill(self):
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04002809 """
Alex Chanb7480992017-01-30 14:04:47 +00002810 When called with a `bytearray` instance and an `nbytes` value that is
2811 too large, `Connection.recv_into` respects the size of the array and
2812 not the `nbytes` value and doesn't write more bytes into the buffer
2813 than will fit.
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04002814 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002815 self._doesnt_overfill_test(bytearray)
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04002816
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002817 def test_peek(self):
Alex Chanb7480992017-01-30 14:04:47 +00002818 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002819 server.send(b'xy')
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002820
2821 for _ in range(2):
2822 output_buffer = bytearray(5)
Alex Chanb7480992017-01-30 14:04:47 +00002823 assert client.recv_into(output_buffer, flags=MSG_PEEK) == 2
2824 assert output_buffer == bytearray(b'xy\x00\x00\x00')
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002825
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002826 @skip_if_py26
2827 def test_memoryview_no_length(self):
2828 """
Alex Chanb7480992017-01-30 14:04:47 +00002829 `Connection.recv_into` can be passed a `memoryview` instance and data
2830 in the receive buffer is written to it.
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002831 """
2832 self._no_length_test(_make_memoryview)
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002833
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002834 @skip_if_py26
2835 def test_memoryview_respects_length(self):
2836 """
Alex Chanb7480992017-01-30 14:04:47 +00002837 When called with a `memoryview` instance, `Connection.recv_into`
2838 respects the ``nbytes`` parameter and doesn't copy more than that
2839 number of bytes in.
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002840 """
2841 self._respects_length_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01002842
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002843 @skip_if_py26
2844 def test_memoryview_doesnt_overfill(self):
2845 """
Alex Chanb7480992017-01-30 14:04:47 +00002846 When called with a `memoryview` instance, `Connection.recv_into`
2847 respects the size of the array and doesn't write more bytes into it
2848 than will fit.
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002849 """
2850 self._doesnt_overfill_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01002851
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002852 @skip_if_py26
2853 def test_memoryview_really_doesnt_overfill(self):
2854 """
Alex Chanb7480992017-01-30 14:04:47 +00002855 When called with a `memoryview` instance and an `nbytes` value that is
2856 too large, `Connection.recv_into` respects the size of the array and
2857 not the `nbytes` value and doesn't write more bytes into the buffer
2858 than will fit.
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002859 """
2860 self._doesnt_overfill_test(_make_memoryview)
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04002861
Cory Benfield62d10332014-06-15 10:03:41 +01002862
Alex Chanb7480992017-01-30 14:04:47 +00002863class TestConnectionSendall(object):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002864 """
Alex Chanb7480992017-01-30 14:04:47 +00002865 Tests for `Connection.sendall`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002866 """
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002867 def test_wrong_args(self):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002868 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002869 When called with arguments other than a string argument for its first
Alex Chanb7480992017-01-30 14:04:47 +00002870 parameter, `Connection.sendall` raises `TypeError`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002871 """
2872 connection = Connection(Context(TLSv1_METHOD), None)
Alex Chanb7480992017-01-30 14:04:47 +00002873 with pytest.raises(TypeError):
2874 connection.sendall(object())
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002875
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002876 def test_short(self):
2877 """
Alex Chanb7480992017-01-30 14:04:47 +00002878 `Connection.sendall` transmits all of the bytes in the string
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02002879 passed to it.
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002880 """
Alex Chanb7480992017-01-30 14:04:47 +00002881 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002882 server.sendall(b'x')
Alex Chanb7480992017-01-30 14:04:47 +00002883 assert client.recv(1) == b'x'
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002884
Abraham Martinef063482015-03-25 14:06:24 +00002885 def test_text(self):
2886 """
Alex Chanb7480992017-01-30 14:04:47 +00002887 `Connection.sendall` transmits all the content in the string passed
2888 to it, raising a DeprecationWarning in case of this being a text.
Abraham Martinef063482015-03-25 14:06:24 +00002889 """
Alex Chanb7480992017-01-30 14:04:47 +00002890 server, client = loopback()
2891 with pytest.warns(DeprecationWarning) as w:
Abraham Martinef063482015-03-25 14:06:24 +00002892 simplefilter("always")
Jean-Paul Calderone8dc37a12015-03-29 08:16:52 -04002893 server.sendall(b"x".decode("ascii"))
Alex Chanb7480992017-01-30 14:04:47 +00002894 assert (
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002895 "{0} for buf is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002896 WARNING_TYPE_EXPECTED
Alex Chanb7480992017-01-30 14:04:47 +00002897 ) == str(w[-1].message))
2898 assert client.recv(1) == b"x"
Abraham Martinef063482015-03-25 14:06:24 +00002899
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02002900 @skip_if_py26
2901 def test_short_memoryview(self):
2902 """
2903 When passed a memoryview onto a small number of bytes,
Alex Chanb7480992017-01-30 14:04:47 +00002904 `Connection.sendall` transmits all of them.
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02002905 """
Alex Chanb7480992017-01-30 14:04:47 +00002906 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002907 server.sendall(memoryview(b'x'))
Alex Chanb7480992017-01-30 14:04:47 +00002908 assert client.recv(1) == b'x'
Abraham Martinef063482015-03-25 14:06:24 +00002909
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02002910 @skip_if_py3
2911 def test_short_buffers(self):
2912 """
2913 When passed a buffer containing a small number of bytes,
Alex Chanb7480992017-01-30 14:04:47 +00002914 `Connection.sendall` transmits all of them.
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02002915 """
Alex Chanb7480992017-01-30 14:04:47 +00002916 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002917 server.sendall(buffer(b'x'))
Alex Chanb7480992017-01-30 14:04:47 +00002918 assert client.recv(1) == b'x'
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02002919
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002920 def test_long(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002921 """
Alex Chanb7480992017-01-30 14:04:47 +00002922 `Connection.sendall` transmits all the bytes in the string passed to it
2923 even if this requires multiple calls of an underlying write function.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002924 """
Alex Chanb7480992017-01-30 14:04:47 +00002925 server, client = loopback()
Jean-Paul Calderone6241c702010-09-16 19:59:24 -04002926 # Should be enough, underlying SSL_write should only do 16k at a time.
Hynek Schlawack35618382015-09-05 21:54:25 +02002927 # On Windows, after 32k of bytes the write will block (forever
2928 # - because no one is yet reading).
Alex Gaynore7f51982016-09-11 11:48:14 -04002929 message = b'x' * (1024 * 32 - 1) + b'y'
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002930 server.sendall(message)
2931 accum = []
2932 received = 0
2933 while received < len(message):
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04002934 data = client.recv(1024)
2935 accum.append(data)
2936 received += len(data)
Alex Chanb7480992017-01-30 14:04:47 +00002937 assert message == b''.join(accum)
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002938
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04002939 def test_closed(self):
2940 """
Alex Chanb7480992017-01-30 14:04:47 +00002941 If the underlying socket is closed, `Connection.sendall` propagates the
2942 write error from the low level write call.
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04002943 """
Alex Chanb7480992017-01-30 14:04:47 +00002944 server, client = loopback()
Jean-Paul Calderone05d43e82010-09-24 18:01:36 -04002945 server.sock_shutdown(2)
Alex Chanb7480992017-01-30 14:04:47 +00002946 with pytest.raises(SysCallError) as err:
2947 server.sendall(b"hello, world")
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +02002948 if platform == "win32":
Alex Chanb7480992017-01-30 14:04:47 +00002949 assert err.value.args[0] == ESHUTDOWN
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +02002950 else:
Alex Chanb7480992017-01-30 14:04:47 +00002951 assert err.value.args[0] == EPIPE
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04002952
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002953
Alex Chanb7480992017-01-30 14:04:47 +00002954class TestConnectionRenegotiate(object):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002955 """
2956 Tests for SSL renegotiation APIs.
2957 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002958 def test_total_renegotiations(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002959 """
Alex Chanb7480992017-01-30 14:04:47 +00002960 `Connection.total_renegotiations` returns `0` before any renegotiations
2961 have happened.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002962 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002963 connection = Connection(Context(TLSv1_METHOD), None)
Alex Chanb7480992017-01-30 14:04:47 +00002964 assert connection.total_renegotiations() == 0
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002965
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01002966 def test_renegotiate(self):
2967 """
2968 Go through a complete renegotiation cycle.
2969 """
Alex Chanb7480992017-01-30 14:04:47 +00002970 server, client = loopback()
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002971
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01002972 server.send(b"hello world")
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002973
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01002974 assert b"hello world" == client.recv(len(b"hello world"))
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002975
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01002976 assert 0 == server.total_renegotiations()
2977 assert False is server.renegotiate_pending()
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002978
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01002979 assert True is server.renegotiate()
2980
2981 assert True is server.renegotiate_pending()
2982
2983 server.setblocking(False)
2984 client.setblocking(False)
2985
2986 client.do_handshake()
2987 server.do_handshake()
2988
2989 assert 1 == server.total_renegotiations()
2990 while False is server.renegotiate_pending():
2991 pass
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002992
2993
Alex Chanb7480992017-01-30 14:04:47 +00002994class TestError(object):
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002995 """
Alex Chanb7480992017-01-30 14:04:47 +00002996 Unit tests for `OpenSSL.SSL.Error`.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002997 """
2998 def test_type(self):
2999 """
Alex Chanb7480992017-01-30 14:04:47 +00003000 `Error` is an exception type.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003001 """
Alex Chanb7480992017-01-30 14:04:47 +00003002 assert issubclass(Error, Exception)
3003 assert Error.__name__ == 'Error'
Rick Deane15b1472009-07-09 15:53:42 -05003004
3005
Alex Chanb7480992017-01-30 14:04:47 +00003006class TestConstants(object):
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003007 """
Alex Chanb7480992017-01-30 14:04:47 +00003008 Tests for the values of constants exposed in `OpenSSL.SSL`.
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003009
3010 These are values defined by OpenSSL intended only to be used as flags to
3011 OpenSSL APIs. The only assertions it seems can be made about them is
3012 their values.
3013 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003014 @pytest.mark.skipif(
3015 OP_NO_QUERY_MTU is None,
3016 reason="OP_NO_QUERY_MTU unavailable - OpenSSL version may be too old"
3017 )
3018 def test_op_no_query_mtu(self):
3019 """
Alex Chanb7480992017-01-30 14:04:47 +00003020 The value of `OpenSSL.SSL.OP_NO_QUERY_MTU` is 0x1000, the value
3021 of `SSL_OP_NO_QUERY_MTU` defined by `openssl/ssl.h`.
Hynek Schlawack35618382015-09-05 21:54:25 +02003022 """
Alex Chanb7480992017-01-30 14:04:47 +00003023 assert OP_NO_QUERY_MTU == 0x1000
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003024
Hynek Schlawack35618382015-09-05 21:54:25 +02003025 @pytest.mark.skipif(
3026 OP_COOKIE_EXCHANGE is None,
3027 reason="OP_COOKIE_EXCHANGE unavailable - "
3028 "OpenSSL version may be too old"
3029 )
3030 def test_op_cookie_exchange(self):
3031 """
Alex Chanb7480992017-01-30 14:04:47 +00003032 The value of `OpenSSL.SSL.OP_COOKIE_EXCHANGE` is 0x2000, the
3033 value of `SSL_OP_COOKIE_EXCHANGE` defined by `openssl/ssl.h`.
Hynek Schlawack35618382015-09-05 21:54:25 +02003034 """
Alex Chanb7480992017-01-30 14:04:47 +00003035 assert OP_COOKIE_EXCHANGE == 0x2000
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003036
Hynek Schlawack35618382015-09-05 21:54:25 +02003037 @pytest.mark.skipif(
3038 OP_NO_TICKET is None,
3039 reason="OP_NO_TICKET unavailable - OpenSSL version may be too old"
3040 )
3041 def test_op_no_ticket(self):
3042 """
Alex Chanb7480992017-01-30 14:04:47 +00003043 The value of `OpenSSL.SSL.OP_NO_TICKET` is 0x4000, the value of
3044 `SSL_OP_NO_TICKET` defined by `openssl/ssl.h`.
Hynek Schlawack35618382015-09-05 21:54:25 +02003045 """
Alex Chanb7480992017-01-30 14:04:47 +00003046 assert OP_NO_TICKET == 0x4000
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003047
Hynek Schlawack35618382015-09-05 21:54:25 +02003048 @pytest.mark.skipif(
3049 OP_NO_COMPRESSION is None,
3050 reason="OP_NO_COMPRESSION unavailable - OpenSSL version may be too old"
3051 )
3052 def test_op_no_compression(self):
3053 """
Alex Chanb7480992017-01-30 14:04:47 +00003054 The value of `OpenSSL.SSL.OP_NO_COMPRESSION` is 0x20000, the
3055 value of `SSL_OP_NO_COMPRESSION` defined by `openssl/ssl.h`.
Hynek Schlawack35618382015-09-05 21:54:25 +02003056 """
Alex Chanb7480992017-01-30 14:04:47 +00003057 assert OP_NO_COMPRESSION == 0x20000
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04003058
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003059 def test_sess_cache_off(self):
3060 """
Alex Chanb7480992017-01-30 14:04:47 +00003061 The value of `OpenSSL.SSL.SESS_CACHE_OFF` 0x0, the value of
3062 `SSL_SESS_CACHE_OFF` defined by `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003063 """
Alex Chanb7480992017-01-30 14:04:47 +00003064 assert 0x0 == SESS_CACHE_OFF
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003065
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003066 def test_sess_cache_client(self):
3067 """
Alex Chanb7480992017-01-30 14:04:47 +00003068 The value of `OpenSSL.SSL.SESS_CACHE_CLIENT` 0x1, the value of
3069 `SSL_SESS_CACHE_CLIENT` defined by `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003070 """
Alex Chanb7480992017-01-30 14:04:47 +00003071 assert 0x1 == SESS_CACHE_CLIENT
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003072
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003073 def test_sess_cache_server(self):
3074 """
Alex Chanb7480992017-01-30 14:04:47 +00003075 The value of `OpenSSL.SSL.SESS_CACHE_SERVER` 0x2, the value of
3076 `SSL_SESS_CACHE_SERVER` defined by `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003077 """
Alex Chanb7480992017-01-30 14:04:47 +00003078 assert 0x2 == SESS_CACHE_SERVER
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003079
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003080 def test_sess_cache_both(self):
3081 """
Alex Chanb7480992017-01-30 14:04:47 +00003082 The value of `OpenSSL.SSL.SESS_CACHE_BOTH` 0x3, the value of
3083 `SSL_SESS_CACHE_BOTH` defined by `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003084 """
Alex Chanb7480992017-01-30 14:04:47 +00003085 assert 0x3 == SESS_CACHE_BOTH
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003086
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003087 def test_sess_cache_no_auto_clear(self):
3088 """
Alex Chanb7480992017-01-30 14:04:47 +00003089 The value of `OpenSSL.SSL.SESS_CACHE_NO_AUTO_CLEAR` 0x80, the
3090 value of `SSL_SESS_CACHE_NO_AUTO_CLEAR` defined by
3091 `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003092 """
Alex Chanb7480992017-01-30 14:04:47 +00003093 assert 0x80 == SESS_CACHE_NO_AUTO_CLEAR
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003094
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003095 def test_sess_cache_no_internal_lookup(self):
3096 """
Alex Chanb7480992017-01-30 14:04:47 +00003097 The value of `OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_LOOKUP` 0x100,
3098 the value of `SSL_SESS_CACHE_NO_INTERNAL_LOOKUP` defined by
3099 `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003100 """
Alex Chanb7480992017-01-30 14:04:47 +00003101 assert 0x100 == SESS_CACHE_NO_INTERNAL_LOOKUP
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003102
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003103 def test_sess_cache_no_internal_store(self):
3104 """
Alex Chanb7480992017-01-30 14:04:47 +00003105 The value of `OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_STORE` 0x200,
3106 the value of `SSL_SESS_CACHE_NO_INTERNAL_STORE` defined by
3107 `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003108 """
Alex Chanb7480992017-01-30 14:04:47 +00003109 assert 0x200 == SESS_CACHE_NO_INTERNAL_STORE
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003110
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003111 def test_sess_cache_no_internal(self):
3112 """
Alex Chanb7480992017-01-30 14:04:47 +00003113 The value of `OpenSSL.SSL.SESS_CACHE_NO_INTERNAL` 0x300, the
3114 value of `SSL_SESS_CACHE_NO_INTERNAL` defined by
3115 `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003116 """
Alex Chanb7480992017-01-30 14:04:47 +00003117 assert 0x300 == SESS_CACHE_NO_INTERNAL
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003118
3119
Alex Chanb7480992017-01-30 14:04:47 +00003120class TestMemoryBIO(object):
Rick Deanb71c0d22009-04-01 14:09:23 -05003121 """
Alex Chanb7480992017-01-30 14:04:47 +00003122 Tests for `OpenSSL.SSL.Connection` using a memory BIO.
Rick Deanb71c0d22009-04-01 14:09:23 -05003123 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003124 def _server(self, sock):
3125 """
Alex Chanb7480992017-01-30 14:04:47 +00003126 Create a new server-side SSL `Connection` object wrapped around `sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003127 """
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003128 # Create the server side Connection. This is mostly setup boilerplate
3129 # - use TLSv1, use a particular certificate, etc.
3130 server_ctx = Context(TLSv1_METHOD)
Alex Gaynor43307782015-09-04 09:05:45 -04003131 server_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE)
Hynek Schlawack35618382015-09-05 21:54:25 +02003132 server_ctx.set_verify(
3133 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT | VERIFY_CLIENT_ONCE,
3134 verify_cb
3135 )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003136 server_store = server_ctx.get_cert_store()
Hynek Schlawack35618382015-09-05 21:54:25 +02003137 server_ctx.use_privatekey(
3138 load_privatekey(FILETYPE_PEM, server_key_pem))
3139 server_ctx.use_certificate(
3140 load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003141 server_ctx.check_privatekey()
3142 server_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Hynek Schlawack35618382015-09-05 21:54:25 +02003143 # Here the Connection is actually created. If None is passed as the
3144 # 2nd parameter, it indicates a memory BIO should be created.
Rick Deanb1ccd562009-07-09 23:52:39 -05003145 server_conn = Connection(server_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003146 server_conn.set_accept_state()
3147 return server_conn
3148
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003149 def _client(self, sock):
3150 """
Alex Chanb7480992017-01-30 14:04:47 +00003151 Create a new client-side SSL `Connection` object wrapped around `sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003152 """
3153 # Now create the client side Connection. Similar boilerplate to the
3154 # above.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003155 client_ctx = Context(TLSv1_METHOD)
Alex Gaynor43307782015-09-04 09:05:45 -04003156 client_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE)
Hynek Schlawack35618382015-09-05 21:54:25 +02003157 client_ctx.set_verify(
3158 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT | VERIFY_CLIENT_ONCE,
3159 verify_cb
3160 )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003161 client_store = client_ctx.get_cert_store()
Hynek Schlawack35618382015-09-05 21:54:25 +02003162 client_ctx.use_privatekey(
3163 load_privatekey(FILETYPE_PEM, client_key_pem))
3164 client_ctx.use_certificate(
3165 load_certificate(FILETYPE_PEM, client_cert_pem))
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003166 client_ctx.check_privatekey()
3167 client_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05003168 client_conn = Connection(client_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003169 client_conn.set_connect_state()
3170 return client_conn
3171
Alex Chanb7480992017-01-30 14:04:47 +00003172 def test_memory_connect(self):
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003173 """
Alex Chanb7480992017-01-30 14:04:47 +00003174 Two `Connection`s which use memory BIOs can be manually connected by
3175 reading from the output of each and writing those bytes to the input of
3176 the other and in this way establish a connection and exchange
3177 application-level bytes with each other.
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003178 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003179 server_conn = self._server(None)
3180 client_conn = self._client(None)
Rick Deanb71c0d22009-04-01 14:09:23 -05003181
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003182 # There should be no key or nonces yet.
Alex Chanb7480992017-01-30 14:04:47 +00003183 assert server_conn.master_key() is None
3184 assert server_conn.client_random() is None
3185 assert server_conn.server_random() is None
Rick Deanb71c0d22009-04-01 14:09:23 -05003186
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003187 # First, the handshake needs to happen. We'll deliver bytes back and
3188 # forth between the client and server until neither of them feels like
3189 # speaking any more.
Alex Chanb7480992017-01-30 14:04:47 +00003190 assert interact_in_memory(client_conn, server_conn) is None
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003191
3192 # Now that the handshake is done, there should be a key and nonces.
Alex Chanb7480992017-01-30 14:04:47 +00003193 assert server_conn.master_key() is not None
3194 assert server_conn.client_random() is not None
3195 assert server_conn.server_random() is not None
3196 assert server_conn.client_random() == client_conn.client_random()
3197 assert server_conn.server_random() == client_conn.server_random()
3198 assert server_conn.client_random() != server_conn.server_random()
3199 assert client_conn.client_random() != client_conn.server_random()
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003200
3201 # Here are the bytes we'll try to send.
Alex Gaynore7f51982016-09-11 11:48:14 -04003202 important_message = b'One if by land, two if by sea.'
Rick Deanb71c0d22009-04-01 14:09:23 -05003203
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003204 server_conn.write(important_message)
Alex Chanb7480992017-01-30 14:04:47 +00003205 assert (
3206 interact_in_memory(client_conn, server_conn) ==
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003207 (client_conn, important_message))
3208
3209 client_conn.write(important_message[::-1])
Alex Chanb7480992017-01-30 14:04:47 +00003210 assert (
3211 interact_in_memory(client_conn, server_conn) ==
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003212 (server_conn, important_message[::-1]))
Rick Deanb71c0d22009-04-01 14:09:23 -05003213
Alex Chanb7480992017-01-30 14:04:47 +00003214 def test_socket_connect(self):
Rick Deanb1ccd562009-07-09 23:52:39 -05003215 """
Alex Chanb7480992017-01-30 14:04:47 +00003216 Just like `test_memory_connect` but with an actual socket.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003217
Hynek Schlawack35618382015-09-05 21:54:25 +02003218 This is primarily to rule out the memory BIO code as the source of any
Alex Chanb7480992017-01-30 14:04:47 +00003219 problems encountered while passing data over a `Connection` (if
Hynek Schlawack35618382015-09-05 21:54:25 +02003220 this test fails, there must be a problem outside the memory BIO code,
3221 as no memory BIO is involved here). Even though this isn't a memory
3222 BIO test, it's convenient to have it here.
Rick Deanb1ccd562009-07-09 23:52:39 -05003223 """
Alex Chanb7480992017-01-30 14:04:47 +00003224 server_conn, client_conn = loopback()
Rick Deanb1ccd562009-07-09 23:52:39 -05003225
Alex Gaynore7f51982016-09-11 11:48:14 -04003226 important_message = b"Help me Obi Wan Kenobi, you're my only hope."
Rick Deanb1ccd562009-07-09 23:52:39 -05003227 client_conn.send(important_message)
3228 msg = server_conn.recv(1024)
Alex Chanb7480992017-01-30 14:04:47 +00003229 assert msg == important_message
Rick Deanb1ccd562009-07-09 23:52:39 -05003230
3231 # Again in the other direction, just for fun.
3232 important_message = important_message[::-1]
3233 server_conn.send(important_message)
3234 msg = client_conn.recv(1024)
Alex Chanb7480992017-01-30 14:04:47 +00003235 assert msg == important_message
Rick Deanb1ccd562009-07-09 23:52:39 -05003236
Alex Chanb7480992017-01-30 14:04:47 +00003237 def test_socket_overrides_memory(self):
Rick Deanb71c0d22009-04-01 14:09:23 -05003238 """
Alex Chanb7480992017-01-30 14:04:47 +00003239 Test that `OpenSSL.SSL.bio_read` and `OpenSSL.SSL.bio_write` don't
3240 work on `OpenSSL.SSL.Connection`() that use sockets.
Rick Deanb71c0d22009-04-01 14:09:23 -05003241 """
Alex Gaynor51d424c2016-09-10 14:50:11 -04003242 context = Context(TLSv1_METHOD)
Rick Deanb71c0d22009-04-01 14:09:23 -05003243 client = socket()
3244 clientSSL = Connection(context, client)
Alex Chanb7480992017-01-30 14:04:47 +00003245 with pytest.raises(TypeError):
3246 clientSSL.bio_read(100)
3247 with pytest.raises(TypeError):
3248 clientSSL.bio_write("foo")
3249 with pytest.raises(TypeError):
3250 clientSSL.bio_shutdown()
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003251
Alex Chanb7480992017-01-30 14:04:47 +00003252 def test_outgoing_overflow(self):
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003253 """
3254 If more bytes than can be written to the memory BIO are passed to
Alex Chanb7480992017-01-30 14:04:47 +00003255 `Connection.send` at once, the number of bytes which were written is
3256 returned and that many bytes from the beginning of the input can be
3257 read from the other end of the connection.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003258 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003259 server = self._server(None)
3260 client = self._client(None)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003261
Alex Chanb7480992017-01-30 14:04:47 +00003262 interact_in_memory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003263
3264 size = 2 ** 15
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003265 sent = client.send(b"x" * size)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003266 # Sanity check. We're trying to test what happens when the entire
3267 # input can't be sent. If the entire input was sent, this test is
3268 # meaningless.
Alex Chanb7480992017-01-30 14:04:47 +00003269 assert sent < size
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003270
Alex Chanb7480992017-01-30 14:04:47 +00003271 receiver, received = interact_in_memory(client, server)
3272 assert receiver is server
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003273
3274 # We can rely on all of these bytes being received at once because
Alex Chanb7480992017-01-30 14:04:47 +00003275 # loopback passes 2 ** 16 to recv - more than 2 ** 15.
3276 assert len(received) == sent
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003277
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003278 def test_shutdown(self):
3279 """
Alex Chanb7480992017-01-30 14:04:47 +00003280 `Connection.bio_shutdown` signals the end of the data stream
3281 from which the `Connection` reads.
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003282 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003283 server = self._server(None)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003284 server.bio_shutdown()
Alex Chanb7480992017-01-30 14:04:47 +00003285 with pytest.raises(Error) as err:
3286 server.recv(1024)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003287 # We don't want WantReadError or ZeroReturnError or anything - it's a
3288 # handshake failure.
Alex Chanb7480992017-01-30 14:04:47 +00003289 assert type(err.value) in [Error, SysCallError]
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003290
Alex Chanb7480992017-01-30 14:04:47 +00003291 def test_unexpected_EOF(self):
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003292 """
3293 If the connection is lost before an orderly SSL shutdown occurs,
Alex Chanb7480992017-01-30 14:04:47 +00003294 `OpenSSL.SSL.SysCallError` is raised with a message of
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003295 "Unexpected EOF".
3296 """
Alex Chanb7480992017-01-30 14:04:47 +00003297 server_conn, client_conn = loopback()
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003298 client_conn.sock_shutdown(SHUT_RDWR)
Alex Chanb7480992017-01-30 14:04:47 +00003299 with pytest.raises(SysCallError) as err:
3300 server_conn.recv(1024)
3301 assert err.value.args == (-1, "Unexpected EOF")
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003302
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003303 def _check_client_ca_list(self, func):
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003304 """
Alex Chanb7480992017-01-30 14:04:47 +00003305 Verify the return value of the `get_client_ca_list` method for
Hynek Schlawack35618382015-09-05 21:54:25 +02003306 server and client connections.
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003307
Jonathan Ballet78b92a22011-07-16 08:07:26 +09003308 :param func: A function which will be called with the server context
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003309 before the client and server are connected to each other. This
3310 function should specify a list of CAs for the server to send to the
3311 client and return that same list. The list will be used to verify
Alex Chanb7480992017-01-30 14:04:47 +00003312 that `get_client_ca_list` returns the proper value at
Hynek Schlawack35618382015-09-05 21:54:25 +02003313 various times.
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003314 """
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003315 server = self._server(None)
3316 client = self._client(None)
Alex Chanb7480992017-01-30 14:04:47 +00003317 assert client.get_client_ca_list() == []
3318 assert server.get_client_ca_list() == []
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003319 ctx = server.get_context()
3320 expected = func(ctx)
Alex Chanb7480992017-01-30 14:04:47 +00003321 assert client.get_client_ca_list() == []
3322 assert server.get_client_ca_list() == expected
3323 interact_in_memory(client, server)
3324 assert client.get_client_ca_list() == expected
3325 assert server.get_client_ca_list() == expected
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003326
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003327 def test_set_client_ca_list_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003328 """
Alex Chanb7480992017-01-30 14:04:47 +00003329 `Context.set_client_ca_list` raises a `TypeError` if called with a
3330 non-list or a list that contains objects other than X509Names.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003331 """
3332 ctx = Context(TLSv1_METHOD)
Alex Chanb7480992017-01-30 14:04:47 +00003333 with pytest.raises(TypeError):
3334 ctx.set_client_ca_list("spam")
3335 with pytest.raises(TypeError):
3336 ctx.set_client_ca_list(["spam"])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003337
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003338 def test_set_empty_ca_list(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003339 """
Alex Chanb7480992017-01-30 14:04:47 +00003340 If passed an empty list, `Context.set_client_ca_list` configures the
3341 context to send no CA names to the client and, on both the server and
3342 client sides, `Connection.get_client_ca_list` returns an empty list
3343 after the connection is set up.
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003344 """
3345 def no_ca(ctx):
3346 ctx.set_client_ca_list([])
3347 return []
3348 self._check_client_ca_list(no_ca)
3349
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003350 def test_set_one_ca_list(self):
3351 """
3352 If passed a list containing a single X509Name,
Alex Chanb7480992017-01-30 14:04:47 +00003353 `Context.set_client_ca_list` configures the context to send
Hynek Schlawack35618382015-09-05 21:54:25 +02003354 that CA name to the client and, on both the server and client sides,
Alex Chanb7480992017-01-30 14:04:47 +00003355 `Connection.get_client_ca_list` returns a list containing that
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003356 X509Name after the connection is set up.
3357 """
3358 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3359 cadesc = cacert.get_subject()
Hynek Schlawack35618382015-09-05 21:54:25 +02003360
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003361 def single_ca(ctx):
3362 ctx.set_client_ca_list([cadesc])
3363 return [cadesc]
3364 self._check_client_ca_list(single_ca)
3365
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003366 def test_set_multiple_ca_list(self):
3367 """
3368 If passed a list containing multiple X509Name objects,
Alex Chanb7480992017-01-30 14:04:47 +00003369 `Context.set_client_ca_list` configures the context to send
Hynek Schlawack35618382015-09-05 21:54:25 +02003370 those CA names to the client and, on both the server and client sides,
Alex Chanb7480992017-01-30 14:04:47 +00003371 `Connection.get_client_ca_list` returns a list containing those
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003372 X509Names after the connection is set up.
3373 """
3374 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3375 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3376
3377 sedesc = secert.get_subject()
3378 cldesc = clcert.get_subject()
3379
3380 def multiple_ca(ctx):
3381 L = [sedesc, cldesc]
3382 ctx.set_client_ca_list(L)
3383 return L
3384 self._check_client_ca_list(multiple_ca)
3385
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003386 def test_reset_ca_list(self):
3387 """
3388 If called multiple times, only the X509Names passed to the final call
Alex Chanb7480992017-01-30 14:04:47 +00003389 of `Context.set_client_ca_list` are used to configure the CA
Hynek Schlawack35618382015-09-05 21:54:25 +02003390 names sent to the client.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003391 """
3392 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3393 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3394 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3395
3396 cadesc = cacert.get_subject()
3397 sedesc = secert.get_subject()
3398 cldesc = clcert.get_subject()
3399
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003400 def changed_ca(ctx):
3401 ctx.set_client_ca_list([sedesc, cldesc])
3402 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003403 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003404 self._check_client_ca_list(changed_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003405
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003406 def test_mutated_ca_list(self):
3407 """
Alex Chanb7480992017-01-30 14:04:47 +00003408 If the list passed to `Context.set_client_ca_list` is mutated
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003409 afterwards, this does not affect the list of CA names sent to the
3410 client.
3411 """
3412 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3413 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3414
3415 cadesc = cacert.get_subject()
3416 sedesc = secert.get_subject()
3417
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003418 def mutated_ca(ctx):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003419 L = [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003420 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003421 L.append(sedesc)
3422 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003423 self._check_client_ca_list(mutated_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003424
Alex Chanb7480992017-01-30 14:04:47 +00003425 def test_add_client_ca_wrong_args(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003426 """
Alex Chanb7480992017-01-30 14:04:47 +00003427 `Context.add_client_ca` raises `TypeError` if called with
3428 a non-X509 object.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003429 """
3430 ctx = Context(TLSv1_METHOD)
Alex Chanb7480992017-01-30 14:04:47 +00003431 with pytest.raises(TypeError):
3432 ctx.add_client_ca("spam")
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003433
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003434 def test_one_add_client_ca(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003435 """
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003436 A certificate's subject can be added as a CA to be sent to the client
Alex Chanb7480992017-01-30 14:04:47 +00003437 with `Context.add_client_ca`.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003438 """
3439 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3440 cadesc = cacert.get_subject()
Hynek Schlawack35618382015-09-05 21:54:25 +02003441
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003442 def single_ca(ctx):
3443 ctx.add_client_ca(cacert)
3444 return [cadesc]
3445 self._check_client_ca_list(single_ca)
3446
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003447 def test_multiple_add_client_ca(self):
3448 """
3449 Multiple CA names can be sent to the client by calling
Alex Chanb7480992017-01-30 14:04:47 +00003450 `Context.add_client_ca` with multiple X509 objects.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003451 """
3452 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3453 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3454
3455 cadesc = cacert.get_subject()
3456 sedesc = secert.get_subject()
3457
3458 def multiple_ca(ctx):
3459 ctx.add_client_ca(cacert)
3460 ctx.add_client_ca(secert)
3461 return [cadesc, sedesc]
3462 self._check_client_ca_list(multiple_ca)
3463
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003464 def test_set_and_add_client_ca(self):
3465 """
Alex Chanb7480992017-01-30 14:04:47 +00003466 A call to `Context.set_client_ca_list` followed by a call to
3467 `Context.add_client_ca` results in using the CA names from the
Hynek Schlawack35618382015-09-05 21:54:25 +02003468 first call and the CA name from the second call.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003469 """
3470 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3471 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3472 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3473
3474 cadesc = cacert.get_subject()
3475 sedesc = secert.get_subject()
3476 cldesc = clcert.get_subject()
3477
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003478 def mixed_set_add_ca(ctx):
3479 ctx.set_client_ca_list([cadesc, sedesc])
3480 ctx.add_client_ca(clcert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003481 return [cadesc, sedesc, cldesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003482 self._check_client_ca_list(mixed_set_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003483
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003484 def test_set_after_add_client_ca(self):
3485 """
Alex Chanb7480992017-01-30 14:04:47 +00003486 A call to `Context.set_client_ca_list` after a call to
3487 `Context.add_client_ca` replaces the CA name specified by the
Hynek Schlawack35618382015-09-05 21:54:25 +02003488 former call with the names specified by the latter call.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003489 """
3490 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3491 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3492 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3493
3494 cadesc = cacert.get_subject()
3495 sedesc = secert.get_subject()
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003496
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003497 def set_replaces_add_ca(ctx):
3498 ctx.add_client_ca(clcert)
3499 ctx.set_client_ca_list([cadesc])
3500 ctx.add_client_ca(secert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003501 return [cadesc, sedesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003502 self._check_client_ca_list(set_replaces_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003503
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003504
Alex Chanb7480992017-01-30 14:04:47 +00003505class TestInfoConstants(object):
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003506 """
3507 Tests for assorted constants exposed for use in info callbacks.
3508 """
3509 def test_integers(self):
3510 """
3511 All of the info constants are integers.
3512
3513 This is a very weak test. It would be nice to have one that actually
3514 verifies that as certain info events happen, the value passed to the
3515 info callback matches up with the constant exposed by OpenSSL.SSL.
3516 """
3517 for const in [
Alex Gaynor5af32d02016-09-24 01:52:21 -04003518 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK,
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003519 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
3520 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
3521 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
Hynek Schlawack35618382015-09-05 21:54:25 +02003522 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE
3523 ]:
Alex Gaynor5af32d02016-09-24 01:52:21 -04003524 assert isinstance(const, int)
3525
3526 # These constants don't exist on OpenSSL 1.1.0
3527 for const in [
3528 SSL_ST_INIT, SSL_ST_BEFORE, SSL_ST_OK, SSL_ST_RENEGOTIATE
3529 ]:
3530 assert const is None or isinstance(const, int)
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003531
Ziga Seilnacht44611bf2009-08-31 20:49:30 +02003532
Cory Benfield1d142142016-03-30 11:51:45 +01003533class TestRequires(object):
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003534 """
3535 Tests for the decorator factory used to conditionally raise
Cory Benfield1d142142016-03-30 11:51:45 +01003536 NotImplementedError when older OpenSSLs are used.
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003537 """
3538 def test_available(self):
3539 """
3540 When the OpenSSL functionality is available the decorated functions
3541 work appropriately.
3542 """
3543 feature_guard = _make_requires(True, "Error text")
3544 results = []
3545
3546 @feature_guard
3547 def inner():
3548 results.append(True)
3549 return True
3550
Cory Benfield2333e5e2016-03-30 14:24:16 +01003551 assert inner() is True
3552 assert [True] == results
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003553
3554 def test_unavailable(self):
3555 """
3556 When the OpenSSL functionality is not available the decorated function
3557 does not execute and NotImplementedError is raised.
3558 """
3559 feature_guard = _make_requires(False, "Error text")
3560 results = []
3561
3562 @feature_guard
3563 def inner():
3564 results.append(True)
3565 return True
3566
Cory Benfield1d142142016-03-30 11:51:45 +01003567 with pytest.raises(NotImplementedError) as e:
3568 inner()
3569
3570 assert "Error text" in str(e.value)
Cory Benfield2333e5e2016-03-30 14:24:16 +01003571 assert results == []
Cory Benfield496652a2017-01-24 11:42:56 +00003572
3573
Alex Chanb7480992017-01-30 14:04:47 +00003574class TestOCSP(object):
Cory Benfield496652a2017-01-24 11:42:56 +00003575 """
3576 Tests for PyOpenSSL's OCSP stapling support.
3577 """
3578 sample_ocsp_data = b"this is totally ocsp data"
3579
3580 def _client_connection(self, callback, data, request_ocsp=True):
3581 """
3582 Builds a client connection suitable for using OCSP.
3583
3584 :param callback: The callback to register for OCSP.
3585 :param data: The opaque data object that will be handed to the
3586 OCSP callback.
3587 :param request_ocsp: Whether the client will actually ask for OCSP
3588 stapling. Useful for testing only.
3589 """
3590 ctx = Context(SSLv23_METHOD)
3591 ctx.set_ocsp_client_callback(callback, data)
3592 client = Connection(ctx)
3593
3594 if request_ocsp:
3595 client.request_ocsp()
3596
3597 client.set_connect_state()
3598 return client
3599
3600 def _server_connection(self, callback, data):
3601 """
3602 Builds a server connection suitable for using OCSP.
3603
3604 :param callback: The callback to register for OCSP.
3605 :param data: The opaque data object that will be handed to the
3606 OCSP callback.
3607 """
3608 ctx = Context(SSLv23_METHOD)
3609 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
3610 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
3611 ctx.set_ocsp_server_callback(callback, data)
3612 server = Connection(ctx)
3613 server.set_accept_state()
3614 return server
3615
3616 def test_callbacks_arent_called_by_default(self):
3617 """
3618 If both the client and the server have registered OCSP callbacks, but
3619 the client does not send the OCSP request, neither callback gets
3620 called.
3621 """
3622 called = []
3623
3624 def ocsp_callback(*args, **kwargs):
3625 called.append((args, kwargs))
3626
3627 client = self._client_connection(
3628 callback=ocsp_callback, data=None, request_ocsp=False
3629 )
3630 server = self._server_connection(callback=ocsp_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00003631 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003632
3633 assert not called
3634
3635 def test_client_negotiates_without_server(self):
3636 """
3637 If the client wants to do OCSP but the server does not, the handshake
3638 succeeds, and the client callback fires with an empty byte string.
3639 """
3640 called = []
3641
3642 def ocsp_callback(conn, ocsp_data, ignored):
3643 called.append(ocsp_data)
3644 return True
3645
3646 client = self._client_connection(callback=ocsp_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00003647 server = loopback_server_factory(socket=None)
3648 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003649
3650 assert len(called) == 1
3651 assert called[0] == b''
3652
3653 def test_client_receives_servers_data(self):
3654 """
3655 The data the server sends in its callback is received by the client.
3656 """
3657 calls = []
3658
3659 def server_callback(*args, **kwargs):
3660 return self.sample_ocsp_data
3661
3662 def client_callback(conn, ocsp_data, ignored):
3663 calls.append(ocsp_data)
3664 return True
3665
3666 client = self._client_connection(callback=client_callback, data=None)
3667 server = self._server_connection(callback=server_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00003668 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003669
3670 assert len(calls) == 1
3671 assert calls[0] == self.sample_ocsp_data
3672
3673 def test_callbacks_are_invoked_with_connections(self):
3674 """
3675 The first arguments to both callbacks are their respective connections.
3676 """
3677 client_calls = []
3678 server_calls = []
3679
3680 def client_callback(conn, *args, **kwargs):
3681 client_calls.append(conn)
3682 return True
3683
3684 def server_callback(conn, *args, **kwargs):
3685 server_calls.append(conn)
3686 return self.sample_ocsp_data
3687
3688 client = self._client_connection(callback=client_callback, data=None)
3689 server = self._server_connection(callback=server_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00003690 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003691
3692 assert len(client_calls) == 1
3693 assert len(server_calls) == 1
3694 assert client_calls[0] is client
3695 assert server_calls[0] is server
3696
3697 def test_opaque_data_is_passed_through(self):
3698 """
3699 Both callbacks receive an opaque, user-provided piece of data in their
3700 callbacks as the final argument.
3701 """
3702 calls = []
3703
3704 def server_callback(*args):
3705 calls.append(args)
3706 return self.sample_ocsp_data
3707
3708 def client_callback(*args):
3709 calls.append(args)
3710 return True
3711
3712 sentinel = object()
3713
3714 client = self._client_connection(
3715 callback=client_callback, data=sentinel
3716 )
3717 server = self._server_connection(
3718 callback=server_callback, data=sentinel
3719 )
Alex Chanb7480992017-01-30 14:04:47 +00003720 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003721
3722 assert len(calls) == 2
3723 assert calls[0][-1] is sentinel
3724 assert calls[1][-1] is sentinel
3725
3726 def test_server_returns_empty_string(self):
3727 """
3728 If the server returns an empty bytestring from its callback, the
3729 client callback is called with the empty bytestring.
3730 """
3731 client_calls = []
3732
3733 def server_callback(*args):
3734 return b''
3735
3736 def client_callback(conn, ocsp_data, ignored):
3737 client_calls.append(ocsp_data)
3738 return True
3739
3740 client = self._client_connection(callback=client_callback, data=None)
3741 server = self._server_connection(callback=server_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00003742 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003743
3744 assert len(client_calls) == 1
3745 assert client_calls[0] == b''
3746
3747 def test_client_returns_false_terminates_handshake(self):
3748 """
3749 If the client returns False from its callback, the handshake fails.
3750 """
3751 def server_callback(*args):
3752 return self.sample_ocsp_data
3753
3754 def client_callback(*args):
3755 return False
3756
3757 client = self._client_connection(callback=client_callback, data=None)
3758 server = self._server_connection(callback=server_callback, data=None)
3759
3760 with pytest.raises(Error):
Alex Chanb7480992017-01-30 14:04:47 +00003761 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003762
3763 def test_exceptions_in_client_bubble_up(self):
3764 """
3765 The callbacks thrown in the client callback bubble up to the caller.
3766 """
3767 class SentinelException(Exception):
3768 pass
3769
3770 def server_callback(*args):
3771 return self.sample_ocsp_data
3772
3773 def client_callback(*args):
3774 raise SentinelException()
3775
3776 client = self._client_connection(callback=client_callback, data=None)
3777 server = self._server_connection(callback=server_callback, data=None)
3778
3779 with pytest.raises(SentinelException):
Alex Chanb7480992017-01-30 14:04:47 +00003780 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003781
3782 def test_exceptions_in_server_bubble_up(self):
3783 """
3784 The callbacks thrown in the server callback bubble up to the caller.
3785 """
3786 class SentinelException(Exception):
3787 pass
3788
3789 def server_callback(*args):
3790 raise SentinelException()
3791
3792 def client_callback(*args):
3793 pytest.fail("Should not be called")
3794
3795 client = self._client_connection(callback=client_callback, data=None)
3796 server = self._server_connection(callback=server_callback, data=None)
3797
3798 with pytest.raises(SentinelException):
Alex Chanb7480992017-01-30 14:04:47 +00003799 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003800
3801 def test_server_must_return_bytes(self):
3802 """
3803 The server callback must return a bytestring, or a TypeError is thrown.
3804 """
3805 def server_callback(*args):
3806 return self.sample_ocsp_data.decode('ascii')
3807
3808 def client_callback(*args):
3809 pytest.fail("Should not be called")
3810
3811 client = self._client_connection(callback=client_callback, data=None)
3812 server = self._server_connection(callback=server_callback, data=None)
3813
3814 with pytest.raises(TypeError):
Alex Chanb7480992017-01-30 14:04:47 +00003815 handshake_in_memory(client, server)