blob: 14b23107f92fb4520bcb8200402f94943dc52db2 [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
Abraham Martinef063482015-03-25 14:06:24 +000018from warnings import catch_warnings, 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 Chan532b79e2017-01-24 15:14:52 +000084from .util import (
85 WARNING_TYPE_EXPECTED, NON_ASCII, TestCase, is_consistent_type)
Hynek Schlawackf0e66852015-10-16 20:18:38 +020086from .test_crypto import (
87 cleartextCertificatePEM, cleartextPrivateKeyPEM,
88 client_cert_pem, client_key_pem, server_cert_pem, server_key_pem,
89 root_cert_pem)
90
Hynek Schlawackde00dd52015-09-05 19:09:26 +020091
Alex Gaynord0bdd2d2016-09-10 14:23:46 -040092# openssl dhparam 1024 -out dh-1024.pem (note that 1024 is a small number of
93# bits to use)
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -040094dhparam = """\
95-----BEGIN DH PARAMETERS-----
Alex Gaynord0bdd2d2016-09-10 14:23:46 -040096MIGHAoGBALdUMvn+C9MM+y5BWZs11mSeH6HHoEq0UVbzVq7UojC1hbsZUuGukQ3a
97Qh2/pwqb18BZFykrWB0zv/OkLa0kx4cuUgNrUVq1EFheBiX6YqryJ7t2sO09NQiO
98V7H54LmltOT/hEh6QWsJqb6BQgH65bswvV/XkYGja8/T0GzvbaVzAgEC
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -040099-----END DH PARAMETERS-----
100"""
101
102
Hynek Schlawackb4f02402015-09-05 20:48:34 +0200103skip_if_py3 = pytest.mark.skipif(PY3, reason="Python 2 only")
Hynek Schlawackf8979a52015-09-05 21:25:25 +0200104skip_if_py26 = pytest.mark.skipif(
105 version_info[0:2] == (2, 6),
106 reason="Python 2.7 and later only"
107)
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200108
109
Jean-Paul Calderone05826732015-04-12 11:38:49 -0400110def join_bytes_or_unicode(prefix, suffix):
111 """
112 Join two path components of either ``bytes`` or ``unicode``.
113
114 The return type is the same as the type of ``prefix``.
115 """
116 # If the types are the same, nothing special is necessary.
117 if type(prefix) == type(suffix):
118 return join(prefix, suffix)
119
120 # Otherwise, coerce suffix to the type of prefix.
121 if isinstance(prefix, text_type):
122 return join(prefix, suffix.decode(getfilesystemencoding()))
123 else:
124 return join(prefix, suffix.encode(getfilesystemencoding()))
125
126
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400127def verify_cb(conn, cert, errnum, depth, ok):
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400128 return ok
129
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400130
Rick Deanb1ccd562009-07-09 23:52:39 -0500131def socket_pair():
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400132 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400133 Establish and return a pair of network sockets connected to each other.
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400134 """
135 # Connect a pair of sockets
Rick Deanb1ccd562009-07-09 23:52:39 -0500136 port = socket()
137 port.bind(('', 0))
138 port.listen(1)
139 client = socket()
140 client.setblocking(False)
Jean-Paul Calderonef23c5d92009-07-23 17:58:15 -0400141 client.connect_ex(("127.0.0.1", port.getsockname()[1]))
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400142 client.setblocking(True)
Rick Deanb1ccd562009-07-09 23:52:39 -0500143 server = port.accept()[0]
Rick Deanb1ccd562009-07-09 23:52:39 -0500144
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400145 # Let's pass some unencrypted data to make sure our socket connection is
146 # fine. Just one byte, so we don't have to worry about buffers getting
147 # filled up or fragmentation.
Alex Gaynore7f51982016-09-11 11:48:14 -0400148 server.send(b"x")
149 assert client.recv(1024) == b"x"
150 client.send(b"y")
151 assert server.recv(1024) == b"y"
Rick Deanb1ccd562009-07-09 23:52:39 -0500152
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -0400153 # Most of our callers want non-blocking sockets, make it easy for them.
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400154 server.setblocking(False)
155 client.setblocking(False)
Jim Shaver46f28912015-05-29 19:32:16 -0400156
Rick Deanb1ccd562009-07-09 23:52:39 -0500157 return (server, client)
158
159
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400160def handshake(client, server):
161 conns = [client, server]
162 while conns:
163 for conn in conns:
164 try:
165 conn.do_handshake()
166 except WantReadError:
167 pass
168 else:
169 conns.remove(conn)
170
171
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400172def _create_certificate_chain():
173 """
174 Construct and return a chain of certificates.
175
176 1. A new self-signed certificate authority certificate (cacert)
177 2. A new intermediate certificate signed by cacert (icert)
178 3. A new server certificate signed by icert (scert)
179 """
Alex Gaynore7f51982016-09-11 11:48:14 -0400180 caext = X509Extension(b'basicConstraints', False, b'CA:true')
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400181
182 # Step 1
183 cakey = PKey()
Alex Gaynor0737a5e2016-09-10 14:35:09 -0400184 cakey.generate_key(TYPE_RSA, 1024)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400185 cacert = X509()
186 cacert.get_subject().commonName = "Authority Certificate"
187 cacert.set_issuer(cacert.get_subject())
188 cacert.set_pubkey(cakey)
Alex Gaynore7f51982016-09-11 11:48:14 -0400189 cacert.set_notBefore(b"20000101000000Z")
190 cacert.set_notAfter(b"20200101000000Z")
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400191 cacert.add_extensions([caext])
192 cacert.set_serial_number(0)
193 cacert.sign(cakey, "sha1")
194
195 # Step 2
196 ikey = PKey()
Alex Gaynor0737a5e2016-09-10 14:35:09 -0400197 ikey.generate_key(TYPE_RSA, 1024)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400198 icert = X509()
199 icert.get_subject().commonName = "Intermediate Certificate"
200 icert.set_issuer(cacert.get_subject())
201 icert.set_pubkey(ikey)
Alex Gaynore7f51982016-09-11 11:48:14 -0400202 icert.set_notBefore(b"20000101000000Z")
203 icert.set_notAfter(b"20200101000000Z")
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400204 icert.add_extensions([caext])
205 icert.set_serial_number(0)
206 icert.sign(cakey, "sha1")
207
208 # Step 3
209 skey = PKey()
Alex Gaynor0737a5e2016-09-10 14:35:09 -0400210 skey.generate_key(TYPE_RSA, 1024)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400211 scert = X509()
212 scert.get_subject().commonName = "Server Certificate"
213 scert.set_issuer(icert.get_subject())
214 scert.set_pubkey(skey)
Alex Gaynore7f51982016-09-11 11:48:14 -0400215 scert.set_notBefore(b"20000101000000Z")
216 scert.set_notAfter(b"20200101000000Z")
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400217 scert.add_extensions([
Alex Gaynore7f51982016-09-11 11:48:14 -0400218 X509Extension(b'basicConstraints', True, b'CA:false')])
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400219 scert.set_serial_number(0)
220 scert.sign(ikey, "sha1")
221
222 return [(cakey, cacert), (ikey, icert), (skey, scert)]
223
224
Alex Chan1ca9e3a2016-11-05 13:01:51 +0000225class _LoopbackMixin(object):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400226 """
227 Helper mixin which defines methods for creating a connected socket pair and
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200228 for forcing two connected SSL sockets to talk to each other via memory
229 BIOs.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400230 """
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500231 def _loopbackClientFactory(self, socket):
Alex Chan1c0cb662017-01-30 07:13:30 +0000232 return loopback_client_factory(socket)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400233
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500234 def _loopbackServerFactory(self, socket):
Alex Chan1c0cb662017-01-30 07:13:30 +0000235 return loopback_server_factory(socket)
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500236
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500237 def _loopback(self, serverFactory=None, clientFactory=None):
Alex Chan1c0cb662017-01-30 07:13:30 +0000238 return loopback(serverFactory, clientFactory)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400239
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400240 def _interactInMemory(self, client_conn, server_conn):
Alex Chan1ca9e3a2016-11-05 13:01:51 +0000241 return interact_in_memory(client_conn, server_conn)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400242
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -0400243 def _handshakeInMemory(self, client_conn, server_conn):
Alex Chan532b79e2017-01-24 15:14:52 +0000244 return handshake_in_memory(client_conn, server_conn)
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -0400245
246
Alex Chan1c0cb662017-01-30 07:13:30 +0000247def loopback_client_factory(socket):
248 client = Connection(Context(TLSv1_METHOD), socket)
249 client.set_connect_state()
250 return client
251
252
253def loopback_server_factory(socket):
254 ctx = Context(TLSv1_METHOD)
255 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
256 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
257 server = Connection(ctx, socket)
258 server.set_accept_state()
259 return server
260
261
262def loopback(server_factory=None, client_factory=None):
263 """
264 Create a connected socket pair and force two connected SSL sockets
265 to talk to each other via memory BIOs.
266 """
267 if server_factory is None:
268 server_factory = loopback_server_factory
269 if client_factory is None:
270 client_factory = loopback_client_factory
271
272 (server, client) = socket_pair()
273 server = server_factory(server)
274 client = client_factory(client)
275
276 handshake(client, server)
277
278 server.setblocking(True)
279 client.setblocking(True)
280 return server, client
281
282
Alex Chan1ca9e3a2016-11-05 13:01:51 +0000283def interact_in_memory(client_conn, server_conn):
284 """
285 Try to read application bytes from each of the two `Connection` objects.
286 Copy bytes back and forth between their send/receive buffers for as long
287 as there is anything to copy. When there is nothing more to copy,
288 return `None`. If one of them actually manages to deliver some application
289 bytes, return a two-tuple of the connection from which the bytes were read
290 and the bytes themselves.
291 """
292 wrote = True
293 while wrote:
294 # Loop until neither side has anything to say
295 wrote = False
296
297 # Copy stuff from each side's send buffer to the other side's
298 # receive buffer.
299 for (read, write) in [(client_conn, server_conn),
300 (server_conn, client_conn)]:
301
302 # Give the side a chance to generate some more bytes, or succeed.
303 try:
304 data = read.recv(2 ** 16)
305 except WantReadError:
306 # It didn't succeed, so we'll hope it generated some output.
307 pass
308 else:
309 # It did succeed, so we'll stop now and let the caller deal
310 # with it.
311 return (read, data)
312
313 while True:
314 # Keep copying as long as there's more stuff there.
315 try:
316 dirty = read.bio_read(4096)
317 except WantReadError:
318 # Okay, nothing more waiting to be sent. Stop
319 # processing this send buffer.
320 break
321 else:
322 # Keep track of the fact that someone generated some
323 # output.
324 wrote = True
325 write.bio_write(dirty)
326
327
Alex Chan532b79e2017-01-24 15:14:52 +0000328def handshake_in_memory(client_conn, server_conn):
329 """
330 Perform the TLS handshake between two `Connection` instances connected to
331 each other via memory BIOs.
332 """
333 client_conn.set_connect_state()
334 server_conn.set_accept_state()
335
336 for conn in [client_conn, server_conn]:
337 try:
338 conn.do_handshake()
339 except WantReadError:
340 pass
341
342 interact_in_memory(client_conn, server_conn)
343
344
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400345class VersionTests(TestCase):
346 """
347 Tests for version information exposed by
Jonathan Ballet648875f2011-07-16 14:14:58 +0900348 :py:obj:`OpenSSL.SSL.SSLeay_version` and
349 :py:obj:`OpenSSL.SSL.OPENSSL_VERSION_NUMBER`.
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400350 """
351 def test_OPENSSL_VERSION_NUMBER(self):
352 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900353 :py:obj:`OPENSSL_VERSION_NUMBER` is an integer with status in the low
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400354 byte and the patch, fix, minor, and major versions in the
355 nibbles above that.
356 """
357 self.assertTrue(isinstance(OPENSSL_VERSION_NUMBER, int))
358
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400359 def test_SSLeay_version(self):
360 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900361 :py:obj:`SSLeay_version` takes a version type indicator and returns
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400362 one of a number of version strings based on that indicator.
363 """
364 versions = {}
365 for t in [SSLEAY_VERSION, SSLEAY_CFLAGS, SSLEAY_BUILT_ON,
366 SSLEAY_PLATFORM, SSLEAY_DIR]:
367 version = SSLeay_version(t)
368 versions[version] = t
369 self.assertTrue(isinstance(version, bytes))
370 self.assertEqual(len(versions), 5)
371
372
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100373@pytest.fixture
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100374def ca_file(tmpdir):
375 """
376 Create a valid PEM file with CA certificates and return the path.
377 """
378 key = rsa.generate_private_key(
379 public_exponent=65537,
380 key_size=2048,
381 backend=default_backend()
382 )
383 public_key = key.public_key()
384
385 builder = x509.CertificateBuilder()
386 builder = builder.subject_name(x509.Name([
387 x509.NameAttribute(NameOID.COMMON_NAME, u"pyopenssl.org"),
388 ]))
389 builder = builder.issuer_name(x509.Name([
390 x509.NameAttribute(NameOID.COMMON_NAME, u"pyopenssl.org"),
391 ]))
392 one_day = datetime.timedelta(1, 0, 0)
393 builder = builder.not_valid_before(datetime.datetime.today() - one_day)
394 builder = builder.not_valid_after(datetime.datetime.today() + one_day)
395 builder = builder.serial_number(int(uuid.uuid4()))
396 builder = builder.public_key(public_key)
397 builder = builder.add_extension(
398 x509.BasicConstraints(ca=True, path_length=None), critical=True,
399 )
400
401 certificate = builder.sign(
402 private_key=key, algorithm=hashes.SHA256(),
403 backend=default_backend()
404 )
405
406 ca_file = tmpdir.join("test.pem")
407 ca_file.write_binary(
408 certificate.public_bytes(
409 encoding=serialization.Encoding.PEM,
410 )
411 )
412
413 return str(ca_file).encode("ascii")
414
415
416@pytest.fixture
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100417def context():
418 """
419 A simple TLS 1.0 context.
420 """
421 return Context(TLSv1_METHOD)
422
423
424class TestContext(object):
Hynek Schlawackaa861212016-03-13 13:53:48 +0100425 """
Alex Chan532b79e2017-01-24 15:14:52 +0000426 Unit tests for `OpenSSL.SSL.Context`.
Hynek Schlawackaa861212016-03-13 13:53:48 +0100427 """
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100428 @pytest.mark.parametrize("cipher_string", [
429 b"hello world:AES128-SHA",
430 u"hello world:AES128-SHA",
431 ])
432 def test_set_cipher_list(self, context, cipher_string):
433 """
Alex Chan532b79e2017-01-24 15:14:52 +0000434 `Context.set_cipher_list` accepts both byte and unicode strings
Hynek Schlawacka7a63af2016-03-11 12:05:26 +0100435 for naming the ciphers which connections created with the context
436 object will be able to choose from.
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100437 """
438 context.set_cipher_list(cipher_string)
439 conn = Connection(context, None)
440
441 assert "AES128-SHA" in conn.get_cipher_list()
442
443 @pytest.mark.parametrize("cipher_list,error", [
444 (object(), TypeError),
445 ("imaginary-cipher", Error),
446 ])
447 def test_set_cipher_list_wrong_args(self, context, cipher_list, error):
448 """
Alex Chan532b79e2017-01-24 15:14:52 +0000449 `Context.set_cipher_list` raises `TypeError` when passed a non-string
450 argument and raises `OpenSSL.SSL.Error` when passed an incorrect cipher
451 list string.
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100452 """
453 with pytest.raises(error):
454 context.set_cipher_list(cipher_list)
455
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100456 def test_load_client_ca(self, context, ca_file):
457 """
Alex Chan532b79e2017-01-24 15:14:52 +0000458 `Context.load_client_ca` works as far as we can tell.
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100459 """
460 context.load_client_ca(ca_file)
461
462 def test_load_client_ca_invalid(self, context, tmpdir):
463 """
Alex Chan532b79e2017-01-24 15:14:52 +0000464 `Context.load_client_ca` raises an Error if the ca file is invalid.
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100465 """
466 ca_file = tmpdir.join("test.pem")
467 ca_file.write("")
468
469 with pytest.raises(Error) as e:
470 context.load_client_ca(str(ca_file).encode("ascii"))
471
472 assert "PEM routines" == e.value.args[0][0][0]
473
474 def test_load_client_ca_unicode(self, context, ca_file):
475 """
476 Passing the path as unicode raises a warning but works.
477 """
478 pytest.deprecated_call(
479 context.load_client_ca, ca_file.decode("ascii")
480 )
481
482 def test_set_session_id(self, context):
483 """
Alex Chan532b79e2017-01-24 15:14:52 +0000484 `Context.set_session_id` works as far as we can tell.
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100485 """
486 context.set_session_id(b"abc")
487
488 def test_set_session_id_fail(self, context):
489 """
Alex Chan532b79e2017-01-24 15:14:52 +0000490 `Context.set_session_id` errors are propagated.
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100491 """
492 with pytest.raises(Error) as e:
493 context.set_session_id(b"abc" * 1000)
494
495 assert [
496 ("SSL routines",
497 "SSL_CTX_set_session_id_context",
498 "ssl session id context too long")
499 ] == e.value.args[0]
500
501 def test_set_session_id_unicode(self, context):
502 """
Alex Chan532b79e2017-01-24 15:14:52 +0000503 `Context.set_session_id` raises a warning if a unicode string is
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100504 passed.
505 """
506 pytest.deprecated_call(context.set_session_id, u"abc")
507
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400508 def test_method(self):
509 """
Alex Chan532b79e2017-01-24 15:14:52 +0000510 `Context` can be instantiated with one of `SSLv2_METHOD`,
511 `SSLv3_METHOD`, `SSLv23_METHOD`, `TLSv1_METHOD`, `TLSv1_1_METHOD`,
512 or `TLSv1_2_METHOD`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400513 """
Alex Gaynor5af32d02016-09-24 01:52:21 -0400514 methods = [SSLv23_METHOD, TLSv1_METHOD]
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400515 for meth in methods:
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400516 Context(meth)
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400517
Alex Gaynor5af32d02016-09-24 01:52:21 -0400518 maybe = [SSLv2_METHOD, SSLv3_METHOD, TLSv1_1_METHOD, TLSv1_2_METHOD]
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400519 for meth in maybe:
520 try:
521 Context(meth)
522 except (Error, ValueError):
523 # Some versions of OpenSSL have SSLv2 / TLSv1.1 / TLSv1.2, some
524 # don't. Difficult to say in advance.
525 pass
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400526
Alex Chan532b79e2017-01-24 15:14:52 +0000527 with pytest.raises(TypeError):
528 Context("")
529 with pytest.raises(ValueError):
530 Context(10)
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400531
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200532 @skip_if_py3
533 def test_method_long(self):
534 """
Alex Chan532b79e2017-01-24 15:14:52 +0000535 On Python 2 `Context` accepts values of type `long` as well as `int`.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200536 """
537 Context(long(TLSv1_METHOD))
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500538
Rick Deane15b1472009-07-09 15:53:42 -0500539 def test_type(self):
540 """
Alex Chan532b79e2017-01-24 15:14:52 +0000541 `Context` and `ContextType` refer to the same type object and can
542 be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -0500543 """
Alex Chan532b79e2017-01-24 15:14:52 +0000544 assert Context is ContextType
545 assert is_consistent_type(Context, 'Context', TLSv1_METHOD)
Rick Deane15b1472009-07-09 15:53:42 -0500546
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400547 def test_use_privatekey(self):
548 """
Alex Chan532b79e2017-01-24 15:14:52 +0000549 `Context.use_privatekey` takes an `OpenSSL.crypto.PKey` instance.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400550 """
551 key = PKey()
552 key.generate_key(TYPE_RSA, 128)
553 ctx = Context(TLSv1_METHOD)
554 ctx.use_privatekey(key)
Alex Chan532b79e2017-01-24 15:14:52 +0000555 with pytest.raises(TypeError):
556 ctx.use_privatekey("")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400557
Alex Chan532b79e2017-01-24 15:14:52 +0000558 def test_use_privatekey_file_missing(self, tmpfile):
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800559 """
Alex Chan532b79e2017-01-24 15:14:52 +0000560 `Context.use_privatekey_file` raises `OpenSSL.SSL.Error` when passed
561 the name of a file which does not exist.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800562 """
563 ctx = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000564 with pytest.raises(Error):
565 ctx.use_privatekey_file(tmpfile)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800566
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400567 def _use_privatekey_file_test(self, pemfile, filetype):
568 """
569 Verify that calling ``Context.use_privatekey_file`` with the given
570 arguments does not raise an exception.
571 """
572 key = PKey()
573 key.generate_key(TYPE_RSA, 128)
574
575 with open(pemfile, "wt") as pem:
576 pem.write(
577 dump_privatekey(FILETYPE_PEM, key).decode("ascii")
578 )
579
580 ctx = Context(TLSv1_METHOD)
581 ctx.use_privatekey_file(pemfile, filetype)
582
Alex Chan532b79e2017-01-24 15:14:52 +0000583 def test_use_privatekey_file_bytes(self, tmpfile):
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400584 """
585 A private key can be specified from a file by passing a ``bytes``
586 instance giving the file name to ``Context.use_privatekey_file``.
587 """
588 self._use_privatekey_file_test(
Alex Chan532b79e2017-01-24 15:14:52 +0000589 tmpfile + NON_ASCII.encode(getfilesystemencoding()),
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400590 FILETYPE_PEM,
591 )
592
Alex Chan532b79e2017-01-24 15:14:52 +0000593 def test_use_privatekey_file_unicode(self, tmpfile):
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400594 """
595 A private key can be specified from a file by passing a ``unicode``
596 instance giving the file name to ``Context.use_privatekey_file``.
597 """
598 self._use_privatekey_file_test(
Alex Chan532b79e2017-01-24 15:14:52 +0000599 tmpfile.decode(getfilesystemencoding()) + NON_ASCII,
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400600 FILETYPE_PEM,
601 )
602
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200603 @skip_if_py3
Alex Chan532b79e2017-01-24 15:14:52 +0000604 def test_use_privatekey_file_long(self, tmpfile):
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200605 """
Alex Chan532b79e2017-01-24 15:14:52 +0000606 On Python 2 `Context.use_privatekey_file` accepts a filetype of
607 type `long` as well as `int`.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200608 """
Alex Chan532b79e2017-01-24 15:14:52 +0000609 self._use_privatekey_file_test(tmpfile, long(FILETYPE_PEM))
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500610
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800611 def test_use_certificate_wrong_args(self):
612 """
Alex Chan532b79e2017-01-24 15:14:52 +0000613 `Context.use_certificate_wrong_args` raises `TypeError` when not passed
614 exactly one `OpenSSL.crypto.X509` instance as an argument.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800615 """
616 ctx = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000617 with pytest.raises(TypeError):
618 ctx.use_certificate("hello, world")
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800619
620 def test_use_certificate_uninitialized(self):
621 """
Alex Chan532b79e2017-01-24 15:14:52 +0000622 `Context.use_certificate` raises `OpenSSL.SSL.Error` when passed a
623 `OpenSSL.crypto.X509` instance which has not been initialized
624 (ie, which does not actually have any certificate data).
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800625 """
626 ctx = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000627 with pytest.raises(Error):
628 ctx.use_certificate(X509())
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800629
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800630 def test_use_certificate(self):
631 """
Alex Chan532b79e2017-01-24 15:14:52 +0000632 `Context.use_certificate` sets the certificate which will be
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800633 used to identify connections created using the context.
634 """
635 # TODO
636 # Hard to assert anything. But we could set a privatekey then ask
637 # OpenSSL if the cert and key agree using check_privatekey. Then as
638 # long as check_privatekey works right we're good...
639 ctx = Context(TLSv1_METHOD)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200640 ctx.use_certificate(
641 load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
642 )
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800643
644 def test_use_certificate_file_wrong_args(self):
645 """
Alex Chan532b79e2017-01-24 15:14:52 +0000646 `Context.use_certificate_file` raises `TypeError` if the first
647 argument is not a byte string or the second argument is not an integer.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800648 """
649 ctx = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000650 with pytest.raises(TypeError):
651 ctx.use_certificate_file(object(), FILETYPE_PEM)
652 with pytest.raises(TypeError):
653 ctx.use_certificate_file(b"somefile", object())
654 with pytest.raises(TypeError):
655 ctx.use_certificate_file(object(), FILETYPE_PEM)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800656
Alex Chan532b79e2017-01-24 15:14:52 +0000657 def test_use_certificate_file_missing(self, tmpfile):
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800658 """
Alex Chan532b79e2017-01-24 15:14:52 +0000659 `Context.use_certificate_file` raises `OpenSSL.SSL.Error` if passed
660 the name of a file which does not exist.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800661 """
662 ctx = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000663 with pytest.raises(Error):
664 ctx.use_certificate_file(tmpfile)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800665
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400666 def _use_certificate_file_test(self, certificate_file):
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800667 """
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400668 Verify that calling ``Context.use_certificate_file`` with the given
669 filename doesn't raise an exception.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800670 """
671 # TODO
672 # Hard to assert anything. But we could set a privatekey then ask
673 # OpenSSL if the cert and key agree using check_privatekey. Then as
674 # long as check_privatekey works right we're good...
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400675 with open(certificate_file, "wb") as pem_file:
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800676 pem_file.write(cleartextCertificatePEM)
677
678 ctx = Context(TLSv1_METHOD)
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400679 ctx.use_certificate_file(certificate_file)
680
Alex Chan532b79e2017-01-24 15:14:52 +0000681 def test_use_certificate_file_bytes(self, tmpfile):
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400682 """
Alex Chan532b79e2017-01-24 15:14:52 +0000683 `Context.use_certificate_file` sets the certificate (given as a
684 `bytes` filename) which will be used to identify connections created
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400685 using the context.
686 """
Alex Chan532b79e2017-01-24 15:14:52 +0000687 filename = tmpfile + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400688 self._use_certificate_file_test(filename)
689
Alex Chan532b79e2017-01-24 15:14:52 +0000690 def test_use_certificate_file_unicode(self, tmpfile):
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400691 """
Alex Chan532b79e2017-01-24 15:14:52 +0000692 `Context.use_certificate_file` sets the certificate (given as a
693 `bytes` filename) which will be used to identify connections created
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400694 using the context.
695 """
Alex Chan532b79e2017-01-24 15:14:52 +0000696 filename = tmpfile.decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400697 self._use_certificate_file_test(filename)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800698
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200699 @skip_if_py3
Alex Chan532b79e2017-01-24 15:14:52 +0000700 def test_use_certificate_file_long(self, tmpfile):
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200701 """
Alex Chan532b79e2017-01-24 15:14:52 +0000702 On Python 2 `Context.use_certificate_file` accepts a
703 filetype of type `long` as well as `int`.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200704 """
Alex Chan532b79e2017-01-24 15:14:52 +0000705 pem_filename = tmpfile
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200706 with open(pem_filename, "wb") as pem_file:
707 pem_file.write(cleartextCertificatePEM)
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500708
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200709 ctx = Context(TLSv1_METHOD)
710 ctx.use_certificate_file(pem_filename, long(FILETYPE_PEM))
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500711
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500712 def test_check_privatekey_valid(self):
713 """
Alex Chan532b79e2017-01-24 15:14:52 +0000714 `Context.check_privatekey` returns `None` if the `Context` instance
715 has been configured to use a matched key and certificate pair.
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500716 """
717 key = load_privatekey(FILETYPE_PEM, client_key_pem)
718 cert = load_certificate(FILETYPE_PEM, client_cert_pem)
719 context = Context(TLSv1_METHOD)
720 context.use_privatekey(key)
721 context.use_certificate(cert)
Alex Chan532b79e2017-01-24 15:14:52 +0000722 assert None is context.check_privatekey()
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500723
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500724 def test_check_privatekey_invalid(self):
725 """
Alex Chan532b79e2017-01-24 15:14:52 +0000726 `Context.check_privatekey` raises `Error` if the `Context` instance
727 has been configured to use a key and certificate pair which don't
728 relate to each other.
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500729 """
730 key = load_privatekey(FILETYPE_PEM, client_key_pem)
731 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
732 context = Context(TLSv1_METHOD)
733 context.use_privatekey(key)
734 context.use_certificate(cert)
Alex Chan532b79e2017-01-24 15:14:52 +0000735 with pytest.raises(Error):
736 context.check_privatekey()
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400737
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400738 def test_app_data(self):
739 """
Alex Chan532b79e2017-01-24 15:14:52 +0000740 `Context.set_app_data` stores an object for later retrieval
741 using `Context.get_app_data`.
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400742 """
743 app_data = object()
744 context = Context(TLSv1_METHOD)
745 context.set_app_data(app_data)
Alex Chan532b79e2017-01-24 15:14:52 +0000746 assert context.get_app_data() is app_data
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400747
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400748 def test_set_options_wrong_args(self):
749 """
Alex Chan532b79e2017-01-24 15:14:52 +0000750 `Context.set_options` raises `TypeError` if called with
751 a non-`int` argument.
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400752 """
753 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000754 with pytest.raises(TypeError):
755 context.set_options(None)
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400756
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500757 def test_set_options(self):
758 """
Alex Chan532b79e2017-01-24 15:14:52 +0000759 `Context.set_options` returns the new options value.
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500760 """
761 context = Context(TLSv1_METHOD)
762 options = context.set_options(OP_NO_SSLv2)
Alex Gaynor2310f8b2016-09-10 14:39:32 -0400763 assert options & OP_NO_SSLv2 == OP_NO_SSLv2
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500764
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200765 @skip_if_py3
766 def test_set_options_long(self):
767 """
Alex Chan532b79e2017-01-24 15:14:52 +0000768 On Python 2 `Context.set_options` accepts values of type
769 `long` as well as `int`.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200770 """
771 context = Context(TLSv1_METHOD)
772 options = context.set_options(long(OP_NO_SSLv2))
Alex Gaynor2310f8b2016-09-10 14:39:32 -0400773 assert options & OP_NO_SSLv2 == OP_NO_SSLv2
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500774
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300775 def test_set_mode_wrong_args(self):
776 """
Alex Chan532b79e2017-01-24 15:14:52 +0000777 `Context.set_mode` raises `TypeError` if called with
778 a non-`int` argument.
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300779 """
780 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000781 with pytest.raises(TypeError):
782 context.set_mode(None)
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300783
Alex Gaynord3b5d9b2016-07-31 10:54:24 -0400784 def test_set_mode(self):
785 """
Alex Chan532b79e2017-01-24 15:14:52 +0000786 `Context.set_mode` accepts a mode bitvector and returns the
Alex Gaynord3b5d9b2016-07-31 10:54:24 -0400787 newly set mode.
788 """
789 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000790 assert MODE_RELEASE_BUFFERS & context.set_mode(MODE_RELEASE_BUFFERS)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500791
Alex Gaynord3b5d9b2016-07-31 10:54:24 -0400792 @skip_if_py3
793 def test_set_mode_long(self):
794 """
Alex Chan532b79e2017-01-24 15:14:52 +0000795 On Python 2 `Context.set_mode` accepts values of type `long` as well
796 as `int`.
Alex Gaynord3b5d9b2016-07-31 10:54:24 -0400797 """
798 context = Context(TLSv1_METHOD)
799 mode = context.set_mode(long(MODE_RELEASE_BUFFERS))
Alex Chan532b79e2017-01-24 15:14:52 +0000800 assert MODE_RELEASE_BUFFERS & mode
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400801
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400802 def test_set_timeout_wrong_args(self):
803 """
Alex Chan532b79e2017-01-24 15:14:52 +0000804 `Context.set_timeout` raises `TypeError` if called with
805 a non-`int` argument.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400806 """
807 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000808 with pytest.raises(TypeError):
809 context.set_timeout(None)
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400810
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400811 def test_timeout(self):
812 """
Alex Chan532b79e2017-01-24 15:14:52 +0000813 `Context.set_timeout` sets the session timeout for all connections
814 created using the context object. `Context.get_timeout` retrieves
815 this value.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400816 """
817 context = Context(TLSv1_METHOD)
818 context.set_timeout(1234)
Alex Chan532b79e2017-01-24 15:14:52 +0000819 assert context.get_timeout() == 1234
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400820
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200821 @skip_if_py3
822 def test_timeout_long(self):
823 """
Alex Chan532b79e2017-01-24 15:14:52 +0000824 On Python 2 `Context.set_timeout` accepts values of type `long` as
825 well as int.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200826 """
827 context = Context(TLSv1_METHOD)
828 context.set_timeout(long(1234))
Alex Chan532b79e2017-01-24 15:14:52 +0000829 assert context.get_timeout() == 1234
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500830
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400831 def test_set_verify_depth_wrong_args(self):
832 """
Alex Chan532b79e2017-01-24 15:14:52 +0000833 `Context.set_verify_depth` raises `TypeError` if called with a
834 non-`int` argument.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400835 """
836 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000837 with pytest.raises(TypeError):
838 context.set_verify_depth(None)
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400839
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400840 def test_verify_depth(self):
841 """
Alex Chan532b79e2017-01-24 15:14:52 +0000842 `Context.set_verify_depth` sets the number of certificates in
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200843 a chain to follow before giving up. The value can be retrieved with
Alex Chan532b79e2017-01-24 15:14:52 +0000844 `Context.get_verify_depth`.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400845 """
846 context = Context(TLSv1_METHOD)
847 context.set_verify_depth(11)
Alex Chan532b79e2017-01-24 15:14:52 +0000848 assert context.get_verify_depth() == 11
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400849
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200850 @skip_if_py3
851 def test_verify_depth_long(self):
852 """
Alex Chan532b79e2017-01-24 15:14:52 +0000853 On Python 2 `Context.set_verify_depth` accepts values of type `long`
854 as well as int.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200855 """
856 context = Context(TLSv1_METHOD)
857 context.set_verify_depth(long(11))
Alex Chan532b79e2017-01-24 15:14:52 +0000858 assert context.get_verify_depth() == 11
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500859
Alex Chan532b79e2017-01-24 15:14:52 +0000860 def _write_encrypted_pem(self, passphrase, tmpfile):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400861 """
862 Write a new private key out to a new file, encrypted using the given
863 passphrase. Return the path to the new file.
864 """
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400865 key = PKey()
866 key.generate_key(TYPE_RSA, 128)
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400867 pem = dump_privatekey(FILETYPE_PEM, key, "blowfish", passphrase)
Alex Chan532b79e2017-01-24 15:14:52 +0000868 with open(tmpfile, 'w') as fObj:
869 fObj.write(pem.decode('ascii'))
870 return tmpfile
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400871
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400872 def test_set_passwd_cb_wrong_args(self):
873 """
Alex Chan532b79e2017-01-24 15:14:52 +0000874 `Context.set_passwd_cb` raises `TypeError` if called with a
875 non-callable first argument.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400876 """
877 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000878 with pytest.raises(TypeError):
879 context.set_passwd_cb(None)
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400880
Alex Chan532b79e2017-01-24 15:14:52 +0000881 def test_set_passwd_cb(self, tmpfile):
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400882 """
Alex Chan532b79e2017-01-24 15:14:52 +0000883 `Context.set_passwd_cb` accepts a callable which will be invoked when
884 a private key is loaded from an encrypted PEM.
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400885 """
Alex Gaynore7f51982016-09-11 11:48:14 -0400886 passphrase = b"foobar"
Alex Chan532b79e2017-01-24 15:14:52 +0000887 pemFile = self._write_encrypted_pem(passphrase, tmpfile)
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400888 calledWith = []
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200889
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400890 def passphraseCallback(maxlen, verify, extra):
891 calledWith.append((maxlen, verify, extra))
892 return passphrase
893 context = Context(TLSv1_METHOD)
894 context.set_passwd_cb(passphraseCallback)
895 context.use_privatekey_file(pemFile)
Alex Chan532b79e2017-01-24 15:14:52 +0000896 assert len(calledWith) == 1
897 assert isinstance(calledWith[0][0], int)
898 assert isinstance(calledWith[0][1], int)
899 assert calledWith[0][2] is None
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400900
Alex Chan532b79e2017-01-24 15:14:52 +0000901 def test_passwd_callback_exception(self, tmpfile):
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400902 """
Alex Chan532b79e2017-01-24 15:14:52 +0000903 `Context.use_privatekey_file` propagates any exception raised
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200904 by the passphrase callback.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400905 """
Alex Chan532b79e2017-01-24 15:14:52 +0000906 pemFile = self._write_encrypted_pem(b"monkeys are nice", tmpfile)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200907
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400908 def passphraseCallback(maxlen, verify, extra):
909 raise RuntimeError("Sorry, I am a fail.")
910
911 context = Context(TLSv1_METHOD)
912 context.set_passwd_cb(passphraseCallback)
Alex Chan532b79e2017-01-24 15:14:52 +0000913 with pytest.raises(RuntimeError):
914 context.use_privatekey_file(pemFile)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400915
Alex Chan532b79e2017-01-24 15:14:52 +0000916 def test_passwd_callback_false(self, tmpfile):
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400917 """
Alex Chan532b79e2017-01-24 15:14:52 +0000918 `Context.use_privatekey_file` raises `OpenSSL.SSL.Error` if the
919 passphrase callback returns a false value.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400920 """
Alex Chan532b79e2017-01-24 15:14:52 +0000921 pemFile = self._write_encrypted_pem(b"monkeys are nice", tmpfile)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200922
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400923 def passphraseCallback(maxlen, verify, extra):
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500924 return b""
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400925
926 context = Context(TLSv1_METHOD)
927 context.set_passwd_cb(passphraseCallback)
Alex Chan532b79e2017-01-24 15:14:52 +0000928 with pytest.raises(Error):
929 context.use_privatekey_file(pemFile)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400930
Alex Chan532b79e2017-01-24 15:14:52 +0000931 def test_passwd_callback_non_string(self, tmpfile):
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400932 """
Alex Chan532b79e2017-01-24 15:14:52 +0000933 `Context.use_privatekey_file` raises `OpenSSL.SSL.Error` if the
934 passphrase callback returns a true non-string value.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400935 """
Alex Chan532b79e2017-01-24 15:14:52 +0000936 pemFile = self._write_encrypted_pem(b"monkeys are nice", tmpfile)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200937
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400938 def passphraseCallback(maxlen, verify, extra):
939 return 10
940
941 context = Context(TLSv1_METHOD)
942 context.set_passwd_cb(passphraseCallback)
Alex Chan532b79e2017-01-24 15:14:52 +0000943 # TODO: Surely this is the wrong error?
944 with pytest.raises(ValueError):
945 context.use_privatekey_file(pemFile)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400946
Alex Chan532b79e2017-01-24 15:14:52 +0000947 def test_passwd_callback_too_long(self, tmpfile):
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400948 """
949 If the passphrase returned by the passphrase callback returns a string
950 longer than the indicated maximum length, it is truncated.
951 """
952 # A priori knowledge!
Alex Gaynore7f51982016-09-11 11:48:14 -0400953 passphrase = b"x" * 1024
Alex Chan532b79e2017-01-24 15:14:52 +0000954 pemFile = self._write_encrypted_pem(passphrase, tmpfile)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200955
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400956 def passphraseCallback(maxlen, verify, extra):
957 assert maxlen == 1024
Alex Gaynore7f51982016-09-11 11:48:14 -0400958 return passphrase + b"y"
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400959
960 context = Context(TLSv1_METHOD)
961 context.set_passwd_cb(passphraseCallback)
962 # This shall succeed because the truncated result is the correct
963 # passphrase.
964 context.use_privatekey_file(pemFile)
965
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400966 def test_set_info_callback(self):
967 """
Alex Chan532b79e2017-01-24 15:14:52 +0000968 `Context.set_info_callback` accepts a callable which will be
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200969 invoked when certain information about an SSL connection is available.
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400970 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500971 (server, client) = socket_pair()
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400972
973 clientSSL = Connection(Context(TLSv1_METHOD), client)
974 clientSSL.set_connect_state()
975
976 called = []
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200977
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400978 def info(conn, where, ret):
979 called.append((conn, where, ret))
980 context = Context(TLSv1_METHOD)
981 context.set_info_callback(info)
982 context.use_certificate(
983 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
984 context.use_privatekey(
985 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
986
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400987 serverSSL = Connection(context, server)
988 serverSSL.set_accept_state()
989
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -0500990 handshake(clientSSL, serverSSL)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400991
Jean-Paul Calderone3835e522014-02-02 11:12:30 -0500992 # The callback must always be called with a Connection instance as the
993 # first argument. It would probably be better to split this into
994 # separate tests for client and server side info callbacks so we could
995 # assert it is called with the right Connection instance. It would
996 # also be good to assert *something* about `where` and `ret`.
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -0500997 notConnections = [
998 conn for (conn, where, ret) in called
999 if not isinstance(conn, Connection)]
Alex Chan532b79e2017-01-24 15:14:52 +00001000 assert [] == notConnections, (
1001 "Some info callback arguments were not Connection instances.")
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001002
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001003 def _load_verify_locations_test(self, *args):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001004 """
1005 Create a client context which will verify the peer certificate and call
Alex Chan532b79e2017-01-24 15:14:52 +00001006 its `load_verify_locations` method with the given arguments.
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04001007 Then connect it to a server and ensure that the handshake succeeds.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001008 """
Rick Deanb1ccd562009-07-09 23:52:39 -05001009 (server, client) = socket_pair()
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001010
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001011 clientContext = Context(TLSv1_METHOD)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001012 clientContext.load_verify_locations(*args)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001013 # Require that the server certificate verify properly or the
1014 # connection will fail.
1015 clientContext.set_verify(
1016 VERIFY_PEER,
1017 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
1018
1019 clientSSL = Connection(clientContext, client)
1020 clientSSL.set_connect_state()
1021
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001022 serverContext = Context(TLSv1_METHOD)
1023 serverContext.use_certificate(
1024 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1025 serverContext.use_privatekey(
1026 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1027
1028 serverSSL = Connection(serverContext, server)
1029 serverSSL.set_accept_state()
1030
Jean-Paul Calderonef8742032010-09-25 00:00:32 -04001031 # Without load_verify_locations above, the handshake
1032 # will fail:
1033 # Error: [('SSL routines', 'SSL3_GET_SERVER_CERTIFICATE',
1034 # 'certificate verify failed')]
1035 handshake(clientSSL, serverSSL)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001036
1037 cert = clientSSL.get_peer_certificate()
Alex Chan532b79e2017-01-24 15:14:52 +00001038 assert cert.get_subject().CN == 'Testing Root CA'
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -04001039
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001040 def _load_verify_cafile(self, cafile):
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001041 """
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001042 Verify that if path to a file containing a certificate is passed to
Alex Chan532b79e2017-01-24 15:14:52 +00001043 `Context.load_verify_locations` for the ``cafile`` parameter, that
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001044 certificate is used as a trust root for the purposes of verifying
Alex Chan532b79e2017-01-24 15:14:52 +00001045 connections created using that `Context`.
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001046 """
Alex Chan532b79e2017-01-24 15:14:52 +00001047 with open(cafile, 'w') as fObj:
1048 fObj.write(cleartextCertificatePEM.decode('ascii'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001049
1050 self._load_verify_locations_test(cafile)
1051
Alex Chan532b79e2017-01-24 15:14:52 +00001052 def test_load_verify_bytes_cafile(self, tmpfile):
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001053 """
Alex Chan532b79e2017-01-24 15:14:52 +00001054 `Context.load_verify_locations` accepts a file name as a `bytes`
1055 instance and uses the certificates within for verification purposes.
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001056 """
Alex Chan532b79e2017-01-24 15:14:52 +00001057 cafile = tmpfile + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001058 self._load_verify_cafile(cafile)
1059
Alex Chan532b79e2017-01-24 15:14:52 +00001060 def test_load_verify_unicode_cafile(self, tmpfile):
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001061 """
Alex Chan532b79e2017-01-24 15:14:52 +00001062 `Context.load_verify_locations` accepts a file name as a `unicode`
1063 instance and uses the certificates within for verification purposes.
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001064 """
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001065 self._load_verify_cafile(
Alex Chan532b79e2017-01-24 15:14:52 +00001066 tmpfile.decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001067 )
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001068
Alex Chan532b79e2017-01-24 15:14:52 +00001069 def test_load_verify_invalid_file(self, tmpfile):
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -04001070 """
Alex Chan532b79e2017-01-24 15:14:52 +00001071 `Context.load_verify_locations` raises `Error` when passed a
1072 non-existent cafile.
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -04001073 """
1074 clientContext = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001075 with pytest.raises(Error):
1076 clientContext.load_verify_locations(tmpfile)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001077
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001078 def _load_verify_directory_locations_capath(self, capath):
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001079 """
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001080 Verify that if path to a directory containing certificate files is
1081 passed to ``Context.load_verify_locations`` for the ``capath``
1082 parameter, those certificates are used as trust roots for the purposes
1083 of verifying connections created using that ``Context``.
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001084 """
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001085 makedirs(capath)
Jean-Paul Calderone24dfb332011-05-04 18:10:26 -04001086 # Hash values computed manually with c_rehash to avoid depending on
1087 # c_rehash in the test suite. One is from OpenSSL 0.9.8, the other
1088 # from OpenSSL 1.0.0.
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001089 for name in [b'c7adac82.0', b'c3705638.0']:
Jean-Paul Calderone05826732015-04-12 11:38:49 -04001090 cafile = join_bytes_or_unicode(capath, name)
1091 with open(cafile, 'w') as fObj:
1092 fObj.write(cleartextCertificatePEM.decode('ascii'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001093
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001094 self._load_verify_locations_test(None, capath)
1095
Alex Chan532b79e2017-01-24 15:14:52 +00001096 def test_load_verify_directory_bytes_capath(self, tmpfile):
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001097 """
Alex Chan532b79e2017-01-24 15:14:52 +00001098 `Context.load_verify_locations` accepts a directory name as a `bytes`
1099 instance and uses the certificates within for verification purposes.
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001100 """
1101 self._load_verify_directory_locations_capath(
Alex Chan532b79e2017-01-24 15:14:52 +00001102 tmpfile + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001103 )
1104
Alex Chan532b79e2017-01-24 15:14:52 +00001105 def test_load_verify_directory_unicode_capath(self, tmpfile):
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001106 """
Alex Chan532b79e2017-01-24 15:14:52 +00001107 `Context.load_verify_locations` accepts a directory name as a `unicode`
1108 instance and uses the certificates within for verification purposes.
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001109 """
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001110 self._load_verify_directory_locations_capath(
Alex Chan532b79e2017-01-24 15:14:52 +00001111 tmpfile.decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001112 )
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001113
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001114 def test_load_verify_locations_wrong_args(self):
1115 """
Alex Chan532b79e2017-01-24 15:14:52 +00001116 `Context.load_verify_locations` raises `TypeError` if with non-`str`
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001117 arguments.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001118 """
1119 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001120 with pytest.raises(TypeError):
1121 context.load_verify_locations(object())
1122 with pytest.raises(TypeError):
1123 context.load_verify_locations(object(), object())
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001124
Hynek Schlawack734d3022015-09-05 19:19:32 +02001125 @pytest.mark.skipif(
1126 platform == "win32",
1127 reason="set_default_verify_paths appears not to work on Windows. "
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -04001128 "See LP#404343 and LP#404344."
Hynek Schlawack734d3022015-09-05 19:19:32 +02001129 )
1130 def test_set_default_verify_paths(self):
1131 """
Alex Chan532b79e2017-01-24 15:14:52 +00001132 `Context.set_default_verify_paths` causes the platform-specific CA
1133 certificate locations to be used for verification purposes.
Hynek Schlawack734d3022015-09-05 19:19:32 +02001134 """
1135 # Testing this requires a server with a certificate signed by one
1136 # of the CAs in the platform CA location. Getting one of those
1137 # costs money. Fortunately (or unfortunately, depending on your
1138 # perspective), it's easy to think of a public server on the
1139 # internet which has such a certificate. Connecting to the network
1140 # in a unit test is bad, but it's the only way I can think of to
1141 # really test this. -exarkun
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001142
Hynek Schlawack734d3022015-09-05 19:19:32 +02001143 # Arg, verisign.com doesn't speak anything newer than TLS 1.0
Hynek Schlawackbf887932015-10-21 17:13:47 +02001144 context = Context(SSLv23_METHOD)
Hynek Schlawack734d3022015-09-05 19:19:32 +02001145 context.set_default_verify_paths()
1146 context.set_verify(
1147 VERIFY_PEER,
1148 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001149
Hynek Schlawack734d3022015-09-05 19:19:32 +02001150 client = socket()
Hynek Schlawackbf887932015-10-21 17:13:47 +02001151 client.connect(("encrypted.google.com", 443))
Hynek Schlawack734d3022015-09-05 19:19:32 +02001152 clientSSL = Connection(context, client)
1153 clientSSL.set_connect_state()
1154 clientSSL.do_handshake()
1155 clientSSL.send(b"GET / HTTP/1.0\r\n\r\n")
Alex Chan532b79e2017-01-24 15:14:52 +00001156 assert clientSSL.recv(1024)
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05001157
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001158 def test_add_extra_chain_cert_invalid_cert(self):
1159 """
Alex Chan532b79e2017-01-24 15:14:52 +00001160 `Context.add_extra_chain_cert` raises `TypeError` if called with an
1161 object which is not an instance of `X509`.
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001162 """
1163 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001164 with pytest.raises(TypeError):
1165 context.add_extra_chain_cert(object())
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001166
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001167 def _handshake_test(self, serverContext, clientContext):
1168 """
1169 Verify that a client and server created with the given contexts can
1170 successfully handshake and communicate.
1171 """
1172 serverSocket, clientSocket = socket_pair()
1173
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001174 server = Connection(serverContext, serverSocket)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001175 server.set_accept_state()
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001176
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001177 client = Connection(clientContext, clientSocket)
1178 client.set_connect_state()
1179
1180 # Make them talk to each other.
Alex Chan532b79e2017-01-24 15:14:52 +00001181 # interact_in_memory(client, server)
1182 for _ in range(3):
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001183 for s in [client, server]:
1184 try:
1185 s.do_handshake()
1186 except WantReadError:
1187 pass
1188
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001189 def test_set_verify_callback_connection_argument(self):
1190 """
1191 The first argument passed to the verify callback is the
Alex Chan532b79e2017-01-24 15:14:52 +00001192 `Connection` instance for which verification is taking place.
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001193 """
1194 serverContext = Context(TLSv1_METHOD)
1195 serverContext.use_privatekey(
1196 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1197 serverContext.use_certificate(
1198 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1199 serverConnection = Connection(serverContext, None)
1200
1201 class VerifyCallback(object):
1202 def callback(self, connection, *args):
1203 self.connection = connection
1204 return 1
1205
1206 verify = VerifyCallback()
1207 clientContext = Context(TLSv1_METHOD)
1208 clientContext.set_verify(VERIFY_PEER, verify.callback)
1209 clientConnection = Connection(clientContext, None)
1210 clientConnection.set_connect_state()
1211
Alex Chan532b79e2017-01-24 15:14:52 +00001212 handshake_in_memory(clientConnection, serverConnection)
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001213
Alex Chan532b79e2017-01-24 15:14:52 +00001214 assert verify.connection is clientConnection
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001215
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001216 def test_set_verify_callback_exception(self):
1217 """
Alex Chan532b79e2017-01-24 15:14:52 +00001218 If the verify callback passed to `Context.set_verify` raises an
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001219 exception, verification fails and the exception is propagated to the
Alex Chan532b79e2017-01-24 15:14:52 +00001220 caller of `Connection.do_handshake`.
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001221 """
1222 serverContext = Context(TLSv1_METHOD)
1223 serverContext.use_privatekey(
1224 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1225 serverContext.use_certificate(
1226 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1227
1228 clientContext = Context(TLSv1_METHOD)
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001229
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001230 def verify_callback(*args):
1231 raise Exception("silly verify failure")
1232 clientContext.set_verify(VERIFY_PEER, verify_callback)
1233
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01001234 with pytest.raises(Exception) as exc:
1235 self._handshake_test(serverContext, clientContext)
1236
Alex Chan532b79e2017-01-24 15:14:52 +00001237 assert "silly verify failure" == str(exc.value)
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001238
Alex Chan532b79e2017-01-24 15:14:52 +00001239 def test_add_extra_chain_cert(self, tmpdir):
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001240 """
Alex Chan532b79e2017-01-24 15:14:52 +00001241 `Context.add_extra_chain_cert` accepts an `X509`
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001242 instance to add to the certificate chain.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001243
Alex Chan532b79e2017-01-24 15:14:52 +00001244 See `_create_certificate_chain` for the details of the
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001245 certificate chain tested.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001246
1247 The chain is tested by starting a server with scert and connecting
1248 to it with a client which trusts cacert and requires verification to
1249 succeed.
1250 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001251 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001252 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1253
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001254 # Dump the CA certificate to a file because that's the only way to load
1255 # it as a trusted CA in the client context.
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001256 for cert, name in [(cacert, 'ca.pem'),
1257 (icert, 'i.pem'),
1258 (scert, 's.pem')]:
Alex Chan532b79e2017-01-24 15:14:52 +00001259 with tmpdir.join(name).open('w') as f:
Hynek Schlawacke90680f2015-04-16 15:09:27 -04001260 f.write(dump_certificate(FILETYPE_PEM, cert).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001261
Hynek Schlawack1902c012015-04-16 15:06:41 -04001262 for key, name in [(cakey, 'ca.key'),
1263 (ikey, 'i.key'),
1264 (skey, 's.key')]:
Alex Chan532b79e2017-01-24 15:14:52 +00001265 with tmpdir.join(name).open('w') as f:
Hynek Schlawacke90680f2015-04-16 15:09:27 -04001266 f.write(dump_privatekey(FILETYPE_PEM, key).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001267
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001268 # Create the server context
1269 serverContext = Context(TLSv1_METHOD)
1270 serverContext.use_privatekey(skey)
1271 serverContext.use_certificate(scert)
Jean-Paul Calderone16cf03d2010-09-08 18:53:39 -04001272 # The client already has cacert, we only need to give them icert.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001273 serverContext.add_extra_chain_cert(icert)
1274
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001275 # Create the client
1276 clientContext = Context(TLSv1_METHOD)
1277 clientContext.set_verify(
1278 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Alex Chan532b79e2017-01-24 15:14:52 +00001279 clientContext.load_verify_locations(str(tmpdir.join("ca.pem")))
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001280
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001281 # Try it out.
1282 self._handshake_test(serverContext, clientContext)
1283
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001284 def _use_certificate_chain_file_test(self, certdir):
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001285 """
Alex Chan532b79e2017-01-24 15:14:52 +00001286 Verify that `Context.use_certificate_chain_file` reads a
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001287 certificate chain from a specified file.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001288
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001289 The chain is tested by starting a server with scert and connecting to
1290 it with a client which trusts cacert and requires verification to
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001291 succeed.
1292 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001293 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001294 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1295
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001296 makedirs(certdir)
1297
Jean-Paul Calderone05826732015-04-12 11:38:49 -04001298 chainFile = join_bytes_or_unicode(certdir, "chain.pem")
1299 caFile = join_bytes_or_unicode(certdir, "ca.pem")
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001300
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001301 # Write out the chain file.
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001302 with open(chainFile, 'wb') as fObj:
1303 # Most specific to least general.
1304 fObj.write(dump_certificate(FILETYPE_PEM, scert))
1305 fObj.write(dump_certificate(FILETYPE_PEM, icert))
1306 fObj.write(dump_certificate(FILETYPE_PEM, cacert))
1307
1308 with open(caFile, 'w') as fObj:
1309 fObj.write(dump_certificate(FILETYPE_PEM, cacert).decode('ascii'))
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001310
1311 serverContext = Context(TLSv1_METHOD)
1312 serverContext.use_certificate_chain_file(chainFile)
1313 serverContext.use_privatekey(skey)
1314
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001315 clientContext = Context(TLSv1_METHOD)
1316 clientContext.set_verify(
1317 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001318 clientContext.load_verify_locations(caFile)
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001319
1320 self._handshake_test(serverContext, clientContext)
1321
Alex Chan532b79e2017-01-24 15:14:52 +00001322 def test_use_certificate_chain_file_bytes(self, tmpfile):
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001323 """
1324 ``Context.use_certificate_chain_file`` accepts the name of a file (as
1325 an instance of ``bytes``) to specify additional certificates to use to
1326 construct and verify a trust chain.
1327 """
1328 self._use_certificate_chain_file_test(
Alex Chan532b79e2017-01-24 15:14:52 +00001329 tmpfile + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001330 )
1331
Alex Chan532b79e2017-01-24 15:14:52 +00001332 def test_use_certificate_chain_file_unicode(self, tmpfile):
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001333 """
1334 ``Context.use_certificate_chain_file`` accepts the name of a file (as
1335 an instance of ``unicode``) to specify additional certificates to use
1336 to construct and verify a trust chain.
1337 """
1338 self._use_certificate_chain_file_test(
Alex Chan532b79e2017-01-24 15:14:52 +00001339 tmpfile.decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001340 )
1341
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001342 def test_use_certificate_chain_file_wrong_args(self):
1343 """
Alex Chan532b79e2017-01-24 15:14:52 +00001344 `Context.use_certificate_chain_file` raises `TypeError` if passed a
1345 non-byte string single argument.
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001346 """
1347 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001348 with pytest.raises(TypeError):
1349 context.use_certificate_chain_file(object())
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001350
Alex Chan532b79e2017-01-24 15:14:52 +00001351 def test_use_certificate_chain_file_missing_file(self, tmpfile):
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001352 """
Alex Chan532b79e2017-01-24 15:14:52 +00001353 `Context.use_certificate_chain_file` raises `OpenSSL.SSL.Error` when
1354 passed a bad chain file name (for example, the name of a file which
1355 does not exist).
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001356 """
1357 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001358 with pytest.raises(Error):
1359 context.use_certificate_chain_file(tmpfile)
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001360
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001361 def test_set_verify_mode(self):
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001362 """
Alex Chan532b79e2017-01-24 15:14:52 +00001363 `Context.get_verify_mode` returns the verify mode flags previously
1364 passed to `Context.set_verify`.
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001365 """
1366 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001367 assert context.get_verify_mode() == 0
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001368 context.set_verify(
1369 VERIFY_PEER | VERIFY_CLIENT_ONCE, lambda *args: None)
Alex Chan532b79e2017-01-24 15:14:52 +00001370 assert context.get_verify_mode() == (VERIFY_PEER | VERIFY_CLIENT_ONCE)
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001371
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001372 @skip_if_py3
1373 def test_set_verify_mode_long(self):
1374 """
Alex Chan532b79e2017-01-24 15:14:52 +00001375 On Python 2 `Context.set_verify_mode` accepts values of type `long`
1376 as well as `int`.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001377 """
1378 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001379 assert context.get_verify_mode() == 0
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001380 context.set_verify(
Hynek Schlawackb4ceed32015-09-05 20:55:19 +02001381 long(VERIFY_PEER | VERIFY_CLIENT_ONCE), lambda *args: None
1382 ) # pragma: nocover
Alex Chan532b79e2017-01-24 15:14:52 +00001383 assert context.get_verify_mode() == (VERIFY_PEER | VERIFY_CLIENT_ONCE)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001384
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001385 def test_load_tmp_dh_wrong_args(self):
1386 """
Alex Chan532b79e2017-01-24 15:14:52 +00001387 `Context.load_tmp_dh` raises `TypeError` if called with a
1388 non-`str` argument.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001389 """
1390 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001391 with pytest.raises(TypeError):
1392 context.load_tmp_dh(object())
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001393
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001394 def test_load_tmp_dh_missing_file(self):
1395 """
Alex Chan532b79e2017-01-24 15:14:52 +00001396 `Context.load_tmp_dh` raises `OpenSSL.SSL.Error` if the
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001397 specified file does not exist.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001398 """
1399 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001400 with pytest.raises(Error):
1401 context.load_tmp_dh(b"hello")
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001402
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001403 def _load_tmp_dh_test(self, dhfilename):
Jean-Paul Calderone4e0c43f2015-04-13 10:15:17 -04001404 """
1405 Verify that calling ``Context.load_tmp_dh`` with the given filename
1406 does not raise an exception.
1407 """
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001408 context = Context(TLSv1_METHOD)
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001409 with open(dhfilename, "w") as dhfile:
1410 dhfile.write(dhparam)
1411
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001412 context.load_tmp_dh(dhfilename)
1413 # XXX What should I assert here? -exarkun
1414
Alex Chan532b79e2017-01-24 15:14:52 +00001415 def test_load_tmp_dh_bytes(self, tmpfile):
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001416 """
Alex Chan532b79e2017-01-24 15:14:52 +00001417 `Context.load_tmp_dh` loads Diffie-Hellman parameters from the
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001418 specified file (given as ``bytes``).
1419 """
1420 self._load_tmp_dh_test(
Alex Chan532b79e2017-01-24 15:14:52 +00001421 tmpfile + NON_ASCII.encode(getfilesystemencoding()),
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001422 )
1423
Alex Chan532b79e2017-01-24 15:14:52 +00001424 def test_load_tmp_dh_unicode(self, tmpfile):
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001425 """
Alex Chan532b79e2017-01-24 15:14:52 +00001426 `Context.load_tmp_dh` loads Diffie-Hellman parameters from the
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001427 specified file (given as ``unicode``).
1428 """
1429 self._load_tmp_dh_test(
Alex Chan532b79e2017-01-24 15:14:52 +00001430 tmpfile.decode(getfilesystemencoding()) + NON_ASCII,
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001431 )
1432
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001433 def test_set_tmp_ecdh(self):
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001434 """
Alex Chan532b79e2017-01-24 15:14:52 +00001435 `Context.set_tmp_ecdh` sets the elliptic curve for Diffie-Hellman to
1436 the specified curve.
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001437 """
1438 context = Context(TLSv1_METHOD)
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001439 for curve in get_elliptic_curves():
Hynek Schlawacka07fa8c2015-10-17 10:15:28 +02001440 if curve.name.startswith(u"Oakley-"):
Hynek Schlawack7408aff2015-10-17 09:51:16 +02001441 # Setting Oakley-EC2N-4 and Oakley-EC2N-3 adds
1442 # ('bignum routines', 'BN_mod_inverse', 'no inverse') to the
1443 # error queue on OpenSSL 1.0.2.
1444 continue
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001445 # The only easily "assertable" thing is that it does not raise an
1446 # exception.
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001447 context.set_tmp_ecdh(curve)
Alex Gaynor12dc0842014-01-17 12:51:31 -06001448
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001449 def test_set_session_cache_mode_wrong_args(self):
1450 """
Alex Chan532b79e2017-01-24 15:14:52 +00001451 `Context.set_session_cache_mode` raises `TypeError` if called with
1452 a non-integer argument.
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001453 called with other than one integer argument.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001454 """
1455 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001456 with pytest.raises(TypeError):
1457 context.set_session_cache_mode(object())
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001458
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001459 def test_session_cache_mode(self):
1460 """
Alex Chan532b79e2017-01-24 15:14:52 +00001461 `Context.set_session_cache_mode` specifies how sessions are cached.
1462 The setting can be retrieved via `Context.get_session_cache_mode`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001463 """
1464 context = Context(TLSv1_METHOD)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001465 context.set_session_cache_mode(SESS_CACHE_OFF)
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001466 off = context.set_session_cache_mode(SESS_CACHE_BOTH)
Alex Chan532b79e2017-01-24 15:14:52 +00001467 assert SESS_CACHE_OFF == off
1468 assert SESS_CACHE_BOTH == context.get_session_cache_mode()
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001469
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001470 @skip_if_py3
1471 def test_session_cache_mode_long(self):
1472 """
Alex Chan532b79e2017-01-24 15:14:52 +00001473 On Python 2 `Context.set_session_cache_mode` accepts values
1474 of type `long` as well as `int`.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001475 """
1476 context = Context(TLSv1_METHOD)
1477 context.set_session_cache_mode(long(SESS_CACHE_BOTH))
Alex Chan532b79e2017-01-24 15:14:52 +00001478 assert SESS_CACHE_BOTH == context.get_session_cache_mode()
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001479
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001480 def test_get_cert_store(self):
1481 """
Alex Chan532b79e2017-01-24 15:14:52 +00001482 `Context.get_cert_store` returns a `X509Store` instance.
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001483 """
1484 context = Context(TLSv1_METHOD)
1485 store = context.get_cert_store()
Alex Chan532b79e2017-01-24 15:14:52 +00001486 assert isinstance(store, X509Store)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001487
1488
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001489class TestServerNameCallback(object):
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001490 """
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001491 Tests for `Context.set_tlsext_servername_callback` and its
1492 interaction with `Connection`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001493 """
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001494 def test_old_callback_forgotten(self):
1495 """
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001496 If `Context.set_tlsext_servername_callback` is used to specify
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001497 a new callback, the one it replaces is dereferenced.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001498 """
1499 def callback(connection):
1500 pass
1501
1502 def replacement(connection):
1503 pass
1504
1505 context = Context(TLSv1_METHOD)
1506 context.set_tlsext_servername_callback(callback)
1507
1508 tracker = ref(callback)
1509 del callback
1510
1511 context.set_tlsext_servername_callback(replacement)
Jean-Paul Calderoned4033eb2014-01-11 08:21:46 -05001512
1513 # One run of the garbage collector happens to work on CPython. PyPy
1514 # doesn't collect the underlying object until a second run for whatever
1515 # reason. That's fine, it still demonstrates our code has properly
1516 # dropped the reference.
1517 collect()
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001518 collect()
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001519
1520 callback = tracker()
1521 if callback is not None:
1522 referrers = get_referrers(callback)
Jean-Paul Calderone7de39562014-01-11 08:17:59 -05001523 if len(referrers) > 1:
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001524 self.fail("Some references remain: %r" % (referrers,))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001525
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001526 def test_no_servername(self):
1527 """
1528 When a client specifies no server name, the callback passed to
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001529 `Context.set_tlsext_servername_callback` is invoked and the
1530 result of `Connection.get_servername` is `None`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001531 """
1532 args = []
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001533
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001534 def servername(conn):
1535 args.append((conn, conn.get_servername()))
1536 context = Context(TLSv1_METHOD)
1537 context.set_tlsext_servername_callback(servername)
1538
1539 # Lose our reference to it. The Context is responsible for keeping it
1540 # alive now.
1541 del servername
1542 collect()
1543
1544 # Necessary to actually accept the connection
1545 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001546 context.use_certificate(
1547 load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001548
1549 # Do a little connection to trigger the logic
1550 server = Connection(context, None)
1551 server.set_accept_state()
1552
1553 client = Connection(Context(TLSv1_METHOD), None)
1554 client.set_connect_state()
1555
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001556 interact_in_memory(server, client)
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001557
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001558 assert args == [(server, None)]
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001559
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001560 def test_servername(self):
1561 """
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001562 When a client specifies a server name in its hello message, the
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001563 callback passed to `Contexts.set_tlsext_servername_callback` is
1564 invoked and the result of `Connection.get_servername` is that
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001565 server name.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001566 """
1567 args = []
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001568
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001569 def servername(conn):
1570 args.append((conn, conn.get_servername()))
1571 context = Context(TLSv1_METHOD)
1572 context.set_tlsext_servername_callback(servername)
1573
1574 # Necessary to actually accept the connection
1575 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001576 context.use_certificate(
1577 load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001578
1579 # Do a little connection to trigger the logic
1580 server = Connection(context, None)
1581 server.set_accept_state()
1582
1583 client = Connection(Context(TLSv1_METHOD), None)
1584 client.set_connect_state()
Alex Gaynore7f51982016-09-11 11:48:14 -04001585 client.set_tlsext_host_name(b"foo1.example.com")
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001586
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001587 interact_in_memory(server, client)
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001588
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001589 assert args == [(server, b"foo1.example.com")]
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001590
1591
Alex Chan9e08b3e2016-11-10 12:18:54 +00001592class TestNextProtoNegotiation(object):
Cory Benfield84a121e2014-03-31 20:30:25 +01001593 """
1594 Test for Next Protocol Negotiation in PyOpenSSL.
1595 """
Alex Chan9e08b3e2016-11-10 12:18:54 +00001596 def test_npn_success(self):
1597 """
1598 Tests that clients and servers that agree on the negotiated next
1599 protocol can correct establish a connection, and that the agreed
1600 protocol is reported by the connections.
1601 """
1602 advertise_args = []
1603 select_args = []
1604
1605 def advertise(conn):
1606 advertise_args.append((conn,))
1607 return [b'http/1.1', b'spdy/2']
1608
1609 def select(conn, options):
1610 select_args.append((conn, options))
1611 return b'spdy/2'
1612
1613 server_context = Context(TLSv1_METHOD)
1614 server_context.set_npn_advertise_callback(advertise)
1615
1616 client_context = Context(TLSv1_METHOD)
1617 client_context.set_npn_select_callback(select)
1618
1619 # Necessary to actually accept the connection
1620 server_context.use_privatekey(
1621 load_privatekey(FILETYPE_PEM, server_key_pem))
1622 server_context.use_certificate(
1623 load_certificate(FILETYPE_PEM, server_cert_pem))
1624
1625 # Do a little connection to trigger the logic
1626 server = Connection(server_context, None)
1627 server.set_accept_state()
1628
1629 client = Connection(client_context, None)
1630 client.set_connect_state()
1631
1632 interact_in_memory(server, client)
1633
1634 assert advertise_args == [(server,)]
1635 assert select_args == [(client, [b'http/1.1', b'spdy/2'])]
1636
1637 assert server.get_next_proto_negotiated() == b'spdy/2'
1638 assert client.get_next_proto_negotiated() == b'spdy/2'
1639
1640 def test_npn_client_fail(self):
1641 """
1642 Tests that when clients and servers cannot agree on what protocol
1643 to use next that the TLS connection does not get established.
1644 """
1645 advertise_args = []
1646 select_args = []
1647
1648 def advertise(conn):
1649 advertise_args.append((conn,))
1650 return [b'http/1.1', b'spdy/2']
1651
1652 def select(conn, options):
1653 select_args.append((conn, options))
1654 return b''
1655
1656 server_context = Context(TLSv1_METHOD)
1657 server_context.set_npn_advertise_callback(advertise)
1658
1659 client_context = Context(TLSv1_METHOD)
1660 client_context.set_npn_select_callback(select)
1661
1662 # Necessary to actually accept the connection
1663 server_context.use_privatekey(
1664 load_privatekey(FILETYPE_PEM, server_key_pem))
1665 server_context.use_certificate(
1666 load_certificate(FILETYPE_PEM, server_cert_pem))
1667
1668 # Do a little connection to trigger the logic
1669 server = Connection(server_context, None)
1670 server.set_accept_state()
1671
1672 client = Connection(client_context, None)
1673 client.set_connect_state()
1674
1675 # If the client doesn't return anything, the connection will fail.
1676 with pytest.raises(Error):
1677 interact_in_memory(server, client)
1678
1679 assert advertise_args == [(server,)]
1680 assert select_args == [(client, [b'http/1.1', b'spdy/2'])]
1681
1682 def test_npn_select_error(self):
1683 """
1684 Test that we can handle exceptions in the select callback. If
1685 select fails it should be fatal to the connection.
1686 """
1687 advertise_args = []
1688
1689 def advertise(conn):
1690 advertise_args.append((conn,))
1691 return [b'http/1.1', b'spdy/2']
1692
1693 def select(conn, options):
1694 raise TypeError
1695
1696 server_context = Context(TLSv1_METHOD)
1697 server_context.set_npn_advertise_callback(advertise)
1698
1699 client_context = Context(TLSv1_METHOD)
1700 client_context.set_npn_select_callback(select)
1701
1702 # Necessary to actually accept the connection
1703 server_context.use_privatekey(
1704 load_privatekey(FILETYPE_PEM, server_key_pem))
1705 server_context.use_certificate(
1706 load_certificate(FILETYPE_PEM, server_cert_pem))
1707
1708 # Do a little connection to trigger the logic
1709 server = Connection(server_context, None)
1710 server.set_accept_state()
1711
1712 client = Connection(client_context, None)
1713 client.set_connect_state()
1714
1715 # If the callback throws an exception it should be raised here.
1716 with pytest.raises(TypeError):
1717 interact_in_memory(server, client)
1718 assert advertise_args == [(server,), ]
1719
1720 def test_npn_advertise_error(self):
1721 """
1722 Test that we can handle exceptions in the advertise callback. If
1723 advertise fails no NPN is advertised to the client.
1724 """
1725 select_args = []
1726
1727 def advertise(conn):
1728 raise TypeError
1729
1730 def select(conn, options): # pragma: nocover
Cory Benfieldba1820d2015-04-13 17:39:12 -04001731 """
Alex Chan9e08b3e2016-11-10 12:18:54 +00001732 Assert later that no args are actually appended.
Cory Benfieldba1820d2015-04-13 17:39:12 -04001733 """
Alex Chan9e08b3e2016-11-10 12:18:54 +00001734 select_args.append((conn, options))
1735 return b''
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001736
Alex Chan9e08b3e2016-11-10 12:18:54 +00001737 server_context = Context(TLSv1_METHOD)
1738 server_context.set_npn_advertise_callback(advertise)
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001739
Alex Chan9e08b3e2016-11-10 12:18:54 +00001740 client_context = Context(TLSv1_METHOD)
1741 client_context.set_npn_select_callback(select)
Cory Benfield84a121e2014-03-31 20:30:25 +01001742
Alex Chan9e08b3e2016-11-10 12:18:54 +00001743 # Necessary to actually accept the connection
1744 server_context.use_privatekey(
1745 load_privatekey(FILETYPE_PEM, server_key_pem))
1746 server_context.use_certificate(
1747 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield84a121e2014-03-31 20:30:25 +01001748
Alex Chan9e08b3e2016-11-10 12:18:54 +00001749 # Do a little connection to trigger the logic
1750 server = Connection(server_context, None)
1751 server.set_accept_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001752
Alex Chan9e08b3e2016-11-10 12:18:54 +00001753 client = Connection(client_context, None)
1754 client.set_connect_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001755
Alex Chan9e08b3e2016-11-10 12:18:54 +00001756 # If the client doesn't return anything, the connection will fail.
1757 with pytest.raises(TypeError):
1758 interact_in_memory(server, client)
1759 assert select_args == []
Cory Benfield0ea76e72015-03-22 09:05:28 +00001760
1761
Alex Chanec1e32d2016-11-10 14:11:45 +00001762class TestApplicationLayerProtoNegotiation(object):
Cory Benfield12eae892014-06-07 15:42:56 +01001763 """
1764 Tests for ALPN in PyOpenSSL.
1765 """
Cory Benfielde46fa842015-04-13 16:50:49 -04001766 # Skip tests on versions that don't support ALPN.
1767 if _lib.Cryptography_HAS_ALPN:
Cory Benfield12eae892014-06-07 15:42:56 +01001768
Cory Benfielde46fa842015-04-13 16:50:49 -04001769 def test_alpn_success(self):
1770 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04001771 Clients and servers that agree on the negotiated ALPN protocol can
1772 correct establish a connection, and the agreed protocol is reported
1773 by the connections.
Cory Benfielde46fa842015-04-13 16:50:49 -04001774 """
1775 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001776
Cory Benfielde46fa842015-04-13 16:50:49 -04001777 def select(conn, options):
1778 select_args.append((conn, options))
1779 return b'spdy/2'
Cory Benfield12eae892014-06-07 15:42:56 +01001780
Cory Benfielde46fa842015-04-13 16:50:49 -04001781 client_context = Context(TLSv1_METHOD)
1782 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfield12eae892014-06-07 15:42:56 +01001783
Cory Benfielde46fa842015-04-13 16:50:49 -04001784 server_context = Context(TLSv1_METHOD)
1785 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01001786
Cory Benfielde46fa842015-04-13 16:50:49 -04001787 # Necessary to actually accept the connection
1788 server_context.use_privatekey(
1789 load_privatekey(FILETYPE_PEM, server_key_pem))
1790 server_context.use_certificate(
1791 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield12eae892014-06-07 15:42:56 +01001792
Cory Benfielde46fa842015-04-13 16:50:49 -04001793 # Do a little connection to trigger the logic
1794 server = Connection(server_context, None)
1795 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001796
Cory Benfielde46fa842015-04-13 16:50:49 -04001797 client = Connection(client_context, None)
1798 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001799
Alex Chanec1e32d2016-11-10 14:11:45 +00001800 interact_in_memory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001801
Alex Chanec1e32d2016-11-10 14:11:45 +00001802 assert select_args == [(server, [b'http/1.1', b'spdy/2'])]
Cory Benfielde46fa842015-04-13 16:50:49 -04001803
Alex Chanec1e32d2016-11-10 14:11:45 +00001804 assert server.get_alpn_proto_negotiated() == b'spdy/2'
1805 assert client.get_alpn_proto_negotiated() == b'spdy/2'
Cory Benfield12eae892014-06-07 15:42:56 +01001806
Cory Benfielde46fa842015-04-13 16:50:49 -04001807 def test_alpn_set_on_connection(self):
1808 """
1809 The same as test_alpn_success, but setting the ALPN protocols on
1810 the connection rather than the context.
1811 """
1812 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001813
Cory Benfielde46fa842015-04-13 16:50:49 -04001814 def select(conn, options):
1815 select_args.append((conn, options))
1816 return b'spdy/2'
Cory Benfield12eae892014-06-07 15:42:56 +01001817
Cory Benfielde46fa842015-04-13 16:50:49 -04001818 # Setup the client context but don't set any ALPN protocols.
1819 client_context = Context(TLSv1_METHOD)
Cory Benfield12eae892014-06-07 15:42:56 +01001820
Cory Benfielde46fa842015-04-13 16:50:49 -04001821 server_context = Context(TLSv1_METHOD)
1822 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01001823
Cory Benfielde46fa842015-04-13 16:50:49 -04001824 # Necessary to actually accept the connection
1825 server_context.use_privatekey(
1826 load_privatekey(FILETYPE_PEM, server_key_pem))
1827 server_context.use_certificate(
1828 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield12eae892014-06-07 15:42:56 +01001829
Cory Benfielde46fa842015-04-13 16:50:49 -04001830 # Do a little connection to trigger the logic
1831 server = Connection(server_context, None)
1832 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001833
Cory Benfielde46fa842015-04-13 16:50:49 -04001834 # Set the ALPN protocols on the client connection.
1835 client = Connection(client_context, None)
1836 client.set_alpn_protos([b'http/1.1', b'spdy/2'])
1837 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001838
Alex Chanec1e32d2016-11-10 14:11:45 +00001839 interact_in_memory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001840
Alex Chanec1e32d2016-11-10 14:11:45 +00001841 assert select_args == [(server, [b'http/1.1', b'spdy/2'])]
Cory Benfield12eae892014-06-07 15:42:56 +01001842
Alex Chanec1e32d2016-11-10 14:11:45 +00001843 assert server.get_alpn_proto_negotiated() == b'spdy/2'
1844 assert client.get_alpn_proto_negotiated() == b'spdy/2'
Cory Benfield12eae892014-06-07 15:42:56 +01001845
Cory Benfielde46fa842015-04-13 16:50:49 -04001846 def test_alpn_server_fail(self):
1847 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04001848 When clients and servers cannot agree on what protocol to use next
1849 the TLS connection does not get established.
Cory Benfielde46fa842015-04-13 16:50:49 -04001850 """
1851 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001852
Cory Benfielde46fa842015-04-13 16:50:49 -04001853 def select(conn, options):
1854 select_args.append((conn, options))
1855 return b''
Cory Benfield12eae892014-06-07 15:42:56 +01001856
Cory Benfielde46fa842015-04-13 16:50:49 -04001857 client_context = Context(TLSv1_METHOD)
1858 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfield12eae892014-06-07 15:42:56 +01001859
Cory Benfielde46fa842015-04-13 16:50:49 -04001860 server_context = Context(TLSv1_METHOD)
1861 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01001862
Cory Benfielde46fa842015-04-13 16:50:49 -04001863 # Necessary to actually accept the connection
1864 server_context.use_privatekey(
1865 load_privatekey(FILETYPE_PEM, server_key_pem))
1866 server_context.use_certificate(
1867 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield12eae892014-06-07 15:42:56 +01001868
Cory Benfielde46fa842015-04-13 16:50:49 -04001869 # Do a little connection to trigger the logic
1870 server = Connection(server_context, None)
1871 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001872
Cory Benfielde46fa842015-04-13 16:50:49 -04001873 client = Connection(client_context, None)
1874 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001875
Cory Benfielde46fa842015-04-13 16:50:49 -04001876 # If the client doesn't return anything, the connection will fail.
Alex Chanec1e32d2016-11-10 14:11:45 +00001877 with pytest.raises(Error):
1878 interact_in_memory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001879
Alex Chanec1e32d2016-11-10 14:11:45 +00001880 assert select_args == [(server, [b'http/1.1', b'spdy/2'])]
Cory Benfield12eae892014-06-07 15:42:56 +01001881
Cory Benfielde46fa842015-04-13 16:50:49 -04001882 def test_alpn_no_server(self):
1883 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04001884 When clients and servers cannot agree on what protocol to use next
1885 because the server doesn't offer ALPN, no protocol is negotiated.
Cory Benfielde46fa842015-04-13 16:50:49 -04001886 """
1887 client_context = Context(TLSv1_METHOD)
1888 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfielde3d57152015-04-11 17:57:35 -04001889
Cory Benfielde46fa842015-04-13 16:50:49 -04001890 server_context = Context(TLSv1_METHOD)
Cory Benfielde3d57152015-04-11 17:57:35 -04001891
Cory Benfielde46fa842015-04-13 16:50:49 -04001892 # Necessary to actually accept the connection
1893 server_context.use_privatekey(
1894 load_privatekey(FILETYPE_PEM, server_key_pem))
1895 server_context.use_certificate(
1896 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfielde3d57152015-04-11 17:57:35 -04001897
Cory Benfielde46fa842015-04-13 16:50:49 -04001898 # Do a little connection to trigger the logic
1899 server = Connection(server_context, None)
1900 server.set_accept_state()
Cory Benfielde3d57152015-04-11 17:57:35 -04001901
Cory Benfielde46fa842015-04-13 16:50:49 -04001902 client = Connection(client_context, None)
1903 client.set_connect_state()
Cory Benfielde3d57152015-04-11 17:57:35 -04001904
Cory Benfielde46fa842015-04-13 16:50:49 -04001905 # Do the dance.
Alex Chanec1e32d2016-11-10 14:11:45 +00001906 interact_in_memory(server, client)
Cory Benfielde3d57152015-04-11 17:57:35 -04001907
Alex Chanec1e32d2016-11-10 14:11:45 +00001908 assert client.get_alpn_proto_negotiated() == b''
Cory Benfielde3d57152015-04-11 17:57:35 -04001909
Cory Benfielde46fa842015-04-13 16:50:49 -04001910 def test_alpn_callback_exception(self):
1911 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04001912 We can handle exceptions in the ALPN select callback.
Cory Benfielde46fa842015-04-13 16:50:49 -04001913 """
1914 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001915
Cory Benfielde46fa842015-04-13 16:50:49 -04001916 def select(conn, options):
1917 select_args.append((conn, options))
Cory Benfieldef401452015-04-13 18:17:36 -04001918 raise TypeError()
Cory Benfieldf1177e72015-04-12 09:11:49 -04001919
Cory Benfielde46fa842015-04-13 16:50:49 -04001920 client_context = Context(TLSv1_METHOD)
1921 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfieldf1177e72015-04-12 09:11:49 -04001922
Cory Benfielde46fa842015-04-13 16:50:49 -04001923 server_context = Context(TLSv1_METHOD)
1924 server_context.set_alpn_select_callback(select)
Cory Benfieldf1177e72015-04-12 09:11:49 -04001925
Cory Benfielde46fa842015-04-13 16:50:49 -04001926 # Necessary to actually accept the connection
1927 server_context.use_privatekey(
1928 load_privatekey(FILETYPE_PEM, server_key_pem))
1929 server_context.use_certificate(
1930 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfieldf1177e72015-04-12 09:11:49 -04001931
Cory Benfielde46fa842015-04-13 16:50:49 -04001932 # Do a little connection to trigger the logic
1933 server = Connection(server_context, None)
1934 server.set_accept_state()
Cory Benfieldf1177e72015-04-12 09:11:49 -04001935
Cory Benfielde46fa842015-04-13 16:50:49 -04001936 client = Connection(client_context, None)
1937 client.set_connect_state()
Cory Benfieldf1177e72015-04-12 09:11:49 -04001938
Alex Chanec1e32d2016-11-10 14:11:45 +00001939 with pytest.raises(TypeError):
1940 interact_in_memory(server, client)
1941 assert select_args == [(server, [b'http/1.1', b'spdy/2'])]
Cory Benfieldf1177e72015-04-12 09:11:49 -04001942
Cory Benfield0f7b04c2015-04-13 17:51:12 -04001943 else:
1944 # No ALPN.
1945 def test_alpn_not_implemented(self):
Cory Benfieldef401452015-04-13 18:17:36 -04001946 """
1947 If ALPN is not in OpenSSL, we should raise NotImplementedError.
1948 """
Cory Benfield0f7b04c2015-04-13 17:51:12 -04001949 # Test the context methods first.
1950 context = Context(TLSv1_METHOD)
Alex Chanec1e32d2016-11-10 14:11:45 +00001951 with pytest.raises(NotImplementedError):
1952 context.set_alpn_protos(None)
1953 with pytest.raises(NotImplementedError):
1954 context.set_alpn_select_callback(None)
Cory Benfield0f7b04c2015-04-13 17:51:12 -04001955
1956 # Now test a connection.
1957 conn = Connection(context)
Alex Chanec1e32d2016-11-10 14:11:45 +00001958 with pytest.raises(NotImplementedError):
1959 conn.set_alpn_protos(None)
Cory Benfield0f7b04c2015-04-13 17:51:12 -04001960
Cory Benfieldf1177e72015-04-12 09:11:49 -04001961
Alex Chanec1e32d2016-11-10 14:11:45 +00001962class TestSession(object):
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05001963 """
1964 Unit tests for :py:obj:`OpenSSL.SSL.Session`.
1965 """
1966 def test_construction(self):
1967 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001968 :py:class:`Session` can be constructed with no arguments, creating
1969 a new instance of that type.
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05001970 """
1971 new_session = Session()
Alex Chanec1e32d2016-11-10 14:11:45 +00001972 assert isinstance(new_session, Session)
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05001973
1974
Alex Chan1c0cb662017-01-30 07:13:30 +00001975class TestConnection(object):
Rick Deane15b1472009-07-09 15:53:42 -05001976 """
Alex Chan1c0cb662017-01-30 07:13:30 +00001977 Unit tests for `OpenSSL.SSL.Connection`.
Rick Deane15b1472009-07-09 15:53:42 -05001978 """
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04001979 # XXX get_peer_certificate -> None
1980 # XXX sock_shutdown
1981 # XXX master_key -> TypeError
1982 # XXX server_random -> TypeError
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04001983 # XXX connect -> TypeError
1984 # XXX connect_ex -> TypeError
1985 # XXX set_connect_state -> TypeError
1986 # XXX set_accept_state -> TypeError
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04001987 # XXX do_handshake -> TypeError
1988 # XXX bio_read -> TypeError
1989 # XXX recv -> TypeError
1990 # XXX send -> TypeError
1991 # XXX bio_write -> TypeError
1992
Rick Deane15b1472009-07-09 15:53:42 -05001993 def test_type(self):
1994 """
Alex Chan1c0cb662017-01-30 07:13:30 +00001995 `Connection` and `ConnectionType` refer to the same type object and
1996 can be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -05001997 """
Alex Chan1c0cb662017-01-30 07:13:30 +00001998 assert Connection is ConnectionType
Rick Deane15b1472009-07-09 15:53:42 -05001999 ctx = Context(TLSv1_METHOD)
Alex Chan1c0cb662017-01-30 07:13:30 +00002000 assert is_consistent_type(Connection, 'Connection', ctx, None)
Rick Deane15b1472009-07-09 15:53:42 -05002001
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002002 def test_get_context(self):
2003 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002004 `Connection.get_context` returns the `Context` instance used to
2005 construct the `Connection` instance.
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002006 """
2007 context = Context(TLSv1_METHOD)
2008 connection = Connection(context, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002009 assert connection.get_context() is context
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002010
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002011 def test_set_context_wrong_args(self):
2012 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002013 `Connection.set_context` raises `TypeError` if called with a
2014 non-`Context` instance argument,
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002015 """
2016 ctx = Context(TLSv1_METHOD)
2017 connection = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002018 with pytest.raises(TypeError):
2019 connection.set_context(object())
2020 with pytest.raises(TypeError):
2021 connection.set_context("hello")
2022 with pytest.raises(TypeError):
2023 connection.set_context(1)
2024 assert ctx is connection.get_context()
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002025
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002026 def test_set_context(self):
2027 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002028 `Connection.set_context` specifies a new `Context` instance to be
2029 used for the connection.
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002030 """
2031 original = Context(SSLv23_METHOD)
2032 replacement = Context(TLSv1_METHOD)
2033 connection = Connection(original, None)
2034 connection.set_context(replacement)
Alex Chan1c0cb662017-01-30 07:13:30 +00002035 assert replacement is connection.get_context()
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002036 # Lose our references to the contexts, just in case the Connection
2037 # isn't properly managing its own contributions to their reference
2038 # counts.
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002039 del original, replacement
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002040 collect()
2041
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002042 def test_set_tlsext_host_name_wrong_args(self):
2043 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002044 If `Connection.set_tlsext_host_name` is called with a non-byte string
2045 argument or a byte string with an embedded NUL, `TypeError` is raised.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002046 """
2047 conn = Connection(Context(TLSv1_METHOD), None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002048 with pytest.raises(TypeError):
2049 conn.set_tlsext_host_name(object())
2050 with pytest.raises(TypeError):
2051 conn.set_tlsext_host_name(b"with\0null")
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002052
Abraham Martinc5484ba2015-03-25 15:33:05 +00002053 if PY3:
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002054 # On Python 3.x, don't accidentally implicitly convert from text.
Alex Chan1c0cb662017-01-30 07:13:30 +00002055 with pytest.raises(TypeError):
2056 conn.set_tlsext_host_name(b"example.com".decode("ascii"))
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04002057
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002058 def test_pending(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002059 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002060 `Connection.pending` returns the number of bytes available for
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002061 immediate read.
2062 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002063 connection = Connection(Context(TLSv1_METHOD), None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002064 assert connection.pending() == 0
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002065
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002066 def test_peek(self):
2067 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002068 `Connection.recv` peeks into the connection if `socket.MSG_PEEK`
2069 is passed.
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002070 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002071 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002072 server.send(b'xy')
Alex Chan1c0cb662017-01-30 07:13:30 +00002073 assert client.recv(2, MSG_PEEK) == b'xy'
2074 assert client.recv(2, MSG_PEEK) == b'xy'
2075 assert client.recv(2) == b'xy'
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002076
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002077 def test_connect_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002078 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002079 `Connection.connect` raises `TypeError` if called with
2080 a non-address argument.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002081 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002082 connection = Connection(Context(TLSv1_METHOD), socket())
Alex Chan1c0cb662017-01-30 07:13:30 +00002083 with pytest.raises(TypeError):
2084 connection.connect(None)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002085
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002086 def test_connect_refused(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002087 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002088 `Connection.connect` raises `socket.error` if the underlying socket
2089 connect method raises it.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002090 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002091 client = socket()
2092 context = Context(TLSv1_METHOD)
2093 clientSSL = Connection(context, client)
Alex Gaynor122717b2015-09-05 14:14:18 -04002094 # pytest.raises here doesn't work because of a bug in py.test on Python
2095 # 2.6: https://github.com/pytest-dev/pytest/issues/988
Alex Gaynore69c2782015-09-05 14:07:48 -04002096 try:
Alex Gaynor1aabb2e2015-09-05 13:35:18 -04002097 clientSSL.connect(("127.0.0.1", 1))
Alex Gaynore69c2782015-09-05 14:07:48 -04002098 except error as e:
Alex Gaynor20a4c082015-09-05 14:24:15 -04002099 exc = e
2100 assert exc.args[0] == ECONNREFUSED
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002101
2102 def test_connect(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002103 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002104 `Connection.connect` establishes a connection to the specified address.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002105 """
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002106 port = socket()
2107 port.bind(('', 0))
2108 port.listen(3)
2109
2110 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002111 clientSSL.connect(('127.0.0.1', port.getsockname()[1]))
2112 # XXX An assertion? Or something?
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002113
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002114 @pytest.mark.skipif(
2115 platform == "darwin",
2116 reason="connect_ex sometimes causes a kernel panic on OS X 10.6.4"
2117 )
2118 def test_connect_ex(self):
2119 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002120 If there is a connection error, `Connection.connect_ex` returns the
2121 errno instead of raising an exception.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002122 """
2123 port = socket()
2124 port.bind(('', 0))
2125 port.listen(3)
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002126
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002127 clientSSL = Connection(Context(TLSv1_METHOD), socket())
2128 clientSSL.setblocking(False)
2129 result = clientSSL.connect_ex(port.getsockname())
2130 expected = (EINPROGRESS, EWOULDBLOCK)
Alex Chan1c0cb662017-01-30 07:13:30 +00002131 assert result in expected
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002132
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002133 def test_accept(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002134 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002135 `Connection.accept` accepts a pending connection attempt and returns a
2136 tuple of a new `Connection` (the accepted client) and the address the
2137 connection originated from.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002138 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002139 ctx = Context(TLSv1_METHOD)
2140 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2141 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002142 port = socket()
2143 portSSL = Connection(ctx, port)
2144 portSSL.bind(('', 0))
2145 portSSL.listen(3)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002146
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002147 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002148
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002149 # Calling portSSL.getsockname() here to get the server IP address
2150 # sounds great, but frequently fails on Windows.
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002151 clientSSL.connect(('127.0.0.1', portSSL.getsockname()[1]))
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002152
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002153 serverSSL, address = portSSL.accept()
2154
Alex Chan1c0cb662017-01-30 07:13:30 +00002155 assert isinstance(serverSSL, Connection)
2156 assert serverSSL.get_context() is ctx
2157 assert address == clientSSL.getsockname()
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002158
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002159 def test_shutdown_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002160 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002161 `Connection.set_shutdown` raises `TypeError` if called with arguments
2162 other than integers.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002163 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002164 connection = Connection(Context(TLSv1_METHOD), None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002165 with pytest.raises(TypeError):
2166 connection.set_shutdown(None)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002167
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002168 def test_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002169 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002170 `Connection.shutdown` performs an SSL-level connection shutdown.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002171 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002172 server, client = loopback()
2173 assert not server.shutdown()
2174 assert server.get_shutdown() == SENT_SHUTDOWN
2175 with pytest.raises(ZeroReturnError):
2176 client.recv(1024)
2177 assert client.get_shutdown() == RECEIVED_SHUTDOWN
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04002178 client.shutdown()
Alex Chan1c0cb662017-01-30 07:13:30 +00002179 assert client.get_shutdown() == (SENT_SHUTDOWN | RECEIVED_SHUTDOWN)
2180 with pytest.raises(ZeroReturnError):
2181 server.recv(1024)
2182 assert server.get_shutdown() == (SENT_SHUTDOWN | RECEIVED_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002183
Paul Aurichc85e0862015-01-08 08:34:33 -08002184 def test_shutdown_closed(self):
2185 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002186 If the underlying socket is closed, `Connection.shutdown` propagates
2187 the write error from the low level write call.
Paul Aurichc85e0862015-01-08 08:34:33 -08002188 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002189 server, client = loopback()
Paul Aurichc85e0862015-01-08 08:34:33 -08002190 server.sock_shutdown(2)
Alex Chan1c0cb662017-01-30 07:13:30 +00002191 with pytest.raises(SysCallError) as exc:
2192 server.shutdown()
2193 if platform == "win32":
2194 assert exc.value.args[0] == ESHUTDOWN
2195 else:
2196 assert exc.value.args[0] == EPIPE
Paul Aurichc85e0862015-01-08 08:34:33 -08002197
Glyph89389472015-04-14 17:29:26 -04002198 def test_shutdown_truncated(self):
Glyph6064ec32015-04-14 16:38:22 -04002199 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002200 If the underlying connection is truncated, `Connection.shutdown`
2201 raises an `Error`.
Glyph6064ec32015-04-14 16:38:22 -04002202 """
Glyph89389472015-04-14 17:29:26 -04002203 server_ctx = Context(TLSv1_METHOD)
2204 client_ctx = Context(TLSv1_METHOD)
2205 server_ctx.use_privatekey(
2206 load_privatekey(FILETYPE_PEM, server_key_pem))
2207 server_ctx.use_certificate(
2208 load_certificate(FILETYPE_PEM, server_cert_pem))
2209 server = Connection(server_ctx, None)
2210 client = Connection(client_ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002211 handshake_in_memory(client, server)
2212 assert not server.shutdown()
2213 with pytest.raises(WantReadError):
2214 server.shutdown()
Glyph89389472015-04-14 17:29:26 -04002215 server.bio_shutdown()
Alex Chan1c0cb662017-01-30 07:13:30 +00002216 with pytest.raises(Error):
2217 server.shutdown()
Glyph6064ec32015-04-14 16:38:22 -04002218
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002219 def test_set_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002220 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002221 `Connection.set_shutdown` sets the state of the SSL connection
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002222 shutdown process.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002223 """
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002224 connection = Connection(Context(TLSv1_METHOD), socket())
2225 connection.set_shutdown(RECEIVED_SHUTDOWN)
Alex Chan1c0cb662017-01-30 07:13:30 +00002226 assert connection.get_shutdown() == RECEIVED_SHUTDOWN
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002227
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002228 @skip_if_py3
2229 def test_set_shutdown_long(self):
2230 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002231 On Python 2 `Connection.set_shutdown` accepts an argument
2232 of type `long` as well as `int`.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002233 """
2234 connection = Connection(Context(TLSv1_METHOD), socket())
2235 connection.set_shutdown(long(RECEIVED_SHUTDOWN))
Alex Chan1c0cb662017-01-30 07:13:30 +00002236 assert connection.get_shutdown() == RECEIVED_SHUTDOWN
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -05002237
kjavaf248592015-09-07 12:14:01 +01002238 def test_state_string(self):
2239 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002240 `Connection.state_string` verbosely describes the current state of
2241 the `Connection`.
kjavaf248592015-09-07 12:14:01 +01002242 """
Hynek Schlawackb0274ce2015-10-16 19:56:26 +02002243 server, client = socket_pair()
Alex Chan1c0cb662017-01-30 07:13:30 +00002244 server = loopback_server_factory(server)
2245 client = loopback_client_factory(client)
kjavaf248592015-09-07 12:14:01 +01002246
Alex Gaynor5af32d02016-09-24 01:52:21 -04002247 assert server.get_state_string() in [
2248 b"before/accept initialization", b"before SSL initialization"
2249 ]
2250 assert client.get_state_string() in [
2251 b"before/connect initialization", b"before SSL initialization"
2252 ]
kjavaf248592015-09-07 12:14:01 +01002253
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002254 def test_app_data(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002255 """
2256 Any object can be set as app data by passing it to
Alex Chan1c0cb662017-01-30 07:13:30 +00002257 `Connection.set_app_data` and later retrieved with
2258 `Connection.get_app_data`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002259 """
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002260 conn = Connection(Context(TLSv1_METHOD), None)
Todd Chapman4f73e4f2015-08-27 11:26:43 -04002261 assert None is conn.get_app_data()
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002262 app_data = object()
2263 conn.set_app_data(app_data)
Todd Chapman4f73e4f2015-08-27 11:26:43 -04002264 assert conn.get_app_data() is app_data
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002265
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002266 def test_makefile(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002267 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002268 `Connection.makefile` is not implemented and calling that
2269 method raises `NotImplementedError`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002270 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002271 conn = Connection(Context(TLSv1_METHOD), None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002272 with pytest.raises(NotImplementedError):
2273 conn.makefile()
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002274
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002275 def test_get_peer_cert_chain(self):
2276 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002277 `Connection.get_peer_cert_chain` returns a list of certificates
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002278 which the connected server returned for the certification verification.
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002279 """
2280 chain = _create_certificate_chain()
2281 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
2282
2283 serverContext = Context(TLSv1_METHOD)
2284 serverContext.use_privatekey(skey)
2285 serverContext.use_certificate(scert)
2286 serverContext.add_extra_chain_cert(icert)
2287 serverContext.add_extra_chain_cert(cacert)
2288 server = Connection(serverContext, None)
2289 server.set_accept_state()
2290
2291 # Create the client
2292 clientContext = Context(TLSv1_METHOD)
2293 clientContext.set_verify(VERIFY_NONE, verify_cb)
2294 client = Connection(clientContext, None)
2295 client.set_connect_state()
2296
Alex Chan1c0cb662017-01-30 07:13:30 +00002297 interact_in_memory(client, server)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002298
2299 chain = client.get_peer_cert_chain()
Alex Chan1c0cb662017-01-30 07:13:30 +00002300 assert len(chain) == 3
2301 assert "Server Certificate" == chain[0].get_subject().CN
2302 assert "Intermediate Certificate" == chain[1].get_subject().CN
2303 assert "Authority Certificate" == chain[2].get_subject().CN
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002304
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002305 def test_get_peer_cert_chain_none(self):
2306 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002307 `Connection.get_peer_cert_chain` returns `None` if the peer sends
2308 no certificate chain.
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002309 """
2310 ctx = Context(TLSv1_METHOD)
2311 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2312 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
2313 server = Connection(ctx, None)
2314 server.set_accept_state()
2315 client = Connection(Context(TLSv1_METHOD), None)
2316 client.set_connect_state()
Alex Chan1c0cb662017-01-30 07:13:30 +00002317 interact_in_memory(client, server)
2318 assert None is server.get_peer_cert_chain()
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002319
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002320 def test_get_session_unconnected(self):
2321 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002322 `Connection.get_session` returns `None` when used with an object
2323 which has not been connected.
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002324 """
2325 ctx = Context(TLSv1_METHOD)
2326 server = Connection(ctx, None)
2327 session = server.get_session()
Alex Chan1c0cb662017-01-30 07:13:30 +00002328 assert None is session
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002329
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002330 def test_server_get_session(self):
2331 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002332 On the server side of a connection, `Connection.get_session` returns a
2333 `Session` instance representing the SSL session for that connection.
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002334 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002335 server, client = loopback()
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002336 session = server.get_session()
Alex Chan1c0cb662017-01-30 07:13:30 +00002337 assert isinstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002338
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002339 def test_client_get_session(self):
2340 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002341 On the client side of a connection, `Connection.get_session`
2342 returns a `Session` instance representing the SSL session for
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002343 that connection.
2344 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002345 server, client = loopback()
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002346 session = client.get_session()
Alex Chan1c0cb662017-01-30 07:13:30 +00002347 assert isinstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002348
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002349 def test_set_session_wrong_args(self):
2350 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002351 `Connection.set_session` raises `TypeError` if called with an object
2352 that is not an instance of `Session`.
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002353 """
2354 ctx = Context(TLSv1_METHOD)
2355 connection = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002356 with pytest.raises(TypeError):
2357 connection.set_session(123)
2358 with pytest.raises(TypeError):
2359 connection.set_session("hello")
2360 with pytest.raises(TypeError):
2361 connection.set_session(object())
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002362
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002363 def test_client_set_session(self):
2364 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002365 `Connection.set_session`, when used prior to a connection being
2366 established, accepts a `Session` instance and causes an attempt to
2367 re-use the session it represents when the SSL handshake is performed.
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002368 """
2369 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2370 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
2371 ctx = Context(TLSv1_METHOD)
2372 ctx.use_privatekey(key)
2373 ctx.use_certificate(cert)
2374 ctx.set_session_id("unity-test")
2375
2376 def makeServer(socket):
2377 server = Connection(ctx, socket)
2378 server.set_accept_state()
2379 return server
2380
Alex Chan1c0cb662017-01-30 07:13:30 +00002381 originalServer, originalClient = loopback(
2382 server_factory=makeServer)
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002383 originalSession = originalClient.get_session()
2384
2385 def makeClient(socket):
Alex Chan1c0cb662017-01-30 07:13:30 +00002386 client = loopback_client_factory(socket)
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002387 client.set_session(originalSession)
2388 return client
Alex Chan1c0cb662017-01-30 07:13:30 +00002389 resumedServer, resumedClient = loopback(
2390 server_factory=makeServer,
2391 client_factory=makeClient)
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002392
2393 # This is a proxy: in general, we have no access to any unique
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002394 # identifier for the session (new enough versions of OpenSSL expose
2395 # a hash which could be usable, but "new enough" is very, very new).
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002396 # Instead, exploit the fact that the master key is re-used if the
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002397 # session is re-used. As long as the master key for the two
2398 # connections is the same, the session was re-used!
Alex Chan1c0cb662017-01-30 07:13:30 +00002399 assert originalServer.master_key() == resumedServer.master_key()
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002400
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002401 def test_set_session_wrong_method(self):
2402 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002403 If `Connection.set_session` is passed a `Session` instance associated
2404 with a context using a different SSL method than the `Connection`
2405 is using, a `OpenSSL.SSL.Error` is raised.
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002406 """
Alex Gaynor5af32d02016-09-24 01:52:21 -04002407 # Make this work on both OpenSSL 1.0.0, which doesn't support TLSv1.2
2408 # and also on OpenSSL 1.1.0 which doesn't support SSLv3. (SSL_ST_INIT
2409 # is a way to check for 1.1.0)
2410 if SSL_ST_INIT is not None:
2411 v1 = TLSv1_METHOD
2412 v2 = SSLv3_METHOD
2413 else:
2414 v1 = TLSv1_2_METHOD
2415 v2 = TLSv1_METHOD
2416
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002417 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2418 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
Alex Gaynor5af32d02016-09-24 01:52:21 -04002419 ctx = Context(v1)
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002420 ctx.use_privatekey(key)
2421 ctx.use_certificate(cert)
2422 ctx.set_session_id("unity-test")
2423
2424 def makeServer(socket):
2425 server = Connection(ctx, socket)
2426 server.set_accept_state()
2427 return server
2428
Alex Gaynor5af32d02016-09-24 01:52:21 -04002429 def makeOriginalClient(socket):
2430 client = Connection(Context(v1), socket)
2431 client.set_connect_state()
2432 return client
2433
Alex Chan1c0cb662017-01-30 07:13:30 +00002434 originalServer, originalClient = loopback(
2435 server_factory=makeServer, client_factory=makeOriginalClient)
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002436 originalSession = originalClient.get_session()
2437
2438 def makeClient(socket):
2439 # Intentionally use a different, incompatible method here.
Alex Gaynor5af32d02016-09-24 01:52:21 -04002440 client = Connection(Context(v2), socket)
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002441 client.set_connect_state()
2442 client.set_session(originalSession)
2443 return client
2444
Alex Chan1c0cb662017-01-30 07:13:30 +00002445 with pytest.raises(Error):
2446 loopback(client_factory=makeClient, server_factory=makeServer)
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002447
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002448 def test_wantWriteError(self):
2449 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002450 `Connection` methods which generate output raise
2451 `OpenSSL.SSL.WantWriteError` if writing to the connection's BIO
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002452 fail indicating a should-write state.
2453 """
2454 client_socket, server_socket = socket_pair()
2455 # Fill up the client's send buffer so Connection won't be able to write
Jean-Paul Calderonebbff8b92014-03-22 14:20:30 -04002456 # anything. Only write a single byte at a time so we can be sure we
2457 # completely fill the buffer. Even though the socket API is allowed to
2458 # signal a short write via its return value it seems this doesn't
2459 # always happen on all platforms (FreeBSD and OS X particular) for the
2460 # very last bit of available buffer space.
2461 msg = b"x"
2462 for i in range(1024 * 1024 * 4):
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002463 try:
2464 client_socket.send(msg)
2465 except error as e:
2466 if e.errno == EWOULDBLOCK:
2467 break
2468 raise
2469 else:
Alex Chan1c0cb662017-01-30 07:13:30 +00002470 pytest.fail(
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002471 "Failed to fill socket buffer, cannot test BIO want write")
2472
2473 ctx = Context(TLSv1_METHOD)
2474 conn = Connection(ctx, client_socket)
2475 # Client's speak first, so make it an SSL client
2476 conn.set_connect_state()
Alex Chan1c0cb662017-01-30 07:13:30 +00002477 with pytest.raises(WantWriteError):
2478 conn.do_handshake()
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002479
2480 # XXX want_read
2481
Fedor Brunner416f4a12014-03-28 13:18:38 +01002482 def test_get_finished_before_connect(self):
Fedor Brunner5747b932014-03-05 14:22:34 +01002483 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002484 `Connection.get_finished` returns `None` before TLS handshake
2485 is completed.
Fedor Brunner5747b932014-03-05 14:22:34 +01002486 """
Fedor Brunner5747b932014-03-05 14:22:34 +01002487 ctx = Context(TLSv1_METHOD)
2488 connection = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002489 assert connection.get_finished() is None
Fedor Brunner416f4a12014-03-28 13:18:38 +01002490
2491 def test_get_peer_finished_before_connect(self):
2492 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002493 `Connection.get_peer_finished` returns `None` before TLS handshake
2494 is completed.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002495 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002496 ctx = Context(TLSv1_METHOD)
2497 connection = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002498 assert connection.get_peer_finished() is None
Fedor Brunner5747b932014-03-05 14:22:34 +01002499
Fedor Brunner416f4a12014-03-28 13:18:38 +01002500 def test_get_finished(self):
2501 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002502 `Connection.get_finished` method returns the TLS Finished message send
2503 from client, or server. Finished messages are send during
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002504 TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002505 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002506 server, client = loopback()
Fedor Brunner416f4a12014-03-28 13:18:38 +01002507
Alex Chan1c0cb662017-01-30 07:13:30 +00002508 assert server.get_finished() is not None
2509 assert len(server.get_finished()) > 0
Fedor Brunner416f4a12014-03-28 13:18:38 +01002510
2511 def test_get_peer_finished(self):
2512 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002513 `Connection.get_peer_finished` method returns the TLS Finished
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002514 message received from client, or server. Finished messages are send
2515 during TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002516 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002517 server, client = loopback()
Fedor Brunner416f4a12014-03-28 13:18:38 +01002518
Alex Chan1c0cb662017-01-30 07:13:30 +00002519 assert server.get_peer_finished() is not None
2520 assert len(server.get_peer_finished()) > 0
Fedor Brunner5747b932014-03-05 14:22:34 +01002521
Fedor Brunner416f4a12014-03-28 13:18:38 +01002522 def test_tls_finished_message_symmetry(self):
2523 """
Hynek Schlawackdddd1112015-09-05 21:12:30 +02002524 The TLS Finished message send by server must be the TLS Finished
2525 message received by client.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002526
Hynek Schlawackdddd1112015-09-05 21:12:30 +02002527 The TLS Finished message send by client must be the TLS Finished
2528 message received by server.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002529 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002530 server, client = loopback()
Fedor Brunner416f4a12014-03-28 13:18:38 +01002531
Alex Chan1c0cb662017-01-30 07:13:30 +00002532 assert server.get_finished() == client.get_peer_finished()
2533 assert client.get_finished() == server.get_peer_finished()
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002534
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002535 def test_get_cipher_name_before_connect(self):
2536 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002537 `Connection.get_cipher_name` returns `None` if no connection
2538 has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002539 """
2540 ctx = Context(TLSv1_METHOD)
2541 conn = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002542 assert conn.get_cipher_name() is None
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002543
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002544 def test_get_cipher_name(self):
2545 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002546 `Connection.get_cipher_name` returns a `unicode` string giving the
2547 name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002548 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002549 server, client = loopback()
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002550 server_cipher_name, client_cipher_name = \
2551 server.get_cipher_name(), client.get_cipher_name()
2552
Alex Chan1c0cb662017-01-30 07:13:30 +00002553 assert isinstance(server_cipher_name, text_type)
2554 assert isinstance(client_cipher_name, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002555
Alex Chan1c0cb662017-01-30 07:13:30 +00002556 assert server_cipher_name == client_cipher_name
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002557
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002558 def test_get_cipher_version_before_connect(self):
2559 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002560 `Connection.get_cipher_version` returns `None` if no connection
2561 has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002562 """
2563 ctx = Context(TLSv1_METHOD)
2564 conn = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002565 assert conn.get_cipher_version() is None
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002566
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002567 def test_get_cipher_version(self):
2568 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002569 `Connection.get_cipher_version` returns a `unicode` string giving
2570 the protocol name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002571 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002572 server, client = loopback()
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002573 server_cipher_version, client_cipher_version = \
2574 server.get_cipher_version(), client.get_cipher_version()
2575
Alex Chan1c0cb662017-01-30 07:13:30 +00002576 assert isinstance(server_cipher_version, text_type)
2577 assert isinstance(client_cipher_version, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002578
Alex Chan1c0cb662017-01-30 07:13:30 +00002579 assert server_cipher_version == client_cipher_version
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002580
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002581 def test_get_cipher_bits_before_connect(self):
2582 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002583 `Connection.get_cipher_bits` returns `None` if no connection has
2584 been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002585 """
2586 ctx = Context(TLSv1_METHOD)
2587 conn = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002588 assert conn.get_cipher_bits() is None
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002589
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002590 def test_get_cipher_bits(self):
2591 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002592 `Connection.get_cipher_bits` returns the number of secret bits
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002593 of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002594 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002595 server, client = loopback()
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002596 server_cipher_bits, client_cipher_bits = \
2597 server.get_cipher_bits(), client.get_cipher_bits()
2598
Alex Chan1c0cb662017-01-30 07:13:30 +00002599 assert isinstance(server_cipher_bits, int)
2600 assert isinstance(client_cipher_bits, int)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002601
Alex Chan1c0cb662017-01-30 07:13:30 +00002602 assert server_cipher_bits == client_cipher_bits
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002603
Jim Shaverabff1882015-05-27 09:15:55 -04002604 def test_get_protocol_version_name(self):
2605 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002606 `Connection.get_protocol_version_name()` returns a string giving the
2607 protocol version of the current connection.
Jim Shaverabff1882015-05-27 09:15:55 -04002608 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002609 server, client = loopback()
Jim Shaverabff1882015-05-27 09:15:55 -04002610 client_protocol_version_name = client.get_protocol_version_name()
2611 server_protocol_version_name = server.get_protocol_version_name()
2612
Alex Chan1c0cb662017-01-30 07:13:30 +00002613 assert isinstance(server_protocol_version_name, text_type)
2614 assert isinstance(client_protocol_version_name, text_type)
Jim Shaverabff1882015-05-27 09:15:55 -04002615
Alex Chan1c0cb662017-01-30 07:13:30 +00002616 assert server_protocol_version_name == client_protocol_version_name
Jim Shaverabff1882015-05-27 09:15:55 -04002617
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002618 def test_get_protocol_version(self):
2619 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002620 `Connection.get_protocol_version()` returns an integer
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002621 giving the protocol version of the current connection.
2622 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002623 server, client = loopback()
Jim Shaver85a4dff2015-04-27 17:42:46 -04002624 client_protocol_version = client.get_protocol_version()
2625 server_protocol_version = server.get_protocol_version()
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002626
Alex Chan1c0cb662017-01-30 07:13:30 +00002627 assert isinstance(server_protocol_version, int)
2628 assert isinstance(client_protocol_version, int)
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002629
Alex Chan1c0cb662017-01-30 07:13:30 +00002630 assert server_protocol_version == client_protocol_version
2631
2632 def test_wantReadError(self):
2633 """
2634 `Connection.bio_read` raises `OpenSSL.SSL.WantReadError` if there are
2635 no bytes available to be read from the BIO.
2636 """
2637 ctx = Context(TLSv1_METHOD)
2638 conn = Connection(ctx, None)
2639 with pytest.raises(WantReadError):
2640 conn.bio_read(1024)
2641
2642 def test_buffer_size(self):
2643 """
2644 `Connection.bio_read` accepts an integer giving the maximum number
2645 of bytes to read and return.
2646 """
2647 ctx = Context(TLSv1_METHOD)
2648 conn = Connection(ctx, None)
2649 conn.set_connect_state()
2650 try:
2651 conn.do_handshake()
2652 except WantReadError:
2653 pass
2654 data = conn.bio_read(2)
2655 assert 2 == len(data)
2656
2657 @skip_if_py3
2658 def test_buffer_size_long(self):
2659 """
2660 On Python 2 `Connection.bio_read` accepts values of type `long` as
2661 well as `int`.
2662 """
2663 ctx = Context(TLSv1_METHOD)
2664 conn = Connection(ctx, None)
2665 conn.set_connect_state()
2666 try:
2667 conn.do_handshake()
2668 except WantReadError:
2669 pass
2670 data = conn.bio_read(long(2))
2671 assert 2 == len(data)
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002672
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002673
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002674class ConnectionGetCipherListTests(TestCase):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002675 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002676 Tests for :py:obj:`Connection.get_cipher_list`.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002677 """
Jean-Paul Calderone54a2bc02010-09-09 17:52:38 -04002678 def test_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002679 """
Hynek Schlawackdddd1112015-09-05 21:12:30 +02002680 :py:obj:`Connection.get_cipher_list` raises :py:obj:`TypeError` if
2681 called with any arguments.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002682 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002683 connection = Connection(Context(TLSv1_METHOD), None)
2684 self.assertRaises(TypeError, connection.get_cipher_list, None)
2685
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002686 def test_result(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002687 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002688 :py:obj:`Connection.get_cipher_list` returns a :py:obj:`list` of
2689 :py:obj:`bytes` giving the names of the ciphers which might be used.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002690 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002691 connection = Connection(Context(TLSv1_METHOD), None)
2692 ciphers = connection.get_cipher_list()
2693 self.assertTrue(isinstance(ciphers, list))
2694 for cipher in ciphers:
2695 self.assertTrue(isinstance(cipher, str))
2696
2697
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002698class ConnectionSendTests(TestCase, _LoopbackMixin):
2699 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002700 Tests for :py:obj:`Connection.send`
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002701 """
2702 def test_wrong_args(self):
2703 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002704 When called with arguments other than string argument for its first
2705 parameter or more than two arguments, :py:obj:`Connection.send` raises
2706 :py:obj:`TypeError`.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002707 """
2708 connection = Connection(Context(TLSv1_METHOD), None)
Jean-Paul Calderone77fa2602011-01-05 18:23:39 -05002709 self.assertRaises(TypeError, connection.send)
2710 self.assertRaises(TypeError, connection.send, object())
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002711 self.assertRaises(TypeError, connection.send, "foo", object(), "bar")
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002712
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002713 def test_short_bytes(self):
2714 """
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002715 When passed a short byte string, :py:obj:`Connection.send` transmits
2716 all of it and returns the number of bytes sent.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002717 """
2718 server, client = self._loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002719 count = server.send(b'xy')
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002720 self.assertEquals(count, 2)
Alex Gaynore7f51982016-09-11 11:48:14 -04002721 self.assertEquals(client.recv(2), b'xy')
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002722
Abraham Martinef063482015-03-25 14:06:24 +00002723 def test_text(self):
2724 """
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002725 When passed a text, :py:obj:`Connection.send` transmits all of it and
2726 returns the number of bytes sent. It also raises a DeprecationWarning.
Abraham Martinef063482015-03-25 14:06:24 +00002727 """
2728 server, client = self._loopback()
2729 with catch_warnings(record=True) as w:
2730 simplefilter("always")
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002731 count = server.send(b"xy".decode("ascii"))
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002732 self.assertEqual(
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002733 "{0} for buf is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002734 WARNING_TYPE_EXPECTED
2735 ),
2736 str(w[-1].message)
2737 )
2738 self.assertIs(w[-1].category, DeprecationWarning)
Abraham Martinef063482015-03-25 14:06:24 +00002739 self.assertEquals(count, 2)
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002740 self.assertEquals(client.recv(2), b"xy")
Abraham Martinef063482015-03-25 14:06:24 +00002741
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002742 @skip_if_py26
2743 def test_short_memoryview(self):
2744 """
2745 When passed a memoryview onto a small number of bytes,
2746 :py:obj:`Connection.send` transmits all of them and returns the number
2747 of bytes sent.
2748 """
2749 server, client = self._loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002750 count = server.send(memoryview(b'xy'))
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002751 self.assertEquals(count, 2)
Alex Gaynore7f51982016-09-11 11:48:14 -04002752 self.assertEquals(client.recv(2), b'xy')
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002753
Hynek Schlawack8e94f1b2015-09-05 21:31:00 +02002754 @skip_if_py3
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002755 def test_short_buffer(self):
2756 """
2757 When passed a buffer containing a small number of bytes,
2758 :py:obj:`Connection.send` transmits all of them and returns the number
2759 of bytes sent.
2760 """
2761 server, client = self._loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002762 count = server.send(buffer(b'xy'))
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002763 self.assertEquals(count, 2)
Alex Gaynore7f51982016-09-11 11:48:14 -04002764 self.assertEquals(client.recv(2), b'xy')
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02002765
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05002766
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002767def _make_memoryview(size):
2768 """
2769 Create a new ``memoryview`` wrapped around a ``bytearray`` of the given
2770 size.
2771 """
2772 return memoryview(bytearray(size))
2773
2774
Cory Benfield62d10332014-06-15 10:03:41 +01002775class ConnectionRecvIntoTests(TestCase, _LoopbackMixin):
2776 """
2777 Tests for :py:obj:`Connection.recv_into`
2778 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002779 def _no_length_test(self, factory):
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04002780 """
2781 Assert that when the given buffer is passed to
2782 ``Connection.recv_into``, whatever bytes are available to be received
2783 that fit into that buffer are written into that buffer.
2784 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002785 output_buffer = factory(5)
2786
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04002787 server, client = self._loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002788 server.send(b'xy')
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04002789
Jean-Paul Calderone320af1e2015-03-15 17:20:13 -04002790 self.assertEqual(client.recv_into(output_buffer), 2)
Alex Gaynore7f51982016-09-11 11:48:14 -04002791 self.assertEqual(output_buffer, bytearray(b'xy\x00\x00\x00'))
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04002792
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002793 def test_bytearray_no_length(self):
Cory Benfield62d10332014-06-15 10:03:41 +01002794 """
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04002795 :py:obj:`Connection.recv_into` can be passed a ``bytearray`` instance
2796 and data in the receive buffer is written to it.
Cory Benfield62d10332014-06-15 10:03:41 +01002797 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002798 self._no_length_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01002799
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002800 def _respects_length_test(self, factory):
Cory Benfield62d10332014-06-15 10:03:41 +01002801 """
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002802 Assert that when the given buffer is passed to ``Connection.recv_into``
2803 along with a value for ``nbytes`` that is less than the size of that
2804 buffer, only ``nbytes`` bytes are written into the buffer.
Cory Benfield62d10332014-06-15 10:03:41 +01002805 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002806 output_buffer = factory(10)
2807
Cory Benfield62d10332014-06-15 10:03:41 +01002808 server, client = self._loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002809 server.send(b'abcdefghij')
Cory Benfield62d10332014-06-15 10:03:41 +01002810
Jean-Paul Calderone320af1e2015-03-15 17:20:13 -04002811 self.assertEqual(client.recv_into(output_buffer, 5), 5)
2812 self.assertEqual(
Alex Gaynore7f51982016-09-11 11:48:14 -04002813 output_buffer, bytearray(b'abcde\x00\x00\x00\x00\x00')
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002814 )
2815
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002816 def test_bytearray_respects_length(self):
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002817 """
2818 When called with a ``bytearray`` instance,
2819 :py:obj:`Connection.recv_into` respects the ``nbytes`` parameter and
2820 doesn't copy in more than that number of bytes.
2821 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002822 self._respects_length_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01002823
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002824 def _doesnt_overfill_test(self, factory):
Cory Benfield62d10332014-06-15 10:03:41 +01002825 """
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002826 Assert that if there are more bytes available to be read from the
2827 receive buffer than would fit into the buffer passed to
2828 :py:obj:`Connection.recv_into`, only as many as fit are written into
2829 it.
Cory Benfield62d10332014-06-15 10:03:41 +01002830 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002831 output_buffer = factory(5)
2832
Cory Benfield62d10332014-06-15 10:03:41 +01002833 server, client = self._loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002834 server.send(b'abcdefghij')
Cory Benfield62d10332014-06-15 10:03:41 +01002835
Jean-Paul Calderone320af1e2015-03-15 17:20:13 -04002836 self.assertEqual(client.recv_into(output_buffer), 5)
Alex Gaynore7f51982016-09-11 11:48:14 -04002837 self.assertEqual(output_buffer, bytearray(b'abcde'))
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002838 rest = client.recv(5)
Alex Gaynore7f51982016-09-11 11:48:14 -04002839 self.assertEqual(b'fghij', rest)
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002840
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002841 def test_bytearray_doesnt_overfill(self):
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002842 """
2843 When called with a ``bytearray`` instance,
2844 :py:obj:`Connection.recv_into` respects the size of the array and
2845 doesn't write more bytes into it than will fit.
2846 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002847 self._doesnt_overfill_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01002848
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002849 def test_bytearray_really_doesnt_overfill(self):
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04002850 """
2851 When called with a ``bytearray`` instance and an ``nbytes`` value that
2852 is too large, :py:obj:`Connection.recv_into` respects the size of the
2853 array and not the ``nbytes`` value and doesn't write more bytes into
2854 the buffer than will fit.
2855 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002856 self._doesnt_overfill_test(bytearray)
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04002857
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002858 def test_peek(self):
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002859 server, client = self._loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002860 server.send(b'xy')
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002861
2862 for _ in range(2):
2863 output_buffer = bytearray(5)
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002864 self.assertEqual(
2865 client.recv_into(output_buffer, flags=MSG_PEEK), 2)
Alex Gaynore7f51982016-09-11 11:48:14 -04002866 self.assertEqual(output_buffer, bytearray(b'xy\x00\x00\x00'))
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002867
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002868 @skip_if_py26
2869 def test_memoryview_no_length(self):
2870 """
2871 :py:obj:`Connection.recv_into` can be passed a ``memoryview``
2872 instance and data in the receive buffer is written to it.
2873 """
2874 self._no_length_test(_make_memoryview)
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002875
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002876 @skip_if_py26
2877 def test_memoryview_respects_length(self):
2878 """
2879 When called with a ``memoryview`` instance,
2880 :py:obj:`Connection.recv_into` respects the ``nbytes`` parameter
2881 and doesn't copy more than that number of bytes in.
2882 """
2883 self._respects_length_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01002884
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002885 @skip_if_py26
2886 def test_memoryview_doesnt_overfill(self):
2887 """
2888 When called with a ``memoryview`` instance,
2889 :py:obj:`Connection.recv_into` respects the size of the array and
2890 doesn't write more bytes into it than will fit.
2891 """
2892 self._doesnt_overfill_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01002893
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002894 @skip_if_py26
2895 def test_memoryview_really_doesnt_overfill(self):
2896 """
2897 When called with a ``memoryview`` instance and an ``nbytes`` value
2898 that is too large, :py:obj:`Connection.recv_into` respects the size
2899 of the array and not the ``nbytes`` value and doesn't write more
2900 bytes into the buffer than will fit.
2901 """
2902 self._doesnt_overfill_test(_make_memoryview)
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04002903
Cory Benfield62d10332014-06-15 10:03:41 +01002904
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002905class ConnectionSendallTests(TestCase, _LoopbackMixin):
2906 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002907 Tests for :py:obj:`Connection.sendall`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002908 """
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002909 def test_wrong_args(self):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002910 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002911 When called with arguments other than a string argument for its first
2912 parameter or with more than two arguments, :py:obj:`Connection.sendall`
2913 raises :py:obj:`TypeError`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002914 """
2915 connection = Connection(Context(TLSv1_METHOD), None)
2916 self.assertRaises(TypeError, connection.sendall)
2917 self.assertRaises(TypeError, connection.sendall, object())
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002918 self.assertRaises(
2919 TypeError, connection.sendall, "foo", object(), "bar")
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04002920
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002921 def test_short(self):
2922 """
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02002923 :py:obj:`Connection.sendall` transmits all of the bytes in the string
2924 passed to it.
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002925 """
2926 server, client = self._loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002927 server.sendall(b'x')
2928 self.assertEquals(client.recv(1), b'x')
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002929
Abraham Martinef063482015-03-25 14:06:24 +00002930 def test_text(self):
2931 """
Jean-Paul Calderone93477422015-04-13 20:38:57 -04002932 :py:obj:`Connection.sendall` transmits all the content in the string
2933 passed to it raising a DeprecationWarning in case of this being a text.
Abraham Martinef063482015-03-25 14:06:24 +00002934 """
2935 server, client = self._loopback()
2936 with catch_warnings(record=True) as w:
2937 simplefilter("always")
Jean-Paul Calderone8dc37a12015-03-29 08:16:52 -04002938 server.sendall(b"x".decode("ascii"))
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002939 self.assertEqual(
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002940 "{0} for buf is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002941 WARNING_TYPE_EXPECTED
2942 ),
2943 str(w[-1].message)
2944 )
2945 self.assertIs(w[-1].category, DeprecationWarning)
2946 self.assertEquals(client.recv(1), b"x")
Abraham Martinef063482015-03-25 14:06:24 +00002947
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02002948 @skip_if_py26
2949 def test_short_memoryview(self):
2950 """
2951 When passed a memoryview onto a small number of bytes,
2952 :py:obj:`Connection.sendall` transmits all of them.
2953 """
2954 server, client = self._loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002955 server.sendall(memoryview(b'x'))
2956 self.assertEquals(client.recv(1), b'x')
Abraham Martinef063482015-03-25 14:06:24 +00002957
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02002958 @skip_if_py3
2959 def test_short_buffers(self):
2960 """
2961 When passed a buffer containing a small number of bytes,
2962 :py:obj:`Connection.sendall` transmits all of them.
2963 """
2964 server, client = self._loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002965 server.sendall(buffer(b'x'))
2966 self.assertEquals(client.recv(1), b'x')
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02002967
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002968 def test_long(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002969 """
Hynek Schlawack35618382015-09-05 21:54:25 +02002970 :py:obj:`Connection.sendall` transmits all of the bytes in the string
2971 passed to it even if this requires multiple calls of an underlying
2972 write function.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002973 """
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002974 server, client = self._loopback()
Jean-Paul Calderone6241c702010-09-16 19:59:24 -04002975 # Should be enough, underlying SSL_write should only do 16k at a time.
Hynek Schlawack35618382015-09-05 21:54:25 +02002976 # On Windows, after 32k of bytes the write will block (forever
2977 # - because no one is yet reading).
Alex Gaynore7f51982016-09-11 11:48:14 -04002978 message = b'x' * (1024 * 32 - 1) + b'y'
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002979 server.sendall(message)
2980 accum = []
2981 received = 0
2982 while received < len(message):
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04002983 data = client.recv(1024)
2984 accum.append(data)
2985 received += len(data)
Alex Gaynore7f51982016-09-11 11:48:14 -04002986 self.assertEquals(message, b''.join(accum))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04002987
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04002988 def test_closed(self):
2989 """
Hynek Schlawack35618382015-09-05 21:54:25 +02002990 If the underlying socket is closed, :py:obj:`Connection.sendall`
2991 propagates the write error from the low level write call.
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04002992 """
2993 server, client = self._loopback()
Jean-Paul Calderone05d43e82010-09-24 18:01:36 -04002994 server.sock_shutdown(2)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002995 exc = self.assertRaises(SysCallError, server.sendall, b"hello, world")
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +02002996 if platform == "win32":
2997 self.assertEqual(exc.args[0], ESHUTDOWN)
2998 else:
2999 self.assertEqual(exc.args[0], EPIPE)
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003000
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003001
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003002class ConnectionRenegotiateTests(TestCase, _LoopbackMixin):
3003 """
3004 Tests for SSL renegotiation APIs.
3005 """
3006 def test_renegotiate_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003007 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003008 :py:obj:`Connection.renegotiate` raises :py:obj:`TypeError` if called
3009 with any arguments.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003010 """
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003011 connection = Connection(Context(TLSv1_METHOD), None)
3012 self.assertRaises(TypeError, connection.renegotiate, None)
3013
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003014 def test_total_renegotiations_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003015 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003016 :py:obj:`Connection.total_renegotiations` raises :py:obj:`TypeError` if
3017 called with any arguments.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003018 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003019 connection = Connection(Context(TLSv1_METHOD), None)
3020 self.assertRaises(TypeError, connection.total_renegotiations, None)
3021
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003022 def test_total_renegotiations(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003023 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003024 :py:obj:`Connection.total_renegotiations` returns :py:obj:`0` before
3025 any renegotiations have happened.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003026 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003027 connection = Connection(Context(TLSv1_METHOD), None)
3028 self.assertEquals(connection.total_renegotiations(), 0)
3029
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003030 def test_renegotiate(self):
3031 """
3032 Go through a complete renegotiation cycle.
3033 """
3034 server, client = self._loopback()
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003035
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003036 server.send(b"hello world")
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003037
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003038 assert b"hello world" == client.recv(len(b"hello world"))
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003039
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003040 assert 0 == server.total_renegotiations()
3041 assert False is server.renegotiate_pending()
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003042
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003043 assert True is server.renegotiate()
3044
3045 assert True is server.renegotiate_pending()
3046
3047 server.setblocking(False)
3048 client.setblocking(False)
3049
3050 client.do_handshake()
3051 server.do_handshake()
3052
3053 assert 1 == server.total_renegotiations()
3054 while False is server.renegotiate_pending():
3055 pass
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003056
3057
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003058class ErrorTests(TestCase):
3059 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003060 Unit tests for :py:obj:`OpenSSL.SSL.Error`.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003061 """
3062 def test_type(self):
3063 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003064 :py:obj:`Error` is an exception type.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003065 """
3066 self.assertTrue(issubclass(Error, Exception))
Rick Deane15b1472009-07-09 15:53:42 -05003067 self.assertEqual(Error.__name__, 'Error')
Rick Deane15b1472009-07-09 15:53:42 -05003068
3069
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003070class ConstantsTests(TestCase):
3071 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003072 Tests for the values of constants exposed in :py:obj:`OpenSSL.SSL`.
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003073
3074 These are values defined by OpenSSL intended only to be used as flags to
3075 OpenSSL APIs. The only assertions it seems can be made about them is
3076 their values.
3077 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003078 @pytest.mark.skipif(
3079 OP_NO_QUERY_MTU is None,
3080 reason="OP_NO_QUERY_MTU unavailable - OpenSSL version may be too old"
3081 )
3082 def test_op_no_query_mtu(self):
3083 """
3084 The value of :py:obj:`OpenSSL.SSL.OP_NO_QUERY_MTU` is 0x1000, the value
3085 of :py:const:`SSL_OP_NO_QUERY_MTU` defined by :file:`openssl/ssl.h`.
3086 """
3087 self.assertEqual(OP_NO_QUERY_MTU, 0x1000)
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003088
Hynek Schlawack35618382015-09-05 21:54:25 +02003089 @pytest.mark.skipif(
3090 OP_COOKIE_EXCHANGE is None,
3091 reason="OP_COOKIE_EXCHANGE unavailable - "
3092 "OpenSSL version may be too old"
3093 )
3094 def test_op_cookie_exchange(self):
3095 """
3096 The value of :py:obj:`OpenSSL.SSL.OP_COOKIE_EXCHANGE` is 0x2000, the
3097 value of :py:const:`SSL_OP_COOKIE_EXCHANGE` defined by
3098 :file:`openssl/ssl.h`.
3099 """
3100 self.assertEqual(OP_COOKIE_EXCHANGE, 0x2000)
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003101
Hynek Schlawack35618382015-09-05 21:54:25 +02003102 @pytest.mark.skipif(
3103 OP_NO_TICKET is None,
3104 reason="OP_NO_TICKET unavailable - OpenSSL version may be too old"
3105 )
3106 def test_op_no_ticket(self):
3107 """
3108 The value of :py:obj:`OpenSSL.SSL.OP_NO_TICKET` is 0x4000, the value of
3109 :py:const:`SSL_OP_NO_TICKET` defined by :file:`openssl/ssl.h`.
3110 """
3111 self.assertEqual(OP_NO_TICKET, 0x4000)
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003112
Hynek Schlawack35618382015-09-05 21:54:25 +02003113 @pytest.mark.skipif(
3114 OP_NO_COMPRESSION is None,
3115 reason="OP_NO_COMPRESSION unavailable - OpenSSL version may be too old"
3116 )
3117 def test_op_no_compression(self):
3118 """
3119 The value of :py:obj:`OpenSSL.SSL.OP_NO_COMPRESSION` is 0x20000, the
3120 value of :py:const:`SSL_OP_NO_COMPRESSION` defined by
3121 :file:`openssl/ssl.h`.
3122 """
3123 self.assertEqual(OP_NO_COMPRESSION, 0x20000)
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04003124
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003125 def test_sess_cache_off(self):
3126 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003127 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_OFF` 0x0, the value of
3128 :py:obj:`SSL_SESS_CACHE_OFF` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003129 """
3130 self.assertEqual(0x0, SESS_CACHE_OFF)
3131
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003132 def test_sess_cache_client(self):
3133 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003134 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_CLIENT` 0x1, the value of
3135 :py:obj:`SSL_SESS_CACHE_CLIENT` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003136 """
3137 self.assertEqual(0x1, SESS_CACHE_CLIENT)
3138
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003139 def test_sess_cache_server(self):
3140 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003141 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_SERVER` 0x2, the value of
3142 :py:obj:`SSL_SESS_CACHE_SERVER` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003143 """
3144 self.assertEqual(0x2, SESS_CACHE_SERVER)
3145
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003146 def test_sess_cache_both(self):
3147 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003148 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_BOTH` 0x3, the value of
3149 :py:obj:`SSL_SESS_CACHE_BOTH` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003150 """
3151 self.assertEqual(0x3, SESS_CACHE_BOTH)
3152
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003153 def test_sess_cache_no_auto_clear(self):
3154 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003155 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_AUTO_CLEAR` 0x80, the
3156 value of :py:obj:`SSL_SESS_CACHE_NO_AUTO_CLEAR` defined by
3157 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003158 """
3159 self.assertEqual(0x80, SESS_CACHE_NO_AUTO_CLEAR)
3160
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003161 def test_sess_cache_no_internal_lookup(self):
3162 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003163 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_LOOKUP` 0x100,
3164 the value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL_LOOKUP` defined by
3165 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003166 """
3167 self.assertEqual(0x100, SESS_CACHE_NO_INTERNAL_LOOKUP)
3168
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003169 def test_sess_cache_no_internal_store(self):
3170 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003171 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_STORE` 0x200,
3172 the value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL_STORE` defined by
3173 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003174 """
3175 self.assertEqual(0x200, SESS_CACHE_NO_INTERNAL_STORE)
3176
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003177 def test_sess_cache_no_internal(self):
3178 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003179 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL` 0x300, the
3180 value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL` defined by
3181 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003182 """
3183 self.assertEqual(0x300, SESS_CACHE_NO_INTERNAL)
3184
3185
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003186class MemoryBIOTests(TestCase, _LoopbackMixin):
Rick Deanb71c0d22009-04-01 14:09:23 -05003187 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003188 Tests for :py:obj:`OpenSSL.SSL.Connection` using a memory BIO.
Rick Deanb71c0d22009-04-01 14:09:23 -05003189 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003190 def _server(self, sock):
3191 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003192 Create a new server-side SSL :py:obj:`Connection` object wrapped around
3193 :py:obj:`sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003194 """
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003195 # Create the server side Connection. This is mostly setup boilerplate
3196 # - use TLSv1, use a particular certificate, etc.
3197 server_ctx = Context(TLSv1_METHOD)
Alex Gaynor43307782015-09-04 09:05:45 -04003198 server_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE)
Hynek Schlawack35618382015-09-05 21:54:25 +02003199 server_ctx.set_verify(
3200 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT | VERIFY_CLIENT_ONCE,
3201 verify_cb
3202 )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003203 server_store = server_ctx.get_cert_store()
Hynek Schlawack35618382015-09-05 21:54:25 +02003204 server_ctx.use_privatekey(
3205 load_privatekey(FILETYPE_PEM, server_key_pem))
3206 server_ctx.use_certificate(
3207 load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003208 server_ctx.check_privatekey()
3209 server_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Hynek Schlawack35618382015-09-05 21:54:25 +02003210 # Here the Connection is actually created. If None is passed as the
3211 # 2nd parameter, it indicates a memory BIO should be created.
Rick Deanb1ccd562009-07-09 23:52:39 -05003212 server_conn = Connection(server_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003213 server_conn.set_accept_state()
3214 return server_conn
3215
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003216 def _client(self, sock):
3217 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003218 Create a new client-side SSL :py:obj:`Connection` object wrapped around
3219 :py:obj:`sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003220 """
3221 # Now create the client side Connection. Similar boilerplate to the
3222 # above.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003223 client_ctx = Context(TLSv1_METHOD)
Alex Gaynor43307782015-09-04 09:05:45 -04003224 client_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE)
Hynek Schlawack35618382015-09-05 21:54:25 +02003225 client_ctx.set_verify(
3226 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT | VERIFY_CLIENT_ONCE,
3227 verify_cb
3228 )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003229 client_store = client_ctx.get_cert_store()
Hynek Schlawack35618382015-09-05 21:54:25 +02003230 client_ctx.use_privatekey(
3231 load_privatekey(FILETYPE_PEM, client_key_pem))
3232 client_ctx.use_certificate(
3233 load_certificate(FILETYPE_PEM, client_cert_pem))
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003234 client_ctx.check_privatekey()
3235 client_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05003236 client_conn = Connection(client_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003237 client_conn.set_connect_state()
3238 return client_conn
3239
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003240 def test_memoryConnect(self):
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003241 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003242 Two :py:obj:`Connection`s which use memory BIOs can be manually
3243 connected by reading from the output of each and writing those bytes to
3244 the input of the other and in this way establish a connection and
3245 exchange application-level bytes with each other.
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003246 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003247 server_conn = self._server(None)
3248 client_conn = self._client(None)
Rick Deanb71c0d22009-04-01 14:09:23 -05003249
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003250 # There should be no key or nonces yet.
3251 self.assertIdentical(server_conn.master_key(), None)
3252 self.assertIdentical(server_conn.client_random(), None)
3253 self.assertIdentical(server_conn.server_random(), None)
Rick Deanb71c0d22009-04-01 14:09:23 -05003254
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003255 # First, the handshake needs to happen. We'll deliver bytes back and
3256 # forth between the client and server until neither of them feels like
3257 # speaking any more.
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003258 self.assertIdentical(
3259 self._interactInMemory(client_conn, server_conn), None)
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003260
3261 # Now that the handshake is done, there should be a key and nonces.
3262 self.assertNotIdentical(server_conn.master_key(), None)
3263 self.assertNotIdentical(server_conn.client_random(), None)
3264 self.assertNotIdentical(server_conn.server_random(), None)
Hynek Schlawack35618382015-09-05 21:54:25 +02003265 self.assertEquals(
3266 server_conn.client_random(), client_conn.client_random())
3267 self.assertEquals(
3268 server_conn.server_random(), client_conn.server_random())
3269 self.assertNotEquals(
3270 server_conn.client_random(), server_conn.server_random())
3271 self.assertNotEquals(
3272 client_conn.client_random(), client_conn.server_random())
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003273
3274 # Here are the bytes we'll try to send.
Alex Gaynore7f51982016-09-11 11:48:14 -04003275 important_message = b'One if by land, two if by sea.'
Rick Deanb71c0d22009-04-01 14:09:23 -05003276
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003277 server_conn.write(important_message)
3278 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003279 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003280 (client_conn, important_message))
3281
3282 client_conn.write(important_message[::-1])
3283 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003284 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003285 (server_conn, important_message[::-1]))
Rick Deanb71c0d22009-04-01 14:09:23 -05003286
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003287 def test_socketConnect(self):
Rick Deanb1ccd562009-07-09 23:52:39 -05003288 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003289 Just like :py:obj:`test_memoryConnect` but with an actual socket.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003290
Hynek Schlawack35618382015-09-05 21:54:25 +02003291 This is primarily to rule out the memory BIO code as the source of any
3292 problems encountered while passing data over a :py:obj:`Connection` (if
3293 this test fails, there must be a problem outside the memory BIO code,
3294 as no memory BIO is involved here). Even though this isn't a memory
3295 BIO test, it's convenient to have it here.
Rick Deanb1ccd562009-07-09 23:52:39 -05003296 """
Jean-Paul Calderone06c7cc92010-09-24 23:52:00 -04003297 server_conn, client_conn = self._loopback()
Rick Deanb1ccd562009-07-09 23:52:39 -05003298
Alex Gaynore7f51982016-09-11 11:48:14 -04003299 important_message = b"Help me Obi Wan Kenobi, you're my only hope."
Rick Deanb1ccd562009-07-09 23:52:39 -05003300 client_conn.send(important_message)
3301 msg = server_conn.recv(1024)
3302 self.assertEqual(msg, important_message)
3303
3304 # Again in the other direction, just for fun.
3305 important_message = important_message[::-1]
3306 server_conn.send(important_message)
3307 msg = client_conn.recv(1024)
3308 self.assertEqual(msg, important_message)
3309
Jean-Paul Calderonefc4ed0f2009-04-27 11:51:27 -04003310 def test_socketOverridesMemory(self):
Rick Deanb71c0d22009-04-01 14:09:23 -05003311 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003312 Test that :py:obj:`OpenSSL.SSL.bio_read` and
3313 :py:obj:`OpenSSL.SSL.bio_write` don't work on
3314 :py:obj:`OpenSSL.SSL.Connection`() that use sockets.
Rick Deanb71c0d22009-04-01 14:09:23 -05003315 """
Alex Gaynor51d424c2016-09-10 14:50:11 -04003316 context = Context(TLSv1_METHOD)
Rick Deanb71c0d22009-04-01 14:09:23 -05003317 client = socket()
3318 clientSSL = Connection(context, client)
Alex Gaynor43307782015-09-04 09:05:45 -04003319 self.assertRaises(TypeError, clientSSL.bio_read, 100)
3320 self.assertRaises(TypeError, clientSSL.bio_write, "foo")
Alex Gaynor7e8b61e2015-09-04 13:13:05 -04003321 self.assertRaises(TypeError, clientSSL.bio_shutdown)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003322
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003323 def test_outgoingOverflow(self):
3324 """
3325 If more bytes than can be written to the memory BIO are passed to
Hynek Schlawack35618382015-09-05 21:54:25 +02003326 :py:obj:`Connection.send` at once, the number of bytes which were
3327 written is returned and that many bytes from the beginning of the input
3328 can be read from the other end of the connection.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003329 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003330 server = self._server(None)
3331 client = self._client(None)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003332
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003333 self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003334
3335 size = 2 ** 15
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003336 sent = client.send(b"x" * size)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003337 # Sanity check. We're trying to test what happens when the entire
3338 # input can't be sent. If the entire input was sent, this test is
3339 # meaningless.
3340 self.assertTrue(sent < size)
3341
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003342 receiver, received = self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003343 self.assertIdentical(receiver, server)
3344
3345 # We can rely on all of these bytes being received at once because
3346 # _loopback passes 2 ** 16 to recv - more than 2 ** 15.
3347 self.assertEquals(len(received), sent)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003348
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003349 def test_shutdown(self):
3350 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003351 :py:obj:`Connection.bio_shutdown` signals the end of the data stream
3352 from which the :py:obj:`Connection` reads.
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003353 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003354 server = self._server(None)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003355 server.bio_shutdown()
3356 e = self.assertRaises(Error, server.recv, 1024)
3357 # We don't want WantReadError or ZeroReturnError or anything - it's a
3358 # handshake failure.
Alex Gaynor5af32d02016-09-24 01:52:21 -04003359 assert type(e) in [Error, SysCallError]
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003360
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003361 def test_unexpectedEndOfFile(self):
3362 """
3363 If the connection is lost before an orderly SSL shutdown occurs,
3364 :py:obj:`OpenSSL.SSL.SysCallError` is raised with a message of
3365 "Unexpected EOF".
3366 """
3367 server_conn, client_conn = self._loopback()
3368 client_conn.sock_shutdown(SHUT_RDWR)
3369 exc = self.assertRaises(SysCallError, server_conn.recv, 1024)
3370 self.assertEqual(exc.args, (-1, "Unexpected EOF"))
3371
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003372 def _check_client_ca_list(self, func):
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003373 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003374 Verify the return value of the :py:obj:`get_client_ca_list` method for
3375 server and client connections.
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003376
Jonathan Ballet78b92a22011-07-16 08:07:26 +09003377 :param func: A function which will be called with the server context
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003378 before the client and server are connected to each other. This
3379 function should specify a list of CAs for the server to send to the
3380 client and return that same list. The list will be used to verify
Hynek Schlawack35618382015-09-05 21:54:25 +02003381 that :py:obj:`get_client_ca_list` returns the proper value at
3382 various times.
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003383 """
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003384 server = self._server(None)
3385 client = self._client(None)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003386 self.assertEqual(client.get_client_ca_list(), [])
3387 self.assertEqual(server.get_client_ca_list(), [])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003388 ctx = server.get_context()
3389 expected = func(ctx)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003390 self.assertEqual(client.get_client_ca_list(), [])
3391 self.assertEqual(server.get_client_ca_list(), expected)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003392 self._interactInMemory(client, server)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003393 self.assertEqual(client.get_client_ca_list(), expected)
3394 self.assertEqual(server.get_client_ca_list(), expected)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003395
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003396 def test_set_client_ca_list_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003397 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003398 :py:obj:`Context.set_client_ca_list` raises a :py:obj:`TypeError` if
3399 called with a non-list or a list that contains objects other than
3400 X509Names.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003401 """
3402 ctx = Context(TLSv1_METHOD)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003403 self.assertRaises(TypeError, ctx.set_client_ca_list, "spam")
3404 self.assertRaises(TypeError, ctx.set_client_ca_list, ["spam"])
3405 self.assertIdentical(ctx.set_client_ca_list([]), None)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003406
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003407 def test_set_empty_ca_list(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003408 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003409 If passed an empty list, :py:obj:`Context.set_client_ca_list`
3410 configures the context to send no CA names to the client and, on both
3411 the server and client sides, :py:obj:`Connection.get_client_ca_list`
3412 returns an empty list after the connection is set up.
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003413 """
3414 def no_ca(ctx):
3415 ctx.set_client_ca_list([])
3416 return []
3417 self._check_client_ca_list(no_ca)
3418
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003419 def test_set_one_ca_list(self):
3420 """
3421 If passed a list containing a single X509Name,
Hynek Schlawack35618382015-09-05 21:54:25 +02003422 :py:obj:`Context.set_client_ca_list` configures the context to send
3423 that CA name to the client and, on both the server and client sides,
Jonathan Ballet648875f2011-07-16 14:14:58 +09003424 :py:obj:`Connection.get_client_ca_list` returns a list containing that
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003425 X509Name after the connection is set up.
3426 """
3427 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3428 cadesc = cacert.get_subject()
Hynek Schlawack35618382015-09-05 21:54:25 +02003429
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003430 def single_ca(ctx):
3431 ctx.set_client_ca_list([cadesc])
3432 return [cadesc]
3433 self._check_client_ca_list(single_ca)
3434
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003435 def test_set_multiple_ca_list(self):
3436 """
3437 If passed a list containing multiple X509Name objects,
Hynek Schlawack35618382015-09-05 21:54:25 +02003438 :py:obj:`Context.set_client_ca_list` configures the context to send
3439 those CA names to the client and, on both the server and client sides,
Jonathan Ballet648875f2011-07-16 14:14:58 +09003440 :py:obj:`Connection.get_client_ca_list` returns a list containing those
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003441 X509Names after the connection is set up.
3442 """
3443 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3444 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3445
3446 sedesc = secert.get_subject()
3447 cldesc = clcert.get_subject()
3448
3449 def multiple_ca(ctx):
3450 L = [sedesc, cldesc]
3451 ctx.set_client_ca_list(L)
3452 return L
3453 self._check_client_ca_list(multiple_ca)
3454
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003455 def test_reset_ca_list(self):
3456 """
3457 If called multiple times, only the X509Names passed to the final call
Hynek Schlawack35618382015-09-05 21:54:25 +02003458 of :py:obj:`Context.set_client_ca_list` are used to configure the CA
3459 names sent to the client.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003460 """
3461 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3462 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3463 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3464
3465 cadesc = cacert.get_subject()
3466 sedesc = secert.get_subject()
3467 cldesc = clcert.get_subject()
3468
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003469 def changed_ca(ctx):
3470 ctx.set_client_ca_list([sedesc, cldesc])
3471 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003472 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003473 self._check_client_ca_list(changed_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003474
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003475 def test_mutated_ca_list(self):
3476 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003477 If the list passed to :py:obj:`Context.set_client_ca_list` is mutated
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003478 afterwards, this does not affect the list of CA names sent to the
3479 client.
3480 """
3481 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3482 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3483
3484 cadesc = cacert.get_subject()
3485 sedesc = secert.get_subject()
3486
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003487 def mutated_ca(ctx):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003488 L = [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003489 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003490 L.append(sedesc)
3491 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003492 self._check_client_ca_list(mutated_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003493
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003494 def test_add_client_ca_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003495 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003496 :py:obj:`Context.add_client_ca` raises :py:obj:`TypeError` if called
3497 with a non-X509 object or with a number of arguments other than one.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003498 """
3499 ctx = Context(TLSv1_METHOD)
3500 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003501 self.assertRaises(TypeError, ctx.add_client_ca)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003502 self.assertRaises(TypeError, ctx.add_client_ca, "spam")
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003503 self.assertRaises(TypeError, ctx.add_client_ca, cacert, cacert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003504
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003505 def test_one_add_client_ca(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003506 """
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003507 A certificate's subject can be added as a CA to be sent to the client
Jonathan Ballet648875f2011-07-16 14:14:58 +09003508 with :py:obj:`Context.add_client_ca`.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003509 """
3510 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3511 cadesc = cacert.get_subject()
Hynek Schlawack35618382015-09-05 21:54:25 +02003512
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003513 def single_ca(ctx):
3514 ctx.add_client_ca(cacert)
3515 return [cadesc]
3516 self._check_client_ca_list(single_ca)
3517
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003518 def test_multiple_add_client_ca(self):
3519 """
3520 Multiple CA names can be sent to the client by calling
Jonathan Ballet648875f2011-07-16 14:14:58 +09003521 :py:obj:`Context.add_client_ca` with multiple X509 objects.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003522 """
3523 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3524 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3525
3526 cadesc = cacert.get_subject()
3527 sedesc = secert.get_subject()
3528
3529 def multiple_ca(ctx):
3530 ctx.add_client_ca(cacert)
3531 ctx.add_client_ca(secert)
3532 return [cadesc, sedesc]
3533 self._check_client_ca_list(multiple_ca)
3534
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003535 def test_set_and_add_client_ca(self):
3536 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003537 A call to :py:obj:`Context.set_client_ca_list` followed by a call to
Hynek Schlawack35618382015-09-05 21:54:25 +02003538 :py:obj:`Context.add_client_ca` results in using the CA names from the
3539 first call and the CA name from the second call.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003540 """
3541 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3542 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3543 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3544
3545 cadesc = cacert.get_subject()
3546 sedesc = secert.get_subject()
3547 cldesc = clcert.get_subject()
3548
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003549 def mixed_set_add_ca(ctx):
3550 ctx.set_client_ca_list([cadesc, sedesc])
3551 ctx.add_client_ca(clcert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003552 return [cadesc, sedesc, cldesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003553 self._check_client_ca_list(mixed_set_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003554
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003555 def test_set_after_add_client_ca(self):
3556 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003557 A call to :py:obj:`Context.set_client_ca_list` after a call to
Hynek Schlawack35618382015-09-05 21:54:25 +02003558 :py:obj:`Context.add_client_ca` replaces the CA name specified by the
3559 former call with the names specified by the latter call.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003560 """
3561 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3562 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3563 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3564
3565 cadesc = cacert.get_subject()
3566 sedesc = secert.get_subject()
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003567
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003568 def set_replaces_add_ca(ctx):
3569 ctx.add_client_ca(clcert)
3570 ctx.set_client_ca_list([cadesc])
3571 ctx.add_client_ca(secert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003572 return [cadesc, sedesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003573 self._check_client_ca_list(set_replaces_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003574
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003575
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003576class InfoConstantTests(TestCase):
3577 """
3578 Tests for assorted constants exposed for use in info callbacks.
3579 """
3580 def test_integers(self):
3581 """
3582 All of the info constants are integers.
3583
3584 This is a very weak test. It would be nice to have one that actually
3585 verifies that as certain info events happen, the value passed to the
3586 info callback matches up with the constant exposed by OpenSSL.SSL.
3587 """
3588 for const in [
Alex Gaynor5af32d02016-09-24 01:52:21 -04003589 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK,
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003590 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
3591 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
3592 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
Hynek Schlawack35618382015-09-05 21:54:25 +02003593 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE
3594 ]:
Alex Gaynor5af32d02016-09-24 01:52:21 -04003595 assert isinstance(const, int)
3596
3597 # These constants don't exist on OpenSSL 1.1.0
3598 for const in [
3599 SSL_ST_INIT, SSL_ST_BEFORE, SSL_ST_OK, SSL_ST_RENEGOTIATE
3600 ]:
3601 assert const is None or isinstance(const, int)
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003602
Ziga Seilnacht44611bf2009-08-31 20:49:30 +02003603
Cory Benfield1d142142016-03-30 11:51:45 +01003604class TestRequires(object):
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003605 """
3606 Tests for the decorator factory used to conditionally raise
Cory Benfield1d142142016-03-30 11:51:45 +01003607 NotImplementedError when older OpenSSLs are used.
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003608 """
3609 def test_available(self):
3610 """
3611 When the OpenSSL functionality is available the decorated functions
3612 work appropriately.
3613 """
3614 feature_guard = _make_requires(True, "Error text")
3615 results = []
3616
3617 @feature_guard
3618 def inner():
3619 results.append(True)
3620 return True
3621
Cory Benfield2333e5e2016-03-30 14:24:16 +01003622 assert inner() is True
3623 assert [True] == results
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003624
3625 def test_unavailable(self):
3626 """
3627 When the OpenSSL functionality is not available the decorated function
3628 does not execute and NotImplementedError is raised.
3629 """
3630 feature_guard = _make_requires(False, "Error text")
3631 results = []
3632
3633 @feature_guard
3634 def inner():
3635 results.append(True)
3636 return True
3637
Cory Benfield1d142142016-03-30 11:51:45 +01003638 with pytest.raises(NotImplementedError) as e:
3639 inner()
3640
3641 assert "Error text" in str(e.value)
Cory Benfield2333e5e2016-03-30 14:24:16 +01003642 assert results == []
Cory Benfield496652a2017-01-24 11:42:56 +00003643
3644
3645class TestOCSP(_LoopbackMixin):
3646 """
3647 Tests for PyOpenSSL's OCSP stapling support.
3648 """
3649 sample_ocsp_data = b"this is totally ocsp data"
3650
3651 def _client_connection(self, callback, data, request_ocsp=True):
3652 """
3653 Builds a client connection suitable for using OCSP.
3654
3655 :param callback: The callback to register for OCSP.
3656 :param data: The opaque data object that will be handed to the
3657 OCSP callback.
3658 :param request_ocsp: Whether the client will actually ask for OCSP
3659 stapling. Useful for testing only.
3660 """
3661 ctx = Context(SSLv23_METHOD)
3662 ctx.set_ocsp_client_callback(callback, data)
3663 client = Connection(ctx)
3664
3665 if request_ocsp:
3666 client.request_ocsp()
3667
3668 client.set_connect_state()
3669 return client
3670
3671 def _server_connection(self, callback, data):
3672 """
3673 Builds a server connection suitable for using OCSP.
3674
3675 :param callback: The callback to register for OCSP.
3676 :param data: The opaque data object that will be handed to the
3677 OCSP callback.
3678 """
3679 ctx = Context(SSLv23_METHOD)
3680 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
3681 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
3682 ctx.set_ocsp_server_callback(callback, data)
3683 server = Connection(ctx)
3684 server.set_accept_state()
3685 return server
3686
3687 def test_callbacks_arent_called_by_default(self):
3688 """
3689 If both the client and the server have registered OCSP callbacks, but
3690 the client does not send the OCSP request, neither callback gets
3691 called.
3692 """
3693 called = []
3694
3695 def ocsp_callback(*args, **kwargs):
3696 called.append((args, kwargs))
3697
3698 client = self._client_connection(
3699 callback=ocsp_callback, data=None, request_ocsp=False
3700 )
3701 server = self._server_connection(callback=ocsp_callback, data=None)
3702 self._handshakeInMemory(client, server)
3703
3704 assert not called
3705
3706 def test_client_negotiates_without_server(self):
3707 """
3708 If the client wants to do OCSP but the server does not, the handshake
3709 succeeds, and the client callback fires with an empty byte string.
3710 """
3711 called = []
3712
3713 def ocsp_callback(conn, ocsp_data, ignored):
3714 called.append(ocsp_data)
3715 return True
3716
3717 client = self._client_connection(callback=ocsp_callback, data=None)
3718 server = self._loopbackServerFactory(socket=None)
3719 self._handshakeInMemory(client, server)
3720
3721 assert len(called) == 1
3722 assert called[0] == b''
3723
3724 def test_client_receives_servers_data(self):
3725 """
3726 The data the server sends in its callback is received by the client.
3727 """
3728 calls = []
3729
3730 def server_callback(*args, **kwargs):
3731 return self.sample_ocsp_data
3732
3733 def client_callback(conn, ocsp_data, ignored):
3734 calls.append(ocsp_data)
3735 return True
3736
3737 client = self._client_connection(callback=client_callback, data=None)
3738 server = self._server_connection(callback=server_callback, data=None)
3739 self._handshakeInMemory(client, server)
3740
3741 assert len(calls) == 1
3742 assert calls[0] == self.sample_ocsp_data
3743
3744 def test_callbacks_are_invoked_with_connections(self):
3745 """
3746 The first arguments to both callbacks are their respective connections.
3747 """
3748 client_calls = []
3749 server_calls = []
3750
3751 def client_callback(conn, *args, **kwargs):
3752 client_calls.append(conn)
3753 return True
3754
3755 def server_callback(conn, *args, **kwargs):
3756 server_calls.append(conn)
3757 return self.sample_ocsp_data
3758
3759 client = self._client_connection(callback=client_callback, data=None)
3760 server = self._server_connection(callback=server_callback, data=None)
3761 self._handshakeInMemory(client, server)
3762
3763 assert len(client_calls) == 1
3764 assert len(server_calls) == 1
3765 assert client_calls[0] is client
3766 assert server_calls[0] is server
3767
3768 def test_opaque_data_is_passed_through(self):
3769 """
3770 Both callbacks receive an opaque, user-provided piece of data in their
3771 callbacks as the final argument.
3772 """
3773 calls = []
3774
3775 def server_callback(*args):
3776 calls.append(args)
3777 return self.sample_ocsp_data
3778
3779 def client_callback(*args):
3780 calls.append(args)
3781 return True
3782
3783 sentinel = object()
3784
3785 client = self._client_connection(
3786 callback=client_callback, data=sentinel
3787 )
3788 server = self._server_connection(
3789 callback=server_callback, data=sentinel
3790 )
3791 self._handshakeInMemory(client, server)
3792
3793 assert len(calls) == 2
3794 assert calls[0][-1] is sentinel
3795 assert calls[1][-1] is sentinel
3796
3797 def test_server_returns_empty_string(self):
3798 """
3799 If the server returns an empty bytestring from its callback, the
3800 client callback is called with the empty bytestring.
3801 """
3802 client_calls = []
3803
3804 def server_callback(*args):
3805 return b''
3806
3807 def client_callback(conn, ocsp_data, ignored):
3808 client_calls.append(ocsp_data)
3809 return True
3810
3811 client = self._client_connection(callback=client_callback, data=None)
3812 server = self._server_connection(callback=server_callback, data=None)
3813 self._handshakeInMemory(client, server)
3814
3815 assert len(client_calls) == 1
3816 assert client_calls[0] == b''
3817
3818 def test_client_returns_false_terminates_handshake(self):
3819 """
3820 If the client returns False from its callback, the handshake fails.
3821 """
3822 def server_callback(*args):
3823 return self.sample_ocsp_data
3824
3825 def client_callback(*args):
3826 return False
3827
3828 client = self._client_connection(callback=client_callback, data=None)
3829 server = self._server_connection(callback=server_callback, data=None)
3830
3831 with pytest.raises(Error):
3832 self._handshakeInMemory(client, server)
3833
3834 def test_exceptions_in_client_bubble_up(self):
3835 """
3836 The callbacks thrown in the client callback bubble up to the caller.
3837 """
3838 class SentinelException(Exception):
3839 pass
3840
3841 def server_callback(*args):
3842 return self.sample_ocsp_data
3843
3844 def client_callback(*args):
3845 raise SentinelException()
3846
3847 client = self._client_connection(callback=client_callback, data=None)
3848 server = self._server_connection(callback=server_callback, data=None)
3849
3850 with pytest.raises(SentinelException):
3851 self._handshakeInMemory(client, server)
3852
3853 def test_exceptions_in_server_bubble_up(self):
3854 """
3855 The callbacks thrown in the server callback bubble up to the caller.
3856 """
3857 class SentinelException(Exception):
3858 pass
3859
3860 def server_callback(*args):
3861 raise SentinelException()
3862
3863 def client_callback(*args):
3864 pytest.fail("Should not be called")
3865
3866 client = self._client_connection(callback=client_callback, data=None)
3867 server = self._server_connection(callback=server_callback, data=None)
3868
3869 with pytest.raises(SentinelException):
3870 self._handshakeInMemory(client, server)
3871
3872 def test_server_must_return_bytes(self):
3873 """
3874 The server callback must return a bytestring, or a TypeError is thrown.
3875 """
3876 def server_callback(*args):
3877 return self.sample_ocsp_data.decode('ascii')
3878
3879 def client_callback(*args):
3880 pytest.fail("Should not be called")
3881
3882 client = self._client_connection(callback=client_callback, data=None)
3883 server = self._server_connection(callback=server_callback, data=None)
3884
3885 with pytest.raises(TypeError):
3886 self._handshakeInMemory(client, server)