blob: 03dd9352484c4ce2bb476c0e1e371d9bfc4bc538 [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 Calderone31e85a82011-03-21 19:13:35 -040069from OpenSSL.SSL import (
Alex Gaynor5af32d02016-09-24 01:52:21 -040070 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK,
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -040071 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
72 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
73 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
74 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE)
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -040075
Alex Gaynor5af32d02016-09-24 01:52:21 -040076try:
77 from OpenSSL.SSL import (
78 SSL_ST_INIT, SSL_ST_BEFORE, SSL_ST_OK, SSL_ST_RENEGOTIATE
79 )
80except ImportError:
81 SSL_ST_INIT = SSL_ST_BEFORE = SSL_ST_OK = SSL_ST_RENEGOTIATE = None
82
Alex Chanb7480992017-01-30 14:04:47 +000083from .util import WARNING_TYPE_EXPECTED, NON_ASCII, is_consistent_type
Hynek Schlawackf0e66852015-10-16 20:18:38 +020084from .test_crypto import (
85 cleartextCertificatePEM, cleartextPrivateKeyPEM,
86 client_cert_pem, client_key_pem, server_cert_pem, server_key_pem,
87 root_cert_pem)
88
Hynek Schlawackde00dd52015-09-05 19:09:26 +020089
Alex Gaynord0bdd2d2016-09-10 14:23:46 -040090# openssl dhparam 1024 -out dh-1024.pem (note that 1024 is a small number of
91# bits to use)
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -040092dhparam = """\
93-----BEGIN DH PARAMETERS-----
Alex Gaynord0bdd2d2016-09-10 14:23:46 -040094MIGHAoGBALdUMvn+C9MM+y5BWZs11mSeH6HHoEq0UVbzVq7UojC1hbsZUuGukQ3a
95Qh2/pwqb18BZFykrWB0zv/OkLa0kx4cuUgNrUVq1EFheBiX6YqryJ7t2sO09NQiO
96V7H54LmltOT/hEh6QWsJqb6BQgH65bswvV/XkYGja8/T0GzvbaVzAgEC
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -040097-----END DH PARAMETERS-----
98"""
99
100
Hynek Schlawackb4f02402015-09-05 20:48:34 +0200101skip_if_py3 = pytest.mark.skipif(PY3, reason="Python 2 only")
Hynek Schlawackf8979a52015-09-05 21:25:25 +0200102skip_if_py26 = pytest.mark.skipif(
103 version_info[0:2] == (2, 6),
104 reason="Python 2.7 and later only"
105)
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200106
107
Jean-Paul Calderone05826732015-04-12 11:38:49 -0400108def join_bytes_or_unicode(prefix, suffix):
109 """
110 Join two path components of either ``bytes`` or ``unicode``.
111
112 The return type is the same as the type of ``prefix``.
113 """
114 # If the types are the same, nothing special is necessary.
115 if type(prefix) == type(suffix):
116 return join(prefix, suffix)
117
118 # Otherwise, coerce suffix to the type of prefix.
119 if isinstance(prefix, text_type):
120 return join(prefix, suffix.decode(getfilesystemencoding()))
121 else:
122 return join(prefix, suffix.encode(getfilesystemencoding()))
123
124
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400125def verify_cb(conn, cert, errnum, depth, ok):
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400126 return ok
127
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400128
Rick Deanb1ccd562009-07-09 23:52:39 -0500129def socket_pair():
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400130 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400131 Establish and return a pair of network sockets connected to each other.
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400132 """
133 # Connect a pair of sockets
Rick Deanb1ccd562009-07-09 23:52:39 -0500134 port = socket()
135 port.bind(('', 0))
136 port.listen(1)
137 client = socket()
138 client.setblocking(False)
Jean-Paul Calderonef23c5d92009-07-23 17:58:15 -0400139 client.connect_ex(("127.0.0.1", port.getsockname()[1]))
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400140 client.setblocking(True)
Rick Deanb1ccd562009-07-09 23:52:39 -0500141 server = port.accept()[0]
Rick Deanb1ccd562009-07-09 23:52:39 -0500142
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400143 # Let's pass some unencrypted data to make sure our socket connection is
144 # fine. Just one byte, so we don't have to worry about buffers getting
145 # filled up or fragmentation.
Alex Gaynore7f51982016-09-11 11:48:14 -0400146 server.send(b"x")
147 assert client.recv(1024) == b"x"
148 client.send(b"y")
149 assert server.recv(1024) == b"y"
Rick Deanb1ccd562009-07-09 23:52:39 -0500150
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -0400151 # Most of our callers want non-blocking sockets, make it easy for them.
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400152 server.setblocking(False)
153 client.setblocking(False)
Jim Shaver46f28912015-05-29 19:32:16 -0400154
Rick Deanb1ccd562009-07-09 23:52:39 -0500155 return (server, client)
156
157
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400158def handshake(client, server):
159 conns = [client, server]
160 while conns:
161 for conn in conns:
162 try:
163 conn.do_handshake()
164 except WantReadError:
165 pass
166 else:
167 conns.remove(conn)
168
169
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400170def _create_certificate_chain():
171 """
172 Construct and return a chain of certificates.
173
174 1. A new self-signed certificate authority certificate (cacert)
175 2. A new intermediate certificate signed by cacert (icert)
176 3. A new server certificate signed by icert (scert)
177 """
Alex Gaynore7f51982016-09-11 11:48:14 -0400178 caext = X509Extension(b'basicConstraints', False, b'CA:true')
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400179
180 # Step 1
181 cakey = PKey()
Alex Gaynor0737a5e2016-09-10 14:35:09 -0400182 cakey.generate_key(TYPE_RSA, 1024)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400183 cacert = X509()
184 cacert.get_subject().commonName = "Authority Certificate"
185 cacert.set_issuer(cacert.get_subject())
186 cacert.set_pubkey(cakey)
Alex Gaynore7f51982016-09-11 11:48:14 -0400187 cacert.set_notBefore(b"20000101000000Z")
188 cacert.set_notAfter(b"20200101000000Z")
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400189 cacert.add_extensions([caext])
190 cacert.set_serial_number(0)
191 cacert.sign(cakey, "sha1")
192
193 # Step 2
194 ikey = PKey()
Alex Gaynor0737a5e2016-09-10 14:35:09 -0400195 ikey.generate_key(TYPE_RSA, 1024)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400196 icert = X509()
197 icert.get_subject().commonName = "Intermediate Certificate"
198 icert.set_issuer(cacert.get_subject())
199 icert.set_pubkey(ikey)
Alex Gaynore7f51982016-09-11 11:48:14 -0400200 icert.set_notBefore(b"20000101000000Z")
201 icert.set_notAfter(b"20200101000000Z")
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400202 icert.add_extensions([caext])
203 icert.set_serial_number(0)
204 icert.sign(cakey, "sha1")
205
206 # Step 3
207 skey = PKey()
Alex Gaynor0737a5e2016-09-10 14:35:09 -0400208 skey.generate_key(TYPE_RSA, 1024)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400209 scert = X509()
210 scert.get_subject().commonName = "Server Certificate"
211 scert.set_issuer(icert.get_subject())
212 scert.set_pubkey(skey)
Alex Gaynore7f51982016-09-11 11:48:14 -0400213 scert.set_notBefore(b"20000101000000Z")
214 scert.set_notAfter(b"20200101000000Z")
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400215 scert.add_extensions([
Alex Gaynore7f51982016-09-11 11:48:14 -0400216 X509Extension(b'basicConstraints', True, b'CA:false')])
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400217 scert.set_serial_number(0)
218 scert.sign(ikey, "sha1")
219
220 return [(cakey, cacert), (ikey, icert), (skey, scert)]
221
222
Alex Chan1c0cb662017-01-30 07:13:30 +0000223def loopback_client_factory(socket):
Alex Gaynor85b17582017-08-07 11:52:08 -0400224 client = Connection(Context(SSLv23_METHOD), socket)
Alex Chan1c0cb662017-01-30 07:13:30 +0000225 client.set_connect_state()
226 return client
227
228
229def loopback_server_factory(socket):
Alex Gaynor85b17582017-08-07 11:52:08 -0400230 ctx = Context(SSLv23_METHOD)
Alex Chan1c0cb662017-01-30 07:13:30 +0000231 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
232 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
233 server = Connection(ctx, socket)
234 server.set_accept_state()
235 return server
236
237
238def loopback(server_factory=None, client_factory=None):
239 """
240 Create a connected socket pair and force two connected SSL sockets
241 to talk to each other via memory BIOs.
242 """
243 if server_factory is None:
244 server_factory = loopback_server_factory
245 if client_factory is None:
246 client_factory = loopback_client_factory
247
248 (server, client) = socket_pair()
249 server = server_factory(server)
250 client = client_factory(client)
251
252 handshake(client, server)
253
254 server.setblocking(True)
255 client.setblocking(True)
256 return server, client
257
258
Alex Chan1ca9e3a2016-11-05 13:01:51 +0000259def interact_in_memory(client_conn, server_conn):
260 """
261 Try to read application bytes from each of the two `Connection` objects.
262 Copy bytes back and forth between their send/receive buffers for as long
263 as there is anything to copy. When there is nothing more to copy,
264 return `None`. If one of them actually manages to deliver some application
265 bytes, return a two-tuple of the connection from which the bytes were read
266 and the bytes themselves.
267 """
268 wrote = True
269 while wrote:
270 # Loop until neither side has anything to say
271 wrote = False
272
273 # Copy stuff from each side's send buffer to the other side's
274 # receive buffer.
275 for (read, write) in [(client_conn, server_conn),
276 (server_conn, client_conn)]:
277
278 # Give the side a chance to generate some more bytes, or succeed.
279 try:
280 data = read.recv(2 ** 16)
281 except WantReadError:
282 # It didn't succeed, so we'll hope it generated some output.
283 pass
284 else:
285 # It did succeed, so we'll stop now and let the caller deal
286 # with it.
287 return (read, data)
288
289 while True:
290 # Keep copying as long as there's more stuff there.
291 try:
292 dirty = read.bio_read(4096)
293 except WantReadError:
294 # Okay, nothing more waiting to be sent. Stop
295 # processing this send buffer.
296 break
297 else:
298 # Keep track of the fact that someone generated some
299 # output.
300 wrote = True
301 write.bio_write(dirty)
302
303
Alex Chan532b79e2017-01-24 15:14:52 +0000304def handshake_in_memory(client_conn, server_conn):
305 """
306 Perform the TLS handshake between two `Connection` instances connected to
307 each other via memory BIOs.
308 """
309 client_conn.set_connect_state()
310 server_conn.set_accept_state()
311
312 for conn in [client_conn, server_conn]:
313 try:
314 conn.do_handshake()
315 except WantReadError:
316 pass
317
318 interact_in_memory(client_conn, server_conn)
319
320
Alex Chanb7480992017-01-30 14:04:47 +0000321class TestVersion(object):
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400322 """
Alex Chanb7480992017-01-30 14:04:47 +0000323 Tests for version information exposed by `OpenSSL.SSL.SSLeay_version` and
324 `OpenSSL.SSL.OPENSSL_VERSION_NUMBER`.
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400325 """
326 def test_OPENSSL_VERSION_NUMBER(self):
327 """
Alex Chanb7480992017-01-30 14:04:47 +0000328 `OPENSSL_VERSION_NUMBER` is an integer with status in the low byte and
329 the patch, fix, minor, and major versions in the nibbles above that.
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400330 """
Alex Chanb7480992017-01-30 14:04:47 +0000331 assert isinstance(OPENSSL_VERSION_NUMBER, int)
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400332
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400333 def test_SSLeay_version(self):
334 """
Alex Chanb7480992017-01-30 14:04:47 +0000335 `SSLeay_version` takes a version type indicator and returns one of a
336 number of version strings based on that indicator.
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400337 """
338 versions = {}
339 for t in [SSLEAY_VERSION, SSLEAY_CFLAGS, SSLEAY_BUILT_ON,
340 SSLEAY_PLATFORM, SSLEAY_DIR]:
341 version = SSLeay_version(t)
342 versions[version] = t
Alex Chanb7480992017-01-30 14:04:47 +0000343 assert isinstance(version, bytes)
344 assert len(versions) == 5
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400345
346
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100347@pytest.fixture
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100348def ca_file(tmpdir):
349 """
350 Create a valid PEM file with CA certificates and return the path.
351 """
352 key = rsa.generate_private_key(
353 public_exponent=65537,
354 key_size=2048,
355 backend=default_backend()
356 )
357 public_key = key.public_key()
358
359 builder = x509.CertificateBuilder()
360 builder = builder.subject_name(x509.Name([
361 x509.NameAttribute(NameOID.COMMON_NAME, u"pyopenssl.org"),
362 ]))
363 builder = builder.issuer_name(x509.Name([
364 x509.NameAttribute(NameOID.COMMON_NAME, u"pyopenssl.org"),
365 ]))
366 one_day = datetime.timedelta(1, 0, 0)
367 builder = builder.not_valid_before(datetime.datetime.today() - one_day)
368 builder = builder.not_valid_after(datetime.datetime.today() + one_day)
369 builder = builder.serial_number(int(uuid.uuid4()))
370 builder = builder.public_key(public_key)
371 builder = builder.add_extension(
372 x509.BasicConstraints(ca=True, path_length=None), critical=True,
373 )
374
375 certificate = builder.sign(
376 private_key=key, algorithm=hashes.SHA256(),
377 backend=default_backend()
378 )
379
380 ca_file = tmpdir.join("test.pem")
381 ca_file.write_binary(
382 certificate.public_bytes(
383 encoding=serialization.Encoding.PEM,
384 )
385 )
386
387 return str(ca_file).encode("ascii")
388
389
390@pytest.fixture
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100391def context():
392 """
393 A simple TLS 1.0 context.
394 """
395 return Context(TLSv1_METHOD)
396
397
398class TestContext(object):
Hynek Schlawackaa861212016-03-13 13:53:48 +0100399 """
Alex Chan532b79e2017-01-24 15:14:52 +0000400 Unit tests for `OpenSSL.SSL.Context`.
Hynek Schlawackaa861212016-03-13 13:53:48 +0100401 """
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100402 @pytest.mark.parametrize("cipher_string", [
403 b"hello world:AES128-SHA",
404 u"hello world:AES128-SHA",
405 ])
406 def test_set_cipher_list(self, context, cipher_string):
407 """
Alex Chan532b79e2017-01-24 15:14:52 +0000408 `Context.set_cipher_list` accepts both byte and unicode strings
Hynek Schlawacka7a63af2016-03-11 12:05:26 +0100409 for naming the ciphers which connections created with the context
410 object will be able to choose from.
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100411 """
412 context.set_cipher_list(cipher_string)
413 conn = Connection(context, None)
414
415 assert "AES128-SHA" in conn.get_cipher_list()
416
417 @pytest.mark.parametrize("cipher_list,error", [
418 (object(), TypeError),
419 ("imaginary-cipher", Error),
420 ])
421 def test_set_cipher_list_wrong_args(self, context, cipher_list, error):
422 """
Alex Chan532b79e2017-01-24 15:14:52 +0000423 `Context.set_cipher_list` raises `TypeError` when passed a non-string
424 argument and raises `OpenSSL.SSL.Error` when passed an incorrect cipher
425 list string.
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100426 """
427 with pytest.raises(error):
428 context.set_cipher_list(cipher_list)
429
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100430 def test_load_client_ca(self, context, ca_file):
431 """
Alex Chan532b79e2017-01-24 15:14:52 +0000432 `Context.load_client_ca` works as far as we can tell.
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100433 """
434 context.load_client_ca(ca_file)
435
436 def test_load_client_ca_invalid(self, context, tmpdir):
437 """
Alex Chan532b79e2017-01-24 15:14:52 +0000438 `Context.load_client_ca` raises an Error if the ca file is invalid.
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100439 """
440 ca_file = tmpdir.join("test.pem")
441 ca_file.write("")
442
443 with pytest.raises(Error) as e:
444 context.load_client_ca(str(ca_file).encode("ascii"))
445
446 assert "PEM routines" == e.value.args[0][0][0]
447
448 def test_load_client_ca_unicode(self, context, ca_file):
449 """
450 Passing the path as unicode raises a warning but works.
451 """
452 pytest.deprecated_call(
453 context.load_client_ca, ca_file.decode("ascii")
454 )
455
456 def test_set_session_id(self, context):
457 """
Alex Chan532b79e2017-01-24 15:14:52 +0000458 `Context.set_session_id` works as far as we can tell.
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100459 """
460 context.set_session_id(b"abc")
461
462 def test_set_session_id_fail(self, context):
463 """
Alex Chan532b79e2017-01-24 15:14:52 +0000464 `Context.set_session_id` errors are propagated.
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100465 """
466 with pytest.raises(Error) as e:
467 context.set_session_id(b"abc" * 1000)
468
469 assert [
470 ("SSL routines",
471 "SSL_CTX_set_session_id_context",
472 "ssl session id context too long")
473 ] == e.value.args[0]
474
475 def test_set_session_id_unicode(self, context):
476 """
Alex Chan532b79e2017-01-24 15:14:52 +0000477 `Context.set_session_id` raises a warning if a unicode string is
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100478 passed.
479 """
480 pytest.deprecated_call(context.set_session_id, u"abc")
481
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400482 def test_method(self):
483 """
Alex Chan532b79e2017-01-24 15:14:52 +0000484 `Context` can be instantiated with one of `SSLv2_METHOD`,
485 `SSLv3_METHOD`, `SSLv23_METHOD`, `TLSv1_METHOD`, `TLSv1_1_METHOD`,
486 or `TLSv1_2_METHOD`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400487 """
Alex Gaynor5af32d02016-09-24 01:52:21 -0400488 methods = [SSLv23_METHOD, TLSv1_METHOD]
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400489 for meth in methods:
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400490 Context(meth)
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400491
Alex Gaynor5af32d02016-09-24 01:52:21 -0400492 maybe = [SSLv2_METHOD, SSLv3_METHOD, TLSv1_1_METHOD, TLSv1_2_METHOD]
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400493 for meth in maybe:
494 try:
495 Context(meth)
496 except (Error, ValueError):
497 # Some versions of OpenSSL have SSLv2 / TLSv1.1 / TLSv1.2, some
498 # don't. Difficult to say in advance.
499 pass
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400500
Alex Chan532b79e2017-01-24 15:14:52 +0000501 with pytest.raises(TypeError):
502 Context("")
503 with pytest.raises(ValueError):
504 Context(10)
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400505
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200506 @skip_if_py3
507 def test_method_long(self):
508 """
Alex Chan532b79e2017-01-24 15:14:52 +0000509 On Python 2 `Context` accepts values of type `long` as well as `int`.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200510 """
511 Context(long(TLSv1_METHOD))
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500512
Rick Deane15b1472009-07-09 15:53:42 -0500513 def test_type(self):
514 """
Alex Chan532b79e2017-01-24 15:14:52 +0000515 `Context` and `ContextType` refer to the same type object and can
516 be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -0500517 """
Alex Chan532b79e2017-01-24 15:14:52 +0000518 assert Context is ContextType
519 assert is_consistent_type(Context, 'Context', TLSv1_METHOD)
Rick Deane15b1472009-07-09 15:53:42 -0500520
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400521 def test_use_privatekey(self):
522 """
Alex Chan532b79e2017-01-24 15:14:52 +0000523 `Context.use_privatekey` takes an `OpenSSL.crypto.PKey` instance.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400524 """
525 key = PKey()
526 key.generate_key(TYPE_RSA, 128)
527 ctx = Context(TLSv1_METHOD)
528 ctx.use_privatekey(key)
Alex Chan532b79e2017-01-24 15:14:52 +0000529 with pytest.raises(TypeError):
530 ctx.use_privatekey("")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400531
Alex Chan532b79e2017-01-24 15:14:52 +0000532 def test_use_privatekey_file_missing(self, tmpfile):
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800533 """
Alex Chan532b79e2017-01-24 15:14:52 +0000534 `Context.use_privatekey_file` raises `OpenSSL.SSL.Error` when passed
535 the name of a file which does not exist.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800536 """
537 ctx = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000538 with pytest.raises(Error):
539 ctx.use_privatekey_file(tmpfile)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800540
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400541 def _use_privatekey_file_test(self, pemfile, filetype):
542 """
543 Verify that calling ``Context.use_privatekey_file`` with the given
544 arguments does not raise an exception.
545 """
546 key = PKey()
547 key.generate_key(TYPE_RSA, 128)
548
549 with open(pemfile, "wt") as pem:
550 pem.write(
551 dump_privatekey(FILETYPE_PEM, key).decode("ascii")
552 )
553
554 ctx = Context(TLSv1_METHOD)
555 ctx.use_privatekey_file(pemfile, filetype)
556
Alex Chanfb078d82017-04-20 11:16:15 +0100557 @pytest.mark.parametrize('filetype', [object(), "", None, 1.0])
558 def test_wrong_privatekey_file_wrong_args(self, tmpfile, filetype):
559 """
560 `Context.use_privatekey_file` raises `TypeError` when called with
561 a `filetype` which is not a valid file encoding.
562 """
563 ctx = Context(TLSv1_METHOD)
564 with pytest.raises(TypeError):
565 ctx.use_privatekey_file(tmpfile, filetype)
566
Alex Chan532b79e2017-01-24 15:14:52 +0000567 def test_use_privatekey_file_bytes(self, tmpfile):
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400568 """
569 A private key can be specified from a file by passing a ``bytes``
570 instance giving the file name to ``Context.use_privatekey_file``.
571 """
572 self._use_privatekey_file_test(
Alex Chan532b79e2017-01-24 15:14:52 +0000573 tmpfile + NON_ASCII.encode(getfilesystemencoding()),
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400574 FILETYPE_PEM,
575 )
576
Alex Chan532b79e2017-01-24 15:14:52 +0000577 def test_use_privatekey_file_unicode(self, tmpfile):
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400578 """
579 A private key can be specified from a file by passing a ``unicode``
580 instance giving the file name to ``Context.use_privatekey_file``.
581 """
582 self._use_privatekey_file_test(
Alex Chan532b79e2017-01-24 15:14:52 +0000583 tmpfile.decode(getfilesystemencoding()) + NON_ASCII,
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400584 FILETYPE_PEM,
585 )
586
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200587 @skip_if_py3
Alex Chan532b79e2017-01-24 15:14:52 +0000588 def test_use_privatekey_file_long(self, tmpfile):
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200589 """
Alex Chan532b79e2017-01-24 15:14:52 +0000590 On Python 2 `Context.use_privatekey_file` accepts a filetype of
591 type `long` as well as `int`.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200592 """
Alex Chan532b79e2017-01-24 15:14:52 +0000593 self._use_privatekey_file_test(tmpfile, long(FILETYPE_PEM))
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500594
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800595 def test_use_certificate_wrong_args(self):
596 """
Alex Chan532b79e2017-01-24 15:14:52 +0000597 `Context.use_certificate_wrong_args` raises `TypeError` when not passed
598 exactly one `OpenSSL.crypto.X509` instance as an argument.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800599 """
600 ctx = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000601 with pytest.raises(TypeError):
602 ctx.use_certificate("hello, world")
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800603
604 def test_use_certificate_uninitialized(self):
605 """
Alex Chan532b79e2017-01-24 15:14:52 +0000606 `Context.use_certificate` raises `OpenSSL.SSL.Error` when passed a
607 `OpenSSL.crypto.X509` instance which has not been initialized
608 (ie, which does not actually have any certificate data).
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800609 """
610 ctx = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000611 with pytest.raises(Error):
612 ctx.use_certificate(X509())
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800613
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800614 def test_use_certificate(self):
615 """
Alex Chan532b79e2017-01-24 15:14:52 +0000616 `Context.use_certificate` sets the certificate which will be
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800617 used to identify connections created using the context.
618 """
619 # TODO
620 # Hard to assert anything. But we could set a privatekey then ask
621 # OpenSSL if the cert and key agree using check_privatekey. Then as
622 # long as check_privatekey works right we're good...
623 ctx = Context(TLSv1_METHOD)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200624 ctx.use_certificate(
625 load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
626 )
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800627
628 def test_use_certificate_file_wrong_args(self):
629 """
Alex Chan532b79e2017-01-24 15:14:52 +0000630 `Context.use_certificate_file` raises `TypeError` if the first
631 argument is not a byte string or the second argument is not an integer.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800632 """
633 ctx = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000634 with pytest.raises(TypeError):
635 ctx.use_certificate_file(object(), FILETYPE_PEM)
636 with pytest.raises(TypeError):
637 ctx.use_certificate_file(b"somefile", object())
638 with pytest.raises(TypeError):
639 ctx.use_certificate_file(object(), FILETYPE_PEM)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800640
Alex Chan532b79e2017-01-24 15:14:52 +0000641 def test_use_certificate_file_missing(self, tmpfile):
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800642 """
Alex Chan532b79e2017-01-24 15:14:52 +0000643 `Context.use_certificate_file` raises `OpenSSL.SSL.Error` if passed
644 the name of a file which does not exist.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800645 """
646 ctx = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000647 with pytest.raises(Error):
648 ctx.use_certificate_file(tmpfile)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800649
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400650 def _use_certificate_file_test(self, certificate_file):
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800651 """
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400652 Verify that calling ``Context.use_certificate_file`` with the given
653 filename doesn't raise an exception.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800654 """
655 # TODO
656 # Hard to assert anything. But we could set a privatekey then ask
657 # OpenSSL if the cert and key agree using check_privatekey. Then as
658 # long as check_privatekey works right we're good...
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400659 with open(certificate_file, "wb") as pem_file:
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800660 pem_file.write(cleartextCertificatePEM)
661
662 ctx = Context(TLSv1_METHOD)
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400663 ctx.use_certificate_file(certificate_file)
664
Alex Chan532b79e2017-01-24 15:14:52 +0000665 def test_use_certificate_file_bytes(self, tmpfile):
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400666 """
Alex Chan532b79e2017-01-24 15:14:52 +0000667 `Context.use_certificate_file` sets the certificate (given as a
668 `bytes` filename) which will be used to identify connections created
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400669 using the context.
670 """
Alex Chan532b79e2017-01-24 15:14:52 +0000671 filename = tmpfile + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400672 self._use_certificate_file_test(filename)
673
Alex Chan532b79e2017-01-24 15:14:52 +0000674 def test_use_certificate_file_unicode(self, tmpfile):
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400675 """
Alex Chan532b79e2017-01-24 15:14:52 +0000676 `Context.use_certificate_file` sets the certificate (given as a
677 `bytes` filename) which will be used to identify connections created
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400678 using the context.
679 """
Alex Chan532b79e2017-01-24 15:14:52 +0000680 filename = tmpfile.decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400681 self._use_certificate_file_test(filename)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800682
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200683 @skip_if_py3
Alex Chan532b79e2017-01-24 15:14:52 +0000684 def test_use_certificate_file_long(self, tmpfile):
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200685 """
Alex Chan532b79e2017-01-24 15:14:52 +0000686 On Python 2 `Context.use_certificate_file` accepts a
687 filetype of type `long` as well as `int`.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200688 """
Alex Chan532b79e2017-01-24 15:14:52 +0000689 pem_filename = tmpfile
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200690 with open(pem_filename, "wb") as pem_file:
691 pem_file.write(cleartextCertificatePEM)
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500692
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200693 ctx = Context(TLSv1_METHOD)
694 ctx.use_certificate_file(pem_filename, long(FILETYPE_PEM))
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500695
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500696 def test_check_privatekey_valid(self):
697 """
Alex Chan532b79e2017-01-24 15:14:52 +0000698 `Context.check_privatekey` returns `None` if the `Context` instance
699 has been configured to use a matched key and certificate pair.
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500700 """
701 key = load_privatekey(FILETYPE_PEM, client_key_pem)
702 cert = load_certificate(FILETYPE_PEM, client_cert_pem)
703 context = Context(TLSv1_METHOD)
704 context.use_privatekey(key)
705 context.use_certificate(cert)
Alex Chan532b79e2017-01-24 15:14:52 +0000706 assert None is context.check_privatekey()
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500707
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500708 def test_check_privatekey_invalid(self):
709 """
Alex Chan532b79e2017-01-24 15:14:52 +0000710 `Context.check_privatekey` raises `Error` if the `Context` instance
711 has been configured to use a key and certificate pair which don't
712 relate to each other.
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500713 """
714 key = load_privatekey(FILETYPE_PEM, client_key_pem)
715 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
716 context = Context(TLSv1_METHOD)
717 context.use_privatekey(key)
718 context.use_certificate(cert)
Alex Chan532b79e2017-01-24 15:14:52 +0000719 with pytest.raises(Error):
720 context.check_privatekey()
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400721
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400722 def test_app_data(self):
723 """
Alex Chan532b79e2017-01-24 15:14:52 +0000724 `Context.set_app_data` stores an object for later retrieval
725 using `Context.get_app_data`.
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400726 """
727 app_data = object()
728 context = Context(TLSv1_METHOD)
729 context.set_app_data(app_data)
Alex Chan532b79e2017-01-24 15:14:52 +0000730 assert context.get_app_data() is app_data
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400731
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400732 def test_set_options_wrong_args(self):
733 """
Alex Chan532b79e2017-01-24 15:14:52 +0000734 `Context.set_options` raises `TypeError` if called with
735 a non-`int` argument.
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400736 """
737 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000738 with pytest.raises(TypeError):
739 context.set_options(None)
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400740
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500741 def test_set_options(self):
742 """
Alex Chan532b79e2017-01-24 15:14:52 +0000743 `Context.set_options` returns the new options value.
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500744 """
745 context = Context(TLSv1_METHOD)
746 options = context.set_options(OP_NO_SSLv2)
Alex Gaynor2310f8b2016-09-10 14:39:32 -0400747 assert options & OP_NO_SSLv2 == OP_NO_SSLv2
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500748
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200749 @skip_if_py3
750 def test_set_options_long(self):
751 """
Alex Chan532b79e2017-01-24 15:14:52 +0000752 On Python 2 `Context.set_options` accepts values of type
753 `long` as well as `int`.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200754 """
755 context = Context(TLSv1_METHOD)
756 options = context.set_options(long(OP_NO_SSLv2))
Alex Gaynor2310f8b2016-09-10 14:39:32 -0400757 assert options & OP_NO_SSLv2 == OP_NO_SSLv2
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500758
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300759 def test_set_mode_wrong_args(self):
760 """
Alex Chan532b79e2017-01-24 15:14:52 +0000761 `Context.set_mode` raises `TypeError` if called with
762 a non-`int` argument.
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300763 """
764 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000765 with pytest.raises(TypeError):
766 context.set_mode(None)
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300767
Alex Gaynord3b5d9b2016-07-31 10:54:24 -0400768 def test_set_mode(self):
769 """
Alex Chan532b79e2017-01-24 15:14:52 +0000770 `Context.set_mode` accepts a mode bitvector and returns the
Alex Gaynord3b5d9b2016-07-31 10:54:24 -0400771 newly set mode.
772 """
773 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000774 assert MODE_RELEASE_BUFFERS & context.set_mode(MODE_RELEASE_BUFFERS)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500775
Alex Gaynord3b5d9b2016-07-31 10:54:24 -0400776 @skip_if_py3
777 def test_set_mode_long(self):
778 """
Alex Chan532b79e2017-01-24 15:14:52 +0000779 On Python 2 `Context.set_mode` accepts values of type `long` as well
780 as `int`.
Alex Gaynord3b5d9b2016-07-31 10:54:24 -0400781 """
782 context = Context(TLSv1_METHOD)
783 mode = context.set_mode(long(MODE_RELEASE_BUFFERS))
Alex Chan532b79e2017-01-24 15:14:52 +0000784 assert MODE_RELEASE_BUFFERS & mode
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400785
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400786 def test_set_timeout_wrong_args(self):
787 """
Alex Chan532b79e2017-01-24 15:14:52 +0000788 `Context.set_timeout` raises `TypeError` if called with
789 a non-`int` argument.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400790 """
791 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000792 with pytest.raises(TypeError):
793 context.set_timeout(None)
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400794
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400795 def test_timeout(self):
796 """
Alex Chan532b79e2017-01-24 15:14:52 +0000797 `Context.set_timeout` sets the session timeout for all connections
798 created using the context object. `Context.get_timeout` retrieves
799 this value.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400800 """
801 context = Context(TLSv1_METHOD)
802 context.set_timeout(1234)
Alex Chan532b79e2017-01-24 15:14:52 +0000803 assert context.get_timeout() == 1234
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400804
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200805 @skip_if_py3
806 def test_timeout_long(self):
807 """
Alex Chan532b79e2017-01-24 15:14:52 +0000808 On Python 2 `Context.set_timeout` accepts values of type `long` as
809 well as int.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200810 """
811 context = Context(TLSv1_METHOD)
812 context.set_timeout(long(1234))
Alex Chan532b79e2017-01-24 15:14:52 +0000813 assert context.get_timeout() == 1234
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500814
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400815 def test_set_verify_depth_wrong_args(self):
816 """
Alex Chan532b79e2017-01-24 15:14:52 +0000817 `Context.set_verify_depth` raises `TypeError` if called with a
818 non-`int` argument.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400819 """
820 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000821 with pytest.raises(TypeError):
822 context.set_verify_depth(None)
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400823
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400824 def test_verify_depth(self):
825 """
Alex Chan532b79e2017-01-24 15:14:52 +0000826 `Context.set_verify_depth` sets the number of certificates in
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200827 a chain to follow before giving up. The value can be retrieved with
Alex Chan532b79e2017-01-24 15:14:52 +0000828 `Context.get_verify_depth`.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400829 """
830 context = Context(TLSv1_METHOD)
831 context.set_verify_depth(11)
Alex Chan532b79e2017-01-24 15:14:52 +0000832 assert context.get_verify_depth() == 11
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400833
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200834 @skip_if_py3
835 def test_verify_depth_long(self):
836 """
Alex Chan532b79e2017-01-24 15:14:52 +0000837 On Python 2 `Context.set_verify_depth` accepts values of type `long`
838 as well as int.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200839 """
840 context = Context(TLSv1_METHOD)
841 context.set_verify_depth(long(11))
Alex Chan532b79e2017-01-24 15:14:52 +0000842 assert context.get_verify_depth() == 11
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500843
Alex Chan532b79e2017-01-24 15:14:52 +0000844 def _write_encrypted_pem(self, passphrase, tmpfile):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400845 """
846 Write a new private key out to a new file, encrypted using the given
847 passphrase. Return the path to the new file.
848 """
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400849 key = PKey()
850 key.generate_key(TYPE_RSA, 128)
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400851 pem = dump_privatekey(FILETYPE_PEM, key, "blowfish", passphrase)
Alex Chan532b79e2017-01-24 15:14:52 +0000852 with open(tmpfile, 'w') as fObj:
853 fObj.write(pem.decode('ascii'))
854 return tmpfile
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400855
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400856 def test_set_passwd_cb_wrong_args(self):
857 """
Alex Chan532b79e2017-01-24 15:14:52 +0000858 `Context.set_passwd_cb` raises `TypeError` if called with a
859 non-callable first argument.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400860 """
861 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +0000862 with pytest.raises(TypeError):
863 context.set_passwd_cb(None)
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400864
Alex Chan532b79e2017-01-24 15:14:52 +0000865 def test_set_passwd_cb(self, tmpfile):
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400866 """
Alex Chan532b79e2017-01-24 15:14:52 +0000867 `Context.set_passwd_cb` accepts a callable which will be invoked when
868 a private key is loaded from an encrypted PEM.
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400869 """
Alex Gaynore7f51982016-09-11 11:48:14 -0400870 passphrase = b"foobar"
Alex Chan532b79e2017-01-24 15:14:52 +0000871 pemFile = self._write_encrypted_pem(passphrase, tmpfile)
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400872 calledWith = []
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200873
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400874 def passphraseCallback(maxlen, verify, extra):
875 calledWith.append((maxlen, verify, extra))
876 return passphrase
877 context = Context(TLSv1_METHOD)
878 context.set_passwd_cb(passphraseCallback)
879 context.use_privatekey_file(pemFile)
Alex Chan532b79e2017-01-24 15:14:52 +0000880 assert len(calledWith) == 1
881 assert isinstance(calledWith[0][0], int)
882 assert isinstance(calledWith[0][1], int)
883 assert calledWith[0][2] is None
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400884
Alex Chan532b79e2017-01-24 15:14:52 +0000885 def test_passwd_callback_exception(self, tmpfile):
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400886 """
Alex Chan532b79e2017-01-24 15:14:52 +0000887 `Context.use_privatekey_file` propagates any exception raised
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200888 by the passphrase callback.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400889 """
Alex Chan532b79e2017-01-24 15:14:52 +0000890 pemFile = self._write_encrypted_pem(b"monkeys are nice", tmpfile)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200891
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400892 def passphraseCallback(maxlen, verify, extra):
893 raise RuntimeError("Sorry, I am a fail.")
894
895 context = Context(TLSv1_METHOD)
896 context.set_passwd_cb(passphraseCallback)
Alex Chan532b79e2017-01-24 15:14:52 +0000897 with pytest.raises(RuntimeError):
898 context.use_privatekey_file(pemFile)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400899
Alex Chan532b79e2017-01-24 15:14:52 +0000900 def test_passwd_callback_false(self, tmpfile):
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400901 """
Alex Chan532b79e2017-01-24 15:14:52 +0000902 `Context.use_privatekey_file` raises `OpenSSL.SSL.Error` if the
903 passphrase callback returns a false value.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400904 """
Alex Chan532b79e2017-01-24 15:14:52 +0000905 pemFile = self._write_encrypted_pem(b"monkeys are nice", tmpfile)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200906
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400907 def passphraseCallback(maxlen, verify, extra):
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500908 return b""
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400909
910 context = Context(TLSv1_METHOD)
911 context.set_passwd_cb(passphraseCallback)
Alex Chan532b79e2017-01-24 15:14:52 +0000912 with pytest.raises(Error):
913 context.use_privatekey_file(pemFile)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400914
Alex Chan532b79e2017-01-24 15:14:52 +0000915 def test_passwd_callback_non_string(self, tmpfile):
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400916 """
Alex Chan532b79e2017-01-24 15:14:52 +0000917 `Context.use_privatekey_file` raises `OpenSSL.SSL.Error` if the
918 passphrase callback returns a true non-string value.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400919 """
Alex Chan532b79e2017-01-24 15:14:52 +0000920 pemFile = self._write_encrypted_pem(b"monkeys are nice", tmpfile)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200921
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400922 def passphraseCallback(maxlen, verify, extra):
923 return 10
924
925 context = Context(TLSv1_METHOD)
926 context.set_passwd_cb(passphraseCallback)
Alex Chan532b79e2017-01-24 15:14:52 +0000927 # TODO: Surely this is the wrong error?
928 with pytest.raises(ValueError):
929 context.use_privatekey_file(pemFile)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400930
Alex Chan532b79e2017-01-24 15:14:52 +0000931 def test_passwd_callback_too_long(self, tmpfile):
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400932 """
933 If the passphrase returned by the passphrase callback returns a string
934 longer than the indicated maximum length, it is truncated.
935 """
936 # A priori knowledge!
Alex Gaynore7f51982016-09-11 11:48:14 -0400937 passphrase = b"x" * 1024
Alex Chan532b79e2017-01-24 15:14:52 +0000938 pemFile = self._write_encrypted_pem(passphrase, tmpfile)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200939
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400940 def passphraseCallback(maxlen, verify, extra):
941 assert maxlen == 1024
Alex Gaynore7f51982016-09-11 11:48:14 -0400942 return passphrase + b"y"
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400943
944 context = Context(TLSv1_METHOD)
945 context.set_passwd_cb(passphraseCallback)
946 # This shall succeed because the truncated result is the correct
947 # passphrase.
948 context.use_privatekey_file(pemFile)
949
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400950 def test_set_info_callback(self):
951 """
Alex Chan532b79e2017-01-24 15:14:52 +0000952 `Context.set_info_callback` accepts a callable which will be
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200953 invoked when certain information about an SSL connection is available.
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400954 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500955 (server, client) = socket_pair()
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400956
957 clientSSL = Connection(Context(TLSv1_METHOD), client)
958 clientSSL.set_connect_state()
959
960 called = []
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200961
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400962 def info(conn, where, ret):
963 called.append((conn, where, ret))
964 context = Context(TLSv1_METHOD)
965 context.set_info_callback(info)
966 context.use_certificate(
967 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
968 context.use_privatekey(
969 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
970
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400971 serverSSL = Connection(context, server)
972 serverSSL.set_accept_state()
973
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -0500974 handshake(clientSSL, serverSSL)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400975
Jean-Paul Calderone3835e522014-02-02 11:12:30 -0500976 # The callback must always be called with a Connection instance as the
977 # first argument. It would probably be better to split this into
978 # separate tests for client and server side info callbacks so we could
979 # assert it is called with the right Connection instance. It would
980 # also be good to assert *something* about `where` and `ret`.
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -0500981 notConnections = [
982 conn for (conn, where, ret) in called
983 if not isinstance(conn, Connection)]
Alex Chan532b79e2017-01-24 15:14:52 +0000984 assert [] == notConnections, (
985 "Some info callback arguments were not Connection instances.")
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400986
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400987 def _load_verify_locations_test(self, *args):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400988 """
989 Create a client context which will verify the peer certificate and call
Alex Chan532b79e2017-01-24 15:14:52 +0000990 its `load_verify_locations` method with the given arguments.
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -0400991 Then connect it to a server and ensure that the handshake succeeds.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400992 """
Rick Deanb1ccd562009-07-09 23:52:39 -0500993 (server, client) = socket_pair()
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400994
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400995 clientContext = Context(TLSv1_METHOD)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -0400996 clientContext.load_verify_locations(*args)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -0400997 # Require that the server certificate verify properly or the
998 # connection will fail.
999 clientContext.set_verify(
1000 VERIFY_PEER,
1001 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
1002
1003 clientSSL = Connection(clientContext, client)
1004 clientSSL.set_connect_state()
1005
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001006 serverContext = Context(TLSv1_METHOD)
1007 serverContext.use_certificate(
1008 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1009 serverContext.use_privatekey(
1010 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1011
1012 serverSSL = Connection(serverContext, server)
1013 serverSSL.set_accept_state()
1014
Jean-Paul Calderonef8742032010-09-25 00:00:32 -04001015 # Without load_verify_locations above, the handshake
1016 # will fail:
1017 # Error: [('SSL routines', 'SSL3_GET_SERVER_CERTIFICATE',
1018 # 'certificate verify failed')]
1019 handshake(clientSSL, serverSSL)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001020
1021 cert = clientSSL.get_peer_certificate()
Alex Chan532b79e2017-01-24 15:14:52 +00001022 assert cert.get_subject().CN == 'Testing Root CA'
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -04001023
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001024 def _load_verify_cafile(self, cafile):
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001025 """
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001026 Verify that if path to a file containing a certificate is passed to
Alex Chan532b79e2017-01-24 15:14:52 +00001027 `Context.load_verify_locations` for the ``cafile`` parameter, that
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001028 certificate is used as a trust root for the purposes of verifying
Alex Chan532b79e2017-01-24 15:14:52 +00001029 connections created using that `Context`.
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001030 """
Alex Chan532b79e2017-01-24 15:14:52 +00001031 with open(cafile, 'w') as fObj:
1032 fObj.write(cleartextCertificatePEM.decode('ascii'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001033
1034 self._load_verify_locations_test(cafile)
1035
Alex Chan532b79e2017-01-24 15:14:52 +00001036 def test_load_verify_bytes_cafile(self, tmpfile):
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001037 """
Alex Chan532b79e2017-01-24 15:14:52 +00001038 `Context.load_verify_locations` accepts a file name as a `bytes`
1039 instance and uses the certificates within for verification purposes.
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001040 """
Alex Chan532b79e2017-01-24 15:14:52 +00001041 cafile = tmpfile + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001042 self._load_verify_cafile(cafile)
1043
Alex Chan532b79e2017-01-24 15:14:52 +00001044 def test_load_verify_unicode_cafile(self, tmpfile):
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001045 """
Alex Chan532b79e2017-01-24 15:14:52 +00001046 `Context.load_verify_locations` accepts a file name as a `unicode`
1047 instance and uses the certificates within for verification purposes.
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001048 """
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001049 self._load_verify_cafile(
Alex Chan532b79e2017-01-24 15:14:52 +00001050 tmpfile.decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001051 )
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001052
Alex Chan532b79e2017-01-24 15:14:52 +00001053 def test_load_verify_invalid_file(self, tmpfile):
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -04001054 """
Alex Chan532b79e2017-01-24 15:14:52 +00001055 `Context.load_verify_locations` raises `Error` when passed a
1056 non-existent cafile.
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -04001057 """
1058 clientContext = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001059 with pytest.raises(Error):
1060 clientContext.load_verify_locations(tmpfile)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001061
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001062 def _load_verify_directory_locations_capath(self, capath):
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001063 """
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001064 Verify that if path to a directory containing certificate files is
1065 passed to ``Context.load_verify_locations`` for the ``capath``
1066 parameter, those certificates are used as trust roots for the purposes
1067 of verifying connections created using that ``Context``.
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001068 """
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001069 makedirs(capath)
Jean-Paul Calderone24dfb332011-05-04 18:10:26 -04001070 # Hash values computed manually with c_rehash to avoid depending on
1071 # c_rehash in the test suite. One is from OpenSSL 0.9.8, the other
1072 # from OpenSSL 1.0.0.
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001073 for name in [b'c7adac82.0', b'c3705638.0']:
Jean-Paul Calderone05826732015-04-12 11:38:49 -04001074 cafile = join_bytes_or_unicode(capath, name)
1075 with open(cafile, 'w') as fObj:
1076 fObj.write(cleartextCertificatePEM.decode('ascii'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001077
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001078 self._load_verify_locations_test(None, capath)
1079
Alex Chan532b79e2017-01-24 15:14:52 +00001080 def test_load_verify_directory_bytes_capath(self, tmpfile):
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001081 """
Alex Chan532b79e2017-01-24 15:14:52 +00001082 `Context.load_verify_locations` accepts a directory name as a `bytes`
1083 instance and uses the certificates within for verification purposes.
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001084 """
1085 self._load_verify_directory_locations_capath(
Alex Chan532b79e2017-01-24 15:14:52 +00001086 tmpfile + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001087 )
1088
Alex Chan532b79e2017-01-24 15:14:52 +00001089 def test_load_verify_directory_unicode_capath(self, tmpfile):
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001090 """
Alex Chan532b79e2017-01-24 15:14:52 +00001091 `Context.load_verify_locations` accepts a directory name as a `unicode`
1092 instance and uses the certificates within for verification purposes.
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001093 """
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001094 self._load_verify_directory_locations_capath(
Alex Chan532b79e2017-01-24 15:14:52 +00001095 tmpfile.decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001096 )
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001097
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001098 def test_load_verify_locations_wrong_args(self):
1099 """
Alex Chan532b79e2017-01-24 15:14:52 +00001100 `Context.load_verify_locations` raises `TypeError` if with non-`str`
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001101 arguments.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001102 """
1103 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001104 with pytest.raises(TypeError):
1105 context.load_verify_locations(object())
1106 with pytest.raises(TypeError):
1107 context.load_verify_locations(object(), object())
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001108
Hynek Schlawack734d3022015-09-05 19:19:32 +02001109 @pytest.mark.skipif(
Paul Kehrer55fb3412017-06-29 18:44:08 -05001110 not platform.startswith("linux"),
1111 reason="Loading fallback paths is a linux-specific behavior to "
1112 "accommodate pyca/cryptography manylinux1 wheels"
1113 )
1114 def test_fallback_default_verify_paths(self, monkeypatch):
1115 """
1116 Test that we load certificates successfully on linux from the fallback
1117 path. To do this we set the _CRYPTOGRAPHY_MANYLINUX1_CA_FILE and
1118 _CRYPTOGRAPHY_MANYLINUX1_CA_DIR vars to be equal to whatever the
1119 current OpenSSL default is and we disable
1120 SSL_CTX_SET_default_verify_paths so that it can't find certs unless
1121 it loads via fallback.
1122 """
1123 context = Context(TLSv1_METHOD)
1124 monkeypatch.setattr(
1125 _lib, "SSL_CTX_set_default_verify_paths", lambda x: 1
1126 )
1127 monkeypatch.setattr(
1128 SSL,
1129 "_CRYPTOGRAPHY_MANYLINUX1_CA_FILE",
1130 _ffi.string(_lib.X509_get_default_cert_file())
1131 )
1132 monkeypatch.setattr(
1133 SSL,
1134 "_CRYPTOGRAPHY_MANYLINUX1_CA_DIR",
1135 _ffi.string(_lib.X509_get_default_cert_dir())
1136 )
1137 context.set_default_verify_paths()
1138 store = context.get_cert_store()
1139 sk_obj = _lib.X509_STORE_get0_objects(store._store)
1140 assert sk_obj != _ffi.NULL
1141 num = _lib.sk_X509_OBJECT_num(sk_obj)
1142 assert num != 0
1143
1144 def test_check_env_vars(self, monkeypatch):
1145 """
1146 Test that we return True/False appropriately if the env vars are set.
1147 """
1148 context = Context(TLSv1_METHOD)
1149 dir_var = "CUSTOM_DIR_VAR"
1150 file_var = "CUSTOM_FILE_VAR"
1151 assert context._check_env_vars_set(dir_var, file_var) is False
1152 monkeypatch.setenv(dir_var, "value")
1153 monkeypatch.setenv(file_var, "value")
1154 assert context._check_env_vars_set(dir_var, file_var) is True
1155 assert context._check_env_vars_set(dir_var, file_var) is True
1156
1157 def test_verify_no_fallback_if_env_vars_set(self, monkeypatch):
1158 """
1159 Test that we don't use the fallback path if env vars are set.
1160 """
1161 context = Context(TLSv1_METHOD)
1162 monkeypatch.setattr(
1163 _lib, "SSL_CTX_set_default_verify_paths", lambda x: 1
1164 )
1165 dir_env_var = _ffi.string(
1166 _lib.X509_get_default_cert_dir_env()
1167 ).decode("ascii")
1168 file_env_var = _ffi.string(
1169 _lib.X509_get_default_cert_file_env()
1170 ).decode("ascii")
1171 monkeypatch.setenv(dir_env_var, "value")
1172 monkeypatch.setenv(file_env_var, "value")
1173 context.set_default_verify_paths()
1174
1175 monkeypatch.setattr(
1176 context,
1177 "_fallback_default_verify_paths",
1178 raiser(SystemError)
1179 )
1180 context.set_default_verify_paths()
1181
1182 @pytest.mark.skipif(
Hynek Schlawack734d3022015-09-05 19:19:32 +02001183 platform == "win32",
1184 reason="set_default_verify_paths appears not to work on Windows. "
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -04001185 "See LP#404343 and LP#404344."
Hynek Schlawack734d3022015-09-05 19:19:32 +02001186 )
1187 def test_set_default_verify_paths(self):
1188 """
Alex Chan532b79e2017-01-24 15:14:52 +00001189 `Context.set_default_verify_paths` causes the platform-specific CA
1190 certificate locations to be used for verification purposes.
Hynek Schlawack734d3022015-09-05 19:19:32 +02001191 """
1192 # Testing this requires a server with a certificate signed by one
1193 # of the CAs in the platform CA location. Getting one of those
1194 # costs money. Fortunately (or unfortunately, depending on your
1195 # perspective), it's easy to think of a public server on the
1196 # internet which has such a certificate. Connecting to the network
1197 # in a unit test is bad, but it's the only way I can think of to
1198 # really test this. -exarkun
Hynek Schlawackbf887932015-10-21 17:13:47 +02001199 context = Context(SSLv23_METHOD)
Hynek Schlawack734d3022015-09-05 19:19:32 +02001200 context.set_default_verify_paths()
1201 context.set_verify(
1202 VERIFY_PEER,
1203 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001204
Hynek Schlawack734d3022015-09-05 19:19:32 +02001205 client = socket()
Hynek Schlawackbf887932015-10-21 17:13:47 +02001206 client.connect(("encrypted.google.com", 443))
Hynek Schlawack734d3022015-09-05 19:19:32 +02001207 clientSSL = Connection(context, client)
1208 clientSSL.set_connect_state()
1209 clientSSL.do_handshake()
1210 clientSSL.send(b"GET / HTTP/1.0\r\n\r\n")
Alex Chan532b79e2017-01-24 15:14:52 +00001211 assert clientSSL.recv(1024)
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05001212
Paul Kehrer55fb3412017-06-29 18:44:08 -05001213 def test_fallback_path_is_not_file_or_dir(self):
1214 """
1215 Test that when passed empty arrays or paths that do not exist no
1216 errors are raised.
1217 """
1218 context = Context(TLSv1_METHOD)
1219 context._fallback_default_verify_paths([], [])
1220 context._fallback_default_verify_paths(
1221 ["/not/a/file"], ["/not/a/dir"]
1222 )
1223
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001224 def test_add_extra_chain_cert_invalid_cert(self):
1225 """
Alex Chan532b79e2017-01-24 15:14:52 +00001226 `Context.add_extra_chain_cert` raises `TypeError` if called with an
1227 object which is not an instance of `X509`.
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001228 """
1229 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001230 with pytest.raises(TypeError):
1231 context.add_extra_chain_cert(object())
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001232
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001233 def _handshake_test(self, serverContext, clientContext):
1234 """
1235 Verify that a client and server created with the given contexts can
1236 successfully handshake and communicate.
1237 """
1238 serverSocket, clientSocket = socket_pair()
1239
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001240 server = Connection(serverContext, serverSocket)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001241 server.set_accept_state()
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001242
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001243 client = Connection(clientContext, clientSocket)
1244 client.set_connect_state()
1245
1246 # Make them talk to each other.
Alex Chan532b79e2017-01-24 15:14:52 +00001247 # interact_in_memory(client, server)
1248 for _ in range(3):
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001249 for s in [client, server]:
1250 try:
1251 s.do_handshake()
1252 except WantReadError:
1253 pass
1254
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001255 def test_set_verify_callback_connection_argument(self):
1256 """
1257 The first argument passed to the verify callback is the
Alex Chan532b79e2017-01-24 15:14:52 +00001258 `Connection` instance for which verification is taking place.
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001259 """
1260 serverContext = Context(TLSv1_METHOD)
1261 serverContext.use_privatekey(
1262 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1263 serverContext.use_certificate(
1264 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1265 serverConnection = Connection(serverContext, None)
1266
1267 class VerifyCallback(object):
1268 def callback(self, connection, *args):
1269 self.connection = connection
1270 return 1
1271
1272 verify = VerifyCallback()
1273 clientContext = Context(TLSv1_METHOD)
1274 clientContext.set_verify(VERIFY_PEER, verify.callback)
1275 clientConnection = Connection(clientContext, None)
1276 clientConnection.set_connect_state()
1277
Alex Chan532b79e2017-01-24 15:14:52 +00001278 handshake_in_memory(clientConnection, serverConnection)
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001279
Alex Chan532b79e2017-01-24 15:14:52 +00001280 assert verify.connection is clientConnection
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001281
Paul Kehrere7381862017-11-30 20:55:25 +08001282 def test_x509_in_verify_works(self):
1283 """
1284 We had a bug where the X509 cert instantiated in the callback wrapper
1285 didn't __init__ so it was missing objects needed when calling
1286 get_subject. This test sets up a handshake where we call get_subject
1287 on the cert provided to the verify callback.
1288 """
1289 serverContext = Context(TLSv1_METHOD)
1290 serverContext.use_privatekey(
1291 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1292 serverContext.use_certificate(
1293 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1294 serverConnection = Connection(serverContext, None)
1295
1296 def verify_cb_get_subject(conn, cert, errnum, depth, ok):
1297 assert cert.get_subject()
1298 return 1
1299
1300 clientContext = Context(TLSv1_METHOD)
1301 clientContext.set_verify(VERIFY_PEER, verify_cb_get_subject)
1302 clientConnection = Connection(clientContext, None)
1303 clientConnection.set_connect_state()
1304
1305 handshake_in_memory(clientConnection, serverConnection)
1306
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001307 def test_set_verify_callback_exception(self):
1308 """
Alex Chan532b79e2017-01-24 15:14:52 +00001309 If the verify callback passed to `Context.set_verify` raises an
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001310 exception, verification fails and the exception is propagated to the
Alex Chan532b79e2017-01-24 15:14:52 +00001311 caller of `Connection.do_handshake`.
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001312 """
1313 serverContext = Context(TLSv1_METHOD)
1314 serverContext.use_privatekey(
1315 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1316 serverContext.use_certificate(
1317 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1318
1319 clientContext = Context(TLSv1_METHOD)
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001320
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001321 def verify_callback(*args):
1322 raise Exception("silly verify failure")
1323 clientContext.set_verify(VERIFY_PEER, verify_callback)
1324
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01001325 with pytest.raises(Exception) as exc:
1326 self._handshake_test(serverContext, clientContext)
1327
Alex Chan532b79e2017-01-24 15:14:52 +00001328 assert "silly verify failure" == str(exc.value)
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001329
Alex Chan532b79e2017-01-24 15:14:52 +00001330 def test_add_extra_chain_cert(self, tmpdir):
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001331 """
Alex Chan532b79e2017-01-24 15:14:52 +00001332 `Context.add_extra_chain_cert` accepts an `X509`
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001333 instance to add to the certificate chain.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001334
Alex Chan532b79e2017-01-24 15:14:52 +00001335 See `_create_certificate_chain` for the details of the
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001336 certificate chain tested.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001337
1338 The chain is tested by starting a server with scert and connecting
1339 to it with a client which trusts cacert and requires verification to
1340 succeed.
1341 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001342 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001343 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1344
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001345 # Dump the CA certificate to a file because that's the only way to load
1346 # it as a trusted CA in the client context.
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001347 for cert, name in [(cacert, 'ca.pem'),
1348 (icert, 'i.pem'),
1349 (scert, 's.pem')]:
Alex Chan532b79e2017-01-24 15:14:52 +00001350 with tmpdir.join(name).open('w') as f:
Hynek Schlawacke90680f2015-04-16 15:09:27 -04001351 f.write(dump_certificate(FILETYPE_PEM, cert).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001352
Hynek Schlawack1902c012015-04-16 15:06:41 -04001353 for key, name in [(cakey, 'ca.key'),
1354 (ikey, 'i.key'),
1355 (skey, 's.key')]:
Alex Chan532b79e2017-01-24 15:14:52 +00001356 with tmpdir.join(name).open('w') as f:
Hynek Schlawacke90680f2015-04-16 15:09:27 -04001357 f.write(dump_privatekey(FILETYPE_PEM, key).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001358
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001359 # Create the server context
1360 serverContext = Context(TLSv1_METHOD)
1361 serverContext.use_privatekey(skey)
1362 serverContext.use_certificate(scert)
Jean-Paul Calderone16cf03d2010-09-08 18:53:39 -04001363 # The client already has cacert, we only need to give them icert.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001364 serverContext.add_extra_chain_cert(icert)
1365
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001366 # Create the client
1367 clientContext = Context(TLSv1_METHOD)
1368 clientContext.set_verify(
1369 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Alex Chan532b79e2017-01-24 15:14:52 +00001370 clientContext.load_verify_locations(str(tmpdir.join("ca.pem")))
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001371
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001372 # Try it out.
1373 self._handshake_test(serverContext, clientContext)
1374
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001375 def _use_certificate_chain_file_test(self, certdir):
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001376 """
Alex Chan532b79e2017-01-24 15:14:52 +00001377 Verify that `Context.use_certificate_chain_file` reads a
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001378 certificate chain from a specified file.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001379
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001380 The chain is tested by starting a server with scert and connecting to
1381 it with a client which trusts cacert and requires verification to
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001382 succeed.
1383 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001384 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001385 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1386
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001387 makedirs(certdir)
1388
Jean-Paul Calderone05826732015-04-12 11:38:49 -04001389 chainFile = join_bytes_or_unicode(certdir, "chain.pem")
1390 caFile = join_bytes_or_unicode(certdir, "ca.pem")
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001391
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001392 # Write out the chain file.
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001393 with open(chainFile, 'wb') as fObj:
1394 # Most specific to least general.
1395 fObj.write(dump_certificate(FILETYPE_PEM, scert))
1396 fObj.write(dump_certificate(FILETYPE_PEM, icert))
1397 fObj.write(dump_certificate(FILETYPE_PEM, cacert))
1398
1399 with open(caFile, 'w') as fObj:
1400 fObj.write(dump_certificate(FILETYPE_PEM, cacert).decode('ascii'))
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001401
1402 serverContext = Context(TLSv1_METHOD)
1403 serverContext.use_certificate_chain_file(chainFile)
1404 serverContext.use_privatekey(skey)
1405
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001406 clientContext = Context(TLSv1_METHOD)
1407 clientContext.set_verify(
1408 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001409 clientContext.load_verify_locations(caFile)
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001410
1411 self._handshake_test(serverContext, clientContext)
1412
Alex Chan532b79e2017-01-24 15:14:52 +00001413 def test_use_certificate_chain_file_bytes(self, tmpfile):
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001414 """
1415 ``Context.use_certificate_chain_file`` accepts the name of a file (as
1416 an instance of ``bytes``) to specify additional certificates to use to
1417 construct and verify a trust chain.
1418 """
1419 self._use_certificate_chain_file_test(
Alex Chan532b79e2017-01-24 15:14:52 +00001420 tmpfile + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001421 )
1422
Alex Chan532b79e2017-01-24 15:14:52 +00001423 def test_use_certificate_chain_file_unicode(self, tmpfile):
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001424 """
1425 ``Context.use_certificate_chain_file`` accepts the name of a file (as
1426 an instance of ``unicode``) to specify additional certificates to use
1427 to construct and verify a trust chain.
1428 """
1429 self._use_certificate_chain_file_test(
Alex Chan532b79e2017-01-24 15:14:52 +00001430 tmpfile.decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001431 )
1432
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001433 def test_use_certificate_chain_file_wrong_args(self):
1434 """
Alex Chan532b79e2017-01-24 15:14:52 +00001435 `Context.use_certificate_chain_file` raises `TypeError` if passed a
1436 non-byte string single argument.
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001437 """
1438 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001439 with pytest.raises(TypeError):
1440 context.use_certificate_chain_file(object())
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001441
Alex Chan532b79e2017-01-24 15:14:52 +00001442 def test_use_certificate_chain_file_missing_file(self, tmpfile):
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001443 """
Alex Chan532b79e2017-01-24 15:14:52 +00001444 `Context.use_certificate_chain_file` raises `OpenSSL.SSL.Error` when
1445 passed a bad chain file name (for example, the name of a file which
1446 does not exist).
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001447 """
1448 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001449 with pytest.raises(Error):
1450 context.use_certificate_chain_file(tmpfile)
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001451
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001452 def test_set_verify_mode(self):
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001453 """
Alex Chan532b79e2017-01-24 15:14:52 +00001454 `Context.get_verify_mode` returns the verify mode flags previously
1455 passed to `Context.set_verify`.
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001456 """
1457 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001458 assert context.get_verify_mode() == 0
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001459 context.set_verify(
1460 VERIFY_PEER | VERIFY_CLIENT_ONCE, lambda *args: None)
Alex Chan532b79e2017-01-24 15:14:52 +00001461 assert context.get_verify_mode() == (VERIFY_PEER | VERIFY_CLIENT_ONCE)
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001462
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001463 @skip_if_py3
1464 def test_set_verify_mode_long(self):
1465 """
Alex Chan532b79e2017-01-24 15:14:52 +00001466 On Python 2 `Context.set_verify_mode` accepts values of type `long`
1467 as well as `int`.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001468 """
1469 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001470 assert context.get_verify_mode() == 0
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001471 context.set_verify(
Hynek Schlawackb4ceed32015-09-05 20:55:19 +02001472 long(VERIFY_PEER | VERIFY_CLIENT_ONCE), lambda *args: None
1473 ) # pragma: nocover
Alex Chan532b79e2017-01-24 15:14:52 +00001474 assert context.get_verify_mode() == (VERIFY_PEER | VERIFY_CLIENT_ONCE)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001475
Alex Chanfb078d82017-04-20 11:16:15 +01001476 @pytest.mark.parametrize('mode', [None, 1.0, object(), 'mode'])
1477 def test_set_verify_wrong_mode_arg(self, mode):
1478 """
1479 `Context.set_verify` raises `TypeError` if the first argument is
1480 not an integer.
1481 """
1482 context = Context(TLSv1_METHOD)
1483 with pytest.raises(TypeError):
1484 context.set_verify(mode=mode, callback=lambda *args: None)
1485
1486 @pytest.mark.parametrize('callback', [None, 1.0, 'mode', ('foo', 'bar')])
1487 def test_set_verify_wrong_callable_arg(self, callback):
1488 """
1489 `Context.set_verify` raises `TypeError` if the the second argument
1490 is not callable.
1491 """
1492 context = Context(TLSv1_METHOD)
1493 with pytest.raises(TypeError):
1494 context.set_verify(mode=VERIFY_PEER, callback=callback)
1495
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001496 def test_load_tmp_dh_wrong_args(self):
1497 """
Alex Chan532b79e2017-01-24 15:14:52 +00001498 `Context.load_tmp_dh` raises `TypeError` if called with a
1499 non-`str` argument.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001500 """
1501 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001502 with pytest.raises(TypeError):
1503 context.load_tmp_dh(object())
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001504
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001505 def test_load_tmp_dh_missing_file(self):
1506 """
Alex Chan532b79e2017-01-24 15:14:52 +00001507 `Context.load_tmp_dh` raises `OpenSSL.SSL.Error` if the
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001508 specified file does not exist.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001509 """
1510 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001511 with pytest.raises(Error):
1512 context.load_tmp_dh(b"hello")
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001513
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001514 def _load_tmp_dh_test(self, dhfilename):
Jean-Paul Calderone4e0c43f2015-04-13 10:15:17 -04001515 """
1516 Verify that calling ``Context.load_tmp_dh`` with the given filename
1517 does not raise an exception.
1518 """
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001519 context = Context(TLSv1_METHOD)
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001520 with open(dhfilename, "w") as dhfile:
1521 dhfile.write(dhparam)
1522
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001523 context.load_tmp_dh(dhfilename)
1524 # XXX What should I assert here? -exarkun
1525
Alex Chan532b79e2017-01-24 15:14:52 +00001526 def test_load_tmp_dh_bytes(self, tmpfile):
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001527 """
Alex Chan532b79e2017-01-24 15:14:52 +00001528 `Context.load_tmp_dh` loads Diffie-Hellman parameters from the
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001529 specified file (given as ``bytes``).
1530 """
1531 self._load_tmp_dh_test(
Alex Chan532b79e2017-01-24 15:14:52 +00001532 tmpfile + NON_ASCII.encode(getfilesystemencoding()),
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001533 )
1534
Alex Chan532b79e2017-01-24 15:14:52 +00001535 def test_load_tmp_dh_unicode(self, tmpfile):
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001536 """
Alex Chan532b79e2017-01-24 15:14:52 +00001537 `Context.load_tmp_dh` loads Diffie-Hellman parameters from the
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001538 specified file (given as ``unicode``).
1539 """
1540 self._load_tmp_dh_test(
Alex Chan532b79e2017-01-24 15:14:52 +00001541 tmpfile.decode(getfilesystemencoding()) + NON_ASCII,
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001542 )
1543
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001544 def test_set_tmp_ecdh(self):
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001545 """
Alex Chan532b79e2017-01-24 15:14:52 +00001546 `Context.set_tmp_ecdh` sets the elliptic curve for Diffie-Hellman to
1547 the specified curve.
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001548 """
1549 context = Context(TLSv1_METHOD)
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001550 for curve in get_elliptic_curves():
Hynek Schlawacka07fa8c2015-10-17 10:15:28 +02001551 if curve.name.startswith(u"Oakley-"):
Hynek Schlawack7408aff2015-10-17 09:51:16 +02001552 # Setting Oakley-EC2N-4 and Oakley-EC2N-3 adds
1553 # ('bignum routines', 'BN_mod_inverse', 'no inverse') to the
1554 # error queue on OpenSSL 1.0.2.
1555 continue
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001556 # The only easily "assertable" thing is that it does not raise an
1557 # exception.
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001558 context.set_tmp_ecdh(curve)
Alex Gaynor12dc0842014-01-17 12:51:31 -06001559
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001560 def test_set_session_cache_mode_wrong_args(self):
1561 """
Alex Chan532b79e2017-01-24 15:14:52 +00001562 `Context.set_session_cache_mode` raises `TypeError` if called with
1563 a non-integer argument.
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001564 called with other than one integer argument.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001565 """
1566 context = Context(TLSv1_METHOD)
Alex Chan532b79e2017-01-24 15:14:52 +00001567 with pytest.raises(TypeError):
1568 context.set_session_cache_mode(object())
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001569
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001570 def test_session_cache_mode(self):
1571 """
Alex Chan532b79e2017-01-24 15:14:52 +00001572 `Context.set_session_cache_mode` specifies how sessions are cached.
1573 The setting can be retrieved via `Context.get_session_cache_mode`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001574 """
1575 context = Context(TLSv1_METHOD)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001576 context.set_session_cache_mode(SESS_CACHE_OFF)
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001577 off = context.set_session_cache_mode(SESS_CACHE_BOTH)
Alex Chan532b79e2017-01-24 15:14:52 +00001578 assert SESS_CACHE_OFF == off
1579 assert SESS_CACHE_BOTH == context.get_session_cache_mode()
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001580
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001581 @skip_if_py3
1582 def test_session_cache_mode_long(self):
1583 """
Alex Chan532b79e2017-01-24 15:14:52 +00001584 On Python 2 `Context.set_session_cache_mode` accepts values
1585 of type `long` as well as `int`.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001586 """
1587 context = Context(TLSv1_METHOD)
1588 context.set_session_cache_mode(long(SESS_CACHE_BOTH))
Alex Chan532b79e2017-01-24 15:14:52 +00001589 assert SESS_CACHE_BOTH == context.get_session_cache_mode()
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001590
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001591 def test_get_cert_store(self):
1592 """
Alex Chan532b79e2017-01-24 15:14:52 +00001593 `Context.get_cert_store` returns a `X509Store` instance.
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001594 """
1595 context = Context(TLSv1_METHOD)
1596 store = context.get_cert_store()
Alex Chan532b79e2017-01-24 15:14:52 +00001597 assert isinstance(store, X509Store)
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001598
1599
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001600class TestServerNameCallback(object):
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001601 """
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001602 Tests for `Context.set_tlsext_servername_callback` and its
1603 interaction with `Connection`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001604 """
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001605 def test_old_callback_forgotten(self):
1606 """
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001607 If `Context.set_tlsext_servername_callback` is used to specify
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001608 a new callback, the one it replaces is dereferenced.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001609 """
Alex Chanfb078d82017-04-20 11:16:15 +01001610 def callback(connection): # pragma: no cover
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001611 pass
1612
Alex Chanfb078d82017-04-20 11:16:15 +01001613 def replacement(connection): # pragma: no cover
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001614 pass
1615
1616 context = Context(TLSv1_METHOD)
1617 context.set_tlsext_servername_callback(callback)
1618
1619 tracker = ref(callback)
1620 del callback
1621
1622 context.set_tlsext_servername_callback(replacement)
Jean-Paul Calderoned4033eb2014-01-11 08:21:46 -05001623
1624 # One run of the garbage collector happens to work on CPython. PyPy
1625 # doesn't collect the underlying object until a second run for whatever
1626 # reason. That's fine, it still demonstrates our code has properly
1627 # dropped the reference.
1628 collect()
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001629 collect()
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001630
1631 callback = tracker()
1632 if callback is not None:
1633 referrers = get_referrers(callback)
Alex Chanfb078d82017-04-20 11:16:15 +01001634 if len(referrers) > 1: # pragma: nocover
1635 pytest.fail("Some references remain: %r" % (referrers,))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001636
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001637 def test_no_servername(self):
1638 """
1639 When a client specifies no server name, the callback passed to
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001640 `Context.set_tlsext_servername_callback` is invoked and the
1641 result of `Connection.get_servername` is `None`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001642 """
1643 args = []
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001644
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001645 def servername(conn):
1646 args.append((conn, conn.get_servername()))
1647 context = Context(TLSv1_METHOD)
1648 context.set_tlsext_servername_callback(servername)
1649
1650 # Lose our reference to it. The Context is responsible for keeping it
1651 # alive now.
1652 del servername
1653 collect()
1654
1655 # Necessary to actually accept the connection
1656 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001657 context.use_certificate(
1658 load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001659
1660 # Do a little connection to trigger the logic
1661 server = Connection(context, None)
1662 server.set_accept_state()
1663
1664 client = Connection(Context(TLSv1_METHOD), None)
1665 client.set_connect_state()
1666
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001667 interact_in_memory(server, client)
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001668
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001669 assert args == [(server, None)]
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001670
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001671 def test_servername(self):
1672 """
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001673 When a client specifies a server name in its hello message, the
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001674 callback passed to `Contexts.set_tlsext_servername_callback` is
1675 invoked and the result of `Connection.get_servername` is that
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001676 server name.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001677 """
1678 args = []
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001679
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001680 def servername(conn):
1681 args.append((conn, conn.get_servername()))
1682 context = Context(TLSv1_METHOD)
1683 context.set_tlsext_servername_callback(servername)
1684
1685 # Necessary to actually accept the connection
1686 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001687 context.use_certificate(
1688 load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001689
1690 # Do a little connection to trigger the logic
1691 server = Connection(context, None)
1692 server.set_accept_state()
1693
1694 client = Connection(Context(TLSv1_METHOD), None)
1695 client.set_connect_state()
Alex Gaynore7f51982016-09-11 11:48:14 -04001696 client.set_tlsext_host_name(b"foo1.example.com")
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001697
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001698 interact_in_memory(server, client)
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001699
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001700 assert args == [(server, b"foo1.example.com")]
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001701
1702
Alex Chan9e08b3e2016-11-10 12:18:54 +00001703class TestNextProtoNegotiation(object):
Cory Benfield84a121e2014-03-31 20:30:25 +01001704 """
1705 Test for Next Protocol Negotiation in PyOpenSSL.
1706 """
Alex Chan9e08b3e2016-11-10 12:18:54 +00001707 def test_npn_success(self):
1708 """
1709 Tests that clients and servers that agree on the negotiated next
1710 protocol can correct establish a connection, and that the agreed
1711 protocol is reported by the connections.
1712 """
1713 advertise_args = []
1714 select_args = []
1715
1716 def advertise(conn):
1717 advertise_args.append((conn,))
1718 return [b'http/1.1', b'spdy/2']
1719
1720 def select(conn, options):
1721 select_args.append((conn, options))
1722 return b'spdy/2'
1723
1724 server_context = Context(TLSv1_METHOD)
1725 server_context.set_npn_advertise_callback(advertise)
1726
1727 client_context = Context(TLSv1_METHOD)
1728 client_context.set_npn_select_callback(select)
1729
1730 # Necessary to actually accept the connection
1731 server_context.use_privatekey(
1732 load_privatekey(FILETYPE_PEM, server_key_pem))
1733 server_context.use_certificate(
1734 load_certificate(FILETYPE_PEM, server_cert_pem))
1735
1736 # Do a little connection to trigger the logic
1737 server = Connection(server_context, None)
1738 server.set_accept_state()
1739
1740 client = Connection(client_context, None)
1741 client.set_connect_state()
1742
1743 interact_in_memory(server, client)
1744
1745 assert advertise_args == [(server,)]
1746 assert select_args == [(client, [b'http/1.1', b'spdy/2'])]
1747
1748 assert server.get_next_proto_negotiated() == b'spdy/2'
1749 assert client.get_next_proto_negotiated() == b'spdy/2'
1750
1751 def test_npn_client_fail(self):
1752 """
1753 Tests that when clients and servers cannot agree on what protocol
1754 to use next that the TLS connection does not get established.
1755 """
1756 advertise_args = []
1757 select_args = []
1758
1759 def advertise(conn):
1760 advertise_args.append((conn,))
1761 return [b'http/1.1', b'spdy/2']
1762
1763 def select(conn, options):
1764 select_args.append((conn, options))
1765 return b''
1766
1767 server_context = Context(TLSv1_METHOD)
1768 server_context.set_npn_advertise_callback(advertise)
1769
1770 client_context = Context(TLSv1_METHOD)
1771 client_context.set_npn_select_callback(select)
1772
1773 # Necessary to actually accept the connection
1774 server_context.use_privatekey(
1775 load_privatekey(FILETYPE_PEM, server_key_pem))
1776 server_context.use_certificate(
1777 load_certificate(FILETYPE_PEM, server_cert_pem))
1778
1779 # Do a little connection to trigger the logic
1780 server = Connection(server_context, None)
1781 server.set_accept_state()
1782
1783 client = Connection(client_context, None)
1784 client.set_connect_state()
1785
1786 # If the client doesn't return anything, the connection will fail.
1787 with pytest.raises(Error):
1788 interact_in_memory(server, client)
1789
1790 assert advertise_args == [(server,)]
1791 assert select_args == [(client, [b'http/1.1', b'spdy/2'])]
1792
1793 def test_npn_select_error(self):
1794 """
1795 Test that we can handle exceptions in the select callback. If
1796 select fails it should be fatal to the connection.
1797 """
1798 advertise_args = []
1799
1800 def advertise(conn):
1801 advertise_args.append((conn,))
1802 return [b'http/1.1', b'spdy/2']
1803
1804 def select(conn, options):
1805 raise TypeError
1806
1807 server_context = Context(TLSv1_METHOD)
1808 server_context.set_npn_advertise_callback(advertise)
1809
1810 client_context = Context(TLSv1_METHOD)
1811 client_context.set_npn_select_callback(select)
1812
1813 # Necessary to actually accept the connection
1814 server_context.use_privatekey(
1815 load_privatekey(FILETYPE_PEM, server_key_pem))
1816 server_context.use_certificate(
1817 load_certificate(FILETYPE_PEM, server_cert_pem))
1818
1819 # Do a little connection to trigger the logic
1820 server = Connection(server_context, None)
1821 server.set_accept_state()
1822
1823 client = Connection(client_context, None)
1824 client.set_connect_state()
1825
1826 # If the callback throws an exception it should be raised here.
1827 with pytest.raises(TypeError):
1828 interact_in_memory(server, client)
1829 assert advertise_args == [(server,), ]
1830
1831 def test_npn_advertise_error(self):
1832 """
1833 Test that we can handle exceptions in the advertise callback. If
1834 advertise fails no NPN is advertised to the client.
1835 """
1836 select_args = []
1837
1838 def advertise(conn):
1839 raise TypeError
1840
1841 def select(conn, options): # pragma: nocover
Cory Benfieldba1820d2015-04-13 17:39:12 -04001842 """
Alex Chan9e08b3e2016-11-10 12:18:54 +00001843 Assert later that no args are actually appended.
Cory Benfieldba1820d2015-04-13 17:39:12 -04001844 """
Alex Chan9e08b3e2016-11-10 12:18:54 +00001845 select_args.append((conn, options))
1846 return b''
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001847
Alex Chan9e08b3e2016-11-10 12:18:54 +00001848 server_context = Context(TLSv1_METHOD)
1849 server_context.set_npn_advertise_callback(advertise)
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001850
Alex Chan9e08b3e2016-11-10 12:18:54 +00001851 client_context = Context(TLSv1_METHOD)
1852 client_context.set_npn_select_callback(select)
Cory Benfield84a121e2014-03-31 20:30:25 +01001853
Alex Chan9e08b3e2016-11-10 12:18:54 +00001854 # Necessary to actually accept the connection
1855 server_context.use_privatekey(
1856 load_privatekey(FILETYPE_PEM, server_key_pem))
1857 server_context.use_certificate(
1858 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield84a121e2014-03-31 20:30:25 +01001859
Alex Chan9e08b3e2016-11-10 12:18:54 +00001860 # Do a little connection to trigger the logic
1861 server = Connection(server_context, None)
1862 server.set_accept_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001863
Alex Chan9e08b3e2016-11-10 12:18:54 +00001864 client = Connection(client_context, None)
1865 client.set_connect_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001866
Alex Chan9e08b3e2016-11-10 12:18:54 +00001867 # If the client doesn't return anything, the connection will fail.
1868 with pytest.raises(TypeError):
1869 interact_in_memory(server, client)
1870 assert select_args == []
Cory Benfield0ea76e72015-03-22 09:05:28 +00001871
1872
Alex Chanec1e32d2016-11-10 14:11:45 +00001873class TestApplicationLayerProtoNegotiation(object):
Cory Benfield12eae892014-06-07 15:42:56 +01001874 """
1875 Tests for ALPN in PyOpenSSL.
1876 """
Cory Benfielde46fa842015-04-13 16:50:49 -04001877 # Skip tests on versions that don't support ALPN.
1878 if _lib.Cryptography_HAS_ALPN:
Cory Benfield12eae892014-06-07 15:42:56 +01001879
Cory Benfielde46fa842015-04-13 16:50:49 -04001880 def test_alpn_success(self):
1881 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04001882 Clients and servers that agree on the negotiated ALPN protocol can
1883 correct establish a connection, and the agreed protocol is reported
1884 by the connections.
Cory Benfielde46fa842015-04-13 16:50:49 -04001885 """
1886 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001887
Cory Benfielde46fa842015-04-13 16:50:49 -04001888 def select(conn, options):
1889 select_args.append((conn, options))
1890 return b'spdy/2'
Cory Benfield12eae892014-06-07 15:42:56 +01001891
Cory Benfielde46fa842015-04-13 16:50:49 -04001892 client_context = Context(TLSv1_METHOD)
1893 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfield12eae892014-06-07 15:42:56 +01001894
Cory Benfielde46fa842015-04-13 16:50:49 -04001895 server_context = Context(TLSv1_METHOD)
1896 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01001897
Cory Benfielde46fa842015-04-13 16:50:49 -04001898 # Necessary to actually accept the connection
1899 server_context.use_privatekey(
1900 load_privatekey(FILETYPE_PEM, server_key_pem))
1901 server_context.use_certificate(
1902 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield12eae892014-06-07 15:42:56 +01001903
Cory Benfielde46fa842015-04-13 16:50:49 -04001904 # Do a little connection to trigger the logic
1905 server = Connection(server_context, None)
1906 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001907
Cory Benfielde46fa842015-04-13 16:50:49 -04001908 client = Connection(client_context, None)
1909 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001910
Alex Chanec1e32d2016-11-10 14:11:45 +00001911 interact_in_memory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001912
Alex Chanec1e32d2016-11-10 14:11:45 +00001913 assert select_args == [(server, [b'http/1.1', b'spdy/2'])]
Cory Benfielde46fa842015-04-13 16:50:49 -04001914
Alex Chanec1e32d2016-11-10 14:11:45 +00001915 assert server.get_alpn_proto_negotiated() == b'spdy/2'
1916 assert client.get_alpn_proto_negotiated() == b'spdy/2'
Cory Benfield12eae892014-06-07 15:42:56 +01001917
Cory Benfielde46fa842015-04-13 16:50:49 -04001918 def test_alpn_set_on_connection(self):
1919 """
1920 The same as test_alpn_success, but setting the ALPN protocols on
1921 the connection rather than the context.
1922 """
1923 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001924
Cory Benfielde46fa842015-04-13 16:50:49 -04001925 def select(conn, options):
1926 select_args.append((conn, options))
1927 return b'spdy/2'
Cory Benfield12eae892014-06-07 15:42:56 +01001928
Cory Benfielde46fa842015-04-13 16:50:49 -04001929 # Setup the client context but don't set any ALPN protocols.
1930 client_context = Context(TLSv1_METHOD)
Cory Benfield12eae892014-06-07 15:42:56 +01001931
Cory Benfielde46fa842015-04-13 16:50:49 -04001932 server_context = Context(TLSv1_METHOD)
1933 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01001934
Cory Benfielde46fa842015-04-13 16:50:49 -04001935 # Necessary to actually accept the connection
1936 server_context.use_privatekey(
1937 load_privatekey(FILETYPE_PEM, server_key_pem))
1938 server_context.use_certificate(
1939 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield12eae892014-06-07 15:42:56 +01001940
Cory Benfielde46fa842015-04-13 16:50:49 -04001941 # Do a little connection to trigger the logic
1942 server = Connection(server_context, None)
1943 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001944
Cory Benfielde46fa842015-04-13 16:50:49 -04001945 # Set the ALPN protocols on the client connection.
1946 client = Connection(client_context, None)
1947 client.set_alpn_protos([b'http/1.1', b'spdy/2'])
1948 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001949
Alex Chanec1e32d2016-11-10 14:11:45 +00001950 interact_in_memory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001951
Alex Chanec1e32d2016-11-10 14:11:45 +00001952 assert select_args == [(server, [b'http/1.1', b'spdy/2'])]
Cory Benfield12eae892014-06-07 15:42:56 +01001953
Alex Chanec1e32d2016-11-10 14:11:45 +00001954 assert server.get_alpn_proto_negotiated() == b'spdy/2'
1955 assert client.get_alpn_proto_negotiated() == b'spdy/2'
Cory Benfield12eae892014-06-07 15:42:56 +01001956
Cory Benfielde46fa842015-04-13 16:50:49 -04001957 def test_alpn_server_fail(self):
1958 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04001959 When clients and servers cannot agree on what protocol to use next
1960 the TLS connection does not get established.
Cory Benfielde46fa842015-04-13 16:50:49 -04001961 """
1962 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001963
Cory Benfielde46fa842015-04-13 16:50:49 -04001964 def select(conn, options):
1965 select_args.append((conn, options))
1966 return b''
Cory Benfield12eae892014-06-07 15:42:56 +01001967
Cory Benfielde46fa842015-04-13 16:50:49 -04001968 client_context = Context(TLSv1_METHOD)
1969 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfield12eae892014-06-07 15:42:56 +01001970
Cory Benfielde46fa842015-04-13 16:50:49 -04001971 server_context = Context(TLSv1_METHOD)
1972 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01001973
Cory Benfielde46fa842015-04-13 16:50:49 -04001974 # Necessary to actually accept the connection
1975 server_context.use_privatekey(
1976 load_privatekey(FILETYPE_PEM, server_key_pem))
1977 server_context.use_certificate(
1978 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield12eae892014-06-07 15:42:56 +01001979
Cory Benfielde46fa842015-04-13 16:50:49 -04001980 # Do a little connection to trigger the logic
1981 server = Connection(server_context, None)
1982 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001983
Cory Benfielde46fa842015-04-13 16:50:49 -04001984 client = Connection(client_context, None)
1985 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001986
Cory Benfielde46fa842015-04-13 16:50:49 -04001987 # If the client doesn't return anything, the connection will fail.
Alex Chanec1e32d2016-11-10 14:11:45 +00001988 with pytest.raises(Error):
1989 interact_in_memory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001990
Alex Chanec1e32d2016-11-10 14:11:45 +00001991 assert select_args == [(server, [b'http/1.1', b'spdy/2'])]
Cory Benfield12eae892014-06-07 15:42:56 +01001992
Cory Benfielde46fa842015-04-13 16:50:49 -04001993 def test_alpn_no_server(self):
1994 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04001995 When clients and servers cannot agree on what protocol to use next
1996 because the server doesn't offer ALPN, no protocol is negotiated.
Cory Benfielde46fa842015-04-13 16:50:49 -04001997 """
1998 client_context = Context(TLSv1_METHOD)
1999 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfielde3d57152015-04-11 17:57:35 -04002000
Cory Benfielde46fa842015-04-13 16:50:49 -04002001 server_context = Context(TLSv1_METHOD)
Cory Benfielde3d57152015-04-11 17:57:35 -04002002
Cory Benfielde46fa842015-04-13 16:50:49 -04002003 # Necessary to actually accept the connection
2004 server_context.use_privatekey(
2005 load_privatekey(FILETYPE_PEM, server_key_pem))
2006 server_context.use_certificate(
2007 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfielde3d57152015-04-11 17:57:35 -04002008
Cory Benfielde46fa842015-04-13 16:50:49 -04002009 # Do a little connection to trigger the logic
2010 server = Connection(server_context, None)
2011 server.set_accept_state()
Cory Benfielde3d57152015-04-11 17:57:35 -04002012
Cory Benfielde46fa842015-04-13 16:50:49 -04002013 client = Connection(client_context, None)
2014 client.set_connect_state()
Cory Benfielde3d57152015-04-11 17:57:35 -04002015
Cory Benfielde46fa842015-04-13 16:50:49 -04002016 # Do the dance.
Alex Chanec1e32d2016-11-10 14:11:45 +00002017 interact_in_memory(server, client)
Cory Benfielde3d57152015-04-11 17:57:35 -04002018
Alex Chanec1e32d2016-11-10 14:11:45 +00002019 assert client.get_alpn_proto_negotiated() == b''
Cory Benfielde3d57152015-04-11 17:57:35 -04002020
Cory Benfielde46fa842015-04-13 16:50:49 -04002021 def test_alpn_callback_exception(self):
2022 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04002023 We can handle exceptions in the ALPN select callback.
Cory Benfielde46fa842015-04-13 16:50:49 -04002024 """
2025 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002026
Cory Benfielde46fa842015-04-13 16:50:49 -04002027 def select(conn, options):
2028 select_args.append((conn, options))
Cory Benfieldef401452015-04-13 18:17:36 -04002029 raise TypeError()
Cory Benfieldf1177e72015-04-12 09:11:49 -04002030
Cory Benfielde46fa842015-04-13 16:50:49 -04002031 client_context = Context(TLSv1_METHOD)
2032 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfieldf1177e72015-04-12 09:11:49 -04002033
Cory Benfielde46fa842015-04-13 16:50:49 -04002034 server_context = Context(TLSv1_METHOD)
2035 server_context.set_alpn_select_callback(select)
Cory Benfieldf1177e72015-04-12 09:11:49 -04002036
Cory Benfielde46fa842015-04-13 16:50:49 -04002037 # Necessary to actually accept the connection
2038 server_context.use_privatekey(
2039 load_privatekey(FILETYPE_PEM, server_key_pem))
2040 server_context.use_certificate(
2041 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfieldf1177e72015-04-12 09:11:49 -04002042
Cory Benfielde46fa842015-04-13 16:50:49 -04002043 # Do a little connection to trigger the logic
2044 server = Connection(server_context, None)
2045 server.set_accept_state()
Cory Benfieldf1177e72015-04-12 09:11:49 -04002046
Cory Benfielde46fa842015-04-13 16:50:49 -04002047 client = Connection(client_context, None)
2048 client.set_connect_state()
Cory Benfieldf1177e72015-04-12 09:11:49 -04002049
Alex Chanec1e32d2016-11-10 14:11:45 +00002050 with pytest.raises(TypeError):
2051 interact_in_memory(server, client)
2052 assert select_args == [(server, [b'http/1.1', b'spdy/2'])]
Cory Benfieldf1177e72015-04-12 09:11:49 -04002053
Cory Benfield0f7b04c2015-04-13 17:51:12 -04002054 else:
2055 # No ALPN.
2056 def test_alpn_not_implemented(self):
Cory Benfieldef401452015-04-13 18:17:36 -04002057 """
2058 If ALPN is not in OpenSSL, we should raise NotImplementedError.
2059 """
Cory Benfield0f7b04c2015-04-13 17:51:12 -04002060 # Test the context methods first.
2061 context = Context(TLSv1_METHOD)
Alex Chanec1e32d2016-11-10 14:11:45 +00002062 with pytest.raises(NotImplementedError):
2063 context.set_alpn_protos(None)
2064 with pytest.raises(NotImplementedError):
2065 context.set_alpn_select_callback(None)
Cory Benfield0f7b04c2015-04-13 17:51:12 -04002066
2067 # Now test a connection.
2068 conn = Connection(context)
Alex Chanec1e32d2016-11-10 14:11:45 +00002069 with pytest.raises(NotImplementedError):
2070 conn.set_alpn_protos(None)
Cory Benfield0f7b04c2015-04-13 17:51:12 -04002071
Cory Benfieldf1177e72015-04-12 09:11:49 -04002072
Alex Chanec1e32d2016-11-10 14:11:45 +00002073class TestSession(object):
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05002074 """
2075 Unit tests for :py:obj:`OpenSSL.SSL.Session`.
2076 """
2077 def test_construction(self):
2078 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002079 :py:class:`Session` can be constructed with no arguments, creating
2080 a new instance of that type.
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05002081 """
2082 new_session = Session()
Alex Chanec1e32d2016-11-10 14:11:45 +00002083 assert isinstance(new_session, Session)
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05002084
2085
Alex Chan1c0cb662017-01-30 07:13:30 +00002086class TestConnection(object):
Rick Deane15b1472009-07-09 15:53:42 -05002087 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002088 Unit tests for `OpenSSL.SSL.Connection`.
Rick Deane15b1472009-07-09 15:53:42 -05002089 """
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04002090 # XXX get_peer_certificate -> None
2091 # XXX sock_shutdown
2092 # XXX master_key -> TypeError
2093 # XXX server_random -> TypeError
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04002094 # XXX connect -> TypeError
2095 # XXX connect_ex -> TypeError
2096 # XXX set_connect_state -> TypeError
2097 # XXX set_accept_state -> TypeError
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04002098 # XXX do_handshake -> TypeError
2099 # XXX bio_read -> TypeError
2100 # XXX recv -> TypeError
2101 # XXX send -> TypeError
2102 # XXX bio_write -> TypeError
2103
Rick Deane15b1472009-07-09 15:53:42 -05002104 def test_type(self):
2105 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002106 `Connection` and `ConnectionType` refer to the same type object and
2107 can be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -05002108 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002109 assert Connection is ConnectionType
Rick Deane15b1472009-07-09 15:53:42 -05002110 ctx = Context(TLSv1_METHOD)
Alex Chan1c0cb662017-01-30 07:13:30 +00002111 assert is_consistent_type(Connection, 'Connection', ctx, None)
Rick Deane15b1472009-07-09 15:53:42 -05002112
Alex Chanfb078d82017-04-20 11:16:15 +01002113 @pytest.mark.parametrize('bad_context', [object(), 'context', None, 1])
2114 def test_wrong_args(self, bad_context):
2115 """
2116 `Connection.__init__` raises `TypeError` if called with a non-`Context`
2117 instance argument.
2118 """
2119 with pytest.raises(TypeError):
2120 Connection(bad_context)
2121
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002122 def test_get_context(self):
2123 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002124 `Connection.get_context` returns the `Context` instance used to
2125 construct the `Connection` instance.
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002126 """
2127 context = Context(TLSv1_METHOD)
2128 connection = Connection(context, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002129 assert connection.get_context() is context
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002130
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002131 def test_set_context_wrong_args(self):
2132 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002133 `Connection.set_context` raises `TypeError` if called with a
Alex Chanfb078d82017-04-20 11:16:15 +01002134 non-`Context` instance argument.
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002135 """
2136 ctx = Context(TLSv1_METHOD)
2137 connection = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002138 with pytest.raises(TypeError):
2139 connection.set_context(object())
2140 with pytest.raises(TypeError):
2141 connection.set_context("hello")
2142 with pytest.raises(TypeError):
2143 connection.set_context(1)
2144 assert ctx is connection.get_context()
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002145
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002146 def test_set_context(self):
2147 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002148 `Connection.set_context` specifies a new `Context` instance to be
2149 used for the connection.
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002150 """
2151 original = Context(SSLv23_METHOD)
2152 replacement = Context(TLSv1_METHOD)
2153 connection = Connection(original, None)
2154 connection.set_context(replacement)
Alex Chan1c0cb662017-01-30 07:13:30 +00002155 assert replacement is connection.get_context()
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002156 # Lose our references to the contexts, just in case the Connection
2157 # isn't properly managing its own contributions to their reference
2158 # counts.
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002159 del original, replacement
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002160 collect()
2161
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002162 def test_set_tlsext_host_name_wrong_args(self):
2163 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002164 If `Connection.set_tlsext_host_name` is called with a non-byte string
2165 argument or a byte string with an embedded NUL, `TypeError` is raised.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002166 """
2167 conn = Connection(Context(TLSv1_METHOD), None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002168 with pytest.raises(TypeError):
2169 conn.set_tlsext_host_name(object())
2170 with pytest.raises(TypeError):
2171 conn.set_tlsext_host_name(b"with\0null")
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002172
Abraham Martinc5484ba2015-03-25 15:33:05 +00002173 if PY3:
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002174 # On Python 3.x, don't accidentally implicitly convert from text.
Alex Chan1c0cb662017-01-30 07:13:30 +00002175 with pytest.raises(TypeError):
2176 conn.set_tlsext_host_name(b"example.com".decode("ascii"))
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04002177
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002178 def test_pending(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002179 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002180 `Connection.pending` returns the number of bytes available for
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002181 immediate read.
2182 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002183 connection = Connection(Context(TLSv1_METHOD), None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002184 assert connection.pending() == 0
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002185
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002186 def test_peek(self):
2187 """
Hynek Schlawack3bcf3152017-02-18 08:25:34 +01002188 `Connection.recv` peeks into the connection if `socket.MSG_PEEK` is
2189 passed.
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002190 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002191 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002192 server.send(b'xy')
Alex Chan1c0cb662017-01-30 07:13:30 +00002193 assert client.recv(2, MSG_PEEK) == b'xy'
2194 assert client.recv(2, MSG_PEEK) == b'xy'
2195 assert client.recv(2) == b'xy'
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002196
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002197 def test_connect_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002198 """
Hynek Schlawack3bcf3152017-02-18 08:25:34 +01002199 `Connection.connect` raises `TypeError` if called with a non-address
2200 argument.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002201 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002202 connection = Connection(Context(TLSv1_METHOD), socket())
Alex Chan1c0cb662017-01-30 07:13:30 +00002203 with pytest.raises(TypeError):
2204 connection.connect(None)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002205
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002206 def test_connect_refused(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002207 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002208 `Connection.connect` raises `socket.error` if the underlying socket
2209 connect method raises it.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002210 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002211 client = socket()
2212 context = Context(TLSv1_METHOD)
2213 clientSSL = Connection(context, client)
Alex Gaynor122717b2015-09-05 14:14:18 -04002214 # pytest.raises here doesn't work because of a bug in py.test on Python
2215 # 2.6: https://github.com/pytest-dev/pytest/issues/988
Alex Gaynore69c2782015-09-05 14:07:48 -04002216 try:
Alex Gaynor1aabb2e2015-09-05 13:35:18 -04002217 clientSSL.connect(("127.0.0.1", 1))
Alex Gaynore69c2782015-09-05 14:07:48 -04002218 except error as e:
Alex Gaynor20a4c082015-09-05 14:24:15 -04002219 exc = e
2220 assert exc.args[0] == ECONNREFUSED
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002221
2222 def test_connect(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002223 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002224 `Connection.connect` establishes a connection to the specified address.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002225 """
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002226 port = socket()
2227 port.bind(('', 0))
2228 port.listen(3)
2229
2230 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002231 clientSSL.connect(('127.0.0.1', port.getsockname()[1]))
2232 # XXX An assertion? Or something?
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002233
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002234 @pytest.mark.skipif(
2235 platform == "darwin",
2236 reason="connect_ex sometimes causes a kernel panic on OS X 10.6.4"
2237 )
2238 def test_connect_ex(self):
2239 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002240 If there is a connection error, `Connection.connect_ex` returns the
2241 errno instead of raising an exception.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002242 """
2243 port = socket()
2244 port.bind(('', 0))
2245 port.listen(3)
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002246
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002247 clientSSL = Connection(Context(TLSv1_METHOD), socket())
2248 clientSSL.setblocking(False)
2249 result = clientSSL.connect_ex(port.getsockname())
2250 expected = (EINPROGRESS, EWOULDBLOCK)
Alex Chan1c0cb662017-01-30 07:13:30 +00002251 assert result in expected
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002252
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002253 def test_accept(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002254 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002255 `Connection.accept` accepts a pending connection attempt and returns a
2256 tuple of a new `Connection` (the accepted client) and the address the
2257 connection originated from.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002258 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002259 ctx = Context(TLSv1_METHOD)
2260 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2261 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002262 port = socket()
2263 portSSL = Connection(ctx, port)
2264 portSSL.bind(('', 0))
2265 portSSL.listen(3)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002266
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002267 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002268
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002269 # Calling portSSL.getsockname() here to get the server IP address
2270 # sounds great, but frequently fails on Windows.
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002271 clientSSL.connect(('127.0.0.1', portSSL.getsockname()[1]))
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002272
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002273 serverSSL, address = portSSL.accept()
2274
Alex Chan1c0cb662017-01-30 07:13:30 +00002275 assert isinstance(serverSSL, Connection)
2276 assert serverSSL.get_context() is ctx
2277 assert address == clientSSL.getsockname()
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002278
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002279 def test_shutdown_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002280 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002281 `Connection.set_shutdown` raises `TypeError` if called with arguments
2282 other than integers.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002283 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002284 connection = Connection(Context(TLSv1_METHOD), None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002285 with pytest.raises(TypeError):
2286 connection.set_shutdown(None)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002287
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002288 def test_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002289 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002290 `Connection.shutdown` performs an SSL-level connection shutdown.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002291 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002292 server, client = loopback()
2293 assert not server.shutdown()
2294 assert server.get_shutdown() == SENT_SHUTDOWN
2295 with pytest.raises(ZeroReturnError):
2296 client.recv(1024)
2297 assert client.get_shutdown() == RECEIVED_SHUTDOWN
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04002298 client.shutdown()
Alex Chan1c0cb662017-01-30 07:13:30 +00002299 assert client.get_shutdown() == (SENT_SHUTDOWN | RECEIVED_SHUTDOWN)
2300 with pytest.raises(ZeroReturnError):
2301 server.recv(1024)
2302 assert server.get_shutdown() == (SENT_SHUTDOWN | RECEIVED_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002303
Paul Aurichc85e0862015-01-08 08:34:33 -08002304 def test_shutdown_closed(self):
2305 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002306 If the underlying socket is closed, `Connection.shutdown` propagates
2307 the write error from the low level write call.
Paul Aurichc85e0862015-01-08 08:34:33 -08002308 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002309 server, client = loopback()
Paul Aurichc85e0862015-01-08 08:34:33 -08002310 server.sock_shutdown(2)
Alex Chan1c0cb662017-01-30 07:13:30 +00002311 with pytest.raises(SysCallError) as exc:
2312 server.shutdown()
Alex Chanfb078d82017-04-20 11:16:15 +01002313 if platform == "win32":
2314 assert exc.value.args[0] == ESHUTDOWN
2315 else:
2316 assert exc.value.args[0] == EPIPE
Paul Aurichc85e0862015-01-08 08:34:33 -08002317
Glyph89389472015-04-14 17:29:26 -04002318 def test_shutdown_truncated(self):
Glyph6064ec32015-04-14 16:38:22 -04002319 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002320 If the underlying connection is truncated, `Connection.shutdown`
2321 raises an `Error`.
Glyph6064ec32015-04-14 16:38:22 -04002322 """
Glyph89389472015-04-14 17:29:26 -04002323 server_ctx = Context(TLSv1_METHOD)
2324 client_ctx = Context(TLSv1_METHOD)
2325 server_ctx.use_privatekey(
2326 load_privatekey(FILETYPE_PEM, server_key_pem))
2327 server_ctx.use_certificate(
2328 load_certificate(FILETYPE_PEM, server_cert_pem))
2329 server = Connection(server_ctx, None)
2330 client = Connection(client_ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002331 handshake_in_memory(client, server)
2332 assert not server.shutdown()
2333 with pytest.raises(WantReadError):
2334 server.shutdown()
Glyph89389472015-04-14 17:29:26 -04002335 server.bio_shutdown()
Alex Chan1c0cb662017-01-30 07:13:30 +00002336 with pytest.raises(Error):
2337 server.shutdown()
Glyph6064ec32015-04-14 16:38:22 -04002338
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002339 def test_set_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002340 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002341 `Connection.set_shutdown` sets the state of the SSL connection
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002342 shutdown process.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002343 """
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002344 connection = Connection(Context(TLSv1_METHOD), socket())
2345 connection.set_shutdown(RECEIVED_SHUTDOWN)
Alex Chan1c0cb662017-01-30 07:13:30 +00002346 assert connection.get_shutdown() == RECEIVED_SHUTDOWN
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002347
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002348 @skip_if_py3
2349 def test_set_shutdown_long(self):
2350 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002351 On Python 2 `Connection.set_shutdown` accepts an argument
2352 of type `long` as well as `int`.
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002353 """
2354 connection = Connection(Context(TLSv1_METHOD), socket())
2355 connection.set_shutdown(long(RECEIVED_SHUTDOWN))
Alex Chan1c0cb662017-01-30 07:13:30 +00002356 assert connection.get_shutdown() == RECEIVED_SHUTDOWN
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -05002357
kjavaf248592015-09-07 12:14:01 +01002358 def test_state_string(self):
2359 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002360 `Connection.state_string` verbosely describes the current state of
2361 the `Connection`.
kjavaf248592015-09-07 12:14:01 +01002362 """
Hynek Schlawackb0274ce2015-10-16 19:56:26 +02002363 server, client = socket_pair()
Alex Chan1c0cb662017-01-30 07:13:30 +00002364 server = loopback_server_factory(server)
2365 client = loopback_client_factory(client)
kjavaf248592015-09-07 12:14:01 +01002366
Alex Gaynor5af32d02016-09-24 01:52:21 -04002367 assert server.get_state_string() in [
2368 b"before/accept initialization", b"before SSL initialization"
2369 ]
2370 assert client.get_state_string() in [
2371 b"before/connect initialization", b"before SSL initialization"
2372 ]
kjavaf248592015-09-07 12:14:01 +01002373
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002374 def test_app_data(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002375 """
2376 Any object can be set as app data by passing it to
Alex Chan1c0cb662017-01-30 07:13:30 +00002377 `Connection.set_app_data` and later retrieved with
2378 `Connection.get_app_data`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002379 """
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002380 conn = Connection(Context(TLSv1_METHOD), None)
Todd Chapman4f73e4f2015-08-27 11:26:43 -04002381 assert None is conn.get_app_data()
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002382 app_data = object()
2383 conn.set_app_data(app_data)
Todd Chapman4f73e4f2015-08-27 11:26:43 -04002384 assert conn.get_app_data() is app_data
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002385
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002386 def test_makefile(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002387 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002388 `Connection.makefile` is not implemented and calling that
2389 method raises `NotImplementedError`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002390 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002391 conn = Connection(Context(TLSv1_METHOD), None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002392 with pytest.raises(NotImplementedError):
2393 conn.makefile()
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002394
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002395 def test_get_peer_cert_chain(self):
2396 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002397 `Connection.get_peer_cert_chain` returns a list of certificates
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002398 which the connected server returned for the certification verification.
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002399 """
2400 chain = _create_certificate_chain()
2401 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
2402
2403 serverContext = Context(TLSv1_METHOD)
2404 serverContext.use_privatekey(skey)
2405 serverContext.use_certificate(scert)
2406 serverContext.add_extra_chain_cert(icert)
2407 serverContext.add_extra_chain_cert(cacert)
2408 server = Connection(serverContext, None)
2409 server.set_accept_state()
2410
2411 # Create the client
2412 clientContext = Context(TLSv1_METHOD)
2413 clientContext.set_verify(VERIFY_NONE, verify_cb)
2414 client = Connection(clientContext, None)
2415 client.set_connect_state()
2416
Alex Chan1c0cb662017-01-30 07:13:30 +00002417 interact_in_memory(client, server)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002418
2419 chain = client.get_peer_cert_chain()
Alex Chan1c0cb662017-01-30 07:13:30 +00002420 assert len(chain) == 3
2421 assert "Server Certificate" == chain[0].get_subject().CN
2422 assert "Intermediate Certificate" == chain[1].get_subject().CN
2423 assert "Authority Certificate" == chain[2].get_subject().CN
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002424
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002425 def test_get_peer_cert_chain_none(self):
2426 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002427 `Connection.get_peer_cert_chain` returns `None` if the peer sends
2428 no certificate chain.
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002429 """
2430 ctx = Context(TLSv1_METHOD)
2431 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2432 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
2433 server = Connection(ctx, None)
2434 server.set_accept_state()
2435 client = Connection(Context(TLSv1_METHOD), None)
2436 client.set_connect_state()
Alex Chan1c0cb662017-01-30 07:13:30 +00002437 interact_in_memory(client, server)
2438 assert None is server.get_peer_cert_chain()
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002439
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002440 def test_get_session_unconnected(self):
2441 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002442 `Connection.get_session` returns `None` when used with an object
2443 which has not been connected.
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002444 """
2445 ctx = Context(TLSv1_METHOD)
2446 server = Connection(ctx, None)
2447 session = server.get_session()
Alex Chan1c0cb662017-01-30 07:13:30 +00002448 assert None is session
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002449
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002450 def test_server_get_session(self):
2451 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002452 On the server side of a connection, `Connection.get_session` returns a
2453 `Session` instance representing the SSL session for that connection.
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002454 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002455 server, client = loopback()
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002456 session = server.get_session()
Alex Chan1c0cb662017-01-30 07:13:30 +00002457 assert isinstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002458
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002459 def test_client_get_session(self):
2460 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002461 On the client side of a connection, `Connection.get_session`
2462 returns a `Session` instance representing the SSL session for
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002463 that connection.
2464 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002465 server, client = loopback()
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002466 session = client.get_session()
Alex Chan1c0cb662017-01-30 07:13:30 +00002467 assert isinstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002468
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002469 def test_set_session_wrong_args(self):
2470 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002471 `Connection.set_session` raises `TypeError` if called with an object
2472 that is not an instance of `Session`.
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002473 """
2474 ctx = Context(TLSv1_METHOD)
2475 connection = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002476 with pytest.raises(TypeError):
2477 connection.set_session(123)
2478 with pytest.raises(TypeError):
2479 connection.set_session("hello")
2480 with pytest.raises(TypeError):
2481 connection.set_session(object())
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002482
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002483 def test_client_set_session(self):
2484 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002485 `Connection.set_session`, when used prior to a connection being
2486 established, accepts a `Session` instance and causes an attempt to
2487 re-use the session it represents when the SSL handshake is performed.
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002488 """
2489 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2490 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
Alex Gaynor332848f2017-08-07 12:40:09 -04002491 ctx = Context(SSLv23_METHOD)
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002492 ctx.use_privatekey(key)
2493 ctx.use_certificate(cert)
2494 ctx.set_session_id("unity-test")
2495
2496 def makeServer(socket):
2497 server = Connection(ctx, socket)
2498 server.set_accept_state()
2499 return server
2500
Alex Chan1c0cb662017-01-30 07:13:30 +00002501 originalServer, originalClient = loopback(
2502 server_factory=makeServer)
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002503 originalSession = originalClient.get_session()
2504
2505 def makeClient(socket):
Alex Chan1c0cb662017-01-30 07:13:30 +00002506 client = loopback_client_factory(socket)
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002507 client.set_session(originalSession)
2508 return client
Alex Chan1c0cb662017-01-30 07:13:30 +00002509 resumedServer, resumedClient = loopback(
2510 server_factory=makeServer,
2511 client_factory=makeClient)
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002512
2513 # This is a proxy: in general, we have no access to any unique
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002514 # identifier for the session (new enough versions of OpenSSL expose
2515 # a hash which could be usable, but "new enough" is very, very new).
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002516 # Instead, exploit the fact that the master key is re-used if the
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002517 # session is re-used. As long as the master key for the two
2518 # connections is the same, the session was re-used!
Alex Chan1c0cb662017-01-30 07:13:30 +00002519 assert originalServer.master_key() == resumedServer.master_key()
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002520
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002521 def test_set_session_wrong_method(self):
2522 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002523 If `Connection.set_session` is passed a `Session` instance associated
2524 with a context using a different SSL method than the `Connection`
2525 is using, a `OpenSSL.SSL.Error` is raised.
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002526 """
Alex Gaynor5af32d02016-09-24 01:52:21 -04002527 # Make this work on both OpenSSL 1.0.0, which doesn't support TLSv1.2
2528 # and also on OpenSSL 1.1.0 which doesn't support SSLv3. (SSL_ST_INIT
2529 # is a way to check for 1.1.0)
Alex Gaynoraa32e712017-06-29 20:56:12 -07002530 if SSL_ST_INIT is None:
2531 v1 = TLSv1_2_METHOD
2532 v2 = TLSv1_METHOD
2533 elif hasattr(_lib, "SSLv3_method"):
Alex Gaynor5af32d02016-09-24 01:52:21 -04002534 v1 = TLSv1_METHOD
2535 v2 = SSLv3_METHOD
2536 else:
Alex Gaynoraa32e712017-06-29 20:56:12 -07002537 pytest.skip("Test requires either OpenSSL 1.1.0 or SSLv3")
Alex Gaynor5af32d02016-09-24 01:52:21 -04002538
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002539 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2540 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
Alex Gaynor5af32d02016-09-24 01:52:21 -04002541 ctx = Context(v1)
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002542 ctx.use_privatekey(key)
2543 ctx.use_certificate(cert)
2544 ctx.set_session_id("unity-test")
2545
2546 def makeServer(socket):
2547 server = Connection(ctx, socket)
2548 server.set_accept_state()
2549 return server
2550
Alex Gaynor5af32d02016-09-24 01:52:21 -04002551 def makeOriginalClient(socket):
2552 client = Connection(Context(v1), socket)
2553 client.set_connect_state()
2554 return client
2555
Alex Chan1c0cb662017-01-30 07:13:30 +00002556 originalServer, originalClient = loopback(
2557 server_factory=makeServer, client_factory=makeOriginalClient)
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002558 originalSession = originalClient.get_session()
2559
2560 def makeClient(socket):
2561 # Intentionally use a different, incompatible method here.
Alex Gaynor5af32d02016-09-24 01:52:21 -04002562 client = Connection(Context(v2), socket)
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002563 client.set_connect_state()
2564 client.set_session(originalSession)
2565 return client
2566
Alex Chan1c0cb662017-01-30 07:13:30 +00002567 with pytest.raises(Error):
2568 loopback(client_factory=makeClient, server_factory=makeServer)
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002569
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002570 def test_wantWriteError(self):
2571 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002572 `Connection` methods which generate output raise
2573 `OpenSSL.SSL.WantWriteError` if writing to the connection's BIO
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002574 fail indicating a should-write state.
2575 """
2576 client_socket, server_socket = socket_pair()
2577 # Fill up the client's send buffer so Connection won't be able to write
Jean-Paul Calderonebbff8b92014-03-22 14:20:30 -04002578 # anything. Only write a single byte at a time so we can be sure we
2579 # completely fill the buffer. Even though the socket API is allowed to
2580 # signal a short write via its return value it seems this doesn't
2581 # always happen on all platforms (FreeBSD and OS X particular) for the
2582 # very last bit of available buffer space.
2583 msg = b"x"
2584 for i in range(1024 * 1024 * 4):
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002585 try:
2586 client_socket.send(msg)
2587 except error as e:
2588 if e.errno == EWOULDBLOCK:
2589 break
2590 raise
2591 else:
Alex Chan1c0cb662017-01-30 07:13:30 +00002592 pytest.fail(
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002593 "Failed to fill socket buffer, cannot test BIO want write")
2594
2595 ctx = Context(TLSv1_METHOD)
2596 conn = Connection(ctx, client_socket)
2597 # Client's speak first, so make it an SSL client
2598 conn.set_connect_state()
Alex Chan1c0cb662017-01-30 07:13:30 +00002599 with pytest.raises(WantWriteError):
2600 conn.do_handshake()
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002601
2602 # XXX want_read
2603
Fedor Brunner416f4a12014-03-28 13:18:38 +01002604 def test_get_finished_before_connect(self):
Fedor Brunner5747b932014-03-05 14:22:34 +01002605 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002606 `Connection.get_finished` returns `None` before TLS handshake
2607 is completed.
Fedor Brunner5747b932014-03-05 14:22:34 +01002608 """
Fedor Brunner5747b932014-03-05 14:22:34 +01002609 ctx = Context(TLSv1_METHOD)
2610 connection = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002611 assert connection.get_finished() is None
Fedor Brunner416f4a12014-03-28 13:18:38 +01002612
2613 def test_get_peer_finished_before_connect(self):
2614 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002615 `Connection.get_peer_finished` returns `None` before TLS handshake
2616 is completed.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002617 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002618 ctx = Context(TLSv1_METHOD)
2619 connection = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002620 assert connection.get_peer_finished() is None
Fedor Brunner5747b932014-03-05 14:22:34 +01002621
Fedor Brunner416f4a12014-03-28 13:18:38 +01002622 def test_get_finished(self):
2623 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002624 `Connection.get_finished` method returns the TLS Finished message send
2625 from client, or server. Finished messages are send during
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002626 TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002627 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002628 server, client = loopback()
Fedor Brunner416f4a12014-03-28 13:18:38 +01002629
Alex Chan1c0cb662017-01-30 07:13:30 +00002630 assert server.get_finished() is not None
2631 assert len(server.get_finished()) > 0
Fedor Brunner416f4a12014-03-28 13:18:38 +01002632
2633 def test_get_peer_finished(self):
2634 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002635 `Connection.get_peer_finished` method returns the TLS Finished
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002636 message received from client, or server. Finished messages are send
2637 during TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002638 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002639 server, client = loopback()
Fedor Brunner416f4a12014-03-28 13:18:38 +01002640
Alex Chan1c0cb662017-01-30 07:13:30 +00002641 assert server.get_peer_finished() is not None
2642 assert len(server.get_peer_finished()) > 0
Fedor Brunner5747b932014-03-05 14:22:34 +01002643
Fedor Brunner416f4a12014-03-28 13:18:38 +01002644 def test_tls_finished_message_symmetry(self):
2645 """
Hynek Schlawackdddd1112015-09-05 21:12:30 +02002646 The TLS Finished message send by server must be the TLS Finished
2647 message received by client.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002648
Hynek Schlawackdddd1112015-09-05 21:12:30 +02002649 The TLS Finished message send by client must be the TLS Finished
2650 message received by server.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002651 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002652 server, client = loopback()
Fedor Brunner416f4a12014-03-28 13:18:38 +01002653
Alex Chan1c0cb662017-01-30 07:13:30 +00002654 assert server.get_finished() == client.get_peer_finished()
2655 assert client.get_finished() == server.get_peer_finished()
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002656
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002657 def test_get_cipher_name_before_connect(self):
2658 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002659 `Connection.get_cipher_name` returns `None` if no connection
2660 has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002661 """
2662 ctx = Context(TLSv1_METHOD)
2663 conn = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002664 assert conn.get_cipher_name() is None
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002665
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002666 def test_get_cipher_name(self):
2667 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002668 `Connection.get_cipher_name` returns a `unicode` string giving the
2669 name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002670 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002671 server, client = loopback()
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002672 server_cipher_name, client_cipher_name = \
2673 server.get_cipher_name(), client.get_cipher_name()
2674
Alex Chan1c0cb662017-01-30 07:13:30 +00002675 assert isinstance(server_cipher_name, text_type)
2676 assert isinstance(client_cipher_name, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002677
Alex Chan1c0cb662017-01-30 07:13:30 +00002678 assert server_cipher_name == client_cipher_name
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002679
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002680 def test_get_cipher_version_before_connect(self):
2681 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002682 `Connection.get_cipher_version` returns `None` if no connection
2683 has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002684 """
2685 ctx = Context(TLSv1_METHOD)
2686 conn = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002687 assert conn.get_cipher_version() is None
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002688
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002689 def test_get_cipher_version(self):
2690 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002691 `Connection.get_cipher_version` returns a `unicode` string giving
2692 the protocol name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002693 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002694 server, client = loopback()
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002695 server_cipher_version, client_cipher_version = \
2696 server.get_cipher_version(), client.get_cipher_version()
2697
Alex Chan1c0cb662017-01-30 07:13:30 +00002698 assert isinstance(server_cipher_version, text_type)
2699 assert isinstance(client_cipher_version, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002700
Alex Chan1c0cb662017-01-30 07:13:30 +00002701 assert server_cipher_version == client_cipher_version
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002702
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002703 def test_get_cipher_bits_before_connect(self):
2704 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002705 `Connection.get_cipher_bits` returns `None` if no connection has
2706 been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002707 """
2708 ctx = Context(TLSv1_METHOD)
2709 conn = Connection(ctx, None)
Alex Chan1c0cb662017-01-30 07:13:30 +00002710 assert conn.get_cipher_bits() is None
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002711
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002712 def test_get_cipher_bits(self):
2713 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002714 `Connection.get_cipher_bits` returns the number of secret bits
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002715 of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002716 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002717 server, client = loopback()
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002718 server_cipher_bits, client_cipher_bits = \
2719 server.get_cipher_bits(), client.get_cipher_bits()
2720
Alex Chan1c0cb662017-01-30 07:13:30 +00002721 assert isinstance(server_cipher_bits, int)
2722 assert isinstance(client_cipher_bits, int)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002723
Alex Chan1c0cb662017-01-30 07:13:30 +00002724 assert server_cipher_bits == client_cipher_bits
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002725
Jim Shaverabff1882015-05-27 09:15:55 -04002726 def test_get_protocol_version_name(self):
2727 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002728 `Connection.get_protocol_version_name()` returns a string giving the
2729 protocol version of the current connection.
Jim Shaverabff1882015-05-27 09:15:55 -04002730 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002731 server, client = loopback()
Jim Shaverabff1882015-05-27 09:15:55 -04002732 client_protocol_version_name = client.get_protocol_version_name()
2733 server_protocol_version_name = server.get_protocol_version_name()
2734
Alex Chan1c0cb662017-01-30 07:13:30 +00002735 assert isinstance(server_protocol_version_name, text_type)
2736 assert isinstance(client_protocol_version_name, text_type)
Jim Shaverabff1882015-05-27 09:15:55 -04002737
Alex Chan1c0cb662017-01-30 07:13:30 +00002738 assert server_protocol_version_name == client_protocol_version_name
Jim Shaverabff1882015-05-27 09:15:55 -04002739
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002740 def test_get_protocol_version(self):
2741 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002742 `Connection.get_protocol_version()` returns an integer
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002743 giving the protocol version of the current connection.
2744 """
Alex Chan1c0cb662017-01-30 07:13:30 +00002745 server, client = loopback()
Jim Shaver85a4dff2015-04-27 17:42:46 -04002746 client_protocol_version = client.get_protocol_version()
2747 server_protocol_version = server.get_protocol_version()
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002748
Alex Chan1c0cb662017-01-30 07:13:30 +00002749 assert isinstance(server_protocol_version, int)
2750 assert isinstance(client_protocol_version, int)
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002751
Alex Chan1c0cb662017-01-30 07:13:30 +00002752 assert server_protocol_version == client_protocol_version
2753
2754 def test_wantReadError(self):
2755 """
2756 `Connection.bio_read` raises `OpenSSL.SSL.WantReadError` if there are
2757 no bytes available to be read from the BIO.
2758 """
2759 ctx = Context(TLSv1_METHOD)
2760 conn = Connection(ctx, None)
2761 with pytest.raises(WantReadError):
2762 conn.bio_read(1024)
2763
Alex Chanfb078d82017-04-20 11:16:15 +01002764 @pytest.mark.parametrize('bufsize', [1.0, None, object(), 'bufsize'])
2765 def test_bio_read_wrong_args(self, bufsize):
2766 """
2767 `Connection.bio_read` raises `TypeError` if passed a non-integer
2768 argument.
2769 """
2770 ctx = Context(TLSv1_METHOD)
2771 conn = Connection(ctx, None)
2772 with pytest.raises(TypeError):
2773 conn.bio_read(bufsize)
2774
Alex Chan1c0cb662017-01-30 07:13:30 +00002775 def test_buffer_size(self):
2776 """
2777 `Connection.bio_read` accepts an integer giving the maximum number
2778 of bytes to read and return.
2779 """
2780 ctx = Context(TLSv1_METHOD)
2781 conn = Connection(ctx, None)
2782 conn.set_connect_state()
2783 try:
2784 conn.do_handshake()
2785 except WantReadError:
2786 pass
2787 data = conn.bio_read(2)
2788 assert 2 == len(data)
2789
2790 @skip_if_py3
2791 def test_buffer_size_long(self):
2792 """
2793 On Python 2 `Connection.bio_read` accepts values of type `long` as
2794 well as `int`.
2795 """
2796 ctx = Context(TLSv1_METHOD)
2797 conn = Connection(ctx, None)
2798 conn.set_connect_state()
2799 try:
2800 conn.do_handshake()
2801 except WantReadError:
2802 pass
2803 data = conn.bio_read(long(2))
2804 assert 2 == len(data)
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002805
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002806
Alex Chanb7480992017-01-30 14:04:47 +00002807class TestConnectionGetCipherList(object):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002808 """
Alex Chanb7480992017-01-30 14:04:47 +00002809 Tests for `Connection.get_cipher_list`.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002810 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002811 def test_result(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002812 """
Alex Chanb7480992017-01-30 14:04:47 +00002813 `Connection.get_cipher_list` returns a list of `bytes` giving the
2814 names of the ciphers which might be used.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002815 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002816 connection = Connection(Context(TLSv1_METHOD), None)
2817 ciphers = connection.get_cipher_list()
Alex Chanb7480992017-01-30 14:04:47 +00002818 assert isinstance(ciphers, list)
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002819 for cipher in ciphers:
Alex Chanb7480992017-01-30 14:04:47 +00002820 assert isinstance(cipher, str)
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002821
2822
Maximilian Hils868dc3c2017-02-10 14:56:55 +01002823class VeryLarge(bytes):
2824 """
2825 Mock object so that we don't have to allocate 2**31 bytes
2826 """
2827 def __len__(self):
2828 return 2**31
2829
2830
Alex Chanb7480992017-01-30 14:04:47 +00002831class TestConnectionSend(object):
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002832 """
Alex Chanb7480992017-01-30 14:04:47 +00002833 Tests for `Connection.send`.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002834 """
2835 def test_wrong_args(self):
2836 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002837 When called with arguments other than string argument for its first
Alex Chanb7480992017-01-30 14:04:47 +00002838 parameter, `Connection.send` raises `TypeError`.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002839 """
2840 connection = Connection(Context(TLSv1_METHOD), None)
Alex Chanb7480992017-01-30 14:04:47 +00002841 with pytest.raises(TypeError):
2842 connection.send(object())
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002843
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002844 def test_short_bytes(self):
2845 """
Alex Chanb7480992017-01-30 14:04:47 +00002846 When passed a short byte string, `Connection.send` transmits all of it
2847 and returns the number of bytes sent.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002848 """
Alex Chanb7480992017-01-30 14:04:47 +00002849 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002850 count = server.send(b'xy')
Alex Chanb7480992017-01-30 14:04:47 +00002851 assert count == 2
2852 assert client.recv(2) == b'xy'
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002853
Abraham Martinef063482015-03-25 14:06:24 +00002854 def test_text(self):
2855 """
Alex Chanb7480992017-01-30 14:04:47 +00002856 When passed a text, `Connection.send` transmits all of it and
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002857 returns the number of bytes sent. It also raises a DeprecationWarning.
Abraham Martinef063482015-03-25 14:06:24 +00002858 """
Alex Chanb7480992017-01-30 14:04:47 +00002859 server, client = loopback()
2860 with pytest.warns(DeprecationWarning) as w:
Abraham Martinef063482015-03-25 14:06:24 +00002861 simplefilter("always")
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002862 count = server.send(b"xy".decode("ascii"))
Alex Chanb7480992017-01-30 14:04:47 +00002863 assert (
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002864 "{0} for buf is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002865 WARNING_TYPE_EXPECTED
Alex Chanb7480992017-01-30 14:04:47 +00002866 ) == str(w[-1].message))
2867 assert count == 2
2868 assert client.recv(2) == b'xy'
Abraham Martinef063482015-03-25 14:06:24 +00002869
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002870 @skip_if_py26
2871 def test_short_memoryview(self):
2872 """
2873 When passed a memoryview onto a small number of bytes,
Alex Chanb7480992017-01-30 14:04:47 +00002874 `Connection.send` transmits all of them and returns the number
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002875 of bytes sent.
2876 """
Alex Chanb7480992017-01-30 14:04:47 +00002877 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002878 count = server.send(memoryview(b'xy'))
Alex Chanb7480992017-01-30 14:04:47 +00002879 assert count == 2
2880 assert client.recv(2) == b'xy'
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002881
Hynek Schlawack8e94f1b2015-09-05 21:31:00 +02002882 @skip_if_py3
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002883 def test_short_buffer(self):
2884 """
2885 When passed a buffer containing a small number of bytes,
Alex Chanb7480992017-01-30 14:04:47 +00002886 `Connection.send` transmits all of them and returns the number
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002887 of bytes sent.
2888 """
Alex Chanb7480992017-01-30 14:04:47 +00002889 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002890 count = server.send(buffer(b'xy'))
Alex Chanb7480992017-01-30 14:04:47 +00002891 assert count == 2
2892 assert client.recv(2) == b'xy'
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02002893
Maximilian Hils868dc3c2017-02-10 14:56:55 +01002894 @pytest.mark.skipif(
2895 sys.maxsize < 2**31,
2896 reason="sys.maxsize < 2**31 - test requires 64 bit"
2897 )
2898 def test_buf_too_large(self):
2899 """
2900 When passed a buffer containing >= 2**31 bytes,
2901 `Connection.send` bails out as SSL_write only
2902 accepts an int for the buffer length.
2903 """
2904 connection = Connection(Context(TLSv1_METHOD), None)
2905 with pytest.raises(ValueError) as exc_info:
2906 connection.send(VeryLarge())
2907 exc_info.match(r"Cannot send more than .+ bytes at once")
2908
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05002909
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002910def _make_memoryview(size):
2911 """
2912 Create a new ``memoryview`` wrapped around a ``bytearray`` of the given
2913 size.
2914 """
2915 return memoryview(bytearray(size))
2916
2917
Alex Chanb7480992017-01-30 14:04:47 +00002918class TestConnectionRecvInto(object):
Cory Benfield62d10332014-06-15 10:03:41 +01002919 """
Alex Chanb7480992017-01-30 14:04:47 +00002920 Tests for `Connection.recv_into`.
Cory Benfield62d10332014-06-15 10:03:41 +01002921 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002922 def _no_length_test(self, factory):
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04002923 """
Alex Chanb7480992017-01-30 14:04:47 +00002924 Assert that when the given buffer is passed to `Connection.recv_into`,
2925 whatever bytes are available to be received that fit into that buffer
2926 are written into that buffer.
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04002927 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002928 output_buffer = factory(5)
2929
Alex Chanb7480992017-01-30 14:04:47 +00002930 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002931 server.send(b'xy')
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04002932
Alex Chanb7480992017-01-30 14:04:47 +00002933 assert client.recv_into(output_buffer) == 2
2934 assert output_buffer == bytearray(b'xy\x00\x00\x00')
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04002935
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002936 def test_bytearray_no_length(self):
Cory Benfield62d10332014-06-15 10:03:41 +01002937 """
Alex Chanb7480992017-01-30 14:04:47 +00002938 `Connection.recv_into` can be passed a `bytearray` instance and data
2939 in the receive buffer is written to it.
Cory Benfield62d10332014-06-15 10:03:41 +01002940 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002941 self._no_length_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01002942
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002943 def _respects_length_test(self, factory):
Cory Benfield62d10332014-06-15 10:03:41 +01002944 """
Alex Chanb7480992017-01-30 14:04:47 +00002945 Assert that when the given buffer is passed to `Connection.recv_into`
2946 along with a value for `nbytes` that is less than the size of that
2947 buffer, only `nbytes` bytes are written into the buffer.
Cory Benfield62d10332014-06-15 10:03:41 +01002948 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002949 output_buffer = factory(10)
2950
Alex Chanb7480992017-01-30 14:04:47 +00002951 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002952 server.send(b'abcdefghij')
Cory Benfield62d10332014-06-15 10:03:41 +01002953
Alex Chanb7480992017-01-30 14:04:47 +00002954 assert client.recv_into(output_buffer, 5) == 5
2955 assert output_buffer == bytearray(b'abcde\x00\x00\x00\x00\x00')
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002956
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002957 def test_bytearray_respects_length(self):
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002958 """
Alex Chanb7480992017-01-30 14:04:47 +00002959 When called with a `bytearray` instance, `Connection.recv_into`
2960 respects the `nbytes` parameter and doesn't copy in more than that
2961 number of bytes.
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002962 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002963 self._respects_length_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01002964
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002965 def _doesnt_overfill_test(self, factory):
Cory Benfield62d10332014-06-15 10:03:41 +01002966 """
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002967 Assert that if there are more bytes available to be read from the
2968 receive buffer than would fit into the buffer passed to
Alex Chanb7480992017-01-30 14:04:47 +00002969 `Connection.recv_into`, only as many as fit are written into it.
Cory Benfield62d10332014-06-15 10:03:41 +01002970 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002971 output_buffer = factory(5)
2972
Alex Chanb7480992017-01-30 14:04:47 +00002973 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002974 server.send(b'abcdefghij')
Cory Benfield62d10332014-06-15 10:03:41 +01002975
Alex Chanb7480992017-01-30 14:04:47 +00002976 assert client.recv_into(output_buffer) == 5
2977 assert output_buffer == bytearray(b'abcde')
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002978 rest = client.recv(5)
Alex Chanb7480992017-01-30 14:04:47 +00002979 assert b'fghij' == rest
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002980
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002981 def test_bytearray_doesnt_overfill(self):
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002982 """
Alex Chanb7480992017-01-30 14:04:47 +00002983 When called with a `bytearray` instance, `Connection.recv_into`
2984 respects the size of the array and doesn't write more bytes into it
2985 than will fit.
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04002986 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002987 self._doesnt_overfill_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01002988
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002989 def test_bytearray_really_doesnt_overfill(self):
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04002990 """
Alex Chanb7480992017-01-30 14:04:47 +00002991 When called with a `bytearray` instance and an `nbytes` value that is
2992 too large, `Connection.recv_into` respects the size of the array and
2993 not the `nbytes` value and doesn't write more bytes into the buffer
2994 than will fit.
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04002995 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002996 self._doesnt_overfill_test(bytearray)
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04002997
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002998 def test_peek(self):
Alex Chanb7480992017-01-30 14:04:47 +00002999 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04003000 server.send(b'xy')
Maximilian Hils1d95dea2015-08-17 19:27:20 +02003001
3002 for _ in range(2):
3003 output_buffer = bytearray(5)
Alex Chanb7480992017-01-30 14:04:47 +00003004 assert client.recv_into(output_buffer, flags=MSG_PEEK) == 2
3005 assert output_buffer == bytearray(b'xy\x00\x00\x00')
Maximilian Hils1d95dea2015-08-17 19:27:20 +02003006
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003007 @skip_if_py26
3008 def test_memoryview_no_length(self):
3009 """
Alex Chanb7480992017-01-30 14:04:47 +00003010 `Connection.recv_into` can be passed a `memoryview` instance and data
3011 in the receive buffer is written to it.
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003012 """
3013 self._no_length_test(_make_memoryview)
Maximilian Hils1d95dea2015-08-17 19:27:20 +02003014
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003015 @skip_if_py26
3016 def test_memoryview_respects_length(self):
3017 """
Alex Chanb7480992017-01-30 14:04:47 +00003018 When called with a `memoryview` instance, `Connection.recv_into`
3019 respects the ``nbytes`` parameter and doesn't copy more than that
3020 number of bytes in.
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003021 """
3022 self._respects_length_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01003023
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003024 @skip_if_py26
3025 def test_memoryview_doesnt_overfill(self):
3026 """
Alex Chanb7480992017-01-30 14:04:47 +00003027 When called with a `memoryview` instance, `Connection.recv_into`
3028 respects the size of the array and doesn't write more bytes into it
3029 than will fit.
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003030 """
3031 self._doesnt_overfill_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01003032
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003033 @skip_if_py26
3034 def test_memoryview_really_doesnt_overfill(self):
3035 """
Alex Chanb7480992017-01-30 14:04:47 +00003036 When called with a `memoryview` instance and an `nbytes` value that is
3037 too large, `Connection.recv_into` respects the size of the array and
3038 not the `nbytes` value and doesn't write more bytes into the buffer
3039 than will fit.
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003040 """
3041 self._doesnt_overfill_test(_make_memoryview)
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003042
Cory Benfield62d10332014-06-15 10:03:41 +01003043
Alex Chanb7480992017-01-30 14:04:47 +00003044class TestConnectionSendall(object):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003045 """
Alex Chanb7480992017-01-30 14:04:47 +00003046 Tests for `Connection.sendall`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003047 """
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003048 def test_wrong_args(self):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003049 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003050 When called with arguments other than a string argument for its first
Alex Chanb7480992017-01-30 14:04:47 +00003051 parameter, `Connection.sendall` raises `TypeError`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003052 """
3053 connection = Connection(Context(TLSv1_METHOD), None)
Alex Chanb7480992017-01-30 14:04:47 +00003054 with pytest.raises(TypeError):
3055 connection.sendall(object())
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003056
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003057 def test_short(self):
3058 """
Alex Chanb7480992017-01-30 14:04:47 +00003059 `Connection.sendall` transmits all of the bytes in the string
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003060 passed to it.
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003061 """
Alex Chanb7480992017-01-30 14:04:47 +00003062 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04003063 server.sendall(b'x')
Alex Chanb7480992017-01-30 14:04:47 +00003064 assert client.recv(1) == b'x'
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003065
Abraham Martinef063482015-03-25 14:06:24 +00003066 def test_text(self):
3067 """
Alex Chanb7480992017-01-30 14:04:47 +00003068 `Connection.sendall` transmits all the content in the string passed
3069 to it, raising a DeprecationWarning in case of this being a text.
Abraham Martinef063482015-03-25 14:06:24 +00003070 """
Alex Chanb7480992017-01-30 14:04:47 +00003071 server, client = loopback()
3072 with pytest.warns(DeprecationWarning) as w:
Abraham Martinef063482015-03-25 14:06:24 +00003073 simplefilter("always")
Jean-Paul Calderone8dc37a12015-03-29 08:16:52 -04003074 server.sendall(b"x".decode("ascii"))
Alex Chanb7480992017-01-30 14:04:47 +00003075 assert (
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04003076 "{0} for buf is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04003077 WARNING_TYPE_EXPECTED
Alex Chanb7480992017-01-30 14:04:47 +00003078 ) == str(w[-1].message))
3079 assert client.recv(1) == b"x"
Abraham Martinef063482015-03-25 14:06:24 +00003080
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003081 @skip_if_py26
3082 def test_short_memoryview(self):
3083 """
3084 When passed a memoryview onto a small number of bytes,
Alex Chanb7480992017-01-30 14:04:47 +00003085 `Connection.sendall` transmits all of them.
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003086 """
Alex Chanb7480992017-01-30 14:04:47 +00003087 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04003088 server.sendall(memoryview(b'x'))
Alex Chanb7480992017-01-30 14:04:47 +00003089 assert client.recv(1) == b'x'
Abraham Martinef063482015-03-25 14:06:24 +00003090
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003091 @skip_if_py3
3092 def test_short_buffers(self):
3093 """
3094 When passed a buffer containing a small number of bytes,
Alex Chanb7480992017-01-30 14:04:47 +00003095 `Connection.sendall` transmits all of them.
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003096 """
Alex Chanb7480992017-01-30 14:04:47 +00003097 server, client = loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04003098 server.sendall(buffer(b'x'))
Alex Chanb7480992017-01-30 14:04:47 +00003099 assert client.recv(1) == b'x'
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02003100
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003101 def test_long(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003102 """
Alex Chanb7480992017-01-30 14:04:47 +00003103 `Connection.sendall` transmits all the bytes in the string passed to it
3104 even if this requires multiple calls of an underlying write function.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003105 """
Alex Chanb7480992017-01-30 14:04:47 +00003106 server, client = loopback()
Jean-Paul Calderone6241c702010-09-16 19:59:24 -04003107 # Should be enough, underlying SSL_write should only do 16k at a time.
Hynek Schlawack35618382015-09-05 21:54:25 +02003108 # On Windows, after 32k of bytes the write will block (forever
3109 # - because no one is yet reading).
Alex Gaynore7f51982016-09-11 11:48:14 -04003110 message = b'x' * (1024 * 32 - 1) + b'y'
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003111 server.sendall(message)
3112 accum = []
3113 received = 0
3114 while received < len(message):
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04003115 data = client.recv(1024)
3116 accum.append(data)
3117 received += len(data)
Alex Chanb7480992017-01-30 14:04:47 +00003118 assert message == b''.join(accum)
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003119
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003120 def test_closed(self):
3121 """
Alex Chanb7480992017-01-30 14:04:47 +00003122 If the underlying socket is closed, `Connection.sendall` propagates the
3123 write error from the low level write call.
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003124 """
Alex Chanb7480992017-01-30 14:04:47 +00003125 server, client = loopback()
Jean-Paul Calderone05d43e82010-09-24 18:01:36 -04003126 server.sock_shutdown(2)
Alex Chanb7480992017-01-30 14:04:47 +00003127 with pytest.raises(SysCallError) as err:
3128 server.sendall(b"hello, world")
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +02003129 if platform == "win32":
Alex Chanb7480992017-01-30 14:04:47 +00003130 assert err.value.args[0] == ESHUTDOWN
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +02003131 else:
Alex Chanb7480992017-01-30 14:04:47 +00003132 assert err.value.args[0] == EPIPE
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003133
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003134
Alex Chanb7480992017-01-30 14:04:47 +00003135class TestConnectionRenegotiate(object):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003136 """
3137 Tests for SSL renegotiation APIs.
3138 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003139 def test_total_renegotiations(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003140 """
Alex Chanb7480992017-01-30 14:04:47 +00003141 `Connection.total_renegotiations` returns `0` before any renegotiations
3142 have happened.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003143 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003144 connection = Connection(Context(TLSv1_METHOD), None)
Alex Chanb7480992017-01-30 14:04:47 +00003145 assert connection.total_renegotiations() == 0
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003146
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003147 def test_renegotiate(self):
3148 """
3149 Go through a complete renegotiation cycle.
3150 """
Alex Chanb7480992017-01-30 14:04:47 +00003151 server, client = loopback()
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003152
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003153 server.send(b"hello world")
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003154
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003155 assert b"hello world" == client.recv(len(b"hello world"))
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003156
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003157 assert 0 == server.total_renegotiations()
3158 assert False is server.renegotiate_pending()
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003159
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003160 assert True is server.renegotiate()
3161
3162 assert True is server.renegotiate_pending()
3163
3164 server.setblocking(False)
3165 client.setblocking(False)
3166
3167 client.do_handshake()
3168 server.do_handshake()
3169
3170 assert 1 == server.total_renegotiations()
3171 while False is server.renegotiate_pending():
3172 pass
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003173
3174
Alex Chanb7480992017-01-30 14:04:47 +00003175class TestError(object):
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003176 """
Alex Chanb7480992017-01-30 14:04:47 +00003177 Unit tests for `OpenSSL.SSL.Error`.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003178 """
3179 def test_type(self):
3180 """
Alex Chanb7480992017-01-30 14:04:47 +00003181 `Error` is an exception type.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003182 """
Alex Chanb7480992017-01-30 14:04:47 +00003183 assert issubclass(Error, Exception)
3184 assert Error.__name__ == 'Error'
Rick Deane15b1472009-07-09 15:53:42 -05003185
3186
Alex Chanb7480992017-01-30 14:04:47 +00003187class TestConstants(object):
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003188 """
Alex Chanb7480992017-01-30 14:04:47 +00003189 Tests for the values of constants exposed in `OpenSSL.SSL`.
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003190
3191 These are values defined by OpenSSL intended only to be used as flags to
3192 OpenSSL APIs. The only assertions it seems can be made about them is
3193 their values.
3194 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003195 @pytest.mark.skipif(
3196 OP_NO_QUERY_MTU is None,
3197 reason="OP_NO_QUERY_MTU unavailable - OpenSSL version may be too old"
3198 )
3199 def test_op_no_query_mtu(self):
3200 """
Alex Chanb7480992017-01-30 14:04:47 +00003201 The value of `OpenSSL.SSL.OP_NO_QUERY_MTU` is 0x1000, the value
3202 of `SSL_OP_NO_QUERY_MTU` defined by `openssl/ssl.h`.
Hynek Schlawack35618382015-09-05 21:54:25 +02003203 """
Alex Chanb7480992017-01-30 14:04:47 +00003204 assert OP_NO_QUERY_MTU == 0x1000
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003205
Hynek Schlawack35618382015-09-05 21:54:25 +02003206 @pytest.mark.skipif(
3207 OP_COOKIE_EXCHANGE is None,
3208 reason="OP_COOKIE_EXCHANGE unavailable - "
3209 "OpenSSL version may be too old"
3210 )
3211 def test_op_cookie_exchange(self):
3212 """
Alex Chanb7480992017-01-30 14:04:47 +00003213 The value of `OpenSSL.SSL.OP_COOKIE_EXCHANGE` is 0x2000, the
3214 value of `SSL_OP_COOKIE_EXCHANGE` defined by `openssl/ssl.h`.
Hynek Schlawack35618382015-09-05 21:54:25 +02003215 """
Alex Chanb7480992017-01-30 14:04:47 +00003216 assert OP_COOKIE_EXCHANGE == 0x2000
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003217
Hynek Schlawack35618382015-09-05 21:54:25 +02003218 @pytest.mark.skipif(
3219 OP_NO_TICKET is None,
3220 reason="OP_NO_TICKET unavailable - OpenSSL version may be too old"
3221 )
3222 def test_op_no_ticket(self):
3223 """
Alex Chanb7480992017-01-30 14:04:47 +00003224 The value of `OpenSSL.SSL.OP_NO_TICKET` is 0x4000, the value of
3225 `SSL_OP_NO_TICKET` defined by `openssl/ssl.h`.
Hynek Schlawack35618382015-09-05 21:54:25 +02003226 """
Alex Chanb7480992017-01-30 14:04:47 +00003227 assert OP_NO_TICKET == 0x4000
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003228
Hynek Schlawack35618382015-09-05 21:54:25 +02003229 @pytest.mark.skipif(
3230 OP_NO_COMPRESSION is None,
3231 reason="OP_NO_COMPRESSION unavailable - OpenSSL version may be too old"
3232 )
3233 def test_op_no_compression(self):
3234 """
Alex Chanb7480992017-01-30 14:04:47 +00003235 The value of `OpenSSL.SSL.OP_NO_COMPRESSION` is 0x20000, the
3236 value of `SSL_OP_NO_COMPRESSION` defined by `openssl/ssl.h`.
Hynek Schlawack35618382015-09-05 21:54:25 +02003237 """
Alex Chanb7480992017-01-30 14:04:47 +00003238 assert OP_NO_COMPRESSION == 0x20000
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04003239
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003240 def test_sess_cache_off(self):
3241 """
Alex Chanb7480992017-01-30 14:04:47 +00003242 The value of `OpenSSL.SSL.SESS_CACHE_OFF` 0x0, the value of
3243 `SSL_SESS_CACHE_OFF` defined by `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003244 """
Alex Chanb7480992017-01-30 14:04:47 +00003245 assert 0x0 == SESS_CACHE_OFF
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003246
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003247 def test_sess_cache_client(self):
3248 """
Alex Chanb7480992017-01-30 14:04:47 +00003249 The value of `OpenSSL.SSL.SESS_CACHE_CLIENT` 0x1, the value of
3250 `SSL_SESS_CACHE_CLIENT` defined by `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003251 """
Alex Chanb7480992017-01-30 14:04:47 +00003252 assert 0x1 == SESS_CACHE_CLIENT
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003253
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003254 def test_sess_cache_server(self):
3255 """
Alex Chanb7480992017-01-30 14:04:47 +00003256 The value of `OpenSSL.SSL.SESS_CACHE_SERVER` 0x2, the value of
3257 `SSL_SESS_CACHE_SERVER` defined by `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003258 """
Alex Chanb7480992017-01-30 14:04:47 +00003259 assert 0x2 == SESS_CACHE_SERVER
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003260
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003261 def test_sess_cache_both(self):
3262 """
Alex Chanb7480992017-01-30 14:04:47 +00003263 The value of `OpenSSL.SSL.SESS_CACHE_BOTH` 0x3, the value of
3264 `SSL_SESS_CACHE_BOTH` defined by `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003265 """
Alex Chanb7480992017-01-30 14:04:47 +00003266 assert 0x3 == SESS_CACHE_BOTH
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003267
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003268 def test_sess_cache_no_auto_clear(self):
3269 """
Alex Chanb7480992017-01-30 14:04:47 +00003270 The value of `OpenSSL.SSL.SESS_CACHE_NO_AUTO_CLEAR` 0x80, the
3271 value of `SSL_SESS_CACHE_NO_AUTO_CLEAR` defined by
3272 `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003273 """
Alex Chanb7480992017-01-30 14:04:47 +00003274 assert 0x80 == SESS_CACHE_NO_AUTO_CLEAR
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003275
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003276 def test_sess_cache_no_internal_lookup(self):
3277 """
Alex Chanb7480992017-01-30 14:04:47 +00003278 The value of `OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_LOOKUP` 0x100,
3279 the value of `SSL_SESS_CACHE_NO_INTERNAL_LOOKUP` defined by
3280 `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003281 """
Alex Chanb7480992017-01-30 14:04:47 +00003282 assert 0x100 == SESS_CACHE_NO_INTERNAL_LOOKUP
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003283
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003284 def test_sess_cache_no_internal_store(self):
3285 """
Alex Chanb7480992017-01-30 14:04:47 +00003286 The value of `OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_STORE` 0x200,
3287 the value of `SSL_SESS_CACHE_NO_INTERNAL_STORE` defined by
3288 `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003289 """
Alex Chanb7480992017-01-30 14:04:47 +00003290 assert 0x200 == SESS_CACHE_NO_INTERNAL_STORE
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003291
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003292 def test_sess_cache_no_internal(self):
3293 """
Alex Chanb7480992017-01-30 14:04:47 +00003294 The value of `OpenSSL.SSL.SESS_CACHE_NO_INTERNAL` 0x300, the
3295 value of `SSL_SESS_CACHE_NO_INTERNAL` defined by
3296 `openssl/ssl.h`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003297 """
Alex Chanb7480992017-01-30 14:04:47 +00003298 assert 0x300 == SESS_CACHE_NO_INTERNAL
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003299
3300
Alex Chanb7480992017-01-30 14:04:47 +00003301class TestMemoryBIO(object):
Rick Deanb71c0d22009-04-01 14:09:23 -05003302 """
Alex Chanb7480992017-01-30 14:04:47 +00003303 Tests for `OpenSSL.SSL.Connection` using a memory BIO.
Rick Deanb71c0d22009-04-01 14:09:23 -05003304 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003305 def _server(self, sock):
3306 """
Alex Chanb7480992017-01-30 14:04:47 +00003307 Create a new server-side SSL `Connection` object wrapped around `sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003308 """
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003309 # Create the server side Connection. This is mostly setup boilerplate
3310 # - use TLSv1, use a particular certificate, etc.
3311 server_ctx = Context(TLSv1_METHOD)
Alex Gaynor43307782015-09-04 09:05:45 -04003312 server_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE)
Hynek Schlawack35618382015-09-05 21:54:25 +02003313 server_ctx.set_verify(
3314 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT | VERIFY_CLIENT_ONCE,
3315 verify_cb
3316 )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003317 server_store = server_ctx.get_cert_store()
Hynek Schlawack35618382015-09-05 21:54:25 +02003318 server_ctx.use_privatekey(
3319 load_privatekey(FILETYPE_PEM, server_key_pem))
3320 server_ctx.use_certificate(
3321 load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003322 server_ctx.check_privatekey()
3323 server_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Hynek Schlawack35618382015-09-05 21:54:25 +02003324 # Here the Connection is actually created. If None is passed as the
3325 # 2nd parameter, it indicates a memory BIO should be created.
Rick Deanb1ccd562009-07-09 23:52:39 -05003326 server_conn = Connection(server_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003327 server_conn.set_accept_state()
3328 return server_conn
3329
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003330 def _client(self, sock):
3331 """
Alex Chanb7480992017-01-30 14:04:47 +00003332 Create a new client-side SSL `Connection` object wrapped around `sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003333 """
3334 # Now create the client side Connection. Similar boilerplate to the
3335 # above.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003336 client_ctx = Context(TLSv1_METHOD)
Alex Gaynor43307782015-09-04 09:05:45 -04003337 client_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE)
Hynek Schlawack35618382015-09-05 21:54:25 +02003338 client_ctx.set_verify(
3339 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT | VERIFY_CLIENT_ONCE,
3340 verify_cb
3341 )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003342 client_store = client_ctx.get_cert_store()
Hynek Schlawack35618382015-09-05 21:54:25 +02003343 client_ctx.use_privatekey(
3344 load_privatekey(FILETYPE_PEM, client_key_pem))
3345 client_ctx.use_certificate(
3346 load_certificate(FILETYPE_PEM, client_cert_pem))
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003347 client_ctx.check_privatekey()
3348 client_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05003349 client_conn = Connection(client_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003350 client_conn.set_connect_state()
3351 return client_conn
3352
Alex Chanb7480992017-01-30 14:04:47 +00003353 def test_memory_connect(self):
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003354 """
Alex Chanb7480992017-01-30 14:04:47 +00003355 Two `Connection`s which use memory BIOs can be manually connected by
3356 reading from the output of each and writing those bytes to the input of
3357 the other and in this way establish a connection and exchange
3358 application-level bytes with each other.
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003359 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003360 server_conn = self._server(None)
3361 client_conn = self._client(None)
Rick Deanb71c0d22009-04-01 14:09:23 -05003362
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003363 # There should be no key or nonces yet.
Alex Chanb7480992017-01-30 14:04:47 +00003364 assert server_conn.master_key() is None
3365 assert server_conn.client_random() is None
3366 assert server_conn.server_random() is None
Rick Deanb71c0d22009-04-01 14:09:23 -05003367
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003368 # First, the handshake needs to happen. We'll deliver bytes back and
3369 # forth between the client and server until neither of them feels like
3370 # speaking any more.
Alex Chanb7480992017-01-30 14:04:47 +00003371 assert interact_in_memory(client_conn, server_conn) is None
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003372
3373 # Now that the handshake is done, there should be a key and nonces.
Alex Chanb7480992017-01-30 14:04:47 +00003374 assert server_conn.master_key() is not None
3375 assert server_conn.client_random() is not None
3376 assert server_conn.server_random() is not None
3377 assert server_conn.client_random() == client_conn.client_random()
3378 assert server_conn.server_random() == client_conn.server_random()
3379 assert server_conn.client_random() != server_conn.server_random()
3380 assert client_conn.client_random() != client_conn.server_random()
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003381
Paul Kehrerbdb76392017-12-01 04:54:32 +08003382 # Export key material for other uses.
3383 cekm = client_conn.export_keying_material(b'LABEL', 32)
3384 sekm = server_conn.export_keying_material(b'LABEL', 32)
3385 assert cekm is not None
3386 assert sekm is not None
3387 assert cekm == sekm
3388 assert len(sekm) == 32
3389
3390 # Export key material for other uses with additional context.
3391 cekmc = client_conn.export_keying_material(b'LABEL', 32, b'CONTEXT')
3392 sekmc = server_conn.export_keying_material(b'LABEL', 32, b'CONTEXT')
3393 assert cekmc is not None
3394 assert sekmc is not None
3395 assert cekmc == sekmc
3396 assert cekmc != cekm
3397 assert sekmc != sekm
3398 # Export with alternate label
3399 cekmt = client_conn.export_keying_material(b'test', 32, b'CONTEXT')
3400 sekmt = server_conn.export_keying_material(b'test', 32, b'CONTEXT')
3401 assert cekmc != cekmt
3402 assert sekmc != sekmt
3403
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003404 # Here are the bytes we'll try to send.
Alex Gaynore7f51982016-09-11 11:48:14 -04003405 important_message = b'One if by land, two if by sea.'
Rick Deanb71c0d22009-04-01 14:09:23 -05003406
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003407 server_conn.write(important_message)
Alex Chanb7480992017-01-30 14:04:47 +00003408 assert (
3409 interact_in_memory(client_conn, server_conn) ==
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003410 (client_conn, important_message))
3411
3412 client_conn.write(important_message[::-1])
Alex Chanb7480992017-01-30 14:04:47 +00003413 assert (
3414 interact_in_memory(client_conn, server_conn) ==
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003415 (server_conn, important_message[::-1]))
Rick Deanb71c0d22009-04-01 14:09:23 -05003416
Alex Chanb7480992017-01-30 14:04:47 +00003417 def test_socket_connect(self):
Rick Deanb1ccd562009-07-09 23:52:39 -05003418 """
Alex Chanb7480992017-01-30 14:04:47 +00003419 Just like `test_memory_connect` but with an actual socket.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003420
Hynek Schlawack35618382015-09-05 21:54:25 +02003421 This is primarily to rule out the memory BIO code as the source of any
Alex Chanb7480992017-01-30 14:04:47 +00003422 problems encountered while passing data over a `Connection` (if
Hynek Schlawack35618382015-09-05 21:54:25 +02003423 this test fails, there must be a problem outside the memory BIO code,
3424 as no memory BIO is involved here). Even though this isn't a memory
3425 BIO test, it's convenient to have it here.
Rick Deanb1ccd562009-07-09 23:52:39 -05003426 """
Alex Chanb7480992017-01-30 14:04:47 +00003427 server_conn, client_conn = loopback()
Rick Deanb1ccd562009-07-09 23:52:39 -05003428
Alex Gaynore7f51982016-09-11 11:48:14 -04003429 important_message = b"Help me Obi Wan Kenobi, you're my only hope."
Rick Deanb1ccd562009-07-09 23:52:39 -05003430 client_conn.send(important_message)
3431 msg = server_conn.recv(1024)
Alex Chanb7480992017-01-30 14:04:47 +00003432 assert msg == important_message
Rick Deanb1ccd562009-07-09 23:52:39 -05003433
3434 # Again in the other direction, just for fun.
3435 important_message = important_message[::-1]
3436 server_conn.send(important_message)
3437 msg = client_conn.recv(1024)
Alex Chanb7480992017-01-30 14:04:47 +00003438 assert msg == important_message
Rick Deanb1ccd562009-07-09 23:52:39 -05003439
Alex Chanb7480992017-01-30 14:04:47 +00003440 def test_socket_overrides_memory(self):
Rick Deanb71c0d22009-04-01 14:09:23 -05003441 """
Alex Chanb7480992017-01-30 14:04:47 +00003442 Test that `OpenSSL.SSL.bio_read` and `OpenSSL.SSL.bio_write` don't
3443 work on `OpenSSL.SSL.Connection`() that use sockets.
Rick Deanb71c0d22009-04-01 14:09:23 -05003444 """
Alex Gaynor51d424c2016-09-10 14:50:11 -04003445 context = Context(TLSv1_METHOD)
Rick Deanb71c0d22009-04-01 14:09:23 -05003446 client = socket()
3447 clientSSL = Connection(context, client)
Alex Chanb7480992017-01-30 14:04:47 +00003448 with pytest.raises(TypeError):
3449 clientSSL.bio_read(100)
3450 with pytest.raises(TypeError):
3451 clientSSL.bio_write("foo")
3452 with pytest.raises(TypeError):
3453 clientSSL.bio_shutdown()
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003454
Alex Chanb7480992017-01-30 14:04:47 +00003455 def test_outgoing_overflow(self):
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003456 """
3457 If more bytes than can be written to the memory BIO are passed to
Alex Chanb7480992017-01-30 14:04:47 +00003458 `Connection.send` at once, the number of bytes which were written is
3459 returned and that many bytes from the beginning of the input can be
3460 read from the other end of the connection.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003461 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003462 server = self._server(None)
3463 client = self._client(None)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003464
Alex Chanb7480992017-01-30 14:04:47 +00003465 interact_in_memory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003466
3467 size = 2 ** 15
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003468 sent = client.send(b"x" * size)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003469 # Sanity check. We're trying to test what happens when the entire
3470 # input can't be sent. If the entire input was sent, this test is
3471 # meaningless.
Alex Chanb7480992017-01-30 14:04:47 +00003472 assert sent < size
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003473
Alex Chanb7480992017-01-30 14:04:47 +00003474 receiver, received = interact_in_memory(client, server)
3475 assert receiver is server
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003476
3477 # We can rely on all of these bytes being received at once because
Alex Chanb7480992017-01-30 14:04:47 +00003478 # loopback passes 2 ** 16 to recv - more than 2 ** 15.
3479 assert len(received) == sent
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003480
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003481 def test_shutdown(self):
3482 """
Alex Chanb7480992017-01-30 14:04:47 +00003483 `Connection.bio_shutdown` signals the end of the data stream
3484 from which the `Connection` reads.
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003485 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003486 server = self._server(None)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003487 server.bio_shutdown()
Alex Chanb7480992017-01-30 14:04:47 +00003488 with pytest.raises(Error) as err:
3489 server.recv(1024)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003490 # We don't want WantReadError or ZeroReturnError or anything - it's a
3491 # handshake failure.
Alex Chanb7480992017-01-30 14:04:47 +00003492 assert type(err.value) in [Error, SysCallError]
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003493
Alex Chanb7480992017-01-30 14:04:47 +00003494 def test_unexpected_EOF(self):
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003495 """
3496 If the connection is lost before an orderly SSL shutdown occurs,
Alex Chanb7480992017-01-30 14:04:47 +00003497 `OpenSSL.SSL.SysCallError` is raised with a message of
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003498 "Unexpected EOF".
3499 """
Alex Chanb7480992017-01-30 14:04:47 +00003500 server_conn, client_conn = loopback()
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003501 client_conn.sock_shutdown(SHUT_RDWR)
Alex Chanb7480992017-01-30 14:04:47 +00003502 with pytest.raises(SysCallError) as err:
3503 server_conn.recv(1024)
3504 assert err.value.args == (-1, "Unexpected EOF")
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003505
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003506 def _check_client_ca_list(self, func):
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003507 """
Alex Chanb7480992017-01-30 14:04:47 +00003508 Verify the return value of the `get_client_ca_list` method for
Hynek Schlawack35618382015-09-05 21:54:25 +02003509 server and client connections.
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003510
Jonathan Ballet78b92a22011-07-16 08:07:26 +09003511 :param func: A function which will be called with the server context
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003512 before the client and server are connected to each other. This
3513 function should specify a list of CAs for the server to send to the
3514 client and return that same list. The list will be used to verify
Alex Chanb7480992017-01-30 14:04:47 +00003515 that `get_client_ca_list` returns the proper value at
Hynek Schlawack35618382015-09-05 21:54:25 +02003516 various times.
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003517 """
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003518 server = self._server(None)
3519 client = self._client(None)
Alex Chanb7480992017-01-30 14:04:47 +00003520 assert client.get_client_ca_list() == []
3521 assert server.get_client_ca_list() == []
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003522 ctx = server.get_context()
3523 expected = func(ctx)
Alex Chanb7480992017-01-30 14:04:47 +00003524 assert client.get_client_ca_list() == []
3525 assert server.get_client_ca_list() == expected
3526 interact_in_memory(client, server)
3527 assert client.get_client_ca_list() == expected
3528 assert server.get_client_ca_list() == expected
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003529
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003530 def test_set_client_ca_list_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003531 """
Alex Chanb7480992017-01-30 14:04:47 +00003532 `Context.set_client_ca_list` raises a `TypeError` if called with a
3533 non-list or a list that contains objects other than X509Names.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003534 """
3535 ctx = Context(TLSv1_METHOD)
Alex Chanb7480992017-01-30 14:04:47 +00003536 with pytest.raises(TypeError):
3537 ctx.set_client_ca_list("spam")
3538 with pytest.raises(TypeError):
3539 ctx.set_client_ca_list(["spam"])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003540
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003541 def test_set_empty_ca_list(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003542 """
Alex Chanb7480992017-01-30 14:04:47 +00003543 If passed an empty list, `Context.set_client_ca_list` configures the
3544 context to send no CA names to the client and, on both the server and
3545 client sides, `Connection.get_client_ca_list` returns an empty list
3546 after the connection is set up.
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003547 """
3548 def no_ca(ctx):
3549 ctx.set_client_ca_list([])
3550 return []
3551 self._check_client_ca_list(no_ca)
3552
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003553 def test_set_one_ca_list(self):
3554 """
3555 If passed a list containing a single X509Name,
Alex Chanb7480992017-01-30 14:04:47 +00003556 `Context.set_client_ca_list` configures the context to send
Hynek Schlawack35618382015-09-05 21:54:25 +02003557 that CA name to the client and, on both the server and client sides,
Alex Chanb7480992017-01-30 14:04:47 +00003558 `Connection.get_client_ca_list` returns a list containing that
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003559 X509Name after the connection is set up.
3560 """
3561 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3562 cadesc = cacert.get_subject()
Hynek Schlawack35618382015-09-05 21:54:25 +02003563
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003564 def single_ca(ctx):
3565 ctx.set_client_ca_list([cadesc])
3566 return [cadesc]
3567 self._check_client_ca_list(single_ca)
3568
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003569 def test_set_multiple_ca_list(self):
3570 """
3571 If passed a list containing multiple X509Name objects,
Alex Chanb7480992017-01-30 14:04:47 +00003572 `Context.set_client_ca_list` configures the context to send
Hynek Schlawack35618382015-09-05 21:54:25 +02003573 those CA names to the client and, on both the server and client sides,
Alex Chanb7480992017-01-30 14:04:47 +00003574 `Connection.get_client_ca_list` returns a list containing those
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003575 X509Names after the connection is set up.
3576 """
3577 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3578 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3579
3580 sedesc = secert.get_subject()
3581 cldesc = clcert.get_subject()
3582
3583 def multiple_ca(ctx):
3584 L = [sedesc, cldesc]
3585 ctx.set_client_ca_list(L)
3586 return L
3587 self._check_client_ca_list(multiple_ca)
3588
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003589 def test_reset_ca_list(self):
3590 """
3591 If called multiple times, only the X509Names passed to the final call
Alex Chanb7480992017-01-30 14:04:47 +00003592 of `Context.set_client_ca_list` are used to configure the CA
Hynek Schlawack35618382015-09-05 21:54:25 +02003593 names sent to the client.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003594 """
3595 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3596 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3597 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3598
3599 cadesc = cacert.get_subject()
3600 sedesc = secert.get_subject()
3601 cldesc = clcert.get_subject()
3602
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003603 def changed_ca(ctx):
3604 ctx.set_client_ca_list([sedesc, cldesc])
3605 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003606 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003607 self._check_client_ca_list(changed_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003608
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003609 def test_mutated_ca_list(self):
3610 """
Alex Chanb7480992017-01-30 14:04:47 +00003611 If the list passed to `Context.set_client_ca_list` is mutated
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003612 afterwards, this does not affect the list of CA names sent to the
3613 client.
3614 """
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
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003621 def mutated_ca(ctx):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003622 L = [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003623 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003624 L.append(sedesc)
3625 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003626 self._check_client_ca_list(mutated_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003627
Alex Chanb7480992017-01-30 14:04:47 +00003628 def test_add_client_ca_wrong_args(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003629 """
Alex Chanb7480992017-01-30 14:04:47 +00003630 `Context.add_client_ca` raises `TypeError` if called with
3631 a non-X509 object.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003632 """
3633 ctx = Context(TLSv1_METHOD)
Alex Chanb7480992017-01-30 14:04:47 +00003634 with pytest.raises(TypeError):
3635 ctx.add_client_ca("spam")
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003636
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003637 def test_one_add_client_ca(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003638 """
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003639 A certificate's subject can be added as a CA to be sent to the client
Alex Chanb7480992017-01-30 14:04:47 +00003640 with `Context.add_client_ca`.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003641 """
3642 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3643 cadesc = cacert.get_subject()
Hynek Schlawack35618382015-09-05 21:54:25 +02003644
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003645 def single_ca(ctx):
3646 ctx.add_client_ca(cacert)
3647 return [cadesc]
3648 self._check_client_ca_list(single_ca)
3649
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003650 def test_multiple_add_client_ca(self):
3651 """
3652 Multiple CA names can be sent to the client by calling
Alex Chanb7480992017-01-30 14:04:47 +00003653 `Context.add_client_ca` with multiple X509 objects.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003654 """
3655 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3656 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3657
3658 cadesc = cacert.get_subject()
3659 sedesc = secert.get_subject()
3660
3661 def multiple_ca(ctx):
3662 ctx.add_client_ca(cacert)
3663 ctx.add_client_ca(secert)
3664 return [cadesc, sedesc]
3665 self._check_client_ca_list(multiple_ca)
3666
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003667 def test_set_and_add_client_ca(self):
3668 """
Alex Chanb7480992017-01-30 14:04:47 +00003669 A call to `Context.set_client_ca_list` followed by a call to
3670 `Context.add_client_ca` results in using the CA names from the
Hynek Schlawack35618382015-09-05 21:54:25 +02003671 first call and the CA name from the second call.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003672 """
3673 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3674 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3675 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3676
3677 cadesc = cacert.get_subject()
3678 sedesc = secert.get_subject()
3679 cldesc = clcert.get_subject()
3680
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003681 def mixed_set_add_ca(ctx):
3682 ctx.set_client_ca_list([cadesc, sedesc])
3683 ctx.add_client_ca(clcert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003684 return [cadesc, sedesc, cldesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003685 self._check_client_ca_list(mixed_set_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003686
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003687 def test_set_after_add_client_ca(self):
3688 """
Alex Chanb7480992017-01-30 14:04:47 +00003689 A call to `Context.set_client_ca_list` after a call to
3690 `Context.add_client_ca` replaces the CA name specified by the
Hynek Schlawack35618382015-09-05 21:54:25 +02003691 former call with the names specified by the latter call.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003692 """
3693 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3694 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3695 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3696
3697 cadesc = cacert.get_subject()
3698 sedesc = secert.get_subject()
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003699
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003700 def set_replaces_add_ca(ctx):
3701 ctx.add_client_ca(clcert)
3702 ctx.set_client_ca_list([cadesc])
3703 ctx.add_client_ca(secert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003704 return [cadesc, sedesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003705 self._check_client_ca_list(set_replaces_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003706
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003707
Alex Chanb7480992017-01-30 14:04:47 +00003708class TestInfoConstants(object):
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003709 """
3710 Tests for assorted constants exposed for use in info callbacks.
3711 """
3712 def test_integers(self):
3713 """
3714 All of the info constants are integers.
3715
3716 This is a very weak test. It would be nice to have one that actually
3717 verifies that as certain info events happen, the value passed to the
3718 info callback matches up with the constant exposed by OpenSSL.SSL.
3719 """
3720 for const in [
Alex Gaynor5af32d02016-09-24 01:52:21 -04003721 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK,
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003722 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
3723 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
3724 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
Hynek Schlawack35618382015-09-05 21:54:25 +02003725 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE
3726 ]:
Alex Gaynor5af32d02016-09-24 01:52:21 -04003727 assert isinstance(const, int)
3728
3729 # These constants don't exist on OpenSSL 1.1.0
3730 for const in [
3731 SSL_ST_INIT, SSL_ST_BEFORE, SSL_ST_OK, SSL_ST_RENEGOTIATE
3732 ]:
3733 assert const is None or isinstance(const, int)
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003734
Ziga Seilnacht44611bf2009-08-31 20:49:30 +02003735
Cory Benfield1d142142016-03-30 11:51:45 +01003736class TestRequires(object):
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003737 """
3738 Tests for the decorator factory used to conditionally raise
Cory Benfield1d142142016-03-30 11:51:45 +01003739 NotImplementedError when older OpenSSLs are used.
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003740 """
3741 def test_available(self):
3742 """
3743 When the OpenSSL functionality is available the decorated functions
3744 work appropriately.
3745 """
3746 feature_guard = _make_requires(True, "Error text")
3747 results = []
3748
3749 @feature_guard
3750 def inner():
3751 results.append(True)
3752 return True
3753
Cory Benfield2333e5e2016-03-30 14:24:16 +01003754 assert inner() is True
3755 assert [True] == results
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003756
3757 def test_unavailable(self):
3758 """
3759 When the OpenSSL functionality is not available the decorated function
3760 does not execute and NotImplementedError is raised.
3761 """
3762 feature_guard = _make_requires(False, "Error text")
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003763
3764 @feature_guard
Alex Chanfb078d82017-04-20 11:16:15 +01003765 def inner(): # pragma: nocover
3766 pytest.fail("Should not be called")
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003767
Cory Benfield1d142142016-03-30 11:51:45 +01003768 with pytest.raises(NotImplementedError) as e:
3769 inner()
3770
3771 assert "Error text" in str(e.value)
Cory Benfield496652a2017-01-24 11:42:56 +00003772
3773
Alex Chanb7480992017-01-30 14:04:47 +00003774class TestOCSP(object):
Cory Benfield496652a2017-01-24 11:42:56 +00003775 """
3776 Tests for PyOpenSSL's OCSP stapling support.
3777 """
3778 sample_ocsp_data = b"this is totally ocsp data"
3779
3780 def _client_connection(self, callback, data, request_ocsp=True):
3781 """
3782 Builds a client connection suitable for using OCSP.
3783
3784 :param callback: The callback to register for OCSP.
3785 :param data: The opaque data object that will be handed to the
3786 OCSP callback.
3787 :param request_ocsp: Whether the client will actually ask for OCSP
3788 stapling. Useful for testing only.
3789 """
3790 ctx = Context(SSLv23_METHOD)
3791 ctx.set_ocsp_client_callback(callback, data)
3792 client = Connection(ctx)
3793
3794 if request_ocsp:
3795 client.request_ocsp()
3796
3797 client.set_connect_state()
3798 return client
3799
3800 def _server_connection(self, callback, data):
3801 """
3802 Builds a server connection suitable for using OCSP.
3803
3804 :param callback: The callback to register for OCSP.
3805 :param data: The opaque data object that will be handed to the
3806 OCSP callback.
3807 """
3808 ctx = Context(SSLv23_METHOD)
3809 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
3810 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
3811 ctx.set_ocsp_server_callback(callback, data)
3812 server = Connection(ctx)
3813 server.set_accept_state()
3814 return server
3815
3816 def test_callbacks_arent_called_by_default(self):
3817 """
3818 If both the client and the server have registered OCSP callbacks, but
3819 the client does not send the OCSP request, neither callback gets
3820 called.
3821 """
Alex Chanfb078d82017-04-20 11:16:15 +01003822 def ocsp_callback(*args, **kwargs): # pragma: nocover
3823 pytest.fail("Should not be called")
Cory Benfield496652a2017-01-24 11:42:56 +00003824
3825 client = self._client_connection(
3826 callback=ocsp_callback, data=None, request_ocsp=False
3827 )
3828 server = self._server_connection(callback=ocsp_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00003829 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003830
Cory Benfield496652a2017-01-24 11:42:56 +00003831 def test_client_negotiates_without_server(self):
3832 """
3833 If the client wants to do OCSP but the server does not, the handshake
3834 succeeds, and the client callback fires with an empty byte string.
3835 """
3836 called = []
3837
3838 def ocsp_callback(conn, ocsp_data, ignored):
3839 called.append(ocsp_data)
3840 return True
3841
3842 client = self._client_connection(callback=ocsp_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00003843 server = loopback_server_factory(socket=None)
3844 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003845
3846 assert len(called) == 1
3847 assert called[0] == b''
3848
3849 def test_client_receives_servers_data(self):
3850 """
3851 The data the server sends in its callback is received by the client.
3852 """
3853 calls = []
3854
3855 def server_callback(*args, **kwargs):
3856 return self.sample_ocsp_data
3857
3858 def client_callback(conn, ocsp_data, ignored):
3859 calls.append(ocsp_data)
3860 return True
3861
3862 client = self._client_connection(callback=client_callback, data=None)
3863 server = self._server_connection(callback=server_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00003864 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003865
3866 assert len(calls) == 1
3867 assert calls[0] == self.sample_ocsp_data
3868
3869 def test_callbacks_are_invoked_with_connections(self):
3870 """
3871 The first arguments to both callbacks are their respective connections.
3872 """
3873 client_calls = []
3874 server_calls = []
3875
3876 def client_callback(conn, *args, **kwargs):
3877 client_calls.append(conn)
3878 return True
3879
3880 def server_callback(conn, *args, **kwargs):
3881 server_calls.append(conn)
3882 return self.sample_ocsp_data
3883
3884 client = self._client_connection(callback=client_callback, data=None)
3885 server = self._server_connection(callback=server_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00003886 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003887
3888 assert len(client_calls) == 1
3889 assert len(server_calls) == 1
3890 assert client_calls[0] is client
3891 assert server_calls[0] is server
3892
3893 def test_opaque_data_is_passed_through(self):
3894 """
3895 Both callbacks receive an opaque, user-provided piece of data in their
3896 callbacks as the final argument.
3897 """
3898 calls = []
3899
3900 def server_callback(*args):
3901 calls.append(args)
3902 return self.sample_ocsp_data
3903
3904 def client_callback(*args):
3905 calls.append(args)
3906 return True
3907
3908 sentinel = object()
3909
3910 client = self._client_connection(
3911 callback=client_callback, data=sentinel
3912 )
3913 server = self._server_connection(
3914 callback=server_callback, data=sentinel
3915 )
Alex Chanb7480992017-01-30 14:04:47 +00003916 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003917
3918 assert len(calls) == 2
3919 assert calls[0][-1] is sentinel
3920 assert calls[1][-1] is sentinel
3921
3922 def test_server_returns_empty_string(self):
3923 """
3924 If the server returns an empty bytestring from its callback, the
3925 client callback is called with the empty bytestring.
3926 """
3927 client_calls = []
3928
3929 def server_callback(*args):
3930 return b''
3931
3932 def client_callback(conn, ocsp_data, ignored):
3933 client_calls.append(ocsp_data)
3934 return True
3935
3936 client = self._client_connection(callback=client_callback, data=None)
3937 server = self._server_connection(callback=server_callback, data=None)
Alex Chanb7480992017-01-30 14:04:47 +00003938 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003939
3940 assert len(client_calls) == 1
3941 assert client_calls[0] == b''
3942
3943 def test_client_returns_false_terminates_handshake(self):
3944 """
3945 If the client returns False from its callback, the handshake fails.
3946 """
3947 def server_callback(*args):
3948 return self.sample_ocsp_data
3949
3950 def client_callback(*args):
3951 return False
3952
3953 client = self._client_connection(callback=client_callback, data=None)
3954 server = self._server_connection(callback=server_callback, data=None)
3955
3956 with pytest.raises(Error):
Alex Chanb7480992017-01-30 14:04:47 +00003957 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003958
3959 def test_exceptions_in_client_bubble_up(self):
3960 """
3961 The callbacks thrown in the client callback bubble up to the caller.
3962 """
3963 class SentinelException(Exception):
3964 pass
3965
3966 def server_callback(*args):
3967 return self.sample_ocsp_data
3968
3969 def client_callback(*args):
3970 raise SentinelException()
3971
3972 client = self._client_connection(callback=client_callback, data=None)
3973 server = self._server_connection(callback=server_callback, data=None)
3974
3975 with pytest.raises(SentinelException):
Alex Chanb7480992017-01-30 14:04:47 +00003976 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003977
3978 def test_exceptions_in_server_bubble_up(self):
3979 """
3980 The callbacks thrown in the server callback bubble up to the caller.
3981 """
3982 class SentinelException(Exception):
3983 pass
3984
3985 def server_callback(*args):
3986 raise SentinelException()
3987
Alex Chanfb078d82017-04-20 11:16:15 +01003988 def client_callback(*args): # pragma: nocover
Cory Benfield496652a2017-01-24 11:42:56 +00003989 pytest.fail("Should not be called")
3990
3991 client = self._client_connection(callback=client_callback, data=None)
3992 server = self._server_connection(callback=server_callback, data=None)
3993
3994 with pytest.raises(SentinelException):
Alex Chanb7480992017-01-30 14:04:47 +00003995 handshake_in_memory(client, server)
Cory Benfield496652a2017-01-24 11:42:56 +00003996
3997 def test_server_must_return_bytes(self):
3998 """
3999 The server callback must return a bytestring, or a TypeError is thrown.
4000 """
4001 def server_callback(*args):
4002 return self.sample_ocsp_data.decode('ascii')
4003
Alex Chanfb078d82017-04-20 11:16:15 +01004004 def client_callback(*args): # pragma: nocover
Cory Benfield496652a2017-01-24 11:42:56 +00004005 pytest.fail("Should not be called")
4006
4007 client = self._client_connection(callback=client_callback, data=None)
4008 server = self._server_connection(callback=server_callback, data=None)
4009
4010 with pytest.raises(TypeError):
Alex Chanb7480992017-01-30 14:04:47 +00004011 handshake_in_memory(client, server)