blob: 1ca7f8b5d2b18e338c2444c4f4bc328719b4d551 [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)
Alex Gaynoraa32e712017-06-29 20:56:12 -07002512 if SSL_ST_INIT is None:
2513 v1 = TLSv1_2_METHOD
2514 v2 = TLSv1_METHOD
2515 elif hasattr(_lib, "SSLv3_method"):
Alex Gaynor5af32d02016-09-24 01:52:21 -04002516 v1 = TLSv1_METHOD
2517 v2 = SSLv3_METHOD
2518 else:
Alex Gaynoraa32e712017-06-29 20:56:12 -07002519 pytest.skip("Test requires either OpenSSL 1.1.0 or SSLv3")
Alex Gaynor5af32d02016-09-24 01:52:21 -04002520
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002521 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2522 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
Alex Gaynor5af32d02016-09-24 01:52:21 -04002523 ctx = Context(v1)
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002524 ctx.use_privatekey(key)
2525 ctx.use_certificate(cert)
2526 ctx.set_session_id("unity-test")
2527
2528 def makeServer(socket):
2529 server = Connection(ctx, socket)
2530 server.set_accept_state()
2531 return server
2532
Alex Gaynor5af32d02016-09-24 01:52:21 -04002533 def makeOriginalClient(socket):
2534 client = Connection(Context(v1), socket)
2535 client.set_connect_state()
2536 return client
2537
Alex Chan1c0cb662017-01-30 07:13:30 +00002538 originalServer, originalClient = loopback(
2539 server_factory=makeServer, client_factory=makeOriginalClient)
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002540 originalSession = originalClient.get_session()
2541
2542 def makeClient(socket):
2543 # Intentionally use a different, incompatible method here.
Alex Gaynor5af32d02016-09-24 01:52:21 -04002544 client = Connection(Context(v2), socket)
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002545 client.set_connect_state()
2546 client.set_session(originalSession)
2547 return client
2548
Alex Chan1c0cb662017-01-30 07:13:30 +00002549 with pytest.raises(Error):
2550 loopback(client_factory=makeClient, server_factory=makeServer)
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002551
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002552 def test_wantWriteError(self):
2553 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002554 `Connection` methods which generate output raise
2555 `OpenSSL.SSL.WantWriteError` if writing to the connection's BIO
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002556 fail indicating a should-write state.
2557 """
2558 client_socket, server_socket = socket_pair()
2559 # Fill up the client's send buffer so Connection won't be able to write
Jean-Paul Calderonebbff8b92014-03-22 14:20:30 -04002560 # anything. Only write a single byte at a time so we can be sure we
2561 # completely fill the buffer. Even though the socket API is allowed to
2562 # signal a short write via its return value it seems this doesn't
2563 # always happen on all platforms (FreeBSD and OS X particular) for the
2564 # very last bit of available buffer space.
2565 msg = b"x"
2566 for i in range(1024 * 1024 * 4):
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002567 try:
2568 client_socket.send(msg)
2569 except error as e:
2570 if e.errno == EWOULDBLOCK:
2571 break
2572 raise
2573 else:
Alex Chan1c0cb662017-01-30 07:13:30 +00002574 pytest.fail(
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002575 "Failed to fill socket buffer, cannot test BIO want write")
2576
2577 ctx = Context(TLSv1_METHOD)
2578 conn = Connection(ctx, client_socket)
2579 # Client's speak first, so make it an SSL client
2580 conn.set_connect_state()
Alex Chan1c0cb662017-01-30 07:13:30 +00002581 with pytest.raises(WantWriteError):
2582 conn.do_handshake()
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002583
2584 # XXX want_read
2585
Fedor Brunner416f4a12014-03-28 13:18:38 +01002586 def test_get_finished_before_connect(self):
Fedor Brunner5747b932014-03-05 14:22:34 +01002587 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002588 `Connection.get_finished` returns `None` before TLS handshake
2589 is completed.
Fedor Brunner5747b932014-03-05 14:22:34 +01002590 """
Fedor Brunner5747b932014-03-05 14:22:34 +01002591 ctx = Context(TLSv1_METHOD)
2592 connection = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002593 assert connection.get_finished() is None
Fedor Brunner416f4a12014-03-28 13:18:38 +01002594
2595 def test_get_peer_finished_before_connect(self):
2596 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002597 `Connection.get_peer_finished` returns `None` before TLS handshake
2598 is completed.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002599 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002600 ctx = Context(TLSv1_METHOD)
2601 connection = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002602 assert connection.get_peer_finished() is None
Fedor Brunner5747b932014-03-05 14:22:34 +01002603
Fedor Brunner416f4a12014-03-28 13:18:38 +01002604 def test_get_finished(self):
2605 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002606 `Connection.get_finished` method returns the TLS Finished message send
2607 from client, or server. Finished messages are send during
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002608 TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002609 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002610 server, client = loopback()
Fedor Brunner416f4a12014-03-28 13:18:38 +01002611
Alex Chan1c0cb662017-01-30 07:13:30 +00002612 assert server.get_finished() is not None
2613 assert len(server.get_finished()) > 0
Fedor Brunner416f4a12014-03-28 13:18:38 +01002614
2615 def test_get_peer_finished(self):
2616 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002617 `Connection.get_peer_finished` method returns the TLS Finished
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002618 message received from client, or server. Finished messages are send
2619 during TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002620 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002621 server, client = loopback()
Fedor Brunner416f4a12014-03-28 13:18:38 +01002622
Alex Chan1c0cb662017-01-30 07:13:30 +00002623 assert server.get_peer_finished() is not None
2624 assert len(server.get_peer_finished()) > 0
Fedor Brunner5747b932014-03-05 14:22:34 +01002625
Fedor Brunner416f4a12014-03-28 13:18:38 +01002626 def test_tls_finished_message_symmetry(self):
2627 """
Hynek Schlawackdddd1112015-09-05 21:12:30 +02002628 The TLS Finished message send by server must be the TLS Finished
2629 message received by client.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002630
Hynek Schlawackdddd1112015-09-05 21:12:30 +02002631 The TLS Finished message send by client must be the TLS Finished
2632 message received by server.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002633 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002634 server, client = loopback()
Fedor Brunner416f4a12014-03-28 13:18:38 +01002635
Alex Chan1c0cb662017-01-30 07:13:30 +00002636 assert server.get_finished() == client.get_peer_finished()
2637 assert client.get_finished() == server.get_peer_finished()
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002638
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002639 def test_get_cipher_name_before_connect(self):
2640 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002641 `Connection.get_cipher_name` returns `None` if no connection
2642 has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002643 """
2644 ctx = Context(TLSv1_METHOD)
2645 conn = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002646 assert conn.get_cipher_name() is None
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002647
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002648 def test_get_cipher_name(self):
2649 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002650 `Connection.get_cipher_name` returns a `unicode` string giving the
2651 name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002652 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002653 server, client = loopback()
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002654 server_cipher_name, client_cipher_name = \
2655 server.get_cipher_name(), client.get_cipher_name()
2656
Alex Chan1c0cb662017-01-30 07:13:30 +00002657 assert isinstance(server_cipher_name, text_type)
2658 assert isinstance(client_cipher_name, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002659
Alex Chan1c0cb662017-01-30 07:13:30 +00002660 assert server_cipher_name == client_cipher_name
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002661
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002662 def test_get_cipher_version_before_connect(self):
2663 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002664 `Connection.get_cipher_version` returns `None` if no connection
2665 has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002666 """
2667 ctx = Context(TLSv1_METHOD)
2668 conn = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002669 assert conn.get_cipher_version() is None
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002670
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002671 def test_get_cipher_version(self):
2672 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002673 `Connection.get_cipher_version` returns a `unicode` string giving
2674 the protocol name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002675 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002676 server, client = loopback()
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002677 server_cipher_version, client_cipher_version = \
2678 server.get_cipher_version(), client.get_cipher_version()
2679
Alex Chan1c0cb662017-01-30 07:13:30 +00002680 assert isinstance(server_cipher_version, text_type)
2681 assert isinstance(client_cipher_version, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002682
Alex Chan1c0cb662017-01-30 07:13:30 +00002683 assert server_cipher_version == client_cipher_version
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002684
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002685 def test_get_cipher_bits_before_connect(self):
2686 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002687 `Connection.get_cipher_bits` returns `None` if no connection has
2688 been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002689 """
2690 ctx = Context(TLSv1_METHOD)
2691 conn = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002692 assert conn.get_cipher_bits() is None
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002693
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002694 def test_get_cipher_bits(self):
2695 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002696 `Connection.get_cipher_bits` returns the number of secret bits
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002697 of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002698 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002699 server, client = loopback()
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002700 server_cipher_bits, client_cipher_bits = \
2701 server.get_cipher_bits(), client.get_cipher_bits()
2702
Alex Chan1c0cb662017-01-30 07:13:30 +00002703 assert isinstance(server_cipher_bits, int)
2704 assert isinstance(client_cipher_bits, int)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002705
Alex Chan1c0cb662017-01-30 07:13:30 +00002706 assert server_cipher_bits == client_cipher_bits
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002707
Jim Shaverabff1882015-05-27 09:15:55 -04002708 def test_get_protocol_version_name(self):
2709 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002710 `Connection.get_protocol_version_name()` returns a string giving the
2711 protocol version of the current connection.
Jim Shaverabff1882015-05-27 09:15:55 -04002712 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002713 server, client = loopback()
Jim Shaverabff1882015-05-27 09:15:55 -04002714 client_protocol_version_name = client.get_protocol_version_name()
2715 server_protocol_version_name = server.get_protocol_version_name()
2716
Alex Chan1c0cb662017-01-30 07:13:30 +00002717 assert isinstance(server_protocol_version_name, text_type)
2718 assert isinstance(client_protocol_version_name, text_type)
Jim Shaverabff1882015-05-27 09:15:55 -04002719
Alex Chan1c0cb662017-01-30 07:13:30 +00002720 assert server_protocol_version_name == client_protocol_version_name
Jim Shaverabff1882015-05-27 09:15:55 -04002721
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002722 def test_get_protocol_version(self):
2723 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002724 `Connection.get_protocol_version()` returns an integer
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002725 giving the protocol version of the current connection.
2726 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002727 server, client = loopback()
Jim Shaver85a4dff2015-04-27 17:42:46 -04002728 client_protocol_version = client.get_protocol_version()
2729 server_protocol_version = server.get_protocol_version()
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002730
Alex Chan1c0cb662017-01-30 07:13:30 +00002731 assert isinstance(server_protocol_version, int)
2732 assert isinstance(client_protocol_version, int)
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002733
Alex Chan1c0cb662017-01-30 07:13:30 +00002734 assert server_protocol_version == client_protocol_version
2735
2736 def test_wantReadError(self):
2737 """
2738 `Connection.bio_read` raises `OpenSSL.SSL.WantReadError` if there are
2739 no bytes available to be read from the BIO.
2740 """
2741 ctx = Context(TLSv1_METHOD)
2742 conn = Connection(ctx, None)
2743 with pytest.raises(WantReadError):
2744 conn.bio_read(1024)
2745
Alex Chanfb078d82017-04-20 11:16:15 +01002746 @pytest.mark.parametrize('bufsize', [1.0, None, object(), 'bufsize'])
2747 def test_bio_read_wrong_args(self, bufsize):
2748 """
2749 `Connection.bio_read` raises `TypeError` if passed a non-integer
2750 argument.
2751 """
2752 ctx = Context(TLSv1_METHOD)
2753 conn = Connection(ctx, None)
2754 with pytest.raises(TypeError):
2755 conn.bio_read(bufsize)
2756
Alex Chan1c0cb662017-01-30 07:13:30 +00002757 def test_buffer_size(self):
2758 """
2759 `Connection.bio_read` accepts an integer giving the maximum number
2760 of bytes to read and return.
2761 """
2762 ctx = Context(TLSv1_METHOD)
2763 conn = Connection(ctx, None)
2764 conn.set_connect_state()
2765 try:
2766 conn.do_handshake()
2767 except WantReadError:
2768 pass
2769 data = conn.bio_read(2)
2770 assert 2 == len(data)
2771
2772 @skip_if_py3
2773 def test_buffer_size_long(self):
2774 """
2775 On Python 2 `Connection.bio_read` accepts values of type `long` as
2776 well as `int`.
2777 """
2778 ctx = Context(TLSv1_METHOD)
2779 conn = Connection(ctx, None)
2780 conn.set_connect_state()
2781 try:
2782 conn.do_handshake()
2783 except WantReadError:
2784 pass
2785 data = conn.bio_read(long(2))
2786 assert 2 == len(data)
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002787
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002788
Alex Chanb7480992017-01-30 14:04:47 +00002789class TestConnectionGetCipherList(object):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002790 """
Alex Chanb7480992017-01-30 14:04:47 +00002791 Tests for `Connection.get_cipher_list`.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002792 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002793 def test_result(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002794 """
Alex Chanb7480992017-01-30 14:04:47 +00002795 `Connection.get_cipher_list` returns a list of `bytes` giving the
2796 names of the ciphers which might be used.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002797 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002798 connection = Connection(Context(TLSv1_METHOD), None)
2799 ciphers = connection.get_cipher_list()
Alex Chanb7480992017-01-30 14:04:47 +00002800 assert isinstance(ciphers, list)
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002801 for cipher in ciphers:
Alex Chanb7480992017-01-30 14:04:47 +00002802 assert isinstance(cipher, str)
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002803
2804
Maximilian Hils868dc3c2017-02-10 14:56:55 +01002805class VeryLarge(bytes):
2806 """
2807 Mock object so that we don't have to allocate 2**31 bytes
2808 """
2809 def __len__(self):
2810 return 2**31
2811
2812
Alex Chanb7480992017-01-30 14:04:47 +00002813class TestConnectionSend(object):
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002814 """
Alex Chanb7480992017-01-30 14:04:47 +00002815 Tests for `Connection.send`.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002816 """
2817 def test_wrong_args(self):
2818 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002819 When called with arguments other than string argument for its first
Alex Chanb7480992017-01-30 14:04:47 +00002820 parameter, `Connection.send` raises `TypeError`.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002821 """
2822 connection = Connection(Context(TLSv1_METHOD), None)
Alex Chanb7480992017-01-30 14:04:47 +00002823 with pytest.raises(TypeError):
2824 connection.send(object())
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002825
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002826 def test_short_bytes(self):
2827 """
Alex Chanb7480992017-01-30 14:04:47 +00002828 When passed a short byte string, `Connection.send` transmits all of it
2829 and returns the number of bytes sent.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002830 """
Alex Chanb7480992017-01-30 14:04:47 +00002831 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002832 count = server.send(b'xy')
Alex Chanb7480992017-01-30 14:04:47 +00002833 assert count == 2
2834 assert client.recv(2) == b'xy'
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002835
Abraham Martinef063482015-03-25 14:06:24 +00002836 def test_text(self):
2837 """
Alex Chanb7480992017-01-30 14:04:47 +00002838 When passed a text, `Connection.send` transmits all of it and
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002839 returns the number of bytes sent. It also raises a DeprecationWarning.
Abraham Martinef063482015-03-25 14:06:24 +00002840 """
Alex Chanb7480992017-01-30 14:04:47 +00002841 server, client = loopback()
2842 with pytest.warns(DeprecationWarning) as w:
Abraham Martinef063482015-03-25 14:06:24 +00002843 simplefilter("always")
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002844 count = server.send(b"xy".decode("ascii"))
Alex Chanb7480992017-01-30 14:04:47 +00002845 assert (
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002846 "{0} for buf is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002847 WARNING_TYPE_EXPECTED
Alex Chanb7480992017-01-30 14:04:47 +00002848 ) == str(w[-1].message))
2849 assert count == 2
2850 assert client.recv(2) == b'xy'
Abraham Martinef063482015-03-25 14:06:24 +00002851
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002852 @skip_if_py26
2853 def test_short_memoryview(self):
2854 """
2855 When passed a memoryview onto a small number of bytes,
Alex Chanb7480992017-01-30 14:04:47 +00002856 `Connection.send` transmits all of them and returns the number
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002857 of bytes sent.
2858 """
Alex Chanb7480992017-01-30 14:04:47 +00002859 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002860 count = server.send(memoryview(b'xy'))
Alex Chanb7480992017-01-30 14:04:47 +00002861 assert count == 2
2862 assert client.recv(2) == b'xy'
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002863
Hynek Schlawack8e94f1b2015-09-05 21:31:00 +02002864 @skip_if_py3
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002865 def test_short_buffer(self):
2866 """
2867 When passed a buffer containing a small number of bytes,
Alex Chanb7480992017-01-30 14:04:47 +00002868 `Connection.send` transmits all of them and returns the number
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002869 of bytes sent.
2870 """
Alex Chanb7480992017-01-30 14:04:47 +00002871 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002872 count = server.send(buffer(b'xy'))
Alex Chanb7480992017-01-30 14:04:47 +00002873 assert count == 2
2874 assert client.recv(2) == b'xy'
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02002875
Maximilian Hils868dc3c2017-02-10 14:56:55 +01002876 @pytest.mark.skipif(
2877 sys.maxsize < 2**31,
2878 reason="sys.maxsize < 2**31 - test requires 64 bit"
2879 )
2880 def test_buf_too_large(self):
2881 """
2882 When passed a buffer containing >= 2**31 bytes,
2883 `Connection.send` bails out as SSL_write only
2884 accepts an int for the buffer length.
2885 """
2886 connection = Connection(Context(TLSv1_METHOD), None)
2887 with pytest.raises(ValueError) as exc_info:
2888 connection.send(VeryLarge())
2889 exc_info.match(r"Cannot send more than .+ bytes at once")
2890
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05002891
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002892def _make_memoryview(size):
2893 """
2894 Create a new ``memoryview`` wrapped around a ``bytearray`` of the given
2895 size.
2896 """
2897 return memoryview(bytearray(size))
2898
2899
Alex Chanb7480992017-01-30 14:04:47 +00002900class TestConnectionRecvInto(object):
Cory Benfield62d10332014-06-15 10:03:41 +01002901 """
Alex Chanb7480992017-01-30 14:04:47 +00002902 Tests for `Connection.recv_into`.
Cory Benfield62d10332014-06-15 10:03:41 +01002903 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002904 def _no_length_test(self, factory):
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04002905 """
Alex Chanb7480992017-01-30 14:04:47 +00002906 Assert that when the given buffer is passed to `Connection.recv_into`,
2907 whatever bytes are available to be received that fit into that buffer
2908 are written into that buffer.
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04002909 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002910 output_buffer = factory(5)
2911
Alex Chanb7480992017-01-30 14:04:47 +00002912 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002913 server.send(b'xy')
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04002914
Alex Chanb7480992017-01-30 14:04:47 +00002915 assert client.recv_into(output_buffer) == 2
2916 assert output_buffer == bytearray(b'xy\x00\x00\x00')
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04002917
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002918 def test_bytearray_no_length(self):
Cory Benfield62d10332014-06-15 10:03:41 +01002919 """
Alex Chanb7480992017-01-30 14:04:47 +00002920 `Connection.recv_into` can be passed a `bytearray` instance and data
2921 in the receive buffer is written to it.
Cory Benfield62d10332014-06-15 10:03:41 +01002922 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002923 self._no_length_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01002924
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002925 def _respects_length_test(self, factory):
Cory Benfield62d10332014-06-15 10:03:41 +01002926 """
Alex Chanb7480992017-01-30 14:04:47 +00002927 Assert that when the given buffer is passed to `Connection.recv_into`
2928 along with a value for `nbytes` that is less than the size of that
2929 buffer, only `nbytes` bytes are written into the buffer.
Cory Benfield62d10332014-06-15 10:03:41 +01002930 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002931 output_buffer = factory(10)
2932
Alex Chanb7480992017-01-30 14:04:47 +00002933 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002934 server.send(b'abcdefghij')
Cory Benfield62d10332014-06-15 10:03:41 +01002935
Alex Chanb7480992017-01-30 14:04:47 +00002936 assert client.recv_into(output_buffer, 5) == 5
2937 assert output_buffer == bytearray(b'abcde\x00\x00\x00\x00\x00')
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002938
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002939 def test_bytearray_respects_length(self):
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002940 """
Alex Chanb7480992017-01-30 14:04:47 +00002941 When called with a `bytearray` instance, `Connection.recv_into`
2942 respects the `nbytes` parameter and doesn't copy in more than that
2943 number of bytes.
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002944 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002945 self._respects_length_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01002946
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002947 def _doesnt_overfill_test(self, factory):
Cory Benfield62d10332014-06-15 10:03:41 +01002948 """
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002949 Assert that if there are more bytes available to be read from the
2950 receive buffer than would fit into the buffer passed to
Alex Chanb7480992017-01-30 14:04:47 +00002951 `Connection.recv_into`, only as many as fit are written into it.
Cory Benfield62d10332014-06-15 10:03:41 +01002952 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002953 output_buffer = factory(5)
2954
Alex Chanb7480992017-01-30 14:04:47 +00002955 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002956 server.send(b'abcdefghij')
Cory Benfield62d10332014-06-15 10:03:41 +01002957
Alex Chanb7480992017-01-30 14:04:47 +00002958 assert client.recv_into(output_buffer) == 5
2959 assert output_buffer == bytearray(b'abcde')
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002960 rest = client.recv(5)
Alex Chanb7480992017-01-30 14:04:47 +00002961 assert b'fghij' == rest
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002962
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002963 def test_bytearray_doesnt_overfill(self):
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002964 """
Alex Chanb7480992017-01-30 14:04:47 +00002965 When called with a `bytearray` instance, `Connection.recv_into`
2966 respects the size of the array and doesn't write more bytes into it
2967 than will fit.
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002968 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002969 self._doesnt_overfill_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01002970
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002971 def test_bytearray_really_doesnt_overfill(self):
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04002972 """
Alex Chanb7480992017-01-30 14:04:47 +00002973 When called with a `bytearray` instance and an `nbytes` value that is
2974 too large, `Connection.recv_into` respects the size of the array and
2975 not the `nbytes` value and doesn't write more bytes into the buffer
2976 than will fit.
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04002977 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002978 self._doesnt_overfill_test(bytearray)
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04002979
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002980 def test_peek(self):
Alex Chanb7480992017-01-30 14:04:47 +00002981 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002982 server.send(b'xy')
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002983
2984 for _ in range(2):
2985 output_buffer = bytearray(5)
Alex Chanb7480992017-01-30 14:04:47 +00002986 assert client.recv_into(output_buffer, flags=MSG_PEEK) == 2
2987 assert output_buffer == bytearray(b'xy\x00\x00\x00')
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002988
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002989 @skip_if_py26
2990 def test_memoryview_no_length(self):
2991 """
Alex Chanb7480992017-01-30 14:04:47 +00002992 `Connection.recv_into` can be passed a `memoryview` instance and data
2993 in the receive buffer is written to it.
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002994 """
2995 self._no_length_test(_make_memoryview)
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002996
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002997 @skip_if_py26
2998 def test_memoryview_respects_length(self):
2999 """
Alex Chanb7480992017-01-30 14:04:47 +00003000 When called with a `memoryview` instance, `Connection.recv_into`
3001 respects the ``nbytes`` parameter and doesn't copy more than that
3002 number of bytes in.
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003003 """
3004 self._respects_length_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01003005
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003006 @skip_if_py26
3007 def test_memoryview_doesnt_overfill(self):
3008 """
Alex Chanb7480992017-01-30 14:04:47 +00003009 When called with a `memoryview` instance, `Connection.recv_into`
3010 respects the size of the array and doesn't write more bytes into it
3011 than will fit.
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003012 """
3013 self._doesnt_overfill_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01003014
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003015 @skip_if_py26
3016 def test_memoryview_really_doesnt_overfill(self):
3017 """
Alex Chanb7480992017-01-30 14:04:47 +00003018 When called with a `memoryview` instance and an `nbytes` value that is
3019 too large, `Connection.recv_into` respects the size of the array and
3020 not the `nbytes` value and doesn't write more bytes into the buffer
3021 than will fit.
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003022 """
3023 self._doesnt_overfill_test(_make_memoryview)
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003024
Cory Benfield62d10332014-06-15 10:03:41 +01003025
Alex Chanb7480992017-01-30 14:04:47 +00003026class TestConnectionSendall(object):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003027 """
Alex Chanb7480992017-01-30 14:04:47 +00003028 Tests for `Connection.sendall`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003029 """
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003030 def test_wrong_args(self):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003031 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003032 When called with arguments other than a string argument for its first
Alex Chanb7480992017-01-30 14:04:47 +00003033 parameter, `Connection.sendall` raises `TypeError`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003034 """
3035 connection = Connection(Context(TLSv1_METHOD), None)
Alex Chanb7480992017-01-30 14:04:47 +00003036 with pytest.raises(TypeError):
3037 connection.sendall(object())
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003038
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003039 def test_short(self):
3040 """
Alex Chanb7480992017-01-30 14:04:47 +00003041 `Connection.sendall` transmits all of the bytes in the string
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003042 passed to it.
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003043 """
Alex Chanb7480992017-01-30 14:04:47 +00003044 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04003045 server.sendall(b'x')
Alex Chanb7480992017-01-30 14:04:47 +00003046 assert client.recv(1) == b'x'
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003047
Abraham Martinef063482015-03-25 14:06:24 +00003048 def test_text(self):
3049 """
Alex Chanb7480992017-01-30 14:04:47 +00003050 `Connection.sendall` transmits all the content in the string passed
3051 to it, raising a DeprecationWarning in case of this being a text.
Abraham Martinef063482015-03-25 14:06:24 +00003052 """
Alex Chanb7480992017-01-30 14:04:47 +00003053 server, client = loopback()
3054 with pytest.warns(DeprecationWarning) as w:
Abraham Martinef063482015-03-25 14:06:24 +00003055 simplefilter("always")
Jean-Paul Calderone8dc37a12015-03-29 08:16:52 -04003056 server.sendall(b"x".decode("ascii"))
Alex Chanb7480992017-01-30 14:04:47 +00003057 assert (
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04003058 "{0} for buf is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04003059 WARNING_TYPE_EXPECTED
Alex Chanb7480992017-01-30 14:04:47 +00003060 ) == str(w[-1].message))
3061 assert client.recv(1) == b"x"
Abraham Martinef063482015-03-25 14:06:24 +00003062
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003063 @skip_if_py26
3064 def test_short_memoryview(self):
3065 """
3066 When passed a memoryview onto a small number of bytes,
Alex Chanb7480992017-01-30 14:04:47 +00003067 `Connection.sendall` transmits all of them.
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003068 """
Alex Chanb7480992017-01-30 14:04:47 +00003069 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04003070 server.sendall(memoryview(b'x'))
Alex Chanb7480992017-01-30 14:04:47 +00003071 assert client.recv(1) == b'x'
Abraham Martinef063482015-03-25 14:06:24 +00003072
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003073 @skip_if_py3
3074 def test_short_buffers(self):
3075 """
3076 When passed a buffer containing a small number of bytes,
Alex Chanb7480992017-01-30 14:04:47 +00003077 `Connection.sendall` transmits all of them.
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003078 """
Alex Chanb7480992017-01-30 14:04:47 +00003079 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04003080 server.sendall(buffer(b'x'))
Alex Chanb7480992017-01-30 14:04:47 +00003081 assert client.recv(1) == b'x'
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02003082
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003083 def test_long(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003084 """
Alex Chanb7480992017-01-30 14:04:47 +00003085 `Connection.sendall` transmits all the bytes in the string passed to it
3086 even if this requires multiple calls of an underlying write function.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003087 """
Alex Chanb7480992017-01-30 14:04:47 +00003088 server, client = loopback()
Jean-Paul Calderone6241c702010-09-16 19:59:24 -04003089 # Should be enough, underlying SSL_write should only do 16k at a time.
Hynek Schlawack35618382015-09-05 21:54:25 +02003090 # On Windows, after 32k of bytes the write will block (forever
3091 # - because no one is yet reading).
Alex Gaynore7f51982016-09-11 11:48:14 -04003092 message = b'x' * (1024 * 32 - 1) + b'y'
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003093 server.sendall(message)
3094 accum = []
3095 received = 0
3096 while received < len(message):
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04003097 data = client.recv(1024)
3098 accum.append(data)
3099 received += len(data)
Alex Chanb7480992017-01-30 14:04:47 +00003100 assert message == b''.join(accum)
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003101
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003102 def test_closed(self):
3103 """
Alex Chanb7480992017-01-30 14:04:47 +00003104 If the underlying socket is closed, `Connection.sendall` propagates the
3105 write error from the low level write call.
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003106 """
Alex Chanb7480992017-01-30 14:04:47 +00003107 server, client = loopback()
Jean-Paul Calderone05d43e82010-09-24 18:01:36 -04003108 server.sock_shutdown(2)
Alex Chanb7480992017-01-30 14:04:47 +00003109 with pytest.raises(SysCallError) as err:
3110 server.sendall(b"hello, world")
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +02003111 if platform == "win32":
Alex Chanb7480992017-01-30 14:04:47 +00003112 assert err.value.args[0] == ESHUTDOWN
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +02003113 else:
Alex Chanb7480992017-01-30 14:04:47 +00003114 assert err.value.args[0] == EPIPE
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003115
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003116
Alex Chanb7480992017-01-30 14:04:47 +00003117class TestConnectionRenegotiate(object):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003118 """
3119 Tests for SSL renegotiation APIs.
3120 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003121 def test_total_renegotiations(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003122 """
Alex Chanb7480992017-01-30 14:04:47 +00003123 `Connection.total_renegotiations` returns `0` before any renegotiations
3124 have happened.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003125 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003126 connection = Connection(Context(TLSv1_METHOD), None)
Alex Chanb7480992017-01-30 14:04:47 +00003127 assert connection.total_renegotiations() == 0
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003128
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003129 def test_renegotiate(self):
3130 """
3131 Go through a complete renegotiation cycle.
3132 """
Alex Chanb7480992017-01-30 14:04:47 +00003133 server, client = loopback()
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003134
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003135 server.send(b"hello world")
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003136
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003137 assert b"hello world" == client.recv(len(b"hello world"))
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003138
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003139 assert 0 == server.total_renegotiations()
3140 assert False is server.renegotiate_pending()
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003141
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003142 assert True is server.renegotiate()
3143
3144 assert True is server.renegotiate_pending()
3145
3146 server.setblocking(False)
3147 client.setblocking(False)
3148
3149 client.do_handshake()
3150 server.do_handshake()
3151
3152 assert 1 == server.total_renegotiations()
3153 while False is server.renegotiate_pending():
3154 pass
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003155
3156
Alex Chanb7480992017-01-30 14:04:47 +00003157class TestError(object):
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003158 """
Alex Chanb7480992017-01-30 14:04:47 +00003159 Unit tests for `OpenSSL.SSL.Error`.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003160 """
3161 def test_type(self):
3162 """
Alex Chanb7480992017-01-30 14:04:47 +00003163 `Error` is an exception type.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003164 """
Alex Chanb7480992017-01-30 14:04:47 +00003165 assert issubclass(Error, Exception)
3166 assert Error.__name__ == 'Error'
Rick Deane15b1472009-07-09 15:53:42 -05003167
3168
Alex Chanb7480992017-01-30 14:04:47 +00003169class TestConstants(object):
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003170 """
Alex Chanb7480992017-01-30 14:04:47 +00003171 Tests for the values of constants exposed in `OpenSSL.SSL`.
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003172
3173 These are values defined by OpenSSL intended only to be used as flags to
3174 OpenSSL APIs. The only assertions it seems can be made about them is
3175 their values.
3176 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003177 @pytest.mark.skipif(
3178 OP_NO_QUERY_MTU is None,
3179 reason="OP_NO_QUERY_MTU unavailable - OpenSSL version may be too old"
3180 )
3181 def test_op_no_query_mtu(self):
3182 """
Alex Chanb7480992017-01-30 14:04:47 +00003183 The value of `OpenSSL.SSL.OP_NO_QUERY_MTU` is 0x1000, the value
3184 of `SSL_OP_NO_QUERY_MTU` defined by `openssl/ssl.h`.
Hynek Schlawack35618382015-09-05 21:54:25 +02003185 """
Alex Chanb7480992017-01-30 14:04:47 +00003186 assert OP_NO_QUERY_MTU == 0x1000
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003187
Hynek Schlawack35618382015-09-05 21:54:25 +02003188 @pytest.mark.skipif(
3189 OP_COOKIE_EXCHANGE is None,
3190 reason="OP_COOKIE_EXCHANGE unavailable - "
3191 "OpenSSL version may be too old"
3192 )
3193 def test_op_cookie_exchange(self):
3194 """
Alex Chanb7480992017-01-30 14:04:47 +00003195 The value of `OpenSSL.SSL.OP_COOKIE_EXCHANGE` is 0x2000, the
3196 value of `SSL_OP_COOKIE_EXCHANGE` defined by `openssl/ssl.h`.
Hynek Schlawack35618382015-09-05 21:54:25 +02003197 """
Alex Chanb7480992017-01-30 14:04:47 +00003198 assert OP_COOKIE_EXCHANGE == 0x2000
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003199
Hynek Schlawack35618382015-09-05 21:54:25 +02003200 @pytest.mark.skipif(
3201 OP_NO_TICKET is None,
3202 reason="OP_NO_TICKET unavailable - OpenSSL version may be too old"
3203 )
3204 def test_op_no_ticket(self):
3205 """
Alex Chanb7480992017-01-30 14:04:47 +00003206 The value of `OpenSSL.SSL.OP_NO_TICKET` is 0x4000, the value of
3207 `SSL_OP_NO_TICKET` defined by `openssl/ssl.h`.
Hynek Schlawack35618382015-09-05 21:54:25 +02003208 """
Alex Chanb7480992017-01-30 14:04:47 +00003209 assert OP_NO_TICKET == 0x4000
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003210
Hynek Schlawack35618382015-09-05 21:54:25 +02003211 @pytest.mark.skipif(
3212 OP_NO_COMPRESSION is None,
3213 reason="OP_NO_COMPRESSION unavailable - OpenSSL version may be too old"
3214 )
3215 def test_op_no_compression(self):
3216 """
Alex Chanb7480992017-01-30 14:04:47 +00003217 The value of `OpenSSL.SSL.OP_NO_COMPRESSION` is 0x20000, the
3218 value of `SSL_OP_NO_COMPRESSION` defined by `openssl/ssl.h`.
Hynek Schlawack35618382015-09-05 21:54:25 +02003219 """
Alex Chanb7480992017-01-30 14:04:47 +00003220 assert OP_NO_COMPRESSION == 0x20000
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04003221
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003222 def test_sess_cache_off(self):
3223 """
Alex Chanb7480992017-01-30 14:04:47 +00003224 The value of `OpenSSL.SSL.SESS_CACHE_OFF` 0x0, the value of
3225 `SSL_SESS_CACHE_OFF` defined by `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003226 """
Alex Chanb7480992017-01-30 14:04:47 +00003227 assert 0x0 == SESS_CACHE_OFF
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003228
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003229 def test_sess_cache_client(self):
3230 """
Alex Chanb7480992017-01-30 14:04:47 +00003231 The value of `OpenSSL.SSL.SESS_CACHE_CLIENT` 0x1, the value of
3232 `SSL_SESS_CACHE_CLIENT` defined by `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003233 """
Alex Chanb7480992017-01-30 14:04:47 +00003234 assert 0x1 == SESS_CACHE_CLIENT
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003235
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003236 def test_sess_cache_server(self):
3237 """
Alex Chanb7480992017-01-30 14:04:47 +00003238 The value of `OpenSSL.SSL.SESS_CACHE_SERVER` 0x2, the value of
3239 `SSL_SESS_CACHE_SERVER` defined by `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003240 """
Alex Chanb7480992017-01-30 14:04:47 +00003241 assert 0x2 == SESS_CACHE_SERVER
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003242
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003243 def test_sess_cache_both(self):
3244 """
Alex Chanb7480992017-01-30 14:04:47 +00003245 The value of `OpenSSL.SSL.SESS_CACHE_BOTH` 0x3, the value of
3246 `SSL_SESS_CACHE_BOTH` defined by `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003247 """
Alex Chanb7480992017-01-30 14:04:47 +00003248 assert 0x3 == SESS_CACHE_BOTH
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003249
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003250 def test_sess_cache_no_auto_clear(self):
3251 """
Alex Chanb7480992017-01-30 14:04:47 +00003252 The value of `OpenSSL.SSL.SESS_CACHE_NO_AUTO_CLEAR` 0x80, the
3253 value of `SSL_SESS_CACHE_NO_AUTO_CLEAR` defined by
3254 `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003255 """
Alex Chanb7480992017-01-30 14:04:47 +00003256 assert 0x80 == SESS_CACHE_NO_AUTO_CLEAR
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003257
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003258 def test_sess_cache_no_internal_lookup(self):
3259 """
Alex Chanb7480992017-01-30 14:04:47 +00003260 The value of `OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_LOOKUP` 0x100,
3261 the value of `SSL_SESS_CACHE_NO_INTERNAL_LOOKUP` defined by
3262 `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003263 """
Alex Chanb7480992017-01-30 14:04:47 +00003264 assert 0x100 == SESS_CACHE_NO_INTERNAL_LOOKUP
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003265
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003266 def test_sess_cache_no_internal_store(self):
3267 """
Alex Chanb7480992017-01-30 14:04:47 +00003268 The value of `OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_STORE` 0x200,
3269 the value of `SSL_SESS_CACHE_NO_INTERNAL_STORE` defined by
3270 `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003271 """
Alex Chanb7480992017-01-30 14:04:47 +00003272 assert 0x200 == SESS_CACHE_NO_INTERNAL_STORE
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003273
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003274 def test_sess_cache_no_internal(self):
3275 """
Alex Chanb7480992017-01-30 14:04:47 +00003276 The value of `OpenSSL.SSL.SESS_CACHE_NO_INTERNAL` 0x300, the
3277 value of `SSL_SESS_CACHE_NO_INTERNAL` defined by
3278 `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003279 """
Alex Chanb7480992017-01-30 14:04:47 +00003280 assert 0x300 == SESS_CACHE_NO_INTERNAL
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003281
3282
Alex Chanb7480992017-01-30 14:04:47 +00003283class TestMemoryBIO(object):
Rick Deanb71c0d22009-04-01 14:09:23 -05003284 """
Alex Chanb7480992017-01-30 14:04:47 +00003285 Tests for `OpenSSL.SSL.Connection` using a memory BIO.
Rick Deanb71c0d22009-04-01 14:09:23 -05003286 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003287 def _server(self, sock):
3288 """
Alex Chanb7480992017-01-30 14:04:47 +00003289 Create a new server-side SSL `Connection` object wrapped around `sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003290 """
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003291 # Create the server side Connection. This is mostly setup boilerplate
3292 # - use TLSv1, use a particular certificate, etc.
3293 server_ctx = Context(TLSv1_METHOD)
Alex Gaynor43307782015-09-04 09:05:45 -04003294 server_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE)
Hynek Schlawack35618382015-09-05 21:54:25 +02003295 server_ctx.set_verify(
3296 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT | VERIFY_CLIENT_ONCE,
3297 verify_cb
3298 )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003299 server_store = server_ctx.get_cert_store()
Hynek Schlawack35618382015-09-05 21:54:25 +02003300 server_ctx.use_privatekey(
3301 load_privatekey(FILETYPE_PEM, server_key_pem))
3302 server_ctx.use_certificate(
3303 load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003304 server_ctx.check_privatekey()
3305 server_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Hynek Schlawack35618382015-09-05 21:54:25 +02003306 # Here the Connection is actually created. If None is passed as the
3307 # 2nd parameter, it indicates a memory BIO should be created.
Rick Deanb1ccd562009-07-09 23:52:39 -05003308 server_conn = Connection(server_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003309 server_conn.set_accept_state()
3310 return server_conn
3311
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003312 def _client(self, sock):
3313 """
Alex Chanb7480992017-01-30 14:04:47 +00003314 Create a new client-side SSL `Connection` object wrapped around `sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003315 """
3316 # Now create the client side Connection. Similar boilerplate to the
3317 # above.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003318 client_ctx = Context(TLSv1_METHOD)
Alex Gaynor43307782015-09-04 09:05:45 -04003319 client_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE)
Hynek Schlawack35618382015-09-05 21:54:25 +02003320 client_ctx.set_verify(
3321 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT | VERIFY_CLIENT_ONCE,
3322 verify_cb
3323 )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003324 client_store = client_ctx.get_cert_store()
Hynek Schlawack35618382015-09-05 21:54:25 +02003325 client_ctx.use_privatekey(
3326 load_privatekey(FILETYPE_PEM, client_key_pem))
3327 client_ctx.use_certificate(
3328 load_certificate(FILETYPE_PEM, client_cert_pem))
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003329 client_ctx.check_privatekey()
3330 client_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05003331 client_conn = Connection(client_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003332 client_conn.set_connect_state()
3333 return client_conn
3334
Alex Chanb7480992017-01-30 14:04:47 +00003335 def test_memory_connect(self):
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003336 """
Alex Chanb7480992017-01-30 14:04:47 +00003337 Two `Connection`s which use memory BIOs can be manually connected by
3338 reading from the output of each and writing those bytes to the input of
3339 the other and in this way establish a connection and exchange
3340 application-level bytes with each other.
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003341 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003342 server_conn = self._server(None)
3343 client_conn = self._client(None)
Rick Deanb71c0d22009-04-01 14:09:23 -05003344
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003345 # There should be no key or nonces yet.
Alex Chanb7480992017-01-30 14:04:47 +00003346 assert server_conn.master_key() is None
3347 assert server_conn.client_random() is None
3348 assert server_conn.server_random() is None
Rick Deanb71c0d22009-04-01 14:09:23 -05003349
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003350 # First, the handshake needs to happen. We'll deliver bytes back and
3351 # forth between the client and server until neither of them feels like
3352 # speaking any more.
Alex Chanb7480992017-01-30 14:04:47 +00003353 assert interact_in_memory(client_conn, server_conn) is None
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003354
3355 # Now that the handshake is done, there should be a key and nonces.
Alex Chanb7480992017-01-30 14:04:47 +00003356 assert server_conn.master_key() is not None
3357 assert server_conn.client_random() is not None
3358 assert server_conn.server_random() is not None
3359 assert server_conn.client_random() == client_conn.client_random()
3360 assert server_conn.server_random() == client_conn.server_random()
3361 assert server_conn.client_random() != server_conn.server_random()
3362 assert client_conn.client_random() != client_conn.server_random()
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003363
3364 # Here are the bytes we'll try to send.
Alex Gaynore7f51982016-09-11 11:48:14 -04003365 important_message = b'One if by land, two if by sea.'
Rick Deanb71c0d22009-04-01 14:09:23 -05003366
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003367 server_conn.write(important_message)
Alex Chanb7480992017-01-30 14:04:47 +00003368 assert (
3369 interact_in_memory(client_conn, server_conn) ==
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003370 (client_conn, important_message))
3371
3372 client_conn.write(important_message[::-1])
Alex Chanb7480992017-01-30 14:04:47 +00003373 assert (
3374 interact_in_memory(client_conn, server_conn) ==
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003375 (server_conn, important_message[::-1]))
Rick Deanb71c0d22009-04-01 14:09:23 -05003376
Alex Chanb7480992017-01-30 14:04:47 +00003377 def test_socket_connect(self):
Rick Deanb1ccd562009-07-09 23:52:39 -05003378 """
Alex Chanb7480992017-01-30 14:04:47 +00003379 Just like `test_memory_connect` but with an actual socket.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003380
Hynek Schlawack35618382015-09-05 21:54:25 +02003381 This is primarily to rule out the memory BIO code as the source of any
Alex Chanb7480992017-01-30 14:04:47 +00003382 problems encountered while passing data over a `Connection` (if
Hynek Schlawack35618382015-09-05 21:54:25 +02003383 this test fails, there must be a problem outside the memory BIO code,
3384 as no memory BIO is involved here). Even though this isn't a memory
3385 BIO test, it's convenient to have it here.
Rick Deanb1ccd562009-07-09 23:52:39 -05003386 """
Alex Chanb7480992017-01-30 14:04:47 +00003387 server_conn, client_conn = loopback()
Rick Deanb1ccd562009-07-09 23:52:39 -05003388
Alex Gaynore7f51982016-09-11 11:48:14 -04003389 important_message = b"Help me Obi Wan Kenobi, you're my only hope."
Rick Deanb1ccd562009-07-09 23:52:39 -05003390 client_conn.send(important_message)
3391 msg = server_conn.recv(1024)
Alex Chanb7480992017-01-30 14:04:47 +00003392 assert msg == important_message
Rick Deanb1ccd562009-07-09 23:52:39 -05003393
3394 # Again in the other direction, just for fun.
3395 important_message = important_message[::-1]
3396 server_conn.send(important_message)
3397 msg = client_conn.recv(1024)
Alex Chanb7480992017-01-30 14:04:47 +00003398 assert msg == important_message
Rick Deanb1ccd562009-07-09 23:52:39 -05003399
Alex Chanb7480992017-01-30 14:04:47 +00003400 def test_socket_overrides_memory(self):
Rick Deanb71c0d22009-04-01 14:09:23 -05003401 """
Alex Chanb7480992017-01-30 14:04:47 +00003402 Test that `OpenSSL.SSL.bio_read` and `OpenSSL.SSL.bio_write` don't
3403 work on `OpenSSL.SSL.Connection`() that use sockets.
Rick Deanb71c0d22009-04-01 14:09:23 -05003404 """
Alex Gaynor51d424c2016-09-10 14:50:11 -04003405 context = Context(TLSv1_METHOD)
Rick Deanb71c0d22009-04-01 14:09:23 -05003406 client = socket()
3407 clientSSL = Connection(context, client)
Alex Chanb7480992017-01-30 14:04:47 +00003408 with pytest.raises(TypeError):
3409 clientSSL.bio_read(100)
3410 with pytest.raises(TypeError):
3411 clientSSL.bio_write("foo")
3412 with pytest.raises(TypeError):
3413 clientSSL.bio_shutdown()
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003414
Alex Chanb7480992017-01-30 14:04:47 +00003415 def test_outgoing_overflow(self):
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003416 """
3417 If more bytes than can be written to the memory BIO are passed to
Alex Chanb7480992017-01-30 14:04:47 +00003418 `Connection.send` at once, the number of bytes which were written is
3419 returned and that many bytes from the beginning of the input can be
3420 read from the other end of the connection.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003421 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003422 server = self._server(None)
3423 client = self._client(None)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003424
Alex Chanb7480992017-01-30 14:04:47 +00003425 interact_in_memory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003426
3427 size = 2 ** 15
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003428 sent = client.send(b"x" * size)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003429 # Sanity check. We're trying to test what happens when the entire
3430 # input can't be sent. If the entire input was sent, this test is
3431 # meaningless.
Alex Chanb7480992017-01-30 14:04:47 +00003432 assert sent < size
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003433
Alex Chanb7480992017-01-30 14:04:47 +00003434 receiver, received = interact_in_memory(client, server)
3435 assert receiver is server
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003436
3437 # We can rely on all of these bytes being received at once because
Alex Chanb7480992017-01-30 14:04:47 +00003438 # loopback passes 2 ** 16 to recv - more than 2 ** 15.
3439 assert len(received) == sent
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003440
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003441 def test_shutdown(self):
3442 """
Alex Chanb7480992017-01-30 14:04:47 +00003443 `Connection.bio_shutdown` signals the end of the data stream
3444 from which the `Connection` reads.
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003445 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003446 server = self._server(None)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003447 server.bio_shutdown()
Alex Chanb7480992017-01-30 14:04:47 +00003448 with pytest.raises(Error) as err:
3449 server.recv(1024)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003450 # We don't want WantReadError or ZeroReturnError or anything - it's a
3451 # handshake failure.
Alex Chanb7480992017-01-30 14:04:47 +00003452 assert type(err.value) in [Error, SysCallError]
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003453
Alex Chanb7480992017-01-30 14:04:47 +00003454 def test_unexpected_EOF(self):
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003455 """
3456 If the connection is lost before an orderly SSL shutdown occurs,
Alex Chanb7480992017-01-30 14:04:47 +00003457 `OpenSSL.SSL.SysCallError` is raised with a message of
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003458 "Unexpected EOF".
3459 """
Alex Chanb7480992017-01-30 14:04:47 +00003460 server_conn, client_conn = loopback()
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003461 client_conn.sock_shutdown(SHUT_RDWR)
Alex Chanb7480992017-01-30 14:04:47 +00003462 with pytest.raises(SysCallError) as err:
3463 server_conn.recv(1024)
3464 assert err.value.args == (-1, "Unexpected EOF")
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003465
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003466 def _check_client_ca_list(self, func):
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003467 """
Alex Chanb7480992017-01-30 14:04:47 +00003468 Verify the return value of the `get_client_ca_list` method for
Hynek Schlawack35618382015-09-05 21:54:25 +02003469 server and client connections.
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003470
Jonathan Ballet78b92a22011-07-16 08:07:26 +09003471 :param func: A function which will be called with the server context
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003472 before the client and server are connected to each other. This
3473 function should specify a list of CAs for the server to send to the
3474 client and return that same list. The list will be used to verify
Alex Chanb7480992017-01-30 14:04:47 +00003475 that `get_client_ca_list` returns the proper value at
Hynek Schlawack35618382015-09-05 21:54:25 +02003476 various times.
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003477 """
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003478 server = self._server(None)
3479 client = self._client(None)
Alex Chanb7480992017-01-30 14:04:47 +00003480 assert client.get_client_ca_list() == []
3481 assert server.get_client_ca_list() == []
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003482 ctx = server.get_context()
3483 expected = func(ctx)
Alex Chanb7480992017-01-30 14:04:47 +00003484 assert client.get_client_ca_list() == []
3485 assert server.get_client_ca_list() == expected
3486 interact_in_memory(client, server)
3487 assert client.get_client_ca_list() == expected
3488 assert server.get_client_ca_list() == expected
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003489
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003490 def test_set_client_ca_list_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003491 """
Alex Chanb7480992017-01-30 14:04:47 +00003492 `Context.set_client_ca_list` raises a `TypeError` if called with a
3493 non-list or a list that contains objects other than X509Names.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003494 """
3495 ctx = Context(TLSv1_METHOD)
Alex Chanb7480992017-01-30 14:04:47 +00003496 with pytest.raises(TypeError):
3497 ctx.set_client_ca_list("spam")
3498 with pytest.raises(TypeError):
3499 ctx.set_client_ca_list(["spam"])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003500
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003501 def test_set_empty_ca_list(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003502 """
Alex Chanb7480992017-01-30 14:04:47 +00003503 If passed an empty list, `Context.set_client_ca_list` configures the
3504 context to send no CA names to the client and, on both the server and
3505 client sides, `Connection.get_client_ca_list` returns an empty list
3506 after the connection is set up.
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003507 """
3508 def no_ca(ctx):
3509 ctx.set_client_ca_list([])
3510 return []
3511 self._check_client_ca_list(no_ca)
3512
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003513 def test_set_one_ca_list(self):
3514 """
3515 If passed a list containing a single X509Name,
Alex Chanb7480992017-01-30 14:04:47 +00003516 `Context.set_client_ca_list` configures the context to send
Hynek Schlawack35618382015-09-05 21:54:25 +02003517 that CA name to the client and, on both the server and client sides,
Alex Chanb7480992017-01-30 14:04:47 +00003518 `Connection.get_client_ca_list` returns a list containing that
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003519 X509Name after the connection is set up.
3520 """
3521 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3522 cadesc = cacert.get_subject()
Hynek Schlawack35618382015-09-05 21:54:25 +02003523
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003524 def single_ca(ctx):
3525 ctx.set_client_ca_list([cadesc])
3526 return [cadesc]
3527 self._check_client_ca_list(single_ca)
3528
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003529 def test_set_multiple_ca_list(self):
3530 """
3531 If passed a list containing multiple X509Name objects,
Alex Chanb7480992017-01-30 14:04:47 +00003532 `Context.set_client_ca_list` configures the context to send
Hynek Schlawack35618382015-09-05 21:54:25 +02003533 those CA names to the client and, on both the server and client sides,
Alex Chanb7480992017-01-30 14:04:47 +00003534 `Connection.get_client_ca_list` returns a list containing those
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003535 X509Names after the connection is set up.
3536 """
3537 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3538 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3539
3540 sedesc = secert.get_subject()
3541 cldesc = clcert.get_subject()
3542
3543 def multiple_ca(ctx):
3544 L = [sedesc, cldesc]
3545 ctx.set_client_ca_list(L)
3546 return L
3547 self._check_client_ca_list(multiple_ca)
3548
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003549 def test_reset_ca_list(self):
3550 """
3551 If called multiple times, only the X509Names passed to the final call
Alex Chanb7480992017-01-30 14:04:47 +00003552 of `Context.set_client_ca_list` are used to configure the CA
Hynek Schlawack35618382015-09-05 21:54:25 +02003553 names sent to the client.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003554 """
3555 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3556 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3557 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3558
3559 cadesc = cacert.get_subject()
3560 sedesc = secert.get_subject()
3561 cldesc = clcert.get_subject()
3562
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003563 def changed_ca(ctx):
3564 ctx.set_client_ca_list([sedesc, cldesc])
3565 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003566 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003567 self._check_client_ca_list(changed_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003568
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003569 def test_mutated_ca_list(self):
3570 """
Alex Chanb7480992017-01-30 14:04:47 +00003571 If the list passed to `Context.set_client_ca_list` is mutated
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003572 afterwards, this does not affect the list of CA names sent to the
3573 client.
3574 """
3575 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3576 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3577
3578 cadesc = cacert.get_subject()
3579 sedesc = secert.get_subject()
3580
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003581 def mutated_ca(ctx):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003582 L = [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003583 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003584 L.append(sedesc)
3585 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003586 self._check_client_ca_list(mutated_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003587
Alex Chanb7480992017-01-30 14:04:47 +00003588 def test_add_client_ca_wrong_args(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003589 """
Alex Chanb7480992017-01-30 14:04:47 +00003590 `Context.add_client_ca` raises `TypeError` if called with
3591 a non-X509 object.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003592 """
3593 ctx = Context(TLSv1_METHOD)
Alex Chanb7480992017-01-30 14:04:47 +00003594 with pytest.raises(TypeError):
3595 ctx.add_client_ca("spam")
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003596
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003597 def test_one_add_client_ca(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003598 """
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003599 A certificate's subject can be added as a CA to be sent to the client
Alex Chanb7480992017-01-30 14:04:47 +00003600 with `Context.add_client_ca`.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003601 """
3602 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3603 cadesc = cacert.get_subject()
Hynek Schlawack35618382015-09-05 21:54:25 +02003604
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003605 def single_ca(ctx):
3606 ctx.add_client_ca(cacert)
3607 return [cadesc]
3608 self._check_client_ca_list(single_ca)
3609
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003610 def test_multiple_add_client_ca(self):
3611 """
3612 Multiple CA names can be sent to the client by calling
Alex Chanb7480992017-01-30 14:04:47 +00003613 `Context.add_client_ca` with multiple X509 objects.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003614 """
3615 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3616 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3617
3618 cadesc = cacert.get_subject()
3619 sedesc = secert.get_subject()
3620
3621 def multiple_ca(ctx):
3622 ctx.add_client_ca(cacert)
3623 ctx.add_client_ca(secert)
3624 return [cadesc, sedesc]
3625 self._check_client_ca_list(multiple_ca)
3626
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003627 def test_set_and_add_client_ca(self):
3628 """
Alex Chanb7480992017-01-30 14:04:47 +00003629 A call to `Context.set_client_ca_list` followed by a call to
3630 `Context.add_client_ca` results in using the CA names from the
Hynek Schlawack35618382015-09-05 21:54:25 +02003631 first call and the CA name from the second call.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003632 """
3633 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3634 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3635 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3636
3637 cadesc = cacert.get_subject()
3638 sedesc = secert.get_subject()
3639 cldesc = clcert.get_subject()
3640
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003641 def mixed_set_add_ca(ctx):
3642 ctx.set_client_ca_list([cadesc, sedesc])
3643 ctx.add_client_ca(clcert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003644 return [cadesc, sedesc, cldesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003645 self._check_client_ca_list(mixed_set_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003646
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003647 def test_set_after_add_client_ca(self):
3648 """
Alex Chanb7480992017-01-30 14:04:47 +00003649 A call to `Context.set_client_ca_list` after a call to
3650 `Context.add_client_ca` replaces the CA name specified by the
Hynek Schlawack35618382015-09-05 21:54:25 +02003651 former call with the names specified by the latter call.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003652 """
3653 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3654 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3655 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3656
3657 cadesc = cacert.get_subject()
3658 sedesc = secert.get_subject()
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003659
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003660 def set_replaces_add_ca(ctx):
3661 ctx.add_client_ca(clcert)
3662 ctx.set_client_ca_list([cadesc])
3663 ctx.add_client_ca(secert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003664 return [cadesc, sedesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003665 self._check_client_ca_list(set_replaces_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003666
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003667
Alex Chanb7480992017-01-30 14:04:47 +00003668class TestInfoConstants(object):
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003669 """
3670 Tests for assorted constants exposed for use in info callbacks.
3671 """
3672 def test_integers(self):
3673 """
3674 All of the info constants are integers.
3675
3676 This is a very weak test. It would be nice to have one that actually
3677 verifies that as certain info events happen, the value passed to the
3678 info callback matches up with the constant exposed by OpenSSL.SSL.
3679 """
3680 for const in [
Alex Gaynor5af32d02016-09-24 01:52:21 -04003681 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK,
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003682 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
3683 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
3684 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
Hynek Schlawack35618382015-09-05 21:54:25 +02003685 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE
3686 ]:
Alex Gaynor5af32d02016-09-24 01:52:21 -04003687 assert isinstance(const, int)
3688
3689 # These constants don't exist on OpenSSL 1.1.0
3690 for const in [
3691 SSL_ST_INIT, SSL_ST_BEFORE, SSL_ST_OK, SSL_ST_RENEGOTIATE
3692 ]:
3693 assert const is None or isinstance(const, int)
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003694
Ziga Seilnacht44611bf2009-08-31 20:49:30 +02003695
Cory Benfield1d142142016-03-30 11:51:45 +01003696class TestRequires(object):
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003697 """
3698 Tests for the decorator factory used to conditionally raise
Cory Benfield1d142142016-03-30 11:51:45 +01003699 NotImplementedError when older OpenSSLs are used.
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003700 """
3701 def test_available(self):
3702 """
3703 When the OpenSSL functionality is available the decorated functions
3704 work appropriately.
3705 """
3706 feature_guard = _make_requires(True, "Error text")
3707 results = []
3708
3709 @feature_guard
3710 def inner():
3711 results.append(True)
3712 return True
3713
Cory Benfield2333e5e2016-03-30 14:24:16 +01003714 assert inner() is True
3715 assert [True] == results
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003716
3717 def test_unavailable(self):
3718 """
3719 When the OpenSSL functionality is not available the decorated function
3720 does not execute and NotImplementedError is raised.
3721 """
3722 feature_guard = _make_requires(False, "Error text")
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003723
3724 @feature_guard
Alex Chanfb078d82017-04-20 11:16:15 +01003725 def inner(): # pragma: nocover
3726 pytest.fail("Should not be called")
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003727
Cory Benfield1d142142016-03-30 11:51:45 +01003728 with pytest.raises(NotImplementedError) as e:
3729 inner()
3730
3731 assert "Error text" in str(e.value)
Cory Benfield496652a2017-01-24 11:42:56 +00003732
3733
Alex Chanb7480992017-01-30 14:04:47 +00003734class TestOCSP(object):
Cory Benfield496652a2017-01-24 11:42:56 +00003735 """
3736 Tests for PyOpenSSL's OCSP stapling support.
3737 """
3738 sample_ocsp_data = b"this is totally ocsp data"
3739
3740 def _client_connection(self, callback, data, request_ocsp=True):
3741 """
3742 Builds a client connection suitable for using OCSP.
3743
3744 :param callback: The callback to register for OCSP.
3745 :param data: The opaque data object that will be handed to the
3746 OCSP callback.
3747 :param request_ocsp: Whether the client will actually ask for OCSP
3748 stapling. Useful for testing only.
3749 """
3750 ctx = Context(SSLv23_METHOD)
3751 ctx.set_ocsp_client_callback(callback, data)
3752 client = Connection(ctx)
3753
3754 if request_ocsp:
3755 client.request_ocsp()
3756
3757 client.set_connect_state()
3758 return client
3759
3760 def _server_connection(self, callback, data):
3761 """
3762 Builds a server connection suitable for using OCSP.
3763
3764 :param callback: The callback to register for OCSP.
3765 :param data: The opaque data object that will be handed to the
3766 OCSP callback.
3767 """
3768 ctx = Context(SSLv23_METHOD)
3769 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
3770 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
3771 ctx.set_ocsp_server_callback(callback, data)
3772 server = Connection(ctx)
3773 server.set_accept_state()
3774 return server
3775
3776 def test_callbacks_arent_called_by_default(self):
3777 """
3778 If both the client and the server have registered OCSP callbacks, but
3779 the client does not send the OCSP request, neither callback gets
3780 called.
3781 """
Alex Chanfb078d82017-04-20 11:16:15 +01003782 def ocsp_callback(*args, **kwargs): # pragma: nocover
3783 pytest.fail("Should not be called")
Cory Benfield496652a2017-01-24 11:42:56 +00003784
3785 client = self._client_connection(
3786 callback=ocsp_callback, data=None, request_ocsp=False
3787 )
3788 server = self._server_connection(callback=ocsp_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00003789 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003790
Cory Benfield496652a2017-01-24 11:42:56 +00003791 def test_client_negotiates_without_server(self):
3792 """
3793 If the client wants to do OCSP but the server does not, the handshake
3794 succeeds, and the client callback fires with an empty byte string.
3795 """
3796 called = []
3797
3798 def ocsp_callback(conn, ocsp_data, ignored):
3799 called.append(ocsp_data)
3800 return True
3801
3802 client = self._client_connection(callback=ocsp_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00003803 server = loopback_server_factory(socket=None)
3804 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003805
3806 assert len(called) == 1
3807 assert called[0] == b''
3808
3809 def test_client_receives_servers_data(self):
3810 """
3811 The data the server sends in its callback is received by the client.
3812 """
3813 calls = []
3814
3815 def server_callback(*args, **kwargs):
3816 return self.sample_ocsp_data
3817
3818 def client_callback(conn, ocsp_data, ignored):
3819 calls.append(ocsp_data)
3820 return True
3821
3822 client = self._client_connection(callback=client_callback, data=None)
3823 server = self._server_connection(callback=server_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00003824 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003825
3826 assert len(calls) == 1
3827 assert calls[0] == self.sample_ocsp_data
3828
3829 def test_callbacks_are_invoked_with_connections(self):
3830 """
3831 The first arguments to both callbacks are their respective connections.
3832 """
3833 client_calls = []
3834 server_calls = []
3835
3836 def client_callback(conn, *args, **kwargs):
3837 client_calls.append(conn)
3838 return True
3839
3840 def server_callback(conn, *args, **kwargs):
3841 server_calls.append(conn)
3842 return self.sample_ocsp_data
3843
3844 client = self._client_connection(callback=client_callback, data=None)
3845 server = self._server_connection(callback=server_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00003846 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003847
3848 assert len(client_calls) == 1
3849 assert len(server_calls) == 1
3850 assert client_calls[0] is client
3851 assert server_calls[0] is server
3852
3853 def test_opaque_data_is_passed_through(self):
3854 """
3855 Both callbacks receive an opaque, user-provided piece of data in their
3856 callbacks as the final argument.
3857 """
3858 calls = []
3859
3860 def server_callback(*args):
3861 calls.append(args)
3862 return self.sample_ocsp_data
3863
3864 def client_callback(*args):
3865 calls.append(args)
3866 return True
3867
3868 sentinel = object()
3869
3870 client = self._client_connection(
3871 callback=client_callback, data=sentinel
3872 )
3873 server = self._server_connection(
3874 callback=server_callback, data=sentinel
3875 )
Alex Chanb7480992017-01-30 14:04:47 +00003876 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003877
3878 assert len(calls) == 2
3879 assert calls[0][-1] is sentinel
3880 assert calls[1][-1] is sentinel
3881
3882 def test_server_returns_empty_string(self):
3883 """
3884 If the server returns an empty bytestring from its callback, the
3885 client callback is called with the empty bytestring.
3886 """
3887 client_calls = []
3888
3889 def server_callback(*args):
3890 return b''
3891
3892 def client_callback(conn, ocsp_data, ignored):
3893 client_calls.append(ocsp_data)
3894 return True
3895
3896 client = self._client_connection(callback=client_callback, data=None)
3897 server = self._server_connection(callback=server_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00003898 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003899
3900 assert len(client_calls) == 1
3901 assert client_calls[0] == b''
3902
3903 def test_client_returns_false_terminates_handshake(self):
3904 """
3905 If the client returns False from its callback, the handshake fails.
3906 """
3907 def server_callback(*args):
3908 return self.sample_ocsp_data
3909
3910 def client_callback(*args):
3911 return False
3912
3913 client = self._client_connection(callback=client_callback, data=None)
3914 server = self._server_connection(callback=server_callback, data=None)
3915
3916 with pytest.raises(Error):
Alex Chanb7480992017-01-30 14:04:47 +00003917 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003918
3919 def test_exceptions_in_client_bubble_up(self):
3920 """
3921 The callbacks thrown in the client callback bubble up to the caller.
3922 """
3923 class SentinelException(Exception):
3924 pass
3925
3926 def server_callback(*args):
3927 return self.sample_ocsp_data
3928
3929 def client_callback(*args):
3930 raise SentinelException()
3931
3932 client = self._client_connection(callback=client_callback, data=None)
3933 server = self._server_connection(callback=server_callback, data=None)
3934
3935 with pytest.raises(SentinelException):
Alex Chanb7480992017-01-30 14:04:47 +00003936 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003937
3938 def test_exceptions_in_server_bubble_up(self):
3939 """
3940 The callbacks thrown in the server callback bubble up to the caller.
3941 """
3942 class SentinelException(Exception):
3943 pass
3944
3945 def server_callback(*args):
3946 raise SentinelException()
3947
Alex Chanfb078d82017-04-20 11:16:15 +01003948 def client_callback(*args): # pragma: nocover
Cory Benfield496652a2017-01-24 11:42:56 +00003949 pytest.fail("Should not be called")
3950
3951 client = self._client_connection(callback=client_callback, data=None)
3952 server = self._server_connection(callback=server_callback, data=None)
3953
3954 with pytest.raises(SentinelException):
Alex Chanb7480992017-01-30 14:04:47 +00003955 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003956
3957 def test_server_must_return_bytes(self):
3958 """
3959 The server callback must return a bytestring, or a TypeError is thrown.
3960 """
3961 def server_callback(*args):
3962 return self.sample_ocsp_data.decode('ascii')
3963
Alex Chanfb078d82017-04-20 11:16:15 +01003964 def client_callback(*args): # pragma: nocover
Cory Benfield496652a2017-01-24 11:42:56 +00003965 pytest.fail("Should not be called")
3966
3967 client = self._client_connection(callback=client_callback, data=None)
3968 server = self._server_connection(callback=server_callback, data=None)
3969
3970 with pytest.raises(TypeError):
Alex Chanb7480992017-01-30 14:04:47 +00003971 handshake_in_memory(client, server)