blob: fafffa3ed41dd506444e2f29386c021006ca2a98 [file] [log] [blame]
Jean-Paul Calderone8671c852011-03-02 19:26:20 -05001# Copyright (C) Jean-Paul Calderone
2# See LICENSE for details.
Jean-Paul Calderone8b63d452008-03-21 18:31:12 -04003
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -04004"""
Hynek Schlawackf90e3682016-03-11 11:21:13 +01005Unit tests for :mod:`OpenSSL.SSL`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -04006"""
7
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01008import datetime
Maximilian Hils868dc3c2017-02-10 14:56:55 +01009import sys
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +010010import uuid
11
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -050012from gc import collect, get_referrers
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +020013from errno import ECONNREFUSED, EINPROGRESS, EWOULDBLOCK, EPIPE, ESHUTDOWN
Hynek Schlawackf8979a52015-09-05 21:25:25 +020014from sys import platform, getfilesystemencoding, version_info
Maximilian Hils1d95dea2015-08-17 19:27:20 +020015from socket import MSG_PEEK, SHUT_RDWR, error, socket
Jean-Paul Calderonea65cf6c2009-07-19 10:26:52 -040016from os import makedirs
Jean-Paul Calderone1461c492013-10-03 16:05:00 -040017from os.path import join
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -040018from weakref import ref
Alex Chanb7480992017-01-30 14:04:47 +000019from warnings import simplefilter
Jean-Paul Calderone460cc1f2009-03-07 11:31:12 -050020
Hynek Schlawack734d3022015-09-05 19:19:32 +020021import pytest
22
Paul Kehrer55fb3412017-06-29 18:44:08 -050023from pretend import raiser
24
Hynek Schlawackf90e3682016-03-11 11:21:13 +010025from six import PY3, text_type
Jean-Paul Calderonec76c61c2014-01-18 13:21:52 -050026
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +010027from cryptography import x509
28from cryptography.hazmat.backends import default_backend
29from cryptography.hazmat.primitives import hashes
30from cryptography.hazmat.primitives import serialization
31from cryptography.hazmat.primitives.asymmetric import rsa
32from cryptography.x509.oid import NameOID
33
34
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040035from OpenSSL.crypto import TYPE_RSA, FILETYPE_PEM
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -080036from OpenSSL.crypto import PKey, X509, X509Extension, X509Store
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040037from OpenSSL.crypto import dump_privatekey, load_privatekey
38from OpenSSL.crypto import dump_certificate, load_certificate
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -040039from OpenSSL.crypto import get_elliptic_curves
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040040
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -040041from OpenSSL.SSL import OPENSSL_VERSION_NUMBER, SSLEAY_VERSION, SSLEAY_CFLAGS
42from OpenSSL.SSL import SSLEAY_PLATFORM, SSLEAY_DIR, SSLEAY_BUILT_ON
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -040043from OpenSSL.SSL import SENT_SHUTDOWN, RECEIVED_SHUTDOWN
Jean-Paul Calderone1461c492013-10-03 16:05:00 -040044from OpenSSL.SSL import (
45 SSLv2_METHOD, SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD,
46 TLSv1_1_METHOD, TLSv1_2_METHOD)
47from OpenSSL.SSL import OP_SINGLE_DH_USE, OP_NO_SSLv2, OP_NO_SSLv3
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040048from OpenSSL.SSL import (
49 VERIFY_PEER, VERIFY_FAIL_IF_NO_PEER_CERT, VERIFY_CLIENT_ONCE, VERIFY_NONE)
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040050
Paul Kehrer55fb3412017-06-29 18:44:08 -050051from OpenSSL import SSL
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040052from OpenSSL.SSL import (
Jean-Paul Calderone313bf012012-02-08 13:02:49 -050053 SESS_CACHE_OFF, SESS_CACHE_CLIENT, SESS_CACHE_SERVER, SESS_CACHE_BOTH,
54 SESS_CACHE_NO_AUTO_CLEAR, SESS_CACHE_NO_INTERNAL_LOOKUP,
55 SESS_CACHE_NO_INTERNAL_STORE, SESS_CACHE_NO_INTERNAL)
56
57from OpenSSL.SSL import (
Jean-Paul Calderoned899af02013-03-19 22:10:37 -070058 Error, SysCallError, WantReadError, WantWriteError, ZeroReturnError)
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -050059from OpenSSL.SSL import (
Jean-Paul Calderoned899af02013-03-19 22:10:37 -070060 Context, ContextType, Session, Connection, ConnectionType, SSLeay_version)
Cory Benfield0ba57ec2016-03-30 09:35:05 +010061from OpenSSL.SSL import _make_requires
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040062
Paul Kehrer55fb3412017-06-29 18:44:08 -050063from OpenSSL._util import ffi as _ffi, lib as _lib
Cory Benfieldba1820d2015-04-13 17:39:12 -040064
Alex Gaynord3b5d9b2016-07-31 10:54:24 -040065from OpenSSL.SSL import (
66 OP_NO_QUERY_MTU, OP_COOKIE_EXCHANGE, OP_NO_TICKET, OP_NO_COMPRESSION,
67 MODE_RELEASE_BUFFERS)
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040068
Jean-Paul Calderone1461c492013-10-03 16:05:00 -040069try:
70 from OpenSSL.SSL import OP_NO_TLSv1, OP_NO_TLSv1_1, OP_NO_TLSv1_2
71except ImportError:
72 OP_NO_TLSv1 = OP_NO_TLSv1_1 = OP_NO_TLSv1_2 = None
73
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -040074from OpenSSL.SSL import (
Alex Gaynor5af32d02016-09-24 01:52:21 -040075 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK,
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -040076 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
77 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
78 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
79 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE)
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -040080
Alex Gaynor5af32d02016-09-24 01:52:21 -040081try:
82 from OpenSSL.SSL import (
83 SSL_ST_INIT, SSL_ST_BEFORE, SSL_ST_OK, SSL_ST_RENEGOTIATE
84 )
85except ImportError:
86 SSL_ST_INIT = SSL_ST_BEFORE = SSL_ST_OK = SSL_ST_RENEGOTIATE = None
87
Alex Chanb7480992017-01-30 14:04:47 +000088from .util import WARNING_TYPE_EXPECTED, NON_ASCII, is_consistent_type
Hynek Schlawackf0e66852015-10-16 20:18:38 +020089from .test_crypto import (
90 cleartextCertificatePEM, cleartextPrivateKeyPEM,
91 client_cert_pem, client_key_pem, server_cert_pem, server_key_pem,
92 root_cert_pem)
93
Hynek Schlawackde00dd52015-09-05 19:09:26 +020094
Alex Gaynord0bdd2d2016-09-10 14:23:46 -040095# openssl dhparam 1024 -out dh-1024.pem (note that 1024 is a small number of
96# bits to use)
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -040097dhparam = """\
98-----BEGIN DH PARAMETERS-----
Alex Gaynord0bdd2d2016-09-10 14:23:46 -040099MIGHAoGBALdUMvn+C9MM+y5BWZs11mSeH6HHoEq0UVbzVq7UojC1hbsZUuGukQ3a
100Qh2/pwqb18BZFykrWB0zv/OkLa0kx4cuUgNrUVq1EFheBiX6YqryJ7t2sO09NQiO
101V7H54LmltOT/hEh6QWsJqb6BQgH65bswvV/XkYGja8/T0GzvbaVzAgEC
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -0400102-----END DH PARAMETERS-----
103"""
104
105
Hynek Schlawackb4f02402015-09-05 20:48:34 +0200106skip_if_py3 = pytest.mark.skipif(PY3, reason="Python 2 only")
Hynek Schlawackf8979a52015-09-05 21:25:25 +0200107skip_if_py26 = pytest.mark.skipif(
108 version_info[0:2] == (2, 6),
109 reason="Python 2.7 and later only"
110)
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200111
112
Jean-Paul Calderone05826732015-04-12 11:38:49 -0400113def join_bytes_or_unicode(prefix, suffix):
114 """
115 Join two path components of either ``bytes`` or ``unicode``.
116
117 The return type is the same as the type of ``prefix``.
118 """
119 # If the types are the same, nothing special is necessary.
120 if type(prefix) == type(suffix):
121 return join(prefix, suffix)
122
123 # Otherwise, coerce suffix to the type of prefix.
124 if isinstance(prefix, text_type):
125 return join(prefix, suffix.decode(getfilesystemencoding()))
126 else:
127 return join(prefix, suffix.encode(getfilesystemencoding()))
128
129
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400130def verify_cb(conn, cert, errnum, depth, ok):
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400131 return ok
132
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400133
Rick Deanb1ccd562009-07-09 23:52:39 -0500134def socket_pair():
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400135 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400136 Establish and return a pair of network sockets connected to each other.
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400137 """
138 # Connect a pair of sockets
Rick Deanb1ccd562009-07-09 23:52:39 -0500139 port = socket()
140 port.bind(('', 0))
141 port.listen(1)
142 client = socket()
143 client.setblocking(False)
Jean-Paul Calderonef23c5d92009-07-23 17:58:15 -0400144 client.connect_ex(("127.0.0.1", port.getsockname()[1]))
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400145 client.setblocking(True)
Rick Deanb1ccd562009-07-09 23:52:39 -0500146 server = port.accept()[0]
Rick Deanb1ccd562009-07-09 23:52:39 -0500147
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400148 # Let's pass some unencrypted data to make sure our socket connection is
149 # fine. Just one byte, so we don't have to worry about buffers getting
150 # filled up or fragmentation.
Alex Gaynore7f51982016-09-11 11:48:14 -0400151 server.send(b"x")
152 assert client.recv(1024) == b"x"
153 client.send(b"y")
154 assert server.recv(1024) == b"y"
Rick Deanb1ccd562009-07-09 23:52:39 -0500155
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -0400156 # Most of our callers want non-blocking sockets, make it easy for them.
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400157 server.setblocking(False)
158 client.setblocking(False)
Jim Shaver46f28912015-05-29 19:32:16 -0400159
Rick Deanb1ccd562009-07-09 23:52:39 -0500160 return (server, client)
161
162
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400163def handshake(client, server):
164 conns = [client, server]
165 while conns:
166 for conn in conns:
167 try:
168 conn.do_handshake()
169 except WantReadError:
170 pass
171 else:
172 conns.remove(conn)
173
174
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400175def _create_certificate_chain():
176 """
177 Construct and return a chain of certificates.
178
179 1. A new self-signed certificate authority certificate (cacert)
180 2. A new intermediate certificate signed by cacert (icert)
181 3. A new server certificate signed by icert (scert)
182 """
Alex Gaynore7f51982016-09-11 11:48:14 -0400183 caext = X509Extension(b'basicConstraints', False, b'CA:true')
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400184
185 # Step 1
186 cakey = PKey()
Alex Gaynor0737a5e2016-09-10 14:35:09 -0400187 cakey.generate_key(TYPE_RSA, 1024)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400188 cacert = X509()
189 cacert.get_subject().commonName = "Authority Certificate"
190 cacert.set_issuer(cacert.get_subject())
191 cacert.set_pubkey(cakey)
Alex Gaynore7f51982016-09-11 11:48:14 -0400192 cacert.set_notBefore(b"20000101000000Z")
193 cacert.set_notAfter(b"20200101000000Z")
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400194 cacert.add_extensions([caext])
195 cacert.set_serial_number(0)
196 cacert.sign(cakey, "sha1")
197
198 # Step 2
199 ikey = PKey()
Alex Gaynor0737a5e2016-09-10 14:35:09 -0400200 ikey.generate_key(TYPE_RSA, 1024)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400201 icert = X509()
202 icert.get_subject().commonName = "Intermediate Certificate"
203 icert.set_issuer(cacert.get_subject())
204 icert.set_pubkey(ikey)
Alex Gaynore7f51982016-09-11 11:48:14 -0400205 icert.set_notBefore(b"20000101000000Z")
206 icert.set_notAfter(b"20200101000000Z")
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400207 icert.add_extensions([caext])
208 icert.set_serial_number(0)
209 icert.sign(cakey, "sha1")
210
211 # Step 3
212 skey = PKey()
Alex Gaynor0737a5e2016-09-10 14:35:09 -0400213 skey.generate_key(TYPE_RSA, 1024)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400214 scert = X509()
215 scert.get_subject().commonName = "Server Certificate"
216 scert.set_issuer(icert.get_subject())
217 scert.set_pubkey(skey)
Alex Gaynore7f51982016-09-11 11:48:14 -0400218 scert.set_notBefore(b"20000101000000Z")
219 scert.set_notAfter(b"20200101000000Z")
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400220 scert.add_extensions([
Alex Gaynore7f51982016-09-11 11:48:14 -0400221 X509Extension(b'basicConstraints', True, b'CA:false')])
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400222 scert.set_serial_number(0)
223 scert.sign(ikey, "sha1")
224
225 return [(cakey, cacert), (ikey, icert), (skey, scert)]
226
227
Alex Chan1c0cb662017-01-30 07:13:30 +0000228def loopback_client_factory(socket):
229 client = Connection(Context(TLSv1_METHOD), socket)
230 client.set_connect_state()
231 return client
232
233
234def loopback_server_factory(socket):
235 ctx = Context(TLSv1_METHOD)
236 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
237 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
238 server = Connection(ctx, socket)
239 server.set_accept_state()
240 return server
241
242
243def loopback(server_factory=None, client_factory=None):
244 """
245 Create a connected socket pair and force two connected SSL sockets
246 to talk to each other via memory BIOs.
247 """
248 if server_factory is None:
249 server_factory = loopback_server_factory
250 if client_factory is None:
251 client_factory = loopback_client_factory
252
253 (server, client) = socket_pair()
254 server = server_factory(server)
255 client = client_factory(client)
256
257 handshake(client, server)
258
259 server.setblocking(True)
260 client.setblocking(True)
261 return server, client
262
263
Alex Chan1ca9e3a2016-11-05 13:01:51 +0000264def interact_in_memory(client_conn, server_conn):
265 """
266 Try to read application bytes from each of the two `Connection` objects.
267 Copy bytes back and forth between their send/receive buffers for as long
268 as there is anything to copy. When there is nothing more to copy,
269 return `None`. If one of them actually manages to deliver some application
270 bytes, return a two-tuple of the connection from which the bytes were read
271 and the bytes themselves.
272 """
273 wrote = True
274 while wrote:
275 # Loop until neither side has anything to say
276 wrote = False
277
278 # Copy stuff from each side's send buffer to the other side's
279 # receive buffer.
280 for (read, write) in [(client_conn, server_conn),
281 (server_conn, client_conn)]:
282
283 # Give the side a chance to generate some more bytes, or succeed.
284 try:
285 data = read.recv(2 ** 16)
286 except WantReadError:
287 # It didn't succeed, so we'll hope it generated some output.
288 pass
289 else:
290 # It did succeed, so we'll stop now and let the caller deal
291 # with it.
292 return (read, data)
293
294 while True:
295 # Keep copying as long as there's more stuff there.
296 try:
297 dirty = read.bio_read(4096)
298 except WantReadError:
299 # Okay, nothing more waiting to be sent. Stop
300 # processing this send buffer.
301 break
302 else:
303 # Keep track of the fact that someone generated some
304 # output.
305 wrote = True
306 write.bio_write(dirty)
307
308
Alex Chan532b79e2017-01-24 15:14:52 +0000309def handshake_in_memory(client_conn, server_conn):
310 """
311 Perform the TLS handshake between two `Connection` instances connected to
312 each other via memory BIOs.
313 """
314 client_conn.set_connect_state()
315 server_conn.set_accept_state()
316
317 for conn in [client_conn, server_conn]:
318 try:
319 conn.do_handshake()
320 except WantReadError:
321 pass
322
323 interact_in_memory(client_conn, server_conn)
324
325
Alex Chanb7480992017-01-30 14:04:47 +0000326class TestVersion(object):
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400327 """
Alex Chanb7480992017-01-30 14:04:47 +0000328 Tests for version information exposed by `OpenSSL.SSL.SSLeay_version` and
329 `OpenSSL.SSL.OPENSSL_VERSION_NUMBER`.
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400330 """
331 def test_OPENSSL_VERSION_NUMBER(self):
332 """
Alex Chanb7480992017-01-30 14:04:47 +0000333 `OPENSSL_VERSION_NUMBER` is an integer with status in the low byte and
334 the patch, fix, minor, and major versions in the nibbles above that.
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400335 """
Alex Chanb7480992017-01-30 14:04:47 +0000336 assert isinstance(OPENSSL_VERSION_NUMBER, int)
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400337
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400338 def test_SSLeay_version(self):
339 """
Alex Chanb7480992017-01-30 14:04:47 +0000340 `SSLeay_version` takes a version type indicator and returns one of a
341 number of version strings based on that indicator.
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400342 """
343 versions = {}
344 for t in [SSLEAY_VERSION, SSLEAY_CFLAGS, SSLEAY_BUILT_ON,
345 SSLEAY_PLATFORM, SSLEAY_DIR]:
346 version = SSLeay_version(t)
347 versions[version] = t
Alex Chanb7480992017-01-30 14:04:47 +0000348 assert isinstance(version, bytes)
349 assert len(versions) == 5
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400350
351
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100352@pytest.fixture
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100353def ca_file(tmpdir):
354 """
355 Create a valid PEM file with CA certificates and return the path.
356 """
357 key = rsa.generate_private_key(
358 public_exponent=65537,
359 key_size=2048,
360 backend=default_backend()
361 )
362 public_key = key.public_key()
363
364 builder = x509.CertificateBuilder()
365 builder = builder.subject_name(x509.Name([
366 x509.NameAttribute(NameOID.COMMON_NAME, u"pyopenssl.org"),
367 ]))
368 builder = builder.issuer_name(x509.Name([
369 x509.NameAttribute(NameOID.COMMON_NAME, u"pyopenssl.org"),
370 ]))
371 one_day = datetime.timedelta(1, 0, 0)
372 builder = builder.not_valid_before(datetime.datetime.today() - one_day)
373 builder = builder.not_valid_after(datetime.datetime.today() + one_day)
374 builder = builder.serial_number(int(uuid.uuid4()))
375 builder = builder.public_key(public_key)
376 builder = builder.add_extension(
377 x509.BasicConstraints(ca=True, path_length=None), critical=True,
378 )
379
380 certificate = builder.sign(
381 private_key=key, algorithm=hashes.SHA256(),
382 backend=default_backend()
383 )
384
385 ca_file = tmpdir.join("test.pem")
386 ca_file.write_binary(
387 certificate.public_bytes(
388 encoding=serialization.Encoding.PEM,
389 )
390 )
391
392 return str(ca_file).encode("ascii")
393
394
395@pytest.fixture
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100396def context():
397 """
398 A simple TLS 1.0 context.
399 """
400 return Context(TLSv1_METHOD)
401
402
403class TestContext(object):
Hynek Schlawackaa861212016-03-13 13:53:48 +0100404 """
Alex Chan532b79e2017-01-24 15:14:52 +0000405 Unit tests for `OpenSSL.SSL.Context`.
Hynek Schlawackaa861212016-03-13 13:53:48 +0100406 """
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100407 @pytest.mark.parametrize("cipher_string", [
408 b"hello world:AES128-SHA",
409 u"hello world:AES128-SHA",
410 ])
411 def test_set_cipher_list(self, context, cipher_string):
412 """
Alex Chan532b79e2017-01-24 15:14:52 +0000413 `Context.set_cipher_list` accepts both byte and unicode strings
Hynek Schlawacka7a63af2016-03-11 12:05:26 +0100414 for naming the ciphers which connections created with the context
415 object will be able to choose from.
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100416 """
417 context.set_cipher_list(cipher_string)
418 conn = Connection(context, None)
419
420 assert "AES128-SHA" in conn.get_cipher_list()
421
422 @pytest.mark.parametrize("cipher_list,error", [
423 (object(), TypeError),
424 ("imaginary-cipher", Error),
425 ])
426 def test_set_cipher_list_wrong_args(self, context, cipher_list, error):
427 """
Alex Chan532b79e2017-01-24 15:14:52 +0000428 `Context.set_cipher_list` raises `TypeError` when passed a non-string
429 argument and raises `OpenSSL.SSL.Error` when passed an incorrect cipher
430 list string.
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100431 """
432 with pytest.raises(error):
433 context.set_cipher_list(cipher_list)
434
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100435 def test_load_client_ca(self, context, ca_file):
436 """
Alex Chan532b79e2017-01-24 15:14:52 +0000437 `Context.load_client_ca` works as far as we can tell.
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100438 """
439 context.load_client_ca(ca_file)
440
441 def test_load_client_ca_invalid(self, context, tmpdir):
442 """
Alex Chan532b79e2017-01-24 15:14:52 +0000443 `Context.load_client_ca` raises an Error if the ca file is invalid.
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100444 """
445 ca_file = tmpdir.join("test.pem")
446 ca_file.write("")
447
448 with pytest.raises(Error) as e:
449 context.load_client_ca(str(ca_file).encode("ascii"))
450
451 assert "PEM routines" == e.value.args[0][0][0]
452
453 def test_load_client_ca_unicode(self, context, ca_file):
454 """
455 Passing the path as unicode raises a warning but works.
456 """
457 pytest.deprecated_call(
458 context.load_client_ca, ca_file.decode("ascii")
459 )
460
461 def test_set_session_id(self, context):
462 """
Alex Chan532b79e2017-01-24 15:14:52 +0000463 `Context.set_session_id` works as far as we can tell.
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100464 """
465 context.set_session_id(b"abc")
466
467 def test_set_session_id_fail(self, context):
468 """
Alex Chan532b79e2017-01-24 15:14:52 +0000469 `Context.set_session_id` errors are propagated.
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100470 """
471 with pytest.raises(Error) as e:
472 context.set_session_id(b"abc" * 1000)
473
474 assert [
475 ("SSL routines",
476 "SSL_CTX_set_session_id_context",
477 "ssl session id context too long")
478 ] == e.value.args[0]
479
480 def test_set_session_id_unicode(self, context):
481 """
Alex Chan532b79e2017-01-24 15:14:52 +0000482 `Context.set_session_id` raises a warning if a unicode string is
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100483 passed.
484 """
485 pytest.deprecated_call(context.set_session_id, u"abc")
486
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400487 def test_method(self):
488 """
Alex Chan532b79e2017-01-24 15:14:52 +0000489 `Context` can be instantiated with one of `SSLv2_METHOD`,
490 `SSLv3_METHOD`, `SSLv23_METHOD`, `TLSv1_METHOD`, `TLSv1_1_METHOD`,
491 or `TLSv1_2_METHOD`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400492 """
Alex Gaynor5af32d02016-09-24 01:52:21 -0400493 methods = [SSLv23_METHOD, TLSv1_METHOD]
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400494 for meth in methods:
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400495 Context(meth)
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400496
Alex Gaynor5af32d02016-09-24 01:52:21 -0400497 maybe = [SSLv2_METHOD, SSLv3_METHOD, TLSv1_1_METHOD, TLSv1_2_METHOD]
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400498 for meth in maybe:
499 try:
500 Context(meth)
501 except (Error, ValueError):
502 # Some versions of OpenSSL have SSLv2 / TLSv1.1 / TLSv1.2, some
503 # don't. Difficult to say in advance.
504 pass
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400505
Alex Chan532b79e2017-01-24 15:14:52 +0000506 with pytest.raises(TypeError):
507 Context("")
508 with pytest.raises(ValueError):
509 Context(10)
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400510
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200511 @skip_if_py3
512 def test_method_long(self):
513 """
Alex Chan532b79e2017-01-24 15:14:52 +0000514 On Python 2 `Context` accepts values of type `long` as well as `int`.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200515 """
516 Context(long(TLSv1_METHOD))
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500517
Rick Deane15b1472009-07-09 15:53:42 -0500518 def test_type(self):
519 """
Alex Chan532b79e2017-01-24 15:14:52 +0000520 `Context` and `ContextType` refer to the same type object and can
521 be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -0500522 """
Alex Chan532b79e2017-01-24 15:14:52 +0000523 assert Context is ContextType
524 assert is_consistent_type(Context, 'Context', TLSv1_METHOD)
Rick Deane15b1472009-07-09 15:53:42 -0500525
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400526 def test_use_privatekey(self):
527 """
Alex Chan532b79e2017-01-24 15:14:52 +0000528 `Context.use_privatekey` takes an `OpenSSL.crypto.PKey` instance.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400529 """
530 key = PKey()
531 key.generate_key(TYPE_RSA, 128)
532 ctx = Context(TLSv1_METHOD)
533 ctx.use_privatekey(key)
Alex Chan532b79e2017-01-24 15:14:52 +0000534 with pytest.raises(TypeError):
535 ctx.use_privatekey("")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400536
Alex Chan532b79e2017-01-24 15:14:52 +0000537 def test_use_privatekey_file_missing(self, tmpfile):
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800538 """
Alex Chan532b79e2017-01-24 15:14:52 +0000539 `Context.use_privatekey_file` raises `OpenSSL.SSL.Error` when passed
540 the name of a file which does not exist.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800541 """
542 ctx = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000543 with pytest.raises(Error):
544 ctx.use_privatekey_file(tmpfile)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800545
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400546 def _use_privatekey_file_test(self, pemfile, filetype):
547 """
548 Verify that calling ``Context.use_privatekey_file`` with the given
549 arguments does not raise an exception.
550 """
551 key = PKey()
552 key.generate_key(TYPE_RSA, 128)
553
554 with open(pemfile, "wt") as pem:
555 pem.write(
556 dump_privatekey(FILETYPE_PEM, key).decode("ascii")
557 )
558
559 ctx = Context(TLSv1_METHOD)
560 ctx.use_privatekey_file(pemfile, filetype)
561
Alex Chanfb078d82017-04-20 11:16:15 +0100562 @pytest.mark.parametrize('filetype', [object(), "", None, 1.0])
563 def test_wrong_privatekey_file_wrong_args(self, tmpfile, filetype):
564 """
565 `Context.use_privatekey_file` raises `TypeError` when called with
566 a `filetype` which is not a valid file encoding.
567 """
568 ctx = Context(TLSv1_METHOD)
569 with pytest.raises(TypeError):
570 ctx.use_privatekey_file(tmpfile, filetype)
571
Alex Chan532b79e2017-01-24 15:14:52 +0000572 def test_use_privatekey_file_bytes(self, tmpfile):
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400573 """
574 A private key can be specified from a file by passing a ``bytes``
575 instance giving the file name to ``Context.use_privatekey_file``.
576 """
577 self._use_privatekey_file_test(
Alex Chan532b79e2017-01-24 15:14:52 +0000578 tmpfile + NON_ASCII.encode(getfilesystemencoding()),
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400579 FILETYPE_PEM,
580 )
581
Alex Chan532b79e2017-01-24 15:14:52 +0000582 def test_use_privatekey_file_unicode(self, tmpfile):
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400583 """
584 A private key can be specified from a file by passing a ``unicode``
585 instance giving the file name to ``Context.use_privatekey_file``.
586 """
587 self._use_privatekey_file_test(
Alex Chan532b79e2017-01-24 15:14:52 +0000588 tmpfile.decode(getfilesystemencoding()) + NON_ASCII,
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400589 FILETYPE_PEM,
590 )
591
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200592 @skip_if_py3
Alex Chan532b79e2017-01-24 15:14:52 +0000593 def test_use_privatekey_file_long(self, tmpfile):
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200594 """
Alex Chan532b79e2017-01-24 15:14:52 +0000595 On Python 2 `Context.use_privatekey_file` accepts a filetype of
596 type `long` as well as `int`.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200597 """
Alex Chan532b79e2017-01-24 15:14:52 +0000598 self._use_privatekey_file_test(tmpfile, long(FILETYPE_PEM))
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500599
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800600 def test_use_certificate_wrong_args(self):
601 """
Alex Chan532b79e2017-01-24 15:14:52 +0000602 `Context.use_certificate_wrong_args` raises `TypeError` when not passed
603 exactly one `OpenSSL.crypto.X509` instance as an argument.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800604 """
605 ctx = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000606 with pytest.raises(TypeError):
607 ctx.use_certificate("hello, world")
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800608
609 def test_use_certificate_uninitialized(self):
610 """
Alex Chan532b79e2017-01-24 15:14:52 +0000611 `Context.use_certificate` raises `OpenSSL.SSL.Error` when passed a
612 `OpenSSL.crypto.X509` instance which has not been initialized
613 (ie, which does not actually have any certificate data).
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800614 """
615 ctx = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000616 with pytest.raises(Error):
617 ctx.use_certificate(X509())
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800618
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800619 def test_use_certificate(self):
620 """
Alex Chan532b79e2017-01-24 15:14:52 +0000621 `Context.use_certificate` sets the certificate which will be
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800622 used to identify connections created using the context.
623 """
624 # TODO
625 # Hard to assert anything. But we could set a privatekey then ask
626 # OpenSSL if the cert and key agree using check_privatekey. Then as
627 # long as check_privatekey works right we're good...
628 ctx = Context(TLSv1_METHOD)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200629 ctx.use_certificate(
630 load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
631 )
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800632
633 def test_use_certificate_file_wrong_args(self):
634 """
Alex Chan532b79e2017-01-24 15:14:52 +0000635 `Context.use_certificate_file` raises `TypeError` if the first
636 argument is not a byte string or the second argument is not an integer.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800637 """
638 ctx = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000639 with pytest.raises(TypeError):
640 ctx.use_certificate_file(object(), FILETYPE_PEM)
641 with pytest.raises(TypeError):
642 ctx.use_certificate_file(b"somefile", object())
643 with pytest.raises(TypeError):
644 ctx.use_certificate_file(object(), FILETYPE_PEM)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800645
Alex Chan532b79e2017-01-24 15:14:52 +0000646 def test_use_certificate_file_missing(self, tmpfile):
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800647 """
Alex Chan532b79e2017-01-24 15:14:52 +0000648 `Context.use_certificate_file` raises `OpenSSL.SSL.Error` if passed
649 the name of a file which does not exist.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800650 """
651 ctx = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000652 with pytest.raises(Error):
653 ctx.use_certificate_file(tmpfile)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800654
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400655 def _use_certificate_file_test(self, certificate_file):
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800656 """
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400657 Verify that calling ``Context.use_certificate_file`` with the given
658 filename doesn't raise an exception.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800659 """
660 # TODO
661 # Hard to assert anything. But we could set a privatekey then ask
662 # OpenSSL if the cert and key agree using check_privatekey. Then as
663 # long as check_privatekey works right we're good...
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400664 with open(certificate_file, "wb") as pem_file:
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800665 pem_file.write(cleartextCertificatePEM)
666
667 ctx = Context(TLSv1_METHOD)
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400668 ctx.use_certificate_file(certificate_file)
669
Alex Chan532b79e2017-01-24 15:14:52 +0000670 def test_use_certificate_file_bytes(self, tmpfile):
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400671 """
Alex Chan532b79e2017-01-24 15:14:52 +0000672 `Context.use_certificate_file` sets the certificate (given as a
673 `bytes` filename) which will be used to identify connections created
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400674 using the context.
675 """
Alex Chan532b79e2017-01-24 15:14:52 +0000676 filename = tmpfile + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400677 self._use_certificate_file_test(filename)
678
Alex Chan532b79e2017-01-24 15:14:52 +0000679 def test_use_certificate_file_unicode(self, tmpfile):
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400680 """
Alex Chan532b79e2017-01-24 15:14:52 +0000681 `Context.use_certificate_file` sets the certificate (given as a
682 `bytes` filename) which will be used to identify connections created
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400683 using the context.
684 """
Alex Chan532b79e2017-01-24 15:14:52 +0000685 filename = tmpfile.decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400686 self._use_certificate_file_test(filename)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800687
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200688 @skip_if_py3
Alex Chan532b79e2017-01-24 15:14:52 +0000689 def test_use_certificate_file_long(self, tmpfile):
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200690 """
Alex Chan532b79e2017-01-24 15:14:52 +0000691 On Python 2 `Context.use_certificate_file` accepts a
692 filetype of type `long` as well as `int`.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200693 """
Alex Chan532b79e2017-01-24 15:14:52 +0000694 pem_filename = tmpfile
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200695 with open(pem_filename, "wb") as pem_file:
696 pem_file.write(cleartextCertificatePEM)
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500697
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200698 ctx = Context(TLSv1_METHOD)
699 ctx.use_certificate_file(pem_filename, long(FILETYPE_PEM))
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500700
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500701 def test_check_privatekey_valid(self):
702 """
Alex Chan532b79e2017-01-24 15:14:52 +0000703 `Context.check_privatekey` returns `None` if the `Context` instance
704 has been configured to use a matched key and certificate pair.
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500705 """
706 key = load_privatekey(FILETYPE_PEM, client_key_pem)
707 cert = load_certificate(FILETYPE_PEM, client_cert_pem)
708 context = Context(TLSv1_METHOD)
709 context.use_privatekey(key)
710 context.use_certificate(cert)
Alex Chan532b79e2017-01-24 15:14:52 +0000711 assert None is context.check_privatekey()
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500712
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500713 def test_check_privatekey_invalid(self):
714 """
Alex Chan532b79e2017-01-24 15:14:52 +0000715 `Context.check_privatekey` raises `Error` if the `Context` instance
716 has been configured to use a key and certificate pair which don't
717 relate to each other.
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500718 """
719 key = load_privatekey(FILETYPE_PEM, client_key_pem)
720 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
721 context = Context(TLSv1_METHOD)
722 context.use_privatekey(key)
723 context.use_certificate(cert)
Alex Chan532b79e2017-01-24 15:14:52 +0000724 with pytest.raises(Error):
725 context.check_privatekey()
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400726
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400727 def test_app_data(self):
728 """
Alex Chan532b79e2017-01-24 15:14:52 +0000729 `Context.set_app_data` stores an object for later retrieval
730 using `Context.get_app_data`.
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400731 """
732 app_data = object()
733 context = Context(TLSv1_METHOD)
734 context.set_app_data(app_data)
Alex Chan532b79e2017-01-24 15:14:52 +0000735 assert context.get_app_data() is app_data
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400736
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400737 def test_set_options_wrong_args(self):
738 """
Alex Chan532b79e2017-01-24 15:14:52 +0000739 `Context.set_options` raises `TypeError` if called with
740 a non-`int` argument.
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400741 """
742 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000743 with pytest.raises(TypeError):
744 context.set_options(None)
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400745
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500746 def test_set_options(self):
747 """
Alex Chan532b79e2017-01-24 15:14:52 +0000748 `Context.set_options` returns the new options value.
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500749 """
750 context = Context(TLSv1_METHOD)
751 options = context.set_options(OP_NO_SSLv2)
Alex Gaynor2310f8b2016-09-10 14:39:32 -0400752 assert options & OP_NO_SSLv2 == OP_NO_SSLv2
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500753
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200754 @skip_if_py3
755 def test_set_options_long(self):
756 """
Alex Chan532b79e2017-01-24 15:14:52 +0000757 On Python 2 `Context.set_options` accepts values of type
758 `long` as well as `int`.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200759 """
760 context = Context(TLSv1_METHOD)
761 options = context.set_options(long(OP_NO_SSLv2))
Alex Gaynor2310f8b2016-09-10 14:39:32 -0400762 assert options & OP_NO_SSLv2 == OP_NO_SSLv2
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500763
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300764 def test_set_mode_wrong_args(self):
765 """
Alex Chan532b79e2017-01-24 15:14:52 +0000766 `Context.set_mode` raises `TypeError` if called with
767 a non-`int` argument.
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300768 """
769 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000770 with pytest.raises(TypeError):
771 context.set_mode(None)
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300772
Alex Gaynord3b5d9b2016-07-31 10:54:24 -0400773 def test_set_mode(self):
774 """
Alex Chan532b79e2017-01-24 15:14:52 +0000775 `Context.set_mode` accepts a mode bitvector and returns the
Alex Gaynord3b5d9b2016-07-31 10:54:24 -0400776 newly set mode.
777 """
778 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000779 assert MODE_RELEASE_BUFFERS & context.set_mode(MODE_RELEASE_BUFFERS)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500780
Alex Gaynord3b5d9b2016-07-31 10:54:24 -0400781 @skip_if_py3
782 def test_set_mode_long(self):
783 """
Alex Chan532b79e2017-01-24 15:14:52 +0000784 On Python 2 `Context.set_mode` accepts values of type `long` as well
785 as `int`.
Alex Gaynord3b5d9b2016-07-31 10:54:24 -0400786 """
787 context = Context(TLSv1_METHOD)
788 mode = context.set_mode(long(MODE_RELEASE_BUFFERS))
Alex Chan532b79e2017-01-24 15:14:52 +0000789 assert MODE_RELEASE_BUFFERS & mode
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400790
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400791 def test_set_timeout_wrong_args(self):
792 """
Alex Chan532b79e2017-01-24 15:14:52 +0000793 `Context.set_timeout` raises `TypeError` if called with
794 a non-`int` argument.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400795 """
796 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000797 with pytest.raises(TypeError):
798 context.set_timeout(None)
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400799
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400800 def test_timeout(self):
801 """
Alex Chan532b79e2017-01-24 15:14:52 +0000802 `Context.set_timeout` sets the session timeout for all connections
803 created using the context object. `Context.get_timeout` retrieves
804 this value.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400805 """
806 context = Context(TLSv1_METHOD)
807 context.set_timeout(1234)
Alex Chan532b79e2017-01-24 15:14:52 +0000808 assert context.get_timeout() == 1234
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400809
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200810 @skip_if_py3
811 def test_timeout_long(self):
812 """
Alex Chan532b79e2017-01-24 15:14:52 +0000813 On Python 2 `Context.set_timeout` accepts values of type `long` as
814 well as int.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200815 """
816 context = Context(TLSv1_METHOD)
817 context.set_timeout(long(1234))
Alex Chan532b79e2017-01-24 15:14:52 +0000818 assert context.get_timeout() == 1234
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500819
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400820 def test_set_verify_depth_wrong_args(self):
821 """
Alex Chan532b79e2017-01-24 15:14:52 +0000822 `Context.set_verify_depth` raises `TypeError` if called with a
823 non-`int` argument.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400824 """
825 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000826 with pytest.raises(TypeError):
827 context.set_verify_depth(None)
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400828
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400829 def test_verify_depth(self):
830 """
Alex Chan532b79e2017-01-24 15:14:52 +0000831 `Context.set_verify_depth` sets the number of certificates in
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200832 a chain to follow before giving up. The value can be retrieved with
Alex Chan532b79e2017-01-24 15:14:52 +0000833 `Context.get_verify_depth`.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400834 """
835 context = Context(TLSv1_METHOD)
836 context.set_verify_depth(11)
Alex Chan532b79e2017-01-24 15:14:52 +0000837 assert context.get_verify_depth() == 11
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400838
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200839 @skip_if_py3
840 def test_verify_depth_long(self):
841 """
Alex Chan532b79e2017-01-24 15:14:52 +0000842 On Python 2 `Context.set_verify_depth` accepts values of type `long`
843 as well as int.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200844 """
845 context = Context(TLSv1_METHOD)
846 context.set_verify_depth(long(11))
Alex Chan532b79e2017-01-24 15:14:52 +0000847 assert context.get_verify_depth() == 11
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500848
Alex Chan532b79e2017-01-24 15:14:52 +0000849 def _write_encrypted_pem(self, passphrase, tmpfile):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400850 """
851 Write a new private key out to a new file, encrypted using the given
852 passphrase. Return the path to the new file.
853 """
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400854 key = PKey()
855 key.generate_key(TYPE_RSA, 128)
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400856 pem = dump_privatekey(FILETYPE_PEM, key, "blowfish", passphrase)
Alex Chan532b79e2017-01-24 15:14:52 +0000857 with open(tmpfile, 'w') as fObj:
858 fObj.write(pem.decode('ascii'))
859 return tmpfile
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400860
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400861 def test_set_passwd_cb_wrong_args(self):
862 """
Alex Chan532b79e2017-01-24 15:14:52 +0000863 `Context.set_passwd_cb` raises `TypeError` if called with a
864 non-callable first argument.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400865 """
866 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000867 with pytest.raises(TypeError):
868 context.set_passwd_cb(None)
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400869
Alex Chan532b79e2017-01-24 15:14:52 +0000870 def test_set_passwd_cb(self, tmpfile):
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400871 """
Alex Chan532b79e2017-01-24 15:14:52 +0000872 `Context.set_passwd_cb` accepts a callable which will be invoked when
873 a private key is loaded from an encrypted PEM.
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400874 """
Alex Gaynore7f51982016-09-11 11:48:14 -0400875 passphrase = b"foobar"
Alex Chan532b79e2017-01-24 15:14:52 +0000876 pemFile = self._write_encrypted_pem(passphrase, tmpfile)
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400877 calledWith = []
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200878
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400879 def passphraseCallback(maxlen, verify, extra):
880 calledWith.append((maxlen, verify, extra))
881 return passphrase
882 context = Context(TLSv1_METHOD)
883 context.set_passwd_cb(passphraseCallback)
884 context.use_privatekey_file(pemFile)
Alex Chan532b79e2017-01-24 15:14:52 +0000885 assert len(calledWith) == 1
886 assert isinstance(calledWith[0][0], int)
887 assert isinstance(calledWith[0][1], int)
888 assert calledWith[0][2] is None
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400889
Alex Chan532b79e2017-01-24 15:14:52 +0000890 def test_passwd_callback_exception(self, tmpfile):
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400891 """
Alex Chan532b79e2017-01-24 15:14:52 +0000892 `Context.use_privatekey_file` propagates any exception raised
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200893 by the passphrase callback.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400894 """
Alex Chan532b79e2017-01-24 15:14:52 +0000895 pemFile = self._write_encrypted_pem(b"monkeys are nice", tmpfile)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200896
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400897 def passphraseCallback(maxlen, verify, extra):
898 raise RuntimeError("Sorry, I am a fail.")
899
900 context = Context(TLSv1_METHOD)
901 context.set_passwd_cb(passphraseCallback)
Alex Chan532b79e2017-01-24 15:14:52 +0000902 with pytest.raises(RuntimeError):
903 context.use_privatekey_file(pemFile)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400904
Alex Chan532b79e2017-01-24 15:14:52 +0000905 def test_passwd_callback_false(self, tmpfile):
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400906 """
Alex Chan532b79e2017-01-24 15:14:52 +0000907 `Context.use_privatekey_file` raises `OpenSSL.SSL.Error` if the
908 passphrase callback returns a false value.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400909 """
Alex Chan532b79e2017-01-24 15:14:52 +0000910 pemFile = self._write_encrypted_pem(b"monkeys are nice", tmpfile)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200911
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400912 def passphraseCallback(maxlen, verify, extra):
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500913 return b""
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400914
915 context = Context(TLSv1_METHOD)
916 context.set_passwd_cb(passphraseCallback)
Alex Chan532b79e2017-01-24 15:14:52 +0000917 with pytest.raises(Error):
918 context.use_privatekey_file(pemFile)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400919
Alex Chan532b79e2017-01-24 15:14:52 +0000920 def test_passwd_callback_non_string(self, tmpfile):
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400921 """
Alex Chan532b79e2017-01-24 15:14:52 +0000922 `Context.use_privatekey_file` raises `OpenSSL.SSL.Error` if the
923 passphrase callback returns a true non-string value.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400924 """
Alex Chan532b79e2017-01-24 15:14:52 +0000925 pemFile = self._write_encrypted_pem(b"monkeys are nice", tmpfile)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200926
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400927 def passphraseCallback(maxlen, verify, extra):
928 return 10
929
930 context = Context(TLSv1_METHOD)
931 context.set_passwd_cb(passphraseCallback)
Alex Chan532b79e2017-01-24 15:14:52 +0000932 # TODO: Surely this is the wrong error?
933 with pytest.raises(ValueError):
934 context.use_privatekey_file(pemFile)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400935
Alex Chan532b79e2017-01-24 15:14:52 +0000936 def test_passwd_callback_too_long(self, tmpfile):
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400937 """
938 If the passphrase returned by the passphrase callback returns a string
939 longer than the indicated maximum length, it is truncated.
940 """
941 # A priori knowledge!
Alex Gaynore7f51982016-09-11 11:48:14 -0400942 passphrase = b"x" * 1024
Alex Chan532b79e2017-01-24 15:14:52 +0000943 pemFile = self._write_encrypted_pem(passphrase, tmpfile)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200944
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400945 def passphraseCallback(maxlen, verify, extra):
946 assert maxlen == 1024
Alex Gaynore7f51982016-09-11 11:48:14 -0400947 return passphrase + b"y"
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400948
949 context = Context(TLSv1_METHOD)
950 context.set_passwd_cb(passphraseCallback)
951 # This shall succeed because the truncated result is the correct
952 # passphrase.
953 context.use_privatekey_file(pemFile)
954
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400955 def test_set_info_callback(self):
956 """
Alex Chan532b79e2017-01-24 15:14:52 +0000957 `Context.set_info_callback` accepts a callable which will be
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200958 invoked when certain information about an SSL connection is available.
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400959 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500960 (server, client) = socket_pair()
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400961
962 clientSSL = Connection(Context(TLSv1_METHOD), client)
963 clientSSL.set_connect_state()
964
965 called = []
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200966
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400967 def info(conn, where, ret):
968 called.append((conn, where, ret))
969 context = Context(TLSv1_METHOD)
970 context.set_info_callback(info)
971 context.use_certificate(
972 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
973 context.use_privatekey(
974 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
975
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400976 serverSSL = Connection(context, server)
977 serverSSL.set_accept_state()
978
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -0500979 handshake(clientSSL, serverSSL)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400980
Jean-Paul Calderone3835e522014-02-02 11:12:30 -0500981 # The callback must always be called with a Connection instance as the
982 # first argument. It would probably be better to split this into
983 # separate tests for client and server side info callbacks so we could
984 # assert it is called with the right Connection instance. It would
985 # also be good to assert *something* about `where` and `ret`.
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -0500986 notConnections = [
987 conn for (conn, where, ret) in called
988 if not isinstance(conn, Connection)]
Alex Chan532b79e2017-01-24 15:14:52 +0000989 assert [] == notConnections, (
990 "Some info callback arguments were not Connection instances.")
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400991
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400992 def _load_verify_locations_test(self, *args):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400993 """
994 Create a client context which will verify the peer certificate and call
Alex Chan532b79e2017-01-24 15:14:52 +0000995 its `load_verify_locations` method with the given arguments.
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -0400996 Then connect it to a server and ensure that the handshake succeeds.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400997 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500998 (server, client) = socket_pair()
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400999
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001000 clientContext = Context(TLSv1_METHOD)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001001 clientContext.load_verify_locations(*args)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001002 # Require that the server certificate verify properly or the
1003 # connection will fail.
1004 clientContext.set_verify(
1005 VERIFY_PEER,
1006 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
1007
1008 clientSSL = Connection(clientContext, client)
1009 clientSSL.set_connect_state()
1010
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001011 serverContext = Context(TLSv1_METHOD)
1012 serverContext.use_certificate(
1013 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1014 serverContext.use_privatekey(
1015 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1016
1017 serverSSL = Connection(serverContext, server)
1018 serverSSL.set_accept_state()
1019
Jean-Paul Calderonef8742032010-09-25 00:00:32 -04001020 # Without load_verify_locations above, the handshake
1021 # will fail:
1022 # Error: [('SSL routines', 'SSL3_GET_SERVER_CERTIFICATE',
1023 # 'certificate verify failed')]
1024 handshake(clientSSL, serverSSL)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001025
1026 cert = clientSSL.get_peer_certificate()
Alex Chan532b79e2017-01-24 15:14:52 +00001027 assert cert.get_subject().CN == 'Testing Root CA'
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -04001028
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001029 def _load_verify_cafile(self, cafile):
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001030 """
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001031 Verify that if path to a file containing a certificate is passed to
Alex Chan532b79e2017-01-24 15:14:52 +00001032 `Context.load_verify_locations` for the ``cafile`` parameter, that
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001033 certificate is used as a trust root for the purposes of verifying
Alex Chan532b79e2017-01-24 15:14:52 +00001034 connections created using that `Context`.
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001035 """
Alex Chan532b79e2017-01-24 15:14:52 +00001036 with open(cafile, 'w') as fObj:
1037 fObj.write(cleartextCertificatePEM.decode('ascii'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001038
1039 self._load_verify_locations_test(cafile)
1040
Alex Chan532b79e2017-01-24 15:14:52 +00001041 def test_load_verify_bytes_cafile(self, tmpfile):
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001042 """
Alex Chan532b79e2017-01-24 15:14:52 +00001043 `Context.load_verify_locations` accepts a file name as a `bytes`
1044 instance and uses the certificates within for verification purposes.
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001045 """
Alex Chan532b79e2017-01-24 15:14:52 +00001046 cafile = tmpfile + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001047 self._load_verify_cafile(cafile)
1048
Alex Chan532b79e2017-01-24 15:14:52 +00001049 def test_load_verify_unicode_cafile(self, tmpfile):
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001050 """
Alex Chan532b79e2017-01-24 15:14:52 +00001051 `Context.load_verify_locations` accepts a file name as a `unicode`
1052 instance and uses the certificates within for verification purposes.
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001053 """
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001054 self._load_verify_cafile(
Alex Chan532b79e2017-01-24 15:14:52 +00001055 tmpfile.decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001056 )
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001057
Alex Chan532b79e2017-01-24 15:14:52 +00001058 def test_load_verify_invalid_file(self, tmpfile):
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -04001059 """
Alex Chan532b79e2017-01-24 15:14:52 +00001060 `Context.load_verify_locations` raises `Error` when passed a
1061 non-existent cafile.
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -04001062 """
1063 clientContext = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001064 with pytest.raises(Error):
1065 clientContext.load_verify_locations(tmpfile)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001066
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001067 def _load_verify_directory_locations_capath(self, capath):
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001068 """
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001069 Verify that if path to a directory containing certificate files is
1070 passed to ``Context.load_verify_locations`` for the ``capath``
1071 parameter, those certificates are used as trust roots for the purposes
1072 of verifying connections created using that ``Context``.
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001073 """
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001074 makedirs(capath)
Jean-Paul Calderone24dfb332011-05-04 18:10:26 -04001075 # Hash values computed manually with c_rehash to avoid depending on
1076 # c_rehash in the test suite. One is from OpenSSL 0.9.8, the other
1077 # from OpenSSL 1.0.0.
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001078 for name in [b'c7adac82.0', b'c3705638.0']:
Jean-Paul Calderone05826732015-04-12 11:38:49 -04001079 cafile = join_bytes_or_unicode(capath, name)
1080 with open(cafile, 'w') as fObj:
1081 fObj.write(cleartextCertificatePEM.decode('ascii'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001082
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001083 self._load_verify_locations_test(None, capath)
1084
Alex Chan532b79e2017-01-24 15:14:52 +00001085 def test_load_verify_directory_bytes_capath(self, tmpfile):
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001086 """
Alex Chan532b79e2017-01-24 15:14:52 +00001087 `Context.load_verify_locations` accepts a directory name as a `bytes`
1088 instance and uses the certificates within for verification purposes.
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001089 """
1090 self._load_verify_directory_locations_capath(
Alex Chan532b79e2017-01-24 15:14:52 +00001091 tmpfile + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001092 )
1093
Alex Chan532b79e2017-01-24 15:14:52 +00001094 def test_load_verify_directory_unicode_capath(self, tmpfile):
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001095 """
Alex Chan532b79e2017-01-24 15:14:52 +00001096 `Context.load_verify_locations` accepts a directory name as a `unicode`
1097 instance and uses the certificates within for verification purposes.
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001098 """
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001099 self._load_verify_directory_locations_capath(
Alex Chan532b79e2017-01-24 15:14:52 +00001100 tmpfile.decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001101 )
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001102
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001103 def test_load_verify_locations_wrong_args(self):
1104 """
Alex Chan532b79e2017-01-24 15:14:52 +00001105 `Context.load_verify_locations` raises `TypeError` if with non-`str`
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001106 arguments.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001107 """
1108 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001109 with pytest.raises(TypeError):
1110 context.load_verify_locations(object())
1111 with pytest.raises(TypeError):
1112 context.load_verify_locations(object(), object())
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001113
Hynek Schlawack734d3022015-09-05 19:19:32 +02001114 @pytest.mark.skipif(
Paul Kehrer55fb3412017-06-29 18:44:08 -05001115 not platform.startswith("linux"),
1116 reason="Loading fallback paths is a linux-specific behavior to "
1117 "accommodate pyca/cryptography manylinux1 wheels"
1118 )
1119 def test_fallback_default_verify_paths(self, monkeypatch):
1120 """
1121 Test that we load certificates successfully on linux from the fallback
1122 path. To do this we set the _CRYPTOGRAPHY_MANYLINUX1_CA_FILE and
1123 _CRYPTOGRAPHY_MANYLINUX1_CA_DIR vars to be equal to whatever the
1124 current OpenSSL default is and we disable
1125 SSL_CTX_SET_default_verify_paths so that it can't find certs unless
1126 it loads via fallback.
1127 """
1128 context = Context(TLSv1_METHOD)
1129 monkeypatch.setattr(
1130 _lib, "SSL_CTX_set_default_verify_paths", lambda x: 1
1131 )
1132 monkeypatch.setattr(
1133 SSL,
1134 "_CRYPTOGRAPHY_MANYLINUX1_CA_FILE",
1135 _ffi.string(_lib.X509_get_default_cert_file())
1136 )
1137 monkeypatch.setattr(
1138 SSL,
1139 "_CRYPTOGRAPHY_MANYLINUX1_CA_DIR",
1140 _ffi.string(_lib.X509_get_default_cert_dir())
1141 )
1142 context.set_default_verify_paths()
1143 store = context.get_cert_store()
1144 sk_obj = _lib.X509_STORE_get0_objects(store._store)
1145 assert sk_obj != _ffi.NULL
1146 num = _lib.sk_X509_OBJECT_num(sk_obj)
1147 assert num != 0
1148
1149 def test_check_env_vars(self, monkeypatch):
1150 """
1151 Test that we return True/False appropriately if the env vars are set.
1152 """
1153 context = Context(TLSv1_METHOD)
1154 dir_var = "CUSTOM_DIR_VAR"
1155 file_var = "CUSTOM_FILE_VAR"
1156 assert context._check_env_vars_set(dir_var, file_var) is False
1157 monkeypatch.setenv(dir_var, "value")
1158 monkeypatch.setenv(file_var, "value")
1159 assert context._check_env_vars_set(dir_var, file_var) is True
1160 assert context._check_env_vars_set(dir_var, file_var) is True
1161
1162 def test_verify_no_fallback_if_env_vars_set(self, monkeypatch):
1163 """
1164 Test that we don't use the fallback path if env vars are set.
1165 """
1166 context = Context(TLSv1_METHOD)
1167 monkeypatch.setattr(
1168 _lib, "SSL_CTX_set_default_verify_paths", lambda x: 1
1169 )
1170 dir_env_var = _ffi.string(
1171 _lib.X509_get_default_cert_dir_env()
1172 ).decode("ascii")
1173 file_env_var = _ffi.string(
1174 _lib.X509_get_default_cert_file_env()
1175 ).decode("ascii")
1176 monkeypatch.setenv(dir_env_var, "value")
1177 monkeypatch.setenv(file_env_var, "value")
1178 context.set_default_verify_paths()
1179
1180 monkeypatch.setattr(
1181 context,
1182 "_fallback_default_verify_paths",
1183 raiser(SystemError)
1184 )
1185 context.set_default_verify_paths()
1186
1187 @pytest.mark.skipif(
Hynek Schlawack734d3022015-09-05 19:19:32 +02001188 platform == "win32",
1189 reason="set_default_verify_paths appears not to work on Windows. "
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -04001190 "See LP#404343 and LP#404344."
Hynek Schlawack734d3022015-09-05 19:19:32 +02001191 )
1192 def test_set_default_verify_paths(self):
1193 """
Alex Chan532b79e2017-01-24 15:14:52 +00001194 `Context.set_default_verify_paths` causes the platform-specific CA
1195 certificate locations to be used for verification purposes.
Hynek Schlawack734d3022015-09-05 19:19:32 +02001196 """
1197 # Testing this requires a server with a certificate signed by one
1198 # of the CAs in the platform CA location. Getting one of those
1199 # costs money. Fortunately (or unfortunately, depending on your
1200 # perspective), it's easy to think of a public server on the
1201 # internet which has such a certificate. Connecting to the network
1202 # in a unit test is bad, but it's the only way I can think of to
1203 # really test this. -exarkun
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001204
Hynek Schlawack734d3022015-09-05 19:19:32 +02001205 # Arg, verisign.com doesn't speak anything newer than TLS 1.0
Hynek Schlawackbf887932015-10-21 17:13:47 +02001206 context = Context(SSLv23_METHOD)
Hynek Schlawack734d3022015-09-05 19:19:32 +02001207 context.set_default_verify_paths()
1208 context.set_verify(
1209 VERIFY_PEER,
1210 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001211
Hynek Schlawack734d3022015-09-05 19:19:32 +02001212 client = socket()
Hynek Schlawackbf887932015-10-21 17:13:47 +02001213 client.connect(("encrypted.google.com", 443))
Hynek Schlawack734d3022015-09-05 19:19:32 +02001214 clientSSL = Connection(context, client)
1215 clientSSL.set_connect_state()
1216 clientSSL.do_handshake()
1217 clientSSL.send(b"GET / HTTP/1.0\r\n\r\n")
Alex Chan532b79e2017-01-24 15:14:52 +00001218 assert clientSSL.recv(1024)
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05001219
Paul Kehrer55fb3412017-06-29 18:44:08 -05001220 def test_fallback_path_is_not_file_or_dir(self):
1221 """
1222 Test that when passed empty arrays or paths that do not exist no
1223 errors are raised.
1224 """
1225 context = Context(TLSv1_METHOD)
1226 context._fallback_default_verify_paths([], [])
1227 context._fallback_default_verify_paths(
1228 ["/not/a/file"], ["/not/a/dir"]
1229 )
1230
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001231 def test_add_extra_chain_cert_invalid_cert(self):
1232 """
Alex Chan532b79e2017-01-24 15:14:52 +00001233 `Context.add_extra_chain_cert` raises `TypeError` if called with an
1234 object which is not an instance of `X509`.
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001235 """
1236 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001237 with pytest.raises(TypeError):
1238 context.add_extra_chain_cert(object())
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001239
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001240 def _handshake_test(self, serverContext, clientContext):
1241 """
1242 Verify that a client and server created with the given contexts can
1243 successfully handshake and communicate.
1244 """
1245 serverSocket, clientSocket = socket_pair()
1246
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001247 server = Connection(serverContext, serverSocket)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001248 server.set_accept_state()
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001249
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001250 client = Connection(clientContext, clientSocket)
1251 client.set_connect_state()
1252
1253 # Make them talk to each other.
Alex Chan532b79e2017-01-24 15:14:52 +00001254 # interact_in_memory(client, server)
1255 for _ in range(3):
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001256 for s in [client, server]:
1257 try:
1258 s.do_handshake()
1259 except WantReadError:
1260 pass
1261
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001262 def test_set_verify_callback_connection_argument(self):
1263 """
1264 The first argument passed to the verify callback is the
Alex Chan532b79e2017-01-24 15:14:52 +00001265 `Connection` instance for which verification is taking place.
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001266 """
1267 serverContext = Context(TLSv1_METHOD)
1268 serverContext.use_privatekey(
1269 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1270 serverContext.use_certificate(
1271 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1272 serverConnection = Connection(serverContext, None)
1273
1274 class VerifyCallback(object):
1275 def callback(self, connection, *args):
1276 self.connection = connection
1277 return 1
1278
1279 verify = VerifyCallback()
1280 clientContext = Context(TLSv1_METHOD)
1281 clientContext.set_verify(VERIFY_PEER, verify.callback)
1282 clientConnection = Connection(clientContext, None)
1283 clientConnection.set_connect_state()
1284
Alex Chan532b79e2017-01-24 15:14:52 +00001285 handshake_in_memory(clientConnection, serverConnection)
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001286
Alex Chan532b79e2017-01-24 15:14:52 +00001287 assert verify.connection is clientConnection
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001288
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001289 def test_set_verify_callback_exception(self):
1290 """
Alex Chan532b79e2017-01-24 15:14:52 +00001291 If the verify callback passed to `Context.set_verify` raises an
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001292 exception, verification fails and the exception is propagated to the
Alex Chan532b79e2017-01-24 15:14:52 +00001293 caller of `Connection.do_handshake`.
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001294 """
1295 serverContext = Context(TLSv1_METHOD)
1296 serverContext.use_privatekey(
1297 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1298 serverContext.use_certificate(
1299 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1300
1301 clientContext = Context(TLSv1_METHOD)
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001302
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001303 def verify_callback(*args):
1304 raise Exception("silly verify failure")
1305 clientContext.set_verify(VERIFY_PEER, verify_callback)
1306
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01001307 with pytest.raises(Exception) as exc:
1308 self._handshake_test(serverContext, clientContext)
1309
Alex Chan532b79e2017-01-24 15:14:52 +00001310 assert "silly verify failure" == str(exc.value)
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001311
Alex Chan532b79e2017-01-24 15:14:52 +00001312 def test_add_extra_chain_cert(self, tmpdir):
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001313 """
Alex Chan532b79e2017-01-24 15:14:52 +00001314 `Context.add_extra_chain_cert` accepts an `X509`
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001315 instance to add to the certificate chain.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001316
Alex Chan532b79e2017-01-24 15:14:52 +00001317 See `_create_certificate_chain` for the details of the
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001318 certificate chain tested.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001319
1320 The chain is tested by starting a server with scert and connecting
1321 to it with a client which trusts cacert and requires verification to
1322 succeed.
1323 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001324 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001325 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1326
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001327 # Dump the CA certificate to a file because that's the only way to load
1328 # it as a trusted CA in the client context.
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001329 for cert, name in [(cacert, 'ca.pem'),
1330 (icert, 'i.pem'),
1331 (scert, 's.pem')]:
Alex Chan532b79e2017-01-24 15:14:52 +00001332 with tmpdir.join(name).open('w') as f:
Hynek Schlawacke90680f2015-04-16 15:09:27 -04001333 f.write(dump_certificate(FILETYPE_PEM, cert).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001334
Hynek Schlawack1902c012015-04-16 15:06:41 -04001335 for key, name in [(cakey, 'ca.key'),
1336 (ikey, 'i.key'),
1337 (skey, 's.key')]:
Alex Chan532b79e2017-01-24 15:14:52 +00001338 with tmpdir.join(name).open('w') as f:
Hynek Schlawacke90680f2015-04-16 15:09:27 -04001339 f.write(dump_privatekey(FILETYPE_PEM, key).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001340
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001341 # Create the server context
1342 serverContext = Context(TLSv1_METHOD)
1343 serverContext.use_privatekey(skey)
1344 serverContext.use_certificate(scert)
Jean-Paul Calderone16cf03d2010-09-08 18:53:39 -04001345 # The client already has cacert, we only need to give them icert.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001346 serverContext.add_extra_chain_cert(icert)
1347
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001348 # Create the client
1349 clientContext = Context(TLSv1_METHOD)
1350 clientContext.set_verify(
1351 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Alex Chan532b79e2017-01-24 15:14:52 +00001352 clientContext.load_verify_locations(str(tmpdir.join("ca.pem")))
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001353
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001354 # Try it out.
1355 self._handshake_test(serverContext, clientContext)
1356
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001357 def _use_certificate_chain_file_test(self, certdir):
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001358 """
Alex Chan532b79e2017-01-24 15:14:52 +00001359 Verify that `Context.use_certificate_chain_file` reads a
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001360 certificate chain from a specified file.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001361
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001362 The chain is tested by starting a server with scert and connecting to
1363 it with a client which trusts cacert and requires verification to
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001364 succeed.
1365 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001366 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001367 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1368
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001369 makedirs(certdir)
1370
Jean-Paul Calderone05826732015-04-12 11:38:49 -04001371 chainFile = join_bytes_or_unicode(certdir, "chain.pem")
1372 caFile = join_bytes_or_unicode(certdir, "ca.pem")
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001373
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001374 # Write out the chain file.
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001375 with open(chainFile, 'wb') as fObj:
1376 # Most specific to least general.
1377 fObj.write(dump_certificate(FILETYPE_PEM, scert))
1378 fObj.write(dump_certificate(FILETYPE_PEM, icert))
1379 fObj.write(dump_certificate(FILETYPE_PEM, cacert))
1380
1381 with open(caFile, 'w') as fObj:
1382 fObj.write(dump_certificate(FILETYPE_PEM, cacert).decode('ascii'))
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001383
1384 serverContext = Context(TLSv1_METHOD)
1385 serverContext.use_certificate_chain_file(chainFile)
1386 serverContext.use_privatekey(skey)
1387
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001388 clientContext = Context(TLSv1_METHOD)
1389 clientContext.set_verify(
1390 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001391 clientContext.load_verify_locations(caFile)
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001392
1393 self._handshake_test(serverContext, clientContext)
1394
Alex Chan532b79e2017-01-24 15:14:52 +00001395 def test_use_certificate_chain_file_bytes(self, tmpfile):
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001396 """
1397 ``Context.use_certificate_chain_file`` accepts the name of a file (as
1398 an instance of ``bytes``) to specify additional certificates to use to
1399 construct and verify a trust chain.
1400 """
1401 self._use_certificate_chain_file_test(
Alex Chan532b79e2017-01-24 15:14:52 +00001402 tmpfile + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001403 )
1404
Alex Chan532b79e2017-01-24 15:14:52 +00001405 def test_use_certificate_chain_file_unicode(self, tmpfile):
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001406 """
1407 ``Context.use_certificate_chain_file`` accepts the name of a file (as
1408 an instance of ``unicode``) to specify additional certificates to use
1409 to construct and verify a trust chain.
1410 """
1411 self._use_certificate_chain_file_test(
Alex Chan532b79e2017-01-24 15:14:52 +00001412 tmpfile.decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001413 )
1414
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001415 def test_use_certificate_chain_file_wrong_args(self):
1416 """
Alex Chan532b79e2017-01-24 15:14:52 +00001417 `Context.use_certificate_chain_file` raises `TypeError` if passed a
1418 non-byte string single argument.
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001419 """
1420 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001421 with pytest.raises(TypeError):
1422 context.use_certificate_chain_file(object())
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001423
Alex Chan532b79e2017-01-24 15:14:52 +00001424 def test_use_certificate_chain_file_missing_file(self, tmpfile):
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001425 """
Alex Chan532b79e2017-01-24 15:14:52 +00001426 `Context.use_certificate_chain_file` raises `OpenSSL.SSL.Error` when
1427 passed a bad chain file name (for example, the name of a file which
1428 does not exist).
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001429 """
1430 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001431 with pytest.raises(Error):
1432 context.use_certificate_chain_file(tmpfile)
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001433
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001434 def test_set_verify_mode(self):
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001435 """
Alex Chan532b79e2017-01-24 15:14:52 +00001436 `Context.get_verify_mode` returns the verify mode flags previously
1437 passed to `Context.set_verify`.
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001438 """
1439 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001440 assert context.get_verify_mode() == 0
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001441 context.set_verify(
1442 VERIFY_PEER | VERIFY_CLIENT_ONCE, lambda *args: None)
Alex Chan532b79e2017-01-24 15:14:52 +00001443 assert context.get_verify_mode() == (VERIFY_PEER | VERIFY_CLIENT_ONCE)
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001444
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001445 @skip_if_py3
1446 def test_set_verify_mode_long(self):
1447 """
Alex Chan532b79e2017-01-24 15:14:52 +00001448 On Python 2 `Context.set_verify_mode` accepts values of type `long`
1449 as well as `int`.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001450 """
1451 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001452 assert context.get_verify_mode() == 0
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001453 context.set_verify(
Hynek Schlawackb4ceed32015-09-05 20:55:19 +02001454 long(VERIFY_PEER | VERIFY_CLIENT_ONCE), lambda *args: None
1455 ) # pragma: nocover
Alex Chan532b79e2017-01-24 15:14:52 +00001456 assert context.get_verify_mode() == (VERIFY_PEER | VERIFY_CLIENT_ONCE)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001457
Alex Chanfb078d82017-04-20 11:16:15 +01001458 @pytest.mark.parametrize('mode', [None, 1.0, object(), 'mode'])
1459 def test_set_verify_wrong_mode_arg(self, mode):
1460 """
1461 `Context.set_verify` raises `TypeError` if the first argument is
1462 not an integer.
1463 """
1464 context = Context(TLSv1_METHOD)
1465 with pytest.raises(TypeError):
1466 context.set_verify(mode=mode, callback=lambda *args: None)
1467
1468 @pytest.mark.parametrize('callback', [None, 1.0, 'mode', ('foo', 'bar')])
1469 def test_set_verify_wrong_callable_arg(self, callback):
1470 """
1471 `Context.set_verify` raises `TypeError` if the the second argument
1472 is not callable.
1473 """
1474 context = Context(TLSv1_METHOD)
1475 with pytest.raises(TypeError):
1476 context.set_verify(mode=VERIFY_PEER, callback=callback)
1477
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001478 def test_load_tmp_dh_wrong_args(self):
1479 """
Alex Chan532b79e2017-01-24 15:14:52 +00001480 `Context.load_tmp_dh` raises `TypeError` if called with a
1481 non-`str` argument.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001482 """
1483 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001484 with pytest.raises(TypeError):
1485 context.load_tmp_dh(object())
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001486
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001487 def test_load_tmp_dh_missing_file(self):
1488 """
Alex Chan532b79e2017-01-24 15:14:52 +00001489 `Context.load_tmp_dh` raises `OpenSSL.SSL.Error` if the
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001490 specified file does not exist.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001491 """
1492 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001493 with pytest.raises(Error):
1494 context.load_tmp_dh(b"hello")
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001495
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001496 def _load_tmp_dh_test(self, dhfilename):
Jean-Paul Calderone4e0c43f2015-04-13 10:15:17 -04001497 """
1498 Verify that calling ``Context.load_tmp_dh`` with the given filename
1499 does not raise an exception.
1500 """
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001501 context = Context(TLSv1_METHOD)
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001502 with open(dhfilename, "w") as dhfile:
1503 dhfile.write(dhparam)
1504
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001505 context.load_tmp_dh(dhfilename)
1506 # XXX What should I assert here? -exarkun
1507
Alex Chan532b79e2017-01-24 15:14:52 +00001508 def test_load_tmp_dh_bytes(self, tmpfile):
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001509 """
Alex Chan532b79e2017-01-24 15:14:52 +00001510 `Context.load_tmp_dh` loads Diffie-Hellman parameters from the
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001511 specified file (given as ``bytes``).
1512 """
1513 self._load_tmp_dh_test(
Alex Chan532b79e2017-01-24 15:14:52 +00001514 tmpfile + NON_ASCII.encode(getfilesystemencoding()),
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001515 )
1516
Alex Chan532b79e2017-01-24 15:14:52 +00001517 def test_load_tmp_dh_unicode(self, tmpfile):
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001518 """
Alex Chan532b79e2017-01-24 15:14:52 +00001519 `Context.load_tmp_dh` loads Diffie-Hellman parameters from the
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001520 specified file (given as ``unicode``).
1521 """
1522 self._load_tmp_dh_test(
Alex Chan532b79e2017-01-24 15:14:52 +00001523 tmpfile.decode(getfilesystemencoding()) + NON_ASCII,
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001524 )
1525
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001526 def test_set_tmp_ecdh(self):
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001527 """
Alex Chan532b79e2017-01-24 15:14:52 +00001528 `Context.set_tmp_ecdh` sets the elliptic curve for Diffie-Hellman to
1529 the specified curve.
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001530 """
1531 context = Context(TLSv1_METHOD)
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001532 for curve in get_elliptic_curves():
Hynek Schlawacka07fa8c2015-10-17 10:15:28 +02001533 if curve.name.startswith(u"Oakley-"):
Hynek Schlawack7408aff2015-10-17 09:51:16 +02001534 # Setting Oakley-EC2N-4 and Oakley-EC2N-3 adds
1535 # ('bignum routines', 'BN_mod_inverse', 'no inverse') to the
1536 # error queue on OpenSSL 1.0.2.
1537 continue
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001538 # The only easily "assertable" thing is that it does not raise an
1539 # exception.
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001540 context.set_tmp_ecdh(curve)
Alex Gaynor12dc0842014-01-17 12:51:31 -06001541
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001542 def test_set_session_cache_mode_wrong_args(self):
1543 """
Alex Chan532b79e2017-01-24 15:14:52 +00001544 `Context.set_session_cache_mode` raises `TypeError` if called with
1545 a non-integer argument.
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001546 called with other than one integer argument.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001547 """
1548 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001549 with pytest.raises(TypeError):
1550 context.set_session_cache_mode(object())
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001551
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001552 def test_session_cache_mode(self):
1553 """
Alex Chan532b79e2017-01-24 15:14:52 +00001554 `Context.set_session_cache_mode` specifies how sessions are cached.
1555 The setting can be retrieved via `Context.get_session_cache_mode`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001556 """
1557 context = Context(TLSv1_METHOD)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001558 context.set_session_cache_mode(SESS_CACHE_OFF)
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001559 off = context.set_session_cache_mode(SESS_CACHE_BOTH)
Alex Chan532b79e2017-01-24 15:14:52 +00001560 assert SESS_CACHE_OFF == off
1561 assert SESS_CACHE_BOTH == context.get_session_cache_mode()
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001562
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001563 @skip_if_py3
1564 def test_session_cache_mode_long(self):
1565 """
Alex Chan532b79e2017-01-24 15:14:52 +00001566 On Python 2 `Context.set_session_cache_mode` accepts values
1567 of type `long` as well as `int`.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001568 """
1569 context = Context(TLSv1_METHOD)
1570 context.set_session_cache_mode(long(SESS_CACHE_BOTH))
Alex Chan532b79e2017-01-24 15:14:52 +00001571 assert SESS_CACHE_BOTH == context.get_session_cache_mode()
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001572
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001573 def test_get_cert_store(self):
1574 """
Alex Chan532b79e2017-01-24 15:14:52 +00001575 `Context.get_cert_store` returns a `X509Store` instance.
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001576 """
1577 context = Context(TLSv1_METHOD)
1578 store = context.get_cert_store()
Alex Chan532b79e2017-01-24 15:14:52 +00001579 assert isinstance(store, X509Store)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001580
1581
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001582class TestServerNameCallback(object):
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001583 """
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001584 Tests for `Context.set_tlsext_servername_callback` and its
1585 interaction with `Connection`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001586 """
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001587 def test_old_callback_forgotten(self):
1588 """
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001589 If `Context.set_tlsext_servername_callback` is used to specify
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001590 a new callback, the one it replaces is dereferenced.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001591 """
Alex Chanfb078d82017-04-20 11:16:15 +01001592 def callback(connection): # pragma: no cover
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001593 pass
1594
Alex Chanfb078d82017-04-20 11:16:15 +01001595 def replacement(connection): # pragma: no cover
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001596 pass
1597
1598 context = Context(TLSv1_METHOD)
1599 context.set_tlsext_servername_callback(callback)
1600
1601 tracker = ref(callback)
1602 del callback
1603
1604 context.set_tlsext_servername_callback(replacement)
Jean-Paul Calderoned4033eb2014-01-11 08:21:46 -05001605
1606 # One run of the garbage collector happens to work on CPython. PyPy
1607 # doesn't collect the underlying object until a second run for whatever
1608 # reason. That's fine, it still demonstrates our code has properly
1609 # dropped the reference.
1610 collect()
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001611 collect()
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001612
1613 callback = tracker()
1614 if callback is not None:
1615 referrers = get_referrers(callback)
Alex Chanfb078d82017-04-20 11:16:15 +01001616 if len(referrers) > 1: # pragma: nocover
1617 pytest.fail("Some references remain: %r" % (referrers,))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001618
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001619 def test_no_servername(self):
1620 """
1621 When a client specifies no server name, the callback passed to
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001622 `Context.set_tlsext_servername_callback` is invoked and the
1623 result of `Connection.get_servername` is `None`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001624 """
1625 args = []
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001626
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001627 def servername(conn):
1628 args.append((conn, conn.get_servername()))
1629 context = Context(TLSv1_METHOD)
1630 context.set_tlsext_servername_callback(servername)
1631
1632 # Lose our reference to it. The Context is responsible for keeping it
1633 # alive now.
1634 del servername
1635 collect()
1636
1637 # Necessary to actually accept the connection
1638 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001639 context.use_certificate(
1640 load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001641
1642 # Do a little connection to trigger the logic
1643 server = Connection(context, None)
1644 server.set_accept_state()
1645
1646 client = Connection(Context(TLSv1_METHOD), None)
1647 client.set_connect_state()
1648
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001649 interact_in_memory(server, client)
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001650
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001651 assert args == [(server, None)]
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001652
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001653 def test_servername(self):
1654 """
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001655 When a client specifies a server name in its hello message, the
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001656 callback passed to `Contexts.set_tlsext_servername_callback` is
1657 invoked and the result of `Connection.get_servername` is that
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001658 server name.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001659 """
1660 args = []
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001661
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001662 def servername(conn):
1663 args.append((conn, conn.get_servername()))
1664 context = Context(TLSv1_METHOD)
1665 context.set_tlsext_servername_callback(servername)
1666
1667 # Necessary to actually accept the connection
1668 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001669 context.use_certificate(
1670 load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001671
1672 # Do a little connection to trigger the logic
1673 server = Connection(context, None)
1674 server.set_accept_state()
1675
1676 client = Connection(Context(TLSv1_METHOD), None)
1677 client.set_connect_state()
Alex Gaynore7f51982016-09-11 11:48:14 -04001678 client.set_tlsext_host_name(b"foo1.example.com")
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001679
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001680 interact_in_memory(server, client)
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001681
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001682 assert args == [(server, b"foo1.example.com")]
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001683
1684
Alex Chan9e08b3e2016-11-10 12:18:54 +00001685class TestNextProtoNegotiation(object):
Cory Benfield84a121e2014-03-31 20:30:25 +01001686 """
1687 Test for Next Protocol Negotiation in PyOpenSSL.
1688 """
Alex Chan9e08b3e2016-11-10 12:18:54 +00001689 def test_npn_success(self):
1690 """
1691 Tests that clients and servers that agree on the negotiated next
1692 protocol can correct establish a connection, and that the agreed
1693 protocol is reported by the connections.
1694 """
1695 advertise_args = []
1696 select_args = []
1697
1698 def advertise(conn):
1699 advertise_args.append((conn,))
1700 return [b'http/1.1', b'spdy/2']
1701
1702 def select(conn, options):
1703 select_args.append((conn, options))
1704 return b'spdy/2'
1705
1706 server_context = Context(TLSv1_METHOD)
1707 server_context.set_npn_advertise_callback(advertise)
1708
1709 client_context = Context(TLSv1_METHOD)
1710 client_context.set_npn_select_callback(select)
1711
1712 # Necessary to actually accept the connection
1713 server_context.use_privatekey(
1714 load_privatekey(FILETYPE_PEM, server_key_pem))
1715 server_context.use_certificate(
1716 load_certificate(FILETYPE_PEM, server_cert_pem))
1717
1718 # Do a little connection to trigger the logic
1719 server = Connection(server_context, None)
1720 server.set_accept_state()
1721
1722 client = Connection(client_context, None)
1723 client.set_connect_state()
1724
1725 interact_in_memory(server, client)
1726
1727 assert advertise_args == [(server,)]
1728 assert select_args == [(client, [b'http/1.1', b'spdy/2'])]
1729
1730 assert server.get_next_proto_negotiated() == b'spdy/2'
1731 assert client.get_next_proto_negotiated() == b'spdy/2'
1732
1733 def test_npn_client_fail(self):
1734 """
1735 Tests that when clients and servers cannot agree on what protocol
1736 to use next that the TLS connection does not get established.
1737 """
1738 advertise_args = []
1739 select_args = []
1740
1741 def advertise(conn):
1742 advertise_args.append((conn,))
1743 return [b'http/1.1', b'spdy/2']
1744
1745 def select(conn, options):
1746 select_args.append((conn, options))
1747 return b''
1748
1749 server_context = Context(TLSv1_METHOD)
1750 server_context.set_npn_advertise_callback(advertise)
1751
1752 client_context = Context(TLSv1_METHOD)
1753 client_context.set_npn_select_callback(select)
1754
1755 # Necessary to actually accept the connection
1756 server_context.use_privatekey(
1757 load_privatekey(FILETYPE_PEM, server_key_pem))
1758 server_context.use_certificate(
1759 load_certificate(FILETYPE_PEM, server_cert_pem))
1760
1761 # Do a little connection to trigger the logic
1762 server = Connection(server_context, None)
1763 server.set_accept_state()
1764
1765 client = Connection(client_context, None)
1766 client.set_connect_state()
1767
1768 # If the client doesn't return anything, the connection will fail.
1769 with pytest.raises(Error):
1770 interact_in_memory(server, client)
1771
1772 assert advertise_args == [(server,)]
1773 assert select_args == [(client, [b'http/1.1', b'spdy/2'])]
1774
1775 def test_npn_select_error(self):
1776 """
1777 Test that we can handle exceptions in the select callback. If
1778 select fails it should be fatal to the connection.
1779 """
1780 advertise_args = []
1781
1782 def advertise(conn):
1783 advertise_args.append((conn,))
1784 return [b'http/1.1', b'spdy/2']
1785
1786 def select(conn, options):
1787 raise TypeError
1788
1789 server_context = Context(TLSv1_METHOD)
1790 server_context.set_npn_advertise_callback(advertise)
1791
1792 client_context = Context(TLSv1_METHOD)
1793 client_context.set_npn_select_callback(select)
1794
1795 # Necessary to actually accept the connection
1796 server_context.use_privatekey(
1797 load_privatekey(FILETYPE_PEM, server_key_pem))
1798 server_context.use_certificate(
1799 load_certificate(FILETYPE_PEM, server_cert_pem))
1800
1801 # Do a little connection to trigger the logic
1802 server = Connection(server_context, None)
1803 server.set_accept_state()
1804
1805 client = Connection(client_context, None)
1806 client.set_connect_state()
1807
1808 # If the callback throws an exception it should be raised here.
1809 with pytest.raises(TypeError):
1810 interact_in_memory(server, client)
1811 assert advertise_args == [(server,), ]
1812
1813 def test_npn_advertise_error(self):
1814 """
1815 Test that we can handle exceptions in the advertise callback. If
1816 advertise fails no NPN is advertised to the client.
1817 """
1818 select_args = []
1819
1820 def advertise(conn):
1821 raise TypeError
1822
1823 def select(conn, options): # pragma: nocover
Cory Benfieldba1820d2015-04-13 17:39:12 -04001824 """
Alex Chan9e08b3e2016-11-10 12:18:54 +00001825 Assert later that no args are actually appended.
Cory Benfieldba1820d2015-04-13 17:39:12 -04001826 """
Alex Chan9e08b3e2016-11-10 12:18:54 +00001827 select_args.append((conn, options))
1828 return b''
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001829
Alex Chan9e08b3e2016-11-10 12:18:54 +00001830 server_context = Context(TLSv1_METHOD)
1831 server_context.set_npn_advertise_callback(advertise)
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001832
Alex Chan9e08b3e2016-11-10 12:18:54 +00001833 client_context = Context(TLSv1_METHOD)
1834 client_context.set_npn_select_callback(select)
Cory Benfield84a121e2014-03-31 20:30:25 +01001835
Alex Chan9e08b3e2016-11-10 12:18:54 +00001836 # Necessary to actually accept the connection
1837 server_context.use_privatekey(
1838 load_privatekey(FILETYPE_PEM, server_key_pem))
1839 server_context.use_certificate(
1840 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield84a121e2014-03-31 20:30:25 +01001841
Alex Chan9e08b3e2016-11-10 12:18:54 +00001842 # Do a little connection to trigger the logic
1843 server = Connection(server_context, None)
1844 server.set_accept_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001845
Alex Chan9e08b3e2016-11-10 12:18:54 +00001846 client = Connection(client_context, None)
1847 client.set_connect_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001848
Alex Chan9e08b3e2016-11-10 12:18:54 +00001849 # If the client doesn't return anything, the connection will fail.
1850 with pytest.raises(TypeError):
1851 interact_in_memory(server, client)
1852 assert select_args == []
Cory Benfield0ea76e72015-03-22 09:05:28 +00001853
1854
Alex Chanec1e32d2016-11-10 14:11:45 +00001855class TestApplicationLayerProtoNegotiation(object):
Cory Benfield12eae892014-06-07 15:42:56 +01001856 """
1857 Tests for ALPN in PyOpenSSL.
1858 """
Cory Benfielde46fa842015-04-13 16:50:49 -04001859 # Skip tests on versions that don't support ALPN.
1860 if _lib.Cryptography_HAS_ALPN:
Cory Benfield12eae892014-06-07 15:42:56 +01001861
Cory Benfielde46fa842015-04-13 16:50:49 -04001862 def test_alpn_success(self):
1863 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04001864 Clients and servers that agree on the negotiated ALPN protocol can
1865 correct establish a connection, and the agreed protocol is reported
1866 by the connections.
Cory Benfielde46fa842015-04-13 16:50:49 -04001867 """
1868 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001869
Cory Benfielde46fa842015-04-13 16:50:49 -04001870 def select(conn, options):
1871 select_args.append((conn, options))
1872 return b'spdy/2'
Cory Benfield12eae892014-06-07 15:42:56 +01001873
Cory Benfielde46fa842015-04-13 16:50:49 -04001874 client_context = Context(TLSv1_METHOD)
1875 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfield12eae892014-06-07 15:42:56 +01001876
Cory Benfielde46fa842015-04-13 16:50:49 -04001877 server_context = Context(TLSv1_METHOD)
1878 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01001879
Cory Benfielde46fa842015-04-13 16:50:49 -04001880 # Necessary to actually accept the connection
1881 server_context.use_privatekey(
1882 load_privatekey(FILETYPE_PEM, server_key_pem))
1883 server_context.use_certificate(
1884 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield12eae892014-06-07 15:42:56 +01001885
Cory Benfielde46fa842015-04-13 16:50:49 -04001886 # Do a little connection to trigger the logic
1887 server = Connection(server_context, None)
1888 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001889
Cory Benfielde46fa842015-04-13 16:50:49 -04001890 client = Connection(client_context, None)
1891 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001892
Alex Chanec1e32d2016-11-10 14:11:45 +00001893 interact_in_memory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001894
Alex Chanec1e32d2016-11-10 14:11:45 +00001895 assert select_args == [(server, [b'http/1.1', b'spdy/2'])]
Cory Benfielde46fa842015-04-13 16:50:49 -04001896
Alex Chanec1e32d2016-11-10 14:11:45 +00001897 assert server.get_alpn_proto_negotiated() == b'spdy/2'
1898 assert client.get_alpn_proto_negotiated() == b'spdy/2'
Cory Benfield12eae892014-06-07 15:42:56 +01001899
Cory Benfielde46fa842015-04-13 16:50:49 -04001900 def test_alpn_set_on_connection(self):
1901 """
1902 The same as test_alpn_success, but setting the ALPN protocols on
1903 the connection rather than the context.
1904 """
1905 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001906
Cory Benfielde46fa842015-04-13 16:50:49 -04001907 def select(conn, options):
1908 select_args.append((conn, options))
1909 return b'spdy/2'
Cory Benfield12eae892014-06-07 15:42:56 +01001910
Cory Benfielde46fa842015-04-13 16:50:49 -04001911 # Setup the client context but don't set any ALPN protocols.
1912 client_context = Context(TLSv1_METHOD)
Cory Benfield12eae892014-06-07 15:42:56 +01001913
Cory Benfielde46fa842015-04-13 16:50:49 -04001914 server_context = Context(TLSv1_METHOD)
1915 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01001916
Cory Benfielde46fa842015-04-13 16:50:49 -04001917 # Necessary to actually accept the connection
1918 server_context.use_privatekey(
1919 load_privatekey(FILETYPE_PEM, server_key_pem))
1920 server_context.use_certificate(
1921 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield12eae892014-06-07 15:42:56 +01001922
Cory Benfielde46fa842015-04-13 16:50:49 -04001923 # Do a little connection to trigger the logic
1924 server = Connection(server_context, None)
1925 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001926
Cory Benfielde46fa842015-04-13 16:50:49 -04001927 # Set the ALPN protocols on the client connection.
1928 client = Connection(client_context, None)
1929 client.set_alpn_protos([b'http/1.1', b'spdy/2'])
1930 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001931
Alex Chanec1e32d2016-11-10 14:11:45 +00001932 interact_in_memory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001933
Alex Chanec1e32d2016-11-10 14:11:45 +00001934 assert select_args == [(server, [b'http/1.1', b'spdy/2'])]
Cory Benfield12eae892014-06-07 15:42:56 +01001935
Alex Chanec1e32d2016-11-10 14:11:45 +00001936 assert server.get_alpn_proto_negotiated() == b'spdy/2'
1937 assert client.get_alpn_proto_negotiated() == b'spdy/2'
Cory Benfield12eae892014-06-07 15:42:56 +01001938
Cory Benfielde46fa842015-04-13 16:50:49 -04001939 def test_alpn_server_fail(self):
1940 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04001941 When clients and servers cannot agree on what protocol to use next
1942 the TLS connection does not get established.
Cory Benfielde46fa842015-04-13 16:50:49 -04001943 """
1944 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001945
Cory Benfielde46fa842015-04-13 16:50:49 -04001946 def select(conn, options):
1947 select_args.append((conn, options))
1948 return b''
Cory Benfield12eae892014-06-07 15:42:56 +01001949
Cory Benfielde46fa842015-04-13 16:50:49 -04001950 client_context = Context(TLSv1_METHOD)
1951 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfield12eae892014-06-07 15:42:56 +01001952
Cory Benfielde46fa842015-04-13 16:50:49 -04001953 server_context = Context(TLSv1_METHOD)
1954 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01001955
Cory Benfielde46fa842015-04-13 16:50:49 -04001956 # Necessary to actually accept the connection
1957 server_context.use_privatekey(
1958 load_privatekey(FILETYPE_PEM, server_key_pem))
1959 server_context.use_certificate(
1960 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield12eae892014-06-07 15:42:56 +01001961
Cory Benfielde46fa842015-04-13 16:50:49 -04001962 # Do a little connection to trigger the logic
1963 server = Connection(server_context, None)
1964 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001965
Cory Benfielde46fa842015-04-13 16:50:49 -04001966 client = Connection(client_context, None)
1967 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001968
Cory Benfielde46fa842015-04-13 16:50:49 -04001969 # If the client doesn't return anything, the connection will fail.
Alex Chanec1e32d2016-11-10 14:11:45 +00001970 with pytest.raises(Error):
1971 interact_in_memory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001972
Alex Chanec1e32d2016-11-10 14:11:45 +00001973 assert select_args == [(server, [b'http/1.1', b'spdy/2'])]
Cory Benfield12eae892014-06-07 15:42:56 +01001974
Cory Benfielde46fa842015-04-13 16:50:49 -04001975 def test_alpn_no_server(self):
1976 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04001977 When clients and servers cannot agree on what protocol to use next
1978 because the server doesn't offer ALPN, no protocol is negotiated.
Cory Benfielde46fa842015-04-13 16:50:49 -04001979 """
1980 client_context = Context(TLSv1_METHOD)
1981 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfielde3d57152015-04-11 17:57:35 -04001982
Cory Benfielde46fa842015-04-13 16:50:49 -04001983 server_context = Context(TLSv1_METHOD)
Cory Benfielde3d57152015-04-11 17:57:35 -04001984
Cory Benfielde46fa842015-04-13 16:50:49 -04001985 # Necessary to actually accept the connection
1986 server_context.use_privatekey(
1987 load_privatekey(FILETYPE_PEM, server_key_pem))
1988 server_context.use_certificate(
1989 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfielde3d57152015-04-11 17:57:35 -04001990
Cory Benfielde46fa842015-04-13 16:50:49 -04001991 # Do a little connection to trigger the logic
1992 server = Connection(server_context, None)
1993 server.set_accept_state()
Cory Benfielde3d57152015-04-11 17:57:35 -04001994
Cory Benfielde46fa842015-04-13 16:50:49 -04001995 client = Connection(client_context, None)
1996 client.set_connect_state()
Cory Benfielde3d57152015-04-11 17:57:35 -04001997
Cory Benfielde46fa842015-04-13 16:50:49 -04001998 # Do the dance.
Alex Chanec1e32d2016-11-10 14:11:45 +00001999 interact_in_memory(server, client)
Cory Benfielde3d57152015-04-11 17:57:35 -04002000
Alex Chanec1e32d2016-11-10 14:11:45 +00002001 assert client.get_alpn_proto_negotiated() == b''
Cory Benfielde3d57152015-04-11 17:57:35 -04002002
Cory Benfielde46fa842015-04-13 16:50:49 -04002003 def test_alpn_callback_exception(self):
2004 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04002005 We can handle exceptions in the ALPN select callback.
Cory Benfielde46fa842015-04-13 16:50:49 -04002006 """
2007 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002008
Cory Benfielde46fa842015-04-13 16:50:49 -04002009 def select(conn, options):
2010 select_args.append((conn, options))
Cory Benfieldef401452015-04-13 18:17:36 -04002011 raise TypeError()
Cory Benfieldf1177e72015-04-12 09:11:49 -04002012
Cory Benfielde46fa842015-04-13 16:50:49 -04002013 client_context = Context(TLSv1_METHOD)
2014 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfieldf1177e72015-04-12 09:11:49 -04002015
Cory Benfielde46fa842015-04-13 16:50:49 -04002016 server_context = Context(TLSv1_METHOD)
2017 server_context.set_alpn_select_callback(select)
Cory Benfieldf1177e72015-04-12 09:11:49 -04002018
Cory Benfielde46fa842015-04-13 16:50:49 -04002019 # Necessary to actually accept the connection
2020 server_context.use_privatekey(
2021 load_privatekey(FILETYPE_PEM, server_key_pem))
2022 server_context.use_certificate(
2023 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfieldf1177e72015-04-12 09:11:49 -04002024
Cory Benfielde46fa842015-04-13 16:50:49 -04002025 # Do a little connection to trigger the logic
2026 server = Connection(server_context, None)
2027 server.set_accept_state()
Cory Benfieldf1177e72015-04-12 09:11:49 -04002028
Cory Benfielde46fa842015-04-13 16:50:49 -04002029 client = Connection(client_context, None)
2030 client.set_connect_state()
Cory Benfieldf1177e72015-04-12 09:11:49 -04002031
Alex Chanec1e32d2016-11-10 14:11:45 +00002032 with pytest.raises(TypeError):
2033 interact_in_memory(server, client)
2034 assert select_args == [(server, [b'http/1.1', b'spdy/2'])]
Cory Benfieldf1177e72015-04-12 09:11:49 -04002035
Cory Benfield0f7b04c2015-04-13 17:51:12 -04002036 else:
2037 # No ALPN.
2038 def test_alpn_not_implemented(self):
Cory Benfieldef401452015-04-13 18:17:36 -04002039 """
2040 If ALPN is not in OpenSSL, we should raise NotImplementedError.
2041 """
Cory Benfield0f7b04c2015-04-13 17:51:12 -04002042 # Test the context methods first.
2043 context = Context(TLSv1_METHOD)
Alex Chanec1e32d2016-11-10 14:11:45 +00002044 with pytest.raises(NotImplementedError):
2045 context.set_alpn_protos(None)
2046 with pytest.raises(NotImplementedError):
2047 context.set_alpn_select_callback(None)
Cory Benfield0f7b04c2015-04-13 17:51:12 -04002048
2049 # Now test a connection.
2050 conn = Connection(context)
Alex Chanec1e32d2016-11-10 14:11:45 +00002051 with pytest.raises(NotImplementedError):
2052 conn.set_alpn_protos(None)
Cory Benfield0f7b04c2015-04-13 17:51:12 -04002053
Cory Benfieldf1177e72015-04-12 09:11:49 -04002054
Alex Chanec1e32d2016-11-10 14:11:45 +00002055class TestSession(object):
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05002056 """
2057 Unit tests for :py:obj:`OpenSSL.SSL.Session`.
2058 """
2059 def test_construction(self):
2060 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002061 :py:class:`Session` can be constructed with no arguments, creating
2062 a new instance of that type.
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05002063 """
2064 new_session = Session()
Alex Chanec1e32d2016-11-10 14:11:45 +00002065 assert isinstance(new_session, Session)
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05002066
2067
Alex Chan1c0cb662017-01-30 07:13:30 +00002068class TestConnection(object):
Rick Deane15b1472009-07-09 15:53:42 -05002069 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002070 Unit tests for `OpenSSL.SSL.Connection`.
Rick Deane15b1472009-07-09 15:53:42 -05002071 """
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04002072 # XXX get_peer_certificate -> None
2073 # XXX sock_shutdown
2074 # XXX master_key -> TypeError
2075 # XXX server_random -> TypeError
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04002076 # XXX connect -> TypeError
2077 # XXX connect_ex -> TypeError
2078 # XXX set_connect_state -> TypeError
2079 # XXX set_accept_state -> TypeError
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04002080 # XXX do_handshake -> TypeError
2081 # XXX bio_read -> TypeError
2082 # XXX recv -> TypeError
2083 # XXX send -> TypeError
2084 # XXX bio_write -> TypeError
2085
Rick Deane15b1472009-07-09 15:53:42 -05002086 def test_type(self):
2087 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002088 `Connection` and `ConnectionType` refer to the same type object and
2089 can be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -05002090 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002091 assert Connection is ConnectionType
Rick Deane15b1472009-07-09 15:53:42 -05002092 ctx = Context(TLSv1_METHOD)
Alex Chan1c0cb662017-01-30 07:13:30 +00002093 assert is_consistent_type(Connection, 'Connection', ctx, None)
Rick Deane15b1472009-07-09 15:53:42 -05002094
Alex Chanfb078d82017-04-20 11:16:15 +01002095 @pytest.mark.parametrize('bad_context', [object(), 'context', None, 1])
2096 def test_wrong_args(self, bad_context):
2097 """
2098 `Connection.__init__` raises `TypeError` if called with a non-`Context`
2099 instance argument.
2100 """
2101 with pytest.raises(TypeError):
2102 Connection(bad_context)
2103
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002104 def test_get_context(self):
2105 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002106 `Connection.get_context` returns the `Context` instance used to
2107 construct the `Connection` instance.
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002108 """
2109 context = Context(TLSv1_METHOD)
2110 connection = Connection(context, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002111 assert connection.get_context() is context
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002112
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002113 def test_set_context_wrong_args(self):
2114 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002115 `Connection.set_context` raises `TypeError` if called with a
Alex Chanfb078d82017-04-20 11:16:15 +01002116 non-`Context` instance argument.
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002117 """
2118 ctx = Context(TLSv1_METHOD)
2119 connection = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002120 with pytest.raises(TypeError):
2121 connection.set_context(object())
2122 with pytest.raises(TypeError):
2123 connection.set_context("hello")
2124 with pytest.raises(TypeError):
2125 connection.set_context(1)
2126 assert ctx is connection.get_context()
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002127
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002128 def test_set_context(self):
2129 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002130 `Connection.set_context` specifies a new `Context` instance to be
2131 used for the connection.
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002132 """
2133 original = Context(SSLv23_METHOD)
2134 replacement = Context(TLSv1_METHOD)
2135 connection = Connection(original, None)
2136 connection.set_context(replacement)
Alex Chan1c0cb662017-01-30 07:13:30 +00002137 assert replacement is connection.get_context()
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002138 # Lose our references to the contexts, just in case the Connection
2139 # isn't properly managing its own contributions to their reference
2140 # counts.
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002141 del original, replacement
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002142 collect()
2143
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002144 def test_set_tlsext_host_name_wrong_args(self):
2145 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002146 If `Connection.set_tlsext_host_name` is called with a non-byte string
2147 argument or a byte string with an embedded NUL, `TypeError` is raised.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002148 """
2149 conn = Connection(Context(TLSv1_METHOD), None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002150 with pytest.raises(TypeError):
2151 conn.set_tlsext_host_name(object())
2152 with pytest.raises(TypeError):
2153 conn.set_tlsext_host_name(b"with\0null")
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002154
Abraham Martinc5484ba2015-03-25 15:33:05 +00002155 if PY3:
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002156 # On Python 3.x, don't accidentally implicitly convert from text.
Alex Chan1c0cb662017-01-30 07:13:30 +00002157 with pytest.raises(TypeError):
2158 conn.set_tlsext_host_name(b"example.com".decode("ascii"))
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04002159
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002160 def test_pending(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002161 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002162 `Connection.pending` returns the number of bytes available for
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002163 immediate read.
2164 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002165 connection = Connection(Context(TLSv1_METHOD), None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002166 assert connection.pending() == 0
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002167
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002168 def test_peek(self):
2169 """
Hynek Schlawack3bcf3152017-02-18 08:25:34 +01002170 `Connection.recv` peeks into the connection if `socket.MSG_PEEK` is
2171 passed.
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002172 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002173 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002174 server.send(b'xy')
Alex Chan1c0cb662017-01-30 07:13:30 +00002175 assert client.recv(2, MSG_PEEK) == b'xy'
2176 assert client.recv(2, MSG_PEEK) == b'xy'
2177 assert client.recv(2) == b'xy'
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002178
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002179 def test_connect_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002180 """
Hynek Schlawack3bcf3152017-02-18 08:25:34 +01002181 `Connection.connect` raises `TypeError` if called with a non-address
2182 argument.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002183 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002184 connection = Connection(Context(TLSv1_METHOD), socket())
Alex Chan1c0cb662017-01-30 07:13:30 +00002185 with pytest.raises(TypeError):
2186 connection.connect(None)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002187
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002188 def test_connect_refused(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002189 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002190 `Connection.connect` raises `socket.error` if the underlying socket
2191 connect method raises it.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002192 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002193 client = socket()
2194 context = Context(TLSv1_METHOD)
2195 clientSSL = Connection(context, client)
Alex Gaynor122717b2015-09-05 14:14:18 -04002196 # pytest.raises here doesn't work because of a bug in py.test on Python
2197 # 2.6: https://github.com/pytest-dev/pytest/issues/988
Alex Gaynore69c2782015-09-05 14:07:48 -04002198 try:
Alex Gaynor1aabb2e2015-09-05 13:35:18 -04002199 clientSSL.connect(("127.0.0.1", 1))
Alex Gaynore69c2782015-09-05 14:07:48 -04002200 except error as e:
Alex Gaynor20a4c082015-09-05 14:24:15 -04002201 exc = e
2202 assert exc.args[0] == ECONNREFUSED
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002203
2204 def test_connect(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002205 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002206 `Connection.connect` establishes a connection to the specified address.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002207 """
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002208 port = socket()
2209 port.bind(('', 0))
2210 port.listen(3)
2211
2212 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002213 clientSSL.connect(('127.0.0.1', port.getsockname()[1]))
2214 # XXX An assertion? Or something?
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002215
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002216 @pytest.mark.skipif(
2217 platform == "darwin",
2218 reason="connect_ex sometimes causes a kernel panic on OS X 10.6.4"
2219 )
2220 def test_connect_ex(self):
2221 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002222 If there is a connection error, `Connection.connect_ex` returns the
2223 errno instead of raising an exception.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002224 """
2225 port = socket()
2226 port.bind(('', 0))
2227 port.listen(3)
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002228
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002229 clientSSL = Connection(Context(TLSv1_METHOD), socket())
2230 clientSSL.setblocking(False)
2231 result = clientSSL.connect_ex(port.getsockname())
2232 expected = (EINPROGRESS, EWOULDBLOCK)
Alex Chan1c0cb662017-01-30 07:13:30 +00002233 assert result in expected
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002234
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002235 def test_accept(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002236 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002237 `Connection.accept` accepts a pending connection attempt and returns a
2238 tuple of a new `Connection` (the accepted client) and the address the
2239 connection originated from.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002240 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002241 ctx = Context(TLSv1_METHOD)
2242 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2243 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002244 port = socket()
2245 portSSL = Connection(ctx, port)
2246 portSSL.bind(('', 0))
2247 portSSL.listen(3)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002248
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002249 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002250
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002251 # Calling portSSL.getsockname() here to get the server IP address
2252 # sounds great, but frequently fails on Windows.
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002253 clientSSL.connect(('127.0.0.1', portSSL.getsockname()[1]))
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002254
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002255 serverSSL, address = portSSL.accept()
2256
Alex Chan1c0cb662017-01-30 07:13:30 +00002257 assert isinstance(serverSSL, Connection)
2258 assert serverSSL.get_context() is ctx
2259 assert address == clientSSL.getsockname()
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002260
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002261 def test_shutdown_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002262 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002263 `Connection.set_shutdown` raises `TypeError` if called with arguments
2264 other than integers.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002265 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002266 connection = Connection(Context(TLSv1_METHOD), None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002267 with pytest.raises(TypeError):
2268 connection.set_shutdown(None)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002269
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002270 def test_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002271 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002272 `Connection.shutdown` performs an SSL-level connection shutdown.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002273 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002274 server, client = loopback()
2275 assert not server.shutdown()
2276 assert server.get_shutdown() == SENT_SHUTDOWN
2277 with pytest.raises(ZeroReturnError):
2278 client.recv(1024)
2279 assert client.get_shutdown() == RECEIVED_SHUTDOWN
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04002280 client.shutdown()
Alex Chan1c0cb662017-01-30 07:13:30 +00002281 assert client.get_shutdown() == (SENT_SHUTDOWN | RECEIVED_SHUTDOWN)
2282 with pytest.raises(ZeroReturnError):
2283 server.recv(1024)
2284 assert server.get_shutdown() == (SENT_SHUTDOWN | RECEIVED_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002285
Paul Aurichc85e0862015-01-08 08:34:33 -08002286 def test_shutdown_closed(self):
2287 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002288 If the underlying socket is closed, `Connection.shutdown` propagates
2289 the write error from the low level write call.
Paul Aurichc85e0862015-01-08 08:34:33 -08002290 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002291 server, client = loopback()
Paul Aurichc85e0862015-01-08 08:34:33 -08002292 server.sock_shutdown(2)
Alex Chan1c0cb662017-01-30 07:13:30 +00002293 with pytest.raises(SysCallError) as exc:
2294 server.shutdown()
Alex Chanfb078d82017-04-20 11:16:15 +01002295 if platform == "win32":
2296 assert exc.value.args[0] == ESHUTDOWN
2297 else:
2298 assert exc.value.args[0] == EPIPE
Paul Aurichc85e0862015-01-08 08:34:33 -08002299
Glyph89389472015-04-14 17:29:26 -04002300 def test_shutdown_truncated(self):
Glyph6064ec32015-04-14 16:38:22 -04002301 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002302 If the underlying connection is truncated, `Connection.shutdown`
2303 raises an `Error`.
Glyph6064ec32015-04-14 16:38:22 -04002304 """
Glyph89389472015-04-14 17:29:26 -04002305 server_ctx = Context(TLSv1_METHOD)
2306 client_ctx = Context(TLSv1_METHOD)
2307 server_ctx.use_privatekey(
2308 load_privatekey(FILETYPE_PEM, server_key_pem))
2309 server_ctx.use_certificate(
2310 load_certificate(FILETYPE_PEM, server_cert_pem))
2311 server = Connection(server_ctx, None)
2312 client = Connection(client_ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002313 handshake_in_memory(client, server)
2314 assert not server.shutdown()
2315 with pytest.raises(WantReadError):
2316 server.shutdown()
Glyph89389472015-04-14 17:29:26 -04002317 server.bio_shutdown()
Alex Chan1c0cb662017-01-30 07:13:30 +00002318 with pytest.raises(Error):
2319 server.shutdown()
Glyph6064ec32015-04-14 16:38:22 -04002320
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002321 def test_set_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002322 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002323 `Connection.set_shutdown` sets the state of the SSL connection
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002324 shutdown process.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002325 """
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002326 connection = Connection(Context(TLSv1_METHOD), socket())
2327 connection.set_shutdown(RECEIVED_SHUTDOWN)
Alex Chan1c0cb662017-01-30 07:13:30 +00002328 assert connection.get_shutdown() == RECEIVED_SHUTDOWN
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002329
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002330 @skip_if_py3
2331 def test_set_shutdown_long(self):
2332 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002333 On Python 2 `Connection.set_shutdown` accepts an argument
2334 of type `long` as well as `int`.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002335 """
2336 connection = Connection(Context(TLSv1_METHOD), socket())
2337 connection.set_shutdown(long(RECEIVED_SHUTDOWN))
Alex Chan1c0cb662017-01-30 07:13:30 +00002338 assert connection.get_shutdown() == RECEIVED_SHUTDOWN
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -05002339
kjavaf248592015-09-07 12:14:01 +01002340 def test_state_string(self):
2341 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002342 `Connection.state_string` verbosely describes the current state of
2343 the `Connection`.
kjavaf248592015-09-07 12:14:01 +01002344 """
Hynek Schlawackb0274ce2015-10-16 19:56:26 +02002345 server, client = socket_pair()
Alex Chan1c0cb662017-01-30 07:13:30 +00002346 server = loopback_server_factory(server)
2347 client = loopback_client_factory(client)
kjavaf248592015-09-07 12:14:01 +01002348
Alex Gaynor5af32d02016-09-24 01:52:21 -04002349 assert server.get_state_string() in [
2350 b"before/accept initialization", b"before SSL initialization"
2351 ]
2352 assert client.get_state_string() in [
2353 b"before/connect initialization", b"before SSL initialization"
2354 ]
kjavaf248592015-09-07 12:14:01 +01002355
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002356 def test_app_data(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002357 """
2358 Any object can be set as app data by passing it to
Alex Chan1c0cb662017-01-30 07:13:30 +00002359 `Connection.set_app_data` and later retrieved with
2360 `Connection.get_app_data`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002361 """
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002362 conn = Connection(Context(TLSv1_METHOD), None)
Todd Chapman4f73e4f2015-08-27 11:26:43 -04002363 assert None is conn.get_app_data()
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002364 app_data = object()
2365 conn.set_app_data(app_data)
Todd Chapman4f73e4f2015-08-27 11:26:43 -04002366 assert conn.get_app_data() is app_data
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002367
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002368 def test_makefile(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002369 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002370 `Connection.makefile` is not implemented and calling that
2371 method raises `NotImplementedError`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002372 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002373 conn = Connection(Context(TLSv1_METHOD), None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002374 with pytest.raises(NotImplementedError):
2375 conn.makefile()
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002376
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002377 def test_get_peer_cert_chain(self):
2378 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002379 `Connection.get_peer_cert_chain` returns a list of certificates
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002380 which the connected server returned for the certification verification.
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002381 """
2382 chain = _create_certificate_chain()
2383 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
2384
2385 serverContext = Context(TLSv1_METHOD)
2386 serverContext.use_privatekey(skey)
2387 serverContext.use_certificate(scert)
2388 serverContext.add_extra_chain_cert(icert)
2389 serverContext.add_extra_chain_cert(cacert)
2390 server = Connection(serverContext, None)
2391 server.set_accept_state()
2392
2393 # Create the client
2394 clientContext = Context(TLSv1_METHOD)
2395 clientContext.set_verify(VERIFY_NONE, verify_cb)
2396 client = Connection(clientContext, None)
2397 client.set_connect_state()
2398
Alex Chan1c0cb662017-01-30 07:13:30 +00002399 interact_in_memory(client, server)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002400
2401 chain = client.get_peer_cert_chain()
Alex Chan1c0cb662017-01-30 07:13:30 +00002402 assert len(chain) == 3
2403 assert "Server Certificate" == chain[0].get_subject().CN
2404 assert "Intermediate Certificate" == chain[1].get_subject().CN
2405 assert "Authority Certificate" == chain[2].get_subject().CN
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002406
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002407 def test_get_peer_cert_chain_none(self):
2408 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002409 `Connection.get_peer_cert_chain` returns `None` if the peer sends
2410 no certificate chain.
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002411 """
2412 ctx = Context(TLSv1_METHOD)
2413 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2414 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
2415 server = Connection(ctx, None)
2416 server.set_accept_state()
2417 client = Connection(Context(TLSv1_METHOD), None)
2418 client.set_connect_state()
Alex Chan1c0cb662017-01-30 07:13:30 +00002419 interact_in_memory(client, server)
2420 assert None is server.get_peer_cert_chain()
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002421
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002422 def test_get_session_unconnected(self):
2423 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002424 `Connection.get_session` returns `None` when used with an object
2425 which has not been connected.
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002426 """
2427 ctx = Context(TLSv1_METHOD)
2428 server = Connection(ctx, None)
2429 session = server.get_session()
Alex Chan1c0cb662017-01-30 07:13:30 +00002430 assert None is session
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002431
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002432 def test_server_get_session(self):
2433 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002434 On the server side of a connection, `Connection.get_session` returns a
2435 `Session` instance representing the SSL session for that connection.
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002436 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002437 server, client = loopback()
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002438 session = server.get_session()
Alex Chan1c0cb662017-01-30 07:13:30 +00002439 assert isinstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002440
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002441 def test_client_get_session(self):
2442 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002443 On the client side of a connection, `Connection.get_session`
2444 returns a `Session` instance representing the SSL session for
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002445 that connection.
2446 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002447 server, client = loopback()
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002448 session = client.get_session()
Alex Chan1c0cb662017-01-30 07:13:30 +00002449 assert isinstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002450
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002451 def test_set_session_wrong_args(self):
2452 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002453 `Connection.set_session` raises `TypeError` if called with an object
2454 that is not an instance of `Session`.
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002455 """
2456 ctx = Context(TLSv1_METHOD)
2457 connection = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002458 with pytest.raises(TypeError):
2459 connection.set_session(123)
2460 with pytest.raises(TypeError):
2461 connection.set_session("hello")
2462 with pytest.raises(TypeError):
2463 connection.set_session(object())
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002464
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002465 def test_client_set_session(self):
2466 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002467 `Connection.set_session`, when used prior to a connection being
2468 established, accepts a `Session` instance and causes an attempt to
2469 re-use the session it represents when the SSL handshake is performed.
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002470 """
2471 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2472 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
2473 ctx = Context(TLSv1_METHOD)
2474 ctx.use_privatekey(key)
2475 ctx.use_certificate(cert)
2476 ctx.set_session_id("unity-test")
2477
2478 def makeServer(socket):
2479 server = Connection(ctx, socket)
2480 server.set_accept_state()
2481 return server
2482
Alex Chan1c0cb662017-01-30 07:13:30 +00002483 originalServer, originalClient = loopback(
2484 server_factory=makeServer)
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002485 originalSession = originalClient.get_session()
2486
2487 def makeClient(socket):
Alex Chan1c0cb662017-01-30 07:13:30 +00002488 client = loopback_client_factory(socket)
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002489 client.set_session(originalSession)
2490 return client
Alex Chan1c0cb662017-01-30 07:13:30 +00002491 resumedServer, resumedClient = loopback(
2492 server_factory=makeServer,
2493 client_factory=makeClient)
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002494
2495 # This is a proxy: in general, we have no access to any unique
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002496 # identifier for the session (new enough versions of OpenSSL expose
2497 # a hash which could be usable, but "new enough" is very, very new).
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002498 # Instead, exploit the fact that the master key is re-used if the
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002499 # session is re-used. As long as the master key for the two
2500 # connections is the same, the session was re-used!
Alex Chan1c0cb662017-01-30 07:13:30 +00002501 assert originalServer.master_key() == resumedServer.master_key()
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002502
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002503 def test_set_session_wrong_method(self):
2504 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002505 If `Connection.set_session` is passed a `Session` instance associated
2506 with a context using a different SSL method than the `Connection`
2507 is using, a `OpenSSL.SSL.Error` is raised.
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002508 """
Alex Gaynor5af32d02016-09-24 01:52:21 -04002509 # Make this work on both OpenSSL 1.0.0, which doesn't support TLSv1.2
2510 # and also on OpenSSL 1.1.0 which doesn't support SSLv3. (SSL_ST_INIT
2511 # is a way to check for 1.1.0)
2512 if SSL_ST_INIT is not None:
2513 v1 = TLSv1_METHOD
2514 v2 = SSLv3_METHOD
2515 else:
2516 v1 = TLSv1_2_METHOD
2517 v2 = TLSv1_METHOD
2518
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002519 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2520 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
Alex Gaynor5af32d02016-09-24 01:52:21 -04002521 ctx = Context(v1)
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002522 ctx.use_privatekey(key)
2523 ctx.use_certificate(cert)
2524 ctx.set_session_id("unity-test")
2525
2526 def makeServer(socket):
2527 server = Connection(ctx, socket)
2528 server.set_accept_state()
2529 return server
2530
Alex Gaynor5af32d02016-09-24 01:52:21 -04002531 def makeOriginalClient(socket):
2532 client = Connection(Context(v1), socket)
2533 client.set_connect_state()
2534 return client
2535
Alex Chan1c0cb662017-01-30 07:13:30 +00002536 originalServer, originalClient = loopback(
2537 server_factory=makeServer, client_factory=makeOriginalClient)
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002538 originalSession = originalClient.get_session()
2539
2540 def makeClient(socket):
2541 # Intentionally use a different, incompatible method here.
Alex Gaynor5af32d02016-09-24 01:52:21 -04002542 client = Connection(Context(v2), socket)
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002543 client.set_connect_state()
2544 client.set_session(originalSession)
2545 return client
2546
Alex Chan1c0cb662017-01-30 07:13:30 +00002547 with pytest.raises(Error):
2548 loopback(client_factory=makeClient, server_factory=makeServer)
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002549
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002550 def test_wantWriteError(self):
2551 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002552 `Connection` methods which generate output raise
2553 `OpenSSL.SSL.WantWriteError` if writing to the connection's BIO
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002554 fail indicating a should-write state.
2555 """
2556 client_socket, server_socket = socket_pair()
2557 # Fill up the client's send buffer so Connection won't be able to write
Jean-Paul Calderonebbff8b92014-03-22 14:20:30 -04002558 # anything. Only write a single byte at a time so we can be sure we
2559 # completely fill the buffer. Even though the socket API is allowed to
2560 # signal a short write via its return value it seems this doesn't
2561 # always happen on all platforms (FreeBSD and OS X particular) for the
2562 # very last bit of available buffer space.
2563 msg = b"x"
2564 for i in range(1024 * 1024 * 4):
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002565 try:
2566 client_socket.send(msg)
2567 except error as e:
2568 if e.errno == EWOULDBLOCK:
2569 break
2570 raise
2571 else:
Alex Chan1c0cb662017-01-30 07:13:30 +00002572 pytest.fail(
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002573 "Failed to fill socket buffer, cannot test BIO want write")
2574
2575 ctx = Context(TLSv1_METHOD)
2576 conn = Connection(ctx, client_socket)
2577 # Client's speak first, so make it an SSL client
2578 conn.set_connect_state()
Alex Chan1c0cb662017-01-30 07:13:30 +00002579 with pytest.raises(WantWriteError):
2580 conn.do_handshake()
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002581
2582 # XXX want_read
2583
Fedor Brunner416f4a12014-03-28 13:18:38 +01002584 def test_get_finished_before_connect(self):
Fedor Brunner5747b932014-03-05 14:22:34 +01002585 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002586 `Connection.get_finished` returns `None` before TLS handshake
2587 is completed.
Fedor Brunner5747b932014-03-05 14:22:34 +01002588 """
Fedor Brunner5747b932014-03-05 14:22:34 +01002589 ctx = Context(TLSv1_METHOD)
2590 connection = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002591 assert connection.get_finished() is None
Fedor Brunner416f4a12014-03-28 13:18:38 +01002592
2593 def test_get_peer_finished_before_connect(self):
2594 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002595 `Connection.get_peer_finished` returns `None` before TLS handshake
2596 is completed.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002597 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002598 ctx = Context(TLSv1_METHOD)
2599 connection = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002600 assert connection.get_peer_finished() is None
Fedor Brunner5747b932014-03-05 14:22:34 +01002601
Fedor Brunner416f4a12014-03-28 13:18:38 +01002602 def test_get_finished(self):
2603 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002604 `Connection.get_finished` method returns the TLS Finished message send
2605 from client, or server. Finished messages are send during
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002606 TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002607 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002608 server, client = loopback()
Fedor Brunner416f4a12014-03-28 13:18:38 +01002609
Alex Chan1c0cb662017-01-30 07:13:30 +00002610 assert server.get_finished() is not None
2611 assert len(server.get_finished()) > 0
Fedor Brunner416f4a12014-03-28 13:18:38 +01002612
2613 def test_get_peer_finished(self):
2614 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002615 `Connection.get_peer_finished` method returns the TLS Finished
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002616 message received from client, or server. Finished messages are send
2617 during TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002618 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002619 server, client = loopback()
Fedor Brunner416f4a12014-03-28 13:18:38 +01002620
Alex Chan1c0cb662017-01-30 07:13:30 +00002621 assert server.get_peer_finished() is not None
2622 assert len(server.get_peer_finished()) > 0
Fedor Brunner5747b932014-03-05 14:22:34 +01002623
Fedor Brunner416f4a12014-03-28 13:18:38 +01002624 def test_tls_finished_message_symmetry(self):
2625 """
Hynek Schlawackdddd1112015-09-05 21:12:30 +02002626 The TLS Finished message send by server must be the TLS Finished
2627 message received by client.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002628
Hynek Schlawackdddd1112015-09-05 21:12:30 +02002629 The TLS Finished message send by client must be the TLS Finished
2630 message received by server.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002631 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002632 server, client = loopback()
Fedor Brunner416f4a12014-03-28 13:18:38 +01002633
Alex Chan1c0cb662017-01-30 07:13:30 +00002634 assert server.get_finished() == client.get_peer_finished()
2635 assert client.get_finished() == server.get_peer_finished()
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002636
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002637 def test_get_cipher_name_before_connect(self):
2638 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002639 `Connection.get_cipher_name` returns `None` if no connection
2640 has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002641 """
2642 ctx = Context(TLSv1_METHOD)
2643 conn = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002644 assert conn.get_cipher_name() is None
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002645
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002646 def test_get_cipher_name(self):
2647 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002648 `Connection.get_cipher_name` returns a `unicode` string giving the
2649 name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002650 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002651 server, client = loopback()
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002652 server_cipher_name, client_cipher_name = \
2653 server.get_cipher_name(), client.get_cipher_name()
2654
Alex Chan1c0cb662017-01-30 07:13:30 +00002655 assert isinstance(server_cipher_name, text_type)
2656 assert isinstance(client_cipher_name, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002657
Alex Chan1c0cb662017-01-30 07:13:30 +00002658 assert server_cipher_name == client_cipher_name
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002659
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002660 def test_get_cipher_version_before_connect(self):
2661 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002662 `Connection.get_cipher_version` returns `None` if no connection
2663 has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002664 """
2665 ctx = Context(TLSv1_METHOD)
2666 conn = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002667 assert conn.get_cipher_version() is None
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002668
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002669 def test_get_cipher_version(self):
2670 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002671 `Connection.get_cipher_version` returns a `unicode` string giving
2672 the protocol name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002673 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002674 server, client = loopback()
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002675 server_cipher_version, client_cipher_version = \
2676 server.get_cipher_version(), client.get_cipher_version()
2677
Alex Chan1c0cb662017-01-30 07:13:30 +00002678 assert isinstance(server_cipher_version, text_type)
2679 assert isinstance(client_cipher_version, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002680
Alex Chan1c0cb662017-01-30 07:13:30 +00002681 assert server_cipher_version == client_cipher_version
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002682
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002683 def test_get_cipher_bits_before_connect(self):
2684 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002685 `Connection.get_cipher_bits` returns `None` if no connection has
2686 been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002687 """
2688 ctx = Context(TLSv1_METHOD)
2689 conn = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002690 assert conn.get_cipher_bits() is None
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002691
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002692 def test_get_cipher_bits(self):
2693 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002694 `Connection.get_cipher_bits` returns the number of secret bits
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002695 of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002696 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002697 server, client = loopback()
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002698 server_cipher_bits, client_cipher_bits = \
2699 server.get_cipher_bits(), client.get_cipher_bits()
2700
Alex Chan1c0cb662017-01-30 07:13:30 +00002701 assert isinstance(server_cipher_bits, int)
2702 assert isinstance(client_cipher_bits, int)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002703
Alex Chan1c0cb662017-01-30 07:13:30 +00002704 assert server_cipher_bits == client_cipher_bits
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002705
Jim Shaverabff1882015-05-27 09:15:55 -04002706 def test_get_protocol_version_name(self):
2707 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002708 `Connection.get_protocol_version_name()` returns a string giving the
2709 protocol version of the current connection.
Jim Shaverabff1882015-05-27 09:15:55 -04002710 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002711 server, client = loopback()
Jim Shaverabff1882015-05-27 09:15:55 -04002712 client_protocol_version_name = client.get_protocol_version_name()
2713 server_protocol_version_name = server.get_protocol_version_name()
2714
Alex Chan1c0cb662017-01-30 07:13:30 +00002715 assert isinstance(server_protocol_version_name, text_type)
2716 assert isinstance(client_protocol_version_name, text_type)
Jim Shaverabff1882015-05-27 09:15:55 -04002717
Alex Chan1c0cb662017-01-30 07:13:30 +00002718 assert server_protocol_version_name == client_protocol_version_name
Jim Shaverabff1882015-05-27 09:15:55 -04002719
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002720 def test_get_protocol_version(self):
2721 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002722 `Connection.get_protocol_version()` returns an integer
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002723 giving the protocol version of the current connection.
2724 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002725 server, client = loopback()
Jim Shaver85a4dff2015-04-27 17:42:46 -04002726 client_protocol_version = client.get_protocol_version()
2727 server_protocol_version = server.get_protocol_version()
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002728
Alex Chan1c0cb662017-01-30 07:13:30 +00002729 assert isinstance(server_protocol_version, int)
2730 assert isinstance(client_protocol_version, int)
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002731
Alex Chan1c0cb662017-01-30 07:13:30 +00002732 assert server_protocol_version == client_protocol_version
2733
2734 def test_wantReadError(self):
2735 """
2736 `Connection.bio_read` raises `OpenSSL.SSL.WantReadError` if there are
2737 no bytes available to be read from the BIO.
2738 """
2739 ctx = Context(TLSv1_METHOD)
2740 conn = Connection(ctx, None)
2741 with pytest.raises(WantReadError):
2742 conn.bio_read(1024)
2743
Alex Chanfb078d82017-04-20 11:16:15 +01002744 @pytest.mark.parametrize('bufsize', [1.0, None, object(), 'bufsize'])
2745 def test_bio_read_wrong_args(self, bufsize):
2746 """
2747 `Connection.bio_read` raises `TypeError` if passed a non-integer
2748 argument.
2749 """
2750 ctx = Context(TLSv1_METHOD)
2751 conn = Connection(ctx, None)
2752 with pytest.raises(TypeError):
2753 conn.bio_read(bufsize)
2754
Alex Chan1c0cb662017-01-30 07:13:30 +00002755 def test_buffer_size(self):
2756 """
2757 `Connection.bio_read` accepts an integer giving the maximum number
2758 of bytes to read and return.
2759 """
2760 ctx = Context(TLSv1_METHOD)
2761 conn = Connection(ctx, None)
2762 conn.set_connect_state()
2763 try:
2764 conn.do_handshake()
2765 except WantReadError:
2766 pass
2767 data = conn.bio_read(2)
2768 assert 2 == len(data)
2769
2770 @skip_if_py3
2771 def test_buffer_size_long(self):
2772 """
2773 On Python 2 `Connection.bio_read` accepts values of type `long` as
2774 well as `int`.
2775 """
2776 ctx = Context(TLSv1_METHOD)
2777 conn = Connection(ctx, None)
2778 conn.set_connect_state()
2779 try:
2780 conn.do_handshake()
2781 except WantReadError:
2782 pass
2783 data = conn.bio_read(long(2))
2784 assert 2 == len(data)
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002785
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002786
Alex Chanb7480992017-01-30 14:04:47 +00002787class TestConnectionGetCipherList(object):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002788 """
Alex Chanb7480992017-01-30 14:04:47 +00002789 Tests for `Connection.get_cipher_list`.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002790 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002791 def test_result(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002792 """
Alex Chanb7480992017-01-30 14:04:47 +00002793 `Connection.get_cipher_list` returns a list of `bytes` giving the
2794 names of the ciphers which might be used.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002795 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002796 connection = Connection(Context(TLSv1_METHOD), None)
2797 ciphers = connection.get_cipher_list()
Alex Chanb7480992017-01-30 14:04:47 +00002798 assert isinstance(ciphers, list)
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002799 for cipher in ciphers:
Alex Chanb7480992017-01-30 14:04:47 +00002800 assert isinstance(cipher, str)
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002801
2802
Maximilian Hils868dc3c2017-02-10 14:56:55 +01002803class VeryLarge(bytes):
2804 """
2805 Mock object so that we don't have to allocate 2**31 bytes
2806 """
2807 def __len__(self):
2808 return 2**31
2809
2810
Alex Chanb7480992017-01-30 14:04:47 +00002811class TestConnectionSend(object):
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002812 """
Alex Chanb7480992017-01-30 14:04:47 +00002813 Tests for `Connection.send`.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002814 """
2815 def test_wrong_args(self):
2816 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002817 When called with arguments other than string argument for its first
Alex Chanb7480992017-01-30 14:04:47 +00002818 parameter, `Connection.send` raises `TypeError`.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002819 """
2820 connection = Connection(Context(TLSv1_METHOD), None)
Alex Chanb7480992017-01-30 14:04:47 +00002821 with pytest.raises(TypeError):
2822 connection.send(object())
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002823
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002824 def test_short_bytes(self):
2825 """
Alex Chanb7480992017-01-30 14:04:47 +00002826 When passed a short byte string, `Connection.send` transmits all of it
2827 and returns the number of bytes sent.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002828 """
Alex Chanb7480992017-01-30 14:04:47 +00002829 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002830 count = server.send(b'xy')
Alex Chanb7480992017-01-30 14:04:47 +00002831 assert count == 2
2832 assert client.recv(2) == b'xy'
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002833
Abraham Martinef063482015-03-25 14:06:24 +00002834 def test_text(self):
2835 """
Alex Chanb7480992017-01-30 14:04:47 +00002836 When passed a text, `Connection.send` transmits all of it and
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002837 returns the number of bytes sent. It also raises a DeprecationWarning.
Abraham Martinef063482015-03-25 14:06:24 +00002838 """
Alex Chanb7480992017-01-30 14:04:47 +00002839 server, client = loopback()
2840 with pytest.warns(DeprecationWarning) as w:
Abraham Martinef063482015-03-25 14:06:24 +00002841 simplefilter("always")
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002842 count = server.send(b"xy".decode("ascii"))
Alex Chanb7480992017-01-30 14:04:47 +00002843 assert (
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002844 "{0} for buf is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002845 WARNING_TYPE_EXPECTED
Alex Chanb7480992017-01-30 14:04:47 +00002846 ) == str(w[-1].message))
2847 assert count == 2
2848 assert client.recv(2) == b'xy'
Abraham Martinef063482015-03-25 14:06:24 +00002849
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002850 @skip_if_py26
2851 def test_short_memoryview(self):
2852 """
2853 When passed a memoryview onto a small number of bytes,
Alex Chanb7480992017-01-30 14:04:47 +00002854 `Connection.send` transmits all of them and returns the number
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002855 of bytes sent.
2856 """
Alex Chanb7480992017-01-30 14:04:47 +00002857 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002858 count = server.send(memoryview(b'xy'))
Alex Chanb7480992017-01-30 14:04:47 +00002859 assert count == 2
2860 assert client.recv(2) == b'xy'
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002861
Hynek Schlawack8e94f1b2015-09-05 21:31:00 +02002862 @skip_if_py3
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002863 def test_short_buffer(self):
2864 """
2865 When passed a buffer containing a small number of bytes,
Alex Chanb7480992017-01-30 14:04:47 +00002866 `Connection.send` transmits all of them and returns the number
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002867 of bytes sent.
2868 """
Alex Chanb7480992017-01-30 14:04:47 +00002869 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002870 count = server.send(buffer(b'xy'))
Alex Chanb7480992017-01-30 14:04:47 +00002871 assert count == 2
2872 assert client.recv(2) == b'xy'
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02002873
Maximilian Hils868dc3c2017-02-10 14:56:55 +01002874 @pytest.mark.skipif(
2875 sys.maxsize < 2**31,
2876 reason="sys.maxsize < 2**31 - test requires 64 bit"
2877 )
2878 def test_buf_too_large(self):
2879 """
2880 When passed a buffer containing >= 2**31 bytes,
2881 `Connection.send` bails out as SSL_write only
2882 accepts an int for the buffer length.
2883 """
2884 connection = Connection(Context(TLSv1_METHOD), None)
2885 with pytest.raises(ValueError) as exc_info:
2886 connection.send(VeryLarge())
2887 exc_info.match(r"Cannot send more than .+ bytes at once")
2888
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05002889
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002890def _make_memoryview(size):
2891 """
2892 Create a new ``memoryview`` wrapped around a ``bytearray`` of the given
2893 size.
2894 """
2895 return memoryview(bytearray(size))
2896
2897
Alex Chanb7480992017-01-30 14:04:47 +00002898class TestConnectionRecvInto(object):
Cory Benfield62d10332014-06-15 10:03:41 +01002899 """
Alex Chanb7480992017-01-30 14:04:47 +00002900 Tests for `Connection.recv_into`.
Cory Benfield62d10332014-06-15 10:03:41 +01002901 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002902 def _no_length_test(self, factory):
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04002903 """
Alex Chanb7480992017-01-30 14:04:47 +00002904 Assert that when the given buffer is passed to `Connection.recv_into`,
2905 whatever bytes are available to be received that fit into that buffer
2906 are written into that buffer.
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04002907 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002908 output_buffer = factory(5)
2909
Alex Chanb7480992017-01-30 14:04:47 +00002910 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002911 server.send(b'xy')
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04002912
Alex Chanb7480992017-01-30 14:04:47 +00002913 assert client.recv_into(output_buffer) == 2
2914 assert output_buffer == bytearray(b'xy\x00\x00\x00')
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04002915
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002916 def test_bytearray_no_length(self):
Cory Benfield62d10332014-06-15 10:03:41 +01002917 """
Alex Chanb7480992017-01-30 14:04:47 +00002918 `Connection.recv_into` can be passed a `bytearray` instance and data
2919 in the receive buffer is written to it.
Cory Benfield62d10332014-06-15 10:03:41 +01002920 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002921 self._no_length_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01002922
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002923 def _respects_length_test(self, factory):
Cory Benfield62d10332014-06-15 10:03:41 +01002924 """
Alex Chanb7480992017-01-30 14:04:47 +00002925 Assert that when the given buffer is passed to `Connection.recv_into`
2926 along with a value for `nbytes` that is less than the size of that
2927 buffer, only `nbytes` bytes are written into the buffer.
Cory Benfield62d10332014-06-15 10:03:41 +01002928 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002929 output_buffer = factory(10)
2930
Alex Chanb7480992017-01-30 14:04:47 +00002931 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002932 server.send(b'abcdefghij')
Cory Benfield62d10332014-06-15 10:03:41 +01002933
Alex Chanb7480992017-01-30 14:04:47 +00002934 assert client.recv_into(output_buffer, 5) == 5
2935 assert output_buffer == bytearray(b'abcde\x00\x00\x00\x00\x00')
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002936
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002937 def test_bytearray_respects_length(self):
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002938 """
Alex Chanb7480992017-01-30 14:04:47 +00002939 When called with a `bytearray` instance, `Connection.recv_into`
2940 respects the `nbytes` parameter and doesn't copy in more than that
2941 number of bytes.
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002942 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002943 self._respects_length_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01002944
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002945 def _doesnt_overfill_test(self, factory):
Cory Benfield62d10332014-06-15 10:03:41 +01002946 """
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002947 Assert that if there are more bytes available to be read from the
2948 receive buffer than would fit into the buffer passed to
Alex Chanb7480992017-01-30 14:04:47 +00002949 `Connection.recv_into`, only as many as fit are written into it.
Cory Benfield62d10332014-06-15 10:03:41 +01002950 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002951 output_buffer = factory(5)
2952
Alex Chanb7480992017-01-30 14:04:47 +00002953 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002954 server.send(b'abcdefghij')
Cory Benfield62d10332014-06-15 10:03:41 +01002955
Alex Chanb7480992017-01-30 14:04:47 +00002956 assert client.recv_into(output_buffer) == 5
2957 assert output_buffer == bytearray(b'abcde')
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002958 rest = client.recv(5)
Alex Chanb7480992017-01-30 14:04:47 +00002959 assert b'fghij' == rest
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002960
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002961 def test_bytearray_doesnt_overfill(self):
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002962 """
Alex Chanb7480992017-01-30 14:04:47 +00002963 When called with a `bytearray` instance, `Connection.recv_into`
2964 respects the size of the array and doesn't write more bytes into it
2965 than will fit.
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002966 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002967 self._doesnt_overfill_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01002968
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002969 def test_bytearray_really_doesnt_overfill(self):
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04002970 """
Alex Chanb7480992017-01-30 14:04:47 +00002971 When called with a `bytearray` instance and an `nbytes` value that is
2972 too large, `Connection.recv_into` respects the size of the array and
2973 not the `nbytes` value and doesn't write more bytes into the buffer
2974 than will fit.
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04002975 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002976 self._doesnt_overfill_test(bytearray)
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04002977
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002978 def test_peek(self):
Alex Chanb7480992017-01-30 14:04:47 +00002979 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002980 server.send(b'xy')
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002981
2982 for _ in range(2):
2983 output_buffer = bytearray(5)
Alex Chanb7480992017-01-30 14:04:47 +00002984 assert client.recv_into(output_buffer, flags=MSG_PEEK) == 2
2985 assert output_buffer == bytearray(b'xy\x00\x00\x00')
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002986
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002987 @skip_if_py26
2988 def test_memoryview_no_length(self):
2989 """
Alex Chanb7480992017-01-30 14:04:47 +00002990 `Connection.recv_into` can be passed a `memoryview` instance and data
2991 in the receive buffer is written to it.
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002992 """
2993 self._no_length_test(_make_memoryview)
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002994
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002995 @skip_if_py26
2996 def test_memoryview_respects_length(self):
2997 """
Alex Chanb7480992017-01-30 14:04:47 +00002998 When called with a `memoryview` instance, `Connection.recv_into`
2999 respects the ``nbytes`` parameter and doesn't copy more than that
3000 number of bytes in.
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003001 """
3002 self._respects_length_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01003003
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003004 @skip_if_py26
3005 def test_memoryview_doesnt_overfill(self):
3006 """
Alex Chanb7480992017-01-30 14:04:47 +00003007 When called with a `memoryview` instance, `Connection.recv_into`
3008 respects the size of the array and doesn't write more bytes into it
3009 than will fit.
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003010 """
3011 self._doesnt_overfill_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01003012
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003013 @skip_if_py26
3014 def test_memoryview_really_doesnt_overfill(self):
3015 """
Alex Chanb7480992017-01-30 14:04:47 +00003016 When called with a `memoryview` instance and an `nbytes` value that is
3017 too large, `Connection.recv_into` respects the size of the array and
3018 not the `nbytes` value and doesn't write more bytes into the buffer
3019 than will fit.
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003020 """
3021 self._doesnt_overfill_test(_make_memoryview)
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003022
Cory Benfield62d10332014-06-15 10:03:41 +01003023
Alex Chanb7480992017-01-30 14:04:47 +00003024class TestConnectionSendall(object):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003025 """
Alex Chanb7480992017-01-30 14:04:47 +00003026 Tests for `Connection.sendall`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003027 """
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003028 def test_wrong_args(self):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003029 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003030 When called with arguments other than a string argument for its first
Alex Chanb7480992017-01-30 14:04:47 +00003031 parameter, `Connection.sendall` raises `TypeError`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003032 """
3033 connection = Connection(Context(TLSv1_METHOD), None)
Alex Chanb7480992017-01-30 14:04:47 +00003034 with pytest.raises(TypeError):
3035 connection.sendall(object())
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003036
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003037 def test_short(self):
3038 """
Alex Chanb7480992017-01-30 14:04:47 +00003039 `Connection.sendall` transmits all of the bytes in the string
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003040 passed to it.
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003041 """
Alex Chanb7480992017-01-30 14:04:47 +00003042 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04003043 server.sendall(b'x')
Alex Chanb7480992017-01-30 14:04:47 +00003044 assert client.recv(1) == b'x'
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003045
Abraham Martinef063482015-03-25 14:06:24 +00003046 def test_text(self):
3047 """
Alex Chanb7480992017-01-30 14:04:47 +00003048 `Connection.sendall` transmits all the content in the string passed
3049 to it, raising a DeprecationWarning in case of this being a text.
Abraham Martinef063482015-03-25 14:06:24 +00003050 """
Alex Chanb7480992017-01-30 14:04:47 +00003051 server, client = loopback()
3052 with pytest.warns(DeprecationWarning) as w:
Abraham Martinef063482015-03-25 14:06:24 +00003053 simplefilter("always")
Jean-Paul Calderone8dc37a12015-03-29 08:16:52 -04003054 server.sendall(b"x".decode("ascii"))
Alex Chanb7480992017-01-30 14:04:47 +00003055 assert (
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04003056 "{0} for buf is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04003057 WARNING_TYPE_EXPECTED
Alex Chanb7480992017-01-30 14:04:47 +00003058 ) == str(w[-1].message))
3059 assert client.recv(1) == b"x"
Abraham Martinef063482015-03-25 14:06:24 +00003060
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003061 @skip_if_py26
3062 def test_short_memoryview(self):
3063 """
3064 When passed a memoryview onto a small number of bytes,
Alex Chanb7480992017-01-30 14:04:47 +00003065 `Connection.sendall` transmits all of them.
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003066 """
Alex Chanb7480992017-01-30 14:04:47 +00003067 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04003068 server.sendall(memoryview(b'x'))
Alex Chanb7480992017-01-30 14:04:47 +00003069 assert client.recv(1) == b'x'
Abraham Martinef063482015-03-25 14:06:24 +00003070
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003071 @skip_if_py3
3072 def test_short_buffers(self):
3073 """
3074 When passed a buffer containing a small number of bytes,
Alex Chanb7480992017-01-30 14:04:47 +00003075 `Connection.sendall` transmits all of them.
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003076 """
Alex Chanb7480992017-01-30 14:04:47 +00003077 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04003078 server.sendall(buffer(b'x'))
Alex Chanb7480992017-01-30 14:04:47 +00003079 assert client.recv(1) == b'x'
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02003080
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003081 def test_long(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003082 """
Alex Chanb7480992017-01-30 14:04:47 +00003083 `Connection.sendall` transmits all the bytes in the string passed to it
3084 even if this requires multiple calls of an underlying write function.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003085 """
Alex Chanb7480992017-01-30 14:04:47 +00003086 server, client = loopback()
Jean-Paul Calderone6241c702010-09-16 19:59:24 -04003087 # Should be enough, underlying SSL_write should only do 16k at a time.
Hynek Schlawack35618382015-09-05 21:54:25 +02003088 # On Windows, after 32k of bytes the write will block (forever
3089 # - because no one is yet reading).
Alex Gaynore7f51982016-09-11 11:48:14 -04003090 message = b'x' * (1024 * 32 - 1) + b'y'
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003091 server.sendall(message)
3092 accum = []
3093 received = 0
3094 while received < len(message):
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04003095 data = client.recv(1024)
3096 accum.append(data)
3097 received += len(data)
Alex Chanb7480992017-01-30 14:04:47 +00003098 assert message == b''.join(accum)
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003099
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003100 def test_closed(self):
3101 """
Alex Chanb7480992017-01-30 14:04:47 +00003102 If the underlying socket is closed, `Connection.sendall` propagates the
3103 write error from the low level write call.
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003104 """
Alex Chanb7480992017-01-30 14:04:47 +00003105 server, client = loopback()
Jean-Paul Calderone05d43e82010-09-24 18:01:36 -04003106 server.sock_shutdown(2)
Alex Chanb7480992017-01-30 14:04:47 +00003107 with pytest.raises(SysCallError) as err:
3108 server.sendall(b"hello, world")
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +02003109 if platform == "win32":
Alex Chanb7480992017-01-30 14:04:47 +00003110 assert err.value.args[0] == ESHUTDOWN
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +02003111 else:
Alex Chanb7480992017-01-30 14:04:47 +00003112 assert err.value.args[0] == EPIPE
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003113
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003114
Alex Chanb7480992017-01-30 14:04:47 +00003115class TestConnectionRenegotiate(object):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003116 """
3117 Tests for SSL renegotiation APIs.
3118 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003119 def test_total_renegotiations(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003120 """
Alex Chanb7480992017-01-30 14:04:47 +00003121 `Connection.total_renegotiations` returns `0` before any renegotiations
3122 have happened.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003123 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003124 connection = Connection(Context(TLSv1_METHOD), None)
Alex Chanb7480992017-01-30 14:04:47 +00003125 assert connection.total_renegotiations() == 0
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003126
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003127 def test_renegotiate(self):
3128 """
3129 Go through a complete renegotiation cycle.
3130 """
Alex Chanb7480992017-01-30 14:04:47 +00003131 server, client = loopback()
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003132
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003133 server.send(b"hello world")
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003134
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003135 assert b"hello world" == client.recv(len(b"hello world"))
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003136
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003137 assert 0 == server.total_renegotiations()
3138 assert False is server.renegotiate_pending()
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003139
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003140 assert True is server.renegotiate()
3141
3142 assert True is server.renegotiate_pending()
3143
3144 server.setblocking(False)
3145 client.setblocking(False)
3146
3147 client.do_handshake()
3148 server.do_handshake()
3149
3150 assert 1 == server.total_renegotiations()
3151 while False is server.renegotiate_pending():
3152 pass
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003153
3154
Alex Chanb7480992017-01-30 14:04:47 +00003155class TestError(object):
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003156 """
Alex Chanb7480992017-01-30 14:04:47 +00003157 Unit tests for `OpenSSL.SSL.Error`.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003158 """
3159 def test_type(self):
3160 """
Alex Chanb7480992017-01-30 14:04:47 +00003161 `Error` is an exception type.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003162 """
Alex Chanb7480992017-01-30 14:04:47 +00003163 assert issubclass(Error, Exception)
3164 assert Error.__name__ == 'Error'
Rick Deane15b1472009-07-09 15:53:42 -05003165
3166
Alex Chanb7480992017-01-30 14:04:47 +00003167class TestConstants(object):
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003168 """
Alex Chanb7480992017-01-30 14:04:47 +00003169 Tests for the values of constants exposed in `OpenSSL.SSL`.
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003170
3171 These are values defined by OpenSSL intended only to be used as flags to
3172 OpenSSL APIs. The only assertions it seems can be made about them is
3173 their values.
3174 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003175 @pytest.mark.skipif(
3176 OP_NO_QUERY_MTU is None,
3177 reason="OP_NO_QUERY_MTU unavailable - OpenSSL version may be too old"
3178 )
3179 def test_op_no_query_mtu(self):
3180 """
Alex Chanb7480992017-01-30 14:04:47 +00003181 The value of `OpenSSL.SSL.OP_NO_QUERY_MTU` is 0x1000, the value
3182 of `SSL_OP_NO_QUERY_MTU` defined by `openssl/ssl.h`.
Hynek Schlawack35618382015-09-05 21:54:25 +02003183 """
Alex Chanb7480992017-01-30 14:04:47 +00003184 assert OP_NO_QUERY_MTU == 0x1000
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003185
Hynek Schlawack35618382015-09-05 21:54:25 +02003186 @pytest.mark.skipif(
3187 OP_COOKIE_EXCHANGE is None,
3188 reason="OP_COOKIE_EXCHANGE unavailable - "
3189 "OpenSSL version may be too old"
3190 )
3191 def test_op_cookie_exchange(self):
3192 """
Alex Chanb7480992017-01-30 14:04:47 +00003193 The value of `OpenSSL.SSL.OP_COOKIE_EXCHANGE` is 0x2000, the
3194 value of `SSL_OP_COOKIE_EXCHANGE` defined by `openssl/ssl.h`.
Hynek Schlawack35618382015-09-05 21:54:25 +02003195 """
Alex Chanb7480992017-01-30 14:04:47 +00003196 assert OP_COOKIE_EXCHANGE == 0x2000
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003197
Hynek Schlawack35618382015-09-05 21:54:25 +02003198 @pytest.mark.skipif(
3199 OP_NO_TICKET is None,
3200 reason="OP_NO_TICKET unavailable - OpenSSL version may be too old"
3201 )
3202 def test_op_no_ticket(self):
3203 """
Alex Chanb7480992017-01-30 14:04:47 +00003204 The value of `OpenSSL.SSL.OP_NO_TICKET` is 0x4000, the value of
3205 `SSL_OP_NO_TICKET` defined by `openssl/ssl.h`.
Hynek Schlawack35618382015-09-05 21:54:25 +02003206 """
Alex Chanb7480992017-01-30 14:04:47 +00003207 assert OP_NO_TICKET == 0x4000
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003208
Hynek Schlawack35618382015-09-05 21:54:25 +02003209 @pytest.mark.skipif(
3210 OP_NO_COMPRESSION is None,
3211 reason="OP_NO_COMPRESSION unavailable - OpenSSL version may be too old"
3212 )
3213 def test_op_no_compression(self):
3214 """
Alex Chanb7480992017-01-30 14:04:47 +00003215 The value of `OpenSSL.SSL.OP_NO_COMPRESSION` is 0x20000, the
3216 value of `SSL_OP_NO_COMPRESSION` defined by `openssl/ssl.h`.
Hynek Schlawack35618382015-09-05 21:54:25 +02003217 """
Alex Chanb7480992017-01-30 14:04:47 +00003218 assert OP_NO_COMPRESSION == 0x20000
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04003219
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003220 def test_sess_cache_off(self):
3221 """
Alex Chanb7480992017-01-30 14:04:47 +00003222 The value of `OpenSSL.SSL.SESS_CACHE_OFF` 0x0, the value of
3223 `SSL_SESS_CACHE_OFF` defined by `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003224 """
Alex Chanb7480992017-01-30 14:04:47 +00003225 assert 0x0 == SESS_CACHE_OFF
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003226
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003227 def test_sess_cache_client(self):
3228 """
Alex Chanb7480992017-01-30 14:04:47 +00003229 The value of `OpenSSL.SSL.SESS_CACHE_CLIENT` 0x1, the value of
3230 `SSL_SESS_CACHE_CLIENT` defined by `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003231 """
Alex Chanb7480992017-01-30 14:04:47 +00003232 assert 0x1 == SESS_CACHE_CLIENT
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003233
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003234 def test_sess_cache_server(self):
3235 """
Alex Chanb7480992017-01-30 14:04:47 +00003236 The value of `OpenSSL.SSL.SESS_CACHE_SERVER` 0x2, the value of
3237 `SSL_SESS_CACHE_SERVER` defined by `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003238 """
Alex Chanb7480992017-01-30 14:04:47 +00003239 assert 0x2 == SESS_CACHE_SERVER
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003240
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003241 def test_sess_cache_both(self):
3242 """
Alex Chanb7480992017-01-30 14:04:47 +00003243 The value of `OpenSSL.SSL.SESS_CACHE_BOTH` 0x3, the value of
3244 `SSL_SESS_CACHE_BOTH` defined by `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003245 """
Alex Chanb7480992017-01-30 14:04:47 +00003246 assert 0x3 == SESS_CACHE_BOTH
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003247
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003248 def test_sess_cache_no_auto_clear(self):
3249 """
Alex Chanb7480992017-01-30 14:04:47 +00003250 The value of `OpenSSL.SSL.SESS_CACHE_NO_AUTO_CLEAR` 0x80, the
3251 value of `SSL_SESS_CACHE_NO_AUTO_CLEAR` defined by
3252 `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003253 """
Alex Chanb7480992017-01-30 14:04:47 +00003254 assert 0x80 == SESS_CACHE_NO_AUTO_CLEAR
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003255
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003256 def test_sess_cache_no_internal_lookup(self):
3257 """
Alex Chanb7480992017-01-30 14:04:47 +00003258 The value of `OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_LOOKUP` 0x100,
3259 the value of `SSL_SESS_CACHE_NO_INTERNAL_LOOKUP` defined by
3260 `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003261 """
Alex Chanb7480992017-01-30 14:04:47 +00003262 assert 0x100 == SESS_CACHE_NO_INTERNAL_LOOKUP
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003263
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003264 def test_sess_cache_no_internal_store(self):
3265 """
Alex Chanb7480992017-01-30 14:04:47 +00003266 The value of `OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_STORE` 0x200,
3267 the value of `SSL_SESS_CACHE_NO_INTERNAL_STORE` defined by
3268 `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003269 """
Alex Chanb7480992017-01-30 14:04:47 +00003270 assert 0x200 == SESS_CACHE_NO_INTERNAL_STORE
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003271
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003272 def test_sess_cache_no_internal(self):
3273 """
Alex Chanb7480992017-01-30 14:04:47 +00003274 The value of `OpenSSL.SSL.SESS_CACHE_NO_INTERNAL` 0x300, the
3275 value of `SSL_SESS_CACHE_NO_INTERNAL` defined by
3276 `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003277 """
Alex Chanb7480992017-01-30 14:04:47 +00003278 assert 0x300 == SESS_CACHE_NO_INTERNAL
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003279
3280
Alex Chanb7480992017-01-30 14:04:47 +00003281class TestMemoryBIO(object):
Rick Deanb71c0d22009-04-01 14:09:23 -05003282 """
Alex Chanb7480992017-01-30 14:04:47 +00003283 Tests for `OpenSSL.SSL.Connection` using a memory BIO.
Rick Deanb71c0d22009-04-01 14:09:23 -05003284 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003285 def _server(self, sock):
3286 """
Alex Chanb7480992017-01-30 14:04:47 +00003287 Create a new server-side SSL `Connection` object wrapped around `sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003288 """
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003289 # Create the server side Connection. This is mostly setup boilerplate
3290 # - use TLSv1, use a particular certificate, etc.
3291 server_ctx = Context(TLSv1_METHOD)
Alex Gaynor43307782015-09-04 09:05:45 -04003292 server_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE)
Hynek Schlawack35618382015-09-05 21:54:25 +02003293 server_ctx.set_verify(
3294 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT | VERIFY_CLIENT_ONCE,
3295 verify_cb
3296 )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003297 server_store = server_ctx.get_cert_store()
Hynek Schlawack35618382015-09-05 21:54:25 +02003298 server_ctx.use_privatekey(
3299 load_privatekey(FILETYPE_PEM, server_key_pem))
3300 server_ctx.use_certificate(
3301 load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003302 server_ctx.check_privatekey()
3303 server_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Hynek Schlawack35618382015-09-05 21:54:25 +02003304 # Here the Connection is actually created. If None is passed as the
3305 # 2nd parameter, it indicates a memory BIO should be created.
Rick Deanb1ccd562009-07-09 23:52:39 -05003306 server_conn = Connection(server_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003307 server_conn.set_accept_state()
3308 return server_conn
3309
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003310 def _client(self, sock):
3311 """
Alex Chanb7480992017-01-30 14:04:47 +00003312 Create a new client-side SSL `Connection` object wrapped around `sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003313 """
3314 # Now create the client side Connection. Similar boilerplate to the
3315 # above.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003316 client_ctx = Context(TLSv1_METHOD)
Alex Gaynor43307782015-09-04 09:05:45 -04003317 client_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE)
Hynek Schlawack35618382015-09-05 21:54:25 +02003318 client_ctx.set_verify(
3319 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT | VERIFY_CLIENT_ONCE,
3320 verify_cb
3321 )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003322 client_store = client_ctx.get_cert_store()
Hynek Schlawack35618382015-09-05 21:54:25 +02003323 client_ctx.use_privatekey(
3324 load_privatekey(FILETYPE_PEM, client_key_pem))
3325 client_ctx.use_certificate(
3326 load_certificate(FILETYPE_PEM, client_cert_pem))
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003327 client_ctx.check_privatekey()
3328 client_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05003329 client_conn = Connection(client_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003330 client_conn.set_connect_state()
3331 return client_conn
3332
Alex Chanb7480992017-01-30 14:04:47 +00003333 def test_memory_connect(self):
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003334 """
Alex Chanb7480992017-01-30 14:04:47 +00003335 Two `Connection`s which use memory BIOs can be manually connected by
3336 reading from the output of each and writing those bytes to the input of
3337 the other and in this way establish a connection and exchange
3338 application-level bytes with each other.
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003339 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003340 server_conn = self._server(None)
3341 client_conn = self._client(None)
Rick Deanb71c0d22009-04-01 14:09:23 -05003342
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003343 # There should be no key or nonces yet.
Alex Chanb7480992017-01-30 14:04:47 +00003344 assert server_conn.master_key() is None
3345 assert server_conn.client_random() is None
3346 assert server_conn.server_random() is None
Rick Deanb71c0d22009-04-01 14:09:23 -05003347
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003348 # First, the handshake needs to happen. We'll deliver bytes back and
3349 # forth between the client and server until neither of them feels like
3350 # speaking any more.
Alex Chanb7480992017-01-30 14:04:47 +00003351 assert interact_in_memory(client_conn, server_conn) is None
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003352
3353 # Now that the handshake is done, there should be a key and nonces.
Alex Chanb7480992017-01-30 14:04:47 +00003354 assert server_conn.master_key() is not None
3355 assert server_conn.client_random() is not None
3356 assert server_conn.server_random() is not None
3357 assert server_conn.client_random() == client_conn.client_random()
3358 assert server_conn.server_random() == client_conn.server_random()
3359 assert server_conn.client_random() != server_conn.server_random()
3360 assert client_conn.client_random() != client_conn.server_random()
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003361
3362 # Here are the bytes we'll try to send.
Alex Gaynore7f51982016-09-11 11:48:14 -04003363 important_message = b'One if by land, two if by sea.'
Rick Deanb71c0d22009-04-01 14:09:23 -05003364
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003365 server_conn.write(important_message)
Alex Chanb7480992017-01-30 14:04:47 +00003366 assert (
3367 interact_in_memory(client_conn, server_conn) ==
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003368 (client_conn, important_message))
3369
3370 client_conn.write(important_message[::-1])
Alex Chanb7480992017-01-30 14:04:47 +00003371 assert (
3372 interact_in_memory(client_conn, server_conn) ==
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003373 (server_conn, important_message[::-1]))
Rick Deanb71c0d22009-04-01 14:09:23 -05003374
Alex Chanb7480992017-01-30 14:04:47 +00003375 def test_socket_connect(self):
Rick Deanb1ccd562009-07-09 23:52:39 -05003376 """
Alex Chanb7480992017-01-30 14:04:47 +00003377 Just like `test_memory_connect` but with an actual socket.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003378
Hynek Schlawack35618382015-09-05 21:54:25 +02003379 This is primarily to rule out the memory BIO code as the source of any
Alex Chanb7480992017-01-30 14:04:47 +00003380 problems encountered while passing data over a `Connection` (if
Hynek Schlawack35618382015-09-05 21:54:25 +02003381 this test fails, there must be a problem outside the memory BIO code,
3382 as no memory BIO is involved here). Even though this isn't a memory
3383 BIO test, it's convenient to have it here.
Rick Deanb1ccd562009-07-09 23:52:39 -05003384 """
Alex Chanb7480992017-01-30 14:04:47 +00003385 server_conn, client_conn = loopback()
Rick Deanb1ccd562009-07-09 23:52:39 -05003386
Alex Gaynore7f51982016-09-11 11:48:14 -04003387 important_message = b"Help me Obi Wan Kenobi, you're my only hope."
Rick Deanb1ccd562009-07-09 23:52:39 -05003388 client_conn.send(important_message)
3389 msg = server_conn.recv(1024)
Alex Chanb7480992017-01-30 14:04:47 +00003390 assert msg == important_message
Rick Deanb1ccd562009-07-09 23:52:39 -05003391
3392 # Again in the other direction, just for fun.
3393 important_message = important_message[::-1]
3394 server_conn.send(important_message)
3395 msg = client_conn.recv(1024)
Alex Chanb7480992017-01-30 14:04:47 +00003396 assert msg == important_message
Rick Deanb1ccd562009-07-09 23:52:39 -05003397
Alex Chanb7480992017-01-30 14:04:47 +00003398 def test_socket_overrides_memory(self):
Rick Deanb71c0d22009-04-01 14:09:23 -05003399 """
Alex Chanb7480992017-01-30 14:04:47 +00003400 Test that `OpenSSL.SSL.bio_read` and `OpenSSL.SSL.bio_write` don't
3401 work on `OpenSSL.SSL.Connection`() that use sockets.
Rick Deanb71c0d22009-04-01 14:09:23 -05003402 """
Alex Gaynor51d424c2016-09-10 14:50:11 -04003403 context = Context(TLSv1_METHOD)
Rick Deanb71c0d22009-04-01 14:09:23 -05003404 client = socket()
3405 clientSSL = Connection(context, client)
Alex Chanb7480992017-01-30 14:04:47 +00003406 with pytest.raises(TypeError):
3407 clientSSL.bio_read(100)
3408 with pytest.raises(TypeError):
3409 clientSSL.bio_write("foo")
3410 with pytest.raises(TypeError):
3411 clientSSL.bio_shutdown()
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003412
Alex Chanb7480992017-01-30 14:04:47 +00003413 def test_outgoing_overflow(self):
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003414 """
3415 If more bytes than can be written to the memory BIO are passed to
Alex Chanb7480992017-01-30 14:04:47 +00003416 `Connection.send` at once, the number of bytes which were written is
3417 returned and that many bytes from the beginning of the input can be
3418 read from the other end of the connection.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003419 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003420 server = self._server(None)
3421 client = self._client(None)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003422
Alex Chanb7480992017-01-30 14:04:47 +00003423 interact_in_memory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003424
3425 size = 2 ** 15
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003426 sent = client.send(b"x" * size)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003427 # Sanity check. We're trying to test what happens when the entire
3428 # input can't be sent. If the entire input was sent, this test is
3429 # meaningless.
Alex Chanb7480992017-01-30 14:04:47 +00003430 assert sent < size
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003431
Alex Chanb7480992017-01-30 14:04:47 +00003432 receiver, received = interact_in_memory(client, server)
3433 assert receiver is server
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003434
3435 # We can rely on all of these bytes being received at once because
Alex Chanb7480992017-01-30 14:04:47 +00003436 # loopback passes 2 ** 16 to recv - more than 2 ** 15.
3437 assert len(received) == sent
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003438
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003439 def test_shutdown(self):
3440 """
Alex Chanb7480992017-01-30 14:04:47 +00003441 `Connection.bio_shutdown` signals the end of the data stream
3442 from which the `Connection` reads.
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003443 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003444 server = self._server(None)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003445 server.bio_shutdown()
Alex Chanb7480992017-01-30 14:04:47 +00003446 with pytest.raises(Error) as err:
3447 server.recv(1024)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003448 # We don't want WantReadError or ZeroReturnError or anything - it's a
3449 # handshake failure.
Alex Chanb7480992017-01-30 14:04:47 +00003450 assert type(err.value) in [Error, SysCallError]
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003451
Alex Chanb7480992017-01-30 14:04:47 +00003452 def test_unexpected_EOF(self):
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003453 """
3454 If the connection is lost before an orderly SSL shutdown occurs,
Alex Chanb7480992017-01-30 14:04:47 +00003455 `OpenSSL.SSL.SysCallError` is raised with a message of
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003456 "Unexpected EOF".
3457 """
Alex Chanb7480992017-01-30 14:04:47 +00003458 server_conn, client_conn = loopback()
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003459 client_conn.sock_shutdown(SHUT_RDWR)
Alex Chanb7480992017-01-30 14:04:47 +00003460 with pytest.raises(SysCallError) as err:
3461 server_conn.recv(1024)
3462 assert err.value.args == (-1, "Unexpected EOF")
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003463
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003464 def _check_client_ca_list(self, func):
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003465 """
Alex Chanb7480992017-01-30 14:04:47 +00003466 Verify the return value of the `get_client_ca_list` method for
Hynek Schlawack35618382015-09-05 21:54:25 +02003467 server and client connections.
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003468
Jonathan Ballet78b92a22011-07-16 08:07:26 +09003469 :param func: A function which will be called with the server context
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003470 before the client and server are connected to each other. This
3471 function should specify a list of CAs for the server to send to the
3472 client and return that same list. The list will be used to verify
Alex Chanb7480992017-01-30 14:04:47 +00003473 that `get_client_ca_list` returns the proper value at
Hynek Schlawack35618382015-09-05 21:54:25 +02003474 various times.
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003475 """
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003476 server = self._server(None)
3477 client = self._client(None)
Alex Chanb7480992017-01-30 14:04:47 +00003478 assert client.get_client_ca_list() == []
3479 assert server.get_client_ca_list() == []
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003480 ctx = server.get_context()
3481 expected = func(ctx)
Alex Chanb7480992017-01-30 14:04:47 +00003482 assert client.get_client_ca_list() == []
3483 assert server.get_client_ca_list() == expected
3484 interact_in_memory(client, server)
3485 assert client.get_client_ca_list() == expected
3486 assert server.get_client_ca_list() == expected
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003487
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003488 def test_set_client_ca_list_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003489 """
Alex Chanb7480992017-01-30 14:04:47 +00003490 `Context.set_client_ca_list` raises a `TypeError` if called with a
3491 non-list or a list that contains objects other than X509Names.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003492 """
3493 ctx = Context(TLSv1_METHOD)
Alex Chanb7480992017-01-30 14:04:47 +00003494 with pytest.raises(TypeError):
3495 ctx.set_client_ca_list("spam")
3496 with pytest.raises(TypeError):
3497 ctx.set_client_ca_list(["spam"])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003498
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003499 def test_set_empty_ca_list(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003500 """
Alex Chanb7480992017-01-30 14:04:47 +00003501 If passed an empty list, `Context.set_client_ca_list` configures the
3502 context to send no CA names to the client and, on both the server and
3503 client sides, `Connection.get_client_ca_list` returns an empty list
3504 after the connection is set up.
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003505 """
3506 def no_ca(ctx):
3507 ctx.set_client_ca_list([])
3508 return []
3509 self._check_client_ca_list(no_ca)
3510
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003511 def test_set_one_ca_list(self):
3512 """
3513 If passed a list containing a single X509Name,
Alex Chanb7480992017-01-30 14:04:47 +00003514 `Context.set_client_ca_list` configures the context to send
Hynek Schlawack35618382015-09-05 21:54:25 +02003515 that CA name to the client and, on both the server and client sides,
Alex Chanb7480992017-01-30 14:04:47 +00003516 `Connection.get_client_ca_list` returns a list containing that
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003517 X509Name after the connection is set up.
3518 """
3519 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3520 cadesc = cacert.get_subject()
Hynek Schlawack35618382015-09-05 21:54:25 +02003521
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003522 def single_ca(ctx):
3523 ctx.set_client_ca_list([cadesc])
3524 return [cadesc]
3525 self._check_client_ca_list(single_ca)
3526
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003527 def test_set_multiple_ca_list(self):
3528 """
3529 If passed a list containing multiple X509Name objects,
Alex Chanb7480992017-01-30 14:04:47 +00003530 `Context.set_client_ca_list` configures the context to send
Hynek Schlawack35618382015-09-05 21:54:25 +02003531 those CA names to the client and, on both the server and client sides,
Alex Chanb7480992017-01-30 14:04:47 +00003532 `Connection.get_client_ca_list` returns a list containing those
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003533 X509Names after the connection is set up.
3534 """
3535 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3536 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3537
3538 sedesc = secert.get_subject()
3539 cldesc = clcert.get_subject()
3540
3541 def multiple_ca(ctx):
3542 L = [sedesc, cldesc]
3543 ctx.set_client_ca_list(L)
3544 return L
3545 self._check_client_ca_list(multiple_ca)
3546
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003547 def test_reset_ca_list(self):
3548 """
3549 If called multiple times, only the X509Names passed to the final call
Alex Chanb7480992017-01-30 14:04:47 +00003550 of `Context.set_client_ca_list` are used to configure the CA
Hynek Schlawack35618382015-09-05 21:54:25 +02003551 names sent to the client.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003552 """
3553 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3554 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3555 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3556
3557 cadesc = cacert.get_subject()
3558 sedesc = secert.get_subject()
3559 cldesc = clcert.get_subject()
3560
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003561 def changed_ca(ctx):
3562 ctx.set_client_ca_list([sedesc, cldesc])
3563 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003564 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003565 self._check_client_ca_list(changed_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003566
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003567 def test_mutated_ca_list(self):
3568 """
Alex Chanb7480992017-01-30 14:04:47 +00003569 If the list passed to `Context.set_client_ca_list` is mutated
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003570 afterwards, this does not affect the list of CA names sent to the
3571 client.
3572 """
3573 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3574 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3575
3576 cadesc = cacert.get_subject()
3577 sedesc = secert.get_subject()
3578
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003579 def mutated_ca(ctx):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003580 L = [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003581 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003582 L.append(sedesc)
3583 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003584 self._check_client_ca_list(mutated_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003585
Alex Chanb7480992017-01-30 14:04:47 +00003586 def test_add_client_ca_wrong_args(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003587 """
Alex Chanb7480992017-01-30 14:04:47 +00003588 `Context.add_client_ca` raises `TypeError` if called with
3589 a non-X509 object.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003590 """
3591 ctx = Context(TLSv1_METHOD)
Alex Chanb7480992017-01-30 14:04:47 +00003592 with pytest.raises(TypeError):
3593 ctx.add_client_ca("spam")
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003594
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003595 def test_one_add_client_ca(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003596 """
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003597 A certificate's subject can be added as a CA to be sent to the client
Alex Chanb7480992017-01-30 14:04:47 +00003598 with `Context.add_client_ca`.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003599 """
3600 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3601 cadesc = cacert.get_subject()
Hynek Schlawack35618382015-09-05 21:54:25 +02003602
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003603 def single_ca(ctx):
3604 ctx.add_client_ca(cacert)
3605 return [cadesc]
3606 self._check_client_ca_list(single_ca)
3607
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003608 def test_multiple_add_client_ca(self):
3609 """
3610 Multiple CA names can be sent to the client by calling
Alex Chanb7480992017-01-30 14:04:47 +00003611 `Context.add_client_ca` with multiple X509 objects.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003612 """
3613 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3614 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3615
3616 cadesc = cacert.get_subject()
3617 sedesc = secert.get_subject()
3618
3619 def multiple_ca(ctx):
3620 ctx.add_client_ca(cacert)
3621 ctx.add_client_ca(secert)
3622 return [cadesc, sedesc]
3623 self._check_client_ca_list(multiple_ca)
3624
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003625 def test_set_and_add_client_ca(self):
3626 """
Alex Chanb7480992017-01-30 14:04:47 +00003627 A call to `Context.set_client_ca_list` followed by a call to
3628 `Context.add_client_ca` results in using the CA names from the
Hynek Schlawack35618382015-09-05 21:54:25 +02003629 first call and the CA name from the second call.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003630 """
3631 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3632 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3633 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3634
3635 cadesc = cacert.get_subject()
3636 sedesc = secert.get_subject()
3637 cldesc = clcert.get_subject()
3638
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003639 def mixed_set_add_ca(ctx):
3640 ctx.set_client_ca_list([cadesc, sedesc])
3641 ctx.add_client_ca(clcert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003642 return [cadesc, sedesc, cldesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003643 self._check_client_ca_list(mixed_set_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003644
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003645 def test_set_after_add_client_ca(self):
3646 """
Alex Chanb7480992017-01-30 14:04:47 +00003647 A call to `Context.set_client_ca_list` after a call to
3648 `Context.add_client_ca` replaces the CA name specified by the
Hynek Schlawack35618382015-09-05 21:54:25 +02003649 former call with the names specified by the latter call.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003650 """
3651 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3652 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3653 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3654
3655 cadesc = cacert.get_subject()
3656 sedesc = secert.get_subject()
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003657
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003658 def set_replaces_add_ca(ctx):
3659 ctx.add_client_ca(clcert)
3660 ctx.set_client_ca_list([cadesc])
3661 ctx.add_client_ca(secert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003662 return [cadesc, sedesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003663 self._check_client_ca_list(set_replaces_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003664
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003665
Alex Chanb7480992017-01-30 14:04:47 +00003666class TestInfoConstants(object):
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003667 """
3668 Tests for assorted constants exposed for use in info callbacks.
3669 """
3670 def test_integers(self):
3671 """
3672 All of the info constants are integers.
3673
3674 This is a very weak test. It would be nice to have one that actually
3675 verifies that as certain info events happen, the value passed to the
3676 info callback matches up with the constant exposed by OpenSSL.SSL.
3677 """
3678 for const in [
Alex Gaynor5af32d02016-09-24 01:52:21 -04003679 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK,
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003680 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
3681 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
3682 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
Hynek Schlawack35618382015-09-05 21:54:25 +02003683 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE
3684 ]:
Alex Gaynor5af32d02016-09-24 01:52:21 -04003685 assert isinstance(const, int)
3686
3687 # These constants don't exist on OpenSSL 1.1.0
3688 for const in [
3689 SSL_ST_INIT, SSL_ST_BEFORE, SSL_ST_OK, SSL_ST_RENEGOTIATE
3690 ]:
3691 assert const is None or isinstance(const, int)
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003692
Ziga Seilnacht44611bf2009-08-31 20:49:30 +02003693
Cory Benfield1d142142016-03-30 11:51:45 +01003694class TestRequires(object):
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003695 """
3696 Tests for the decorator factory used to conditionally raise
Cory Benfield1d142142016-03-30 11:51:45 +01003697 NotImplementedError when older OpenSSLs are used.
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003698 """
3699 def test_available(self):
3700 """
3701 When the OpenSSL functionality is available the decorated functions
3702 work appropriately.
3703 """
3704 feature_guard = _make_requires(True, "Error text")
3705 results = []
3706
3707 @feature_guard
3708 def inner():
3709 results.append(True)
3710 return True
3711
Cory Benfield2333e5e2016-03-30 14:24:16 +01003712 assert inner() is True
3713 assert [True] == results
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003714
3715 def test_unavailable(self):
3716 """
3717 When the OpenSSL functionality is not available the decorated function
3718 does not execute and NotImplementedError is raised.
3719 """
3720 feature_guard = _make_requires(False, "Error text")
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003721
3722 @feature_guard
Alex Chanfb078d82017-04-20 11:16:15 +01003723 def inner(): # pragma: nocover
3724 pytest.fail("Should not be called")
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003725
Cory Benfield1d142142016-03-30 11:51:45 +01003726 with pytest.raises(NotImplementedError) as e:
3727 inner()
3728
3729 assert "Error text" in str(e.value)
Cory Benfield496652a2017-01-24 11:42:56 +00003730
3731
Alex Chanb7480992017-01-30 14:04:47 +00003732class TestOCSP(object):
Cory Benfield496652a2017-01-24 11:42:56 +00003733 """
3734 Tests for PyOpenSSL's OCSP stapling support.
3735 """
3736 sample_ocsp_data = b"this is totally ocsp data"
3737
3738 def _client_connection(self, callback, data, request_ocsp=True):
3739 """
3740 Builds a client connection suitable for using OCSP.
3741
3742 :param callback: The callback to register for OCSP.
3743 :param data: The opaque data object that will be handed to the
3744 OCSP callback.
3745 :param request_ocsp: Whether the client will actually ask for OCSP
3746 stapling. Useful for testing only.
3747 """
3748 ctx = Context(SSLv23_METHOD)
3749 ctx.set_ocsp_client_callback(callback, data)
3750 client = Connection(ctx)
3751
3752 if request_ocsp:
3753 client.request_ocsp()
3754
3755 client.set_connect_state()
3756 return client
3757
3758 def _server_connection(self, callback, data):
3759 """
3760 Builds a server connection suitable for using OCSP.
3761
3762 :param callback: The callback to register for OCSP.
3763 :param data: The opaque data object that will be handed to the
3764 OCSP callback.
3765 """
3766 ctx = Context(SSLv23_METHOD)
3767 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
3768 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
3769 ctx.set_ocsp_server_callback(callback, data)
3770 server = Connection(ctx)
3771 server.set_accept_state()
3772 return server
3773
3774 def test_callbacks_arent_called_by_default(self):
3775 """
3776 If both the client and the server have registered OCSP callbacks, but
3777 the client does not send the OCSP request, neither callback gets
3778 called.
3779 """
Alex Chanfb078d82017-04-20 11:16:15 +01003780 def ocsp_callback(*args, **kwargs): # pragma: nocover
3781 pytest.fail("Should not be called")
Cory Benfield496652a2017-01-24 11:42:56 +00003782
3783 client = self._client_connection(
3784 callback=ocsp_callback, data=None, request_ocsp=False
3785 )
3786 server = self._server_connection(callback=ocsp_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00003787 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003788
Cory Benfield496652a2017-01-24 11:42:56 +00003789 def test_client_negotiates_without_server(self):
3790 """
3791 If the client wants to do OCSP but the server does not, the handshake
3792 succeeds, and the client callback fires with an empty byte string.
3793 """
3794 called = []
3795
3796 def ocsp_callback(conn, ocsp_data, ignored):
3797 called.append(ocsp_data)
3798 return True
3799
3800 client = self._client_connection(callback=ocsp_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00003801 server = loopback_server_factory(socket=None)
3802 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003803
3804 assert len(called) == 1
3805 assert called[0] == b''
3806
3807 def test_client_receives_servers_data(self):
3808 """
3809 The data the server sends in its callback is received by the client.
3810 """
3811 calls = []
3812
3813 def server_callback(*args, **kwargs):
3814 return self.sample_ocsp_data
3815
3816 def client_callback(conn, ocsp_data, ignored):
3817 calls.append(ocsp_data)
3818 return True
3819
3820 client = self._client_connection(callback=client_callback, data=None)
3821 server = self._server_connection(callback=server_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00003822 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003823
3824 assert len(calls) == 1
3825 assert calls[0] == self.sample_ocsp_data
3826
3827 def test_callbacks_are_invoked_with_connections(self):
3828 """
3829 The first arguments to both callbacks are their respective connections.
3830 """
3831 client_calls = []
3832 server_calls = []
3833
3834 def client_callback(conn, *args, **kwargs):
3835 client_calls.append(conn)
3836 return True
3837
3838 def server_callback(conn, *args, **kwargs):
3839 server_calls.append(conn)
3840 return self.sample_ocsp_data
3841
3842 client = self._client_connection(callback=client_callback, data=None)
3843 server = self._server_connection(callback=server_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00003844 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003845
3846 assert len(client_calls) == 1
3847 assert len(server_calls) == 1
3848 assert client_calls[0] is client
3849 assert server_calls[0] is server
3850
3851 def test_opaque_data_is_passed_through(self):
3852 """
3853 Both callbacks receive an opaque, user-provided piece of data in their
3854 callbacks as the final argument.
3855 """
3856 calls = []
3857
3858 def server_callback(*args):
3859 calls.append(args)
3860 return self.sample_ocsp_data
3861
3862 def client_callback(*args):
3863 calls.append(args)
3864 return True
3865
3866 sentinel = object()
3867
3868 client = self._client_connection(
3869 callback=client_callback, data=sentinel
3870 )
3871 server = self._server_connection(
3872 callback=server_callback, data=sentinel
3873 )
Alex Chanb7480992017-01-30 14:04:47 +00003874 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003875
3876 assert len(calls) == 2
3877 assert calls[0][-1] is sentinel
3878 assert calls[1][-1] is sentinel
3879
3880 def test_server_returns_empty_string(self):
3881 """
3882 If the server returns an empty bytestring from its callback, the
3883 client callback is called with the empty bytestring.
3884 """
3885 client_calls = []
3886
3887 def server_callback(*args):
3888 return b''
3889
3890 def client_callback(conn, ocsp_data, ignored):
3891 client_calls.append(ocsp_data)
3892 return True
3893
3894 client = self._client_connection(callback=client_callback, data=None)
3895 server = self._server_connection(callback=server_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00003896 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003897
3898 assert len(client_calls) == 1
3899 assert client_calls[0] == b''
3900
3901 def test_client_returns_false_terminates_handshake(self):
3902 """
3903 If the client returns False from its callback, the handshake fails.
3904 """
3905 def server_callback(*args):
3906 return self.sample_ocsp_data
3907
3908 def client_callback(*args):
3909 return False
3910
3911 client = self._client_connection(callback=client_callback, data=None)
3912 server = self._server_connection(callback=server_callback, data=None)
3913
3914 with pytest.raises(Error):
Alex Chanb7480992017-01-30 14:04:47 +00003915 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003916
3917 def test_exceptions_in_client_bubble_up(self):
3918 """
3919 The callbacks thrown in the client callback bubble up to the caller.
3920 """
3921 class SentinelException(Exception):
3922 pass
3923
3924 def server_callback(*args):
3925 return self.sample_ocsp_data
3926
3927 def client_callback(*args):
3928 raise SentinelException()
3929
3930 client = self._client_connection(callback=client_callback, data=None)
3931 server = self._server_connection(callback=server_callback, data=None)
3932
3933 with pytest.raises(SentinelException):
Alex Chanb7480992017-01-30 14:04:47 +00003934 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003935
3936 def test_exceptions_in_server_bubble_up(self):
3937 """
3938 The callbacks thrown in the server callback bubble up to the caller.
3939 """
3940 class SentinelException(Exception):
3941 pass
3942
3943 def server_callback(*args):
3944 raise SentinelException()
3945
Alex Chanfb078d82017-04-20 11:16:15 +01003946 def client_callback(*args): # pragma: nocover
Cory Benfield496652a2017-01-24 11:42:56 +00003947 pytest.fail("Should not be called")
3948
3949 client = self._client_connection(callback=client_callback, data=None)
3950 server = self._server_connection(callback=server_callback, data=None)
3951
3952 with pytest.raises(SentinelException):
Alex Chanb7480992017-01-30 14:04:47 +00003953 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003954
3955 def test_server_must_return_bytes(self):
3956 """
3957 The server callback must return a bytestring, or a TypeError is thrown.
3958 """
3959 def server_callback(*args):
3960 return self.sample_ocsp_data.decode('ascii')
3961
Alex Chanfb078d82017-04-20 11:16:15 +01003962 def client_callback(*args): # pragma: nocover
Cory Benfield496652a2017-01-24 11:42:56 +00003963 pytest.fail("Should not be called")
3964
3965 client = self._client_connection(callback=client_callback, data=None)
3966 server = self._server_connection(callback=server_callback, data=None)
3967
3968 with pytest.raises(TypeError):
Alex Chanb7480992017-01-30 14:04:47 +00003969 handshake_in_memory(client, server)