blob: b1df54f54b3fe0584f43b4a2a828efbdeeab9378 [file] [log] [blame]
Jean-Paul Calderone8671c852011-03-02 19:26:20 -05001# Copyright (C) Jean-Paul Calderone
2# See LICENSE for details.
Jean-Paul Calderone8b63d452008-03-21 18:31:12 -04003
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -04004"""
Hynek Schlawackf90e3682016-03-11 11:21:13 +01005Unit tests for :mod:`OpenSSL.SSL`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -04006"""
7
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01008import datetime
9import uuid
10
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -050011from gc import collect, get_referrers
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +020012from errno import ECONNREFUSED, EINPROGRESS, EWOULDBLOCK, EPIPE, ESHUTDOWN
Hynek Schlawackf8979a52015-09-05 21:25:25 +020013from sys import platform, getfilesystemencoding, version_info
Maximilian Hils1d95dea2015-08-17 19:27:20 +020014from socket import MSG_PEEK, SHUT_RDWR, error, socket
Jean-Paul Calderonea65cf6c2009-07-19 10:26:52 -040015from os import makedirs
Jean-Paul Calderone1461c492013-10-03 16:05:00 -040016from os.path import join
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -040017from weakref import ref
Abraham Martinef063482015-03-25 14:06:24 +000018from warnings import catch_warnings, simplefilter
Jean-Paul Calderone460cc1f2009-03-07 11:31:12 -050019
Hynek Schlawack734d3022015-09-05 19:19:32 +020020import pytest
21
Hynek Schlawackf90e3682016-03-11 11:21:13 +010022from six import PY3, text_type
Jean-Paul Calderonec76c61c2014-01-18 13:21:52 -050023
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +010024from cryptography import x509
25from cryptography.hazmat.backends import default_backend
26from cryptography.hazmat.primitives import hashes
27from cryptography.hazmat.primitives import serialization
28from cryptography.hazmat.primitives.asymmetric import rsa
29from cryptography.x509.oid import NameOID
30
31
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040032from OpenSSL.crypto import TYPE_RSA, FILETYPE_PEM
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -080033from OpenSSL.crypto import PKey, X509, X509Extension, X509Store
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040034from OpenSSL.crypto import dump_privatekey, load_privatekey
35from OpenSSL.crypto import dump_certificate, load_certificate
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -040036from OpenSSL.crypto import get_elliptic_curves
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040037
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -040038from OpenSSL.SSL import OPENSSL_VERSION_NUMBER, SSLEAY_VERSION, SSLEAY_CFLAGS
39from OpenSSL.SSL import SSLEAY_PLATFORM, SSLEAY_DIR, SSLEAY_BUILT_ON
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -040040from OpenSSL.SSL import SENT_SHUTDOWN, RECEIVED_SHUTDOWN
Jean-Paul Calderone1461c492013-10-03 16:05:00 -040041from OpenSSL.SSL import (
42 SSLv2_METHOD, SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD,
43 TLSv1_1_METHOD, TLSv1_2_METHOD)
44from OpenSSL.SSL import OP_SINGLE_DH_USE, OP_NO_SSLv2, OP_NO_SSLv3
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040045from OpenSSL.SSL import (
46 VERIFY_PEER, VERIFY_FAIL_IF_NO_PEER_CERT, VERIFY_CLIENT_ONCE, VERIFY_NONE)
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040047
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040048from OpenSSL.SSL import (
Jean-Paul Calderone313bf012012-02-08 13:02:49 -050049 SESS_CACHE_OFF, SESS_CACHE_CLIENT, SESS_CACHE_SERVER, SESS_CACHE_BOTH,
50 SESS_CACHE_NO_AUTO_CLEAR, SESS_CACHE_NO_INTERNAL_LOOKUP,
51 SESS_CACHE_NO_INTERNAL_STORE, SESS_CACHE_NO_INTERNAL)
52
53from OpenSSL.SSL import (
Jean-Paul Calderoned899af02013-03-19 22:10:37 -070054 Error, SysCallError, WantReadError, WantWriteError, ZeroReturnError)
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -050055from OpenSSL.SSL import (
Jean-Paul Calderoned899af02013-03-19 22:10:37 -070056 Context, ContextType, Session, Connection, ConnectionType, SSLeay_version)
Cory Benfield0ba57ec2016-03-30 09:35:05 +010057from OpenSSL.SSL import _make_requires
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040058
Cory Benfieldba1820d2015-04-13 17:39:12 -040059from OpenSSL._util import lib as _lib
60
Alex Gaynord3b5d9b2016-07-31 10:54:24 -040061from OpenSSL.SSL import (
62 OP_NO_QUERY_MTU, OP_COOKIE_EXCHANGE, OP_NO_TICKET, OP_NO_COMPRESSION,
63 MODE_RELEASE_BUFFERS)
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040064
Jean-Paul Calderone1461c492013-10-03 16:05:00 -040065try:
66 from OpenSSL.SSL import OP_NO_TLSv1, OP_NO_TLSv1_1, OP_NO_TLSv1_2
67except ImportError:
68 OP_NO_TLSv1 = OP_NO_TLSv1_1 = OP_NO_TLSv1_2 = None
69
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -040070from OpenSSL.SSL import (
71 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK, SSL_ST_INIT, SSL_ST_BEFORE,
72 SSL_ST_OK, SSL_ST_RENEGOTIATE,
73 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
74 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
75 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
76 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE)
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -040077
Hynek Schlawackf0e66852015-10-16 20:18:38 +020078from .util import WARNING_TYPE_EXPECTED, NON_ASCII, TestCase, b
79from .test_crypto import (
80 cleartextCertificatePEM, cleartextPrivateKeyPEM,
81 client_cert_pem, client_key_pem, server_cert_pem, server_key_pem,
82 root_cert_pem)
83
Hynek Schlawackde00dd52015-09-05 19:09:26 +020084
Alex Gaynord0bdd2d2016-09-10 14:23:46 -040085# openssl dhparam 1024 -out dh-1024.pem (note that 1024 is a small number of
86# bits to use)
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -040087dhparam = """\
88-----BEGIN DH PARAMETERS-----
Alex Gaynord0bdd2d2016-09-10 14:23:46 -040089MIGHAoGBALdUMvn+C9MM+y5BWZs11mSeH6HHoEq0UVbzVq7UojC1hbsZUuGukQ3a
90Qh2/pwqb18BZFykrWB0zv/OkLa0kx4cuUgNrUVq1EFheBiX6YqryJ7t2sO09NQiO
91V7H54LmltOT/hEh6QWsJqb6BQgH65bswvV/XkYGja8/T0GzvbaVzAgEC
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -040092-----END DH PARAMETERS-----
93"""
94
95
Hynek Schlawackb4f02402015-09-05 20:48:34 +020096skip_if_py3 = pytest.mark.skipif(PY3, reason="Python 2 only")
Hynek Schlawackf8979a52015-09-05 21:25:25 +020097skip_if_py26 = pytest.mark.skipif(
98 version_info[0:2] == (2, 6),
99 reason="Python 2.7 and later only"
100)
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200101
102
Jean-Paul Calderone05826732015-04-12 11:38:49 -0400103def join_bytes_or_unicode(prefix, suffix):
104 """
105 Join two path components of either ``bytes`` or ``unicode``.
106
107 The return type is the same as the type of ``prefix``.
108 """
109 # If the types are the same, nothing special is necessary.
110 if type(prefix) == type(suffix):
111 return join(prefix, suffix)
112
113 # Otherwise, coerce suffix to the type of prefix.
114 if isinstance(prefix, text_type):
115 return join(prefix, suffix.decode(getfilesystemencoding()))
116 else:
117 return join(prefix, suffix.encode(getfilesystemencoding()))
118
119
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400120def verify_cb(conn, cert, errnum, depth, ok):
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400121 return ok
122
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400123
Rick Deanb1ccd562009-07-09 23:52:39 -0500124def socket_pair():
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400125 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400126 Establish and return a pair of network sockets connected to each other.
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400127 """
128 # Connect a pair of sockets
Rick Deanb1ccd562009-07-09 23:52:39 -0500129 port = socket()
130 port.bind(('', 0))
131 port.listen(1)
132 client = socket()
133 client.setblocking(False)
Jean-Paul Calderonef23c5d92009-07-23 17:58:15 -0400134 client.connect_ex(("127.0.0.1", port.getsockname()[1]))
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400135 client.setblocking(True)
Rick Deanb1ccd562009-07-09 23:52:39 -0500136 server = port.accept()[0]
Rick Deanb1ccd562009-07-09 23:52:39 -0500137
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400138 # Let's pass some unencrypted data to make sure our socket connection is
139 # fine. Just one byte, so we don't have to worry about buffers getting
140 # filled up or fragmentation.
Jean-Paul Calderone9e4eeae2010-08-22 21:32:52 -0400141 server.send(b("x"))
142 assert client.recv(1024) == b("x")
143 client.send(b("y"))
144 assert server.recv(1024) == b("y")
Rick Deanb1ccd562009-07-09 23:52:39 -0500145
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -0400146 # Most of our callers want non-blocking sockets, make it easy for them.
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400147 server.setblocking(False)
148 client.setblocking(False)
Jim Shaver46f28912015-05-29 19:32:16 -0400149
Rick Deanb1ccd562009-07-09 23:52:39 -0500150 return (server, client)
151
152
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400153def handshake(client, server):
154 conns = [client, server]
155 while conns:
156 for conn in conns:
157 try:
158 conn.do_handshake()
159 except WantReadError:
160 pass
161 else:
162 conns.remove(conn)
163
164
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400165def _create_certificate_chain():
166 """
167 Construct and return a chain of certificates.
168
169 1. A new self-signed certificate authority certificate (cacert)
170 2. A new intermediate certificate signed by cacert (icert)
171 3. A new server certificate signed by icert (scert)
172 """
173 caext = X509Extension(b('basicConstraints'), False, b('CA:true'))
174
175 # Step 1
176 cakey = PKey()
177 cakey.generate_key(TYPE_RSA, 512)
178 cacert = X509()
179 cacert.get_subject().commonName = "Authority Certificate"
180 cacert.set_issuer(cacert.get_subject())
181 cacert.set_pubkey(cakey)
182 cacert.set_notBefore(b("20000101000000Z"))
183 cacert.set_notAfter(b("20200101000000Z"))
184 cacert.add_extensions([caext])
185 cacert.set_serial_number(0)
186 cacert.sign(cakey, "sha1")
187
188 # Step 2
189 ikey = PKey()
190 ikey.generate_key(TYPE_RSA, 512)
191 icert = X509()
192 icert.get_subject().commonName = "Intermediate Certificate"
193 icert.set_issuer(cacert.get_subject())
194 icert.set_pubkey(ikey)
195 icert.set_notBefore(b("20000101000000Z"))
196 icert.set_notAfter(b("20200101000000Z"))
197 icert.add_extensions([caext])
198 icert.set_serial_number(0)
199 icert.sign(cakey, "sha1")
200
201 # Step 3
202 skey = PKey()
203 skey.generate_key(TYPE_RSA, 512)
204 scert = X509()
205 scert.get_subject().commonName = "Server Certificate"
206 scert.set_issuer(icert.get_subject())
207 scert.set_pubkey(skey)
208 scert.set_notBefore(b("20000101000000Z"))
209 scert.set_notAfter(b("20200101000000Z"))
210 scert.add_extensions([
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200211 X509Extension(b('basicConstraints'), True, b('CA:false'))])
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400212 scert.set_serial_number(0)
213 scert.sign(ikey, "sha1")
214
215 return [(cakey, cacert), (ikey, icert), (skey, scert)]
216
217
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400218class _LoopbackMixin:
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400219 """
220 Helper mixin which defines methods for creating a connected socket pair and
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200221 for forcing two connected SSL sockets to talk to each other via memory
222 BIOs.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400223 """
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500224 def _loopbackClientFactory(self, socket):
225 client = Connection(Context(TLSv1_METHOD), socket)
226 client.set_connect_state()
227 return client
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400228
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500229 def _loopbackServerFactory(self, socket):
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400230 ctx = Context(TLSv1_METHOD)
231 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
232 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500233 server = Connection(ctx, socket)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400234 server.set_accept_state()
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500235 return server
236
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500237 def _loopback(self, serverFactory=None, clientFactory=None):
238 if serverFactory is None:
239 serverFactory = self._loopbackServerFactory
240 if clientFactory is None:
241 clientFactory = self._loopbackClientFactory
242
243 (server, client) = socket_pair()
244 server = serverFactory(server)
245 client = clientFactory(client)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400246
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400247 handshake(client, server)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400248
249 server.setblocking(True)
250 client.setblocking(True)
251 return server, client
252
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400253 def _interactInMemory(self, client_conn, server_conn):
254 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900255 Try to read application bytes from each of the two :py:obj:`Connection`
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400256 objects. Copy bytes back and forth between their send/receive buffers
257 for as long as there is anything to copy. When there is nothing more
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200258 to copy, return :py:obj:`None`. If one of them actually manages to
259 deliver some application bytes, return a two-tuple of the connection
260 from which the bytes were read and the bytes themselves.
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400261 """
262 wrote = True
263 while wrote:
264 # Loop until neither side has anything to say
265 wrote = False
266
267 # Copy stuff from each side's send buffer to the other side's
268 # receive buffer.
269 for (read, write) in [(client_conn, server_conn),
270 (server_conn, client_conn)]:
271
272 # Give the side a chance to generate some more bytes, or
273 # succeed.
274 try:
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400275 data = read.recv(2 ** 16)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400276 except WantReadError:
277 # It didn't succeed, so we'll hope it generated some
278 # output.
279 pass
280 else:
281 # It did succeed, so we'll stop now and let the caller deal
282 # with it.
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400283 return (read, data)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400284
285 while True:
286 # Keep copying as long as there's more stuff there.
287 try:
288 dirty = read.bio_read(4096)
289 except WantReadError:
290 # Okay, nothing more waiting to be sent. Stop
291 # processing this send buffer.
292 break
293 else:
294 # Keep track of the fact that someone generated some
295 # output.
296 wrote = True
297 write.bio_write(dirty)
298
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -0400299 def _handshakeInMemory(self, client_conn, server_conn):
Jean-Paul Calderoneb2b40782014-05-06 08:47:40 -0400300 """
301 Perform the TLS handshake between two :py:class:`Connection` instances
302 connected to each other via memory BIOs.
303 """
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -0400304 client_conn.set_connect_state()
305 server_conn.set_accept_state()
306
307 for conn in [client_conn, server_conn]:
308 try:
309 conn.do_handshake()
310 except WantReadError:
311 pass
312
313 self._interactInMemory(client_conn, server_conn)
314
315
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400316class VersionTests(TestCase):
317 """
318 Tests for version information exposed by
Jonathan Ballet648875f2011-07-16 14:14:58 +0900319 :py:obj:`OpenSSL.SSL.SSLeay_version` and
320 :py:obj:`OpenSSL.SSL.OPENSSL_VERSION_NUMBER`.
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400321 """
322 def test_OPENSSL_VERSION_NUMBER(self):
323 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900324 :py:obj:`OPENSSL_VERSION_NUMBER` is an integer with status in the low
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400325 byte and the patch, fix, minor, and major versions in the
326 nibbles above that.
327 """
328 self.assertTrue(isinstance(OPENSSL_VERSION_NUMBER, int))
329
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400330 def test_SSLeay_version(self):
331 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900332 :py:obj:`SSLeay_version` takes a version type indicator and returns
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400333 one of a number of version strings based on that indicator.
334 """
335 versions = {}
336 for t in [SSLEAY_VERSION, SSLEAY_CFLAGS, SSLEAY_BUILT_ON,
337 SSLEAY_PLATFORM, SSLEAY_DIR]:
338 version = SSLeay_version(t)
339 versions[version] = t
340 self.assertTrue(isinstance(version, bytes))
341 self.assertEqual(len(versions), 5)
342
343
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100344@pytest.fixture
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100345def ca_file(tmpdir):
346 """
347 Create a valid PEM file with CA certificates and return the path.
348 """
349 key = rsa.generate_private_key(
350 public_exponent=65537,
351 key_size=2048,
352 backend=default_backend()
353 )
354 public_key = key.public_key()
355
356 builder = x509.CertificateBuilder()
357 builder = builder.subject_name(x509.Name([
358 x509.NameAttribute(NameOID.COMMON_NAME, u"pyopenssl.org"),
359 ]))
360 builder = builder.issuer_name(x509.Name([
361 x509.NameAttribute(NameOID.COMMON_NAME, u"pyopenssl.org"),
362 ]))
363 one_day = datetime.timedelta(1, 0, 0)
364 builder = builder.not_valid_before(datetime.datetime.today() - one_day)
365 builder = builder.not_valid_after(datetime.datetime.today() + one_day)
366 builder = builder.serial_number(int(uuid.uuid4()))
367 builder = builder.public_key(public_key)
368 builder = builder.add_extension(
369 x509.BasicConstraints(ca=True, path_length=None), critical=True,
370 )
371
372 certificate = builder.sign(
373 private_key=key, algorithm=hashes.SHA256(),
374 backend=default_backend()
375 )
376
377 ca_file = tmpdir.join("test.pem")
378 ca_file.write_binary(
379 certificate.public_bytes(
380 encoding=serialization.Encoding.PEM,
381 )
382 )
383
384 return str(ca_file).encode("ascii")
385
386
387@pytest.fixture
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100388def context():
389 """
390 A simple TLS 1.0 context.
391 """
392 return Context(TLSv1_METHOD)
393
394
395class TestContext(object):
Hynek Schlawackaa861212016-03-13 13:53:48 +0100396 """
397 py.test-based tests for :class:`OpenSSL.SSL.Context`.
398
399 If possible, add new tests here.
400 """
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100401 @pytest.mark.parametrize("cipher_string", [
402 b"hello world:AES128-SHA",
403 u"hello world:AES128-SHA",
404 ])
405 def test_set_cipher_list(self, context, cipher_string):
406 """
Hynek Schlawacka7a63af2016-03-11 12:05:26 +0100407 :meth:`Context.set_cipher_list` accepts both byte and unicode strings
408 for naming the ciphers which connections created with the context
409 object will be able to choose from.
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100410 """
411 context.set_cipher_list(cipher_string)
412 conn = Connection(context, None)
413
414 assert "AES128-SHA" in conn.get_cipher_list()
415
416 @pytest.mark.parametrize("cipher_list,error", [
417 (object(), TypeError),
418 ("imaginary-cipher", Error),
419 ])
420 def test_set_cipher_list_wrong_args(self, context, cipher_list, error):
421 """
422 :meth:`Context.set_cipher_list` raises :exc:`TypeError` when passed a
423 non-string argument and raises :exc:`OpenSSL.SSL.Error` when passed an
424 incorrect cipher list string.
425 """
426 with pytest.raises(error):
427 context.set_cipher_list(cipher_list)
428
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100429 def test_load_client_ca(self, context, ca_file):
430 """
431 :meth:`Context.load_client_ca` works as far as we can tell.
432 """
433 context.load_client_ca(ca_file)
434
435 def test_load_client_ca_invalid(self, context, tmpdir):
436 """
437 :meth:`Context.load_client_ca` raises an Error if the ca file is
438 invalid.
439 """
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 """
458 :meth:`Context.set_session_id` works as far as we can tell.
459 """
460 context.set_session_id(b"abc")
461
462 def test_set_session_id_fail(self, context):
463 """
464 :meth:`Context.set_session_id` errors are propagated.
465 """
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 """
477 :meth:`Context.set_session_id` raises a warning if a unicode string is
478 passed.
479 """
480 pytest.deprecated_call(context.set_session_id, u"abc")
481
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100482
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400483class ContextTests(TestCase, _LoopbackMixin):
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400484 """
Hynek Schlawackaa861212016-03-13 13:53:48 +0100485 Unit tests for :class:`OpenSSL.SSL.Context`.
486
487 If possible, add new tests to :class:`TestContext` above.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400488 """
489 def test_method(self):
490 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200491 :py:obj:`Context` can be instantiated with one of
492 :py:obj:`SSLv2_METHOD`, :py:obj:`SSLv3_METHOD`,
493 :py:obj:`SSLv23_METHOD`, :py:obj:`TLSv1_METHOD`,
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400494 :py:obj:`TLSv1_1_METHOD`, or :py:obj:`TLSv1_2_METHOD`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400495 """
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400496 methods = [
497 SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD]
498 for meth in methods:
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400499 Context(meth)
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400500
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400501 maybe = [SSLv2_METHOD, TLSv1_1_METHOD, TLSv1_2_METHOD]
502 for meth in maybe:
503 try:
504 Context(meth)
505 except (Error, ValueError):
506 # Some versions of OpenSSL have SSLv2 / TLSv1.1 / TLSv1.2, some
507 # don't. Difficult to say in advance.
508 pass
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400509
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400510 self.assertRaises(TypeError, Context, "")
511 self.assertRaises(ValueError, Context, 10)
512
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200513 @skip_if_py3
514 def test_method_long(self):
515 """
516 On Python 2 :py:class:`Context` accepts values of type
517 :py:obj:`long` as well as :py:obj:`int`.
518 """
519 Context(long(TLSv1_METHOD))
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500520
Rick Deane15b1472009-07-09 15:53:42 -0500521 def test_type(self):
522 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200523 :py:obj:`Context` and :py:obj:`ContextType` refer to the same type
524 object and can be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -0500525 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400526 self.assertIdentical(Context, ContextType)
527 self.assertConsistentType(Context, 'Context', TLSv1_METHOD)
Rick Deane15b1472009-07-09 15:53:42 -0500528
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400529 def test_use_privatekey(self):
530 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200531 :py:obj:`Context.use_privatekey` takes an :py:obj:`OpenSSL.crypto.PKey`
532 instance.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400533 """
534 key = PKey()
535 key.generate_key(TYPE_RSA, 128)
536 ctx = Context(TLSv1_METHOD)
537 ctx.use_privatekey(key)
538 self.assertRaises(TypeError, ctx.use_privatekey, "")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400539
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800540 def test_use_privatekey_file_missing(self):
541 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200542 :py:obj:`Context.use_privatekey_file` raises
543 :py:obj:`OpenSSL.SSL.Error` when passed the name of a file which does
544 not exist.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800545 """
546 ctx = Context(TLSv1_METHOD)
547 self.assertRaises(Error, ctx.use_privatekey_file, self.mktemp())
548
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400549 def _use_privatekey_file_test(self, pemfile, filetype):
550 """
551 Verify that calling ``Context.use_privatekey_file`` with the given
552 arguments does not raise an exception.
553 """
554 key = PKey()
555 key.generate_key(TYPE_RSA, 128)
556
557 with open(pemfile, "wt") as pem:
558 pem.write(
559 dump_privatekey(FILETYPE_PEM, key).decode("ascii")
560 )
561
562 ctx = Context(TLSv1_METHOD)
563 ctx.use_privatekey_file(pemfile, filetype)
564
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400565 def test_use_privatekey_file_bytes(self):
566 """
567 A private key can be specified from a file by passing a ``bytes``
568 instance giving the file name to ``Context.use_privatekey_file``.
569 """
570 self._use_privatekey_file_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -0400571 self.mktemp() + NON_ASCII.encode(getfilesystemencoding()),
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400572 FILETYPE_PEM,
573 )
574
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400575 def test_use_privatekey_file_unicode(self):
576 """
577 A private key can be specified from a file by passing a ``unicode``
578 instance giving the file name to ``Context.use_privatekey_file``.
579 """
580 self._use_privatekey_file_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -0400581 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII,
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400582 FILETYPE_PEM,
583 )
584
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200585 @skip_if_py3
586 def test_use_privatekey_file_long(self):
587 """
588 On Python 2 :py:obj:`Context.use_privatekey_file` accepts a
589 filetype of type :py:obj:`long` as well as :py:obj:`int`.
590 """
591 self._use_privatekey_file_test(self.mktemp(), long(FILETYPE_PEM))
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500592
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800593 def test_use_certificate_wrong_args(self):
594 """
595 :py:obj:`Context.use_certificate_wrong_args` raises :py:obj:`TypeError`
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200596 when not passed exactly one :py:obj:`OpenSSL.crypto.X509` instance as
597 an argument.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800598 """
599 ctx = Context(TLSv1_METHOD)
600 self.assertRaises(TypeError, ctx.use_certificate)
601 self.assertRaises(TypeError, ctx.use_certificate, "hello, world")
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200602 self.assertRaises(
603 TypeError, ctx.use_certificate, X509(), "hello, world"
604 )
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800605
606 def test_use_certificate_uninitialized(self):
607 """
608 :py:obj:`Context.use_certificate` raises :py:obj:`OpenSSL.SSL.Error`
609 when passed a :py:obj:`OpenSSL.crypto.X509` instance which has not been
610 initialized (ie, which does not actually have any certificate data).
611 """
612 ctx = Context(TLSv1_METHOD)
613 self.assertRaises(Error, ctx.use_certificate, X509())
614
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800615 def test_use_certificate(self):
616 """
617 :py:obj:`Context.use_certificate` sets the certificate which will be
618 used to identify connections created using the context.
619 """
620 # TODO
621 # Hard to assert anything. But we could set a privatekey then ask
622 # OpenSSL if the cert and key agree using check_privatekey. Then as
623 # long as check_privatekey works right we're good...
624 ctx = Context(TLSv1_METHOD)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200625 ctx.use_certificate(
626 load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
627 )
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800628
629 def test_use_certificate_file_wrong_args(self):
630 """
631 :py:obj:`Context.use_certificate_file` raises :py:obj:`TypeError` if
632 called with zero arguments or more than two arguments, or if the first
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200633 argument is not a byte string or the second argumnent is not an
634 integer.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800635 """
636 ctx = Context(TLSv1_METHOD)
637 self.assertRaises(TypeError, ctx.use_certificate_file)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200638 self.assertRaises(TypeError, ctx.use_certificate_file, b"somefile",
639 object())
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800640 self.assertRaises(
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200641 TypeError, ctx.use_certificate_file, b"somefile", FILETYPE_PEM,
642 object())
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800643 self.assertRaises(
644 TypeError, ctx.use_certificate_file, object(), FILETYPE_PEM)
645 self.assertRaises(
646 TypeError, ctx.use_certificate_file, b"somefile", object())
647
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800648 def test_use_certificate_file_missing(self):
649 """
650 :py:obj:`Context.use_certificate_file` raises
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200651 `:py:obj:`OpenSSL.SSL.Error` if passed the name of a file which does
652 not exist.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800653 """
654 ctx = Context(TLSv1_METHOD)
655 self.assertRaises(Error, ctx.use_certificate_file, self.mktemp())
656
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400657 def _use_certificate_file_test(self, certificate_file):
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800658 """
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400659 Verify that calling ``Context.use_certificate_file`` with the given
660 filename doesn't raise an exception.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800661 """
662 # TODO
663 # Hard to assert anything. But we could set a privatekey then ask
664 # OpenSSL if the cert and key agree using check_privatekey. Then as
665 # long as check_privatekey works right we're good...
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400666 with open(certificate_file, "wb") as pem_file:
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800667 pem_file.write(cleartextCertificatePEM)
668
669 ctx = Context(TLSv1_METHOD)
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400670 ctx.use_certificate_file(certificate_file)
671
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400672 def test_use_certificate_file_bytes(self):
673 """
674 :py:obj:`Context.use_certificate_file` sets the certificate (given as a
675 ``bytes`` filename) which will be used to identify connections created
676 using the context.
677 """
Hynek Schlawack4813c0e2015-04-16 13:38:01 -0400678 filename = self.mktemp() + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400679 self._use_certificate_file_test(filename)
680
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400681 def test_use_certificate_file_unicode(self):
682 """
683 :py:obj:`Context.use_certificate_file` sets the certificate (given as a
684 ``bytes`` filename) which will be used to identify connections created
685 using the context.
686 """
Hynek Schlawack4813c0e2015-04-16 13:38:01 -0400687 filename = self.mktemp().decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400688 self._use_certificate_file_test(filename)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800689
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200690 @skip_if_py3
691 def test_use_certificate_file_long(self):
692 """
693 On Python 2 :py:obj:`Context.use_certificate_file` accepts a
694 filetype of type :py:obj:`long` as well as :py:obj:`int`.
695 """
696 pem_filename = self.mktemp()
697 with open(pem_filename, "wb") as pem_file:
698 pem_file.write(cleartextCertificatePEM)
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500699
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200700 ctx = Context(TLSv1_METHOD)
701 ctx.use_certificate_file(pem_filename, long(FILETYPE_PEM))
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500702
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500703 def test_check_privatekey_valid(self):
704 """
705 :py:obj:`Context.check_privatekey` returns :py:obj:`None` if the
706 :py:obj:`Context` instance has been configured to use a matched key and
707 certificate pair.
708 """
709 key = load_privatekey(FILETYPE_PEM, client_key_pem)
710 cert = load_certificate(FILETYPE_PEM, client_cert_pem)
711 context = Context(TLSv1_METHOD)
712 context.use_privatekey(key)
713 context.use_certificate(cert)
714 self.assertIs(None, context.check_privatekey())
715
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500716 def test_check_privatekey_invalid(self):
717 """
718 :py:obj:`Context.check_privatekey` raises :py:obj:`Error` if the
719 :py:obj:`Context` instance has been configured to use a key and
720 certificate pair which don't relate to each other.
721 """
722 key = load_privatekey(FILETYPE_PEM, client_key_pem)
723 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
724 context = Context(TLSv1_METHOD)
725 context.use_privatekey(key)
726 context.use_certificate(cert)
727 self.assertRaises(Error, context.check_privatekey)
728
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500729 def test_check_privatekey_wrong_args(self):
730 """
731 :py:obj:`Context.check_privatekey` raises :py:obj:`TypeError` if called
732 with other than no arguments.
733 """
734 context = Context(TLSv1_METHOD)
735 self.assertRaises(TypeError, context.check_privatekey, object())
736
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400737 def test_set_app_data_wrong_args(self):
738 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200739 :py:obj:`Context.set_app_data` raises :py:obj:`TypeError` if called
740 with other than one argument.
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400741 """
742 context = Context(TLSv1_METHOD)
743 self.assertRaises(TypeError, context.set_app_data)
744 self.assertRaises(TypeError, context.set_app_data, None, None)
745
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400746 def test_get_app_data_wrong_args(self):
747 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200748 :py:obj:`Context.get_app_data` raises :py:obj:`TypeError` if called
749 with any arguments.
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400750 """
751 context = Context(TLSv1_METHOD)
752 self.assertRaises(TypeError, context.get_app_data, None)
753
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400754 def test_app_data(self):
755 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200756 :py:obj:`Context.set_app_data` stores an object for later retrieval
757 using :py:obj:`Context.get_app_data`.
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400758 """
759 app_data = object()
760 context = Context(TLSv1_METHOD)
761 context.set_app_data(app_data)
762 self.assertIdentical(context.get_app_data(), app_data)
763
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400764 def test_set_options_wrong_args(self):
765 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200766 :py:obj:`Context.set_options` raises :py:obj:`TypeError` if called with
767 the wrong number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400768 """
769 context = Context(TLSv1_METHOD)
770 self.assertRaises(TypeError, context.set_options)
771 self.assertRaises(TypeError, context.set_options, None)
772 self.assertRaises(TypeError, context.set_options, 1, None)
773
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500774 def test_set_options(self):
775 """
776 :py:obj:`Context.set_options` returns the new options value.
777 """
778 context = Context(TLSv1_METHOD)
779 options = context.set_options(OP_NO_SSLv2)
780 self.assertTrue(OP_NO_SSLv2 & options)
781
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200782 @skip_if_py3
783 def test_set_options_long(self):
784 """
785 On Python 2 :py:obj:`Context.set_options` accepts values of type
786 :py:obj:`long` as well as :py:obj:`int`.
787 """
788 context = Context(TLSv1_METHOD)
789 options = context.set_options(long(OP_NO_SSLv2))
790 self.assertTrue(OP_NO_SSLv2 & options)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500791
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300792 def test_set_mode_wrong_args(self):
793 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200794 :py:obj:`Context.set`mode} raises :py:obj:`TypeError` if called with
795 the wrong number of arguments or a non-:py:obj:`int` argument.
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300796 """
797 context = Context(TLSv1_METHOD)
798 self.assertRaises(TypeError, context.set_mode)
799 self.assertRaises(TypeError, context.set_mode, None)
800 self.assertRaises(TypeError, context.set_mode, 1, None)
801
Alex Gaynord3b5d9b2016-07-31 10:54:24 -0400802 def test_set_mode(self):
803 """
804 :py:obj:`Context.set_mode` accepts a mode bitvector and returns the
805 newly set mode.
806 """
807 context = Context(TLSv1_METHOD)
808 self.assertTrue(
809 MODE_RELEASE_BUFFERS & context.set_mode(MODE_RELEASE_BUFFERS))
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500810
Alex Gaynord3b5d9b2016-07-31 10:54:24 -0400811 @skip_if_py3
812 def test_set_mode_long(self):
813 """
814 On Python 2 :py:obj:`Context.set_mode` accepts values of type
815 :py:obj:`long` as well as :py:obj:`int`.
816 """
817 context = Context(TLSv1_METHOD)
818 mode = context.set_mode(long(MODE_RELEASE_BUFFERS))
819 self.assertTrue(MODE_RELEASE_BUFFERS & mode)
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400820
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400821 def test_set_timeout_wrong_args(self):
822 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200823 :py:obj:`Context.set_timeout` raises :py:obj:`TypeError` if called with
824 the wrong number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400825 """
826 context = Context(TLSv1_METHOD)
827 self.assertRaises(TypeError, context.set_timeout)
828 self.assertRaises(TypeError, context.set_timeout, None)
829 self.assertRaises(TypeError, context.set_timeout, 1, None)
830
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400831 def test_get_timeout_wrong_args(self):
832 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200833 :py:obj:`Context.get_timeout` raises :py:obj:`TypeError` if called with
834 any arguments.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400835 """
836 context = Context(TLSv1_METHOD)
837 self.assertRaises(TypeError, context.get_timeout, None)
838
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400839 def test_timeout(self):
840 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200841 :py:obj:`Context.set_timeout` sets the session timeout for all
842 connections created using the context object.
843 :py:obj:`Context.get_timeout` retrieves this value.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400844 """
845 context = Context(TLSv1_METHOD)
846 context.set_timeout(1234)
847 self.assertEquals(context.get_timeout(), 1234)
848
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200849 @skip_if_py3
850 def test_timeout_long(self):
851 """
852 On Python 2 :py:obj:`Context.set_timeout` accepts values of type
853 `long` as well as int.
854 """
855 context = Context(TLSv1_METHOD)
856 context.set_timeout(long(1234))
857 self.assertEquals(context.get_timeout(), 1234)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500858
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400859 def test_set_verify_depth_wrong_args(self):
860 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200861 :py:obj:`Context.set_verify_depth` raises :py:obj:`TypeError` if called
862 with the wrong number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400863 """
864 context = Context(TLSv1_METHOD)
865 self.assertRaises(TypeError, context.set_verify_depth)
866 self.assertRaises(TypeError, context.set_verify_depth, None)
867 self.assertRaises(TypeError, context.set_verify_depth, 1, None)
868
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400869 def test_get_verify_depth_wrong_args(self):
870 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200871 :py:obj:`Context.get_verify_depth` raises :py:obj:`TypeError` if called
872 with any arguments.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400873 """
874 context = Context(TLSv1_METHOD)
875 self.assertRaises(TypeError, context.get_verify_depth, None)
876
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400877 def test_verify_depth(self):
878 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200879 :py:obj:`Context.set_verify_depth` sets the number of certificates in
880 a chain to follow before giving up. The value can be retrieved with
Jonathan Ballet648875f2011-07-16 14:14:58 +0900881 :py:obj:`Context.get_verify_depth`.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400882 """
883 context = Context(TLSv1_METHOD)
884 context.set_verify_depth(11)
885 self.assertEquals(context.get_verify_depth(), 11)
886
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200887 @skip_if_py3
888 def test_verify_depth_long(self):
889 """
890 On Python 2 :py:obj:`Context.set_verify_depth` accepts values of
891 type `long` as well as int.
892 """
893 context = Context(TLSv1_METHOD)
894 context.set_verify_depth(long(11))
895 self.assertEquals(context.get_verify_depth(), 11)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500896
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400897 def _write_encrypted_pem(self, passphrase):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400898 """
899 Write a new private key out to a new file, encrypted using the given
900 passphrase. Return the path to the new file.
901 """
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400902 key = PKey()
903 key.generate_key(TYPE_RSA, 128)
904 pemFile = self.mktemp()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400905 fObj = open(pemFile, 'w')
906 pem = dump_privatekey(FILETYPE_PEM, key, "blowfish", passphrase)
907 fObj.write(pem.decode('ascii'))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400908 fObj.close()
909 return pemFile
910
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400911 def test_set_passwd_cb_wrong_args(self):
912 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200913 :py:obj:`Context.set_passwd_cb` raises :py:obj:`TypeError` if called
914 with the wrong arguments or with a non-callable first argument.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400915 """
916 context = Context(TLSv1_METHOD)
917 self.assertRaises(TypeError, context.set_passwd_cb)
918 self.assertRaises(TypeError, context.set_passwd_cb, None)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200919 self.assertRaises(
920 TypeError, context.set_passwd_cb, lambda: None, None, None
Hynek Schlawack2c013a92015-09-05 19:33:05 +0200921 ) # pragma: nocover
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400922
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400923 def test_set_passwd_cb(self):
924 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200925 :py:obj:`Context.set_passwd_cb` accepts a callable which will be
926 invoked when a private key is loaded from an encrypted PEM.
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400927 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400928 passphrase = b("foobar")
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400929 pemFile = self._write_encrypted_pem(passphrase)
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400930 calledWith = []
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200931
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400932 def passphraseCallback(maxlen, verify, extra):
933 calledWith.append((maxlen, verify, extra))
934 return passphrase
935 context = Context(TLSv1_METHOD)
936 context.set_passwd_cb(passphraseCallback)
937 context.use_privatekey_file(pemFile)
938 self.assertTrue(len(calledWith), 1)
939 self.assertTrue(isinstance(calledWith[0][0], int))
940 self.assertTrue(isinstance(calledWith[0][1], int))
941 self.assertEqual(calledWith[0][2], None)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400942
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400943 def test_passwd_callback_exception(self):
944 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200945 :py:obj:`Context.use_privatekey_file` propagates any exception raised
946 by the passphrase callback.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400947 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400948 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200949
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400950 def passphraseCallback(maxlen, verify, extra):
951 raise RuntimeError("Sorry, I am a fail.")
952
953 context = Context(TLSv1_METHOD)
954 context.set_passwd_cb(passphraseCallback)
955 self.assertRaises(RuntimeError, context.use_privatekey_file, pemFile)
956
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400957 def test_passwd_callback_false(self):
958 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200959 :py:obj:`Context.use_privatekey_file` raises
960 :py:obj:`OpenSSL.SSL.Error` if the passphrase callback returns a false
961 value.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400962 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400963 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200964
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400965 def passphraseCallback(maxlen, verify, extra):
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500966 return b""
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400967
968 context = Context(TLSv1_METHOD)
969 context.set_passwd_cb(passphraseCallback)
970 self.assertRaises(Error, context.use_privatekey_file, pemFile)
971
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400972 def test_passwd_callback_non_string(self):
973 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200974 :py:obj:`Context.use_privatekey_file` raises
975 :py:obj:`OpenSSL.SSL.Error` if the passphrase callback returns a true
976 non-string value.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400977 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400978 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200979
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400980 def passphraseCallback(maxlen, verify, extra):
981 return 10
982
983 context = Context(TLSv1_METHOD)
984 context.set_passwd_cb(passphraseCallback)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800985 self.assertRaises(ValueError, context.use_privatekey_file, pemFile)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400986
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400987 def test_passwd_callback_too_long(self):
988 """
989 If the passphrase returned by the passphrase callback returns a string
990 longer than the indicated maximum length, it is truncated.
991 """
992 # A priori knowledge!
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400993 passphrase = b("x") * 1024
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400994 pemFile = self._write_encrypted_pem(passphrase)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200995
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400996 def passphraseCallback(maxlen, verify, extra):
997 assert maxlen == 1024
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400998 return passphrase + b("y")
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400999
1000 context = Context(TLSv1_METHOD)
1001 context.set_passwd_cb(passphraseCallback)
1002 # This shall succeed because the truncated result is the correct
1003 # passphrase.
1004 context.use_privatekey_file(pemFile)
1005
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -04001006 def test_set_info_callback(self):
1007 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001008 :py:obj:`Context.set_info_callback` accepts a callable which will be
1009 invoked when certain information about an SSL connection is available.
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -04001010 """
Rick Deanb1ccd562009-07-09 23:52:39 -05001011 (server, client) = socket_pair()
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -04001012
1013 clientSSL = Connection(Context(TLSv1_METHOD), client)
1014 clientSSL.set_connect_state()
1015
1016 called = []
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001017
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -04001018 def info(conn, where, ret):
1019 called.append((conn, where, ret))
1020 context = Context(TLSv1_METHOD)
1021 context.set_info_callback(info)
1022 context.use_certificate(
1023 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1024 context.use_privatekey(
1025 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1026
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -04001027 serverSSL = Connection(context, server)
1028 serverSSL.set_accept_state()
1029
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -05001030 handshake(clientSSL, serverSSL)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -04001031
Jean-Paul Calderone3835e522014-02-02 11:12:30 -05001032 # The callback must always be called with a Connection instance as the
1033 # first argument. It would probably be better to split this into
1034 # separate tests for client and server side info callbacks so we could
1035 # assert it is called with the right Connection instance. It would
1036 # also be good to assert *something* about `where` and `ret`.
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -05001037 notConnections = [
1038 conn for (conn, where, ret) in called
1039 if not isinstance(conn, Connection)]
1040 self.assertEqual(
1041 [], notConnections,
1042 "Some info callback arguments were not Connection instaces.")
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001043
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001044 def _load_verify_locations_test(self, *args):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001045 """
1046 Create a client context which will verify the peer certificate and call
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04001047 its :py:obj:`load_verify_locations` method with the given arguments.
1048 Then connect it to a server and ensure that the handshake succeeds.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001049 """
Rick Deanb1ccd562009-07-09 23:52:39 -05001050 (server, client) = socket_pair()
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001051
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001052 clientContext = Context(TLSv1_METHOD)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001053 clientContext.load_verify_locations(*args)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001054 # Require that the server certificate verify properly or the
1055 # connection will fail.
1056 clientContext.set_verify(
1057 VERIFY_PEER,
1058 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
1059
1060 clientSSL = Connection(clientContext, client)
1061 clientSSL.set_connect_state()
1062
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001063 serverContext = Context(TLSv1_METHOD)
1064 serverContext.use_certificate(
1065 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1066 serverContext.use_privatekey(
1067 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1068
1069 serverSSL = Connection(serverContext, server)
1070 serverSSL.set_accept_state()
1071
Jean-Paul Calderonef8742032010-09-25 00:00:32 -04001072 # Without load_verify_locations above, the handshake
1073 # will fail:
1074 # Error: [('SSL routines', 'SSL3_GET_SERVER_CERTIFICATE',
1075 # 'certificate verify failed')]
1076 handshake(clientSSL, serverSSL)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001077
1078 cert = clientSSL.get_peer_certificate()
Jean-Paul Calderone20131f52009-04-01 12:05:45 -04001079 self.assertEqual(cert.get_subject().CN, 'Testing Root CA')
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -04001080
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001081 def _load_verify_cafile(self, cafile):
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001082 """
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001083 Verify that if path to a file containing a certificate is passed to
1084 ``Context.load_verify_locations`` for the ``cafile`` parameter, that
1085 certificate is used as a trust root for the purposes of verifying
1086 connections created using that ``Context``.
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001087 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04001088 fObj = open(cafile, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04001089 fObj.write(cleartextCertificatePEM.decode('ascii'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001090 fObj.close()
1091
1092 self._load_verify_locations_test(cafile)
1093
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001094 def test_load_verify_bytes_cafile(self):
1095 """
1096 :py:obj:`Context.load_verify_locations` accepts a file name as a
1097 ``bytes`` instance and uses the certificates within for verification
1098 purposes.
1099 """
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001100 cafile = self.mktemp() + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001101 self._load_verify_cafile(cafile)
1102
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001103 def test_load_verify_unicode_cafile(self):
1104 """
1105 :py:obj:`Context.load_verify_locations` accepts a file name as a
1106 ``unicode`` instance and uses the certificates within for verification
1107 purposes.
1108 """
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001109 self._load_verify_cafile(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001110 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001111 )
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001112
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -04001113 def test_load_verify_invalid_file(self):
1114 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001115 :py:obj:`Context.load_verify_locations` raises :py:obj:`Error` when
1116 passed a non-existent cafile.
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -04001117 """
1118 clientContext = Context(TLSv1_METHOD)
1119 self.assertRaises(
1120 Error, clientContext.load_verify_locations, self.mktemp())
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001121
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001122 def _load_verify_directory_locations_capath(self, capath):
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001123 """
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001124 Verify that if path to a directory containing certificate files is
1125 passed to ``Context.load_verify_locations`` for the ``capath``
1126 parameter, those certificates are used as trust roots for the purposes
1127 of verifying connections created using that ``Context``.
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001128 """
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001129 makedirs(capath)
Jean-Paul Calderone24dfb332011-05-04 18:10:26 -04001130 # Hash values computed manually with c_rehash to avoid depending on
1131 # c_rehash in the test suite. One is from OpenSSL 0.9.8, the other
1132 # from OpenSSL 1.0.0.
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001133 for name in [b'c7adac82.0', b'c3705638.0']:
Jean-Paul Calderone05826732015-04-12 11:38:49 -04001134 cafile = join_bytes_or_unicode(capath, name)
1135 with open(cafile, 'w') as fObj:
1136 fObj.write(cleartextCertificatePEM.decode('ascii'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001137
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001138 self._load_verify_locations_test(None, capath)
1139
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001140 def test_load_verify_directory_bytes_capath(self):
1141 """
1142 :py:obj:`Context.load_verify_locations` accepts a directory name as a
1143 ``bytes`` instance and uses the certificates within for verification
1144 purposes.
1145 """
1146 self._load_verify_directory_locations_capath(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001147 self.mktemp() + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001148 )
1149
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001150 def test_load_verify_directory_unicode_capath(self):
1151 """
1152 :py:obj:`Context.load_verify_locations` accepts a directory name as a
1153 ``unicode`` instance and uses the certificates within for verification
1154 purposes.
1155 """
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001156 self._load_verify_directory_locations_capath(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001157 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001158 )
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001159
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001160 def test_load_verify_locations_wrong_args(self):
1161 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001162 :py:obj:`Context.load_verify_locations` raises :py:obj:`TypeError` if
1163 called with the wrong number of arguments or with non-:py:obj:`str`
1164 arguments.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001165 """
1166 context = Context(TLSv1_METHOD)
1167 self.assertRaises(TypeError, context.load_verify_locations)
1168 self.assertRaises(TypeError, context.load_verify_locations, object())
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001169 self.assertRaises(
1170 TypeError, context.load_verify_locations, object(), object()
1171 )
1172 self.assertRaises(
1173 TypeError, context.load_verify_locations, None, None, None
1174 )
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001175
Hynek Schlawack734d3022015-09-05 19:19:32 +02001176 @pytest.mark.skipif(
1177 platform == "win32",
1178 reason="set_default_verify_paths appears not to work on Windows. "
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -04001179 "See LP#404343 and LP#404344."
Hynek Schlawack734d3022015-09-05 19:19:32 +02001180 )
1181 def test_set_default_verify_paths(self):
1182 """
1183 :py:obj:`Context.set_default_verify_paths` causes the
1184 platform-specific CA certificate locations to be used for
1185 verification purposes.
1186 """
1187 # Testing this requires a server with a certificate signed by one
1188 # of the CAs in the platform CA location. Getting one of those
1189 # costs money. Fortunately (or unfortunately, depending on your
1190 # perspective), it's easy to think of a public server on the
1191 # internet which has such a certificate. Connecting to the network
1192 # in a unit test is bad, but it's the only way I can think of to
1193 # really test this. -exarkun
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001194
Hynek Schlawack734d3022015-09-05 19:19:32 +02001195 # Arg, verisign.com doesn't speak anything newer than TLS 1.0
Hynek Schlawackbf887932015-10-21 17:13:47 +02001196 context = Context(SSLv23_METHOD)
Hynek Schlawack734d3022015-09-05 19:19:32 +02001197 context.set_default_verify_paths()
1198 context.set_verify(
1199 VERIFY_PEER,
1200 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001201
Hynek Schlawack734d3022015-09-05 19:19:32 +02001202 client = socket()
Hynek Schlawackbf887932015-10-21 17:13:47 +02001203 client.connect(("encrypted.google.com", 443))
Hynek Schlawack734d3022015-09-05 19:19:32 +02001204 clientSSL = Connection(context, client)
1205 clientSSL.set_connect_state()
1206 clientSSL.do_handshake()
1207 clientSSL.send(b"GET / HTTP/1.0\r\n\r\n")
1208 self.assertTrue(clientSSL.recv(1024))
Jean-Paul Calderone9eadb962008-09-07 21:20:44 -04001209
1210 def test_set_default_verify_paths_signature(self):
1211 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001212 :py:obj:`Context.set_default_verify_paths` takes no arguments and
1213 raises :py:obj:`TypeError` if given any.
Jean-Paul Calderone9eadb962008-09-07 21:20:44 -04001214 """
1215 context = Context(TLSv1_METHOD)
1216 self.assertRaises(TypeError, context.set_default_verify_paths, None)
1217 self.assertRaises(TypeError, context.set_default_verify_paths, 1)
1218 self.assertRaises(TypeError, context.set_default_verify_paths, "")
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05001219
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001220 def test_add_extra_chain_cert_invalid_cert(self):
1221 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001222 :py:obj:`Context.add_extra_chain_cert` raises :py:obj:`TypeError` if
1223 called with other than one argument or if called with an object which
1224 is not an instance of :py:obj:`X509`.
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001225 """
1226 context = Context(TLSv1_METHOD)
1227 self.assertRaises(TypeError, context.add_extra_chain_cert)
1228 self.assertRaises(TypeError, context.add_extra_chain_cert, object())
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001229 self.assertRaises(
1230 TypeError, context.add_extra_chain_cert, object(), object()
1231 )
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.
1247 # self._interactInMemory(client, server)
1248 for i in range(3):
1249 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
1258 :py:class:`Connection` instance for which verification is taking place.
1259 """
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
1278 self._handshakeInMemory(clientConnection, serverConnection)
1279
1280 self.assertIdentical(verify.connection, clientConnection)
1281
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001282 def test_set_verify_callback_exception(self):
1283 """
1284 If the verify callback passed to :py:obj:`Context.set_verify` raises an
1285 exception, verification fails and the exception is propagated to the
1286 caller of :py:obj:`Connection.do_handshake`.
1287 """
1288 serverContext = Context(TLSv1_METHOD)
1289 serverContext.use_privatekey(
1290 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1291 serverContext.use_certificate(
1292 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1293
1294 clientContext = Context(TLSv1_METHOD)
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001295
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001296 def verify_callback(*args):
1297 raise Exception("silly verify failure")
1298 clientContext.set_verify(VERIFY_PEER, verify_callback)
1299
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01001300 with pytest.raises(Exception) as exc:
1301 self._handshake_test(serverContext, clientContext)
1302
1303 self.assertEqual("silly verify failure", str(exc.value))
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001304
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001305 def test_add_extra_chain_cert(self):
1306 """
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001307 :py:obj:`Context.add_extra_chain_cert` accepts an :py:obj:`X509`
1308 instance to add to the certificate chain.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001309
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001310 See :py:obj:`_create_certificate_chain` for the details of the
1311 certificate chain tested.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001312
1313 The chain is tested by starting a server with scert and connecting
1314 to it with a client which trusts cacert and requires verification to
1315 succeed.
1316 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001317 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001318 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1319
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001320 # Dump the CA certificate to a file because that's the only way to load
1321 # it as a trusted CA in the client context.
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001322 for cert, name in [(cacert, 'ca.pem'),
1323 (icert, 'i.pem'),
1324 (scert, 's.pem')]:
Hynek Schlawacke90680f2015-04-16 15:09:27 -04001325 with open(join(self.tmpdir, name), 'w') as f:
1326 f.write(dump_certificate(FILETYPE_PEM, cert).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001327
Hynek Schlawack1902c012015-04-16 15:06:41 -04001328 for key, name in [(cakey, 'ca.key'),
1329 (ikey, 'i.key'),
1330 (skey, 's.key')]:
Hynek Schlawacke90680f2015-04-16 15:09:27 -04001331 with open(join(self.tmpdir, name), 'w') as f:
1332 f.write(dump_privatekey(FILETYPE_PEM, key).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001333
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001334 # Create the server context
1335 serverContext = Context(TLSv1_METHOD)
1336 serverContext.use_privatekey(skey)
1337 serverContext.use_certificate(scert)
Jean-Paul Calderone16cf03d2010-09-08 18:53:39 -04001338 # The client already has cacert, we only need to give them icert.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001339 serverContext.add_extra_chain_cert(icert)
1340
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001341 # Create the client
1342 clientContext = Context(TLSv1_METHOD)
1343 clientContext.set_verify(
1344 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001345 clientContext.load_verify_locations(join(self.tmpdir, "ca.pem"))
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001346
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001347 # Try it out.
1348 self._handshake_test(serverContext, clientContext)
1349
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001350 def _use_certificate_chain_file_test(self, certdir):
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001351 """
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001352 Verify that :py:obj:`Context.use_certificate_chain_file` reads a
1353 certificate chain from a specified file.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001354
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001355 The chain is tested by starting a server with scert and connecting to
1356 it with a client which trusts cacert and requires verification to
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001357 succeed.
1358 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001359 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001360 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1361
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001362 makedirs(certdir)
1363
Jean-Paul Calderone05826732015-04-12 11:38:49 -04001364 chainFile = join_bytes_or_unicode(certdir, "chain.pem")
1365 caFile = join_bytes_or_unicode(certdir, "ca.pem")
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001366
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001367 # Write out the chain file.
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001368 with open(chainFile, 'wb') as fObj:
1369 # Most specific to least general.
1370 fObj.write(dump_certificate(FILETYPE_PEM, scert))
1371 fObj.write(dump_certificate(FILETYPE_PEM, icert))
1372 fObj.write(dump_certificate(FILETYPE_PEM, cacert))
1373
1374 with open(caFile, 'w') as fObj:
1375 fObj.write(dump_certificate(FILETYPE_PEM, cacert).decode('ascii'))
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001376
1377 serverContext = Context(TLSv1_METHOD)
1378 serverContext.use_certificate_chain_file(chainFile)
1379 serverContext.use_privatekey(skey)
1380
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001381 clientContext = Context(TLSv1_METHOD)
1382 clientContext.set_verify(
1383 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001384 clientContext.load_verify_locations(caFile)
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001385
1386 self._handshake_test(serverContext, clientContext)
1387
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001388 def test_use_certificate_chain_file_bytes(self):
1389 """
1390 ``Context.use_certificate_chain_file`` accepts the name of a file (as
1391 an instance of ``bytes``) to specify additional certificates to use to
1392 construct and verify a trust chain.
1393 """
1394 self._use_certificate_chain_file_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001395 self.mktemp() + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001396 )
1397
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001398 def test_use_certificate_chain_file_unicode(self):
1399 """
1400 ``Context.use_certificate_chain_file`` accepts the name of a file (as
1401 an instance of ``unicode``) to specify additional certificates to use
1402 to construct and verify a trust chain.
1403 """
1404 self._use_certificate_chain_file_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001405 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001406 )
1407
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001408 def test_use_certificate_chain_file_wrong_args(self):
1409 """
1410 :py:obj:`Context.use_certificate_chain_file` raises :py:obj:`TypeError`
1411 if passed zero or more than one argument or when passed a non-byte
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001412 string single argument. It also raises :py:obj:`OpenSSL.SSL.Error`
1413 when passed a bad chain file name (for example, the name of a file
1414 which does not exist).
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001415 """
1416 context = Context(TLSv1_METHOD)
1417 self.assertRaises(TypeError, context.use_certificate_chain_file)
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001418 self.assertRaises(
1419 TypeError, context.use_certificate_chain_file, object()
1420 )
1421 self.assertRaises(
1422 TypeError, context.use_certificate_chain_file, b"foo", object()
1423 )
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001424
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001425 self.assertRaises(
1426 Error, context.use_certificate_chain_file, self.mktemp()
1427 )
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001428
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001429 def test_get_verify_mode_wrong_args(self):
1430 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001431 :py:obj:`Context.get_verify_mode` raises :py:obj:`TypeError` if called
1432 with any arguments.
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001433 """
1434 context = Context(TLSv1_METHOD)
1435 self.assertRaises(TypeError, context.get_verify_mode, None)
1436
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001437 def test_set_verify_mode(self):
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001438 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001439 :py:obj:`Context.get_verify_mode` returns the verify mode flags
1440 previously passed to :py:obj:`Context.set_verify`.
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001441 """
1442 context = Context(TLSv1_METHOD)
1443 self.assertEquals(context.get_verify_mode(), 0)
1444 context.set_verify(
1445 VERIFY_PEER | VERIFY_CLIENT_ONCE, lambda *args: None)
1446 self.assertEquals(
1447 context.get_verify_mode(), VERIFY_PEER | VERIFY_CLIENT_ONCE)
1448
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001449 @skip_if_py3
1450 def test_set_verify_mode_long(self):
1451 """
1452 On Python 2 :py:obj:`Context.set_verify_mode` accepts values of
1453 type :py:obj:`long` as well as :py:obj:`int`.
1454 """
1455 context = Context(TLSv1_METHOD)
1456 self.assertEquals(context.get_verify_mode(), 0)
1457 context.set_verify(
Hynek Schlawackb4ceed32015-09-05 20:55:19 +02001458 long(VERIFY_PEER | VERIFY_CLIENT_ONCE), lambda *args: None
1459 ) # pragma: nocover
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001460 self.assertEquals(
1461 context.get_verify_mode(), VERIFY_PEER | VERIFY_CLIENT_ONCE)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001462
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001463 def test_load_tmp_dh_wrong_args(self):
1464 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001465 :py:obj:`Context.load_tmp_dh` raises :py:obj:`TypeError` if called with
1466 the wrong number of arguments or with a non-:py:obj:`str` argument.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001467 """
1468 context = Context(TLSv1_METHOD)
1469 self.assertRaises(TypeError, context.load_tmp_dh)
1470 self.assertRaises(TypeError, context.load_tmp_dh, "foo", None)
1471 self.assertRaises(TypeError, context.load_tmp_dh, object())
1472
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001473 def test_load_tmp_dh_missing_file(self):
1474 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001475 :py:obj:`Context.load_tmp_dh` raises :py:obj:`OpenSSL.SSL.Error` if the
1476 specified file does not exist.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001477 """
1478 context = Context(TLSv1_METHOD)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001479 self.assertRaises(Error, context.load_tmp_dh, b"hello")
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001480
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001481 def _load_tmp_dh_test(self, dhfilename):
Jean-Paul Calderone4e0c43f2015-04-13 10:15:17 -04001482 """
1483 Verify that calling ``Context.load_tmp_dh`` with the given filename
1484 does not raise an exception.
1485 """
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001486 context = Context(TLSv1_METHOD)
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001487 with open(dhfilename, "w") as dhfile:
1488 dhfile.write(dhparam)
1489
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001490 context.load_tmp_dh(dhfilename)
1491 # XXX What should I assert here? -exarkun
1492
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001493 def test_load_tmp_dh_bytes(self):
1494 """
1495 :py:obj:`Context.load_tmp_dh` loads Diffie-Hellman parameters from the
1496 specified file (given as ``bytes``).
1497 """
1498 self._load_tmp_dh_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001499 self.mktemp() + NON_ASCII.encode(getfilesystemencoding()),
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001500 )
1501
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001502 def test_load_tmp_dh_unicode(self):
1503 """
1504 :py:obj:`Context.load_tmp_dh` loads Diffie-Hellman parameters from the
1505 specified file (given as ``unicode``).
1506 """
1507 self._load_tmp_dh_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001508 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII,
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001509 )
1510
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001511 def test_set_tmp_ecdh(self):
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001512 """
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001513 :py:obj:`Context.set_tmp_ecdh` sets the elliptic curve for
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001514 Diffie-Hellman to the specified curve.
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001515 """
1516 context = Context(TLSv1_METHOD)
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001517 for curve in get_elliptic_curves():
Hynek Schlawacka07fa8c2015-10-17 10:15:28 +02001518 if curve.name.startswith(u"Oakley-"):
Hynek Schlawack7408aff2015-10-17 09:51:16 +02001519 # Setting Oakley-EC2N-4 and Oakley-EC2N-3 adds
1520 # ('bignum routines', 'BN_mod_inverse', 'no inverse') to the
1521 # error queue on OpenSSL 1.0.2.
1522 continue
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001523 # The only easily "assertable" thing is that it does not raise an
1524 # exception.
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001525 context.set_tmp_ecdh(curve)
Alex Gaynor12dc0842014-01-17 12:51:31 -06001526
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001527 def test_set_session_cache_mode_wrong_args(self):
1528 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001529 :py:obj:`Context.set_session_cache_mode` raises :py:obj:`TypeError` if
1530 called with other than one integer argument.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001531 """
1532 context = Context(TLSv1_METHOD)
1533 self.assertRaises(TypeError, context.set_session_cache_mode)
1534 self.assertRaises(TypeError, context.set_session_cache_mode, object())
1535
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001536 def test_get_session_cache_mode_wrong_args(self):
1537 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001538 :py:obj:`Context.get_session_cache_mode` raises :py:obj:`TypeError` if
1539 called with any arguments.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001540 """
1541 context = Context(TLSv1_METHOD)
1542 self.assertRaises(TypeError, context.get_session_cache_mode, 1)
1543
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001544 def test_session_cache_mode(self):
1545 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001546 :py:obj:`Context.set_session_cache_mode` specifies how sessions are
1547 cached. The setting can be retrieved via
1548 :py:obj:`Context.get_session_cache_mode`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001549 """
1550 context = Context(TLSv1_METHOD)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001551 context.set_session_cache_mode(SESS_CACHE_OFF)
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001552 off = context.set_session_cache_mode(SESS_CACHE_BOTH)
1553 self.assertEqual(SESS_CACHE_OFF, off)
1554 self.assertEqual(SESS_CACHE_BOTH, context.get_session_cache_mode())
1555
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001556 @skip_if_py3
1557 def test_session_cache_mode_long(self):
1558 """
1559 On Python 2 :py:obj:`Context.set_session_cache_mode` accepts values
1560 of type :py:obj:`long` as well as :py:obj:`int`.
1561 """
1562 context = Context(TLSv1_METHOD)
1563 context.set_session_cache_mode(long(SESS_CACHE_BOTH))
1564 self.assertEqual(
1565 SESS_CACHE_BOTH, context.get_session_cache_mode())
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001566
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001567 def test_get_cert_store(self):
1568 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001569 :py:obj:`Context.get_cert_store` returns a :py:obj:`X509Store`
1570 instance.
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001571 """
1572 context = Context(TLSv1_METHOD)
1573 store = context.get_cert_store()
1574 self.assertIsInstance(store, X509Store)
1575
1576
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001577class ServerNameCallbackTests(TestCase, _LoopbackMixin):
1578 """
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001579 Tests for :py:obj:`Context.set_tlsext_servername_callback` and its
1580 interaction with :py:obj:`Connection`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001581 """
1582 def test_wrong_args(self):
1583 """
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001584 :py:obj:`Context.set_tlsext_servername_callback` raises
1585 :py:obj:`TypeError` if called with other than one argument.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001586 """
1587 context = Context(TLSv1_METHOD)
1588 self.assertRaises(TypeError, context.set_tlsext_servername_callback)
1589 self.assertRaises(
1590 TypeError, context.set_tlsext_servername_callback, 1, 2)
1591
1592 def test_old_callback_forgotten(self):
1593 """
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001594 If :py:obj:`Context.set_tlsext_servername_callback` is used to specify
1595 a new callback, the one it replaces is dereferenced.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001596 """
1597 def callback(connection):
1598 pass
1599
1600 def replacement(connection):
1601 pass
1602
1603 context = Context(TLSv1_METHOD)
1604 context.set_tlsext_servername_callback(callback)
1605
1606 tracker = ref(callback)
1607 del callback
1608
1609 context.set_tlsext_servername_callback(replacement)
Jean-Paul Calderoned4033eb2014-01-11 08:21:46 -05001610
1611 # One run of the garbage collector happens to work on CPython. PyPy
1612 # doesn't collect the underlying object until a second run for whatever
1613 # reason. That's fine, it still demonstrates our code has properly
1614 # dropped the reference.
1615 collect()
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001616 collect()
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001617
1618 callback = tracker()
1619 if callback is not None:
1620 referrers = get_referrers(callback)
Jean-Paul Calderone7de39562014-01-11 08:17:59 -05001621 if len(referrers) > 1:
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001622 self.fail("Some references remain: %r" % (referrers,))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001623
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001624 def test_no_servername(self):
1625 """
1626 When a client specifies no server name, the callback passed to
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001627 :py:obj:`Context.set_tlsext_servername_callback` is invoked and the
1628 result of :py:obj:`Connection.get_servername` is :py:obj:`None`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001629 """
1630 args = []
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001631
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001632 def servername(conn):
1633 args.append((conn, conn.get_servername()))
1634 context = Context(TLSv1_METHOD)
1635 context.set_tlsext_servername_callback(servername)
1636
1637 # Lose our reference to it. The Context is responsible for keeping it
1638 # alive now.
1639 del servername
1640 collect()
1641
1642 # Necessary to actually accept the connection
1643 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001644 context.use_certificate(
1645 load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001646
1647 # Do a little connection to trigger the logic
1648 server = Connection(context, None)
1649 server.set_accept_state()
1650
1651 client = Connection(Context(TLSv1_METHOD), None)
1652 client.set_connect_state()
1653
1654 self._interactInMemory(server, client)
1655
1656 self.assertEqual([(server, None)], args)
1657
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001658 def test_servername(self):
1659 """
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001660 When a client specifies a server name in its hello message, the
1661 callback passed to :py:obj:`Contexts.set_tlsext_servername_callback` is
1662 invoked and the result of :py:obj:`Connection.get_servername` is that
1663 server name.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001664 """
1665 args = []
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001666
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001667 def servername(conn):
1668 args.append((conn, conn.get_servername()))
1669 context = Context(TLSv1_METHOD)
1670 context.set_tlsext_servername_callback(servername)
1671
1672 # Necessary to actually accept the connection
1673 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001674 context.use_certificate(
1675 load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001676
1677 # Do a little connection to trigger the logic
1678 server = Connection(context, None)
1679 server.set_accept_state()
1680
1681 client = Connection(Context(TLSv1_METHOD), None)
1682 client.set_connect_state()
1683 client.set_tlsext_host_name(b("foo1.example.com"))
1684
1685 self._interactInMemory(server, client)
1686
1687 self.assertEqual([(server, b("foo1.example.com"))], args)
1688
1689
Cory Benfield84a121e2014-03-31 20:30:25 +01001690class NextProtoNegotiationTests(TestCase, _LoopbackMixin):
1691 """
1692 Test for Next Protocol Negotiation in PyOpenSSL.
1693 """
Cory Benfieldba1820d2015-04-13 17:39:12 -04001694 if _lib.Cryptography_HAS_NEXTPROTONEG:
1695 def test_npn_success(self):
1696 """
1697 Tests that clients and servers that agree on the negotiated next
1698 protocol can correct establish a connection, and that the agreed
1699 protocol is reported by the connections.
1700 """
1701 advertise_args = []
1702 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001703
Cory Benfieldba1820d2015-04-13 17:39:12 -04001704 def advertise(conn):
1705 advertise_args.append((conn,))
1706 return [b'http/1.1', b'spdy/2']
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001707
Cory Benfieldba1820d2015-04-13 17:39:12 -04001708 def select(conn, options):
1709 select_args.append((conn, options))
1710 return b'spdy/2'
Cory Benfield84a121e2014-03-31 20:30:25 +01001711
Cory Benfieldba1820d2015-04-13 17:39:12 -04001712 server_context = Context(TLSv1_METHOD)
1713 server_context.set_npn_advertise_callback(advertise)
Cory Benfield84a121e2014-03-31 20:30:25 +01001714
Cory Benfieldba1820d2015-04-13 17:39:12 -04001715 client_context = Context(TLSv1_METHOD)
1716 client_context.set_npn_select_callback(select)
Cory Benfield84a121e2014-03-31 20:30:25 +01001717
Cory Benfieldba1820d2015-04-13 17:39:12 -04001718 # Necessary to actually accept the connection
1719 server_context.use_privatekey(
1720 load_privatekey(FILETYPE_PEM, server_key_pem))
1721 server_context.use_certificate(
1722 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield84a121e2014-03-31 20:30:25 +01001723
Cory Benfieldba1820d2015-04-13 17:39:12 -04001724 # Do a little connection to trigger the logic
1725 server = Connection(server_context, None)
1726 server.set_accept_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001727
Cory Benfieldba1820d2015-04-13 17:39:12 -04001728 client = Connection(client_context, None)
1729 client.set_connect_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001730
Cory Benfieldba1820d2015-04-13 17:39:12 -04001731 self._interactInMemory(server, client)
Cory Benfield84a121e2014-03-31 20:30:25 +01001732
Cory Benfieldba1820d2015-04-13 17:39:12 -04001733 self.assertEqual([(server,)], advertise_args)
1734 self.assertEqual([(client, [b'http/1.1', b'spdy/2'])], select_args)
Cory Benfield84a121e2014-03-31 20:30:25 +01001735
Cory Benfieldba1820d2015-04-13 17:39:12 -04001736 self.assertEqual(server.get_next_proto_negotiated(), b'spdy/2')
1737 self.assertEqual(client.get_next_proto_negotiated(), b'spdy/2')
Cory Benfield84a121e2014-03-31 20:30:25 +01001738
Cory Benfieldba1820d2015-04-13 17:39:12 -04001739 def test_npn_client_fail(self):
1740 """
1741 Tests that when clients and servers cannot agree on what protocol
1742 to use next that the TLS connection does not get established.
1743 """
1744 advertise_args = []
1745 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001746
Cory Benfieldba1820d2015-04-13 17:39:12 -04001747 def advertise(conn):
1748 advertise_args.append((conn,))
1749 return [b'http/1.1', b'spdy/2']
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001750
Cory Benfieldba1820d2015-04-13 17:39:12 -04001751 def select(conn, options):
1752 select_args.append((conn, options))
1753 return b''
Cory Benfield84a121e2014-03-31 20:30:25 +01001754
Cory Benfieldba1820d2015-04-13 17:39:12 -04001755 server_context = Context(TLSv1_METHOD)
1756 server_context.set_npn_advertise_callback(advertise)
Cory Benfield84a121e2014-03-31 20:30:25 +01001757
Cory Benfieldba1820d2015-04-13 17:39:12 -04001758 client_context = Context(TLSv1_METHOD)
1759 client_context.set_npn_select_callback(select)
Cory Benfield84a121e2014-03-31 20:30:25 +01001760
Cory Benfieldba1820d2015-04-13 17:39:12 -04001761 # Necessary to actually accept the connection
1762 server_context.use_privatekey(
1763 load_privatekey(FILETYPE_PEM, server_key_pem))
1764 server_context.use_certificate(
1765 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield84a121e2014-03-31 20:30:25 +01001766
Cory Benfieldba1820d2015-04-13 17:39:12 -04001767 # Do a little connection to trigger the logic
1768 server = Connection(server_context, None)
1769 server.set_accept_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001770
Cory Benfieldba1820d2015-04-13 17:39:12 -04001771 client = Connection(client_context, None)
1772 client.set_connect_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001773
Cory Benfieldba1820d2015-04-13 17:39:12 -04001774 # If the client doesn't return anything, the connection will fail.
1775 self.assertRaises(Error, self._interactInMemory, server, client)
Cory Benfield84a121e2014-03-31 20:30:25 +01001776
Cory Benfieldba1820d2015-04-13 17:39:12 -04001777 self.assertEqual([(server,)], advertise_args)
1778 self.assertEqual([(client, [b'http/1.1', b'spdy/2'])], select_args)
Cory Benfield84a121e2014-03-31 20:30:25 +01001779
Cory Benfieldba1820d2015-04-13 17:39:12 -04001780 def test_npn_select_error(self):
1781 """
1782 Test that we can handle exceptions in the select callback. If
1783 select fails it should be fatal to the connection.
1784 """
1785 advertise_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001786
Cory Benfieldba1820d2015-04-13 17:39:12 -04001787 def advertise(conn):
1788 advertise_args.append((conn,))
1789 return [b'http/1.1', b'spdy/2']
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001790
Cory Benfieldba1820d2015-04-13 17:39:12 -04001791 def select(conn, options):
1792 raise TypeError
Cory Benfield0ea76e72015-03-22 09:05:28 +00001793
Cory Benfieldba1820d2015-04-13 17:39:12 -04001794 server_context = Context(TLSv1_METHOD)
1795 server_context.set_npn_advertise_callback(advertise)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001796
Cory Benfieldba1820d2015-04-13 17:39:12 -04001797 client_context = Context(TLSv1_METHOD)
1798 client_context.set_npn_select_callback(select)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001799
Cory Benfieldba1820d2015-04-13 17:39:12 -04001800 # Necessary to actually accept the connection
1801 server_context.use_privatekey(
1802 load_privatekey(FILETYPE_PEM, server_key_pem))
1803 server_context.use_certificate(
1804 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield0ea76e72015-03-22 09:05:28 +00001805
Cory Benfieldba1820d2015-04-13 17:39:12 -04001806 # Do a little connection to trigger the logic
1807 server = Connection(server_context, None)
1808 server.set_accept_state()
Cory Benfield0ea76e72015-03-22 09:05:28 +00001809
Cory Benfieldba1820d2015-04-13 17:39:12 -04001810 client = Connection(client_context, None)
1811 client.set_connect_state()
Cory Benfield0ea76e72015-03-22 09:05:28 +00001812
Cory Benfieldba1820d2015-04-13 17:39:12 -04001813 # If the callback throws an exception it should be raised here.
1814 self.assertRaises(
1815 TypeError, self._interactInMemory, server, client
1816 )
1817 self.assertEqual([(server,)], advertise_args)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001818
Cory Benfieldba1820d2015-04-13 17:39:12 -04001819 def test_npn_advertise_error(self):
1820 """
1821 Test that we can handle exceptions in the advertise callback. If
1822 advertise fails no NPN is advertised to the client.
1823 """
1824 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001825
Cory Benfieldba1820d2015-04-13 17:39:12 -04001826 def advertise(conn):
1827 raise TypeError
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001828
Hynek Schlawackb4ceed32015-09-05 20:55:19 +02001829 def select(conn, options): # pragma: nocover
1830 """
1831 Assert later that no args are actually appended.
1832 """
Cory Benfieldba1820d2015-04-13 17:39:12 -04001833 select_args.append((conn, options))
1834 return b''
Cory Benfield0ea76e72015-03-22 09:05:28 +00001835
Cory Benfieldba1820d2015-04-13 17:39:12 -04001836 server_context = Context(TLSv1_METHOD)
1837 server_context.set_npn_advertise_callback(advertise)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001838
Cory Benfieldba1820d2015-04-13 17:39:12 -04001839 client_context = Context(TLSv1_METHOD)
1840 client_context.set_npn_select_callback(select)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001841
Cory Benfieldba1820d2015-04-13 17:39:12 -04001842 # Necessary to actually accept the connection
1843 server_context.use_privatekey(
1844 load_privatekey(FILETYPE_PEM, server_key_pem))
1845 server_context.use_certificate(
1846 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield0ea76e72015-03-22 09:05:28 +00001847
Cory Benfieldba1820d2015-04-13 17:39:12 -04001848 # Do a little connection to trigger the logic
1849 server = Connection(server_context, None)
1850 server.set_accept_state()
Cory Benfield0ea76e72015-03-22 09:05:28 +00001851
Cory Benfieldba1820d2015-04-13 17:39:12 -04001852 client = Connection(client_context, None)
1853 client.set_connect_state()
Cory Benfield0ea76e72015-03-22 09:05:28 +00001854
Cory Benfieldba1820d2015-04-13 17:39:12 -04001855 # If the client doesn't return anything, the connection will fail.
1856 self.assertRaises(
1857 TypeError, self._interactInMemory, server, client
1858 )
1859 self.assertEqual([], select_args)
1860
1861 else:
1862 # No NPN.
1863 def test_npn_not_implemented(self):
1864 # Test the context methods first.
1865 context = Context(TLSv1_METHOD)
1866 fail_methods = [
1867 context.set_npn_advertise_callback,
1868 context.set_npn_select_callback,
1869 ]
1870 for method in fail_methods:
1871 self.assertRaises(
1872 NotImplementedError, method, None
1873 )
1874
1875 # Now test a connection.
1876 conn = Connection(context)
1877 fail_methods = [
1878 conn.get_next_proto_negotiated,
1879 ]
1880 for method in fail_methods:
1881 self.assertRaises(NotImplementedError, method)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001882
1883
Cory Benfield12eae892014-06-07 15:42:56 +01001884class ApplicationLayerProtoNegotiationTests(TestCase, _LoopbackMixin):
1885 """
1886 Tests for ALPN in PyOpenSSL.
1887 """
Cory Benfielde46fa842015-04-13 16:50:49 -04001888 # Skip tests on versions that don't support ALPN.
1889 if _lib.Cryptography_HAS_ALPN:
Cory Benfield12eae892014-06-07 15:42:56 +01001890
Cory Benfielde46fa842015-04-13 16:50:49 -04001891 def test_alpn_success(self):
1892 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04001893 Clients and servers that agree on the negotiated ALPN protocol can
1894 correct establish a connection, and the agreed protocol is reported
1895 by the connections.
Cory Benfielde46fa842015-04-13 16:50:49 -04001896 """
1897 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001898
Cory Benfielde46fa842015-04-13 16:50:49 -04001899 def select(conn, options):
1900 select_args.append((conn, options))
1901 return b'spdy/2'
Cory Benfield12eae892014-06-07 15:42:56 +01001902
Cory Benfielde46fa842015-04-13 16:50:49 -04001903 client_context = Context(TLSv1_METHOD)
1904 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfield12eae892014-06-07 15:42:56 +01001905
Cory Benfielde46fa842015-04-13 16:50:49 -04001906 server_context = Context(TLSv1_METHOD)
1907 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01001908
Cory Benfielde46fa842015-04-13 16:50:49 -04001909 # Necessary to actually accept the connection
1910 server_context.use_privatekey(
1911 load_privatekey(FILETYPE_PEM, server_key_pem))
1912 server_context.use_certificate(
1913 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield12eae892014-06-07 15:42:56 +01001914
Cory Benfielde46fa842015-04-13 16:50:49 -04001915 # Do a little connection to trigger the logic
1916 server = Connection(server_context, None)
1917 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001918
Cory Benfielde46fa842015-04-13 16:50:49 -04001919 client = Connection(client_context, None)
1920 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001921
Cory Benfielde46fa842015-04-13 16:50:49 -04001922 self._interactInMemory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001923
Cory Benfielde46fa842015-04-13 16:50:49 -04001924 self.assertEqual([(server, [b'http/1.1', b'spdy/2'])], select_args)
1925
1926 self.assertEqual(server.get_alpn_proto_negotiated(), b'spdy/2')
1927 self.assertEqual(client.get_alpn_proto_negotiated(), b'spdy/2')
Cory Benfield12eae892014-06-07 15:42:56 +01001928
Cory Benfielde46fa842015-04-13 16:50:49 -04001929 def test_alpn_set_on_connection(self):
1930 """
1931 The same as test_alpn_success, but setting the ALPN protocols on
1932 the connection rather than the context.
1933 """
1934 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001935
Cory Benfielde46fa842015-04-13 16:50:49 -04001936 def select(conn, options):
1937 select_args.append((conn, options))
1938 return b'spdy/2'
Cory Benfield12eae892014-06-07 15:42:56 +01001939
Cory Benfielde46fa842015-04-13 16:50:49 -04001940 # Setup the client context but don't set any ALPN protocols.
1941 client_context = Context(TLSv1_METHOD)
Cory Benfield12eae892014-06-07 15:42:56 +01001942
Cory Benfielde46fa842015-04-13 16:50:49 -04001943 server_context = Context(TLSv1_METHOD)
1944 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01001945
Cory Benfielde46fa842015-04-13 16:50:49 -04001946 # Necessary to actually accept the connection
1947 server_context.use_privatekey(
1948 load_privatekey(FILETYPE_PEM, server_key_pem))
1949 server_context.use_certificate(
1950 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield12eae892014-06-07 15:42:56 +01001951
Cory Benfielde46fa842015-04-13 16:50:49 -04001952 # Do a little connection to trigger the logic
1953 server = Connection(server_context, None)
1954 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001955
Cory Benfielde46fa842015-04-13 16:50:49 -04001956 # Set the ALPN protocols on the client connection.
1957 client = Connection(client_context, None)
1958 client.set_alpn_protos([b'http/1.1', b'spdy/2'])
1959 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001960
Cory Benfielde46fa842015-04-13 16:50:49 -04001961 self._interactInMemory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001962
Cory Benfielde46fa842015-04-13 16:50:49 -04001963 self.assertEqual([(server, [b'http/1.1', b'spdy/2'])], select_args)
Cory Benfield12eae892014-06-07 15:42:56 +01001964
Cory Benfielde46fa842015-04-13 16:50:49 -04001965 self.assertEqual(server.get_alpn_proto_negotiated(), b'spdy/2')
1966 self.assertEqual(client.get_alpn_proto_negotiated(), b'spdy/2')
Cory Benfield12eae892014-06-07 15:42:56 +01001967
Cory Benfielde46fa842015-04-13 16:50:49 -04001968 def test_alpn_server_fail(self):
1969 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04001970 When clients and servers cannot agree on what protocol to use next
1971 the TLS connection does not get established.
Cory Benfielde46fa842015-04-13 16:50:49 -04001972 """
1973 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001974
Cory Benfielde46fa842015-04-13 16:50:49 -04001975 def select(conn, options):
1976 select_args.append((conn, options))
1977 return b''
Cory Benfield12eae892014-06-07 15:42:56 +01001978
Cory Benfielde46fa842015-04-13 16:50:49 -04001979 client_context = Context(TLSv1_METHOD)
1980 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfield12eae892014-06-07 15:42:56 +01001981
Cory Benfielde46fa842015-04-13 16:50:49 -04001982 server_context = Context(TLSv1_METHOD)
1983 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01001984
Cory Benfielde46fa842015-04-13 16:50:49 -04001985 # Necessary to actually accept the connection
1986 server_context.use_privatekey(
1987 load_privatekey(FILETYPE_PEM, server_key_pem))
1988 server_context.use_certificate(
1989 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield12eae892014-06-07 15:42:56 +01001990
Cory Benfielde46fa842015-04-13 16:50:49 -04001991 # Do a little connection to trigger the logic
1992 server = Connection(server_context, None)
1993 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001994
Cory Benfielde46fa842015-04-13 16:50:49 -04001995 client = Connection(client_context, None)
1996 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001997
Cory Benfielde46fa842015-04-13 16:50:49 -04001998 # If the client doesn't return anything, the connection will fail.
1999 self.assertRaises(Error, self._interactInMemory, server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01002000
Cory Benfielde46fa842015-04-13 16:50:49 -04002001 self.assertEqual([(server, [b'http/1.1', b'spdy/2'])], select_args)
Cory Benfield12eae892014-06-07 15:42:56 +01002002
Cory Benfielde46fa842015-04-13 16:50:49 -04002003 def test_alpn_no_server(self):
2004 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04002005 When clients and servers cannot agree on what protocol to use next
2006 because the server doesn't offer ALPN, no protocol is negotiated.
Cory Benfielde46fa842015-04-13 16:50:49 -04002007 """
2008 client_context = Context(TLSv1_METHOD)
2009 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfielde3d57152015-04-11 17:57:35 -04002010
Cory Benfielde46fa842015-04-13 16:50:49 -04002011 server_context = Context(TLSv1_METHOD)
Cory Benfielde3d57152015-04-11 17:57:35 -04002012
Cory Benfielde46fa842015-04-13 16:50:49 -04002013 # Necessary to actually accept the connection
2014 server_context.use_privatekey(
2015 load_privatekey(FILETYPE_PEM, server_key_pem))
2016 server_context.use_certificate(
2017 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfielde3d57152015-04-11 17:57:35 -04002018
Cory Benfielde46fa842015-04-13 16:50:49 -04002019 # Do a little connection to trigger the logic
2020 server = Connection(server_context, None)
2021 server.set_accept_state()
Cory Benfielde3d57152015-04-11 17:57:35 -04002022
Cory Benfielde46fa842015-04-13 16:50:49 -04002023 client = Connection(client_context, None)
2024 client.set_connect_state()
Cory Benfielde3d57152015-04-11 17:57:35 -04002025
Cory Benfielde46fa842015-04-13 16:50:49 -04002026 # Do the dance.
2027 self._interactInMemory(server, client)
Cory Benfielde3d57152015-04-11 17:57:35 -04002028
Cory Benfielde46fa842015-04-13 16:50:49 -04002029 self.assertEqual(client.get_alpn_proto_negotiated(), b'')
Cory Benfielde3d57152015-04-11 17:57:35 -04002030
Cory Benfielde46fa842015-04-13 16:50:49 -04002031 def test_alpn_callback_exception(self):
2032 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04002033 We can handle exceptions in the ALPN select callback.
Cory Benfielde46fa842015-04-13 16:50:49 -04002034 """
2035 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002036
Cory Benfielde46fa842015-04-13 16:50:49 -04002037 def select(conn, options):
2038 select_args.append((conn, options))
Cory Benfieldef401452015-04-13 18:17:36 -04002039 raise TypeError()
Cory Benfieldf1177e72015-04-12 09:11:49 -04002040
Cory Benfielde46fa842015-04-13 16:50:49 -04002041 client_context = Context(TLSv1_METHOD)
2042 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfieldf1177e72015-04-12 09:11:49 -04002043
Cory Benfielde46fa842015-04-13 16:50:49 -04002044 server_context = Context(TLSv1_METHOD)
2045 server_context.set_alpn_select_callback(select)
Cory Benfieldf1177e72015-04-12 09:11:49 -04002046
Cory Benfielde46fa842015-04-13 16:50:49 -04002047 # Necessary to actually accept the connection
2048 server_context.use_privatekey(
2049 load_privatekey(FILETYPE_PEM, server_key_pem))
2050 server_context.use_certificate(
2051 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfieldf1177e72015-04-12 09:11:49 -04002052
Cory Benfielde46fa842015-04-13 16:50:49 -04002053 # Do a little connection to trigger the logic
2054 server = Connection(server_context, None)
2055 server.set_accept_state()
Cory Benfieldf1177e72015-04-12 09:11:49 -04002056
Cory Benfielde46fa842015-04-13 16:50:49 -04002057 client = Connection(client_context, None)
2058 client.set_connect_state()
Cory Benfieldf1177e72015-04-12 09:11:49 -04002059
Cory Benfielde46fa842015-04-13 16:50:49 -04002060 self.assertRaises(
2061 TypeError, self._interactInMemory, server, client
2062 )
2063 self.assertEqual([(server, [b'http/1.1', b'spdy/2'])], select_args)
Cory Benfieldf1177e72015-04-12 09:11:49 -04002064
Cory Benfield0f7b04c2015-04-13 17:51:12 -04002065 else:
2066 # No ALPN.
2067 def test_alpn_not_implemented(self):
Cory Benfieldef401452015-04-13 18:17:36 -04002068 """
2069 If ALPN is not in OpenSSL, we should raise NotImplementedError.
2070 """
Cory Benfield0f7b04c2015-04-13 17:51:12 -04002071 # Test the context methods first.
2072 context = Context(TLSv1_METHOD)
Cory Benfield307e9e62015-04-13 18:21:12 -04002073 self.assertRaises(
2074 NotImplementedError, context.set_alpn_protos, None
2075 )
2076 self.assertRaises(
2077 NotImplementedError, context.set_alpn_select_callback, None
2078 )
Cory Benfield0f7b04c2015-04-13 17:51:12 -04002079
2080 # Now test a connection.
2081 conn = Connection(context)
Cory Benfield307e9e62015-04-13 18:21:12 -04002082 self.assertRaises(
Alex Gaynor68417232015-09-04 07:56:29 -04002083 NotImplementedError, conn.set_alpn_protos, None
Cory Benfield307e9e62015-04-13 18:21:12 -04002084 )
Cory Benfield0f7b04c2015-04-13 17:51:12 -04002085
Cory Benfieldf1177e72015-04-12 09:11:49 -04002086
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05002087class SessionTests(TestCase):
2088 """
2089 Unit tests for :py:obj:`OpenSSL.SSL.Session`.
2090 """
2091 def test_construction(self):
2092 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002093 :py:class:`Session` can be constructed with no arguments, creating
2094 a new instance of that type.
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05002095 """
2096 new_session = Session()
2097 self.assertTrue(isinstance(new_session, Session))
2098
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05002099 def test_construction_wrong_args(self):
2100 """
2101 If any arguments are passed to :py:class:`Session`, :py:obj:`TypeError`
2102 is raised.
2103 """
2104 self.assertRaises(TypeError, Session, 123)
2105 self.assertRaises(TypeError, Session, "hello")
2106 self.assertRaises(TypeError, Session, object())
2107
2108
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002109class ConnectionTests(TestCase, _LoopbackMixin):
Rick Deane15b1472009-07-09 15:53:42 -05002110 """
Hynek Schlawackaa861212016-03-13 13:53:48 +01002111 Unit tests for :class:`OpenSSL.SSL.Connection`.
Rick Deane15b1472009-07-09 15:53:42 -05002112 """
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04002113 # XXX get_peer_certificate -> None
2114 # XXX sock_shutdown
2115 # XXX master_key -> TypeError
2116 # XXX server_random -> TypeError
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04002117 # XXX connect -> TypeError
2118 # XXX connect_ex -> TypeError
2119 # XXX set_connect_state -> TypeError
2120 # XXX set_accept_state -> TypeError
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04002121 # XXX do_handshake -> TypeError
2122 # XXX bio_read -> TypeError
2123 # XXX recv -> TypeError
2124 # XXX send -> TypeError
2125 # XXX bio_write -> TypeError
2126
Rick Deane15b1472009-07-09 15:53:42 -05002127 def test_type(self):
2128 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002129 :py:obj:`Connection` and :py:obj:`ConnectionType` refer to the same
2130 type object and can be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -05002131 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002132 self.assertIdentical(Connection, ConnectionType)
Rick Deane15b1472009-07-09 15:53:42 -05002133 ctx = Context(TLSv1_METHOD)
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002134 self.assertConsistentType(Connection, 'Connection', ctx, None)
Rick Deane15b1472009-07-09 15:53:42 -05002135
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002136 def test_get_context(self):
2137 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002138 :py:obj:`Connection.get_context` returns the :py:obj:`Context` instance
2139 used to construct the :py:obj:`Connection` instance.
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002140 """
2141 context = Context(TLSv1_METHOD)
2142 connection = Connection(context, None)
2143 self.assertIdentical(connection.get_context(), context)
2144
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002145 def test_get_context_wrong_args(self):
2146 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002147 :py:obj:`Connection.get_context` raises :py:obj:`TypeError` if called
2148 with any arguments.
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002149 """
2150 connection = Connection(Context(TLSv1_METHOD), None)
2151 self.assertRaises(TypeError, connection.get_context, None)
2152
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002153 def test_set_context_wrong_args(self):
2154 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002155 :py:obj:`Connection.set_context` raises :py:obj:`TypeError` if called
2156 with a non-:py:obj:`Context` instance argument or with any number of
2157 arguments other than 1.
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002158 """
2159 ctx = Context(TLSv1_METHOD)
2160 connection = Connection(ctx, None)
2161 self.assertRaises(TypeError, connection.set_context)
2162 self.assertRaises(TypeError, connection.set_context, object())
2163 self.assertRaises(TypeError, connection.set_context, "hello")
2164 self.assertRaises(TypeError, connection.set_context, 1)
2165 self.assertRaises(TypeError, connection.set_context, 1, 2)
2166 self.assertRaises(
2167 TypeError, connection.set_context, Context(TLSv1_METHOD), 2)
2168 self.assertIdentical(ctx, connection.get_context())
2169
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002170 def test_set_context(self):
2171 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002172 :py:obj:`Connection.set_context` specifies a new :py:obj:`Context`
2173 instance to be used for the connection.
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002174 """
2175 original = Context(SSLv23_METHOD)
2176 replacement = Context(TLSv1_METHOD)
2177 connection = Connection(original, None)
2178 connection.set_context(replacement)
2179 self.assertIdentical(replacement, connection.get_context())
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002180 # Lose our references to the contexts, just in case the Connection
2181 # isn't properly managing its own contributions to their reference
2182 # counts.
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002183 del original, replacement
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002184 collect()
2185
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002186 def test_set_tlsext_host_name_wrong_args(self):
2187 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002188 If :py:obj:`Connection.set_tlsext_host_name` is called with a non-byte
2189 string argument or a byte string with an embedded NUL or other than one
Jonathan Ballet648875f2011-07-16 14:14:58 +09002190 argument, :py:obj:`TypeError` is raised.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002191 """
2192 conn = Connection(Context(TLSv1_METHOD), None)
2193 self.assertRaises(TypeError, conn.set_tlsext_host_name)
2194 self.assertRaises(TypeError, conn.set_tlsext_host_name, object())
2195 self.assertRaises(TypeError, conn.set_tlsext_host_name, 123, 456)
2196 self.assertRaises(
2197 TypeError, conn.set_tlsext_host_name, b("with\0null"))
2198
Abraham Martinc5484ba2015-03-25 15:33:05 +00002199 if PY3:
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002200 # On Python 3.x, don't accidentally implicitly convert from text.
2201 self.assertRaises(
2202 TypeError,
2203 conn.set_tlsext_host_name, b("example.com").decode("ascii"))
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002204
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04002205 def test_get_servername_wrong_args(self):
2206 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002207 :py:obj:`Connection.get_servername` raises :py:obj:`TypeError` if
2208 called with any arguments.
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04002209 """
2210 connection = Connection(Context(TLSv1_METHOD), None)
2211 self.assertRaises(TypeError, connection.get_servername, object())
2212 self.assertRaises(TypeError, connection.get_servername, 1)
2213 self.assertRaises(TypeError, connection.get_servername, "hello")
2214
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002215 def test_pending(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002216 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002217 :py:obj:`Connection.pending` returns the number of bytes available for
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002218 immediate read.
2219 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002220 connection = Connection(Context(TLSv1_METHOD), None)
2221 self.assertEquals(connection.pending(), 0)
2222
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002223 def test_pending_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002224 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002225 :py:obj:`Connection.pending` raises :py:obj:`TypeError` if called with
2226 any arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002227 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002228 connection = Connection(Context(TLSv1_METHOD), None)
2229 self.assertRaises(TypeError, connection.pending, None)
2230
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002231 def test_peek(self):
2232 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002233 :py:obj:`Connection.recv` peeks into the connection if
2234 :py:obj:`socket.MSG_PEEK` is passed.
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002235 """
2236 server, client = self._loopback()
2237 server.send(b('xy'))
2238 self.assertEqual(client.recv(2, MSG_PEEK), b('xy'))
2239 self.assertEqual(client.recv(2, MSG_PEEK), b('xy'))
2240 self.assertEqual(client.recv(2), b('xy'))
2241
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002242 def test_connect_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002243 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002244 :py:obj:`Connection.connect` raises :py:obj:`TypeError` if called with
2245 a non-address argument or with the wrong number of arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002246 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002247 connection = Connection(Context(TLSv1_METHOD), socket())
2248 self.assertRaises(TypeError, connection.connect, None)
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002249 self.assertRaises(TypeError, connection.connect)
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002250 self.assertRaises(
2251 TypeError, connection.connect, ("127.0.0.1", 1), None
2252 )
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002253
kjavfe508d62015-09-02 12:20:35 +01002254 def test_connection_undefined_attr(self):
2255 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002256 :py:obj:`Connection.connect` raises :py:obj:`TypeError` if called with
2257 a non-address argument or with the wrong number of arguments.
kjavfe508d62015-09-02 12:20:35 +01002258 """
Alex Gaynor1aabb2e2015-09-05 13:35:18 -04002259
kjavfe508d62015-09-02 12:20:35 +01002260 def attr_access_test(connection):
2261 return connection.an_attribute_which_is_not_defined
Alex Gaynor1aabb2e2015-09-05 13:35:18 -04002262
kjavfe508d62015-09-02 12:20:35 +01002263 connection = Connection(Context(TLSv1_METHOD), None)
2264 self.assertRaises(AttributeError, attr_access_test, connection)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002265
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002266 def test_connect_refused(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002267 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002268 :py:obj:`Connection.connect` raises :py:obj:`socket.error` if the
2269 underlying socket connect method raises it.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002270 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002271 client = socket()
2272 context = Context(TLSv1_METHOD)
2273 clientSSL = Connection(context, client)
Alex Gaynor122717b2015-09-05 14:14:18 -04002274 # pytest.raises here doesn't work because of a bug in py.test on Python
2275 # 2.6: https://github.com/pytest-dev/pytest/issues/988
Alex Gaynore69c2782015-09-05 14:07:48 -04002276 try:
Alex Gaynor1aabb2e2015-09-05 13:35:18 -04002277 clientSSL.connect(("127.0.0.1", 1))
Alex Gaynore69c2782015-09-05 14:07:48 -04002278 except error as e:
Alex Gaynor20a4c082015-09-05 14:24:15 -04002279 exc = e
2280 assert exc.args[0] == ECONNREFUSED
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002281
2282 def test_connect(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002283 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002284 :py:obj:`Connection.connect` establishes a connection to the specified
2285 address.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002286 """
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002287 port = socket()
2288 port.bind(('', 0))
2289 port.listen(3)
2290
2291 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002292 clientSSL.connect(('127.0.0.1', port.getsockname()[1]))
2293 # XXX An assertion? Or something?
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002294
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002295 @pytest.mark.skipif(
2296 platform == "darwin",
2297 reason="connect_ex sometimes causes a kernel panic on OS X 10.6.4"
2298 )
2299 def test_connect_ex(self):
2300 """
2301 If there is a connection error, :py:obj:`Connection.connect_ex`
2302 returns the errno instead of raising an exception.
2303 """
2304 port = socket()
2305 port.bind(('', 0))
2306 port.listen(3)
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002307
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002308 clientSSL = Connection(Context(TLSv1_METHOD), socket())
2309 clientSSL.setblocking(False)
2310 result = clientSSL.connect_ex(port.getsockname())
2311 expected = (EINPROGRESS, EWOULDBLOCK)
2312 self.assertTrue(
2313 result in expected, "%r not in %r" % (result, expected))
Jean-Paul Calderone55d91f42010-07-29 19:22:17 -04002314
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002315 def test_accept_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002316 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002317 :py:obj:`Connection.accept` raises :py:obj:`TypeError` if called with
2318 any arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002319 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002320 connection = Connection(Context(TLSv1_METHOD), socket())
2321 self.assertRaises(TypeError, connection.accept, None)
2322
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002323 def test_accept(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002324 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002325 :py:obj:`Connection.accept` accepts a pending connection attempt and
2326 returns a tuple of a new :py:obj:`Connection` (the accepted client) and
2327 the address the connection originated from.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002328 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002329 ctx = Context(TLSv1_METHOD)
2330 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2331 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002332 port = socket()
2333 portSSL = Connection(ctx, port)
2334 portSSL.bind(('', 0))
2335 portSSL.listen(3)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002336
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002337 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002338
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002339 # Calling portSSL.getsockname() here to get the server IP address
2340 # sounds great, but frequently fails on Windows.
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002341 clientSSL.connect(('127.0.0.1', portSSL.getsockname()[1]))
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002342
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002343 serverSSL, address = portSSL.accept()
2344
2345 self.assertTrue(isinstance(serverSSL, Connection))
2346 self.assertIdentical(serverSSL.get_context(), ctx)
2347 self.assertEquals(address, clientSSL.getsockname())
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002348
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002349 def test_shutdown_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002350 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002351 :py:obj:`Connection.shutdown` raises :py:obj:`TypeError` if called with
2352 the wrong number of arguments or with arguments other than integers.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002353 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002354 connection = Connection(Context(TLSv1_METHOD), None)
2355 self.assertRaises(TypeError, connection.shutdown, None)
Jean-Paul Calderone1d3e0222010-07-29 22:52:45 -04002356 self.assertRaises(TypeError, connection.get_shutdown, None)
2357 self.assertRaises(TypeError, connection.set_shutdown)
2358 self.assertRaises(TypeError, connection.set_shutdown, None)
2359 self.assertRaises(TypeError, connection.set_shutdown, 0, 1)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002360
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002361 def test_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002362 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002363 :py:obj:`Connection.shutdown` performs an SSL-level connection
2364 shutdown.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002365 """
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002366 server, client = self._loopback()
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04002367 self.assertFalse(server.shutdown())
2368 self.assertEquals(server.get_shutdown(), SENT_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002369 self.assertRaises(ZeroReturnError, client.recv, 1024)
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04002370 self.assertEquals(client.get_shutdown(), RECEIVED_SHUTDOWN)
2371 client.shutdown()
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002372 self.assertEquals(
2373 client.get_shutdown(), SENT_SHUTDOWN | RECEIVED_SHUTDOWN
2374 )
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04002375 self.assertRaises(ZeroReturnError, server.recv, 1024)
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002376 self.assertEquals(
2377 server.get_shutdown(), SENT_SHUTDOWN | RECEIVED_SHUTDOWN
2378 )
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002379
Paul Aurichc85e0862015-01-08 08:34:33 -08002380 def test_shutdown_closed(self):
2381 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002382 If the underlying socket is closed, :py:obj:`Connection.shutdown`
2383 propagates the write error from the low level write call.
Paul Aurichc85e0862015-01-08 08:34:33 -08002384 """
2385 server, client = self._loopback()
2386 server.sock_shutdown(2)
2387 exc = self.assertRaises(SysCallError, server.shutdown)
2388 if platform == "win32":
2389 self.assertEqual(exc.args[0], ESHUTDOWN)
2390 else:
2391 self.assertEqual(exc.args[0], EPIPE)
2392
Glyph89389472015-04-14 17:29:26 -04002393 def test_shutdown_truncated(self):
Glyph6064ec32015-04-14 16:38:22 -04002394 """
Glyph89389472015-04-14 17:29:26 -04002395 If the underlying connection is truncated, :obj:`Connection.shutdown`
2396 raises an :obj:`Error`.
Glyph6064ec32015-04-14 16:38:22 -04002397 """
Glyph89389472015-04-14 17:29:26 -04002398 server_ctx = Context(TLSv1_METHOD)
2399 client_ctx = Context(TLSv1_METHOD)
2400 server_ctx.use_privatekey(
2401 load_privatekey(FILETYPE_PEM, server_key_pem))
2402 server_ctx.use_certificate(
2403 load_certificate(FILETYPE_PEM, server_cert_pem))
2404 server = Connection(server_ctx, None)
2405 client = Connection(client_ctx, None)
2406 self._handshakeInMemory(client, server)
2407 self.assertEqual(server.shutdown(), False)
2408 self.assertRaises(WantReadError, server.shutdown)
2409 server.bio_shutdown()
Glyph6064ec32015-04-14 16:38:22 -04002410 self.assertRaises(Error, server.shutdown)
2411
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002412 def test_set_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002413 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002414 :py:obj:`Connection.set_shutdown` sets the state of the SSL connection
2415 shutdown process.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002416 """
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002417 connection = Connection(Context(TLSv1_METHOD), socket())
2418 connection.set_shutdown(RECEIVED_SHUTDOWN)
2419 self.assertEquals(connection.get_shutdown(), RECEIVED_SHUTDOWN)
2420
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002421 @skip_if_py3
2422 def test_set_shutdown_long(self):
2423 """
2424 On Python 2 :py:obj:`Connection.set_shutdown` accepts an argument
2425 of type :py:obj:`long` as well as :py:obj:`int`.
2426 """
2427 connection = Connection(Context(TLSv1_METHOD), socket())
2428 connection.set_shutdown(long(RECEIVED_SHUTDOWN))
2429 self.assertEquals(connection.get_shutdown(), RECEIVED_SHUTDOWN)
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -05002430
kjavaf248592015-09-07 12:14:01 +01002431 def test_state_string(self):
2432 """
Hynek Schlawackb0274ce2015-10-16 19:56:26 +02002433 :meth:`Connection.state_string` verbosely describes the current
2434 state of the :class:`Connection`.
kjavaf248592015-09-07 12:14:01 +01002435 """
Hynek Schlawackb0274ce2015-10-16 19:56:26 +02002436 server, client = socket_pair()
kjavaf248592015-09-07 12:14:01 +01002437 server = self._loopbackServerFactory(server)
2438 client = self._loopbackClientFactory(client)
2439
Hynek Schlawackea94f2b2016-03-13 16:17:53 +01002440 assert b"before/accept initialization" == server.get_state_string()
2441 assert b"before/connect initialization" == client.get_state_string()
kjavaf248592015-09-07 12:14:01 +01002442
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002443 def test_app_data_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002444 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002445 :py:obj:`Connection.set_app_data` raises :py:obj:`TypeError` if called
2446 with other than one argument. :py:obj:`Connection.get_app_data` raises
2447 :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002448 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002449 conn = Connection(Context(TLSv1_METHOD), None)
2450 self.assertRaises(TypeError, conn.get_app_data, None)
2451 self.assertRaises(TypeError, conn.set_app_data)
2452 self.assertRaises(TypeError, conn.set_app_data, None, None)
2453
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002454 def test_app_data(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002455 """
2456 Any object can be set as app data by passing it to
Jonathan Ballet648875f2011-07-16 14:14:58 +09002457 :py:obj:`Connection.set_app_data` and later retrieved with
2458 :py:obj:`Connection.get_app_data`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002459 """
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002460 conn = Connection(Context(TLSv1_METHOD), None)
Todd Chapman4f73e4f2015-08-27 11:26:43 -04002461 assert None is conn.get_app_data()
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002462 app_data = object()
2463 conn.set_app_data(app_data)
Todd Chapman4f73e4f2015-08-27 11:26:43 -04002464 assert conn.get_app_data() is app_data
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002465
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002466 def test_makefile(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002467 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002468 :py:obj:`Connection.makefile` is not implemented and calling that
2469 method raises :py:obj:`NotImplementedError`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002470 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002471 conn = Connection(Context(TLSv1_METHOD), None)
2472 self.assertRaises(NotImplementedError, conn.makefile)
2473
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002474 def test_get_peer_cert_chain_wrong_args(self):
2475 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002476 :py:obj:`Connection.get_peer_cert_chain` raises :py:obj:`TypeError` if
2477 called with any arguments.
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002478 """
2479 conn = Connection(Context(TLSv1_METHOD), None)
2480 self.assertRaises(TypeError, conn.get_peer_cert_chain, 1)
2481 self.assertRaises(TypeError, conn.get_peer_cert_chain, "foo")
2482 self.assertRaises(TypeError, conn.get_peer_cert_chain, object())
2483 self.assertRaises(TypeError, conn.get_peer_cert_chain, [])
2484
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002485 def test_get_peer_cert_chain(self):
2486 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002487 :py:obj:`Connection.get_peer_cert_chain` returns a list of certificates
2488 which the connected server returned for the certification verification.
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002489 """
2490 chain = _create_certificate_chain()
2491 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
2492
2493 serverContext = Context(TLSv1_METHOD)
2494 serverContext.use_privatekey(skey)
2495 serverContext.use_certificate(scert)
2496 serverContext.add_extra_chain_cert(icert)
2497 serverContext.add_extra_chain_cert(cacert)
2498 server = Connection(serverContext, None)
2499 server.set_accept_state()
2500
2501 # Create the client
2502 clientContext = Context(TLSv1_METHOD)
2503 clientContext.set_verify(VERIFY_NONE, verify_cb)
2504 client = Connection(clientContext, None)
2505 client.set_connect_state()
2506
2507 self._interactInMemory(client, server)
2508
2509 chain = client.get_peer_cert_chain()
2510 self.assertEqual(len(chain), 3)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04002511 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002512 "Server Certificate", chain[0].get_subject().CN)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04002513 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002514 "Intermediate Certificate", chain[1].get_subject().CN)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04002515 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002516 "Authority Certificate", chain[2].get_subject().CN)
2517
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002518 def test_get_peer_cert_chain_none(self):
2519 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002520 :py:obj:`Connection.get_peer_cert_chain` returns :py:obj:`None` if the
2521 peer sends no certificate chain.
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002522 """
2523 ctx = Context(TLSv1_METHOD)
2524 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2525 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
2526 server = Connection(ctx, None)
2527 server.set_accept_state()
2528 client = Connection(Context(TLSv1_METHOD), None)
2529 client.set_connect_state()
2530 self._interactInMemory(client, server)
2531 self.assertIdentical(None, server.get_peer_cert_chain())
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002532
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002533 def test_get_session_wrong_args(self):
2534 """
2535 :py:obj:`Connection.get_session` raises :py:obj:`TypeError` if called
2536 with any arguments.
2537 """
2538 ctx = Context(TLSv1_METHOD)
2539 server = Connection(ctx, None)
2540 self.assertRaises(TypeError, server.get_session, 123)
2541 self.assertRaises(TypeError, server.get_session, "hello")
2542 self.assertRaises(TypeError, server.get_session, object())
2543
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002544 def test_get_session_unconnected(self):
2545 """
2546 :py:obj:`Connection.get_session` returns :py:obj:`None` when used with
2547 an object which has not been connected.
2548 """
2549 ctx = Context(TLSv1_METHOD)
2550 server = Connection(ctx, None)
2551 session = server.get_session()
2552 self.assertIdentical(None, session)
2553
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002554 def test_server_get_session(self):
2555 """
2556 On the server side of a connection, :py:obj:`Connection.get_session`
2557 returns a :py:class:`Session` instance representing the SSL session for
2558 that connection.
2559 """
2560 server, client = self._loopback()
2561 session = server.get_session()
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08002562 self.assertIsInstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002563
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002564 def test_client_get_session(self):
2565 """
2566 On the client side of a connection, :py:obj:`Connection.get_session`
2567 returns a :py:class:`Session` instance representing the SSL session for
2568 that connection.
2569 """
2570 server, client = self._loopback()
2571 session = client.get_session()
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08002572 self.assertIsInstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002573
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002574 def test_set_session_wrong_args(self):
2575 """
Hynek Schlawackdddd1112015-09-05 21:12:30 +02002576 If called with an object that is not an instance of
2577 :py:class:`Session`, or with other than one argument,
2578 :py:obj:`Connection.set_session` raises :py:obj:`TypeError`.
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002579 """
2580 ctx = Context(TLSv1_METHOD)
2581 connection = Connection(ctx, None)
2582 self.assertRaises(TypeError, connection.set_session)
2583 self.assertRaises(TypeError, connection.set_session, 123)
2584 self.assertRaises(TypeError, connection.set_session, "hello")
2585 self.assertRaises(TypeError, connection.set_session, object())
2586 self.assertRaises(
2587 TypeError, connection.set_session, Session(), Session())
2588
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002589 def test_client_set_session(self):
2590 """
2591 :py:obj:`Connection.set_session`, when used prior to a connection being
2592 established, accepts a :py:class:`Session` instance and causes an
2593 attempt to re-use the session it represents when the SSL handshake is
2594 performed.
2595 """
2596 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2597 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
2598 ctx = Context(TLSv1_METHOD)
2599 ctx.use_privatekey(key)
2600 ctx.use_certificate(cert)
2601 ctx.set_session_id("unity-test")
2602
2603 def makeServer(socket):
2604 server = Connection(ctx, socket)
2605 server.set_accept_state()
2606 return server
2607
2608 originalServer, originalClient = self._loopback(
2609 serverFactory=makeServer)
2610 originalSession = originalClient.get_session()
2611
2612 def makeClient(socket):
2613 client = self._loopbackClientFactory(socket)
2614 client.set_session(originalSession)
2615 return client
2616 resumedServer, resumedClient = self._loopback(
2617 serverFactory=makeServer,
2618 clientFactory=makeClient)
2619
2620 # This is a proxy: in general, we have no access to any unique
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002621 # identifier for the session (new enough versions of OpenSSL expose
2622 # a hash which could be usable, but "new enough" is very, very new).
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002623 # Instead, exploit the fact that the master key is re-used if the
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002624 # session is re-used. As long as the master key for the two
2625 # connections is the same, the session was re-used!
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002626 self.assertEqual(
2627 originalServer.master_key(), resumedServer.master_key())
2628
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002629 def test_set_session_wrong_method(self):
2630 """
Jean-Paul Calderone068cb592012-02-14 16:52:43 -05002631 If :py:obj:`Connection.set_session` is passed a :py:class:`Session`
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002632 instance associated with a context using a different SSL method than
2633 the :py:obj:`Connection` is using, a :py:class:`OpenSSL.SSL.Error` is
Jean-Paul Calderone068cb592012-02-14 16:52:43 -05002634 raised.
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002635 """
2636 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2637 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
2638 ctx = Context(TLSv1_METHOD)
2639 ctx.use_privatekey(key)
2640 ctx.use_certificate(cert)
2641 ctx.set_session_id("unity-test")
2642
2643 def makeServer(socket):
2644 server = Connection(ctx, socket)
2645 server.set_accept_state()
2646 return server
2647
2648 originalServer, originalClient = self._loopback(
2649 serverFactory=makeServer)
2650 originalSession = originalClient.get_session()
2651
2652 def makeClient(socket):
2653 # Intentionally use a different, incompatible method here.
2654 client = Connection(Context(SSLv3_METHOD), socket)
2655 client.set_connect_state()
2656 client.set_session(originalSession)
2657 return client
2658
2659 self.assertRaises(
2660 Error,
2661 self._loopback, clientFactory=makeClient, serverFactory=makeServer)
2662
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002663 def test_wantWriteError(self):
2664 """
2665 :py:obj:`Connection` methods which generate output raise
2666 :py:obj:`OpenSSL.SSL.WantWriteError` if writing to the connection's BIO
2667 fail indicating a should-write state.
2668 """
2669 client_socket, server_socket = socket_pair()
2670 # Fill up the client's send buffer so Connection won't be able to write
Jean-Paul Calderonebbff8b92014-03-22 14:20:30 -04002671 # anything. Only write a single byte at a time so we can be sure we
2672 # completely fill the buffer. Even though the socket API is allowed to
2673 # signal a short write via its return value it seems this doesn't
2674 # always happen on all platforms (FreeBSD and OS X particular) for the
2675 # very last bit of available buffer space.
2676 msg = b"x"
2677 for i in range(1024 * 1024 * 4):
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002678 try:
2679 client_socket.send(msg)
2680 except error as e:
2681 if e.errno == EWOULDBLOCK:
2682 break
2683 raise
2684 else:
2685 self.fail(
2686 "Failed to fill socket buffer, cannot test BIO want write")
2687
2688 ctx = Context(TLSv1_METHOD)
2689 conn = Connection(ctx, client_socket)
2690 # Client's speak first, so make it an SSL client
2691 conn.set_connect_state()
2692 self.assertRaises(WantWriteError, conn.do_handshake)
2693
2694 # XXX want_read
2695
Fedor Brunner416f4a12014-03-28 13:18:38 +01002696 def test_get_finished_before_connect(self):
Fedor Brunner5747b932014-03-05 14:22:34 +01002697 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002698 :py:obj:`Connection.get_finished` returns :py:obj:`None` before TLS
2699 handshake is completed.
Fedor Brunner5747b932014-03-05 14:22:34 +01002700 """
Fedor Brunner5747b932014-03-05 14:22:34 +01002701 ctx = Context(TLSv1_METHOD)
2702 connection = Connection(ctx, None)
2703 self.assertEqual(connection.get_finished(), None)
Fedor Brunner416f4a12014-03-28 13:18:38 +01002704
2705 def test_get_peer_finished_before_connect(self):
2706 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002707 :py:obj:`Connection.get_peer_finished` returns :py:obj:`None` before
2708 TLS handshake is completed.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002709 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002710 ctx = Context(TLSv1_METHOD)
2711 connection = Connection(ctx, None)
Fedor Brunner5747b932014-03-05 14:22:34 +01002712 self.assertEqual(connection.get_peer_finished(), None)
2713
Fedor Brunner416f4a12014-03-28 13:18:38 +01002714 def test_get_finished(self):
2715 """
2716 :py:obj:`Connection.get_finished` method returns the TLS Finished
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002717 message send from client, or server. Finished messages are send during
2718 TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002719 """
2720
Fedor Brunner5747b932014-03-05 14:22:34 +01002721 server, client = self._loopback()
2722
2723 self.assertNotEqual(server.get_finished(), None)
2724 self.assertTrue(len(server.get_finished()) > 0)
Fedor Brunner416f4a12014-03-28 13:18:38 +01002725
2726 def test_get_peer_finished(self):
2727 """
2728 :py:obj:`Connection.get_peer_finished` method returns the TLS Finished
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002729 message received from client, or server. Finished messages are send
2730 during TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002731 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002732 server, client = self._loopback()
2733
2734 self.assertNotEqual(server.get_peer_finished(), None)
Fedor Brunner5747b932014-03-05 14:22:34 +01002735 self.assertTrue(len(server.get_peer_finished()) > 0)
2736
Fedor Brunner416f4a12014-03-28 13:18:38 +01002737 def test_tls_finished_message_symmetry(self):
2738 """
Hynek Schlawackdddd1112015-09-05 21:12:30 +02002739 The TLS Finished message send by server must be the TLS Finished
2740 message received by client.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002741
Hynek Schlawackdddd1112015-09-05 21:12:30 +02002742 The TLS Finished message send by client must be the TLS Finished
2743 message received by server.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002744 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002745 server, client = self._loopback()
2746
Fedor Brunner5747b932014-03-05 14:22:34 +01002747 self.assertEqual(server.get_finished(), client.get_peer_finished())
2748 self.assertEqual(client.get_finished(), server.get_peer_finished())
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002749
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002750 def test_get_cipher_name_before_connect(self):
2751 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002752 :py:obj:`Connection.get_cipher_name` returns :py:obj:`None` if no
2753 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002754 """
2755 ctx = Context(TLSv1_METHOD)
2756 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002757 self.assertIdentical(conn.get_cipher_name(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002758
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002759 def test_get_cipher_name(self):
2760 """
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002761 :py:obj:`Connection.get_cipher_name` returns a :py:class:`unicode`
2762 string giving the name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002763 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002764 server, client = self._loopback()
2765 server_cipher_name, client_cipher_name = \
2766 server.get_cipher_name(), client.get_cipher_name()
2767
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002768 self.assertIsInstance(server_cipher_name, text_type)
2769 self.assertIsInstance(client_cipher_name, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002770
2771 self.assertEqual(server_cipher_name, client_cipher_name)
2772
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002773 def test_get_cipher_version_before_connect(self):
2774 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002775 :py:obj:`Connection.get_cipher_version` returns :py:obj:`None` if no
2776 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002777 """
2778 ctx = Context(TLSv1_METHOD)
2779 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002780 self.assertIdentical(conn.get_cipher_version(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002781
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002782 def test_get_cipher_version(self):
2783 """
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002784 :py:obj:`Connection.get_cipher_version` returns a :py:class:`unicode`
2785 string giving the protocol name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002786 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002787 server, client = self._loopback()
2788 server_cipher_version, client_cipher_version = \
2789 server.get_cipher_version(), client.get_cipher_version()
2790
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002791 self.assertIsInstance(server_cipher_version, text_type)
2792 self.assertIsInstance(client_cipher_version, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002793
2794 self.assertEqual(server_cipher_version, client_cipher_version)
2795
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002796 def test_get_cipher_bits_before_connect(self):
2797 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002798 :py:obj:`Connection.get_cipher_bits` returns :py:obj:`None` if no
2799 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002800 """
2801 ctx = Context(TLSv1_METHOD)
2802 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002803 self.assertIdentical(conn.get_cipher_bits(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002804
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002805 def test_get_cipher_bits(self):
2806 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002807 :py:obj:`Connection.get_cipher_bits` returns the number of secret bits
2808 of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002809 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002810 server, client = self._loopback()
2811 server_cipher_bits, client_cipher_bits = \
2812 server.get_cipher_bits(), client.get_cipher_bits()
2813
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002814 self.assertIsInstance(server_cipher_bits, int)
2815 self.assertIsInstance(client_cipher_bits, int)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002816
2817 self.assertEqual(server_cipher_bits, client_cipher_bits)
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002818
Jim Shaverabff1882015-05-27 09:15:55 -04002819 def test_get_protocol_version_name(self):
2820 """
2821 :py:obj:`Connection.get_protocol_version_name()` returns a string
2822 giving the protocol version of the current connection.
2823 """
2824 server, client = self._loopback()
2825 client_protocol_version_name = client.get_protocol_version_name()
2826 server_protocol_version_name = server.get_protocol_version_name()
2827
Jim Shaver58d25732015-05-28 11:52:32 -04002828 self.assertIsInstance(server_protocol_version_name, text_type)
2829 self.assertIsInstance(client_protocol_version_name, text_type)
Jim Shaverabff1882015-05-27 09:15:55 -04002830
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002831 self.assertEqual(
2832 server_protocol_version_name, client_protocol_version_name
2833 )
Jim Shaverabff1882015-05-27 09:15:55 -04002834
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002835 def test_get_protocol_version(self):
2836 """
Alex Gaynor43307782015-09-04 09:05:45 -04002837 :py:obj:`Connection.get_protocol_version()` returns an integer
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002838 giving the protocol version of the current connection.
2839 """
2840 server, client = self._loopback()
Jim Shaver85a4dff2015-04-27 17:42:46 -04002841 client_protocol_version = client.get_protocol_version()
2842 server_protocol_version = server.get_protocol_version()
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002843
Jim Shaverabff1882015-05-27 09:15:55 -04002844 self.assertIsInstance(server_protocol_version, int)
2845 self.assertIsInstance(client_protocol_version, int)
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002846
2847 self.assertEqual(server_protocol_version, client_protocol_version)
2848
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002849
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002850class ConnectionGetCipherListTests(TestCase):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002851 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002852 Tests for :py:obj:`Connection.get_cipher_list`.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002853 """
Jean-Paul Calderone54a2bc02010-09-09 17:52:38 -04002854 def test_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002855 """
Hynek Schlawackdddd1112015-09-05 21:12:30 +02002856 :py:obj:`Connection.get_cipher_list` raises :py:obj:`TypeError` if
2857 called with any arguments.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002858 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002859 connection = Connection(Context(TLSv1_METHOD), None)
2860 self.assertRaises(TypeError, connection.get_cipher_list, None)
2861
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002862 def test_result(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002863 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002864 :py:obj:`Connection.get_cipher_list` returns a :py:obj:`list` of
2865 :py:obj:`bytes` giving the names of the ciphers which might be used.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002866 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002867 connection = Connection(Context(TLSv1_METHOD), None)
2868 ciphers = connection.get_cipher_list()
2869 self.assertTrue(isinstance(ciphers, list))
2870 for cipher in ciphers:
2871 self.assertTrue(isinstance(cipher, str))
2872
2873
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002874class ConnectionSendTests(TestCase, _LoopbackMixin):
2875 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002876 Tests for :py:obj:`Connection.send`
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002877 """
2878 def test_wrong_args(self):
2879 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002880 When called with arguments other than string argument for its first
2881 parameter or more than two arguments, :py:obj:`Connection.send` raises
2882 :py:obj:`TypeError`.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002883 """
2884 connection = Connection(Context(TLSv1_METHOD), None)
Jean-Paul Calderone77fa2602011-01-05 18:23:39 -05002885 self.assertRaises(TypeError, connection.send)
2886 self.assertRaises(TypeError, connection.send, object())
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002887 self.assertRaises(TypeError, connection.send, "foo", object(), "bar")
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002888
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002889 def test_short_bytes(self):
2890 """
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002891 When passed a short byte string, :py:obj:`Connection.send` transmits
2892 all of it and returns the number of bytes sent.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002893 """
2894 server, client = self._loopback()
2895 count = server.send(b('xy'))
2896 self.assertEquals(count, 2)
2897 self.assertEquals(client.recv(2), b('xy'))
2898
Abraham Martinef063482015-03-25 14:06:24 +00002899 def test_text(self):
2900 """
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002901 When passed a text, :py:obj:`Connection.send` transmits all of it and
2902 returns the number of bytes sent. It also raises a DeprecationWarning.
Abraham Martinef063482015-03-25 14:06:24 +00002903 """
2904 server, client = self._loopback()
2905 with catch_warnings(record=True) as w:
2906 simplefilter("always")
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002907 count = server.send(b"xy".decode("ascii"))
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002908 self.assertEqual(
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002909 "{0} for buf is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002910 WARNING_TYPE_EXPECTED
2911 ),
2912 str(w[-1].message)
2913 )
2914 self.assertIs(w[-1].category, DeprecationWarning)
Abraham Martinef063482015-03-25 14:06:24 +00002915 self.assertEquals(count, 2)
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002916 self.assertEquals(client.recv(2), b"xy")
Abraham Martinef063482015-03-25 14:06:24 +00002917
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002918 @skip_if_py26
2919 def test_short_memoryview(self):
2920 """
2921 When passed a memoryview onto a small number of bytes,
2922 :py:obj:`Connection.send` transmits all of them and returns the number
2923 of bytes sent.
2924 """
2925 server, client = self._loopback()
2926 count = server.send(memoryview(b('xy')))
2927 self.assertEquals(count, 2)
2928 self.assertEquals(client.recv(2), b('xy'))
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002929
Hynek Schlawack8e94f1b2015-09-05 21:31:00 +02002930 @skip_if_py3
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002931 def test_short_buffer(self):
2932 """
2933 When passed a buffer containing a small number of bytes,
2934 :py:obj:`Connection.send` transmits all of them and returns the number
2935 of bytes sent.
2936 """
2937 server, client = self._loopback()
2938 count = server.send(buffer(b('xy')))
2939 self.assertEquals(count, 2)
2940 self.assertEquals(client.recv(2), b('xy'))
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02002941
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05002942
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002943def _make_memoryview(size):
2944 """
2945 Create a new ``memoryview`` wrapped around a ``bytearray`` of the given
2946 size.
2947 """
2948 return memoryview(bytearray(size))
2949
2950
Cory Benfield62d10332014-06-15 10:03:41 +01002951class ConnectionRecvIntoTests(TestCase, _LoopbackMixin):
2952 """
2953 Tests for :py:obj:`Connection.recv_into`
2954 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002955 def _no_length_test(self, factory):
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04002956 """
2957 Assert that when the given buffer is passed to
2958 ``Connection.recv_into``, whatever bytes are available to be received
2959 that fit into that buffer are written into that buffer.
2960 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002961 output_buffer = factory(5)
2962
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04002963 server, client = self._loopback()
2964 server.send(b('xy'))
2965
Jean-Paul Calderone320af1e2015-03-15 17:20:13 -04002966 self.assertEqual(client.recv_into(output_buffer), 2)
2967 self.assertEqual(output_buffer, bytearray(b('xy\x00\x00\x00')))
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04002968
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002969 def test_bytearray_no_length(self):
Cory Benfield62d10332014-06-15 10:03:41 +01002970 """
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04002971 :py:obj:`Connection.recv_into` can be passed a ``bytearray`` instance
2972 and data in the receive buffer is written to it.
Cory Benfield62d10332014-06-15 10:03:41 +01002973 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002974 self._no_length_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01002975
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002976 def _respects_length_test(self, factory):
Cory Benfield62d10332014-06-15 10:03:41 +01002977 """
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002978 Assert that when the given buffer is passed to ``Connection.recv_into``
2979 along with a value for ``nbytes`` that is less than the size of that
2980 buffer, only ``nbytes`` bytes are written into the buffer.
Cory Benfield62d10332014-06-15 10:03:41 +01002981 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002982 output_buffer = factory(10)
2983
Cory Benfield62d10332014-06-15 10:03:41 +01002984 server, client = self._loopback()
2985 server.send(b('abcdefghij'))
Cory Benfield62d10332014-06-15 10:03:41 +01002986
Jean-Paul Calderone320af1e2015-03-15 17:20:13 -04002987 self.assertEqual(client.recv_into(output_buffer, 5), 5)
2988 self.assertEqual(
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002989 output_buffer, bytearray(b('abcde\x00\x00\x00\x00\x00'))
2990 )
2991
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002992 def test_bytearray_respects_length(self):
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002993 """
2994 When called with a ``bytearray`` instance,
2995 :py:obj:`Connection.recv_into` respects the ``nbytes`` parameter and
2996 doesn't copy in more than that number of bytes.
2997 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002998 self._respects_length_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01002999
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003000 def _doesnt_overfill_test(self, factory):
Cory Benfield62d10332014-06-15 10:03:41 +01003001 """
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04003002 Assert that if there are more bytes available to be read from the
3003 receive buffer than would fit into the buffer passed to
3004 :py:obj:`Connection.recv_into`, only as many as fit are written into
3005 it.
Cory Benfield62d10332014-06-15 10:03:41 +01003006 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003007 output_buffer = factory(5)
3008
Cory Benfield62d10332014-06-15 10:03:41 +01003009 server, client = self._loopback()
3010 server.send(b('abcdefghij'))
Cory Benfield62d10332014-06-15 10:03:41 +01003011
Jean-Paul Calderone320af1e2015-03-15 17:20:13 -04003012 self.assertEqual(client.recv_into(output_buffer), 5)
3013 self.assertEqual(output_buffer, bytearray(b('abcde')))
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04003014 rest = client.recv(5)
3015 self.assertEqual(b('fghij'), rest)
3016
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04003017 def test_bytearray_doesnt_overfill(self):
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04003018 """
3019 When called with a ``bytearray`` instance,
3020 :py:obj:`Connection.recv_into` respects the size of the array and
3021 doesn't write more bytes into it than will fit.
3022 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003023 self._doesnt_overfill_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01003024
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04003025 def test_bytearray_really_doesnt_overfill(self):
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003026 """
3027 When called with a ``bytearray`` instance and an ``nbytes`` value that
3028 is too large, :py:obj:`Connection.recv_into` respects the size of the
3029 array and not the ``nbytes`` value and doesn't write more bytes into
3030 the buffer than will fit.
3031 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003032 self._doesnt_overfill_test(bytearray)
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003033
Maximilian Hils1d95dea2015-08-17 19:27:20 +02003034 def test_peek(self):
3035
3036 server, client = self._loopback()
3037 server.send(b('xy'))
3038
3039 for _ in range(2):
3040 output_buffer = bytearray(5)
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003041 self.assertEqual(
3042 client.recv_into(output_buffer, flags=MSG_PEEK), 2)
Maximilian Hils1d95dea2015-08-17 19:27:20 +02003043 self.assertEqual(output_buffer, bytearray(b('xy\x00\x00\x00')))
3044
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003045 @skip_if_py26
3046 def test_memoryview_no_length(self):
3047 """
3048 :py:obj:`Connection.recv_into` can be passed a ``memoryview``
3049 instance and data in the receive buffer is written to it.
3050 """
3051 self._no_length_test(_make_memoryview)
Maximilian Hils1d95dea2015-08-17 19:27:20 +02003052
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003053 @skip_if_py26
3054 def test_memoryview_respects_length(self):
3055 """
3056 When called with a ``memoryview`` instance,
3057 :py:obj:`Connection.recv_into` respects the ``nbytes`` parameter
3058 and doesn't copy more than that number of bytes in.
3059 """
3060 self._respects_length_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01003061
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003062 @skip_if_py26
3063 def test_memoryview_doesnt_overfill(self):
3064 """
3065 When called with a ``memoryview`` instance,
3066 :py:obj:`Connection.recv_into` respects the size of the array and
3067 doesn't write more bytes into it than will fit.
3068 """
3069 self._doesnt_overfill_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01003070
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003071 @skip_if_py26
3072 def test_memoryview_really_doesnt_overfill(self):
3073 """
3074 When called with a ``memoryview`` instance and an ``nbytes`` value
3075 that is too large, :py:obj:`Connection.recv_into` respects the size
3076 of the array and not the ``nbytes`` value and doesn't write more
3077 bytes into the buffer than will fit.
3078 """
3079 self._doesnt_overfill_test(_make_memoryview)
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003080
Cory Benfield62d10332014-06-15 10:03:41 +01003081
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003082class ConnectionSendallTests(TestCase, _LoopbackMixin):
3083 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003084 Tests for :py:obj:`Connection.sendall`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003085 """
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003086 def test_wrong_args(self):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003087 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003088 When called with arguments other than a string argument for its first
3089 parameter or with more than two arguments, :py:obj:`Connection.sendall`
3090 raises :py:obj:`TypeError`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003091 """
3092 connection = Connection(Context(TLSv1_METHOD), None)
3093 self.assertRaises(TypeError, connection.sendall)
3094 self.assertRaises(TypeError, connection.sendall, object())
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003095 self.assertRaises(
3096 TypeError, connection.sendall, "foo", object(), "bar")
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003097
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003098 def test_short(self):
3099 """
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003100 :py:obj:`Connection.sendall` transmits all of the bytes in the string
3101 passed to it.
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003102 """
3103 server, client = self._loopback()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04003104 server.sendall(b('x'))
3105 self.assertEquals(client.recv(1), b('x'))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003106
Abraham Martinef063482015-03-25 14:06:24 +00003107 def test_text(self):
3108 """
Jean-Paul Calderone93477422015-04-13 20:38:57 -04003109 :py:obj:`Connection.sendall` transmits all the content in the string
3110 passed to it raising a DeprecationWarning in case of this being a text.
Abraham Martinef063482015-03-25 14:06:24 +00003111 """
3112 server, client = self._loopback()
3113 with catch_warnings(record=True) as w:
3114 simplefilter("always")
Jean-Paul Calderone8dc37a12015-03-29 08:16:52 -04003115 server.sendall(b"x".decode("ascii"))
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04003116 self.assertEqual(
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04003117 "{0} for buf is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04003118 WARNING_TYPE_EXPECTED
3119 ),
3120 str(w[-1].message)
3121 )
3122 self.assertIs(w[-1].category, DeprecationWarning)
3123 self.assertEquals(client.recv(1), b"x")
Abraham Martinef063482015-03-25 14:06:24 +00003124
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003125 @skip_if_py26
3126 def test_short_memoryview(self):
3127 """
3128 When passed a memoryview onto a small number of bytes,
3129 :py:obj:`Connection.sendall` transmits all of them.
3130 """
3131 server, client = self._loopback()
3132 server.sendall(memoryview(b('x')))
3133 self.assertEquals(client.recv(1), b('x'))
Abraham Martinef063482015-03-25 14:06:24 +00003134
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003135 @skip_if_py3
3136 def test_short_buffers(self):
3137 """
3138 When passed a buffer containing a small number of bytes,
3139 :py:obj:`Connection.sendall` transmits all of them.
3140 """
3141 server, client = self._loopback()
3142 server.sendall(buffer(b('x')))
3143 self.assertEquals(client.recv(1), b('x'))
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02003144
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003145 def test_long(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003146 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003147 :py:obj:`Connection.sendall` transmits all of the bytes in the string
3148 passed to it even if this requires multiple calls of an underlying
3149 write function.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003150 """
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003151 server, client = self._loopback()
Jean-Paul Calderone6241c702010-09-16 19:59:24 -04003152 # Should be enough, underlying SSL_write should only do 16k at a time.
Hynek Schlawack35618382015-09-05 21:54:25 +02003153 # On Windows, after 32k of bytes the write will block (forever
3154 # - because no one is yet reading).
Jean-Paul Calderone9e4c1352010-09-19 09:34:43 -04003155 message = b('x') * (1024 * 32 - 1) + b('y')
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003156 server.sendall(message)
3157 accum = []
3158 received = 0
3159 while received < len(message):
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04003160 data = client.recv(1024)
3161 accum.append(data)
3162 received += len(data)
Jean-Paul Calderonef4047852010-09-19 09:45:57 -04003163 self.assertEquals(message, b('').join(accum))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003164
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003165 def test_closed(self):
3166 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003167 If the underlying socket is closed, :py:obj:`Connection.sendall`
3168 propagates the write error from the low level write call.
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003169 """
3170 server, client = self._loopback()
Jean-Paul Calderone05d43e82010-09-24 18:01:36 -04003171 server.sock_shutdown(2)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003172 exc = self.assertRaises(SysCallError, server.sendall, b"hello, world")
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +02003173 if platform == "win32":
3174 self.assertEqual(exc.args[0], ESHUTDOWN)
3175 else:
3176 self.assertEqual(exc.args[0], EPIPE)
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003177
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003178
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003179class ConnectionRenegotiateTests(TestCase, _LoopbackMixin):
3180 """
3181 Tests for SSL renegotiation APIs.
3182 """
3183 def test_renegotiate_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003184 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003185 :py:obj:`Connection.renegotiate` raises :py:obj:`TypeError` if called
3186 with any arguments.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003187 """
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003188 connection = Connection(Context(TLSv1_METHOD), None)
3189 self.assertRaises(TypeError, connection.renegotiate, None)
3190
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003191 def test_total_renegotiations_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003192 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003193 :py:obj:`Connection.total_renegotiations` raises :py:obj:`TypeError` if
3194 called with any arguments.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003195 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003196 connection = Connection(Context(TLSv1_METHOD), None)
3197 self.assertRaises(TypeError, connection.total_renegotiations, None)
3198
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003199 def test_total_renegotiations(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003200 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003201 :py:obj:`Connection.total_renegotiations` returns :py:obj:`0` before
3202 any renegotiations have happened.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003203 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003204 connection = Connection(Context(TLSv1_METHOD), None)
3205 self.assertEquals(connection.total_renegotiations(), 0)
3206
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003207 def test_renegotiate(self):
3208 """
3209 Go through a complete renegotiation cycle.
3210 """
3211 server, client = self._loopback()
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003212
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003213 server.send(b"hello world")
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003214
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003215 assert b"hello world" == client.recv(len(b"hello world"))
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003216
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003217 assert 0 == server.total_renegotiations()
3218 assert False is server.renegotiate_pending()
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003219
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003220 assert True is server.renegotiate()
3221
3222 assert True is server.renegotiate_pending()
3223
3224 server.setblocking(False)
3225 client.setblocking(False)
3226
3227 client.do_handshake()
3228 server.do_handshake()
3229
3230 assert 1 == server.total_renegotiations()
3231 while False is server.renegotiate_pending():
3232 pass
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003233
3234
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003235class ErrorTests(TestCase):
3236 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003237 Unit tests for :py:obj:`OpenSSL.SSL.Error`.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003238 """
3239 def test_type(self):
3240 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003241 :py:obj:`Error` is an exception type.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003242 """
3243 self.assertTrue(issubclass(Error, Exception))
Rick Deane15b1472009-07-09 15:53:42 -05003244 self.assertEqual(Error.__name__, 'Error')
Rick Deane15b1472009-07-09 15:53:42 -05003245
3246
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003247class ConstantsTests(TestCase):
3248 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003249 Tests for the values of constants exposed in :py:obj:`OpenSSL.SSL`.
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003250
3251 These are values defined by OpenSSL intended only to be used as flags to
3252 OpenSSL APIs. The only assertions it seems can be made about them is
3253 their values.
3254 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003255 @pytest.mark.skipif(
3256 OP_NO_QUERY_MTU is None,
3257 reason="OP_NO_QUERY_MTU unavailable - OpenSSL version may be too old"
3258 )
3259 def test_op_no_query_mtu(self):
3260 """
3261 The value of :py:obj:`OpenSSL.SSL.OP_NO_QUERY_MTU` is 0x1000, the value
3262 of :py:const:`SSL_OP_NO_QUERY_MTU` defined by :file:`openssl/ssl.h`.
3263 """
3264 self.assertEqual(OP_NO_QUERY_MTU, 0x1000)
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003265
Hynek Schlawack35618382015-09-05 21:54:25 +02003266 @pytest.mark.skipif(
3267 OP_COOKIE_EXCHANGE is None,
3268 reason="OP_COOKIE_EXCHANGE unavailable - "
3269 "OpenSSL version may be too old"
3270 )
3271 def test_op_cookie_exchange(self):
3272 """
3273 The value of :py:obj:`OpenSSL.SSL.OP_COOKIE_EXCHANGE` is 0x2000, the
3274 value of :py:const:`SSL_OP_COOKIE_EXCHANGE` defined by
3275 :file:`openssl/ssl.h`.
3276 """
3277 self.assertEqual(OP_COOKIE_EXCHANGE, 0x2000)
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003278
Hynek Schlawack35618382015-09-05 21:54:25 +02003279 @pytest.mark.skipif(
3280 OP_NO_TICKET is None,
3281 reason="OP_NO_TICKET unavailable - OpenSSL version may be too old"
3282 )
3283 def test_op_no_ticket(self):
3284 """
3285 The value of :py:obj:`OpenSSL.SSL.OP_NO_TICKET` is 0x4000, the value of
3286 :py:const:`SSL_OP_NO_TICKET` defined by :file:`openssl/ssl.h`.
3287 """
3288 self.assertEqual(OP_NO_TICKET, 0x4000)
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003289
Hynek Schlawack35618382015-09-05 21:54:25 +02003290 @pytest.mark.skipif(
3291 OP_NO_COMPRESSION is None,
3292 reason="OP_NO_COMPRESSION unavailable - OpenSSL version may be too old"
3293 )
3294 def test_op_no_compression(self):
3295 """
3296 The value of :py:obj:`OpenSSL.SSL.OP_NO_COMPRESSION` is 0x20000, the
3297 value of :py:const:`SSL_OP_NO_COMPRESSION` defined by
3298 :file:`openssl/ssl.h`.
3299 """
3300 self.assertEqual(OP_NO_COMPRESSION, 0x20000)
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04003301
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003302 def test_sess_cache_off(self):
3303 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003304 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_OFF` 0x0, the value of
3305 :py:obj:`SSL_SESS_CACHE_OFF` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003306 """
3307 self.assertEqual(0x0, SESS_CACHE_OFF)
3308
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003309 def test_sess_cache_client(self):
3310 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003311 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_CLIENT` 0x1, the value of
3312 :py:obj:`SSL_SESS_CACHE_CLIENT` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003313 """
3314 self.assertEqual(0x1, SESS_CACHE_CLIENT)
3315
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003316 def test_sess_cache_server(self):
3317 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003318 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_SERVER` 0x2, the value of
3319 :py:obj:`SSL_SESS_CACHE_SERVER` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003320 """
3321 self.assertEqual(0x2, SESS_CACHE_SERVER)
3322
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003323 def test_sess_cache_both(self):
3324 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003325 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_BOTH` 0x3, the value of
3326 :py:obj:`SSL_SESS_CACHE_BOTH` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003327 """
3328 self.assertEqual(0x3, SESS_CACHE_BOTH)
3329
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003330 def test_sess_cache_no_auto_clear(self):
3331 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003332 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_AUTO_CLEAR` 0x80, the
3333 value of :py:obj:`SSL_SESS_CACHE_NO_AUTO_CLEAR` defined by
3334 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003335 """
3336 self.assertEqual(0x80, SESS_CACHE_NO_AUTO_CLEAR)
3337
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003338 def test_sess_cache_no_internal_lookup(self):
3339 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003340 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_LOOKUP` 0x100,
3341 the value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL_LOOKUP` defined by
3342 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003343 """
3344 self.assertEqual(0x100, SESS_CACHE_NO_INTERNAL_LOOKUP)
3345
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003346 def test_sess_cache_no_internal_store(self):
3347 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003348 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_STORE` 0x200,
3349 the value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL_STORE` defined by
3350 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003351 """
3352 self.assertEqual(0x200, SESS_CACHE_NO_INTERNAL_STORE)
3353
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003354 def test_sess_cache_no_internal(self):
3355 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003356 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL` 0x300, the
3357 value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL` defined by
3358 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003359 """
3360 self.assertEqual(0x300, SESS_CACHE_NO_INTERNAL)
3361
3362
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003363class MemoryBIOTests(TestCase, _LoopbackMixin):
Rick Deanb71c0d22009-04-01 14:09:23 -05003364 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003365 Tests for :py:obj:`OpenSSL.SSL.Connection` using a memory BIO.
Rick Deanb71c0d22009-04-01 14:09:23 -05003366 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003367 def _server(self, sock):
3368 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003369 Create a new server-side SSL :py:obj:`Connection` object wrapped around
3370 :py:obj:`sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003371 """
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003372 # Create the server side Connection. This is mostly setup boilerplate
3373 # - use TLSv1, use a particular certificate, etc.
3374 server_ctx = Context(TLSv1_METHOD)
Alex Gaynor43307782015-09-04 09:05:45 -04003375 server_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE)
Hynek Schlawack35618382015-09-05 21:54:25 +02003376 server_ctx.set_verify(
3377 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT | VERIFY_CLIENT_ONCE,
3378 verify_cb
3379 )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003380 server_store = server_ctx.get_cert_store()
Hynek Schlawack35618382015-09-05 21:54:25 +02003381 server_ctx.use_privatekey(
3382 load_privatekey(FILETYPE_PEM, server_key_pem))
3383 server_ctx.use_certificate(
3384 load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003385 server_ctx.check_privatekey()
3386 server_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Hynek Schlawack35618382015-09-05 21:54:25 +02003387 # Here the Connection is actually created. If None is passed as the
3388 # 2nd parameter, it indicates a memory BIO should be created.
Rick Deanb1ccd562009-07-09 23:52:39 -05003389 server_conn = Connection(server_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003390 server_conn.set_accept_state()
3391 return server_conn
3392
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003393 def _client(self, sock):
3394 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003395 Create a new client-side SSL :py:obj:`Connection` object wrapped around
3396 :py:obj:`sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003397 """
3398 # Now create the client side Connection. Similar boilerplate to the
3399 # above.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003400 client_ctx = Context(TLSv1_METHOD)
Alex Gaynor43307782015-09-04 09:05:45 -04003401 client_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE)
Hynek Schlawack35618382015-09-05 21:54:25 +02003402 client_ctx.set_verify(
3403 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT | VERIFY_CLIENT_ONCE,
3404 verify_cb
3405 )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003406 client_store = client_ctx.get_cert_store()
Hynek Schlawack35618382015-09-05 21:54:25 +02003407 client_ctx.use_privatekey(
3408 load_privatekey(FILETYPE_PEM, client_key_pem))
3409 client_ctx.use_certificate(
3410 load_certificate(FILETYPE_PEM, client_cert_pem))
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003411 client_ctx.check_privatekey()
3412 client_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05003413 client_conn = Connection(client_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003414 client_conn.set_connect_state()
3415 return client_conn
3416
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003417 def test_memoryConnect(self):
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003418 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003419 Two :py:obj:`Connection`s which use memory BIOs can be manually
3420 connected by reading from the output of each and writing those bytes to
3421 the input of the other and in this way establish a connection and
3422 exchange application-level bytes with each other.
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003423 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003424 server_conn = self._server(None)
3425 client_conn = self._client(None)
Rick Deanb71c0d22009-04-01 14:09:23 -05003426
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003427 # There should be no key or nonces yet.
3428 self.assertIdentical(server_conn.master_key(), None)
3429 self.assertIdentical(server_conn.client_random(), None)
3430 self.assertIdentical(server_conn.server_random(), None)
Rick Deanb71c0d22009-04-01 14:09:23 -05003431
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003432 # First, the handshake needs to happen. We'll deliver bytes back and
3433 # forth between the client and server until neither of them feels like
3434 # speaking any more.
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003435 self.assertIdentical(
3436 self._interactInMemory(client_conn, server_conn), None)
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003437
3438 # Now that the handshake is done, there should be a key and nonces.
3439 self.assertNotIdentical(server_conn.master_key(), None)
3440 self.assertNotIdentical(server_conn.client_random(), None)
3441 self.assertNotIdentical(server_conn.server_random(), None)
Hynek Schlawack35618382015-09-05 21:54:25 +02003442 self.assertEquals(
3443 server_conn.client_random(), client_conn.client_random())
3444 self.assertEquals(
3445 server_conn.server_random(), client_conn.server_random())
3446 self.assertNotEquals(
3447 server_conn.client_random(), server_conn.server_random())
3448 self.assertNotEquals(
3449 client_conn.client_random(), client_conn.server_random())
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003450
3451 # Here are the bytes we'll try to send.
Jean-Paul Calderonea441fdc2010-08-22 21:33:57 -04003452 important_message = b('One if by land, two if by sea.')
Rick Deanb71c0d22009-04-01 14:09:23 -05003453
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003454 server_conn.write(important_message)
3455 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003456 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003457 (client_conn, important_message))
3458
3459 client_conn.write(important_message[::-1])
3460 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003461 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003462 (server_conn, important_message[::-1]))
Rick Deanb71c0d22009-04-01 14:09:23 -05003463
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003464 def test_socketConnect(self):
Rick Deanb1ccd562009-07-09 23:52:39 -05003465 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003466 Just like :py:obj:`test_memoryConnect` but with an actual socket.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003467
Hynek Schlawack35618382015-09-05 21:54:25 +02003468 This is primarily to rule out the memory BIO code as the source of any
3469 problems encountered while passing data over a :py:obj:`Connection` (if
3470 this test fails, there must be a problem outside the memory BIO code,
3471 as no memory BIO is involved here). Even though this isn't a memory
3472 BIO test, it's convenient to have it here.
Rick Deanb1ccd562009-07-09 23:52:39 -05003473 """
Jean-Paul Calderone06c7cc92010-09-24 23:52:00 -04003474 server_conn, client_conn = self._loopback()
Rick Deanb1ccd562009-07-09 23:52:39 -05003475
Jean-Paul Calderonea441fdc2010-08-22 21:33:57 -04003476 important_message = b("Help me Obi Wan Kenobi, you're my only hope.")
Rick Deanb1ccd562009-07-09 23:52:39 -05003477 client_conn.send(important_message)
3478 msg = server_conn.recv(1024)
3479 self.assertEqual(msg, important_message)
3480
3481 # Again in the other direction, just for fun.
3482 important_message = important_message[::-1]
3483 server_conn.send(important_message)
3484 msg = client_conn.recv(1024)
3485 self.assertEqual(msg, important_message)
3486
Jean-Paul Calderonefc4ed0f2009-04-27 11:51:27 -04003487 def test_socketOverridesMemory(self):
Rick Deanb71c0d22009-04-01 14:09:23 -05003488 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003489 Test that :py:obj:`OpenSSL.SSL.bio_read` and
3490 :py:obj:`OpenSSL.SSL.bio_write` don't work on
3491 :py:obj:`OpenSSL.SSL.Connection`() that use sockets.
Rick Deanb71c0d22009-04-01 14:09:23 -05003492 """
3493 context = Context(SSLv3_METHOD)
3494 client = socket()
3495 clientSSL = Connection(context, client)
Alex Gaynor43307782015-09-04 09:05:45 -04003496 self.assertRaises(TypeError, clientSSL.bio_read, 100)
3497 self.assertRaises(TypeError, clientSSL.bio_write, "foo")
Alex Gaynor7e8b61e2015-09-04 13:13:05 -04003498 self.assertRaises(TypeError, clientSSL.bio_shutdown)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003499
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003500 def test_outgoingOverflow(self):
3501 """
3502 If more bytes than can be written to the memory BIO are passed to
Hynek Schlawack35618382015-09-05 21:54:25 +02003503 :py:obj:`Connection.send` at once, the number of bytes which were
3504 written is returned and that many bytes from the beginning of the input
3505 can be read from the other end of the connection.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003506 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003507 server = self._server(None)
3508 client = self._client(None)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003509
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003510 self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003511
3512 size = 2 ** 15
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003513 sent = client.send(b"x" * size)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003514 # Sanity check. We're trying to test what happens when the entire
3515 # input can't be sent. If the entire input was sent, this test is
3516 # meaningless.
3517 self.assertTrue(sent < size)
3518
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003519 receiver, received = self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003520 self.assertIdentical(receiver, server)
3521
3522 # We can rely on all of these bytes being received at once because
3523 # _loopback passes 2 ** 16 to recv - more than 2 ** 15.
3524 self.assertEquals(len(received), sent)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003525
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003526 def test_shutdown(self):
3527 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003528 :py:obj:`Connection.bio_shutdown` signals the end of the data stream
3529 from which the :py:obj:`Connection` reads.
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003530 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003531 server = self._server(None)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003532 server.bio_shutdown()
3533 e = self.assertRaises(Error, server.recv, 1024)
3534 # We don't want WantReadError or ZeroReturnError or anything - it's a
3535 # handshake failure.
3536 self.assertEquals(e.__class__, Error)
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003537
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003538 def test_unexpectedEndOfFile(self):
3539 """
3540 If the connection is lost before an orderly SSL shutdown occurs,
3541 :py:obj:`OpenSSL.SSL.SysCallError` is raised with a message of
3542 "Unexpected EOF".
3543 """
3544 server_conn, client_conn = self._loopback()
3545 client_conn.sock_shutdown(SHUT_RDWR)
3546 exc = self.assertRaises(SysCallError, server_conn.recv, 1024)
3547 self.assertEqual(exc.args, (-1, "Unexpected EOF"))
3548
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003549 def _check_client_ca_list(self, func):
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003550 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003551 Verify the return value of the :py:obj:`get_client_ca_list` method for
3552 server and client connections.
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003553
Jonathan Ballet78b92a22011-07-16 08:07:26 +09003554 :param func: A function which will be called with the server context
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003555 before the client and server are connected to each other. This
3556 function should specify a list of CAs for the server to send to the
3557 client and return that same list. The list will be used to verify
Hynek Schlawack35618382015-09-05 21:54:25 +02003558 that :py:obj:`get_client_ca_list` returns the proper value at
3559 various times.
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003560 """
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003561 server = self._server(None)
3562 client = self._client(None)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003563 self.assertEqual(client.get_client_ca_list(), [])
3564 self.assertEqual(server.get_client_ca_list(), [])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003565 ctx = server.get_context()
3566 expected = func(ctx)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003567 self.assertEqual(client.get_client_ca_list(), [])
3568 self.assertEqual(server.get_client_ca_list(), expected)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003569 self._interactInMemory(client, server)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003570 self.assertEqual(client.get_client_ca_list(), expected)
3571 self.assertEqual(server.get_client_ca_list(), expected)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003572
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003573 def test_set_client_ca_list_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003574 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003575 :py:obj:`Context.set_client_ca_list` raises a :py:obj:`TypeError` if
3576 called with a non-list or a list that contains objects other than
3577 X509Names.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003578 """
3579 ctx = Context(TLSv1_METHOD)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003580 self.assertRaises(TypeError, ctx.set_client_ca_list, "spam")
3581 self.assertRaises(TypeError, ctx.set_client_ca_list, ["spam"])
3582 self.assertIdentical(ctx.set_client_ca_list([]), None)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003583
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003584 def test_set_empty_ca_list(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003585 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003586 If passed an empty list, :py:obj:`Context.set_client_ca_list`
3587 configures the context to send no CA names to the client and, on both
3588 the server and client sides, :py:obj:`Connection.get_client_ca_list`
3589 returns an empty list after the connection is set up.
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003590 """
3591 def no_ca(ctx):
3592 ctx.set_client_ca_list([])
3593 return []
3594 self._check_client_ca_list(no_ca)
3595
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003596 def test_set_one_ca_list(self):
3597 """
3598 If passed a list containing a single X509Name,
Hynek Schlawack35618382015-09-05 21:54:25 +02003599 :py:obj:`Context.set_client_ca_list` configures the context to send
3600 that CA name to the client and, on both the server and client sides,
Jonathan Ballet648875f2011-07-16 14:14:58 +09003601 :py:obj:`Connection.get_client_ca_list` returns a list containing that
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003602 X509Name after the connection is set up.
3603 """
3604 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3605 cadesc = cacert.get_subject()
Hynek Schlawack35618382015-09-05 21:54:25 +02003606
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003607 def single_ca(ctx):
3608 ctx.set_client_ca_list([cadesc])
3609 return [cadesc]
3610 self._check_client_ca_list(single_ca)
3611
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003612 def test_set_multiple_ca_list(self):
3613 """
3614 If passed a list containing multiple X509Name objects,
Hynek Schlawack35618382015-09-05 21:54:25 +02003615 :py:obj:`Context.set_client_ca_list` configures the context to send
3616 those CA names to the client and, on both the server and client sides,
Jonathan Ballet648875f2011-07-16 14:14:58 +09003617 :py:obj:`Connection.get_client_ca_list` returns a list containing those
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003618 X509Names after the connection is set up.
3619 """
3620 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3621 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3622
3623 sedesc = secert.get_subject()
3624 cldesc = clcert.get_subject()
3625
3626 def multiple_ca(ctx):
3627 L = [sedesc, cldesc]
3628 ctx.set_client_ca_list(L)
3629 return L
3630 self._check_client_ca_list(multiple_ca)
3631
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003632 def test_reset_ca_list(self):
3633 """
3634 If called multiple times, only the X509Names passed to the final call
Hynek Schlawack35618382015-09-05 21:54:25 +02003635 of :py:obj:`Context.set_client_ca_list` are used to configure the CA
3636 names sent to the client.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003637 """
3638 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3639 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3640 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3641
3642 cadesc = cacert.get_subject()
3643 sedesc = secert.get_subject()
3644 cldesc = clcert.get_subject()
3645
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003646 def changed_ca(ctx):
3647 ctx.set_client_ca_list([sedesc, cldesc])
3648 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003649 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003650 self._check_client_ca_list(changed_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003651
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003652 def test_mutated_ca_list(self):
3653 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003654 If the list passed to :py:obj:`Context.set_client_ca_list` is mutated
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003655 afterwards, this does not affect the list of CA names sent to the
3656 client.
3657 """
3658 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3659 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3660
3661 cadesc = cacert.get_subject()
3662 sedesc = secert.get_subject()
3663
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003664 def mutated_ca(ctx):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003665 L = [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003666 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003667 L.append(sedesc)
3668 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003669 self._check_client_ca_list(mutated_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003670
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003671 def test_add_client_ca_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003672 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003673 :py:obj:`Context.add_client_ca` raises :py:obj:`TypeError` if called
3674 with a non-X509 object or with a number of arguments other than one.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003675 """
3676 ctx = Context(TLSv1_METHOD)
3677 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003678 self.assertRaises(TypeError, ctx.add_client_ca)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003679 self.assertRaises(TypeError, ctx.add_client_ca, "spam")
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003680 self.assertRaises(TypeError, ctx.add_client_ca, cacert, cacert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003681
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003682 def test_one_add_client_ca(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003683 """
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003684 A certificate's subject can be added as a CA to be sent to the client
Jonathan Ballet648875f2011-07-16 14:14:58 +09003685 with :py:obj:`Context.add_client_ca`.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003686 """
3687 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3688 cadesc = cacert.get_subject()
Hynek Schlawack35618382015-09-05 21:54:25 +02003689
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003690 def single_ca(ctx):
3691 ctx.add_client_ca(cacert)
3692 return [cadesc]
3693 self._check_client_ca_list(single_ca)
3694
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003695 def test_multiple_add_client_ca(self):
3696 """
3697 Multiple CA names can be sent to the client by calling
Jonathan Ballet648875f2011-07-16 14:14:58 +09003698 :py:obj:`Context.add_client_ca` with multiple X509 objects.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003699 """
3700 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3701 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3702
3703 cadesc = cacert.get_subject()
3704 sedesc = secert.get_subject()
3705
3706 def multiple_ca(ctx):
3707 ctx.add_client_ca(cacert)
3708 ctx.add_client_ca(secert)
3709 return [cadesc, sedesc]
3710 self._check_client_ca_list(multiple_ca)
3711
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003712 def test_set_and_add_client_ca(self):
3713 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003714 A call to :py:obj:`Context.set_client_ca_list` followed by a call to
Hynek Schlawack35618382015-09-05 21:54:25 +02003715 :py:obj:`Context.add_client_ca` results in using the CA names from the
3716 first call and the CA name from the second call.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003717 """
3718 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3719 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3720 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3721
3722 cadesc = cacert.get_subject()
3723 sedesc = secert.get_subject()
3724 cldesc = clcert.get_subject()
3725
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003726 def mixed_set_add_ca(ctx):
3727 ctx.set_client_ca_list([cadesc, sedesc])
3728 ctx.add_client_ca(clcert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003729 return [cadesc, sedesc, cldesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003730 self._check_client_ca_list(mixed_set_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003731
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003732 def test_set_after_add_client_ca(self):
3733 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003734 A call to :py:obj:`Context.set_client_ca_list` after a call to
Hynek Schlawack35618382015-09-05 21:54:25 +02003735 :py:obj:`Context.add_client_ca` replaces the CA name specified by the
3736 former call with the names specified by the latter call.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003737 """
3738 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3739 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3740 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3741
3742 cadesc = cacert.get_subject()
3743 sedesc = secert.get_subject()
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003744
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003745 def set_replaces_add_ca(ctx):
3746 ctx.add_client_ca(clcert)
3747 ctx.set_client_ca_list([cadesc])
3748 ctx.add_client_ca(secert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003749 return [cadesc, sedesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003750 self._check_client_ca_list(set_replaces_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003751
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003752
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003753class ConnectionBIOTests(TestCase):
3754 """
3755 Tests for :py:obj:`Connection.bio_read` and :py:obj:`Connection.bio_write`.
3756 """
3757 def test_wantReadError(self):
3758 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003759 :py:obj:`Connection.bio_read` raises
3760 :py:obj:`OpenSSL.SSL.WantReadError` if there are no bytes available to
3761 be read from the BIO.
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003762 """
3763 ctx = Context(TLSv1_METHOD)
3764 conn = Connection(ctx, None)
3765 self.assertRaises(WantReadError, conn.bio_read, 1024)
3766
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003767 def test_buffer_size(self):
3768 """
3769 :py:obj:`Connection.bio_read` accepts an integer giving the maximum
3770 number of bytes to read and return.
3771 """
3772 ctx = Context(TLSv1_METHOD)
3773 conn = Connection(ctx, None)
3774 conn.set_connect_state()
3775 try:
3776 conn.do_handshake()
3777 except WantReadError:
3778 pass
3779 data = conn.bio_read(2)
3780 self.assertEqual(2, len(data))
3781
Hynek Schlawack35618382015-09-05 21:54:25 +02003782 @skip_if_py3
3783 def test_buffer_size_long(self):
3784 """
3785 On Python 2 :py:obj:`Connection.bio_read` accepts values of type
3786 :py:obj:`long` as well as :py:obj:`int`.
3787 """
3788 ctx = Context(TLSv1_METHOD)
3789 conn = Connection(ctx, None)
3790 conn.set_connect_state()
3791 try:
3792 conn.do_handshake()
3793 except WantReadError:
3794 pass
3795 data = conn.bio_read(long(2))
3796 self.assertEqual(2, len(data))
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003797
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003798
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003799class InfoConstantTests(TestCase):
3800 """
3801 Tests for assorted constants exposed for use in info callbacks.
3802 """
3803 def test_integers(self):
3804 """
3805 All of the info constants are integers.
3806
3807 This is a very weak test. It would be nice to have one that actually
3808 verifies that as certain info events happen, the value passed to the
3809 info callback matches up with the constant exposed by OpenSSL.SSL.
3810 """
3811 for const in [
3812 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK, SSL_ST_INIT,
3813 SSL_ST_BEFORE, SSL_ST_OK, SSL_ST_RENEGOTIATE,
3814 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
3815 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
3816 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
Hynek Schlawack35618382015-09-05 21:54:25 +02003817 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE
3818 ]:
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003819 self.assertTrue(isinstance(const, int))
3820
Ziga Seilnacht44611bf2009-08-31 20:49:30 +02003821
Cory Benfield1d142142016-03-30 11:51:45 +01003822class TestRequires(object):
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003823 """
3824 Tests for the decorator factory used to conditionally raise
Cory Benfield1d142142016-03-30 11:51:45 +01003825 NotImplementedError when older OpenSSLs are used.
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003826 """
3827 def test_available(self):
3828 """
3829 When the OpenSSL functionality is available the decorated functions
3830 work appropriately.
3831 """
3832 feature_guard = _make_requires(True, "Error text")
3833 results = []
3834
3835 @feature_guard
3836 def inner():
3837 results.append(True)
3838 return True
3839
Cory Benfield2333e5e2016-03-30 14:24:16 +01003840 assert inner() is True
3841 assert [True] == results
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003842
3843 def test_unavailable(self):
3844 """
3845 When the OpenSSL functionality is not available the decorated function
3846 does not execute and NotImplementedError is raised.
3847 """
3848 feature_guard = _make_requires(False, "Error text")
3849 results = []
3850
3851 @feature_guard
3852 def inner():
3853 results.append(True)
3854 return True
3855
Cory Benfield1d142142016-03-30 11:51:45 +01003856 with pytest.raises(NotImplementedError) as e:
3857 inner()
3858
3859 assert "Error text" in str(e.value)
Cory Benfield2333e5e2016-03-30 14:24:16 +01003860 assert results == []