blob: 332f5bc1046310184becaad408c8499fbcaf4eec [file] [log] [blame]
Jean-Paul Calderone8671c852011-03-02 19:26:20 -05001# Copyright (C) Jean-Paul Calderone
2# See LICENSE for details.
Jean-Paul Calderone8b63d452008-03-21 18:31:12 -04003
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -04004"""
Hynek Schlawackf90e3682016-03-11 11:21:13 +01005Unit tests for :mod:`OpenSSL.SSL`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -04006"""
7
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01008import datetime
9import uuid
10
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -050011from gc import collect, get_referrers
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +020012from errno import ECONNREFUSED, EINPROGRESS, EWOULDBLOCK, EPIPE, ESHUTDOWN
Hynek Schlawackf8979a52015-09-05 21:25:25 +020013from sys import platform, getfilesystemencoding, version_info
Maximilian Hils1d95dea2015-08-17 19:27:20 +020014from socket import MSG_PEEK, SHUT_RDWR, error, socket
Jean-Paul Calderonea65cf6c2009-07-19 10:26:52 -040015from os import makedirs
Jean-Paul Calderone1461c492013-10-03 16:05:00 -040016from os.path import join
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -040017from weakref import ref
Abraham Martinef063482015-03-25 14:06:24 +000018from warnings import catch_warnings, simplefilter
Jean-Paul Calderone460cc1f2009-03-07 11:31:12 -050019
Hynek Schlawack734d3022015-09-05 19:19:32 +020020import pytest
21
Hynek Schlawackf90e3682016-03-11 11:21:13 +010022from six import PY3, text_type
Jean-Paul Calderonec76c61c2014-01-18 13:21:52 -050023
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +010024from cryptography import x509
25from cryptography.hazmat.backends import default_backend
26from cryptography.hazmat.primitives import hashes
27from cryptography.hazmat.primitives import serialization
28from cryptography.hazmat.primitives.asymmetric import rsa
29from cryptography.x509.oid import NameOID
30
31
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040032from OpenSSL.crypto import TYPE_RSA, FILETYPE_PEM
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -080033from OpenSSL.crypto import PKey, X509, X509Extension, X509Store
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040034from OpenSSL.crypto import dump_privatekey, load_privatekey
35from OpenSSL.crypto import dump_certificate, load_certificate
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -040036from OpenSSL.crypto import get_elliptic_curves
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040037
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -040038from OpenSSL.SSL import OPENSSL_VERSION_NUMBER, SSLEAY_VERSION, SSLEAY_CFLAGS
39from OpenSSL.SSL import SSLEAY_PLATFORM, SSLEAY_DIR, SSLEAY_BUILT_ON
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -040040from OpenSSL.SSL import SENT_SHUTDOWN, RECEIVED_SHUTDOWN
Jean-Paul Calderone1461c492013-10-03 16:05:00 -040041from OpenSSL.SSL import (
42 SSLv2_METHOD, SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD,
43 TLSv1_1_METHOD, TLSv1_2_METHOD)
44from OpenSSL.SSL import OP_SINGLE_DH_USE, OP_NO_SSLv2, OP_NO_SSLv3
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040045from OpenSSL.SSL import (
46 VERIFY_PEER, VERIFY_FAIL_IF_NO_PEER_CERT, VERIFY_CLIENT_ONCE, VERIFY_NONE)
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040047
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040048from OpenSSL.SSL import (
Jean-Paul Calderone313bf012012-02-08 13:02:49 -050049 SESS_CACHE_OFF, SESS_CACHE_CLIENT, SESS_CACHE_SERVER, SESS_CACHE_BOTH,
50 SESS_CACHE_NO_AUTO_CLEAR, SESS_CACHE_NO_INTERNAL_LOOKUP,
51 SESS_CACHE_NO_INTERNAL_STORE, SESS_CACHE_NO_INTERNAL)
52
53from OpenSSL.SSL import (
Jean-Paul Calderoned899af02013-03-19 22:10:37 -070054 Error, SysCallError, WantReadError, WantWriteError, ZeroReturnError)
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -050055from OpenSSL.SSL import (
Jean-Paul Calderoned899af02013-03-19 22:10:37 -070056 Context, ContextType, Session, Connection, ConnectionType, SSLeay_version)
Cory Benfield0ba57ec2016-03-30 09:35:05 +010057from OpenSSL.SSL import _make_requires
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040058
Cory Benfieldba1820d2015-04-13 17:39:12 -040059from OpenSSL._util import lib as _lib
60
Alex Gaynord3b5d9b2016-07-31 10:54:24 -040061from OpenSSL.SSL import (
62 OP_NO_QUERY_MTU, OP_COOKIE_EXCHANGE, OP_NO_TICKET, OP_NO_COMPRESSION,
63 MODE_RELEASE_BUFFERS)
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040064
Jean-Paul Calderone1461c492013-10-03 16:05:00 -040065try:
66 from OpenSSL.SSL import OP_NO_TLSv1, OP_NO_TLSv1_1, OP_NO_TLSv1_2
67except ImportError:
68 OP_NO_TLSv1 = OP_NO_TLSv1_1 = OP_NO_TLSv1_2 = None
69
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -040070from OpenSSL.SSL import (
Alex Gaynor5af32d02016-09-24 01:52:21 -040071 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK,
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -040072 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
73 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
74 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
75 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE)
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -040076
Alex Gaynor5af32d02016-09-24 01:52:21 -040077try:
78 from OpenSSL.SSL import (
79 SSL_ST_INIT, SSL_ST_BEFORE, SSL_ST_OK, SSL_ST_RENEGOTIATE
80 )
81except ImportError:
82 SSL_ST_INIT = SSL_ST_BEFORE = SSL_ST_OK = SSL_ST_RENEGOTIATE = None
83
Alex Gaynore7f51982016-09-11 11:48:14 -040084from .util import WARNING_TYPE_EXPECTED, NON_ASCII, TestCase
Hynek Schlawackf0e66852015-10-16 20:18:38 +020085from .test_crypto import (
86 cleartextCertificatePEM, cleartextPrivateKeyPEM,
87 client_cert_pem, client_key_pem, server_cert_pem, server_key_pem,
88 root_cert_pem)
89
Hynek Schlawackde00dd52015-09-05 19:09:26 +020090
Alex Gaynord0bdd2d2016-09-10 14:23:46 -040091# openssl dhparam 1024 -out dh-1024.pem (note that 1024 is a small number of
92# bits to use)
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -040093dhparam = """\
94-----BEGIN DH PARAMETERS-----
Alex Gaynord0bdd2d2016-09-10 14:23:46 -040095MIGHAoGBALdUMvn+C9MM+y5BWZs11mSeH6HHoEq0UVbzVq7UojC1hbsZUuGukQ3a
96Qh2/pwqb18BZFykrWB0zv/OkLa0kx4cuUgNrUVq1EFheBiX6YqryJ7t2sO09NQiO
97V7H54LmltOT/hEh6QWsJqb6BQgH65bswvV/XkYGja8/T0GzvbaVzAgEC
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -040098-----END DH PARAMETERS-----
99"""
100
101
Hynek Schlawackb4f02402015-09-05 20:48:34 +0200102skip_if_py3 = pytest.mark.skipif(PY3, reason="Python 2 only")
Hynek Schlawackf8979a52015-09-05 21:25:25 +0200103skip_if_py26 = pytest.mark.skipif(
104 version_info[0:2] == (2, 6),
105 reason="Python 2.7 and later only"
106)
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200107
108
Jean-Paul Calderone05826732015-04-12 11:38:49 -0400109def join_bytes_or_unicode(prefix, suffix):
110 """
111 Join two path components of either ``bytes`` or ``unicode``.
112
113 The return type is the same as the type of ``prefix``.
114 """
115 # If the types are the same, nothing special is necessary.
116 if type(prefix) == type(suffix):
117 return join(prefix, suffix)
118
119 # Otherwise, coerce suffix to the type of prefix.
120 if isinstance(prefix, text_type):
121 return join(prefix, suffix.decode(getfilesystemencoding()))
122 else:
123 return join(prefix, suffix.encode(getfilesystemencoding()))
124
125
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400126def verify_cb(conn, cert, errnum, depth, ok):
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400127 return ok
128
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400129
Rick Deanb1ccd562009-07-09 23:52:39 -0500130def socket_pair():
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400131 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400132 Establish and return a pair of network sockets connected to each other.
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400133 """
134 # Connect a pair of sockets
Rick Deanb1ccd562009-07-09 23:52:39 -0500135 port = socket()
136 port.bind(('', 0))
137 port.listen(1)
138 client = socket()
139 client.setblocking(False)
Jean-Paul Calderonef23c5d92009-07-23 17:58:15 -0400140 client.connect_ex(("127.0.0.1", port.getsockname()[1]))
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400141 client.setblocking(True)
Rick Deanb1ccd562009-07-09 23:52:39 -0500142 server = port.accept()[0]
Rick Deanb1ccd562009-07-09 23:52:39 -0500143
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400144 # Let's pass some unencrypted data to make sure our socket connection is
145 # fine. Just one byte, so we don't have to worry about buffers getting
146 # filled up or fragmentation.
Alex Gaynore7f51982016-09-11 11:48:14 -0400147 server.send(b"x")
148 assert client.recv(1024) == b"x"
149 client.send(b"y")
150 assert server.recv(1024) == b"y"
Rick Deanb1ccd562009-07-09 23:52:39 -0500151
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -0400152 # Most of our callers want non-blocking sockets, make it easy for them.
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400153 server.setblocking(False)
154 client.setblocking(False)
Jim Shaver46f28912015-05-29 19:32:16 -0400155
Rick Deanb1ccd562009-07-09 23:52:39 -0500156 return (server, client)
157
158
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400159def handshake(client, server):
160 conns = [client, server]
161 while conns:
162 for conn in conns:
163 try:
164 conn.do_handshake()
165 except WantReadError:
166 pass
167 else:
168 conns.remove(conn)
169
170
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400171def _create_certificate_chain():
172 """
173 Construct and return a chain of certificates.
174
175 1. A new self-signed certificate authority certificate (cacert)
176 2. A new intermediate certificate signed by cacert (icert)
177 3. A new server certificate signed by icert (scert)
178 """
Alex Gaynore7f51982016-09-11 11:48:14 -0400179 caext = X509Extension(b'basicConstraints', False, b'CA:true')
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400180
181 # Step 1
182 cakey = PKey()
Alex Gaynor0737a5e2016-09-10 14:35:09 -0400183 cakey.generate_key(TYPE_RSA, 1024)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400184 cacert = X509()
185 cacert.get_subject().commonName = "Authority Certificate"
186 cacert.set_issuer(cacert.get_subject())
187 cacert.set_pubkey(cakey)
Alex Gaynore7f51982016-09-11 11:48:14 -0400188 cacert.set_notBefore(b"20000101000000Z")
189 cacert.set_notAfter(b"20200101000000Z")
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400190 cacert.add_extensions([caext])
191 cacert.set_serial_number(0)
192 cacert.sign(cakey, "sha1")
193
194 # Step 2
195 ikey = PKey()
Alex Gaynor0737a5e2016-09-10 14:35:09 -0400196 ikey.generate_key(TYPE_RSA, 1024)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400197 icert = X509()
198 icert.get_subject().commonName = "Intermediate Certificate"
199 icert.set_issuer(cacert.get_subject())
200 icert.set_pubkey(ikey)
Alex Gaynore7f51982016-09-11 11:48:14 -0400201 icert.set_notBefore(b"20000101000000Z")
202 icert.set_notAfter(b"20200101000000Z")
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400203 icert.add_extensions([caext])
204 icert.set_serial_number(0)
205 icert.sign(cakey, "sha1")
206
207 # Step 3
208 skey = PKey()
Alex Gaynor0737a5e2016-09-10 14:35:09 -0400209 skey.generate_key(TYPE_RSA, 1024)
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400210 scert = X509()
211 scert.get_subject().commonName = "Server Certificate"
212 scert.set_issuer(icert.get_subject())
213 scert.set_pubkey(skey)
Alex Gaynore7f51982016-09-11 11:48:14 -0400214 scert.set_notBefore(b"20000101000000Z")
215 scert.set_notAfter(b"20200101000000Z")
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400216 scert.add_extensions([
Alex Gaynore7f51982016-09-11 11:48:14 -0400217 X509Extension(b'basicConstraints', True, b'CA:false')])
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400218 scert.set_serial_number(0)
219 scert.sign(ikey, "sha1")
220
221 return [(cakey, cacert), (ikey, icert), (skey, scert)]
222
223
Alex Chan1ca9e3a2016-11-05 13:01:51 +0000224class _LoopbackMixin(object):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400225 """
226 Helper mixin which defines methods for creating a connected socket pair and
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200227 for forcing two connected SSL sockets to talk to each other via memory
228 BIOs.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400229 """
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500230 def _loopbackClientFactory(self, socket):
231 client = Connection(Context(TLSv1_METHOD), socket)
232 client.set_connect_state()
233 return client
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400234
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500235 def _loopbackServerFactory(self, socket):
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400236 ctx = Context(TLSv1_METHOD)
237 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
238 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500239 server = Connection(ctx, socket)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400240 server.set_accept_state()
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500241 return server
242
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500243 def _loopback(self, serverFactory=None, clientFactory=None):
244 if serverFactory is None:
245 serverFactory = self._loopbackServerFactory
246 if clientFactory is None:
247 clientFactory = self._loopbackClientFactory
248
249 (server, client) = socket_pair()
250 server = serverFactory(server)
251 client = clientFactory(client)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400252
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400253 handshake(client, server)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400254
255 server.setblocking(True)
256 client.setblocking(True)
257 return server, client
258
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400259 def _interactInMemory(self, client_conn, server_conn):
Alex Chan1ca9e3a2016-11-05 13:01:51 +0000260 return interact_in_memory(client_conn, server_conn)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400261
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -0400262 def _handshakeInMemory(self, client_conn, server_conn):
Jean-Paul Calderoneb2b40782014-05-06 08:47:40 -0400263 """
264 Perform the TLS handshake between two :py:class:`Connection` instances
265 connected to each other via memory BIOs.
266 """
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -0400267 client_conn.set_connect_state()
268 server_conn.set_accept_state()
269
270 for conn in [client_conn, server_conn]:
271 try:
272 conn.do_handshake()
273 except WantReadError:
274 pass
275
276 self._interactInMemory(client_conn, server_conn)
277
278
Alex Chan1ca9e3a2016-11-05 13:01:51 +0000279def interact_in_memory(client_conn, server_conn):
280 """
281 Try to read application bytes from each of the two `Connection` objects.
282 Copy bytes back and forth between their send/receive buffers for as long
283 as there is anything to copy. When there is nothing more to copy,
284 return `None`. If one of them actually manages to deliver some application
285 bytes, return a two-tuple of the connection from which the bytes were read
286 and the bytes themselves.
287 """
288 wrote = True
289 while wrote:
290 # Loop until neither side has anything to say
291 wrote = False
292
293 # Copy stuff from each side's send buffer to the other side's
294 # receive buffer.
295 for (read, write) in [(client_conn, server_conn),
296 (server_conn, client_conn)]:
297
298 # Give the side a chance to generate some more bytes, or succeed.
299 try:
300 data = read.recv(2 ** 16)
301 except WantReadError:
302 # It didn't succeed, so we'll hope it generated some output.
303 pass
304 else:
305 # It did succeed, so we'll stop now and let the caller deal
306 # with it.
307 return (read, data)
308
309 while True:
310 # Keep copying as long as there's more stuff there.
311 try:
312 dirty = read.bio_read(4096)
313 except WantReadError:
314 # Okay, nothing more waiting to be sent. Stop
315 # processing this send buffer.
316 break
317 else:
318 # Keep track of the fact that someone generated some
319 # output.
320 wrote = True
321 write.bio_write(dirty)
322
323
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400324class VersionTests(TestCase):
325 """
326 Tests for version information exposed by
Jonathan Ballet648875f2011-07-16 14:14:58 +0900327 :py:obj:`OpenSSL.SSL.SSLeay_version` and
328 :py:obj:`OpenSSL.SSL.OPENSSL_VERSION_NUMBER`.
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400329 """
330 def test_OPENSSL_VERSION_NUMBER(self):
331 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900332 :py:obj:`OPENSSL_VERSION_NUMBER` is an integer with status in the low
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400333 byte and the patch, fix, minor, and major versions in the
334 nibbles above that.
335 """
336 self.assertTrue(isinstance(OPENSSL_VERSION_NUMBER, int))
337
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400338 def test_SSLeay_version(self):
339 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900340 :py:obj:`SSLeay_version` takes a version type indicator and returns
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400341 one of a number of version strings based on that indicator.
342 """
343 versions = {}
344 for t in [SSLEAY_VERSION, SSLEAY_CFLAGS, SSLEAY_BUILT_ON,
345 SSLEAY_PLATFORM, SSLEAY_DIR]:
346 version = SSLeay_version(t)
347 versions[version] = t
348 self.assertTrue(isinstance(version, bytes))
349 self.assertEqual(len(versions), 5)
350
351
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100352@pytest.fixture
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100353def ca_file(tmpdir):
354 """
355 Create a valid PEM file with CA certificates and return the path.
356 """
357 key = rsa.generate_private_key(
358 public_exponent=65537,
359 key_size=2048,
360 backend=default_backend()
361 )
362 public_key = key.public_key()
363
364 builder = x509.CertificateBuilder()
365 builder = builder.subject_name(x509.Name([
366 x509.NameAttribute(NameOID.COMMON_NAME, u"pyopenssl.org"),
367 ]))
368 builder = builder.issuer_name(x509.Name([
369 x509.NameAttribute(NameOID.COMMON_NAME, u"pyopenssl.org"),
370 ]))
371 one_day = datetime.timedelta(1, 0, 0)
372 builder = builder.not_valid_before(datetime.datetime.today() - one_day)
373 builder = builder.not_valid_after(datetime.datetime.today() + one_day)
374 builder = builder.serial_number(int(uuid.uuid4()))
375 builder = builder.public_key(public_key)
376 builder = builder.add_extension(
377 x509.BasicConstraints(ca=True, path_length=None), critical=True,
378 )
379
380 certificate = builder.sign(
381 private_key=key, algorithm=hashes.SHA256(),
382 backend=default_backend()
383 )
384
385 ca_file = tmpdir.join("test.pem")
386 ca_file.write_binary(
387 certificate.public_bytes(
388 encoding=serialization.Encoding.PEM,
389 )
390 )
391
392 return str(ca_file).encode("ascii")
393
394
395@pytest.fixture
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100396def context():
397 """
398 A simple TLS 1.0 context.
399 """
400 return Context(TLSv1_METHOD)
401
402
403class TestContext(object):
Hynek Schlawackaa861212016-03-13 13:53:48 +0100404 """
405 py.test-based tests for :class:`OpenSSL.SSL.Context`.
406
407 If possible, add new tests here.
408 """
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100409 @pytest.mark.parametrize("cipher_string", [
410 b"hello world:AES128-SHA",
411 u"hello world:AES128-SHA",
412 ])
413 def test_set_cipher_list(self, context, cipher_string):
414 """
Hynek Schlawacka7a63af2016-03-11 12:05:26 +0100415 :meth:`Context.set_cipher_list` accepts both byte and unicode strings
416 for naming the ciphers which connections created with the context
417 object will be able to choose from.
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100418 """
419 context.set_cipher_list(cipher_string)
420 conn = Connection(context, None)
421
422 assert "AES128-SHA" in conn.get_cipher_list()
423
424 @pytest.mark.parametrize("cipher_list,error", [
425 (object(), TypeError),
426 ("imaginary-cipher", Error),
427 ])
428 def test_set_cipher_list_wrong_args(self, context, cipher_list, error):
429 """
430 :meth:`Context.set_cipher_list` raises :exc:`TypeError` when passed a
431 non-string argument and raises :exc:`OpenSSL.SSL.Error` when passed an
432 incorrect cipher list string.
433 """
434 with pytest.raises(error):
435 context.set_cipher_list(cipher_list)
436
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100437 def test_load_client_ca(self, context, ca_file):
438 """
439 :meth:`Context.load_client_ca` works as far as we can tell.
440 """
441 context.load_client_ca(ca_file)
442
443 def test_load_client_ca_invalid(self, context, tmpdir):
444 """
445 :meth:`Context.load_client_ca` raises an Error if the ca file is
446 invalid.
447 """
448 ca_file = tmpdir.join("test.pem")
449 ca_file.write("")
450
451 with pytest.raises(Error) as e:
452 context.load_client_ca(str(ca_file).encode("ascii"))
453
454 assert "PEM routines" == e.value.args[0][0][0]
455
456 def test_load_client_ca_unicode(self, context, ca_file):
457 """
458 Passing the path as unicode raises a warning but works.
459 """
460 pytest.deprecated_call(
461 context.load_client_ca, ca_file.decode("ascii")
462 )
463
464 def test_set_session_id(self, context):
465 """
466 :meth:`Context.set_session_id` works as far as we can tell.
467 """
468 context.set_session_id(b"abc")
469
470 def test_set_session_id_fail(self, context):
471 """
472 :meth:`Context.set_session_id` errors are propagated.
473 """
474 with pytest.raises(Error) as e:
475 context.set_session_id(b"abc" * 1000)
476
477 assert [
478 ("SSL routines",
479 "SSL_CTX_set_session_id_context",
480 "ssl session id context too long")
481 ] == e.value.args[0]
482
483 def test_set_session_id_unicode(self, context):
484 """
485 :meth:`Context.set_session_id` raises a warning if a unicode string is
486 passed.
487 """
488 pytest.deprecated_call(context.set_session_id, u"abc")
489
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100490
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400491class ContextTests(TestCase, _LoopbackMixin):
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400492 """
Hynek Schlawackaa861212016-03-13 13:53:48 +0100493 Unit tests for :class:`OpenSSL.SSL.Context`.
494
495 If possible, add new tests to :class:`TestContext` above.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400496 """
497 def test_method(self):
498 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200499 :py:obj:`Context` can be instantiated with one of
500 :py:obj:`SSLv2_METHOD`, :py:obj:`SSLv3_METHOD`,
501 :py:obj:`SSLv23_METHOD`, :py:obj:`TLSv1_METHOD`,
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400502 :py:obj:`TLSv1_1_METHOD`, or :py:obj:`TLSv1_2_METHOD`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400503 """
Alex Gaynor5af32d02016-09-24 01:52:21 -0400504 methods = [SSLv23_METHOD, TLSv1_METHOD]
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400505 for meth in methods:
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400506 Context(meth)
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400507
Alex Gaynor5af32d02016-09-24 01:52:21 -0400508 maybe = [SSLv2_METHOD, SSLv3_METHOD, TLSv1_1_METHOD, TLSv1_2_METHOD]
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400509 for meth in maybe:
510 try:
511 Context(meth)
512 except (Error, ValueError):
513 # Some versions of OpenSSL have SSLv2 / TLSv1.1 / TLSv1.2, some
514 # don't. Difficult to say in advance.
515 pass
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400516
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400517 self.assertRaises(TypeError, Context, "")
518 self.assertRaises(ValueError, Context, 10)
519
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200520 @skip_if_py3
521 def test_method_long(self):
522 """
523 On Python 2 :py:class:`Context` accepts values of type
524 :py:obj:`long` as well as :py:obj:`int`.
525 """
526 Context(long(TLSv1_METHOD))
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500527
Rick Deane15b1472009-07-09 15:53:42 -0500528 def test_type(self):
529 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200530 :py:obj:`Context` and :py:obj:`ContextType` refer to the same type
531 object and can be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -0500532 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400533 self.assertIdentical(Context, ContextType)
534 self.assertConsistentType(Context, 'Context', TLSv1_METHOD)
Rick Deane15b1472009-07-09 15:53:42 -0500535
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400536 def test_use_privatekey(self):
537 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200538 :py:obj:`Context.use_privatekey` takes an :py:obj:`OpenSSL.crypto.PKey`
539 instance.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400540 """
541 key = PKey()
542 key.generate_key(TYPE_RSA, 128)
543 ctx = Context(TLSv1_METHOD)
544 ctx.use_privatekey(key)
545 self.assertRaises(TypeError, ctx.use_privatekey, "")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400546
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800547 def test_use_privatekey_file_missing(self):
548 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200549 :py:obj:`Context.use_privatekey_file` raises
550 :py:obj:`OpenSSL.SSL.Error` when passed the name of a file which does
551 not exist.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800552 """
553 ctx = Context(TLSv1_METHOD)
554 self.assertRaises(Error, ctx.use_privatekey_file, self.mktemp())
555
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400556 def _use_privatekey_file_test(self, pemfile, filetype):
557 """
558 Verify that calling ``Context.use_privatekey_file`` with the given
559 arguments does not raise an exception.
560 """
561 key = PKey()
562 key.generate_key(TYPE_RSA, 128)
563
564 with open(pemfile, "wt") as pem:
565 pem.write(
566 dump_privatekey(FILETYPE_PEM, key).decode("ascii")
567 )
568
569 ctx = Context(TLSv1_METHOD)
570 ctx.use_privatekey_file(pemfile, filetype)
571
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400572 def test_use_privatekey_file_bytes(self):
573 """
574 A private key can be specified from a file by passing a ``bytes``
575 instance giving the file name to ``Context.use_privatekey_file``.
576 """
577 self._use_privatekey_file_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -0400578 self.mktemp() + NON_ASCII.encode(getfilesystemencoding()),
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400579 FILETYPE_PEM,
580 )
581
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400582 def test_use_privatekey_file_unicode(self):
583 """
584 A private key can be specified from a file by passing a ``unicode``
585 instance giving the file name to ``Context.use_privatekey_file``.
586 """
587 self._use_privatekey_file_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -0400588 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII,
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400589 FILETYPE_PEM,
590 )
591
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200592 @skip_if_py3
593 def test_use_privatekey_file_long(self):
594 """
595 On Python 2 :py:obj:`Context.use_privatekey_file` accepts a
596 filetype of type :py:obj:`long` as well as :py:obj:`int`.
597 """
598 self._use_privatekey_file_test(self.mktemp(), long(FILETYPE_PEM))
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500599
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800600 def test_use_certificate_wrong_args(self):
601 """
602 :py:obj:`Context.use_certificate_wrong_args` raises :py:obj:`TypeError`
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200603 when not passed exactly one :py:obj:`OpenSSL.crypto.X509` instance as
604 an argument.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800605 """
606 ctx = Context(TLSv1_METHOD)
607 self.assertRaises(TypeError, ctx.use_certificate)
608 self.assertRaises(TypeError, ctx.use_certificate, "hello, world")
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200609 self.assertRaises(
610 TypeError, ctx.use_certificate, X509(), "hello, world"
611 )
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800612
613 def test_use_certificate_uninitialized(self):
614 """
615 :py:obj:`Context.use_certificate` raises :py:obj:`OpenSSL.SSL.Error`
616 when passed a :py:obj:`OpenSSL.crypto.X509` instance which has not been
617 initialized (ie, which does not actually have any certificate data).
618 """
619 ctx = Context(TLSv1_METHOD)
620 self.assertRaises(Error, ctx.use_certificate, X509())
621
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800622 def test_use_certificate(self):
623 """
624 :py:obj:`Context.use_certificate` sets the certificate which will be
625 used to identify connections created using the context.
626 """
627 # TODO
628 # Hard to assert anything. But we could set a privatekey then ask
629 # OpenSSL if the cert and key agree using check_privatekey. Then as
630 # long as check_privatekey works right we're good...
631 ctx = Context(TLSv1_METHOD)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200632 ctx.use_certificate(
633 load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
634 )
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800635
636 def test_use_certificate_file_wrong_args(self):
637 """
638 :py:obj:`Context.use_certificate_file` raises :py:obj:`TypeError` if
639 called with zero arguments or more than two arguments, or if the first
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200640 argument is not a byte string or the second argumnent is not an
641 integer.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800642 """
643 ctx = Context(TLSv1_METHOD)
644 self.assertRaises(TypeError, ctx.use_certificate_file)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200645 self.assertRaises(TypeError, ctx.use_certificate_file, b"somefile",
646 object())
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800647 self.assertRaises(
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200648 TypeError, ctx.use_certificate_file, b"somefile", FILETYPE_PEM,
649 object())
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800650 self.assertRaises(
651 TypeError, ctx.use_certificate_file, object(), FILETYPE_PEM)
652 self.assertRaises(
653 TypeError, ctx.use_certificate_file, b"somefile", object())
654
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800655 def test_use_certificate_file_missing(self):
656 """
657 :py:obj:`Context.use_certificate_file` raises
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200658 `:py:obj:`OpenSSL.SSL.Error` if passed the name of a file which does
659 not exist.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800660 """
661 ctx = Context(TLSv1_METHOD)
662 self.assertRaises(Error, ctx.use_certificate_file, self.mktemp())
663
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400664 def _use_certificate_file_test(self, certificate_file):
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800665 """
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400666 Verify that calling ``Context.use_certificate_file`` with the given
667 filename doesn't raise an exception.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800668 """
669 # TODO
670 # Hard to assert anything. But we could set a privatekey then ask
671 # OpenSSL if the cert and key agree using check_privatekey. Then as
672 # long as check_privatekey works right we're good...
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400673 with open(certificate_file, "wb") as pem_file:
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800674 pem_file.write(cleartextCertificatePEM)
675
676 ctx = Context(TLSv1_METHOD)
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400677 ctx.use_certificate_file(certificate_file)
678
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400679 def test_use_certificate_file_bytes(self):
680 """
681 :py:obj:`Context.use_certificate_file` sets the certificate (given as a
682 ``bytes`` filename) which will be used to identify connections created
683 using the context.
684 """
Hynek Schlawack4813c0e2015-04-16 13:38:01 -0400685 filename = self.mktemp() + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400686 self._use_certificate_file_test(filename)
687
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400688 def test_use_certificate_file_unicode(self):
689 """
690 :py:obj:`Context.use_certificate_file` sets the certificate (given as a
691 ``bytes`` filename) which will be used to identify connections created
692 using the context.
693 """
Hynek Schlawack4813c0e2015-04-16 13:38:01 -0400694 filename = self.mktemp().decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400695 self._use_certificate_file_test(filename)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800696
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200697 @skip_if_py3
698 def test_use_certificate_file_long(self):
699 """
700 On Python 2 :py:obj:`Context.use_certificate_file` accepts a
701 filetype of type :py:obj:`long` as well as :py:obj:`int`.
702 """
703 pem_filename = self.mktemp()
704 with open(pem_filename, "wb") as pem_file:
705 pem_file.write(cleartextCertificatePEM)
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500706
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200707 ctx = Context(TLSv1_METHOD)
708 ctx.use_certificate_file(pem_filename, long(FILETYPE_PEM))
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500709
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500710 def test_check_privatekey_valid(self):
711 """
712 :py:obj:`Context.check_privatekey` returns :py:obj:`None` if the
713 :py:obj:`Context` instance has been configured to use a matched key and
714 certificate pair.
715 """
716 key = load_privatekey(FILETYPE_PEM, client_key_pem)
717 cert = load_certificate(FILETYPE_PEM, client_cert_pem)
718 context = Context(TLSv1_METHOD)
719 context.use_privatekey(key)
720 context.use_certificate(cert)
721 self.assertIs(None, context.check_privatekey())
722
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500723 def test_check_privatekey_invalid(self):
724 """
725 :py:obj:`Context.check_privatekey` raises :py:obj:`Error` if the
726 :py:obj:`Context` instance has been configured to use a key and
727 certificate pair which don't relate to each other.
728 """
729 key = load_privatekey(FILETYPE_PEM, client_key_pem)
730 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
731 context = Context(TLSv1_METHOD)
732 context.use_privatekey(key)
733 context.use_certificate(cert)
734 self.assertRaises(Error, context.check_privatekey)
735
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500736 def test_check_privatekey_wrong_args(self):
737 """
738 :py:obj:`Context.check_privatekey` raises :py:obj:`TypeError` if called
739 with other than no arguments.
740 """
741 context = Context(TLSv1_METHOD)
742 self.assertRaises(TypeError, context.check_privatekey, object())
743
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400744 def test_set_app_data_wrong_args(self):
745 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200746 :py:obj:`Context.set_app_data` raises :py:obj:`TypeError` if called
747 with other than one argument.
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400748 """
749 context = Context(TLSv1_METHOD)
750 self.assertRaises(TypeError, context.set_app_data)
751 self.assertRaises(TypeError, context.set_app_data, None, None)
752
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400753 def test_get_app_data_wrong_args(self):
754 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200755 :py:obj:`Context.get_app_data` raises :py:obj:`TypeError` if called
756 with any arguments.
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400757 """
758 context = Context(TLSv1_METHOD)
759 self.assertRaises(TypeError, context.get_app_data, None)
760
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400761 def test_app_data(self):
762 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200763 :py:obj:`Context.set_app_data` stores an object for later retrieval
764 using :py:obj:`Context.get_app_data`.
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400765 """
766 app_data = object()
767 context = Context(TLSv1_METHOD)
768 context.set_app_data(app_data)
769 self.assertIdentical(context.get_app_data(), app_data)
770
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400771 def test_set_options_wrong_args(self):
772 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200773 :py:obj:`Context.set_options` raises :py:obj:`TypeError` if called with
774 the wrong number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400775 """
776 context = Context(TLSv1_METHOD)
777 self.assertRaises(TypeError, context.set_options)
778 self.assertRaises(TypeError, context.set_options, None)
779 self.assertRaises(TypeError, context.set_options, 1, None)
780
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500781 def test_set_options(self):
782 """
783 :py:obj:`Context.set_options` returns the new options value.
784 """
785 context = Context(TLSv1_METHOD)
786 options = context.set_options(OP_NO_SSLv2)
Alex Gaynor2310f8b2016-09-10 14:39:32 -0400787 assert options & OP_NO_SSLv2 == OP_NO_SSLv2
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500788
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200789 @skip_if_py3
790 def test_set_options_long(self):
791 """
792 On Python 2 :py:obj:`Context.set_options` accepts values of type
793 :py:obj:`long` as well as :py:obj:`int`.
794 """
795 context = Context(TLSv1_METHOD)
796 options = context.set_options(long(OP_NO_SSLv2))
Alex Gaynor2310f8b2016-09-10 14:39:32 -0400797 assert options & OP_NO_SSLv2 == OP_NO_SSLv2
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500798
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300799 def test_set_mode_wrong_args(self):
800 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200801 :py:obj:`Context.set`mode} raises :py:obj:`TypeError` if called with
802 the wrong number of arguments or a non-:py:obj:`int` argument.
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300803 """
804 context = Context(TLSv1_METHOD)
805 self.assertRaises(TypeError, context.set_mode)
806 self.assertRaises(TypeError, context.set_mode, None)
807 self.assertRaises(TypeError, context.set_mode, 1, None)
808
Alex Gaynord3b5d9b2016-07-31 10:54:24 -0400809 def test_set_mode(self):
810 """
811 :py:obj:`Context.set_mode` accepts a mode bitvector and returns the
812 newly set mode.
813 """
814 context = Context(TLSv1_METHOD)
815 self.assertTrue(
816 MODE_RELEASE_BUFFERS & context.set_mode(MODE_RELEASE_BUFFERS))
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500817
Alex Gaynord3b5d9b2016-07-31 10:54:24 -0400818 @skip_if_py3
819 def test_set_mode_long(self):
820 """
821 On Python 2 :py:obj:`Context.set_mode` accepts values of type
822 :py:obj:`long` as well as :py:obj:`int`.
823 """
824 context = Context(TLSv1_METHOD)
825 mode = context.set_mode(long(MODE_RELEASE_BUFFERS))
826 self.assertTrue(MODE_RELEASE_BUFFERS & mode)
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400827
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400828 def test_set_timeout_wrong_args(self):
829 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200830 :py:obj:`Context.set_timeout` raises :py:obj:`TypeError` if called with
831 the wrong number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400832 """
833 context = Context(TLSv1_METHOD)
834 self.assertRaises(TypeError, context.set_timeout)
835 self.assertRaises(TypeError, context.set_timeout, None)
836 self.assertRaises(TypeError, context.set_timeout, 1, None)
837
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400838 def test_get_timeout_wrong_args(self):
839 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200840 :py:obj:`Context.get_timeout` raises :py:obj:`TypeError` if called with
841 any arguments.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400842 """
843 context = Context(TLSv1_METHOD)
844 self.assertRaises(TypeError, context.get_timeout, None)
845
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400846 def test_timeout(self):
847 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200848 :py:obj:`Context.set_timeout` sets the session timeout for all
849 connections created using the context object.
850 :py:obj:`Context.get_timeout` retrieves this value.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400851 """
852 context = Context(TLSv1_METHOD)
853 context.set_timeout(1234)
854 self.assertEquals(context.get_timeout(), 1234)
855
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200856 @skip_if_py3
857 def test_timeout_long(self):
858 """
859 On Python 2 :py:obj:`Context.set_timeout` accepts values of type
860 `long` as well as int.
861 """
862 context = Context(TLSv1_METHOD)
863 context.set_timeout(long(1234))
864 self.assertEquals(context.get_timeout(), 1234)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500865
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400866 def test_set_verify_depth_wrong_args(self):
867 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200868 :py:obj:`Context.set_verify_depth` raises :py:obj:`TypeError` if called
869 with the wrong number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400870 """
871 context = Context(TLSv1_METHOD)
872 self.assertRaises(TypeError, context.set_verify_depth)
873 self.assertRaises(TypeError, context.set_verify_depth, None)
874 self.assertRaises(TypeError, context.set_verify_depth, 1, None)
875
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400876 def test_get_verify_depth_wrong_args(self):
877 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200878 :py:obj:`Context.get_verify_depth` raises :py:obj:`TypeError` if called
879 with any arguments.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400880 """
881 context = Context(TLSv1_METHOD)
882 self.assertRaises(TypeError, context.get_verify_depth, None)
883
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400884 def test_verify_depth(self):
885 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200886 :py:obj:`Context.set_verify_depth` sets the number of certificates in
887 a chain to follow before giving up. The value can be retrieved with
Jonathan Ballet648875f2011-07-16 14:14:58 +0900888 :py:obj:`Context.get_verify_depth`.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400889 """
890 context = Context(TLSv1_METHOD)
891 context.set_verify_depth(11)
892 self.assertEquals(context.get_verify_depth(), 11)
893
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200894 @skip_if_py3
895 def test_verify_depth_long(self):
896 """
897 On Python 2 :py:obj:`Context.set_verify_depth` accepts values of
898 type `long` as well as int.
899 """
900 context = Context(TLSv1_METHOD)
901 context.set_verify_depth(long(11))
902 self.assertEquals(context.get_verify_depth(), 11)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500903
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400904 def _write_encrypted_pem(self, passphrase):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400905 """
906 Write a new private key out to a new file, encrypted using the given
907 passphrase. Return the path to the new file.
908 """
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400909 key = PKey()
910 key.generate_key(TYPE_RSA, 128)
911 pemFile = self.mktemp()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400912 fObj = open(pemFile, 'w')
913 pem = dump_privatekey(FILETYPE_PEM, key, "blowfish", passphrase)
914 fObj.write(pem.decode('ascii'))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400915 fObj.close()
916 return pemFile
917
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400918 def test_set_passwd_cb_wrong_args(self):
919 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200920 :py:obj:`Context.set_passwd_cb` raises :py:obj:`TypeError` if called
921 with the wrong arguments or with a non-callable first argument.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400922 """
923 context = Context(TLSv1_METHOD)
924 self.assertRaises(TypeError, context.set_passwd_cb)
925 self.assertRaises(TypeError, context.set_passwd_cb, None)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200926 self.assertRaises(
927 TypeError, context.set_passwd_cb, lambda: None, None, None
Hynek Schlawack2c013a92015-09-05 19:33:05 +0200928 ) # pragma: nocover
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400929
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400930 def test_set_passwd_cb(self):
931 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200932 :py:obj:`Context.set_passwd_cb` accepts a callable which will be
933 invoked when a private key is loaded from an encrypted PEM.
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400934 """
Alex Gaynore7f51982016-09-11 11:48:14 -0400935 passphrase = b"foobar"
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400936 pemFile = self._write_encrypted_pem(passphrase)
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400937 calledWith = []
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200938
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400939 def passphraseCallback(maxlen, verify, extra):
940 calledWith.append((maxlen, verify, extra))
941 return passphrase
942 context = Context(TLSv1_METHOD)
943 context.set_passwd_cb(passphraseCallback)
944 context.use_privatekey_file(pemFile)
945 self.assertTrue(len(calledWith), 1)
946 self.assertTrue(isinstance(calledWith[0][0], int))
947 self.assertTrue(isinstance(calledWith[0][1], int))
948 self.assertEqual(calledWith[0][2], None)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400949
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400950 def test_passwd_callback_exception(self):
951 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200952 :py:obj:`Context.use_privatekey_file` propagates any exception raised
953 by the passphrase callback.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400954 """
Alex Gaynore7f51982016-09-11 11:48:14 -0400955 pemFile = self._write_encrypted_pem(b"monkeys are nice")
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200956
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400957 def passphraseCallback(maxlen, verify, extra):
958 raise RuntimeError("Sorry, I am a fail.")
959
960 context = Context(TLSv1_METHOD)
961 context.set_passwd_cb(passphraseCallback)
962 self.assertRaises(RuntimeError, context.use_privatekey_file, pemFile)
963
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400964 def test_passwd_callback_false(self):
965 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200966 :py:obj:`Context.use_privatekey_file` raises
967 :py:obj:`OpenSSL.SSL.Error` if the passphrase callback returns a false
968 value.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400969 """
Alex Gaynore7f51982016-09-11 11:48:14 -0400970 pemFile = self._write_encrypted_pem(b"monkeys are nice")
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200971
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400972 def passphraseCallback(maxlen, verify, extra):
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500973 return b""
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400974
975 context = Context(TLSv1_METHOD)
976 context.set_passwd_cb(passphraseCallback)
977 self.assertRaises(Error, context.use_privatekey_file, pemFile)
978
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400979 def test_passwd_callback_non_string(self):
980 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200981 :py:obj:`Context.use_privatekey_file` raises
982 :py:obj:`OpenSSL.SSL.Error` if the passphrase callback returns a true
983 non-string value.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400984 """
Alex Gaynore7f51982016-09-11 11:48:14 -0400985 pemFile = self._write_encrypted_pem(b"monkeys are nice")
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200986
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400987 def passphraseCallback(maxlen, verify, extra):
988 return 10
989
990 context = Context(TLSv1_METHOD)
991 context.set_passwd_cb(passphraseCallback)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800992 self.assertRaises(ValueError, context.use_privatekey_file, pemFile)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400993
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400994 def test_passwd_callback_too_long(self):
995 """
996 If the passphrase returned by the passphrase callback returns a string
997 longer than the indicated maximum length, it is truncated.
998 """
999 # A priori knowledge!
Alex Gaynore7f51982016-09-11 11:48:14 -04001000 passphrase = b"x" * 1024
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -04001001 pemFile = self._write_encrypted_pem(passphrase)
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001002
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -04001003 def passphraseCallback(maxlen, verify, extra):
1004 assert maxlen == 1024
Alex Gaynore7f51982016-09-11 11:48:14 -04001005 return passphrase + b"y"
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -04001006
1007 context = Context(TLSv1_METHOD)
1008 context.set_passwd_cb(passphraseCallback)
1009 # This shall succeed because the truncated result is the correct
1010 # passphrase.
1011 context.use_privatekey_file(pemFile)
1012
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -04001013 def test_set_info_callback(self):
1014 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001015 :py:obj:`Context.set_info_callback` accepts a callable which will be
1016 invoked when certain information about an SSL connection is available.
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -04001017 """
Rick Deanb1ccd562009-07-09 23:52:39 -05001018 (server, client) = socket_pair()
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -04001019
1020 clientSSL = Connection(Context(TLSv1_METHOD), client)
1021 clientSSL.set_connect_state()
1022
1023 called = []
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001024
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -04001025 def info(conn, where, ret):
1026 called.append((conn, where, ret))
1027 context = Context(TLSv1_METHOD)
1028 context.set_info_callback(info)
1029 context.use_certificate(
1030 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1031 context.use_privatekey(
1032 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1033
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -04001034 serverSSL = Connection(context, server)
1035 serverSSL.set_accept_state()
1036
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -05001037 handshake(clientSSL, serverSSL)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -04001038
Jean-Paul Calderone3835e522014-02-02 11:12:30 -05001039 # The callback must always be called with a Connection instance as the
1040 # first argument. It would probably be better to split this into
1041 # separate tests for client and server side info callbacks so we could
1042 # assert it is called with the right Connection instance. It would
1043 # also be good to assert *something* about `where` and `ret`.
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -05001044 notConnections = [
1045 conn for (conn, where, ret) in called
1046 if not isinstance(conn, Connection)]
1047 self.assertEqual(
1048 [], notConnections,
1049 "Some info callback arguments were not Connection instaces.")
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001050
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001051 def _load_verify_locations_test(self, *args):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001052 """
1053 Create a client context which will verify the peer certificate and call
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04001054 its :py:obj:`load_verify_locations` method with the given arguments.
1055 Then connect it to a server and ensure that the handshake succeeds.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001056 """
Rick Deanb1ccd562009-07-09 23:52:39 -05001057 (server, client) = socket_pair()
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001058
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001059 clientContext = Context(TLSv1_METHOD)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001060 clientContext.load_verify_locations(*args)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001061 # Require that the server certificate verify properly or the
1062 # connection will fail.
1063 clientContext.set_verify(
1064 VERIFY_PEER,
1065 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
1066
1067 clientSSL = Connection(clientContext, client)
1068 clientSSL.set_connect_state()
1069
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001070 serverContext = Context(TLSv1_METHOD)
1071 serverContext.use_certificate(
1072 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1073 serverContext.use_privatekey(
1074 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1075
1076 serverSSL = Connection(serverContext, server)
1077 serverSSL.set_accept_state()
1078
Jean-Paul Calderonef8742032010-09-25 00:00:32 -04001079 # Without load_verify_locations above, the handshake
1080 # will fail:
1081 # Error: [('SSL routines', 'SSL3_GET_SERVER_CERTIFICATE',
1082 # 'certificate verify failed')]
1083 handshake(clientSSL, serverSSL)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001084
1085 cert = clientSSL.get_peer_certificate()
Jean-Paul Calderone20131f52009-04-01 12:05:45 -04001086 self.assertEqual(cert.get_subject().CN, 'Testing Root CA')
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -04001087
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001088 def _load_verify_cafile(self, cafile):
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001089 """
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001090 Verify that if path to a file containing a certificate is passed to
1091 ``Context.load_verify_locations`` for the ``cafile`` parameter, that
1092 certificate is used as a trust root for the purposes of verifying
1093 connections created using that ``Context``.
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001094 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04001095 fObj = open(cafile, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04001096 fObj.write(cleartextCertificatePEM.decode('ascii'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001097 fObj.close()
1098
1099 self._load_verify_locations_test(cafile)
1100
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001101 def test_load_verify_bytes_cafile(self):
1102 """
1103 :py:obj:`Context.load_verify_locations` accepts a file name as a
1104 ``bytes`` instance and uses the certificates within for verification
1105 purposes.
1106 """
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001107 cafile = self.mktemp() + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001108 self._load_verify_cafile(cafile)
1109
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001110 def test_load_verify_unicode_cafile(self):
1111 """
1112 :py:obj:`Context.load_verify_locations` accepts a file name as a
1113 ``unicode`` instance and uses the certificates within for verification
1114 purposes.
1115 """
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001116 self._load_verify_cafile(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001117 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001118 )
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001119
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -04001120 def test_load_verify_invalid_file(self):
1121 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001122 :py:obj:`Context.load_verify_locations` raises :py:obj:`Error` when
1123 passed a non-existent cafile.
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -04001124 """
1125 clientContext = Context(TLSv1_METHOD)
1126 self.assertRaises(
1127 Error, clientContext.load_verify_locations, self.mktemp())
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001128
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001129 def _load_verify_directory_locations_capath(self, capath):
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001130 """
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001131 Verify that if path to a directory containing certificate files is
1132 passed to ``Context.load_verify_locations`` for the ``capath``
1133 parameter, those certificates are used as trust roots for the purposes
1134 of verifying connections created using that ``Context``.
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001135 """
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001136 makedirs(capath)
Jean-Paul Calderone24dfb332011-05-04 18:10:26 -04001137 # Hash values computed manually with c_rehash to avoid depending on
1138 # c_rehash in the test suite. One is from OpenSSL 0.9.8, the other
1139 # from OpenSSL 1.0.0.
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001140 for name in [b'c7adac82.0', b'c3705638.0']:
Jean-Paul Calderone05826732015-04-12 11:38:49 -04001141 cafile = join_bytes_or_unicode(capath, name)
1142 with open(cafile, 'w') as fObj:
1143 fObj.write(cleartextCertificatePEM.decode('ascii'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001144
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001145 self._load_verify_locations_test(None, capath)
1146
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001147 def test_load_verify_directory_bytes_capath(self):
1148 """
1149 :py:obj:`Context.load_verify_locations` accepts a directory name as a
1150 ``bytes`` instance and uses the certificates within for verification
1151 purposes.
1152 """
1153 self._load_verify_directory_locations_capath(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001154 self.mktemp() + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001155 )
1156
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001157 def test_load_verify_directory_unicode_capath(self):
1158 """
1159 :py:obj:`Context.load_verify_locations` accepts a directory name as a
1160 ``unicode`` instance and uses the certificates within for verification
1161 purposes.
1162 """
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001163 self._load_verify_directory_locations_capath(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001164 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001165 )
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001166
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001167 def test_load_verify_locations_wrong_args(self):
1168 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001169 :py:obj:`Context.load_verify_locations` raises :py:obj:`TypeError` if
1170 called with the wrong number of arguments or with non-:py:obj:`str`
1171 arguments.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001172 """
1173 context = Context(TLSv1_METHOD)
1174 self.assertRaises(TypeError, context.load_verify_locations)
1175 self.assertRaises(TypeError, context.load_verify_locations, object())
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001176 self.assertRaises(
1177 TypeError, context.load_verify_locations, object(), object()
1178 )
1179 self.assertRaises(
1180 TypeError, context.load_verify_locations, None, None, None
1181 )
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001182
Hynek Schlawack734d3022015-09-05 19:19:32 +02001183 @pytest.mark.skipif(
1184 platform == "win32",
1185 reason="set_default_verify_paths appears not to work on Windows. "
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -04001186 "See LP#404343 and LP#404344."
Hynek Schlawack734d3022015-09-05 19:19:32 +02001187 )
1188 def test_set_default_verify_paths(self):
1189 """
1190 :py:obj:`Context.set_default_verify_paths` causes the
1191 platform-specific CA certificate locations to be used for
1192 verification purposes.
1193 """
1194 # Testing this requires a server with a certificate signed by one
1195 # of the CAs in the platform CA location. Getting one of those
1196 # costs money. Fortunately (or unfortunately, depending on your
1197 # perspective), it's easy to think of a public server on the
1198 # internet which has such a certificate. Connecting to the network
1199 # in a unit test is bad, but it's the only way I can think of to
1200 # really test this. -exarkun
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001201
Hynek Schlawack734d3022015-09-05 19:19:32 +02001202 # Arg, verisign.com doesn't speak anything newer than TLS 1.0
Hynek Schlawackbf887932015-10-21 17:13:47 +02001203 context = Context(SSLv23_METHOD)
Hynek Schlawack734d3022015-09-05 19:19:32 +02001204 context.set_default_verify_paths()
1205 context.set_verify(
1206 VERIFY_PEER,
1207 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001208
Hynek Schlawack734d3022015-09-05 19:19:32 +02001209 client = socket()
Hynek Schlawackbf887932015-10-21 17:13:47 +02001210 client.connect(("encrypted.google.com", 443))
Hynek Schlawack734d3022015-09-05 19:19:32 +02001211 clientSSL = Connection(context, client)
1212 clientSSL.set_connect_state()
1213 clientSSL.do_handshake()
1214 clientSSL.send(b"GET / HTTP/1.0\r\n\r\n")
1215 self.assertTrue(clientSSL.recv(1024))
Jean-Paul Calderone9eadb962008-09-07 21:20:44 -04001216
1217 def test_set_default_verify_paths_signature(self):
1218 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001219 :py:obj:`Context.set_default_verify_paths` takes no arguments and
1220 raises :py:obj:`TypeError` if given any.
Jean-Paul Calderone9eadb962008-09-07 21:20:44 -04001221 """
1222 context = Context(TLSv1_METHOD)
1223 self.assertRaises(TypeError, context.set_default_verify_paths, None)
1224 self.assertRaises(TypeError, context.set_default_verify_paths, 1)
1225 self.assertRaises(TypeError, context.set_default_verify_paths, "")
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05001226
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001227 def test_add_extra_chain_cert_invalid_cert(self):
1228 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001229 :py:obj:`Context.add_extra_chain_cert` raises :py:obj:`TypeError` if
1230 called with other than one argument or if called with an object which
1231 is not an instance of :py:obj:`X509`.
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001232 """
1233 context = Context(TLSv1_METHOD)
1234 self.assertRaises(TypeError, context.add_extra_chain_cert)
1235 self.assertRaises(TypeError, context.add_extra_chain_cert, object())
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001236 self.assertRaises(
1237 TypeError, context.add_extra_chain_cert, object(), object()
1238 )
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001239
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001240 def _handshake_test(self, serverContext, clientContext):
1241 """
1242 Verify that a client and server created with the given contexts can
1243 successfully handshake and communicate.
1244 """
1245 serverSocket, clientSocket = socket_pair()
1246
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001247 server = Connection(serverContext, serverSocket)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001248 server.set_accept_state()
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001249
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001250 client = Connection(clientContext, clientSocket)
1251 client.set_connect_state()
1252
1253 # Make them talk to each other.
1254 # self._interactInMemory(client, server)
1255 for i in range(3):
1256 for s in [client, server]:
1257 try:
1258 s.do_handshake()
1259 except WantReadError:
1260 pass
1261
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001262 def test_set_verify_callback_connection_argument(self):
1263 """
1264 The first argument passed to the verify callback is the
1265 :py:class:`Connection` instance for which verification is taking place.
1266 """
1267 serverContext = Context(TLSv1_METHOD)
1268 serverContext.use_privatekey(
1269 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1270 serverContext.use_certificate(
1271 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1272 serverConnection = Connection(serverContext, None)
1273
1274 class VerifyCallback(object):
1275 def callback(self, connection, *args):
1276 self.connection = connection
1277 return 1
1278
1279 verify = VerifyCallback()
1280 clientContext = Context(TLSv1_METHOD)
1281 clientContext.set_verify(VERIFY_PEER, verify.callback)
1282 clientConnection = Connection(clientContext, None)
1283 clientConnection.set_connect_state()
1284
1285 self._handshakeInMemory(clientConnection, serverConnection)
1286
1287 self.assertIdentical(verify.connection, clientConnection)
1288
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001289 def test_set_verify_callback_exception(self):
1290 """
1291 If the verify callback passed to :py:obj:`Context.set_verify` raises an
1292 exception, verification fails and the exception is propagated to the
1293 caller of :py:obj:`Connection.do_handshake`.
1294 """
1295 serverContext = Context(TLSv1_METHOD)
1296 serverContext.use_privatekey(
1297 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1298 serverContext.use_certificate(
1299 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1300
1301 clientContext = Context(TLSv1_METHOD)
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001302
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001303 def verify_callback(*args):
1304 raise Exception("silly verify failure")
1305 clientContext.set_verify(VERIFY_PEER, verify_callback)
1306
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01001307 with pytest.raises(Exception) as exc:
1308 self._handshake_test(serverContext, clientContext)
1309
1310 self.assertEqual("silly verify failure", str(exc.value))
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001311
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001312 def test_add_extra_chain_cert(self):
1313 """
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001314 :py:obj:`Context.add_extra_chain_cert` accepts an :py:obj:`X509`
1315 instance to add to the certificate chain.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001316
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001317 See :py:obj:`_create_certificate_chain` for the details of the
1318 certificate chain tested.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001319
1320 The chain is tested by starting a server with scert and connecting
1321 to it with a client which trusts cacert and requires verification to
1322 succeed.
1323 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001324 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001325 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1326
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001327 # Dump the CA certificate to a file because that's the only way to load
1328 # it as a trusted CA in the client context.
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001329 for cert, name in [(cacert, 'ca.pem'),
1330 (icert, 'i.pem'),
1331 (scert, 's.pem')]:
Hynek Schlawacke90680f2015-04-16 15:09:27 -04001332 with open(join(self.tmpdir, name), 'w') as f:
1333 f.write(dump_certificate(FILETYPE_PEM, cert).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001334
Hynek Schlawack1902c012015-04-16 15:06:41 -04001335 for key, name in [(cakey, 'ca.key'),
1336 (ikey, 'i.key'),
1337 (skey, 's.key')]:
Hynek Schlawacke90680f2015-04-16 15:09:27 -04001338 with open(join(self.tmpdir, name), 'w') as f:
1339 f.write(dump_privatekey(FILETYPE_PEM, key).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001340
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001341 # Create the server context
1342 serverContext = Context(TLSv1_METHOD)
1343 serverContext.use_privatekey(skey)
1344 serverContext.use_certificate(scert)
Jean-Paul Calderone16cf03d2010-09-08 18:53:39 -04001345 # The client already has cacert, we only need to give them icert.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001346 serverContext.add_extra_chain_cert(icert)
1347
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001348 # Create the client
1349 clientContext = Context(TLSv1_METHOD)
1350 clientContext.set_verify(
1351 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001352 clientContext.load_verify_locations(join(self.tmpdir, "ca.pem"))
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001353
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001354 # Try it out.
1355 self._handshake_test(serverContext, clientContext)
1356
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001357 def _use_certificate_chain_file_test(self, certdir):
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001358 """
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001359 Verify that :py:obj:`Context.use_certificate_chain_file` reads a
1360 certificate chain from a specified file.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001361
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001362 The chain is tested by starting a server with scert and connecting to
1363 it with a client which trusts cacert and requires verification to
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001364 succeed.
1365 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001366 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001367 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1368
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001369 makedirs(certdir)
1370
Jean-Paul Calderone05826732015-04-12 11:38:49 -04001371 chainFile = join_bytes_or_unicode(certdir, "chain.pem")
1372 caFile = join_bytes_or_unicode(certdir, "ca.pem")
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001373
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001374 # Write out the chain file.
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001375 with open(chainFile, 'wb') as fObj:
1376 # Most specific to least general.
1377 fObj.write(dump_certificate(FILETYPE_PEM, scert))
1378 fObj.write(dump_certificate(FILETYPE_PEM, icert))
1379 fObj.write(dump_certificate(FILETYPE_PEM, cacert))
1380
1381 with open(caFile, 'w') as fObj:
1382 fObj.write(dump_certificate(FILETYPE_PEM, cacert).decode('ascii'))
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001383
1384 serverContext = Context(TLSv1_METHOD)
1385 serverContext.use_certificate_chain_file(chainFile)
1386 serverContext.use_privatekey(skey)
1387
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001388 clientContext = Context(TLSv1_METHOD)
1389 clientContext.set_verify(
1390 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001391 clientContext.load_verify_locations(caFile)
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001392
1393 self._handshake_test(serverContext, clientContext)
1394
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001395 def test_use_certificate_chain_file_bytes(self):
1396 """
1397 ``Context.use_certificate_chain_file`` accepts the name of a file (as
1398 an instance of ``bytes``) to specify additional certificates to use to
1399 construct and verify a trust chain.
1400 """
1401 self._use_certificate_chain_file_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001402 self.mktemp() + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001403 )
1404
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001405 def test_use_certificate_chain_file_unicode(self):
1406 """
1407 ``Context.use_certificate_chain_file`` accepts the name of a file (as
1408 an instance of ``unicode``) to specify additional certificates to use
1409 to construct and verify a trust chain.
1410 """
1411 self._use_certificate_chain_file_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001412 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001413 )
1414
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001415 def test_use_certificate_chain_file_wrong_args(self):
1416 """
1417 :py:obj:`Context.use_certificate_chain_file` raises :py:obj:`TypeError`
1418 if passed zero or more than one argument or when passed a non-byte
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001419 string single argument. It also raises :py:obj:`OpenSSL.SSL.Error`
1420 when passed a bad chain file name (for example, the name of a file
1421 which does not exist).
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001422 """
1423 context = Context(TLSv1_METHOD)
1424 self.assertRaises(TypeError, context.use_certificate_chain_file)
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001425 self.assertRaises(
1426 TypeError, context.use_certificate_chain_file, object()
1427 )
1428 self.assertRaises(
1429 TypeError, context.use_certificate_chain_file, b"foo", object()
1430 )
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001431
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001432 self.assertRaises(
1433 Error, context.use_certificate_chain_file, self.mktemp()
1434 )
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001435
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001436 def test_get_verify_mode_wrong_args(self):
1437 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001438 :py:obj:`Context.get_verify_mode` raises :py:obj:`TypeError` if called
1439 with any arguments.
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001440 """
1441 context = Context(TLSv1_METHOD)
1442 self.assertRaises(TypeError, context.get_verify_mode, None)
1443
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001444 def test_set_verify_mode(self):
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001445 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001446 :py:obj:`Context.get_verify_mode` returns the verify mode flags
1447 previously passed to :py:obj:`Context.set_verify`.
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001448 """
1449 context = Context(TLSv1_METHOD)
1450 self.assertEquals(context.get_verify_mode(), 0)
1451 context.set_verify(
1452 VERIFY_PEER | VERIFY_CLIENT_ONCE, lambda *args: None)
1453 self.assertEquals(
1454 context.get_verify_mode(), VERIFY_PEER | VERIFY_CLIENT_ONCE)
1455
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001456 @skip_if_py3
1457 def test_set_verify_mode_long(self):
1458 """
1459 On Python 2 :py:obj:`Context.set_verify_mode` accepts values of
1460 type :py:obj:`long` as well as :py:obj:`int`.
1461 """
1462 context = Context(TLSv1_METHOD)
1463 self.assertEquals(context.get_verify_mode(), 0)
1464 context.set_verify(
Hynek Schlawackb4ceed32015-09-05 20:55:19 +02001465 long(VERIFY_PEER | VERIFY_CLIENT_ONCE), lambda *args: None
1466 ) # pragma: nocover
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001467 self.assertEquals(
1468 context.get_verify_mode(), VERIFY_PEER | VERIFY_CLIENT_ONCE)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001469
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001470 def test_load_tmp_dh_wrong_args(self):
1471 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001472 :py:obj:`Context.load_tmp_dh` raises :py:obj:`TypeError` if called with
1473 the wrong number of arguments or with a non-:py:obj:`str` argument.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001474 """
1475 context = Context(TLSv1_METHOD)
1476 self.assertRaises(TypeError, context.load_tmp_dh)
1477 self.assertRaises(TypeError, context.load_tmp_dh, "foo", None)
1478 self.assertRaises(TypeError, context.load_tmp_dh, object())
1479
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001480 def test_load_tmp_dh_missing_file(self):
1481 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001482 :py:obj:`Context.load_tmp_dh` raises :py:obj:`OpenSSL.SSL.Error` if the
1483 specified file does not exist.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001484 """
1485 context = Context(TLSv1_METHOD)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001486 self.assertRaises(Error, context.load_tmp_dh, b"hello")
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001487
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001488 def _load_tmp_dh_test(self, dhfilename):
Jean-Paul Calderone4e0c43f2015-04-13 10:15:17 -04001489 """
1490 Verify that calling ``Context.load_tmp_dh`` with the given filename
1491 does not raise an exception.
1492 """
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001493 context = Context(TLSv1_METHOD)
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001494 with open(dhfilename, "w") as dhfile:
1495 dhfile.write(dhparam)
1496
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001497 context.load_tmp_dh(dhfilename)
1498 # XXX What should I assert here? -exarkun
1499
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001500 def test_load_tmp_dh_bytes(self):
1501 """
1502 :py:obj:`Context.load_tmp_dh` loads Diffie-Hellman parameters from the
1503 specified file (given as ``bytes``).
1504 """
1505 self._load_tmp_dh_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001506 self.mktemp() + NON_ASCII.encode(getfilesystemencoding()),
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001507 )
1508
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001509 def test_load_tmp_dh_unicode(self):
1510 """
1511 :py:obj:`Context.load_tmp_dh` loads Diffie-Hellman parameters from the
1512 specified file (given as ``unicode``).
1513 """
1514 self._load_tmp_dh_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001515 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII,
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001516 )
1517
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001518 def test_set_tmp_ecdh(self):
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001519 """
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001520 :py:obj:`Context.set_tmp_ecdh` sets the elliptic curve for
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001521 Diffie-Hellman to the specified curve.
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001522 """
1523 context = Context(TLSv1_METHOD)
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001524 for curve in get_elliptic_curves():
Hynek Schlawacka07fa8c2015-10-17 10:15:28 +02001525 if curve.name.startswith(u"Oakley-"):
Hynek Schlawack7408aff2015-10-17 09:51:16 +02001526 # Setting Oakley-EC2N-4 and Oakley-EC2N-3 adds
1527 # ('bignum routines', 'BN_mod_inverse', 'no inverse') to the
1528 # error queue on OpenSSL 1.0.2.
1529 continue
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001530 # The only easily "assertable" thing is that it does not raise an
1531 # exception.
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001532 context.set_tmp_ecdh(curve)
Alex Gaynor12dc0842014-01-17 12:51:31 -06001533
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001534 def test_set_session_cache_mode_wrong_args(self):
1535 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001536 :py:obj:`Context.set_session_cache_mode` raises :py:obj:`TypeError` if
1537 called with other than one integer argument.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001538 """
1539 context = Context(TLSv1_METHOD)
1540 self.assertRaises(TypeError, context.set_session_cache_mode)
1541 self.assertRaises(TypeError, context.set_session_cache_mode, object())
1542
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001543 def test_get_session_cache_mode_wrong_args(self):
1544 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001545 :py:obj:`Context.get_session_cache_mode` raises :py:obj:`TypeError` if
1546 called with any arguments.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001547 """
1548 context = Context(TLSv1_METHOD)
1549 self.assertRaises(TypeError, context.get_session_cache_mode, 1)
1550
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001551 def test_session_cache_mode(self):
1552 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001553 :py:obj:`Context.set_session_cache_mode` specifies how sessions are
1554 cached. The setting can be retrieved via
1555 :py:obj:`Context.get_session_cache_mode`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001556 """
1557 context = Context(TLSv1_METHOD)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001558 context.set_session_cache_mode(SESS_CACHE_OFF)
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001559 off = context.set_session_cache_mode(SESS_CACHE_BOTH)
1560 self.assertEqual(SESS_CACHE_OFF, off)
1561 self.assertEqual(SESS_CACHE_BOTH, context.get_session_cache_mode())
1562
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001563 @skip_if_py3
1564 def test_session_cache_mode_long(self):
1565 """
1566 On Python 2 :py:obj:`Context.set_session_cache_mode` accepts values
1567 of type :py:obj:`long` as well as :py:obj:`int`.
1568 """
1569 context = Context(TLSv1_METHOD)
1570 context.set_session_cache_mode(long(SESS_CACHE_BOTH))
1571 self.assertEqual(
1572 SESS_CACHE_BOTH, context.get_session_cache_mode())
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001573
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001574 def test_get_cert_store(self):
1575 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001576 :py:obj:`Context.get_cert_store` returns a :py:obj:`X509Store`
1577 instance.
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001578 """
1579 context = Context(TLSv1_METHOD)
1580 store = context.get_cert_store()
1581 self.assertIsInstance(store, X509Store)
1582
1583
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001584class TestServerNameCallback(object):
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001585 """
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001586 Tests for `Context.set_tlsext_servername_callback` and its
1587 interaction with `Connection`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001588 """
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001589 def test_old_callback_forgotten(self):
1590 """
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001591 If `Context.set_tlsext_servername_callback` is used to specify
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001592 a new callback, the one it replaces is dereferenced.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001593 """
1594 def callback(connection):
1595 pass
1596
1597 def replacement(connection):
1598 pass
1599
1600 context = Context(TLSv1_METHOD)
1601 context.set_tlsext_servername_callback(callback)
1602
1603 tracker = ref(callback)
1604 del callback
1605
1606 context.set_tlsext_servername_callback(replacement)
Jean-Paul Calderoned4033eb2014-01-11 08:21:46 -05001607
1608 # One run of the garbage collector happens to work on CPython. PyPy
1609 # doesn't collect the underlying object until a second run for whatever
1610 # reason. That's fine, it still demonstrates our code has properly
1611 # dropped the reference.
1612 collect()
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001613 collect()
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001614
1615 callback = tracker()
1616 if callback is not None:
1617 referrers = get_referrers(callback)
Jean-Paul Calderone7de39562014-01-11 08:17:59 -05001618 if len(referrers) > 1:
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001619 self.fail("Some references remain: %r" % (referrers,))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001620
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001621 def test_no_servername(self):
1622 """
1623 When a client specifies no server name, the callback passed to
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001624 `Context.set_tlsext_servername_callback` is invoked and the
1625 result of `Connection.get_servername` is `None`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001626 """
1627 args = []
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001628
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001629 def servername(conn):
1630 args.append((conn, conn.get_servername()))
1631 context = Context(TLSv1_METHOD)
1632 context.set_tlsext_servername_callback(servername)
1633
1634 # Lose our reference to it. The Context is responsible for keeping it
1635 # alive now.
1636 del servername
1637 collect()
1638
1639 # Necessary to actually accept the connection
1640 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001641 context.use_certificate(
1642 load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001643
1644 # Do a little connection to trigger the logic
1645 server = Connection(context, None)
1646 server.set_accept_state()
1647
1648 client = Connection(Context(TLSv1_METHOD), None)
1649 client.set_connect_state()
1650
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001651 interact_in_memory(server, client)
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001652
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001653 assert args == [(server, None)]
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001654
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001655 def test_servername(self):
1656 """
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001657 When a client specifies a server name in its hello message, the
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001658 callback passed to `Contexts.set_tlsext_servername_callback` is
1659 invoked and the result of `Connection.get_servername` is that
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001660 server name.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001661 """
1662 args = []
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001663
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001664 def servername(conn):
1665 args.append((conn, conn.get_servername()))
1666 context = Context(TLSv1_METHOD)
1667 context.set_tlsext_servername_callback(servername)
1668
1669 # Necessary to actually accept the connection
1670 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001671 context.use_certificate(
1672 load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001673
1674 # Do a little connection to trigger the logic
1675 server = Connection(context, None)
1676 server.set_accept_state()
1677
1678 client = Connection(Context(TLSv1_METHOD), None)
1679 client.set_connect_state()
Alex Gaynore7f51982016-09-11 11:48:14 -04001680 client.set_tlsext_host_name(b"foo1.example.com")
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001681
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001682 interact_in_memory(server, client)
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001683
Alex Chan1ca9e3a2016-11-05 13:01:51 +00001684 assert args == [(server, b"foo1.example.com")]
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001685
1686
Cory Benfield84a121e2014-03-31 20:30:25 +01001687class NextProtoNegotiationTests(TestCase, _LoopbackMixin):
1688 """
1689 Test for Next Protocol Negotiation in PyOpenSSL.
1690 """
Cory Benfieldba1820d2015-04-13 17:39:12 -04001691 if _lib.Cryptography_HAS_NEXTPROTONEG:
1692 def test_npn_success(self):
1693 """
1694 Tests that clients and servers that agree on the negotiated next
1695 protocol can correct establish a connection, and that the agreed
1696 protocol is reported by the connections.
1697 """
1698 advertise_args = []
1699 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001700
Cory Benfieldba1820d2015-04-13 17:39:12 -04001701 def advertise(conn):
1702 advertise_args.append((conn,))
1703 return [b'http/1.1', b'spdy/2']
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001704
Cory Benfieldba1820d2015-04-13 17:39:12 -04001705 def select(conn, options):
1706 select_args.append((conn, options))
1707 return b'spdy/2'
Cory Benfield84a121e2014-03-31 20:30:25 +01001708
Cory Benfieldba1820d2015-04-13 17:39:12 -04001709 server_context = Context(TLSv1_METHOD)
1710 server_context.set_npn_advertise_callback(advertise)
Cory Benfield84a121e2014-03-31 20:30:25 +01001711
Cory Benfieldba1820d2015-04-13 17:39:12 -04001712 client_context = Context(TLSv1_METHOD)
1713 client_context.set_npn_select_callback(select)
Cory Benfield84a121e2014-03-31 20:30:25 +01001714
Cory Benfieldba1820d2015-04-13 17:39:12 -04001715 # Necessary to actually accept the connection
1716 server_context.use_privatekey(
1717 load_privatekey(FILETYPE_PEM, server_key_pem))
1718 server_context.use_certificate(
1719 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield84a121e2014-03-31 20:30:25 +01001720
Cory Benfieldba1820d2015-04-13 17:39:12 -04001721 # Do a little connection to trigger the logic
1722 server = Connection(server_context, None)
1723 server.set_accept_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001724
Cory Benfieldba1820d2015-04-13 17:39:12 -04001725 client = Connection(client_context, None)
1726 client.set_connect_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001727
Cory Benfieldba1820d2015-04-13 17:39:12 -04001728 self._interactInMemory(server, client)
Cory Benfield84a121e2014-03-31 20:30:25 +01001729
Cory Benfieldba1820d2015-04-13 17:39:12 -04001730 self.assertEqual([(server,)], advertise_args)
1731 self.assertEqual([(client, [b'http/1.1', b'spdy/2'])], select_args)
Cory Benfield84a121e2014-03-31 20:30:25 +01001732
Cory Benfieldba1820d2015-04-13 17:39:12 -04001733 self.assertEqual(server.get_next_proto_negotiated(), b'spdy/2')
1734 self.assertEqual(client.get_next_proto_negotiated(), b'spdy/2')
Cory Benfield84a121e2014-03-31 20:30:25 +01001735
Cory Benfieldba1820d2015-04-13 17:39:12 -04001736 def test_npn_client_fail(self):
1737 """
1738 Tests that when clients and servers cannot agree on what protocol
1739 to use next that the TLS connection does not get established.
1740 """
1741 advertise_args = []
1742 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001743
Cory Benfieldba1820d2015-04-13 17:39:12 -04001744 def advertise(conn):
1745 advertise_args.append((conn,))
1746 return [b'http/1.1', b'spdy/2']
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001747
Cory Benfieldba1820d2015-04-13 17:39:12 -04001748 def select(conn, options):
1749 select_args.append((conn, options))
1750 return b''
Cory Benfield84a121e2014-03-31 20:30:25 +01001751
Cory Benfieldba1820d2015-04-13 17:39:12 -04001752 server_context = Context(TLSv1_METHOD)
1753 server_context.set_npn_advertise_callback(advertise)
Cory Benfield84a121e2014-03-31 20:30:25 +01001754
Cory Benfieldba1820d2015-04-13 17:39:12 -04001755 client_context = Context(TLSv1_METHOD)
1756 client_context.set_npn_select_callback(select)
Cory Benfield84a121e2014-03-31 20:30:25 +01001757
Cory Benfieldba1820d2015-04-13 17:39:12 -04001758 # Necessary to actually accept the connection
1759 server_context.use_privatekey(
1760 load_privatekey(FILETYPE_PEM, server_key_pem))
1761 server_context.use_certificate(
1762 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield84a121e2014-03-31 20:30:25 +01001763
Cory Benfieldba1820d2015-04-13 17:39:12 -04001764 # Do a little connection to trigger the logic
1765 server = Connection(server_context, None)
1766 server.set_accept_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001767
Cory Benfieldba1820d2015-04-13 17:39:12 -04001768 client = Connection(client_context, None)
1769 client.set_connect_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001770
Cory Benfieldba1820d2015-04-13 17:39:12 -04001771 # If the client doesn't return anything, the connection will fail.
1772 self.assertRaises(Error, self._interactInMemory, server, client)
Cory Benfield84a121e2014-03-31 20:30:25 +01001773
Cory Benfieldba1820d2015-04-13 17:39:12 -04001774 self.assertEqual([(server,)], advertise_args)
1775 self.assertEqual([(client, [b'http/1.1', b'spdy/2'])], select_args)
Cory Benfield84a121e2014-03-31 20:30:25 +01001776
Cory Benfieldba1820d2015-04-13 17:39:12 -04001777 def test_npn_select_error(self):
1778 """
1779 Test that we can handle exceptions in the select callback. If
1780 select fails it should be fatal to the connection.
1781 """
1782 advertise_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001783
Cory Benfieldba1820d2015-04-13 17:39:12 -04001784 def advertise(conn):
1785 advertise_args.append((conn,))
1786 return [b'http/1.1', b'spdy/2']
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001787
Cory Benfieldba1820d2015-04-13 17:39:12 -04001788 def select(conn, options):
1789 raise TypeError
Cory Benfield0ea76e72015-03-22 09:05:28 +00001790
Cory Benfieldba1820d2015-04-13 17:39:12 -04001791 server_context = Context(TLSv1_METHOD)
1792 server_context.set_npn_advertise_callback(advertise)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001793
Cory Benfieldba1820d2015-04-13 17:39:12 -04001794 client_context = Context(TLSv1_METHOD)
1795 client_context.set_npn_select_callback(select)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001796
Cory Benfieldba1820d2015-04-13 17:39:12 -04001797 # Necessary to actually accept the connection
1798 server_context.use_privatekey(
1799 load_privatekey(FILETYPE_PEM, server_key_pem))
1800 server_context.use_certificate(
1801 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield0ea76e72015-03-22 09:05:28 +00001802
Cory Benfieldba1820d2015-04-13 17:39:12 -04001803 # Do a little connection to trigger the logic
1804 server = Connection(server_context, None)
1805 server.set_accept_state()
Cory Benfield0ea76e72015-03-22 09:05:28 +00001806
Cory Benfieldba1820d2015-04-13 17:39:12 -04001807 client = Connection(client_context, None)
1808 client.set_connect_state()
Cory Benfield0ea76e72015-03-22 09:05:28 +00001809
Cory Benfieldba1820d2015-04-13 17:39:12 -04001810 # If the callback throws an exception it should be raised here.
1811 self.assertRaises(
1812 TypeError, self._interactInMemory, server, client
1813 )
1814 self.assertEqual([(server,)], advertise_args)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001815
Cory Benfieldba1820d2015-04-13 17:39:12 -04001816 def test_npn_advertise_error(self):
1817 """
1818 Test that we can handle exceptions in the advertise callback. If
1819 advertise fails no NPN is advertised to the client.
1820 """
1821 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001822
Cory Benfieldba1820d2015-04-13 17:39:12 -04001823 def advertise(conn):
1824 raise TypeError
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001825
Hynek Schlawackb4ceed32015-09-05 20:55:19 +02001826 def select(conn, options): # pragma: nocover
1827 """
1828 Assert later that no args are actually appended.
1829 """
Cory Benfieldba1820d2015-04-13 17:39:12 -04001830 select_args.append((conn, options))
1831 return b''
Cory Benfield0ea76e72015-03-22 09:05:28 +00001832
Cory Benfieldba1820d2015-04-13 17:39:12 -04001833 server_context = Context(TLSv1_METHOD)
1834 server_context.set_npn_advertise_callback(advertise)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001835
Cory Benfieldba1820d2015-04-13 17:39:12 -04001836 client_context = Context(TLSv1_METHOD)
1837 client_context.set_npn_select_callback(select)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001838
Cory Benfieldba1820d2015-04-13 17:39:12 -04001839 # Necessary to actually accept the connection
1840 server_context.use_privatekey(
1841 load_privatekey(FILETYPE_PEM, server_key_pem))
1842 server_context.use_certificate(
1843 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield0ea76e72015-03-22 09:05:28 +00001844
Cory Benfieldba1820d2015-04-13 17:39:12 -04001845 # Do a little connection to trigger the logic
1846 server = Connection(server_context, None)
1847 server.set_accept_state()
Cory Benfield0ea76e72015-03-22 09:05:28 +00001848
Cory Benfieldba1820d2015-04-13 17:39:12 -04001849 client = Connection(client_context, None)
1850 client.set_connect_state()
Cory Benfield0ea76e72015-03-22 09:05:28 +00001851
Cory Benfieldba1820d2015-04-13 17:39:12 -04001852 # If the client doesn't return anything, the connection will fail.
1853 self.assertRaises(
1854 TypeError, self._interactInMemory, server, client
1855 )
1856 self.assertEqual([], select_args)
1857
1858 else:
1859 # No NPN.
1860 def test_npn_not_implemented(self):
1861 # Test the context methods first.
1862 context = Context(TLSv1_METHOD)
1863 fail_methods = [
1864 context.set_npn_advertise_callback,
1865 context.set_npn_select_callback,
1866 ]
1867 for method in fail_methods:
1868 self.assertRaises(
1869 NotImplementedError, method, None
1870 )
1871
1872 # Now test a connection.
1873 conn = Connection(context)
1874 fail_methods = [
1875 conn.get_next_proto_negotiated,
1876 ]
1877 for method in fail_methods:
1878 self.assertRaises(NotImplementedError, method)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001879
1880
Cory Benfield12eae892014-06-07 15:42:56 +01001881class ApplicationLayerProtoNegotiationTests(TestCase, _LoopbackMixin):
1882 """
1883 Tests for ALPN in PyOpenSSL.
1884 """
Cory Benfielde46fa842015-04-13 16:50:49 -04001885 # Skip tests on versions that don't support ALPN.
1886 if _lib.Cryptography_HAS_ALPN:
Cory Benfield12eae892014-06-07 15:42:56 +01001887
Cory Benfielde46fa842015-04-13 16:50:49 -04001888 def test_alpn_success(self):
1889 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04001890 Clients and servers that agree on the negotiated ALPN protocol can
1891 correct establish a connection, and the agreed protocol is reported
1892 by the connections.
Cory Benfielde46fa842015-04-13 16:50:49 -04001893 """
1894 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001895
Cory Benfielde46fa842015-04-13 16:50:49 -04001896 def select(conn, options):
1897 select_args.append((conn, options))
1898 return b'spdy/2'
Cory Benfield12eae892014-06-07 15:42:56 +01001899
Cory Benfielde46fa842015-04-13 16:50:49 -04001900 client_context = Context(TLSv1_METHOD)
1901 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfield12eae892014-06-07 15:42:56 +01001902
Cory Benfielde46fa842015-04-13 16:50:49 -04001903 server_context = Context(TLSv1_METHOD)
1904 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01001905
Cory Benfielde46fa842015-04-13 16:50:49 -04001906 # Necessary to actually accept the connection
1907 server_context.use_privatekey(
1908 load_privatekey(FILETYPE_PEM, server_key_pem))
1909 server_context.use_certificate(
1910 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield12eae892014-06-07 15:42:56 +01001911
Cory Benfielde46fa842015-04-13 16:50:49 -04001912 # Do a little connection to trigger the logic
1913 server = Connection(server_context, None)
1914 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001915
Cory Benfielde46fa842015-04-13 16:50:49 -04001916 client = Connection(client_context, None)
1917 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001918
Cory Benfielde46fa842015-04-13 16:50:49 -04001919 self._interactInMemory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001920
Cory Benfielde46fa842015-04-13 16:50:49 -04001921 self.assertEqual([(server, [b'http/1.1', b'spdy/2'])], select_args)
1922
1923 self.assertEqual(server.get_alpn_proto_negotiated(), b'spdy/2')
1924 self.assertEqual(client.get_alpn_proto_negotiated(), b'spdy/2')
Cory Benfield12eae892014-06-07 15:42:56 +01001925
Cory Benfielde46fa842015-04-13 16:50:49 -04001926 def test_alpn_set_on_connection(self):
1927 """
1928 The same as test_alpn_success, but setting the ALPN protocols on
1929 the connection rather than the context.
1930 """
1931 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001932
Cory Benfielde46fa842015-04-13 16:50:49 -04001933 def select(conn, options):
1934 select_args.append((conn, options))
1935 return b'spdy/2'
Cory Benfield12eae892014-06-07 15:42:56 +01001936
Cory Benfielde46fa842015-04-13 16:50:49 -04001937 # Setup the client context but don't set any ALPN protocols.
1938 client_context = Context(TLSv1_METHOD)
Cory Benfield12eae892014-06-07 15:42:56 +01001939
Cory Benfielde46fa842015-04-13 16:50:49 -04001940 server_context = Context(TLSv1_METHOD)
1941 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01001942
Cory Benfielde46fa842015-04-13 16:50:49 -04001943 # Necessary to actually accept the connection
1944 server_context.use_privatekey(
1945 load_privatekey(FILETYPE_PEM, server_key_pem))
1946 server_context.use_certificate(
1947 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield12eae892014-06-07 15:42:56 +01001948
Cory Benfielde46fa842015-04-13 16:50:49 -04001949 # Do a little connection to trigger the logic
1950 server = Connection(server_context, None)
1951 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001952
Cory Benfielde46fa842015-04-13 16:50:49 -04001953 # Set the ALPN protocols on the client connection.
1954 client = Connection(client_context, None)
1955 client.set_alpn_protos([b'http/1.1', b'spdy/2'])
1956 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001957
Cory Benfielde46fa842015-04-13 16:50:49 -04001958 self._interactInMemory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001959
Cory Benfielde46fa842015-04-13 16:50:49 -04001960 self.assertEqual([(server, [b'http/1.1', b'spdy/2'])], select_args)
Cory Benfield12eae892014-06-07 15:42:56 +01001961
Cory Benfielde46fa842015-04-13 16:50:49 -04001962 self.assertEqual(server.get_alpn_proto_negotiated(), b'spdy/2')
1963 self.assertEqual(client.get_alpn_proto_negotiated(), b'spdy/2')
Cory Benfield12eae892014-06-07 15:42:56 +01001964
Cory Benfielde46fa842015-04-13 16:50:49 -04001965 def test_alpn_server_fail(self):
1966 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04001967 When clients and servers cannot agree on what protocol to use next
1968 the TLS connection does not get established.
Cory Benfielde46fa842015-04-13 16:50:49 -04001969 """
1970 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001971
Cory Benfielde46fa842015-04-13 16:50:49 -04001972 def select(conn, options):
1973 select_args.append((conn, options))
1974 return b''
Cory Benfield12eae892014-06-07 15:42:56 +01001975
Cory Benfielde46fa842015-04-13 16:50:49 -04001976 client_context = Context(TLSv1_METHOD)
1977 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfield12eae892014-06-07 15:42:56 +01001978
Cory Benfielde46fa842015-04-13 16:50:49 -04001979 server_context = Context(TLSv1_METHOD)
1980 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01001981
Cory Benfielde46fa842015-04-13 16:50:49 -04001982 # Necessary to actually accept the connection
1983 server_context.use_privatekey(
1984 load_privatekey(FILETYPE_PEM, server_key_pem))
1985 server_context.use_certificate(
1986 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield12eae892014-06-07 15:42:56 +01001987
Cory Benfielde46fa842015-04-13 16:50:49 -04001988 # Do a little connection to trigger the logic
1989 server = Connection(server_context, None)
1990 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001991
Cory Benfielde46fa842015-04-13 16:50:49 -04001992 client = Connection(client_context, None)
1993 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001994
Cory Benfielde46fa842015-04-13 16:50:49 -04001995 # If the client doesn't return anything, the connection will fail.
1996 self.assertRaises(Error, self._interactInMemory, server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001997
Cory Benfielde46fa842015-04-13 16:50:49 -04001998 self.assertEqual([(server, [b'http/1.1', b'spdy/2'])], select_args)
Cory Benfield12eae892014-06-07 15:42:56 +01001999
Cory Benfielde46fa842015-04-13 16:50:49 -04002000 def test_alpn_no_server(self):
2001 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04002002 When clients and servers cannot agree on what protocol to use next
2003 because the server doesn't offer ALPN, no protocol is negotiated.
Cory Benfielde46fa842015-04-13 16:50:49 -04002004 """
2005 client_context = Context(TLSv1_METHOD)
2006 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfielde3d57152015-04-11 17:57:35 -04002007
Cory Benfielde46fa842015-04-13 16:50:49 -04002008 server_context = Context(TLSv1_METHOD)
Cory Benfielde3d57152015-04-11 17:57:35 -04002009
Cory Benfielde46fa842015-04-13 16:50:49 -04002010 # Necessary to actually accept the connection
2011 server_context.use_privatekey(
2012 load_privatekey(FILETYPE_PEM, server_key_pem))
2013 server_context.use_certificate(
2014 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfielde3d57152015-04-11 17:57:35 -04002015
Cory Benfielde46fa842015-04-13 16:50:49 -04002016 # Do a little connection to trigger the logic
2017 server = Connection(server_context, None)
2018 server.set_accept_state()
Cory Benfielde3d57152015-04-11 17:57:35 -04002019
Cory Benfielde46fa842015-04-13 16:50:49 -04002020 client = Connection(client_context, None)
2021 client.set_connect_state()
Cory Benfielde3d57152015-04-11 17:57:35 -04002022
Cory Benfielde46fa842015-04-13 16:50:49 -04002023 # Do the dance.
2024 self._interactInMemory(server, client)
Cory Benfielde3d57152015-04-11 17:57:35 -04002025
Cory Benfielde46fa842015-04-13 16:50:49 -04002026 self.assertEqual(client.get_alpn_proto_negotiated(), b'')
Cory Benfielde3d57152015-04-11 17:57:35 -04002027
Cory Benfielde46fa842015-04-13 16:50:49 -04002028 def test_alpn_callback_exception(self):
2029 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04002030 We can handle exceptions in the ALPN select callback.
Cory Benfielde46fa842015-04-13 16:50:49 -04002031 """
2032 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002033
Cory Benfielde46fa842015-04-13 16:50:49 -04002034 def select(conn, options):
2035 select_args.append((conn, options))
Cory Benfieldef401452015-04-13 18:17:36 -04002036 raise TypeError()
Cory Benfieldf1177e72015-04-12 09:11:49 -04002037
Cory Benfielde46fa842015-04-13 16:50:49 -04002038 client_context = Context(TLSv1_METHOD)
2039 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfieldf1177e72015-04-12 09:11:49 -04002040
Cory Benfielde46fa842015-04-13 16:50:49 -04002041 server_context = Context(TLSv1_METHOD)
2042 server_context.set_alpn_select_callback(select)
Cory Benfieldf1177e72015-04-12 09:11:49 -04002043
Cory Benfielde46fa842015-04-13 16:50:49 -04002044 # Necessary to actually accept the connection
2045 server_context.use_privatekey(
2046 load_privatekey(FILETYPE_PEM, server_key_pem))
2047 server_context.use_certificate(
2048 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfieldf1177e72015-04-12 09:11:49 -04002049
Cory Benfielde46fa842015-04-13 16:50:49 -04002050 # Do a little connection to trigger the logic
2051 server = Connection(server_context, None)
2052 server.set_accept_state()
Cory Benfieldf1177e72015-04-12 09:11:49 -04002053
Cory Benfielde46fa842015-04-13 16:50:49 -04002054 client = Connection(client_context, None)
2055 client.set_connect_state()
Cory Benfieldf1177e72015-04-12 09:11:49 -04002056
Cory Benfielde46fa842015-04-13 16:50:49 -04002057 self.assertRaises(
2058 TypeError, self._interactInMemory, server, client
2059 )
2060 self.assertEqual([(server, [b'http/1.1', b'spdy/2'])], select_args)
Cory Benfieldf1177e72015-04-12 09:11:49 -04002061
Cory Benfield0f7b04c2015-04-13 17:51:12 -04002062 else:
2063 # No ALPN.
2064 def test_alpn_not_implemented(self):
Cory Benfieldef401452015-04-13 18:17:36 -04002065 """
2066 If ALPN is not in OpenSSL, we should raise NotImplementedError.
2067 """
Cory Benfield0f7b04c2015-04-13 17:51:12 -04002068 # Test the context methods first.
2069 context = Context(TLSv1_METHOD)
Cory Benfield307e9e62015-04-13 18:21:12 -04002070 self.assertRaises(
2071 NotImplementedError, context.set_alpn_protos, None
2072 )
2073 self.assertRaises(
2074 NotImplementedError, context.set_alpn_select_callback, None
2075 )
Cory Benfield0f7b04c2015-04-13 17:51:12 -04002076
2077 # Now test a connection.
2078 conn = Connection(context)
Cory Benfield307e9e62015-04-13 18:21:12 -04002079 self.assertRaises(
Alex Gaynor68417232015-09-04 07:56:29 -04002080 NotImplementedError, conn.set_alpn_protos, None
Cory Benfield307e9e62015-04-13 18:21:12 -04002081 )
Cory Benfield0f7b04c2015-04-13 17:51:12 -04002082
Cory Benfieldf1177e72015-04-12 09:11:49 -04002083
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05002084class SessionTests(TestCase):
2085 """
2086 Unit tests for :py:obj:`OpenSSL.SSL.Session`.
2087 """
2088 def test_construction(self):
2089 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002090 :py:class:`Session` can be constructed with no arguments, creating
2091 a new instance of that type.
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05002092 """
2093 new_session = Session()
2094 self.assertTrue(isinstance(new_session, Session))
2095
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05002096 def test_construction_wrong_args(self):
2097 """
2098 If any arguments are passed to :py:class:`Session`, :py:obj:`TypeError`
2099 is raised.
2100 """
2101 self.assertRaises(TypeError, Session, 123)
2102 self.assertRaises(TypeError, Session, "hello")
2103 self.assertRaises(TypeError, Session, object())
2104
2105
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002106class ConnectionTests(TestCase, _LoopbackMixin):
Rick Deane15b1472009-07-09 15:53:42 -05002107 """
Hynek Schlawackaa861212016-03-13 13:53:48 +01002108 Unit tests for :class:`OpenSSL.SSL.Connection`.
Rick Deane15b1472009-07-09 15:53:42 -05002109 """
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04002110 # XXX get_peer_certificate -> None
2111 # XXX sock_shutdown
2112 # XXX master_key -> TypeError
2113 # XXX server_random -> TypeError
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04002114 # XXX connect -> TypeError
2115 # XXX connect_ex -> TypeError
2116 # XXX set_connect_state -> TypeError
2117 # XXX set_accept_state -> TypeError
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04002118 # XXX do_handshake -> TypeError
2119 # XXX bio_read -> TypeError
2120 # XXX recv -> TypeError
2121 # XXX send -> TypeError
2122 # XXX bio_write -> TypeError
2123
Rick Deane15b1472009-07-09 15:53:42 -05002124 def test_type(self):
2125 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002126 :py:obj:`Connection` and :py:obj:`ConnectionType` refer to the same
2127 type object and can be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -05002128 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002129 self.assertIdentical(Connection, ConnectionType)
Rick Deane15b1472009-07-09 15:53:42 -05002130 ctx = Context(TLSv1_METHOD)
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002131 self.assertConsistentType(Connection, 'Connection', ctx, None)
Rick Deane15b1472009-07-09 15:53:42 -05002132
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002133 def test_get_context(self):
2134 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002135 :py:obj:`Connection.get_context` returns the :py:obj:`Context` instance
2136 used to construct the :py:obj:`Connection` instance.
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002137 """
2138 context = Context(TLSv1_METHOD)
2139 connection = Connection(context, None)
2140 self.assertIdentical(connection.get_context(), context)
2141
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002142 def test_get_context_wrong_args(self):
2143 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002144 :py:obj:`Connection.get_context` raises :py:obj:`TypeError` if called
2145 with any arguments.
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002146 """
2147 connection = Connection(Context(TLSv1_METHOD), None)
2148 self.assertRaises(TypeError, connection.get_context, None)
2149
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002150 def test_set_context_wrong_args(self):
2151 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002152 :py:obj:`Connection.set_context` raises :py:obj:`TypeError` if called
2153 with a non-:py:obj:`Context` instance argument or with any number of
2154 arguments other than 1.
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002155 """
2156 ctx = Context(TLSv1_METHOD)
2157 connection = Connection(ctx, None)
2158 self.assertRaises(TypeError, connection.set_context)
2159 self.assertRaises(TypeError, connection.set_context, object())
2160 self.assertRaises(TypeError, connection.set_context, "hello")
2161 self.assertRaises(TypeError, connection.set_context, 1)
2162 self.assertRaises(TypeError, connection.set_context, 1, 2)
2163 self.assertRaises(
2164 TypeError, connection.set_context, Context(TLSv1_METHOD), 2)
2165 self.assertIdentical(ctx, connection.get_context())
2166
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002167 def test_set_context(self):
2168 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002169 :py:obj:`Connection.set_context` specifies a new :py:obj:`Context`
2170 instance to be used for the connection.
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002171 """
2172 original = Context(SSLv23_METHOD)
2173 replacement = Context(TLSv1_METHOD)
2174 connection = Connection(original, None)
2175 connection.set_context(replacement)
2176 self.assertIdentical(replacement, connection.get_context())
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002177 # Lose our references to the contexts, just in case the Connection
2178 # isn't properly managing its own contributions to their reference
2179 # counts.
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002180 del original, replacement
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002181 collect()
2182
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002183 def test_set_tlsext_host_name_wrong_args(self):
2184 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002185 If :py:obj:`Connection.set_tlsext_host_name` is called with a non-byte
2186 string argument or a byte string with an embedded NUL or other than one
Jonathan Ballet648875f2011-07-16 14:14:58 +09002187 argument, :py:obj:`TypeError` is raised.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002188 """
2189 conn = Connection(Context(TLSv1_METHOD), None)
2190 self.assertRaises(TypeError, conn.set_tlsext_host_name)
2191 self.assertRaises(TypeError, conn.set_tlsext_host_name, object())
2192 self.assertRaises(TypeError, conn.set_tlsext_host_name, 123, 456)
2193 self.assertRaises(
Alex Gaynore7f51982016-09-11 11:48:14 -04002194 TypeError, conn.set_tlsext_host_name, b"with\0null")
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002195
Abraham Martinc5484ba2015-03-25 15:33:05 +00002196 if PY3:
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002197 # On Python 3.x, don't accidentally implicitly convert from text.
2198 self.assertRaises(
2199 TypeError,
Alex Gaynore7f51982016-09-11 11:48:14 -04002200 conn.set_tlsext_host_name, b"example.com".decode("ascii"))
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002201
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04002202 def test_get_servername_wrong_args(self):
2203 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002204 :py:obj:`Connection.get_servername` raises :py:obj:`TypeError` if
2205 called with any arguments.
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04002206 """
2207 connection = Connection(Context(TLSv1_METHOD), None)
2208 self.assertRaises(TypeError, connection.get_servername, object())
2209 self.assertRaises(TypeError, connection.get_servername, 1)
2210 self.assertRaises(TypeError, connection.get_servername, "hello")
2211
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002212 def test_pending(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002213 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002214 :py:obj:`Connection.pending` returns the number of bytes available for
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002215 immediate read.
2216 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002217 connection = Connection(Context(TLSv1_METHOD), None)
2218 self.assertEquals(connection.pending(), 0)
2219
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002220 def test_pending_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002221 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002222 :py:obj:`Connection.pending` raises :py:obj:`TypeError` if called with
2223 any arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002224 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002225 connection = Connection(Context(TLSv1_METHOD), None)
2226 self.assertRaises(TypeError, connection.pending, None)
2227
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002228 def test_peek(self):
2229 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002230 :py:obj:`Connection.recv` peeks into the connection if
2231 :py:obj:`socket.MSG_PEEK` is passed.
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002232 """
2233 server, client = self._loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002234 server.send(b'xy')
2235 self.assertEqual(client.recv(2, MSG_PEEK), b'xy')
2236 self.assertEqual(client.recv(2, MSG_PEEK), b'xy')
2237 self.assertEqual(client.recv(2), b'xy')
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002238
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002239 def test_connect_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002240 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002241 :py:obj:`Connection.connect` raises :py:obj:`TypeError` if called with
2242 a non-address argument or with the wrong number of arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002243 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002244 connection = Connection(Context(TLSv1_METHOD), socket())
2245 self.assertRaises(TypeError, connection.connect, None)
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002246 self.assertRaises(TypeError, connection.connect)
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002247 self.assertRaises(
2248 TypeError, connection.connect, ("127.0.0.1", 1), None
2249 )
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002250
kjavfe508d62015-09-02 12:20:35 +01002251 def test_connection_undefined_attr(self):
2252 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002253 :py:obj:`Connection.connect` raises :py:obj:`TypeError` if called with
2254 a non-address argument or with the wrong number of arguments.
kjavfe508d62015-09-02 12:20:35 +01002255 """
Alex Gaynor1aabb2e2015-09-05 13:35:18 -04002256
kjavfe508d62015-09-02 12:20:35 +01002257 def attr_access_test(connection):
2258 return connection.an_attribute_which_is_not_defined
Alex Gaynor1aabb2e2015-09-05 13:35:18 -04002259
kjavfe508d62015-09-02 12:20:35 +01002260 connection = Connection(Context(TLSv1_METHOD), None)
2261 self.assertRaises(AttributeError, attr_access_test, connection)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002262
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002263 def test_connect_refused(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002264 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002265 :py:obj:`Connection.connect` raises :py:obj:`socket.error` if the
2266 underlying socket connect method raises it.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002267 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002268 client = socket()
2269 context = Context(TLSv1_METHOD)
2270 clientSSL = Connection(context, client)
Alex Gaynor122717b2015-09-05 14:14:18 -04002271 # pytest.raises here doesn't work because of a bug in py.test on Python
2272 # 2.6: https://github.com/pytest-dev/pytest/issues/988
Alex Gaynore69c2782015-09-05 14:07:48 -04002273 try:
Alex Gaynor1aabb2e2015-09-05 13:35:18 -04002274 clientSSL.connect(("127.0.0.1", 1))
Alex Gaynore69c2782015-09-05 14:07:48 -04002275 except error as e:
Alex Gaynor20a4c082015-09-05 14:24:15 -04002276 exc = e
2277 assert exc.args[0] == ECONNREFUSED
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002278
2279 def test_connect(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002280 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002281 :py:obj:`Connection.connect` establishes a connection to the specified
2282 address.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002283 """
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002284 port = socket()
2285 port.bind(('', 0))
2286 port.listen(3)
2287
2288 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002289 clientSSL.connect(('127.0.0.1', port.getsockname()[1]))
2290 # XXX An assertion? Or something?
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002291
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002292 @pytest.mark.skipif(
2293 platform == "darwin",
2294 reason="connect_ex sometimes causes a kernel panic on OS X 10.6.4"
2295 )
2296 def test_connect_ex(self):
2297 """
2298 If there is a connection error, :py:obj:`Connection.connect_ex`
2299 returns the errno instead of raising an exception.
2300 """
2301 port = socket()
2302 port.bind(('', 0))
2303 port.listen(3)
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002304
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002305 clientSSL = Connection(Context(TLSv1_METHOD), socket())
2306 clientSSL.setblocking(False)
2307 result = clientSSL.connect_ex(port.getsockname())
2308 expected = (EINPROGRESS, EWOULDBLOCK)
2309 self.assertTrue(
2310 result in expected, "%r not in %r" % (result, expected))
Jean-Paul Calderone55d91f42010-07-29 19:22:17 -04002311
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002312 def test_accept_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002313 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002314 :py:obj:`Connection.accept` raises :py:obj:`TypeError` if called with
2315 any arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002316 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002317 connection = Connection(Context(TLSv1_METHOD), socket())
2318 self.assertRaises(TypeError, connection.accept, None)
2319
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002320 def test_accept(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002321 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002322 :py:obj:`Connection.accept` accepts a pending connection attempt and
2323 returns a tuple of a new :py:obj:`Connection` (the accepted client) and
2324 the address the connection originated from.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002325 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002326 ctx = Context(TLSv1_METHOD)
2327 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2328 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002329 port = socket()
2330 portSSL = Connection(ctx, port)
2331 portSSL.bind(('', 0))
2332 portSSL.listen(3)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002333
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002334 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002335
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002336 # Calling portSSL.getsockname() here to get the server IP address
2337 # sounds great, but frequently fails on Windows.
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002338 clientSSL.connect(('127.0.0.1', portSSL.getsockname()[1]))
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002339
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002340 serverSSL, address = portSSL.accept()
2341
2342 self.assertTrue(isinstance(serverSSL, Connection))
2343 self.assertIdentical(serverSSL.get_context(), ctx)
2344 self.assertEquals(address, clientSSL.getsockname())
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002345
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002346 def test_shutdown_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002347 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002348 :py:obj:`Connection.shutdown` raises :py:obj:`TypeError` if called with
2349 the wrong number of arguments or with arguments other than integers.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002350 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002351 connection = Connection(Context(TLSv1_METHOD), None)
2352 self.assertRaises(TypeError, connection.shutdown, None)
Jean-Paul Calderone1d3e0222010-07-29 22:52:45 -04002353 self.assertRaises(TypeError, connection.get_shutdown, None)
2354 self.assertRaises(TypeError, connection.set_shutdown)
2355 self.assertRaises(TypeError, connection.set_shutdown, None)
2356 self.assertRaises(TypeError, connection.set_shutdown, 0, 1)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002357
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002358 def test_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002359 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002360 :py:obj:`Connection.shutdown` performs an SSL-level connection
2361 shutdown.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002362 """
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002363 server, client = self._loopback()
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04002364 self.assertFalse(server.shutdown())
2365 self.assertEquals(server.get_shutdown(), SENT_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002366 self.assertRaises(ZeroReturnError, client.recv, 1024)
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04002367 self.assertEquals(client.get_shutdown(), RECEIVED_SHUTDOWN)
2368 client.shutdown()
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002369 self.assertEquals(
2370 client.get_shutdown(), SENT_SHUTDOWN | RECEIVED_SHUTDOWN
2371 )
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04002372 self.assertRaises(ZeroReturnError, server.recv, 1024)
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002373 self.assertEquals(
2374 server.get_shutdown(), SENT_SHUTDOWN | RECEIVED_SHUTDOWN
2375 )
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002376
Paul Aurichc85e0862015-01-08 08:34:33 -08002377 def test_shutdown_closed(self):
2378 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002379 If the underlying socket is closed, :py:obj:`Connection.shutdown`
2380 propagates the write error from the low level write call.
Paul Aurichc85e0862015-01-08 08:34:33 -08002381 """
2382 server, client = self._loopback()
2383 server.sock_shutdown(2)
2384 exc = self.assertRaises(SysCallError, server.shutdown)
2385 if platform == "win32":
2386 self.assertEqual(exc.args[0], ESHUTDOWN)
2387 else:
2388 self.assertEqual(exc.args[0], EPIPE)
2389
Glyph89389472015-04-14 17:29:26 -04002390 def test_shutdown_truncated(self):
Glyph6064ec32015-04-14 16:38:22 -04002391 """
Glyph89389472015-04-14 17:29:26 -04002392 If the underlying connection is truncated, :obj:`Connection.shutdown`
2393 raises an :obj:`Error`.
Glyph6064ec32015-04-14 16:38:22 -04002394 """
Glyph89389472015-04-14 17:29:26 -04002395 server_ctx = Context(TLSv1_METHOD)
2396 client_ctx = Context(TLSv1_METHOD)
2397 server_ctx.use_privatekey(
2398 load_privatekey(FILETYPE_PEM, server_key_pem))
2399 server_ctx.use_certificate(
2400 load_certificate(FILETYPE_PEM, server_cert_pem))
2401 server = Connection(server_ctx, None)
2402 client = Connection(client_ctx, None)
2403 self._handshakeInMemory(client, server)
2404 self.assertEqual(server.shutdown(), False)
2405 self.assertRaises(WantReadError, server.shutdown)
2406 server.bio_shutdown()
Glyph6064ec32015-04-14 16:38:22 -04002407 self.assertRaises(Error, server.shutdown)
2408
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002409 def test_set_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002410 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002411 :py:obj:`Connection.set_shutdown` sets the state of the SSL connection
2412 shutdown process.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002413 """
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002414 connection = Connection(Context(TLSv1_METHOD), socket())
2415 connection.set_shutdown(RECEIVED_SHUTDOWN)
2416 self.assertEquals(connection.get_shutdown(), RECEIVED_SHUTDOWN)
2417
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002418 @skip_if_py3
2419 def test_set_shutdown_long(self):
2420 """
2421 On Python 2 :py:obj:`Connection.set_shutdown` accepts an argument
2422 of type :py:obj:`long` as well as :py:obj:`int`.
2423 """
2424 connection = Connection(Context(TLSv1_METHOD), socket())
2425 connection.set_shutdown(long(RECEIVED_SHUTDOWN))
2426 self.assertEquals(connection.get_shutdown(), RECEIVED_SHUTDOWN)
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -05002427
kjavaf248592015-09-07 12:14:01 +01002428 def test_state_string(self):
2429 """
Hynek Schlawackb0274ce2015-10-16 19:56:26 +02002430 :meth:`Connection.state_string` verbosely describes the current
2431 state of the :class:`Connection`.
kjavaf248592015-09-07 12:14:01 +01002432 """
Hynek Schlawackb0274ce2015-10-16 19:56:26 +02002433 server, client = socket_pair()
kjavaf248592015-09-07 12:14:01 +01002434 server = self._loopbackServerFactory(server)
2435 client = self._loopbackClientFactory(client)
2436
Alex Gaynor5af32d02016-09-24 01:52:21 -04002437 assert server.get_state_string() in [
2438 b"before/accept initialization", b"before SSL initialization"
2439 ]
2440 assert client.get_state_string() in [
2441 b"before/connect initialization", b"before SSL initialization"
2442 ]
kjavaf248592015-09-07 12:14:01 +01002443
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002444 def test_app_data_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002445 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002446 :py:obj:`Connection.set_app_data` raises :py:obj:`TypeError` if called
2447 with other than one argument. :py:obj:`Connection.get_app_data` raises
2448 :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002449 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002450 conn = Connection(Context(TLSv1_METHOD), None)
2451 self.assertRaises(TypeError, conn.get_app_data, None)
2452 self.assertRaises(TypeError, conn.set_app_data)
2453 self.assertRaises(TypeError, conn.set_app_data, None, None)
2454
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002455 def test_app_data(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002456 """
2457 Any object can be set as app data by passing it to
Jonathan Ballet648875f2011-07-16 14:14:58 +09002458 :py:obj:`Connection.set_app_data` and later retrieved with
2459 :py:obj:`Connection.get_app_data`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002460 """
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002461 conn = Connection(Context(TLSv1_METHOD), None)
Todd Chapman4f73e4f2015-08-27 11:26:43 -04002462 assert None is conn.get_app_data()
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002463 app_data = object()
2464 conn.set_app_data(app_data)
Todd Chapman4f73e4f2015-08-27 11:26:43 -04002465 assert conn.get_app_data() is app_data
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002466
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002467 def test_makefile(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002468 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002469 :py:obj:`Connection.makefile` is not implemented and calling that
2470 method raises :py:obj:`NotImplementedError`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002471 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002472 conn = Connection(Context(TLSv1_METHOD), None)
2473 self.assertRaises(NotImplementedError, conn.makefile)
2474
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002475 def test_get_peer_cert_chain_wrong_args(self):
2476 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002477 :py:obj:`Connection.get_peer_cert_chain` raises :py:obj:`TypeError` if
2478 called with any arguments.
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002479 """
2480 conn = Connection(Context(TLSv1_METHOD), None)
2481 self.assertRaises(TypeError, conn.get_peer_cert_chain, 1)
2482 self.assertRaises(TypeError, conn.get_peer_cert_chain, "foo")
2483 self.assertRaises(TypeError, conn.get_peer_cert_chain, object())
2484 self.assertRaises(TypeError, conn.get_peer_cert_chain, [])
2485
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002486 def test_get_peer_cert_chain(self):
2487 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002488 :py:obj:`Connection.get_peer_cert_chain` returns a list of certificates
2489 which the connected server returned for the certification verification.
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002490 """
2491 chain = _create_certificate_chain()
2492 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
2493
2494 serverContext = Context(TLSv1_METHOD)
2495 serverContext.use_privatekey(skey)
2496 serverContext.use_certificate(scert)
2497 serverContext.add_extra_chain_cert(icert)
2498 serverContext.add_extra_chain_cert(cacert)
2499 server = Connection(serverContext, None)
2500 server.set_accept_state()
2501
2502 # Create the client
2503 clientContext = Context(TLSv1_METHOD)
2504 clientContext.set_verify(VERIFY_NONE, verify_cb)
2505 client = Connection(clientContext, None)
2506 client.set_connect_state()
2507
2508 self._interactInMemory(client, server)
2509
2510 chain = client.get_peer_cert_chain()
2511 self.assertEqual(len(chain), 3)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04002512 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002513 "Server Certificate", chain[0].get_subject().CN)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04002514 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002515 "Intermediate Certificate", chain[1].get_subject().CN)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04002516 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002517 "Authority Certificate", chain[2].get_subject().CN)
2518
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002519 def test_get_peer_cert_chain_none(self):
2520 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002521 :py:obj:`Connection.get_peer_cert_chain` returns :py:obj:`None` if the
2522 peer sends no certificate chain.
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002523 """
2524 ctx = Context(TLSv1_METHOD)
2525 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2526 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
2527 server = Connection(ctx, None)
2528 server.set_accept_state()
2529 client = Connection(Context(TLSv1_METHOD), None)
2530 client.set_connect_state()
2531 self._interactInMemory(client, server)
2532 self.assertIdentical(None, server.get_peer_cert_chain())
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002533
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002534 def test_get_session_wrong_args(self):
2535 """
2536 :py:obj:`Connection.get_session` raises :py:obj:`TypeError` if called
2537 with any arguments.
2538 """
2539 ctx = Context(TLSv1_METHOD)
2540 server = Connection(ctx, None)
2541 self.assertRaises(TypeError, server.get_session, 123)
2542 self.assertRaises(TypeError, server.get_session, "hello")
2543 self.assertRaises(TypeError, server.get_session, object())
2544
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002545 def test_get_session_unconnected(self):
2546 """
2547 :py:obj:`Connection.get_session` returns :py:obj:`None` when used with
2548 an object which has not been connected.
2549 """
2550 ctx = Context(TLSv1_METHOD)
2551 server = Connection(ctx, None)
2552 session = server.get_session()
2553 self.assertIdentical(None, session)
2554
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002555 def test_server_get_session(self):
2556 """
2557 On the server side of a connection, :py:obj:`Connection.get_session`
2558 returns a :py:class:`Session` instance representing the SSL session for
2559 that connection.
2560 """
2561 server, client = self._loopback()
2562 session = server.get_session()
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08002563 self.assertIsInstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002564
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002565 def test_client_get_session(self):
2566 """
2567 On the client side of a connection, :py:obj:`Connection.get_session`
2568 returns a :py:class:`Session` instance representing the SSL session for
2569 that connection.
2570 """
2571 server, client = self._loopback()
2572 session = client.get_session()
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08002573 self.assertIsInstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002574
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002575 def test_set_session_wrong_args(self):
2576 """
Hynek Schlawackdddd1112015-09-05 21:12:30 +02002577 If called with an object that is not an instance of
2578 :py:class:`Session`, or with other than one argument,
2579 :py:obj:`Connection.set_session` raises :py:obj:`TypeError`.
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002580 """
2581 ctx = Context(TLSv1_METHOD)
2582 connection = Connection(ctx, None)
2583 self.assertRaises(TypeError, connection.set_session)
2584 self.assertRaises(TypeError, connection.set_session, 123)
2585 self.assertRaises(TypeError, connection.set_session, "hello")
2586 self.assertRaises(TypeError, connection.set_session, object())
2587 self.assertRaises(
2588 TypeError, connection.set_session, Session(), Session())
2589
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002590 def test_client_set_session(self):
2591 """
2592 :py:obj:`Connection.set_session`, when used prior to a connection being
2593 established, accepts a :py:class:`Session` instance and causes an
2594 attempt to re-use the session it represents when the SSL handshake is
2595 performed.
2596 """
2597 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2598 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
2599 ctx = Context(TLSv1_METHOD)
2600 ctx.use_privatekey(key)
2601 ctx.use_certificate(cert)
2602 ctx.set_session_id("unity-test")
2603
2604 def makeServer(socket):
2605 server = Connection(ctx, socket)
2606 server.set_accept_state()
2607 return server
2608
2609 originalServer, originalClient = self._loopback(
2610 serverFactory=makeServer)
2611 originalSession = originalClient.get_session()
2612
2613 def makeClient(socket):
2614 client = self._loopbackClientFactory(socket)
2615 client.set_session(originalSession)
2616 return client
2617 resumedServer, resumedClient = self._loopback(
2618 serverFactory=makeServer,
2619 clientFactory=makeClient)
2620
2621 # This is a proxy: in general, we have no access to any unique
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002622 # identifier for the session (new enough versions of OpenSSL expose
2623 # a hash which could be usable, but "new enough" is very, very new).
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002624 # Instead, exploit the fact that the master key is re-used if the
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002625 # session is re-used. As long as the master key for the two
2626 # connections is the same, the session was re-used!
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002627 self.assertEqual(
2628 originalServer.master_key(), resumedServer.master_key())
2629
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002630 def test_set_session_wrong_method(self):
2631 """
Jean-Paul Calderone068cb592012-02-14 16:52:43 -05002632 If :py:obj:`Connection.set_session` is passed a :py:class:`Session`
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002633 instance associated with a context using a different SSL method than
2634 the :py:obj:`Connection` is using, a :py:class:`OpenSSL.SSL.Error` is
Jean-Paul Calderone068cb592012-02-14 16:52:43 -05002635 raised.
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002636 """
Alex Gaynor5af32d02016-09-24 01:52:21 -04002637 # Make this work on both OpenSSL 1.0.0, which doesn't support TLSv1.2
2638 # and also on OpenSSL 1.1.0 which doesn't support SSLv3. (SSL_ST_INIT
2639 # is a way to check for 1.1.0)
2640 if SSL_ST_INIT is not None:
2641 v1 = TLSv1_METHOD
2642 v2 = SSLv3_METHOD
2643 else:
2644 v1 = TLSv1_2_METHOD
2645 v2 = TLSv1_METHOD
2646
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002647 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2648 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
Alex Gaynor5af32d02016-09-24 01:52:21 -04002649 ctx = Context(v1)
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002650 ctx.use_privatekey(key)
2651 ctx.use_certificate(cert)
2652 ctx.set_session_id("unity-test")
2653
2654 def makeServer(socket):
2655 server = Connection(ctx, socket)
2656 server.set_accept_state()
2657 return server
2658
Alex Gaynor5af32d02016-09-24 01:52:21 -04002659 def makeOriginalClient(socket):
2660 client = Connection(Context(v1), socket)
2661 client.set_connect_state()
2662 return client
2663
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002664 originalServer, originalClient = self._loopback(
Alex Gaynor5af32d02016-09-24 01:52:21 -04002665 serverFactory=makeServer, clientFactory=makeOriginalClient)
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002666 originalSession = originalClient.get_session()
2667
2668 def makeClient(socket):
2669 # Intentionally use a different, incompatible method here.
Alex Gaynor5af32d02016-09-24 01:52:21 -04002670 client = Connection(Context(v2), socket)
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002671 client.set_connect_state()
2672 client.set_session(originalSession)
2673 return client
2674
2675 self.assertRaises(
2676 Error,
2677 self._loopback, clientFactory=makeClient, serverFactory=makeServer)
2678
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002679 def test_wantWriteError(self):
2680 """
2681 :py:obj:`Connection` methods which generate output raise
2682 :py:obj:`OpenSSL.SSL.WantWriteError` if writing to the connection's BIO
2683 fail indicating a should-write state.
2684 """
2685 client_socket, server_socket = socket_pair()
2686 # Fill up the client's send buffer so Connection won't be able to write
Jean-Paul Calderonebbff8b92014-03-22 14:20:30 -04002687 # anything. Only write a single byte at a time so we can be sure we
2688 # completely fill the buffer. Even though the socket API is allowed to
2689 # signal a short write via its return value it seems this doesn't
2690 # always happen on all platforms (FreeBSD and OS X particular) for the
2691 # very last bit of available buffer space.
2692 msg = b"x"
2693 for i in range(1024 * 1024 * 4):
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002694 try:
2695 client_socket.send(msg)
2696 except error as e:
2697 if e.errno == EWOULDBLOCK:
2698 break
2699 raise
2700 else:
2701 self.fail(
2702 "Failed to fill socket buffer, cannot test BIO want write")
2703
2704 ctx = Context(TLSv1_METHOD)
2705 conn = Connection(ctx, client_socket)
2706 # Client's speak first, so make it an SSL client
2707 conn.set_connect_state()
2708 self.assertRaises(WantWriteError, conn.do_handshake)
2709
2710 # XXX want_read
2711
Fedor Brunner416f4a12014-03-28 13:18:38 +01002712 def test_get_finished_before_connect(self):
Fedor Brunner5747b932014-03-05 14:22:34 +01002713 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002714 :py:obj:`Connection.get_finished` returns :py:obj:`None` before TLS
2715 handshake is completed.
Fedor Brunner5747b932014-03-05 14:22:34 +01002716 """
Fedor Brunner5747b932014-03-05 14:22:34 +01002717 ctx = Context(TLSv1_METHOD)
2718 connection = Connection(ctx, None)
2719 self.assertEqual(connection.get_finished(), None)
Fedor Brunner416f4a12014-03-28 13:18:38 +01002720
2721 def test_get_peer_finished_before_connect(self):
2722 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002723 :py:obj:`Connection.get_peer_finished` returns :py:obj:`None` before
2724 TLS handshake is completed.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002725 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002726 ctx = Context(TLSv1_METHOD)
2727 connection = Connection(ctx, None)
Fedor Brunner5747b932014-03-05 14:22:34 +01002728 self.assertEqual(connection.get_peer_finished(), None)
2729
Fedor Brunner416f4a12014-03-28 13:18:38 +01002730 def test_get_finished(self):
2731 """
2732 :py:obj:`Connection.get_finished` method returns the TLS Finished
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002733 message send from client, or server. Finished messages are send during
2734 TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002735 """
2736
Fedor Brunner5747b932014-03-05 14:22:34 +01002737 server, client = self._loopback()
2738
2739 self.assertNotEqual(server.get_finished(), None)
2740 self.assertTrue(len(server.get_finished()) > 0)
Fedor Brunner416f4a12014-03-28 13:18:38 +01002741
2742 def test_get_peer_finished(self):
2743 """
2744 :py:obj:`Connection.get_peer_finished` method returns the TLS Finished
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002745 message received from client, or server. Finished messages are send
2746 during TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002747 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002748 server, client = self._loopback()
2749
2750 self.assertNotEqual(server.get_peer_finished(), None)
Fedor Brunner5747b932014-03-05 14:22:34 +01002751 self.assertTrue(len(server.get_peer_finished()) > 0)
2752
Fedor Brunner416f4a12014-03-28 13:18:38 +01002753 def test_tls_finished_message_symmetry(self):
2754 """
Hynek Schlawackdddd1112015-09-05 21:12:30 +02002755 The TLS Finished message send by server must be the TLS Finished
2756 message received by client.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002757
Hynek Schlawackdddd1112015-09-05 21:12:30 +02002758 The TLS Finished message send by client must be the TLS Finished
2759 message received by server.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002760 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002761 server, client = self._loopback()
2762
Fedor Brunner5747b932014-03-05 14:22:34 +01002763 self.assertEqual(server.get_finished(), client.get_peer_finished())
2764 self.assertEqual(client.get_finished(), server.get_peer_finished())
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002765
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002766 def test_get_cipher_name_before_connect(self):
2767 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002768 :py:obj:`Connection.get_cipher_name` returns :py:obj:`None` if no
2769 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002770 """
2771 ctx = Context(TLSv1_METHOD)
2772 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002773 self.assertIdentical(conn.get_cipher_name(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002774
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002775 def test_get_cipher_name(self):
2776 """
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002777 :py:obj:`Connection.get_cipher_name` returns a :py:class:`unicode`
2778 string giving the name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002779 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002780 server, client = self._loopback()
2781 server_cipher_name, client_cipher_name = \
2782 server.get_cipher_name(), client.get_cipher_name()
2783
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002784 self.assertIsInstance(server_cipher_name, text_type)
2785 self.assertIsInstance(client_cipher_name, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002786
2787 self.assertEqual(server_cipher_name, client_cipher_name)
2788
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002789 def test_get_cipher_version_before_connect(self):
2790 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002791 :py:obj:`Connection.get_cipher_version` returns :py:obj:`None` if no
2792 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002793 """
2794 ctx = Context(TLSv1_METHOD)
2795 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002796 self.assertIdentical(conn.get_cipher_version(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002797
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002798 def test_get_cipher_version(self):
2799 """
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002800 :py:obj:`Connection.get_cipher_version` returns a :py:class:`unicode`
2801 string giving the protocol name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002802 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002803 server, client = self._loopback()
2804 server_cipher_version, client_cipher_version = \
2805 server.get_cipher_version(), client.get_cipher_version()
2806
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002807 self.assertIsInstance(server_cipher_version, text_type)
2808 self.assertIsInstance(client_cipher_version, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002809
2810 self.assertEqual(server_cipher_version, client_cipher_version)
2811
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002812 def test_get_cipher_bits_before_connect(self):
2813 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002814 :py:obj:`Connection.get_cipher_bits` returns :py:obj:`None` if no
2815 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002816 """
2817 ctx = Context(TLSv1_METHOD)
2818 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002819 self.assertIdentical(conn.get_cipher_bits(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002820
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002821 def test_get_cipher_bits(self):
2822 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002823 :py:obj:`Connection.get_cipher_bits` returns the number of secret bits
2824 of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002825 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002826 server, client = self._loopback()
2827 server_cipher_bits, client_cipher_bits = \
2828 server.get_cipher_bits(), client.get_cipher_bits()
2829
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002830 self.assertIsInstance(server_cipher_bits, int)
2831 self.assertIsInstance(client_cipher_bits, int)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002832
2833 self.assertEqual(server_cipher_bits, client_cipher_bits)
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002834
Jim Shaverabff1882015-05-27 09:15:55 -04002835 def test_get_protocol_version_name(self):
2836 """
2837 :py:obj:`Connection.get_protocol_version_name()` returns a string
2838 giving the protocol version of the current connection.
2839 """
2840 server, client = self._loopback()
2841 client_protocol_version_name = client.get_protocol_version_name()
2842 server_protocol_version_name = server.get_protocol_version_name()
2843
Jim Shaver58d25732015-05-28 11:52:32 -04002844 self.assertIsInstance(server_protocol_version_name, text_type)
2845 self.assertIsInstance(client_protocol_version_name, text_type)
Jim Shaverabff1882015-05-27 09:15:55 -04002846
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002847 self.assertEqual(
2848 server_protocol_version_name, client_protocol_version_name
2849 )
Jim Shaverabff1882015-05-27 09:15:55 -04002850
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002851 def test_get_protocol_version(self):
2852 """
Alex Gaynor43307782015-09-04 09:05:45 -04002853 :py:obj:`Connection.get_protocol_version()` returns an integer
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002854 giving the protocol version of the current connection.
2855 """
2856 server, client = self._loopback()
Jim Shaver85a4dff2015-04-27 17:42:46 -04002857 client_protocol_version = client.get_protocol_version()
2858 server_protocol_version = server.get_protocol_version()
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002859
Jim Shaverabff1882015-05-27 09:15:55 -04002860 self.assertIsInstance(server_protocol_version, int)
2861 self.assertIsInstance(client_protocol_version, int)
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002862
2863 self.assertEqual(server_protocol_version, client_protocol_version)
2864
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002865
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002866class ConnectionGetCipherListTests(TestCase):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002867 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002868 Tests for :py:obj:`Connection.get_cipher_list`.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002869 """
Jean-Paul Calderone54a2bc02010-09-09 17:52:38 -04002870 def test_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002871 """
Hynek Schlawackdddd1112015-09-05 21:12:30 +02002872 :py:obj:`Connection.get_cipher_list` raises :py:obj:`TypeError` if
2873 called with any arguments.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002874 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002875 connection = Connection(Context(TLSv1_METHOD), None)
2876 self.assertRaises(TypeError, connection.get_cipher_list, None)
2877
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002878 def test_result(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002879 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002880 :py:obj:`Connection.get_cipher_list` returns a :py:obj:`list` of
2881 :py:obj:`bytes` giving the names of the ciphers which might be used.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002882 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002883 connection = Connection(Context(TLSv1_METHOD), None)
2884 ciphers = connection.get_cipher_list()
2885 self.assertTrue(isinstance(ciphers, list))
2886 for cipher in ciphers:
2887 self.assertTrue(isinstance(cipher, str))
2888
2889
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002890class ConnectionSendTests(TestCase, _LoopbackMixin):
2891 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002892 Tests for :py:obj:`Connection.send`
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002893 """
2894 def test_wrong_args(self):
2895 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002896 When called with arguments other than string argument for its first
2897 parameter or more than two arguments, :py:obj:`Connection.send` raises
2898 :py:obj:`TypeError`.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002899 """
2900 connection = Connection(Context(TLSv1_METHOD), None)
Jean-Paul Calderone77fa2602011-01-05 18:23:39 -05002901 self.assertRaises(TypeError, connection.send)
2902 self.assertRaises(TypeError, connection.send, object())
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002903 self.assertRaises(TypeError, connection.send, "foo", object(), "bar")
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002904
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002905 def test_short_bytes(self):
2906 """
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002907 When passed a short byte string, :py:obj:`Connection.send` transmits
2908 all of it and returns the number of bytes sent.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002909 """
2910 server, client = self._loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002911 count = server.send(b'xy')
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002912 self.assertEquals(count, 2)
Alex Gaynore7f51982016-09-11 11:48:14 -04002913 self.assertEquals(client.recv(2), b'xy')
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002914
Abraham Martinef063482015-03-25 14:06:24 +00002915 def test_text(self):
2916 """
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002917 When passed a text, :py:obj:`Connection.send` transmits all of it and
2918 returns the number of bytes sent. It also raises a DeprecationWarning.
Abraham Martinef063482015-03-25 14:06:24 +00002919 """
2920 server, client = self._loopback()
2921 with catch_warnings(record=True) as w:
2922 simplefilter("always")
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002923 count = server.send(b"xy".decode("ascii"))
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002924 self.assertEqual(
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002925 "{0} for buf is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002926 WARNING_TYPE_EXPECTED
2927 ),
2928 str(w[-1].message)
2929 )
2930 self.assertIs(w[-1].category, DeprecationWarning)
Abraham Martinef063482015-03-25 14:06:24 +00002931 self.assertEquals(count, 2)
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002932 self.assertEquals(client.recv(2), b"xy")
Abraham Martinef063482015-03-25 14:06:24 +00002933
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002934 @skip_if_py26
2935 def test_short_memoryview(self):
2936 """
2937 When passed a memoryview onto a small number of bytes,
2938 :py:obj:`Connection.send` transmits all of them and returns the number
2939 of bytes sent.
2940 """
2941 server, client = self._loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002942 count = server.send(memoryview(b'xy'))
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002943 self.assertEquals(count, 2)
Alex Gaynore7f51982016-09-11 11:48:14 -04002944 self.assertEquals(client.recv(2), b'xy')
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002945
Hynek Schlawack8e94f1b2015-09-05 21:31:00 +02002946 @skip_if_py3
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002947 def test_short_buffer(self):
2948 """
2949 When passed a buffer containing a small number of bytes,
2950 :py:obj:`Connection.send` transmits all of them and returns the number
2951 of bytes sent.
2952 """
2953 server, client = self._loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002954 count = server.send(buffer(b'xy'))
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002955 self.assertEquals(count, 2)
Alex Gaynore7f51982016-09-11 11:48:14 -04002956 self.assertEquals(client.recv(2), b'xy')
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02002957
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05002958
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002959def _make_memoryview(size):
2960 """
2961 Create a new ``memoryview`` wrapped around a ``bytearray`` of the given
2962 size.
2963 """
2964 return memoryview(bytearray(size))
2965
2966
Cory Benfield62d10332014-06-15 10:03:41 +01002967class ConnectionRecvIntoTests(TestCase, _LoopbackMixin):
2968 """
2969 Tests for :py:obj:`Connection.recv_into`
2970 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002971 def _no_length_test(self, factory):
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04002972 """
2973 Assert that when the given buffer is passed to
2974 ``Connection.recv_into``, whatever bytes are available to be received
2975 that fit into that buffer are written into that buffer.
2976 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002977 output_buffer = factory(5)
2978
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04002979 server, client = self._loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002980 server.send(b'xy')
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04002981
Jean-Paul Calderone320af1e2015-03-15 17:20:13 -04002982 self.assertEqual(client.recv_into(output_buffer), 2)
Alex Gaynore7f51982016-09-11 11:48:14 -04002983 self.assertEqual(output_buffer, bytearray(b'xy\x00\x00\x00'))
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04002984
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002985 def test_bytearray_no_length(self):
Cory Benfield62d10332014-06-15 10:03:41 +01002986 """
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04002987 :py:obj:`Connection.recv_into` can be passed a ``bytearray`` instance
2988 and data in the receive buffer is written to it.
Cory Benfield62d10332014-06-15 10:03:41 +01002989 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002990 self._no_length_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01002991
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002992 def _respects_length_test(self, factory):
Cory Benfield62d10332014-06-15 10:03:41 +01002993 """
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002994 Assert that when the given buffer is passed to ``Connection.recv_into``
2995 along with a value for ``nbytes`` that is less than the size of that
2996 buffer, only ``nbytes`` bytes are written into the buffer.
Cory Benfield62d10332014-06-15 10:03:41 +01002997 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002998 output_buffer = factory(10)
2999
Cory Benfield62d10332014-06-15 10:03:41 +01003000 server, client = self._loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04003001 server.send(b'abcdefghij')
Cory Benfield62d10332014-06-15 10:03:41 +01003002
Jean-Paul Calderone320af1e2015-03-15 17:20:13 -04003003 self.assertEqual(client.recv_into(output_buffer, 5), 5)
3004 self.assertEqual(
Alex Gaynore7f51982016-09-11 11:48:14 -04003005 output_buffer, bytearray(b'abcde\x00\x00\x00\x00\x00')
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04003006 )
3007
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04003008 def test_bytearray_respects_length(self):
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04003009 """
3010 When called with a ``bytearray`` instance,
3011 :py:obj:`Connection.recv_into` respects the ``nbytes`` parameter and
3012 doesn't copy in more than that number of bytes.
3013 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003014 self._respects_length_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01003015
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003016 def _doesnt_overfill_test(self, factory):
Cory Benfield62d10332014-06-15 10:03:41 +01003017 """
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04003018 Assert that if there are more bytes available to be read from the
3019 receive buffer than would fit into the buffer passed to
3020 :py:obj:`Connection.recv_into`, only as many as fit are written into
3021 it.
Cory Benfield62d10332014-06-15 10:03:41 +01003022 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003023 output_buffer = factory(5)
3024
Cory Benfield62d10332014-06-15 10:03:41 +01003025 server, client = self._loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04003026 server.send(b'abcdefghij')
Cory Benfield62d10332014-06-15 10:03:41 +01003027
Jean-Paul Calderone320af1e2015-03-15 17:20:13 -04003028 self.assertEqual(client.recv_into(output_buffer), 5)
Alex Gaynore7f51982016-09-11 11:48:14 -04003029 self.assertEqual(output_buffer, bytearray(b'abcde'))
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04003030 rest = client.recv(5)
Alex Gaynore7f51982016-09-11 11:48:14 -04003031 self.assertEqual(b'fghij', rest)
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04003032
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04003033 def test_bytearray_doesnt_overfill(self):
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04003034 """
3035 When called with a ``bytearray`` instance,
3036 :py:obj:`Connection.recv_into` respects the size of the array and
3037 doesn't write more bytes into it than will fit.
3038 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003039 self._doesnt_overfill_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01003040
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04003041 def test_bytearray_really_doesnt_overfill(self):
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003042 """
3043 When called with a ``bytearray`` instance and an ``nbytes`` value that
3044 is too large, :py:obj:`Connection.recv_into` respects the size of the
3045 array and not the ``nbytes`` value and doesn't write more bytes into
3046 the buffer than will fit.
3047 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003048 self._doesnt_overfill_test(bytearray)
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003049
Maximilian Hils1d95dea2015-08-17 19:27:20 +02003050 def test_peek(self):
Maximilian Hils1d95dea2015-08-17 19:27:20 +02003051 server, client = self._loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04003052 server.send(b'xy')
Maximilian Hils1d95dea2015-08-17 19:27:20 +02003053
3054 for _ in range(2):
3055 output_buffer = bytearray(5)
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003056 self.assertEqual(
3057 client.recv_into(output_buffer, flags=MSG_PEEK), 2)
Alex Gaynore7f51982016-09-11 11:48:14 -04003058 self.assertEqual(output_buffer, bytearray(b'xy\x00\x00\x00'))
Maximilian Hils1d95dea2015-08-17 19:27:20 +02003059
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003060 @skip_if_py26
3061 def test_memoryview_no_length(self):
3062 """
3063 :py:obj:`Connection.recv_into` can be passed a ``memoryview``
3064 instance and data in the receive buffer is written to it.
3065 """
3066 self._no_length_test(_make_memoryview)
Maximilian Hils1d95dea2015-08-17 19:27:20 +02003067
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003068 @skip_if_py26
3069 def test_memoryview_respects_length(self):
3070 """
3071 When called with a ``memoryview`` instance,
3072 :py:obj:`Connection.recv_into` respects the ``nbytes`` parameter
3073 and doesn't copy more than that number of bytes in.
3074 """
3075 self._respects_length_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01003076
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003077 @skip_if_py26
3078 def test_memoryview_doesnt_overfill(self):
3079 """
3080 When called with a ``memoryview`` instance,
3081 :py:obj:`Connection.recv_into` respects the size of the array and
3082 doesn't write more bytes into it than will fit.
3083 """
3084 self._doesnt_overfill_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01003085
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003086 @skip_if_py26
3087 def test_memoryview_really_doesnt_overfill(self):
3088 """
3089 When called with a ``memoryview`` instance and an ``nbytes`` value
3090 that is too large, :py:obj:`Connection.recv_into` respects the size
3091 of the array and not the ``nbytes`` value and doesn't write more
3092 bytes into the buffer than will fit.
3093 """
3094 self._doesnt_overfill_test(_make_memoryview)
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003095
Cory Benfield62d10332014-06-15 10:03:41 +01003096
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003097class ConnectionSendallTests(TestCase, _LoopbackMixin):
3098 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003099 Tests for :py:obj:`Connection.sendall`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003100 """
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003101 def test_wrong_args(self):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003102 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003103 When called with arguments other than a string argument for its first
3104 parameter or with more than two arguments, :py:obj:`Connection.sendall`
3105 raises :py:obj:`TypeError`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003106 """
3107 connection = Connection(Context(TLSv1_METHOD), None)
3108 self.assertRaises(TypeError, connection.sendall)
3109 self.assertRaises(TypeError, connection.sendall, object())
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003110 self.assertRaises(
3111 TypeError, connection.sendall, "foo", object(), "bar")
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003112
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003113 def test_short(self):
3114 """
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003115 :py:obj:`Connection.sendall` transmits all of the bytes in the string
3116 passed to it.
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003117 """
3118 server, client = self._loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04003119 server.sendall(b'x')
3120 self.assertEquals(client.recv(1), b'x')
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003121
Abraham Martinef063482015-03-25 14:06:24 +00003122 def test_text(self):
3123 """
Jean-Paul Calderone93477422015-04-13 20:38:57 -04003124 :py:obj:`Connection.sendall` transmits all the content in the string
3125 passed to it raising a DeprecationWarning in case of this being a text.
Abraham Martinef063482015-03-25 14:06:24 +00003126 """
3127 server, client = self._loopback()
3128 with catch_warnings(record=True) as w:
3129 simplefilter("always")
Jean-Paul Calderone8dc37a12015-03-29 08:16:52 -04003130 server.sendall(b"x".decode("ascii"))
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04003131 self.assertEqual(
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04003132 "{0} for buf is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04003133 WARNING_TYPE_EXPECTED
3134 ),
3135 str(w[-1].message)
3136 )
3137 self.assertIs(w[-1].category, DeprecationWarning)
3138 self.assertEquals(client.recv(1), b"x")
Abraham Martinef063482015-03-25 14:06:24 +00003139
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003140 @skip_if_py26
3141 def test_short_memoryview(self):
3142 """
3143 When passed a memoryview onto a small number of bytes,
3144 :py:obj:`Connection.sendall` transmits all of them.
3145 """
3146 server, client = self._loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04003147 server.sendall(memoryview(b'x'))
3148 self.assertEquals(client.recv(1), b'x')
Abraham Martinef063482015-03-25 14:06:24 +00003149
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003150 @skip_if_py3
3151 def test_short_buffers(self):
3152 """
3153 When passed a buffer containing a small number of bytes,
3154 :py:obj:`Connection.sendall` transmits all of them.
3155 """
3156 server, client = self._loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04003157 server.sendall(buffer(b'x'))
3158 self.assertEquals(client.recv(1), b'x')
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02003159
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003160 def test_long(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003161 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003162 :py:obj:`Connection.sendall` transmits all of the bytes in the string
3163 passed to it even if this requires multiple calls of an underlying
3164 write function.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003165 """
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003166 server, client = self._loopback()
Jean-Paul Calderone6241c702010-09-16 19:59:24 -04003167 # Should be enough, underlying SSL_write should only do 16k at a time.
Hynek Schlawack35618382015-09-05 21:54:25 +02003168 # On Windows, after 32k of bytes the write will block (forever
3169 # - because no one is yet reading).
Alex Gaynore7f51982016-09-11 11:48:14 -04003170 message = b'x' * (1024 * 32 - 1) + b'y'
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003171 server.sendall(message)
3172 accum = []
3173 received = 0
3174 while received < len(message):
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04003175 data = client.recv(1024)
3176 accum.append(data)
3177 received += len(data)
Alex Gaynore7f51982016-09-11 11:48:14 -04003178 self.assertEquals(message, b''.join(accum))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003179
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003180 def test_closed(self):
3181 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003182 If the underlying socket is closed, :py:obj:`Connection.sendall`
3183 propagates the write error from the low level write call.
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003184 """
3185 server, client = self._loopback()
Jean-Paul Calderone05d43e82010-09-24 18:01:36 -04003186 server.sock_shutdown(2)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003187 exc = self.assertRaises(SysCallError, server.sendall, b"hello, world")
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +02003188 if platform == "win32":
3189 self.assertEqual(exc.args[0], ESHUTDOWN)
3190 else:
3191 self.assertEqual(exc.args[0], EPIPE)
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003192
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003193
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003194class ConnectionRenegotiateTests(TestCase, _LoopbackMixin):
3195 """
3196 Tests for SSL renegotiation APIs.
3197 """
3198 def test_renegotiate_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003199 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003200 :py:obj:`Connection.renegotiate` raises :py:obj:`TypeError` if called
3201 with any arguments.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003202 """
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003203 connection = Connection(Context(TLSv1_METHOD), None)
3204 self.assertRaises(TypeError, connection.renegotiate, None)
3205
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003206 def test_total_renegotiations_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003207 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003208 :py:obj:`Connection.total_renegotiations` raises :py:obj:`TypeError` if
3209 called with any arguments.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003210 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003211 connection = Connection(Context(TLSv1_METHOD), None)
3212 self.assertRaises(TypeError, connection.total_renegotiations, None)
3213
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003214 def test_total_renegotiations(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003215 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003216 :py:obj:`Connection.total_renegotiations` returns :py:obj:`0` before
3217 any renegotiations have happened.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003218 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003219 connection = Connection(Context(TLSv1_METHOD), None)
3220 self.assertEquals(connection.total_renegotiations(), 0)
3221
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003222 def test_renegotiate(self):
3223 """
3224 Go through a complete renegotiation cycle.
3225 """
3226 server, client = self._loopback()
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003227
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003228 server.send(b"hello world")
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003229
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003230 assert b"hello world" == client.recv(len(b"hello world"))
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003231
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003232 assert 0 == server.total_renegotiations()
3233 assert False is server.renegotiate_pending()
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003234
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003235 assert True is server.renegotiate()
3236
3237 assert True is server.renegotiate_pending()
3238
3239 server.setblocking(False)
3240 client.setblocking(False)
3241
3242 client.do_handshake()
3243 server.do_handshake()
3244
3245 assert 1 == server.total_renegotiations()
3246 while False is server.renegotiate_pending():
3247 pass
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003248
3249
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003250class ErrorTests(TestCase):
3251 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003252 Unit tests for :py:obj:`OpenSSL.SSL.Error`.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003253 """
3254 def test_type(self):
3255 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003256 :py:obj:`Error` is an exception type.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003257 """
3258 self.assertTrue(issubclass(Error, Exception))
Rick Deane15b1472009-07-09 15:53:42 -05003259 self.assertEqual(Error.__name__, 'Error')
Rick Deane15b1472009-07-09 15:53:42 -05003260
3261
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003262class ConstantsTests(TestCase):
3263 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003264 Tests for the values of constants exposed in :py:obj:`OpenSSL.SSL`.
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003265
3266 These are values defined by OpenSSL intended only to be used as flags to
3267 OpenSSL APIs. The only assertions it seems can be made about them is
3268 their values.
3269 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003270 @pytest.mark.skipif(
3271 OP_NO_QUERY_MTU is None,
3272 reason="OP_NO_QUERY_MTU unavailable - OpenSSL version may be too old"
3273 )
3274 def test_op_no_query_mtu(self):
3275 """
3276 The value of :py:obj:`OpenSSL.SSL.OP_NO_QUERY_MTU` is 0x1000, the value
3277 of :py:const:`SSL_OP_NO_QUERY_MTU` defined by :file:`openssl/ssl.h`.
3278 """
3279 self.assertEqual(OP_NO_QUERY_MTU, 0x1000)
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003280
Hynek Schlawack35618382015-09-05 21:54:25 +02003281 @pytest.mark.skipif(
3282 OP_COOKIE_EXCHANGE is None,
3283 reason="OP_COOKIE_EXCHANGE unavailable - "
3284 "OpenSSL version may be too old"
3285 )
3286 def test_op_cookie_exchange(self):
3287 """
3288 The value of :py:obj:`OpenSSL.SSL.OP_COOKIE_EXCHANGE` is 0x2000, the
3289 value of :py:const:`SSL_OP_COOKIE_EXCHANGE` defined by
3290 :file:`openssl/ssl.h`.
3291 """
3292 self.assertEqual(OP_COOKIE_EXCHANGE, 0x2000)
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003293
Hynek Schlawack35618382015-09-05 21:54:25 +02003294 @pytest.mark.skipif(
3295 OP_NO_TICKET is None,
3296 reason="OP_NO_TICKET unavailable - OpenSSL version may be too old"
3297 )
3298 def test_op_no_ticket(self):
3299 """
3300 The value of :py:obj:`OpenSSL.SSL.OP_NO_TICKET` is 0x4000, the value of
3301 :py:const:`SSL_OP_NO_TICKET` defined by :file:`openssl/ssl.h`.
3302 """
3303 self.assertEqual(OP_NO_TICKET, 0x4000)
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003304
Hynek Schlawack35618382015-09-05 21:54:25 +02003305 @pytest.mark.skipif(
3306 OP_NO_COMPRESSION is None,
3307 reason="OP_NO_COMPRESSION unavailable - OpenSSL version may be too old"
3308 )
3309 def test_op_no_compression(self):
3310 """
3311 The value of :py:obj:`OpenSSL.SSL.OP_NO_COMPRESSION` is 0x20000, the
3312 value of :py:const:`SSL_OP_NO_COMPRESSION` defined by
3313 :file:`openssl/ssl.h`.
3314 """
3315 self.assertEqual(OP_NO_COMPRESSION, 0x20000)
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04003316
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003317 def test_sess_cache_off(self):
3318 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003319 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_OFF` 0x0, the value of
3320 :py:obj:`SSL_SESS_CACHE_OFF` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003321 """
3322 self.assertEqual(0x0, SESS_CACHE_OFF)
3323
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003324 def test_sess_cache_client(self):
3325 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003326 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_CLIENT` 0x1, the value of
3327 :py:obj:`SSL_SESS_CACHE_CLIENT` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003328 """
3329 self.assertEqual(0x1, SESS_CACHE_CLIENT)
3330
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003331 def test_sess_cache_server(self):
3332 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003333 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_SERVER` 0x2, the value of
3334 :py:obj:`SSL_SESS_CACHE_SERVER` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003335 """
3336 self.assertEqual(0x2, SESS_CACHE_SERVER)
3337
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003338 def test_sess_cache_both(self):
3339 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003340 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_BOTH` 0x3, the value of
3341 :py:obj:`SSL_SESS_CACHE_BOTH` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003342 """
3343 self.assertEqual(0x3, SESS_CACHE_BOTH)
3344
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003345 def test_sess_cache_no_auto_clear(self):
3346 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003347 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_AUTO_CLEAR` 0x80, the
3348 value of :py:obj:`SSL_SESS_CACHE_NO_AUTO_CLEAR` defined by
3349 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003350 """
3351 self.assertEqual(0x80, SESS_CACHE_NO_AUTO_CLEAR)
3352
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003353 def test_sess_cache_no_internal_lookup(self):
3354 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003355 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_LOOKUP` 0x100,
3356 the value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL_LOOKUP` defined by
3357 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003358 """
3359 self.assertEqual(0x100, SESS_CACHE_NO_INTERNAL_LOOKUP)
3360
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003361 def test_sess_cache_no_internal_store(self):
3362 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003363 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_STORE` 0x200,
3364 the value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL_STORE` defined by
3365 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003366 """
3367 self.assertEqual(0x200, SESS_CACHE_NO_INTERNAL_STORE)
3368
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003369 def test_sess_cache_no_internal(self):
3370 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003371 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL` 0x300, the
3372 value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL` defined by
3373 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003374 """
3375 self.assertEqual(0x300, SESS_CACHE_NO_INTERNAL)
3376
3377
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003378class MemoryBIOTests(TestCase, _LoopbackMixin):
Rick Deanb71c0d22009-04-01 14:09:23 -05003379 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003380 Tests for :py:obj:`OpenSSL.SSL.Connection` using a memory BIO.
Rick Deanb71c0d22009-04-01 14:09:23 -05003381 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003382 def _server(self, sock):
3383 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003384 Create a new server-side SSL :py:obj:`Connection` object wrapped around
3385 :py:obj:`sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003386 """
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003387 # Create the server side Connection. This is mostly setup boilerplate
3388 # - use TLSv1, use a particular certificate, etc.
3389 server_ctx = Context(TLSv1_METHOD)
Alex Gaynor43307782015-09-04 09:05:45 -04003390 server_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE)
Hynek Schlawack35618382015-09-05 21:54:25 +02003391 server_ctx.set_verify(
3392 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT | VERIFY_CLIENT_ONCE,
3393 verify_cb
3394 )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003395 server_store = server_ctx.get_cert_store()
Hynek Schlawack35618382015-09-05 21:54:25 +02003396 server_ctx.use_privatekey(
3397 load_privatekey(FILETYPE_PEM, server_key_pem))
3398 server_ctx.use_certificate(
3399 load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003400 server_ctx.check_privatekey()
3401 server_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Hynek Schlawack35618382015-09-05 21:54:25 +02003402 # Here the Connection is actually created. If None is passed as the
3403 # 2nd parameter, it indicates a memory BIO should be created.
Rick Deanb1ccd562009-07-09 23:52:39 -05003404 server_conn = Connection(server_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003405 server_conn.set_accept_state()
3406 return server_conn
3407
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003408 def _client(self, sock):
3409 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003410 Create a new client-side SSL :py:obj:`Connection` object wrapped around
3411 :py:obj:`sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003412 """
3413 # Now create the client side Connection. Similar boilerplate to the
3414 # above.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003415 client_ctx = Context(TLSv1_METHOD)
Alex Gaynor43307782015-09-04 09:05:45 -04003416 client_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE)
Hynek Schlawack35618382015-09-05 21:54:25 +02003417 client_ctx.set_verify(
3418 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT | VERIFY_CLIENT_ONCE,
3419 verify_cb
3420 )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003421 client_store = client_ctx.get_cert_store()
Hynek Schlawack35618382015-09-05 21:54:25 +02003422 client_ctx.use_privatekey(
3423 load_privatekey(FILETYPE_PEM, client_key_pem))
3424 client_ctx.use_certificate(
3425 load_certificate(FILETYPE_PEM, client_cert_pem))
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003426 client_ctx.check_privatekey()
3427 client_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05003428 client_conn = Connection(client_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003429 client_conn.set_connect_state()
3430 return client_conn
3431
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003432 def test_memoryConnect(self):
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003433 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003434 Two :py:obj:`Connection`s which use memory BIOs can be manually
3435 connected by reading from the output of each and writing those bytes to
3436 the input of the other and in this way establish a connection and
3437 exchange application-level bytes with each other.
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003438 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003439 server_conn = self._server(None)
3440 client_conn = self._client(None)
Rick Deanb71c0d22009-04-01 14:09:23 -05003441
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003442 # There should be no key or nonces yet.
3443 self.assertIdentical(server_conn.master_key(), None)
3444 self.assertIdentical(server_conn.client_random(), None)
3445 self.assertIdentical(server_conn.server_random(), None)
Rick Deanb71c0d22009-04-01 14:09:23 -05003446
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003447 # First, the handshake needs to happen. We'll deliver bytes back and
3448 # forth between the client and server until neither of them feels like
3449 # speaking any more.
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003450 self.assertIdentical(
3451 self._interactInMemory(client_conn, server_conn), None)
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003452
3453 # Now that the handshake is done, there should be a key and nonces.
3454 self.assertNotIdentical(server_conn.master_key(), None)
3455 self.assertNotIdentical(server_conn.client_random(), None)
3456 self.assertNotIdentical(server_conn.server_random(), None)
Hynek Schlawack35618382015-09-05 21:54:25 +02003457 self.assertEquals(
3458 server_conn.client_random(), client_conn.client_random())
3459 self.assertEquals(
3460 server_conn.server_random(), client_conn.server_random())
3461 self.assertNotEquals(
3462 server_conn.client_random(), server_conn.server_random())
3463 self.assertNotEquals(
3464 client_conn.client_random(), client_conn.server_random())
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003465
3466 # Here are the bytes we'll try to send.
Alex Gaynore7f51982016-09-11 11:48:14 -04003467 important_message = b'One if by land, two if by sea.'
Rick Deanb71c0d22009-04-01 14:09:23 -05003468
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003469 server_conn.write(important_message)
3470 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003471 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003472 (client_conn, important_message))
3473
3474 client_conn.write(important_message[::-1])
3475 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003476 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003477 (server_conn, important_message[::-1]))
Rick Deanb71c0d22009-04-01 14:09:23 -05003478
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003479 def test_socketConnect(self):
Rick Deanb1ccd562009-07-09 23:52:39 -05003480 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003481 Just like :py:obj:`test_memoryConnect` but with an actual socket.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003482
Hynek Schlawack35618382015-09-05 21:54:25 +02003483 This is primarily to rule out the memory BIO code as the source of any
3484 problems encountered while passing data over a :py:obj:`Connection` (if
3485 this test fails, there must be a problem outside the memory BIO code,
3486 as no memory BIO is involved here). Even though this isn't a memory
3487 BIO test, it's convenient to have it here.
Rick Deanb1ccd562009-07-09 23:52:39 -05003488 """
Jean-Paul Calderone06c7cc92010-09-24 23:52:00 -04003489 server_conn, client_conn = self._loopback()
Rick Deanb1ccd562009-07-09 23:52:39 -05003490
Alex Gaynore7f51982016-09-11 11:48:14 -04003491 important_message = b"Help me Obi Wan Kenobi, you're my only hope."
Rick Deanb1ccd562009-07-09 23:52:39 -05003492 client_conn.send(important_message)
3493 msg = server_conn.recv(1024)
3494 self.assertEqual(msg, important_message)
3495
3496 # Again in the other direction, just for fun.
3497 important_message = important_message[::-1]
3498 server_conn.send(important_message)
3499 msg = client_conn.recv(1024)
3500 self.assertEqual(msg, important_message)
3501
Jean-Paul Calderonefc4ed0f2009-04-27 11:51:27 -04003502 def test_socketOverridesMemory(self):
Rick Deanb71c0d22009-04-01 14:09:23 -05003503 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003504 Test that :py:obj:`OpenSSL.SSL.bio_read` and
3505 :py:obj:`OpenSSL.SSL.bio_write` don't work on
3506 :py:obj:`OpenSSL.SSL.Connection`() that use sockets.
Rick Deanb71c0d22009-04-01 14:09:23 -05003507 """
Alex Gaynor51d424c2016-09-10 14:50:11 -04003508 context = Context(TLSv1_METHOD)
Rick Deanb71c0d22009-04-01 14:09:23 -05003509 client = socket()
3510 clientSSL = Connection(context, client)
Alex Gaynor43307782015-09-04 09:05:45 -04003511 self.assertRaises(TypeError, clientSSL.bio_read, 100)
3512 self.assertRaises(TypeError, clientSSL.bio_write, "foo")
Alex Gaynor7e8b61e2015-09-04 13:13:05 -04003513 self.assertRaises(TypeError, clientSSL.bio_shutdown)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003514
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003515 def test_outgoingOverflow(self):
3516 """
3517 If more bytes than can be written to the memory BIO are passed to
Hynek Schlawack35618382015-09-05 21:54:25 +02003518 :py:obj:`Connection.send` at once, the number of bytes which were
3519 written is returned and that many bytes from the beginning of the input
3520 can be read from the other end of the connection.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003521 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003522 server = self._server(None)
3523 client = self._client(None)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003524
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003525 self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003526
3527 size = 2 ** 15
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003528 sent = client.send(b"x" * size)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003529 # Sanity check. We're trying to test what happens when the entire
3530 # input can't be sent. If the entire input was sent, this test is
3531 # meaningless.
3532 self.assertTrue(sent < size)
3533
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003534 receiver, received = self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003535 self.assertIdentical(receiver, server)
3536
3537 # We can rely on all of these bytes being received at once because
3538 # _loopback passes 2 ** 16 to recv - more than 2 ** 15.
3539 self.assertEquals(len(received), sent)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003540
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003541 def test_shutdown(self):
3542 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003543 :py:obj:`Connection.bio_shutdown` signals the end of the data stream
3544 from which the :py:obj:`Connection` reads.
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003545 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003546 server = self._server(None)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003547 server.bio_shutdown()
3548 e = self.assertRaises(Error, server.recv, 1024)
3549 # We don't want WantReadError or ZeroReturnError or anything - it's a
3550 # handshake failure.
Alex Gaynor5af32d02016-09-24 01:52:21 -04003551 assert type(e) in [Error, SysCallError]
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003552
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003553 def test_unexpectedEndOfFile(self):
3554 """
3555 If the connection is lost before an orderly SSL shutdown occurs,
3556 :py:obj:`OpenSSL.SSL.SysCallError` is raised with a message of
3557 "Unexpected EOF".
3558 """
3559 server_conn, client_conn = self._loopback()
3560 client_conn.sock_shutdown(SHUT_RDWR)
3561 exc = self.assertRaises(SysCallError, server_conn.recv, 1024)
3562 self.assertEqual(exc.args, (-1, "Unexpected EOF"))
3563
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003564 def _check_client_ca_list(self, func):
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003565 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003566 Verify the return value of the :py:obj:`get_client_ca_list` method for
3567 server and client connections.
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003568
Jonathan Ballet78b92a22011-07-16 08:07:26 +09003569 :param func: A function which will be called with the server context
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003570 before the client and server are connected to each other. This
3571 function should specify a list of CAs for the server to send to the
3572 client and return that same list. The list will be used to verify
Hynek Schlawack35618382015-09-05 21:54:25 +02003573 that :py:obj:`get_client_ca_list` returns the proper value at
3574 various times.
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003575 """
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003576 server = self._server(None)
3577 client = self._client(None)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003578 self.assertEqual(client.get_client_ca_list(), [])
3579 self.assertEqual(server.get_client_ca_list(), [])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003580 ctx = server.get_context()
3581 expected = func(ctx)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003582 self.assertEqual(client.get_client_ca_list(), [])
3583 self.assertEqual(server.get_client_ca_list(), expected)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003584 self._interactInMemory(client, server)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003585 self.assertEqual(client.get_client_ca_list(), expected)
3586 self.assertEqual(server.get_client_ca_list(), expected)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003587
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003588 def test_set_client_ca_list_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003589 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003590 :py:obj:`Context.set_client_ca_list` raises a :py:obj:`TypeError` if
3591 called with a non-list or a list that contains objects other than
3592 X509Names.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003593 """
3594 ctx = Context(TLSv1_METHOD)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003595 self.assertRaises(TypeError, ctx.set_client_ca_list, "spam")
3596 self.assertRaises(TypeError, ctx.set_client_ca_list, ["spam"])
3597 self.assertIdentical(ctx.set_client_ca_list([]), None)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003598
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003599 def test_set_empty_ca_list(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003600 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003601 If passed an empty list, :py:obj:`Context.set_client_ca_list`
3602 configures the context to send no CA names to the client and, on both
3603 the server and client sides, :py:obj:`Connection.get_client_ca_list`
3604 returns an empty list after the connection is set up.
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003605 """
3606 def no_ca(ctx):
3607 ctx.set_client_ca_list([])
3608 return []
3609 self._check_client_ca_list(no_ca)
3610
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003611 def test_set_one_ca_list(self):
3612 """
3613 If passed a list containing a single X509Name,
Hynek Schlawack35618382015-09-05 21:54:25 +02003614 :py:obj:`Context.set_client_ca_list` configures the context to send
3615 that CA name to the client and, on both the server and client sides,
Jonathan Ballet648875f2011-07-16 14:14:58 +09003616 :py:obj:`Connection.get_client_ca_list` returns a list containing that
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003617 X509Name after the connection is set up.
3618 """
3619 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3620 cadesc = cacert.get_subject()
Hynek Schlawack35618382015-09-05 21:54:25 +02003621
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003622 def single_ca(ctx):
3623 ctx.set_client_ca_list([cadesc])
3624 return [cadesc]
3625 self._check_client_ca_list(single_ca)
3626
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003627 def test_set_multiple_ca_list(self):
3628 """
3629 If passed a list containing multiple X509Name objects,
Hynek Schlawack35618382015-09-05 21:54:25 +02003630 :py:obj:`Context.set_client_ca_list` configures the context to send
3631 those CA names to the client and, on both the server and client sides,
Jonathan Ballet648875f2011-07-16 14:14:58 +09003632 :py:obj:`Connection.get_client_ca_list` returns a list containing those
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003633 X509Names after the connection is set up.
3634 """
3635 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3636 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3637
3638 sedesc = secert.get_subject()
3639 cldesc = clcert.get_subject()
3640
3641 def multiple_ca(ctx):
3642 L = [sedesc, cldesc]
3643 ctx.set_client_ca_list(L)
3644 return L
3645 self._check_client_ca_list(multiple_ca)
3646
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003647 def test_reset_ca_list(self):
3648 """
3649 If called multiple times, only the X509Names passed to the final call
Hynek Schlawack35618382015-09-05 21:54:25 +02003650 of :py:obj:`Context.set_client_ca_list` are used to configure the CA
3651 names sent to the client.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003652 """
3653 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3654 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3655 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3656
3657 cadesc = cacert.get_subject()
3658 sedesc = secert.get_subject()
3659 cldesc = clcert.get_subject()
3660
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003661 def changed_ca(ctx):
3662 ctx.set_client_ca_list([sedesc, cldesc])
3663 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003664 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003665 self._check_client_ca_list(changed_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003666
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003667 def test_mutated_ca_list(self):
3668 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003669 If the list passed to :py:obj:`Context.set_client_ca_list` is mutated
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003670 afterwards, this does not affect the list of CA names sent to the
3671 client.
3672 """
3673 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3674 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3675
3676 cadesc = cacert.get_subject()
3677 sedesc = secert.get_subject()
3678
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003679 def mutated_ca(ctx):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003680 L = [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003681 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003682 L.append(sedesc)
3683 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003684 self._check_client_ca_list(mutated_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003685
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003686 def test_add_client_ca_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003687 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003688 :py:obj:`Context.add_client_ca` raises :py:obj:`TypeError` if called
3689 with a non-X509 object or with a number of arguments other than one.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003690 """
3691 ctx = Context(TLSv1_METHOD)
3692 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003693 self.assertRaises(TypeError, ctx.add_client_ca)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003694 self.assertRaises(TypeError, ctx.add_client_ca, "spam")
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003695 self.assertRaises(TypeError, ctx.add_client_ca, cacert, cacert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003696
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003697 def test_one_add_client_ca(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003698 """
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003699 A certificate's subject can be added as a CA to be sent to the client
Jonathan Ballet648875f2011-07-16 14:14:58 +09003700 with :py:obj:`Context.add_client_ca`.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003701 """
3702 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3703 cadesc = cacert.get_subject()
Hynek Schlawack35618382015-09-05 21:54:25 +02003704
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003705 def single_ca(ctx):
3706 ctx.add_client_ca(cacert)
3707 return [cadesc]
3708 self._check_client_ca_list(single_ca)
3709
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003710 def test_multiple_add_client_ca(self):
3711 """
3712 Multiple CA names can be sent to the client by calling
Jonathan Ballet648875f2011-07-16 14:14:58 +09003713 :py:obj:`Context.add_client_ca` with multiple X509 objects.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003714 """
3715 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3716 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3717
3718 cadesc = cacert.get_subject()
3719 sedesc = secert.get_subject()
3720
3721 def multiple_ca(ctx):
3722 ctx.add_client_ca(cacert)
3723 ctx.add_client_ca(secert)
3724 return [cadesc, sedesc]
3725 self._check_client_ca_list(multiple_ca)
3726
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003727 def test_set_and_add_client_ca(self):
3728 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003729 A call to :py:obj:`Context.set_client_ca_list` followed by a call to
Hynek Schlawack35618382015-09-05 21:54:25 +02003730 :py:obj:`Context.add_client_ca` results in using the CA names from the
3731 first call and the CA name from the second call.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003732 """
3733 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3734 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3735 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3736
3737 cadesc = cacert.get_subject()
3738 sedesc = secert.get_subject()
3739 cldesc = clcert.get_subject()
3740
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003741 def mixed_set_add_ca(ctx):
3742 ctx.set_client_ca_list([cadesc, sedesc])
3743 ctx.add_client_ca(clcert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003744 return [cadesc, sedesc, cldesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003745 self._check_client_ca_list(mixed_set_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003746
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003747 def test_set_after_add_client_ca(self):
3748 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003749 A call to :py:obj:`Context.set_client_ca_list` after a call to
Hynek Schlawack35618382015-09-05 21:54:25 +02003750 :py:obj:`Context.add_client_ca` replaces the CA name specified by the
3751 former call with the names specified by the latter call.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003752 """
3753 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3754 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3755 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3756
3757 cadesc = cacert.get_subject()
3758 sedesc = secert.get_subject()
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003759
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003760 def set_replaces_add_ca(ctx):
3761 ctx.add_client_ca(clcert)
3762 ctx.set_client_ca_list([cadesc])
3763 ctx.add_client_ca(secert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003764 return [cadesc, sedesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003765 self._check_client_ca_list(set_replaces_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003766
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003767
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003768class ConnectionBIOTests(TestCase):
3769 """
3770 Tests for :py:obj:`Connection.bio_read` and :py:obj:`Connection.bio_write`.
3771 """
3772 def test_wantReadError(self):
3773 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003774 :py:obj:`Connection.bio_read` raises
3775 :py:obj:`OpenSSL.SSL.WantReadError` if there are no bytes available to
3776 be read from the BIO.
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003777 """
3778 ctx = Context(TLSv1_METHOD)
3779 conn = Connection(ctx, None)
3780 self.assertRaises(WantReadError, conn.bio_read, 1024)
3781
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003782 def test_buffer_size(self):
3783 """
3784 :py:obj:`Connection.bio_read` accepts an integer giving the maximum
3785 number of bytes to read and return.
3786 """
3787 ctx = Context(TLSv1_METHOD)
3788 conn = Connection(ctx, None)
3789 conn.set_connect_state()
3790 try:
3791 conn.do_handshake()
3792 except WantReadError:
3793 pass
3794 data = conn.bio_read(2)
3795 self.assertEqual(2, len(data))
3796
Hynek Schlawack35618382015-09-05 21:54:25 +02003797 @skip_if_py3
3798 def test_buffer_size_long(self):
3799 """
3800 On Python 2 :py:obj:`Connection.bio_read` accepts values of type
3801 :py:obj:`long` as well as :py:obj:`int`.
3802 """
3803 ctx = Context(TLSv1_METHOD)
3804 conn = Connection(ctx, None)
3805 conn.set_connect_state()
3806 try:
3807 conn.do_handshake()
3808 except WantReadError:
3809 pass
3810 data = conn.bio_read(long(2))
3811 self.assertEqual(2, len(data))
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003812
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003813
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003814class InfoConstantTests(TestCase):
3815 """
3816 Tests for assorted constants exposed for use in info callbacks.
3817 """
3818 def test_integers(self):
3819 """
3820 All of the info constants are integers.
3821
3822 This is a very weak test. It would be nice to have one that actually
3823 verifies that as certain info events happen, the value passed to the
3824 info callback matches up with the constant exposed by OpenSSL.SSL.
3825 """
3826 for const in [
Alex Gaynor5af32d02016-09-24 01:52:21 -04003827 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK,
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003828 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
3829 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
3830 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
Hynek Schlawack35618382015-09-05 21:54:25 +02003831 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE
3832 ]:
Alex Gaynor5af32d02016-09-24 01:52:21 -04003833 assert isinstance(const, int)
3834
3835 # These constants don't exist on OpenSSL 1.1.0
3836 for const in [
3837 SSL_ST_INIT, SSL_ST_BEFORE, SSL_ST_OK, SSL_ST_RENEGOTIATE
3838 ]:
3839 assert const is None or isinstance(const, int)
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003840
Ziga Seilnacht44611bf2009-08-31 20:49:30 +02003841
Cory Benfield1d142142016-03-30 11:51:45 +01003842class TestRequires(object):
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003843 """
3844 Tests for the decorator factory used to conditionally raise
Cory Benfield1d142142016-03-30 11:51:45 +01003845 NotImplementedError when older OpenSSLs are used.
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003846 """
3847 def test_available(self):
3848 """
3849 When the OpenSSL functionality is available the decorated functions
3850 work appropriately.
3851 """
3852 feature_guard = _make_requires(True, "Error text")
3853 results = []
3854
3855 @feature_guard
3856 def inner():
3857 results.append(True)
3858 return True
3859
Cory Benfield2333e5e2016-03-30 14:24:16 +01003860 assert inner() is True
3861 assert [True] == results
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003862
3863 def test_unavailable(self):
3864 """
3865 When the OpenSSL functionality is not available the decorated function
3866 does not execute and NotImplementedError is raised.
3867 """
3868 feature_guard = _make_requires(False, "Error text")
3869 results = []
3870
3871 @feature_guard
3872 def inner():
3873 results.append(True)
3874 return True
3875
Cory Benfield1d142142016-03-30 11:51:45 +01003876 with pytest.raises(NotImplementedError) as e:
3877 inner()
3878
3879 assert "Error text" in str(e.value)
Cory Benfield2333e5e2016-03-30 14:24:16 +01003880 assert results == []