blob: 2b7e276756b3b857811206942ad86ae667c38fe5 [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
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400224class _LoopbackMixin:
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):
260 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900261 Try to read application bytes from each of the two :py:obj:`Connection`
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400262 objects. Copy bytes back and forth between their send/receive buffers
263 for as long as there is anything to copy. When there is nothing more
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200264 to copy, return :py:obj:`None`. If one of them actually manages to
265 deliver some application bytes, return a two-tuple of the connection
266 from which the bytes were read and the bytes themselves.
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400267 """
268 wrote = True
269 while wrote:
270 # Loop until neither side has anything to say
271 wrote = False
272
273 # Copy stuff from each side's send buffer to the other side's
274 # receive buffer.
275 for (read, write) in [(client_conn, server_conn),
276 (server_conn, client_conn)]:
277
278 # Give the side a chance to generate some more bytes, or
279 # succeed.
280 try:
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400281 data = read.recv(2 ** 16)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400282 except WantReadError:
283 # It didn't succeed, so we'll hope it generated some
284 # output.
285 pass
286 else:
287 # It did succeed, so we'll stop now and let the caller deal
288 # with it.
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400289 return (read, data)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400290
291 while True:
292 # Keep copying as long as there's more stuff there.
293 try:
294 dirty = read.bio_read(4096)
295 except WantReadError:
296 # Okay, nothing more waiting to be sent. Stop
297 # processing this send buffer.
298 break
299 else:
300 # Keep track of the fact that someone generated some
301 # output.
302 wrote = True
303 write.bio_write(dirty)
304
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -0400305 def _handshakeInMemory(self, client_conn, server_conn):
Jean-Paul Calderoneb2b40782014-05-06 08:47:40 -0400306 """
307 Perform the TLS handshake between two :py:class:`Connection` instances
308 connected to each other via memory BIOs.
309 """
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -0400310 client_conn.set_connect_state()
311 server_conn.set_accept_state()
312
313 for conn in [client_conn, server_conn]:
314 try:
315 conn.do_handshake()
316 except WantReadError:
317 pass
318
319 self._interactInMemory(client_conn, server_conn)
320
321
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400322class VersionTests(TestCase):
323 """
324 Tests for version information exposed by
Jonathan Ballet648875f2011-07-16 14:14:58 +0900325 :py:obj:`OpenSSL.SSL.SSLeay_version` and
326 :py:obj:`OpenSSL.SSL.OPENSSL_VERSION_NUMBER`.
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400327 """
328 def test_OPENSSL_VERSION_NUMBER(self):
329 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900330 :py:obj:`OPENSSL_VERSION_NUMBER` is an integer with status in the low
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400331 byte and the patch, fix, minor, and major versions in the
332 nibbles above that.
333 """
334 self.assertTrue(isinstance(OPENSSL_VERSION_NUMBER, int))
335
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400336 def test_SSLeay_version(self):
337 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900338 :py:obj:`SSLeay_version` takes a version type indicator and returns
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400339 one of a number of version strings based on that indicator.
340 """
341 versions = {}
342 for t in [SSLEAY_VERSION, SSLEAY_CFLAGS, SSLEAY_BUILT_ON,
343 SSLEAY_PLATFORM, SSLEAY_DIR]:
344 version = SSLeay_version(t)
345 versions[version] = t
346 self.assertTrue(isinstance(version, bytes))
347 self.assertEqual(len(versions), 5)
348
349
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100350@pytest.fixture
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100351def ca_file(tmpdir):
352 """
353 Create a valid PEM file with CA certificates and return the path.
354 """
355 key = rsa.generate_private_key(
356 public_exponent=65537,
357 key_size=2048,
358 backend=default_backend()
359 )
360 public_key = key.public_key()
361
362 builder = x509.CertificateBuilder()
363 builder = builder.subject_name(x509.Name([
364 x509.NameAttribute(NameOID.COMMON_NAME, u"pyopenssl.org"),
365 ]))
366 builder = builder.issuer_name(x509.Name([
367 x509.NameAttribute(NameOID.COMMON_NAME, u"pyopenssl.org"),
368 ]))
369 one_day = datetime.timedelta(1, 0, 0)
370 builder = builder.not_valid_before(datetime.datetime.today() - one_day)
371 builder = builder.not_valid_after(datetime.datetime.today() + one_day)
372 builder = builder.serial_number(int(uuid.uuid4()))
373 builder = builder.public_key(public_key)
374 builder = builder.add_extension(
375 x509.BasicConstraints(ca=True, path_length=None), critical=True,
376 )
377
378 certificate = builder.sign(
379 private_key=key, algorithm=hashes.SHA256(),
380 backend=default_backend()
381 )
382
383 ca_file = tmpdir.join("test.pem")
384 ca_file.write_binary(
385 certificate.public_bytes(
386 encoding=serialization.Encoding.PEM,
387 )
388 )
389
390 return str(ca_file).encode("ascii")
391
392
393@pytest.fixture
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100394def context():
395 """
396 A simple TLS 1.0 context.
397 """
398 return Context(TLSv1_METHOD)
399
400
401class TestContext(object):
Hynek Schlawackaa861212016-03-13 13:53:48 +0100402 """
403 py.test-based tests for :class:`OpenSSL.SSL.Context`.
404
405 If possible, add new tests here.
406 """
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100407 @pytest.mark.parametrize("cipher_string", [
408 b"hello world:AES128-SHA",
409 u"hello world:AES128-SHA",
410 ])
411 def test_set_cipher_list(self, context, cipher_string):
412 """
Hynek Schlawacka7a63af2016-03-11 12:05:26 +0100413 :meth:`Context.set_cipher_list` accepts both byte and unicode strings
414 for naming the ciphers which connections created with the context
415 object will be able to choose from.
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100416 """
417 context.set_cipher_list(cipher_string)
418 conn = Connection(context, None)
419
420 assert "AES128-SHA" in conn.get_cipher_list()
421
422 @pytest.mark.parametrize("cipher_list,error", [
423 (object(), TypeError),
424 ("imaginary-cipher", Error),
425 ])
426 def test_set_cipher_list_wrong_args(self, context, cipher_list, error):
427 """
428 :meth:`Context.set_cipher_list` raises :exc:`TypeError` when passed a
429 non-string argument and raises :exc:`OpenSSL.SSL.Error` when passed an
430 incorrect cipher list string.
431 """
432 with pytest.raises(error):
433 context.set_cipher_list(cipher_list)
434
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100435 def test_load_client_ca(self, context, ca_file):
436 """
437 :meth:`Context.load_client_ca` works as far as we can tell.
438 """
439 context.load_client_ca(ca_file)
440
441 def test_load_client_ca_invalid(self, context, tmpdir):
442 """
443 :meth:`Context.load_client_ca` raises an Error if the ca file is
444 invalid.
445 """
446 ca_file = tmpdir.join("test.pem")
447 ca_file.write("")
448
449 with pytest.raises(Error) as e:
450 context.load_client_ca(str(ca_file).encode("ascii"))
451
452 assert "PEM routines" == e.value.args[0][0][0]
453
454 def test_load_client_ca_unicode(self, context, ca_file):
455 """
456 Passing the path as unicode raises a warning but works.
457 """
458 pytest.deprecated_call(
459 context.load_client_ca, ca_file.decode("ascii")
460 )
461
462 def test_set_session_id(self, context):
463 """
464 :meth:`Context.set_session_id` works as far as we can tell.
465 """
466 context.set_session_id(b"abc")
467
468 def test_set_session_id_fail(self, context):
469 """
470 :meth:`Context.set_session_id` errors are propagated.
471 """
472 with pytest.raises(Error) as e:
473 context.set_session_id(b"abc" * 1000)
474
475 assert [
476 ("SSL routines",
477 "SSL_CTX_set_session_id_context",
478 "ssl session id context too long")
479 ] == e.value.args[0]
480
481 def test_set_session_id_unicode(self, context):
482 """
483 :meth:`Context.set_session_id` raises a warning if a unicode string is
484 passed.
485 """
486 pytest.deprecated_call(context.set_session_id, u"abc")
487
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100488
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400489class ContextTests(TestCase, _LoopbackMixin):
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400490 """
Hynek Schlawackaa861212016-03-13 13:53:48 +0100491 Unit tests for :class:`OpenSSL.SSL.Context`.
492
493 If possible, add new tests to :class:`TestContext` above.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400494 """
495 def test_method(self):
496 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200497 :py:obj:`Context` can be instantiated with one of
498 :py:obj:`SSLv2_METHOD`, :py:obj:`SSLv3_METHOD`,
499 :py:obj:`SSLv23_METHOD`, :py:obj:`TLSv1_METHOD`,
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400500 :py:obj:`TLSv1_1_METHOD`, or :py:obj:`TLSv1_2_METHOD`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400501 """
Alex Gaynor5af32d02016-09-24 01:52:21 -0400502 methods = [SSLv23_METHOD, TLSv1_METHOD]
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400503 for meth in methods:
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400504 Context(meth)
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400505
Alex Gaynor5af32d02016-09-24 01:52:21 -0400506 maybe = [SSLv2_METHOD, SSLv3_METHOD, TLSv1_1_METHOD, TLSv1_2_METHOD]
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400507 for meth in maybe:
508 try:
509 Context(meth)
510 except (Error, ValueError):
511 # Some versions of OpenSSL have SSLv2 / TLSv1.1 / TLSv1.2, some
512 # don't. Difficult to say in advance.
513 pass
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400514
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400515 self.assertRaises(TypeError, Context, "")
516 self.assertRaises(ValueError, Context, 10)
517
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200518 @skip_if_py3
519 def test_method_long(self):
520 """
521 On Python 2 :py:class:`Context` accepts values of type
522 :py:obj:`long` as well as :py:obj:`int`.
523 """
524 Context(long(TLSv1_METHOD))
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500525
Rick Deane15b1472009-07-09 15:53:42 -0500526 def test_type(self):
527 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200528 :py:obj:`Context` and :py:obj:`ContextType` refer to the same type
529 object and can be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -0500530 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400531 self.assertIdentical(Context, ContextType)
532 self.assertConsistentType(Context, 'Context', TLSv1_METHOD)
Rick Deane15b1472009-07-09 15:53:42 -0500533
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400534 def test_use_privatekey(self):
535 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200536 :py:obj:`Context.use_privatekey` takes an :py:obj:`OpenSSL.crypto.PKey`
537 instance.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400538 """
539 key = PKey()
540 key.generate_key(TYPE_RSA, 128)
541 ctx = Context(TLSv1_METHOD)
542 ctx.use_privatekey(key)
543 self.assertRaises(TypeError, ctx.use_privatekey, "")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400544
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800545 def test_use_privatekey_file_missing(self):
546 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200547 :py:obj:`Context.use_privatekey_file` raises
548 :py:obj:`OpenSSL.SSL.Error` when passed the name of a file which does
549 not exist.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800550 """
551 ctx = Context(TLSv1_METHOD)
552 self.assertRaises(Error, ctx.use_privatekey_file, self.mktemp())
553
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400554 def _use_privatekey_file_test(self, pemfile, filetype):
555 """
556 Verify that calling ``Context.use_privatekey_file`` with the given
557 arguments does not raise an exception.
558 """
559 key = PKey()
560 key.generate_key(TYPE_RSA, 128)
561
562 with open(pemfile, "wt") as pem:
563 pem.write(
564 dump_privatekey(FILETYPE_PEM, key).decode("ascii")
565 )
566
567 ctx = Context(TLSv1_METHOD)
568 ctx.use_privatekey_file(pemfile, filetype)
569
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400570 def test_use_privatekey_file_bytes(self):
571 """
572 A private key can be specified from a file by passing a ``bytes``
573 instance giving the file name to ``Context.use_privatekey_file``.
574 """
575 self._use_privatekey_file_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -0400576 self.mktemp() + NON_ASCII.encode(getfilesystemencoding()),
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400577 FILETYPE_PEM,
578 )
579
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400580 def test_use_privatekey_file_unicode(self):
581 """
582 A private key can be specified from a file by passing a ``unicode``
583 instance giving the file name to ``Context.use_privatekey_file``.
584 """
585 self._use_privatekey_file_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -0400586 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII,
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400587 FILETYPE_PEM,
588 )
589
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200590 @skip_if_py3
591 def test_use_privatekey_file_long(self):
592 """
593 On Python 2 :py:obj:`Context.use_privatekey_file` accepts a
594 filetype of type :py:obj:`long` as well as :py:obj:`int`.
595 """
596 self._use_privatekey_file_test(self.mktemp(), long(FILETYPE_PEM))
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500597
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800598 def test_use_certificate_wrong_args(self):
599 """
600 :py:obj:`Context.use_certificate_wrong_args` raises :py:obj:`TypeError`
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200601 when not passed exactly one :py:obj:`OpenSSL.crypto.X509` instance as
602 an argument.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800603 """
604 ctx = Context(TLSv1_METHOD)
605 self.assertRaises(TypeError, ctx.use_certificate)
606 self.assertRaises(TypeError, ctx.use_certificate, "hello, world")
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200607 self.assertRaises(
608 TypeError, ctx.use_certificate, X509(), "hello, world"
609 )
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800610
611 def test_use_certificate_uninitialized(self):
612 """
613 :py:obj:`Context.use_certificate` raises :py:obj:`OpenSSL.SSL.Error`
614 when passed a :py:obj:`OpenSSL.crypto.X509` instance which has not been
615 initialized (ie, which does not actually have any certificate data).
616 """
617 ctx = Context(TLSv1_METHOD)
618 self.assertRaises(Error, ctx.use_certificate, X509())
619
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800620 def test_use_certificate(self):
621 """
622 :py:obj:`Context.use_certificate` sets the certificate which will be
623 used to identify connections created using the context.
624 """
625 # TODO
626 # Hard to assert anything. But we could set a privatekey then ask
627 # OpenSSL if the cert and key agree using check_privatekey. Then as
628 # long as check_privatekey works right we're good...
629 ctx = Context(TLSv1_METHOD)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200630 ctx.use_certificate(
631 load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
632 )
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800633
634 def test_use_certificate_file_wrong_args(self):
635 """
636 :py:obj:`Context.use_certificate_file` raises :py:obj:`TypeError` if
637 called with zero arguments or more than two arguments, or if the first
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200638 argument is not a byte string or the second argumnent is not an
639 integer.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800640 """
641 ctx = Context(TLSv1_METHOD)
642 self.assertRaises(TypeError, ctx.use_certificate_file)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200643 self.assertRaises(TypeError, ctx.use_certificate_file, b"somefile",
644 object())
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800645 self.assertRaises(
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200646 TypeError, ctx.use_certificate_file, b"somefile", FILETYPE_PEM,
647 object())
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800648 self.assertRaises(
649 TypeError, ctx.use_certificate_file, object(), FILETYPE_PEM)
650 self.assertRaises(
651 TypeError, ctx.use_certificate_file, b"somefile", object())
652
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800653 def test_use_certificate_file_missing(self):
654 """
655 :py:obj:`Context.use_certificate_file` raises
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200656 `:py:obj:`OpenSSL.SSL.Error` if passed the name of a file which does
657 not exist.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800658 """
659 ctx = Context(TLSv1_METHOD)
660 self.assertRaises(Error, ctx.use_certificate_file, self.mktemp())
661
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400662 def _use_certificate_file_test(self, certificate_file):
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800663 """
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400664 Verify that calling ``Context.use_certificate_file`` with the given
665 filename doesn't raise an exception.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800666 """
667 # TODO
668 # Hard to assert anything. But we could set a privatekey then ask
669 # OpenSSL if the cert and key agree using check_privatekey. Then as
670 # long as check_privatekey works right we're good...
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400671 with open(certificate_file, "wb") as pem_file:
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800672 pem_file.write(cleartextCertificatePEM)
673
674 ctx = Context(TLSv1_METHOD)
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400675 ctx.use_certificate_file(certificate_file)
676
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400677 def test_use_certificate_file_bytes(self):
678 """
679 :py:obj:`Context.use_certificate_file` sets the certificate (given as a
680 ``bytes`` filename) which will be used to identify connections created
681 using the context.
682 """
Hynek Schlawack4813c0e2015-04-16 13:38:01 -0400683 filename = self.mktemp() + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400684 self._use_certificate_file_test(filename)
685
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400686 def test_use_certificate_file_unicode(self):
687 """
688 :py:obj:`Context.use_certificate_file` sets the certificate (given as a
689 ``bytes`` filename) which will be used to identify connections created
690 using the context.
691 """
Hynek Schlawack4813c0e2015-04-16 13:38:01 -0400692 filename = self.mktemp().decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400693 self._use_certificate_file_test(filename)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800694
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200695 @skip_if_py3
696 def test_use_certificate_file_long(self):
697 """
698 On Python 2 :py:obj:`Context.use_certificate_file` accepts a
699 filetype of type :py:obj:`long` as well as :py:obj:`int`.
700 """
701 pem_filename = self.mktemp()
702 with open(pem_filename, "wb") as pem_file:
703 pem_file.write(cleartextCertificatePEM)
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500704
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200705 ctx = Context(TLSv1_METHOD)
706 ctx.use_certificate_file(pem_filename, long(FILETYPE_PEM))
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500707
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500708 def test_check_privatekey_valid(self):
709 """
710 :py:obj:`Context.check_privatekey` returns :py:obj:`None` if the
711 :py:obj:`Context` instance has been configured to use a matched key and
712 certificate pair.
713 """
714 key = load_privatekey(FILETYPE_PEM, client_key_pem)
715 cert = load_certificate(FILETYPE_PEM, client_cert_pem)
716 context = Context(TLSv1_METHOD)
717 context.use_privatekey(key)
718 context.use_certificate(cert)
719 self.assertIs(None, context.check_privatekey())
720
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500721 def test_check_privatekey_invalid(self):
722 """
723 :py:obj:`Context.check_privatekey` raises :py:obj:`Error` if the
724 :py:obj:`Context` instance has been configured to use a key and
725 certificate pair which don't relate to each other.
726 """
727 key = load_privatekey(FILETYPE_PEM, client_key_pem)
728 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
729 context = Context(TLSv1_METHOD)
730 context.use_privatekey(key)
731 context.use_certificate(cert)
732 self.assertRaises(Error, context.check_privatekey)
733
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500734 def test_check_privatekey_wrong_args(self):
735 """
736 :py:obj:`Context.check_privatekey` raises :py:obj:`TypeError` if called
737 with other than no arguments.
738 """
739 context = Context(TLSv1_METHOD)
740 self.assertRaises(TypeError, context.check_privatekey, object())
741
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400742 def test_set_app_data_wrong_args(self):
743 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200744 :py:obj:`Context.set_app_data` raises :py:obj:`TypeError` if called
745 with other than one argument.
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400746 """
747 context = Context(TLSv1_METHOD)
748 self.assertRaises(TypeError, context.set_app_data)
749 self.assertRaises(TypeError, context.set_app_data, None, None)
750
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400751 def test_get_app_data_wrong_args(self):
752 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200753 :py:obj:`Context.get_app_data` raises :py:obj:`TypeError` if called
754 with any arguments.
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400755 """
756 context = Context(TLSv1_METHOD)
757 self.assertRaises(TypeError, context.get_app_data, None)
758
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400759 def test_app_data(self):
760 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200761 :py:obj:`Context.set_app_data` stores an object for later retrieval
762 using :py:obj:`Context.get_app_data`.
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400763 """
764 app_data = object()
765 context = Context(TLSv1_METHOD)
766 context.set_app_data(app_data)
767 self.assertIdentical(context.get_app_data(), app_data)
768
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400769 def test_set_options_wrong_args(self):
770 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200771 :py:obj:`Context.set_options` raises :py:obj:`TypeError` if called with
772 the wrong number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400773 """
774 context = Context(TLSv1_METHOD)
775 self.assertRaises(TypeError, context.set_options)
776 self.assertRaises(TypeError, context.set_options, None)
777 self.assertRaises(TypeError, context.set_options, 1, None)
778
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500779 def test_set_options(self):
780 """
781 :py:obj:`Context.set_options` returns the new options value.
782 """
783 context = Context(TLSv1_METHOD)
784 options = context.set_options(OP_NO_SSLv2)
Alex Gaynor2310f8b2016-09-10 14:39:32 -0400785 assert options & OP_NO_SSLv2 == OP_NO_SSLv2
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500786
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200787 @skip_if_py3
788 def test_set_options_long(self):
789 """
790 On Python 2 :py:obj:`Context.set_options` accepts values of type
791 :py:obj:`long` as well as :py:obj:`int`.
792 """
793 context = Context(TLSv1_METHOD)
794 options = context.set_options(long(OP_NO_SSLv2))
Alex Gaynor2310f8b2016-09-10 14:39:32 -0400795 assert options & OP_NO_SSLv2 == OP_NO_SSLv2
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500796
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300797 def test_set_mode_wrong_args(self):
798 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200799 :py:obj:`Context.set`mode} raises :py:obj:`TypeError` if called with
800 the wrong number of arguments or a non-:py:obj:`int` argument.
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300801 """
802 context = Context(TLSv1_METHOD)
803 self.assertRaises(TypeError, context.set_mode)
804 self.assertRaises(TypeError, context.set_mode, None)
805 self.assertRaises(TypeError, context.set_mode, 1, None)
806
Alex Gaynord3b5d9b2016-07-31 10:54:24 -0400807 def test_set_mode(self):
808 """
809 :py:obj:`Context.set_mode` accepts a mode bitvector and returns the
810 newly set mode.
811 """
812 context = Context(TLSv1_METHOD)
813 self.assertTrue(
814 MODE_RELEASE_BUFFERS & context.set_mode(MODE_RELEASE_BUFFERS))
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500815
Alex Gaynord3b5d9b2016-07-31 10:54:24 -0400816 @skip_if_py3
817 def test_set_mode_long(self):
818 """
819 On Python 2 :py:obj:`Context.set_mode` accepts values of type
820 :py:obj:`long` as well as :py:obj:`int`.
821 """
822 context = Context(TLSv1_METHOD)
823 mode = context.set_mode(long(MODE_RELEASE_BUFFERS))
824 self.assertTrue(MODE_RELEASE_BUFFERS & mode)
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400825
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400826 def test_set_timeout_wrong_args(self):
827 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200828 :py:obj:`Context.set_timeout` raises :py:obj:`TypeError` if called with
829 the wrong number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400830 """
831 context = Context(TLSv1_METHOD)
832 self.assertRaises(TypeError, context.set_timeout)
833 self.assertRaises(TypeError, context.set_timeout, None)
834 self.assertRaises(TypeError, context.set_timeout, 1, None)
835
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400836 def test_get_timeout_wrong_args(self):
837 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200838 :py:obj:`Context.get_timeout` raises :py:obj:`TypeError` if called with
839 any arguments.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400840 """
841 context = Context(TLSv1_METHOD)
842 self.assertRaises(TypeError, context.get_timeout, None)
843
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400844 def test_timeout(self):
845 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200846 :py:obj:`Context.set_timeout` sets the session timeout for all
847 connections created using the context object.
848 :py:obj:`Context.get_timeout` retrieves this value.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400849 """
850 context = Context(TLSv1_METHOD)
851 context.set_timeout(1234)
852 self.assertEquals(context.get_timeout(), 1234)
853
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200854 @skip_if_py3
855 def test_timeout_long(self):
856 """
857 On Python 2 :py:obj:`Context.set_timeout` accepts values of type
858 `long` as well as int.
859 """
860 context = Context(TLSv1_METHOD)
861 context.set_timeout(long(1234))
862 self.assertEquals(context.get_timeout(), 1234)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500863
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400864 def test_set_verify_depth_wrong_args(self):
865 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200866 :py:obj:`Context.set_verify_depth` raises :py:obj:`TypeError` if called
867 with the wrong number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400868 """
869 context = Context(TLSv1_METHOD)
870 self.assertRaises(TypeError, context.set_verify_depth)
871 self.assertRaises(TypeError, context.set_verify_depth, None)
872 self.assertRaises(TypeError, context.set_verify_depth, 1, None)
873
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400874 def test_get_verify_depth_wrong_args(self):
875 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200876 :py:obj:`Context.get_verify_depth` raises :py:obj:`TypeError` if called
877 with any arguments.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400878 """
879 context = Context(TLSv1_METHOD)
880 self.assertRaises(TypeError, context.get_verify_depth, None)
881
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400882 def test_verify_depth(self):
883 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200884 :py:obj:`Context.set_verify_depth` sets the number of certificates in
885 a chain to follow before giving up. The value can be retrieved with
Jonathan Ballet648875f2011-07-16 14:14:58 +0900886 :py:obj:`Context.get_verify_depth`.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400887 """
888 context = Context(TLSv1_METHOD)
889 context.set_verify_depth(11)
890 self.assertEquals(context.get_verify_depth(), 11)
891
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200892 @skip_if_py3
893 def test_verify_depth_long(self):
894 """
895 On Python 2 :py:obj:`Context.set_verify_depth` accepts values of
896 type `long` as well as int.
897 """
898 context = Context(TLSv1_METHOD)
899 context.set_verify_depth(long(11))
900 self.assertEquals(context.get_verify_depth(), 11)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500901
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400902 def _write_encrypted_pem(self, passphrase):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400903 """
904 Write a new private key out to a new file, encrypted using the given
905 passphrase. Return the path to the new file.
906 """
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400907 key = PKey()
908 key.generate_key(TYPE_RSA, 128)
909 pemFile = self.mktemp()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400910 fObj = open(pemFile, 'w')
911 pem = dump_privatekey(FILETYPE_PEM, key, "blowfish", passphrase)
912 fObj.write(pem.decode('ascii'))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400913 fObj.close()
914 return pemFile
915
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400916 def test_set_passwd_cb_wrong_args(self):
917 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200918 :py:obj:`Context.set_passwd_cb` raises :py:obj:`TypeError` if called
919 with the wrong arguments or with a non-callable first argument.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400920 """
921 context = Context(TLSv1_METHOD)
922 self.assertRaises(TypeError, context.set_passwd_cb)
923 self.assertRaises(TypeError, context.set_passwd_cb, None)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200924 self.assertRaises(
925 TypeError, context.set_passwd_cb, lambda: None, None, None
Hynek Schlawack2c013a92015-09-05 19:33:05 +0200926 ) # pragma: nocover
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400927
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400928 def test_set_passwd_cb(self):
929 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200930 :py:obj:`Context.set_passwd_cb` accepts a callable which will be
931 invoked when a private key is loaded from an encrypted PEM.
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400932 """
Alex Gaynore7f51982016-09-11 11:48:14 -0400933 passphrase = b"foobar"
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400934 pemFile = self._write_encrypted_pem(passphrase)
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400935 calledWith = []
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200936
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400937 def passphraseCallback(maxlen, verify, extra):
938 calledWith.append((maxlen, verify, extra))
939 return passphrase
940 context = Context(TLSv1_METHOD)
941 context.set_passwd_cb(passphraseCallback)
942 context.use_privatekey_file(pemFile)
943 self.assertTrue(len(calledWith), 1)
944 self.assertTrue(isinstance(calledWith[0][0], int))
945 self.assertTrue(isinstance(calledWith[0][1], int))
946 self.assertEqual(calledWith[0][2], None)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400947
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400948 def test_passwd_callback_exception(self):
949 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200950 :py:obj:`Context.use_privatekey_file` propagates any exception raised
951 by the passphrase callback.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400952 """
Alex Gaynore7f51982016-09-11 11:48:14 -0400953 pemFile = self._write_encrypted_pem(b"monkeys are nice")
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200954
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400955 def passphraseCallback(maxlen, verify, extra):
956 raise RuntimeError("Sorry, I am a fail.")
957
958 context = Context(TLSv1_METHOD)
959 context.set_passwd_cb(passphraseCallback)
960 self.assertRaises(RuntimeError, context.use_privatekey_file, pemFile)
961
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400962 def test_passwd_callback_false(self):
963 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200964 :py:obj:`Context.use_privatekey_file` raises
965 :py:obj:`OpenSSL.SSL.Error` if the passphrase callback returns a false
966 value.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400967 """
Alex Gaynore7f51982016-09-11 11:48:14 -0400968 pemFile = self._write_encrypted_pem(b"monkeys are nice")
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200969
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400970 def passphraseCallback(maxlen, verify, extra):
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500971 return b""
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400972
973 context = Context(TLSv1_METHOD)
974 context.set_passwd_cb(passphraseCallback)
975 self.assertRaises(Error, context.use_privatekey_file, pemFile)
976
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400977 def test_passwd_callback_non_string(self):
978 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200979 :py:obj:`Context.use_privatekey_file` raises
980 :py:obj:`OpenSSL.SSL.Error` if the passphrase callback returns a true
981 non-string value.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400982 """
Alex Gaynore7f51982016-09-11 11:48:14 -0400983 pemFile = self._write_encrypted_pem(b"monkeys are nice")
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200984
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400985 def passphraseCallback(maxlen, verify, extra):
986 return 10
987
988 context = Context(TLSv1_METHOD)
989 context.set_passwd_cb(passphraseCallback)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800990 self.assertRaises(ValueError, context.use_privatekey_file, pemFile)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400991
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400992 def test_passwd_callback_too_long(self):
993 """
994 If the passphrase returned by the passphrase callback returns a string
995 longer than the indicated maximum length, it is truncated.
996 """
997 # A priori knowledge!
Alex Gaynore7f51982016-09-11 11:48:14 -0400998 passphrase = b"x" * 1024
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400999 pemFile = self._write_encrypted_pem(passphrase)
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001000
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -04001001 def passphraseCallback(maxlen, verify, extra):
1002 assert maxlen == 1024
Alex Gaynore7f51982016-09-11 11:48:14 -04001003 return passphrase + b"y"
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -04001004
1005 context = Context(TLSv1_METHOD)
1006 context.set_passwd_cb(passphraseCallback)
1007 # This shall succeed because the truncated result is the correct
1008 # passphrase.
1009 context.use_privatekey_file(pemFile)
1010
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -04001011 def test_set_info_callback(self):
1012 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001013 :py:obj:`Context.set_info_callback` accepts a callable which will be
1014 invoked when certain information about an SSL connection is available.
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -04001015 """
Rick Deanb1ccd562009-07-09 23:52:39 -05001016 (server, client) = socket_pair()
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -04001017
1018 clientSSL = Connection(Context(TLSv1_METHOD), client)
1019 clientSSL.set_connect_state()
1020
1021 called = []
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001022
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -04001023 def info(conn, where, ret):
1024 called.append((conn, where, ret))
1025 context = Context(TLSv1_METHOD)
1026 context.set_info_callback(info)
1027 context.use_certificate(
1028 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1029 context.use_privatekey(
1030 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1031
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -04001032 serverSSL = Connection(context, server)
1033 serverSSL.set_accept_state()
1034
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -05001035 handshake(clientSSL, serverSSL)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -04001036
Jean-Paul Calderone3835e522014-02-02 11:12:30 -05001037 # The callback must always be called with a Connection instance as the
1038 # first argument. It would probably be better to split this into
1039 # separate tests for client and server side info callbacks so we could
1040 # assert it is called with the right Connection instance. It would
1041 # also be good to assert *something* about `where` and `ret`.
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -05001042 notConnections = [
1043 conn for (conn, where, ret) in called
1044 if not isinstance(conn, Connection)]
1045 self.assertEqual(
1046 [], notConnections,
1047 "Some info callback arguments were not Connection instaces.")
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001048
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001049 def _load_verify_locations_test(self, *args):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001050 """
1051 Create a client context which will verify the peer certificate and call
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04001052 its :py:obj:`load_verify_locations` method with the given arguments.
1053 Then connect it to a server and ensure that the handshake succeeds.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001054 """
Rick Deanb1ccd562009-07-09 23:52:39 -05001055 (server, client) = socket_pair()
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001056
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001057 clientContext = Context(TLSv1_METHOD)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001058 clientContext.load_verify_locations(*args)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001059 # Require that the server certificate verify properly or the
1060 # connection will fail.
1061 clientContext.set_verify(
1062 VERIFY_PEER,
1063 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
1064
1065 clientSSL = Connection(clientContext, client)
1066 clientSSL.set_connect_state()
1067
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001068 serverContext = Context(TLSv1_METHOD)
1069 serverContext.use_certificate(
1070 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1071 serverContext.use_privatekey(
1072 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1073
1074 serverSSL = Connection(serverContext, server)
1075 serverSSL.set_accept_state()
1076
Jean-Paul Calderonef8742032010-09-25 00:00:32 -04001077 # Without load_verify_locations above, the handshake
1078 # will fail:
1079 # Error: [('SSL routines', 'SSL3_GET_SERVER_CERTIFICATE',
1080 # 'certificate verify failed')]
1081 handshake(clientSSL, serverSSL)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001082
1083 cert = clientSSL.get_peer_certificate()
Jean-Paul Calderone20131f52009-04-01 12:05:45 -04001084 self.assertEqual(cert.get_subject().CN, 'Testing Root CA')
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -04001085
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001086 def _load_verify_cafile(self, cafile):
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001087 """
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001088 Verify that if path to a file containing a certificate is passed to
1089 ``Context.load_verify_locations`` for the ``cafile`` parameter, that
1090 certificate is used as a trust root for the purposes of verifying
1091 connections created using that ``Context``.
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001092 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04001093 fObj = open(cafile, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04001094 fObj.write(cleartextCertificatePEM.decode('ascii'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001095 fObj.close()
1096
1097 self._load_verify_locations_test(cafile)
1098
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001099 def test_load_verify_bytes_cafile(self):
1100 """
1101 :py:obj:`Context.load_verify_locations` accepts a file name as a
1102 ``bytes`` instance and uses the certificates within for verification
1103 purposes.
1104 """
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001105 cafile = self.mktemp() + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001106 self._load_verify_cafile(cafile)
1107
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001108 def test_load_verify_unicode_cafile(self):
1109 """
1110 :py:obj:`Context.load_verify_locations` accepts a file name as a
1111 ``unicode`` instance and uses the certificates within for verification
1112 purposes.
1113 """
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001114 self._load_verify_cafile(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001115 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001116 )
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001117
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -04001118 def test_load_verify_invalid_file(self):
1119 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001120 :py:obj:`Context.load_verify_locations` raises :py:obj:`Error` when
1121 passed a non-existent cafile.
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -04001122 """
1123 clientContext = Context(TLSv1_METHOD)
1124 self.assertRaises(
1125 Error, clientContext.load_verify_locations, self.mktemp())
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001126
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001127 def _load_verify_directory_locations_capath(self, capath):
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001128 """
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001129 Verify that if path to a directory containing certificate files is
1130 passed to ``Context.load_verify_locations`` for the ``capath``
1131 parameter, those certificates are used as trust roots for the purposes
1132 of verifying connections created using that ``Context``.
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001133 """
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001134 makedirs(capath)
Jean-Paul Calderone24dfb332011-05-04 18:10:26 -04001135 # Hash values computed manually with c_rehash to avoid depending on
1136 # c_rehash in the test suite. One is from OpenSSL 0.9.8, the other
1137 # from OpenSSL 1.0.0.
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001138 for name in [b'c7adac82.0', b'c3705638.0']:
Jean-Paul Calderone05826732015-04-12 11:38:49 -04001139 cafile = join_bytes_or_unicode(capath, name)
1140 with open(cafile, 'w') as fObj:
1141 fObj.write(cleartextCertificatePEM.decode('ascii'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001142
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001143 self._load_verify_locations_test(None, capath)
1144
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001145 def test_load_verify_directory_bytes_capath(self):
1146 """
1147 :py:obj:`Context.load_verify_locations` accepts a directory name as a
1148 ``bytes`` instance and uses the certificates within for verification
1149 purposes.
1150 """
1151 self._load_verify_directory_locations_capath(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001152 self.mktemp() + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001153 )
1154
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001155 def test_load_verify_directory_unicode_capath(self):
1156 """
1157 :py:obj:`Context.load_verify_locations` accepts a directory name as a
1158 ``unicode`` instance and uses the certificates within for verification
1159 purposes.
1160 """
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001161 self._load_verify_directory_locations_capath(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001162 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001163 )
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001164
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001165 def test_load_verify_locations_wrong_args(self):
1166 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001167 :py:obj:`Context.load_verify_locations` raises :py:obj:`TypeError` if
1168 called with the wrong number of arguments or with non-:py:obj:`str`
1169 arguments.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001170 """
1171 context = Context(TLSv1_METHOD)
1172 self.assertRaises(TypeError, context.load_verify_locations)
1173 self.assertRaises(TypeError, context.load_verify_locations, object())
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001174 self.assertRaises(
1175 TypeError, context.load_verify_locations, object(), object()
1176 )
1177 self.assertRaises(
1178 TypeError, context.load_verify_locations, None, None, None
1179 )
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001180
Hynek Schlawack734d3022015-09-05 19:19:32 +02001181 @pytest.mark.skipif(
1182 platform == "win32",
1183 reason="set_default_verify_paths appears not to work on Windows. "
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -04001184 "See LP#404343 and LP#404344."
Hynek Schlawack734d3022015-09-05 19:19:32 +02001185 )
1186 def test_set_default_verify_paths(self):
1187 """
1188 :py:obj:`Context.set_default_verify_paths` causes the
1189 platform-specific CA certificate locations to be used for
1190 verification purposes.
1191 """
1192 # Testing this requires a server with a certificate signed by one
1193 # of the CAs in the platform CA location. Getting one of those
1194 # costs money. Fortunately (or unfortunately, depending on your
1195 # perspective), it's easy to think of a public server on the
1196 # internet which has such a certificate. Connecting to the network
1197 # in a unit test is bad, but it's the only way I can think of to
1198 # really test this. -exarkun
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001199
Hynek Schlawack734d3022015-09-05 19:19:32 +02001200 # Arg, verisign.com doesn't speak anything newer than TLS 1.0
Hynek Schlawackbf887932015-10-21 17:13:47 +02001201 context = Context(SSLv23_METHOD)
Hynek Schlawack734d3022015-09-05 19:19:32 +02001202 context.set_default_verify_paths()
1203 context.set_verify(
1204 VERIFY_PEER,
1205 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001206
Hynek Schlawack734d3022015-09-05 19:19:32 +02001207 client = socket()
Hynek Schlawackbf887932015-10-21 17:13:47 +02001208 client.connect(("encrypted.google.com", 443))
Hynek Schlawack734d3022015-09-05 19:19:32 +02001209 clientSSL = Connection(context, client)
1210 clientSSL.set_connect_state()
1211 clientSSL.do_handshake()
1212 clientSSL.send(b"GET / HTTP/1.0\r\n\r\n")
1213 self.assertTrue(clientSSL.recv(1024))
Jean-Paul Calderone9eadb962008-09-07 21:20:44 -04001214
1215 def test_set_default_verify_paths_signature(self):
1216 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001217 :py:obj:`Context.set_default_verify_paths` takes no arguments and
1218 raises :py:obj:`TypeError` if given any.
Jean-Paul Calderone9eadb962008-09-07 21:20:44 -04001219 """
1220 context = Context(TLSv1_METHOD)
1221 self.assertRaises(TypeError, context.set_default_verify_paths, None)
1222 self.assertRaises(TypeError, context.set_default_verify_paths, 1)
1223 self.assertRaises(TypeError, context.set_default_verify_paths, "")
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05001224
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001225 def test_add_extra_chain_cert_invalid_cert(self):
1226 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001227 :py:obj:`Context.add_extra_chain_cert` raises :py:obj:`TypeError` if
1228 called with other than one argument or if called with an object which
1229 is not an instance of :py:obj:`X509`.
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001230 """
1231 context = Context(TLSv1_METHOD)
1232 self.assertRaises(TypeError, context.add_extra_chain_cert)
1233 self.assertRaises(TypeError, context.add_extra_chain_cert, object())
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001234 self.assertRaises(
1235 TypeError, context.add_extra_chain_cert, object(), object()
1236 )
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001237
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001238 def _handshake_test(self, serverContext, clientContext):
1239 """
1240 Verify that a client and server created with the given contexts can
1241 successfully handshake and communicate.
1242 """
1243 serverSocket, clientSocket = socket_pair()
1244
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001245 server = Connection(serverContext, serverSocket)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001246 server.set_accept_state()
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001247
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001248 client = Connection(clientContext, clientSocket)
1249 client.set_connect_state()
1250
1251 # Make them talk to each other.
1252 # self._interactInMemory(client, server)
1253 for i in range(3):
1254 for s in [client, server]:
1255 try:
1256 s.do_handshake()
1257 except WantReadError:
1258 pass
1259
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001260 def test_set_verify_callback_connection_argument(self):
1261 """
1262 The first argument passed to the verify callback is the
1263 :py:class:`Connection` instance for which verification is taking place.
1264 """
1265 serverContext = Context(TLSv1_METHOD)
1266 serverContext.use_privatekey(
1267 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1268 serverContext.use_certificate(
1269 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1270 serverConnection = Connection(serverContext, None)
1271
1272 class VerifyCallback(object):
1273 def callback(self, connection, *args):
1274 self.connection = connection
1275 return 1
1276
1277 verify = VerifyCallback()
1278 clientContext = Context(TLSv1_METHOD)
1279 clientContext.set_verify(VERIFY_PEER, verify.callback)
1280 clientConnection = Connection(clientContext, None)
1281 clientConnection.set_connect_state()
1282
1283 self._handshakeInMemory(clientConnection, serverConnection)
1284
1285 self.assertIdentical(verify.connection, clientConnection)
1286
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001287 def test_set_verify_callback_exception(self):
1288 """
1289 If the verify callback passed to :py:obj:`Context.set_verify` raises an
1290 exception, verification fails and the exception is propagated to the
1291 caller of :py:obj:`Connection.do_handshake`.
1292 """
1293 serverContext = Context(TLSv1_METHOD)
1294 serverContext.use_privatekey(
1295 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1296 serverContext.use_certificate(
1297 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1298
1299 clientContext = Context(TLSv1_METHOD)
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001300
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001301 def verify_callback(*args):
1302 raise Exception("silly verify failure")
1303 clientContext.set_verify(VERIFY_PEER, verify_callback)
1304
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01001305 with pytest.raises(Exception) as exc:
1306 self._handshake_test(serverContext, clientContext)
1307
1308 self.assertEqual("silly verify failure", str(exc.value))
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001309
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001310 def test_add_extra_chain_cert(self):
1311 """
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001312 :py:obj:`Context.add_extra_chain_cert` accepts an :py:obj:`X509`
1313 instance to add to the certificate chain.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001314
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001315 See :py:obj:`_create_certificate_chain` for the details of the
1316 certificate chain tested.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001317
1318 The chain is tested by starting a server with scert and connecting
1319 to it with a client which trusts cacert and requires verification to
1320 succeed.
1321 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001322 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001323 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1324
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001325 # Dump the CA certificate to a file because that's the only way to load
1326 # it as a trusted CA in the client context.
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001327 for cert, name in [(cacert, 'ca.pem'),
1328 (icert, 'i.pem'),
1329 (scert, 's.pem')]:
Hynek Schlawacke90680f2015-04-16 15:09:27 -04001330 with open(join(self.tmpdir, name), 'w') as f:
1331 f.write(dump_certificate(FILETYPE_PEM, cert).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001332
Hynek Schlawack1902c012015-04-16 15:06:41 -04001333 for key, name in [(cakey, 'ca.key'),
1334 (ikey, 'i.key'),
1335 (skey, 's.key')]:
Hynek Schlawacke90680f2015-04-16 15:09:27 -04001336 with open(join(self.tmpdir, name), 'w') as f:
1337 f.write(dump_privatekey(FILETYPE_PEM, key).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001338
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001339 # Create the server context
1340 serverContext = Context(TLSv1_METHOD)
1341 serverContext.use_privatekey(skey)
1342 serverContext.use_certificate(scert)
Jean-Paul Calderone16cf03d2010-09-08 18:53:39 -04001343 # The client already has cacert, we only need to give them icert.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001344 serverContext.add_extra_chain_cert(icert)
1345
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001346 # Create the client
1347 clientContext = Context(TLSv1_METHOD)
1348 clientContext.set_verify(
1349 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001350 clientContext.load_verify_locations(join(self.tmpdir, "ca.pem"))
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001351
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001352 # Try it out.
1353 self._handshake_test(serverContext, clientContext)
1354
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001355 def _use_certificate_chain_file_test(self, certdir):
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001356 """
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001357 Verify that :py:obj:`Context.use_certificate_chain_file` reads a
1358 certificate chain from a specified file.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001359
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001360 The chain is tested by starting a server with scert and connecting to
1361 it with a client which trusts cacert and requires verification to
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001362 succeed.
1363 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001364 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001365 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1366
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001367 makedirs(certdir)
1368
Jean-Paul Calderone05826732015-04-12 11:38:49 -04001369 chainFile = join_bytes_or_unicode(certdir, "chain.pem")
1370 caFile = join_bytes_or_unicode(certdir, "ca.pem")
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001371
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001372 # Write out the chain file.
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001373 with open(chainFile, 'wb') as fObj:
1374 # Most specific to least general.
1375 fObj.write(dump_certificate(FILETYPE_PEM, scert))
1376 fObj.write(dump_certificate(FILETYPE_PEM, icert))
1377 fObj.write(dump_certificate(FILETYPE_PEM, cacert))
1378
1379 with open(caFile, 'w') as fObj:
1380 fObj.write(dump_certificate(FILETYPE_PEM, cacert).decode('ascii'))
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001381
1382 serverContext = Context(TLSv1_METHOD)
1383 serverContext.use_certificate_chain_file(chainFile)
1384 serverContext.use_privatekey(skey)
1385
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001386 clientContext = Context(TLSv1_METHOD)
1387 clientContext.set_verify(
1388 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001389 clientContext.load_verify_locations(caFile)
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001390
1391 self._handshake_test(serverContext, clientContext)
1392
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001393 def test_use_certificate_chain_file_bytes(self):
1394 """
1395 ``Context.use_certificate_chain_file`` accepts the name of a file (as
1396 an instance of ``bytes``) to specify additional certificates to use to
1397 construct and verify a trust chain.
1398 """
1399 self._use_certificate_chain_file_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001400 self.mktemp() + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001401 )
1402
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001403 def test_use_certificate_chain_file_unicode(self):
1404 """
1405 ``Context.use_certificate_chain_file`` accepts the name of a file (as
1406 an instance of ``unicode``) to specify additional certificates to use
1407 to construct and verify a trust chain.
1408 """
1409 self._use_certificate_chain_file_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001410 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001411 )
1412
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001413 def test_use_certificate_chain_file_wrong_args(self):
1414 """
1415 :py:obj:`Context.use_certificate_chain_file` raises :py:obj:`TypeError`
1416 if passed zero or more than one argument or when passed a non-byte
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001417 string single argument. It also raises :py:obj:`OpenSSL.SSL.Error`
1418 when passed a bad chain file name (for example, the name of a file
1419 which does not exist).
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001420 """
1421 context = Context(TLSv1_METHOD)
1422 self.assertRaises(TypeError, context.use_certificate_chain_file)
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001423 self.assertRaises(
1424 TypeError, context.use_certificate_chain_file, object()
1425 )
1426 self.assertRaises(
1427 TypeError, context.use_certificate_chain_file, b"foo", object()
1428 )
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001429
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001430 self.assertRaises(
1431 Error, context.use_certificate_chain_file, self.mktemp()
1432 )
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001433
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001434 def test_get_verify_mode_wrong_args(self):
1435 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001436 :py:obj:`Context.get_verify_mode` raises :py:obj:`TypeError` if called
1437 with any arguments.
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001438 """
1439 context = Context(TLSv1_METHOD)
1440 self.assertRaises(TypeError, context.get_verify_mode, None)
1441
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001442 def test_set_verify_mode(self):
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001443 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001444 :py:obj:`Context.get_verify_mode` returns the verify mode flags
1445 previously passed to :py:obj:`Context.set_verify`.
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001446 """
1447 context = Context(TLSv1_METHOD)
1448 self.assertEquals(context.get_verify_mode(), 0)
1449 context.set_verify(
1450 VERIFY_PEER | VERIFY_CLIENT_ONCE, lambda *args: None)
1451 self.assertEquals(
1452 context.get_verify_mode(), VERIFY_PEER | VERIFY_CLIENT_ONCE)
1453
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001454 @skip_if_py3
1455 def test_set_verify_mode_long(self):
1456 """
1457 On Python 2 :py:obj:`Context.set_verify_mode` accepts values of
1458 type :py:obj:`long` as well as :py:obj:`int`.
1459 """
1460 context = Context(TLSv1_METHOD)
1461 self.assertEquals(context.get_verify_mode(), 0)
1462 context.set_verify(
Hynek Schlawackb4ceed32015-09-05 20:55:19 +02001463 long(VERIFY_PEER | VERIFY_CLIENT_ONCE), lambda *args: None
1464 ) # pragma: nocover
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001465 self.assertEquals(
1466 context.get_verify_mode(), VERIFY_PEER | VERIFY_CLIENT_ONCE)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001467
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001468 def test_load_tmp_dh_wrong_args(self):
1469 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001470 :py:obj:`Context.load_tmp_dh` raises :py:obj:`TypeError` if called with
1471 the wrong number of arguments or with a non-:py:obj:`str` argument.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001472 """
1473 context = Context(TLSv1_METHOD)
1474 self.assertRaises(TypeError, context.load_tmp_dh)
1475 self.assertRaises(TypeError, context.load_tmp_dh, "foo", None)
1476 self.assertRaises(TypeError, context.load_tmp_dh, object())
1477
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001478 def test_load_tmp_dh_missing_file(self):
1479 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001480 :py:obj:`Context.load_tmp_dh` raises :py:obj:`OpenSSL.SSL.Error` if the
1481 specified file does not exist.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001482 """
1483 context = Context(TLSv1_METHOD)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001484 self.assertRaises(Error, context.load_tmp_dh, b"hello")
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001485
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001486 def _load_tmp_dh_test(self, dhfilename):
Jean-Paul Calderone4e0c43f2015-04-13 10:15:17 -04001487 """
1488 Verify that calling ``Context.load_tmp_dh`` with the given filename
1489 does not raise an exception.
1490 """
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001491 context = Context(TLSv1_METHOD)
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001492 with open(dhfilename, "w") as dhfile:
1493 dhfile.write(dhparam)
1494
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001495 context.load_tmp_dh(dhfilename)
1496 # XXX What should I assert here? -exarkun
1497
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001498 def test_load_tmp_dh_bytes(self):
1499 """
1500 :py:obj:`Context.load_tmp_dh` loads Diffie-Hellman parameters from the
1501 specified file (given as ``bytes``).
1502 """
1503 self._load_tmp_dh_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001504 self.mktemp() + NON_ASCII.encode(getfilesystemencoding()),
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001505 )
1506
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001507 def test_load_tmp_dh_unicode(self):
1508 """
1509 :py:obj:`Context.load_tmp_dh` loads Diffie-Hellman parameters from the
1510 specified file (given as ``unicode``).
1511 """
1512 self._load_tmp_dh_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001513 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII,
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001514 )
1515
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001516 def test_set_tmp_ecdh(self):
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001517 """
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001518 :py:obj:`Context.set_tmp_ecdh` sets the elliptic curve for
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001519 Diffie-Hellman to the specified curve.
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001520 """
1521 context = Context(TLSv1_METHOD)
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001522 for curve in get_elliptic_curves():
Hynek Schlawacka07fa8c2015-10-17 10:15:28 +02001523 if curve.name.startswith(u"Oakley-"):
Hynek Schlawack7408aff2015-10-17 09:51:16 +02001524 # Setting Oakley-EC2N-4 and Oakley-EC2N-3 adds
1525 # ('bignum routines', 'BN_mod_inverse', 'no inverse') to the
1526 # error queue on OpenSSL 1.0.2.
1527 continue
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001528 # The only easily "assertable" thing is that it does not raise an
1529 # exception.
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001530 context.set_tmp_ecdh(curve)
Alex Gaynor12dc0842014-01-17 12:51:31 -06001531
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001532 def test_set_session_cache_mode_wrong_args(self):
1533 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001534 :py:obj:`Context.set_session_cache_mode` raises :py:obj:`TypeError` if
1535 called with other than one integer argument.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001536 """
1537 context = Context(TLSv1_METHOD)
1538 self.assertRaises(TypeError, context.set_session_cache_mode)
1539 self.assertRaises(TypeError, context.set_session_cache_mode, object())
1540
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001541 def test_get_session_cache_mode_wrong_args(self):
1542 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001543 :py:obj:`Context.get_session_cache_mode` raises :py:obj:`TypeError` if
1544 called with any arguments.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001545 """
1546 context = Context(TLSv1_METHOD)
1547 self.assertRaises(TypeError, context.get_session_cache_mode, 1)
1548
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001549 def test_session_cache_mode(self):
1550 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001551 :py:obj:`Context.set_session_cache_mode` specifies how sessions are
1552 cached. The setting can be retrieved via
1553 :py:obj:`Context.get_session_cache_mode`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001554 """
1555 context = Context(TLSv1_METHOD)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001556 context.set_session_cache_mode(SESS_CACHE_OFF)
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001557 off = context.set_session_cache_mode(SESS_CACHE_BOTH)
1558 self.assertEqual(SESS_CACHE_OFF, off)
1559 self.assertEqual(SESS_CACHE_BOTH, context.get_session_cache_mode())
1560
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001561 @skip_if_py3
1562 def test_session_cache_mode_long(self):
1563 """
1564 On Python 2 :py:obj:`Context.set_session_cache_mode` accepts values
1565 of type :py:obj:`long` as well as :py:obj:`int`.
1566 """
1567 context = Context(TLSv1_METHOD)
1568 context.set_session_cache_mode(long(SESS_CACHE_BOTH))
1569 self.assertEqual(
1570 SESS_CACHE_BOTH, context.get_session_cache_mode())
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001571
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001572 def test_get_cert_store(self):
1573 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001574 :py:obj:`Context.get_cert_store` returns a :py:obj:`X509Store`
1575 instance.
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001576 """
1577 context = Context(TLSv1_METHOD)
1578 store = context.get_cert_store()
1579 self.assertIsInstance(store, X509Store)
1580
1581
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001582class ServerNameCallbackTests(TestCase, _LoopbackMixin):
1583 """
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001584 Tests for :py:obj:`Context.set_tlsext_servername_callback` and its
1585 interaction with :py:obj:`Connection`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001586 """
1587 def test_wrong_args(self):
1588 """
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001589 :py:obj:`Context.set_tlsext_servername_callback` raises
1590 :py:obj:`TypeError` if called with other than one argument.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001591 """
1592 context = Context(TLSv1_METHOD)
1593 self.assertRaises(TypeError, context.set_tlsext_servername_callback)
1594 self.assertRaises(
1595 TypeError, context.set_tlsext_servername_callback, 1, 2)
1596
1597 def test_old_callback_forgotten(self):
1598 """
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001599 If :py:obj:`Context.set_tlsext_servername_callback` is used to specify
1600 a new callback, the one it replaces is dereferenced.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001601 """
1602 def callback(connection):
1603 pass
1604
1605 def replacement(connection):
1606 pass
1607
1608 context = Context(TLSv1_METHOD)
1609 context.set_tlsext_servername_callback(callback)
1610
1611 tracker = ref(callback)
1612 del callback
1613
1614 context.set_tlsext_servername_callback(replacement)
Jean-Paul Calderoned4033eb2014-01-11 08:21:46 -05001615
1616 # One run of the garbage collector happens to work on CPython. PyPy
1617 # doesn't collect the underlying object until a second run for whatever
1618 # reason. That's fine, it still demonstrates our code has properly
1619 # dropped the reference.
1620 collect()
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001621 collect()
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001622
1623 callback = tracker()
1624 if callback is not None:
1625 referrers = get_referrers(callback)
Jean-Paul Calderone7de39562014-01-11 08:17:59 -05001626 if len(referrers) > 1:
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001627 self.fail("Some references remain: %r" % (referrers,))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001628
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001629 def test_no_servername(self):
1630 """
1631 When a client specifies no server name, the callback passed to
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001632 :py:obj:`Context.set_tlsext_servername_callback` is invoked and the
1633 result of :py:obj:`Connection.get_servername` is :py:obj:`None`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001634 """
1635 args = []
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001636
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001637 def servername(conn):
1638 args.append((conn, conn.get_servername()))
1639 context = Context(TLSv1_METHOD)
1640 context.set_tlsext_servername_callback(servername)
1641
1642 # Lose our reference to it. The Context is responsible for keeping it
1643 # alive now.
1644 del servername
1645 collect()
1646
1647 # Necessary to actually accept the connection
1648 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001649 context.use_certificate(
1650 load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001651
1652 # Do a little connection to trigger the logic
1653 server = Connection(context, None)
1654 server.set_accept_state()
1655
1656 client = Connection(Context(TLSv1_METHOD), None)
1657 client.set_connect_state()
1658
1659 self._interactInMemory(server, client)
1660
1661 self.assertEqual([(server, None)], args)
1662
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001663 def test_servername(self):
1664 """
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001665 When a client specifies a server name in its hello message, the
1666 callback passed to :py:obj:`Contexts.set_tlsext_servername_callback` is
1667 invoked and the result of :py:obj:`Connection.get_servername` is that
1668 server name.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001669 """
1670 args = []
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001671
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001672 def servername(conn):
1673 args.append((conn, conn.get_servername()))
1674 context = Context(TLSv1_METHOD)
1675 context.set_tlsext_servername_callback(servername)
1676
1677 # Necessary to actually accept the connection
1678 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001679 context.use_certificate(
1680 load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001681
1682 # Do a little connection to trigger the logic
1683 server = Connection(context, None)
1684 server.set_accept_state()
1685
1686 client = Connection(Context(TLSv1_METHOD), None)
1687 client.set_connect_state()
Alex Gaynore7f51982016-09-11 11:48:14 -04001688 client.set_tlsext_host_name(b"foo1.example.com")
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001689
1690 self._interactInMemory(server, client)
1691
Alex Gaynore7f51982016-09-11 11:48:14 -04001692 self.assertEqual([(server, b"foo1.example.com")], args)
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001693
1694
Cory Benfield84a121e2014-03-31 20:30:25 +01001695class NextProtoNegotiationTests(TestCase, _LoopbackMixin):
1696 """
1697 Test for Next Protocol Negotiation in PyOpenSSL.
1698 """
Cory Benfieldba1820d2015-04-13 17:39:12 -04001699 if _lib.Cryptography_HAS_NEXTPROTONEG:
1700 def test_npn_success(self):
1701 """
1702 Tests that clients and servers that agree on the negotiated next
1703 protocol can correct establish a connection, and that the agreed
1704 protocol is reported by the connections.
1705 """
1706 advertise_args = []
1707 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001708
Cory Benfieldba1820d2015-04-13 17:39:12 -04001709 def advertise(conn):
1710 advertise_args.append((conn,))
1711 return [b'http/1.1', b'spdy/2']
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001712
Cory Benfieldba1820d2015-04-13 17:39:12 -04001713 def select(conn, options):
1714 select_args.append((conn, options))
1715 return b'spdy/2'
Cory Benfield84a121e2014-03-31 20:30:25 +01001716
Cory Benfieldba1820d2015-04-13 17:39:12 -04001717 server_context = Context(TLSv1_METHOD)
1718 server_context.set_npn_advertise_callback(advertise)
Cory Benfield84a121e2014-03-31 20:30:25 +01001719
Cory Benfieldba1820d2015-04-13 17:39:12 -04001720 client_context = Context(TLSv1_METHOD)
1721 client_context.set_npn_select_callback(select)
Cory Benfield84a121e2014-03-31 20:30:25 +01001722
Cory Benfieldba1820d2015-04-13 17:39:12 -04001723 # Necessary to actually accept the connection
1724 server_context.use_privatekey(
1725 load_privatekey(FILETYPE_PEM, server_key_pem))
1726 server_context.use_certificate(
1727 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield84a121e2014-03-31 20:30:25 +01001728
Cory Benfieldba1820d2015-04-13 17:39:12 -04001729 # Do a little connection to trigger the logic
1730 server = Connection(server_context, None)
1731 server.set_accept_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001732
Cory Benfieldba1820d2015-04-13 17:39:12 -04001733 client = Connection(client_context, None)
1734 client.set_connect_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001735
Cory Benfieldba1820d2015-04-13 17:39:12 -04001736 self._interactInMemory(server, client)
Cory Benfield84a121e2014-03-31 20:30:25 +01001737
Cory Benfieldba1820d2015-04-13 17:39:12 -04001738 self.assertEqual([(server,)], advertise_args)
1739 self.assertEqual([(client, [b'http/1.1', b'spdy/2'])], select_args)
Cory Benfield84a121e2014-03-31 20:30:25 +01001740
Cory Benfieldba1820d2015-04-13 17:39:12 -04001741 self.assertEqual(server.get_next_proto_negotiated(), b'spdy/2')
1742 self.assertEqual(client.get_next_proto_negotiated(), b'spdy/2')
Cory Benfield84a121e2014-03-31 20:30:25 +01001743
Cory Benfieldba1820d2015-04-13 17:39:12 -04001744 def test_npn_client_fail(self):
1745 """
1746 Tests that when clients and servers cannot agree on what protocol
1747 to use next that the TLS connection does not get established.
1748 """
1749 advertise_args = []
1750 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001751
Cory Benfieldba1820d2015-04-13 17:39:12 -04001752 def advertise(conn):
1753 advertise_args.append((conn,))
1754 return [b'http/1.1', b'spdy/2']
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001755
Cory Benfieldba1820d2015-04-13 17:39:12 -04001756 def select(conn, options):
1757 select_args.append((conn, options))
1758 return b''
Cory Benfield84a121e2014-03-31 20:30:25 +01001759
Cory Benfieldba1820d2015-04-13 17:39:12 -04001760 server_context = Context(TLSv1_METHOD)
1761 server_context.set_npn_advertise_callback(advertise)
Cory Benfield84a121e2014-03-31 20:30:25 +01001762
Cory Benfieldba1820d2015-04-13 17:39:12 -04001763 client_context = Context(TLSv1_METHOD)
1764 client_context.set_npn_select_callback(select)
Cory Benfield84a121e2014-03-31 20:30:25 +01001765
Cory Benfieldba1820d2015-04-13 17:39:12 -04001766 # Necessary to actually accept the connection
1767 server_context.use_privatekey(
1768 load_privatekey(FILETYPE_PEM, server_key_pem))
1769 server_context.use_certificate(
1770 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield84a121e2014-03-31 20:30:25 +01001771
Cory Benfieldba1820d2015-04-13 17:39:12 -04001772 # Do a little connection to trigger the logic
1773 server = Connection(server_context, None)
1774 server.set_accept_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001775
Cory Benfieldba1820d2015-04-13 17:39:12 -04001776 client = Connection(client_context, None)
1777 client.set_connect_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001778
Cory Benfieldba1820d2015-04-13 17:39:12 -04001779 # If the client doesn't return anything, the connection will fail.
1780 self.assertRaises(Error, self._interactInMemory, server, client)
Cory Benfield84a121e2014-03-31 20:30:25 +01001781
Cory Benfieldba1820d2015-04-13 17:39:12 -04001782 self.assertEqual([(server,)], advertise_args)
1783 self.assertEqual([(client, [b'http/1.1', b'spdy/2'])], select_args)
Cory Benfield84a121e2014-03-31 20:30:25 +01001784
Cory Benfieldba1820d2015-04-13 17:39:12 -04001785 def test_npn_select_error(self):
1786 """
1787 Test that we can handle exceptions in the select callback. If
1788 select fails it should be fatal to the connection.
1789 """
1790 advertise_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001791
Cory Benfieldba1820d2015-04-13 17:39:12 -04001792 def advertise(conn):
1793 advertise_args.append((conn,))
1794 return [b'http/1.1', b'spdy/2']
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001795
Cory Benfieldba1820d2015-04-13 17:39:12 -04001796 def select(conn, options):
1797 raise TypeError
Cory Benfield0ea76e72015-03-22 09:05:28 +00001798
Cory Benfieldba1820d2015-04-13 17:39:12 -04001799 server_context = Context(TLSv1_METHOD)
1800 server_context.set_npn_advertise_callback(advertise)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001801
Cory Benfieldba1820d2015-04-13 17:39:12 -04001802 client_context = Context(TLSv1_METHOD)
1803 client_context.set_npn_select_callback(select)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001804
Cory Benfieldba1820d2015-04-13 17:39:12 -04001805 # Necessary to actually accept the connection
1806 server_context.use_privatekey(
1807 load_privatekey(FILETYPE_PEM, server_key_pem))
1808 server_context.use_certificate(
1809 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield0ea76e72015-03-22 09:05:28 +00001810
Cory Benfieldba1820d2015-04-13 17:39:12 -04001811 # Do a little connection to trigger the logic
1812 server = Connection(server_context, None)
1813 server.set_accept_state()
Cory Benfield0ea76e72015-03-22 09:05:28 +00001814
Cory Benfieldba1820d2015-04-13 17:39:12 -04001815 client = Connection(client_context, None)
1816 client.set_connect_state()
Cory Benfield0ea76e72015-03-22 09:05:28 +00001817
Cory Benfieldba1820d2015-04-13 17:39:12 -04001818 # If the callback throws an exception it should be raised here.
1819 self.assertRaises(
1820 TypeError, self._interactInMemory, server, client
1821 )
1822 self.assertEqual([(server,)], advertise_args)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001823
Cory Benfieldba1820d2015-04-13 17:39:12 -04001824 def test_npn_advertise_error(self):
1825 """
1826 Test that we can handle exceptions in the advertise callback. If
1827 advertise fails no NPN is advertised to the client.
1828 """
1829 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001830
Cory Benfieldba1820d2015-04-13 17:39:12 -04001831 def advertise(conn):
1832 raise TypeError
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001833
Hynek Schlawackb4ceed32015-09-05 20:55:19 +02001834 def select(conn, options): # pragma: nocover
1835 """
1836 Assert later that no args are actually appended.
1837 """
Cory Benfieldba1820d2015-04-13 17:39:12 -04001838 select_args.append((conn, options))
1839 return b''
Cory Benfield0ea76e72015-03-22 09:05:28 +00001840
Cory Benfieldba1820d2015-04-13 17:39:12 -04001841 server_context = Context(TLSv1_METHOD)
1842 server_context.set_npn_advertise_callback(advertise)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001843
Cory Benfieldba1820d2015-04-13 17:39:12 -04001844 client_context = Context(TLSv1_METHOD)
1845 client_context.set_npn_select_callback(select)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001846
Cory Benfieldba1820d2015-04-13 17:39:12 -04001847 # Necessary to actually accept the connection
1848 server_context.use_privatekey(
1849 load_privatekey(FILETYPE_PEM, server_key_pem))
1850 server_context.use_certificate(
1851 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield0ea76e72015-03-22 09:05:28 +00001852
Cory Benfieldba1820d2015-04-13 17:39:12 -04001853 # Do a little connection to trigger the logic
1854 server = Connection(server_context, None)
1855 server.set_accept_state()
Cory Benfield0ea76e72015-03-22 09:05:28 +00001856
Cory Benfieldba1820d2015-04-13 17:39:12 -04001857 client = Connection(client_context, None)
1858 client.set_connect_state()
Cory Benfield0ea76e72015-03-22 09:05:28 +00001859
Cory Benfieldba1820d2015-04-13 17:39:12 -04001860 # If the client doesn't return anything, the connection will fail.
1861 self.assertRaises(
1862 TypeError, self._interactInMemory, server, client
1863 )
1864 self.assertEqual([], select_args)
1865
1866 else:
1867 # No NPN.
1868 def test_npn_not_implemented(self):
1869 # Test the context methods first.
1870 context = Context(TLSv1_METHOD)
1871 fail_methods = [
1872 context.set_npn_advertise_callback,
1873 context.set_npn_select_callback,
1874 ]
1875 for method in fail_methods:
1876 self.assertRaises(
1877 NotImplementedError, method, None
1878 )
1879
1880 # Now test a connection.
1881 conn = Connection(context)
1882 fail_methods = [
1883 conn.get_next_proto_negotiated,
1884 ]
1885 for method in fail_methods:
1886 self.assertRaises(NotImplementedError, method)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001887
1888
Cory Benfield12eae892014-06-07 15:42:56 +01001889class ApplicationLayerProtoNegotiationTests(TestCase, _LoopbackMixin):
1890 """
1891 Tests for ALPN in PyOpenSSL.
1892 """
Cory Benfielde46fa842015-04-13 16:50:49 -04001893 # Skip tests on versions that don't support ALPN.
1894 if _lib.Cryptography_HAS_ALPN:
Cory Benfield12eae892014-06-07 15:42:56 +01001895
Cory Benfielde46fa842015-04-13 16:50:49 -04001896 def test_alpn_success(self):
1897 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04001898 Clients and servers that agree on the negotiated ALPN protocol can
1899 correct establish a connection, and the agreed protocol is reported
1900 by the connections.
Cory Benfielde46fa842015-04-13 16:50:49 -04001901 """
1902 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001903
Cory Benfielde46fa842015-04-13 16:50:49 -04001904 def select(conn, options):
1905 select_args.append((conn, options))
1906 return b'spdy/2'
Cory Benfield12eae892014-06-07 15:42:56 +01001907
Cory Benfielde46fa842015-04-13 16:50:49 -04001908 client_context = Context(TLSv1_METHOD)
1909 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfield12eae892014-06-07 15:42:56 +01001910
Cory Benfielde46fa842015-04-13 16:50:49 -04001911 server_context = Context(TLSv1_METHOD)
1912 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01001913
Cory Benfielde46fa842015-04-13 16:50:49 -04001914 # Necessary to actually accept the connection
1915 server_context.use_privatekey(
1916 load_privatekey(FILETYPE_PEM, server_key_pem))
1917 server_context.use_certificate(
1918 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield12eae892014-06-07 15:42:56 +01001919
Cory Benfielde46fa842015-04-13 16:50:49 -04001920 # Do a little connection to trigger the logic
1921 server = Connection(server_context, None)
1922 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001923
Cory Benfielde46fa842015-04-13 16:50:49 -04001924 client = Connection(client_context, None)
1925 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001926
Cory Benfielde46fa842015-04-13 16:50:49 -04001927 self._interactInMemory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001928
Cory Benfielde46fa842015-04-13 16:50:49 -04001929 self.assertEqual([(server, [b'http/1.1', b'spdy/2'])], select_args)
1930
1931 self.assertEqual(server.get_alpn_proto_negotiated(), b'spdy/2')
1932 self.assertEqual(client.get_alpn_proto_negotiated(), b'spdy/2')
Cory Benfield12eae892014-06-07 15:42:56 +01001933
Cory Benfielde46fa842015-04-13 16:50:49 -04001934 def test_alpn_set_on_connection(self):
1935 """
1936 The same as test_alpn_success, but setting the ALPN protocols on
1937 the connection rather than the context.
1938 """
1939 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001940
Cory Benfielde46fa842015-04-13 16:50:49 -04001941 def select(conn, options):
1942 select_args.append((conn, options))
1943 return b'spdy/2'
Cory Benfield12eae892014-06-07 15:42:56 +01001944
Cory Benfielde46fa842015-04-13 16:50:49 -04001945 # Setup the client context but don't set any ALPN protocols.
1946 client_context = Context(TLSv1_METHOD)
Cory Benfield12eae892014-06-07 15:42:56 +01001947
Cory Benfielde46fa842015-04-13 16:50:49 -04001948 server_context = Context(TLSv1_METHOD)
1949 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01001950
Cory Benfielde46fa842015-04-13 16:50:49 -04001951 # Necessary to actually accept the connection
1952 server_context.use_privatekey(
1953 load_privatekey(FILETYPE_PEM, server_key_pem))
1954 server_context.use_certificate(
1955 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield12eae892014-06-07 15:42:56 +01001956
Cory Benfielde46fa842015-04-13 16:50:49 -04001957 # Do a little connection to trigger the logic
1958 server = Connection(server_context, None)
1959 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001960
Cory Benfielde46fa842015-04-13 16:50:49 -04001961 # Set the ALPN protocols on the client connection.
1962 client = Connection(client_context, None)
1963 client.set_alpn_protos([b'http/1.1', b'spdy/2'])
1964 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001965
Cory Benfielde46fa842015-04-13 16:50:49 -04001966 self._interactInMemory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001967
Cory Benfielde46fa842015-04-13 16:50:49 -04001968 self.assertEqual([(server, [b'http/1.1', b'spdy/2'])], select_args)
Cory Benfield12eae892014-06-07 15:42:56 +01001969
Cory Benfielde46fa842015-04-13 16:50:49 -04001970 self.assertEqual(server.get_alpn_proto_negotiated(), b'spdy/2')
1971 self.assertEqual(client.get_alpn_proto_negotiated(), b'spdy/2')
Cory Benfield12eae892014-06-07 15:42:56 +01001972
Cory Benfielde46fa842015-04-13 16:50:49 -04001973 def test_alpn_server_fail(self):
1974 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04001975 When clients and servers cannot agree on what protocol to use next
1976 the TLS connection does not get established.
Cory Benfielde46fa842015-04-13 16:50:49 -04001977 """
1978 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001979
Cory Benfielde46fa842015-04-13 16:50:49 -04001980 def select(conn, options):
1981 select_args.append((conn, options))
1982 return b''
Cory Benfield12eae892014-06-07 15:42:56 +01001983
Cory Benfielde46fa842015-04-13 16:50:49 -04001984 client_context = Context(TLSv1_METHOD)
1985 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfield12eae892014-06-07 15:42:56 +01001986
Cory Benfielde46fa842015-04-13 16:50:49 -04001987 server_context = Context(TLSv1_METHOD)
1988 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01001989
Cory Benfielde46fa842015-04-13 16:50:49 -04001990 # Necessary to actually accept the connection
1991 server_context.use_privatekey(
1992 load_privatekey(FILETYPE_PEM, server_key_pem))
1993 server_context.use_certificate(
1994 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield12eae892014-06-07 15:42:56 +01001995
Cory Benfielde46fa842015-04-13 16:50:49 -04001996 # Do a little connection to trigger the logic
1997 server = Connection(server_context, None)
1998 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001999
Cory Benfielde46fa842015-04-13 16:50:49 -04002000 client = Connection(client_context, None)
2001 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01002002
Cory Benfielde46fa842015-04-13 16:50:49 -04002003 # If the client doesn't return anything, the connection will fail.
2004 self.assertRaises(Error, self._interactInMemory, server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01002005
Cory Benfielde46fa842015-04-13 16:50:49 -04002006 self.assertEqual([(server, [b'http/1.1', b'spdy/2'])], select_args)
Cory Benfield12eae892014-06-07 15:42:56 +01002007
Cory Benfielde46fa842015-04-13 16:50:49 -04002008 def test_alpn_no_server(self):
2009 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04002010 When clients and servers cannot agree on what protocol to use next
2011 because the server doesn't offer ALPN, no protocol is negotiated.
Cory Benfielde46fa842015-04-13 16:50:49 -04002012 """
2013 client_context = Context(TLSv1_METHOD)
2014 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfielde3d57152015-04-11 17:57:35 -04002015
Cory Benfielde46fa842015-04-13 16:50:49 -04002016 server_context = Context(TLSv1_METHOD)
Cory Benfielde3d57152015-04-11 17:57:35 -04002017
Cory Benfielde46fa842015-04-13 16:50:49 -04002018 # Necessary to actually accept the connection
2019 server_context.use_privatekey(
2020 load_privatekey(FILETYPE_PEM, server_key_pem))
2021 server_context.use_certificate(
2022 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfielde3d57152015-04-11 17:57:35 -04002023
Cory Benfielde46fa842015-04-13 16:50:49 -04002024 # Do a little connection to trigger the logic
2025 server = Connection(server_context, None)
2026 server.set_accept_state()
Cory Benfielde3d57152015-04-11 17:57:35 -04002027
Cory Benfielde46fa842015-04-13 16:50:49 -04002028 client = Connection(client_context, None)
2029 client.set_connect_state()
Cory Benfielde3d57152015-04-11 17:57:35 -04002030
Cory Benfielde46fa842015-04-13 16:50:49 -04002031 # Do the dance.
2032 self._interactInMemory(server, client)
Cory Benfielde3d57152015-04-11 17:57:35 -04002033
Cory Benfielde46fa842015-04-13 16:50:49 -04002034 self.assertEqual(client.get_alpn_proto_negotiated(), b'')
Cory Benfielde3d57152015-04-11 17:57:35 -04002035
Cory Benfielde46fa842015-04-13 16:50:49 -04002036 def test_alpn_callback_exception(self):
2037 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04002038 We can handle exceptions in the ALPN select callback.
Cory Benfielde46fa842015-04-13 16:50:49 -04002039 """
2040 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002041
Cory Benfielde46fa842015-04-13 16:50:49 -04002042 def select(conn, options):
2043 select_args.append((conn, options))
Cory Benfieldef401452015-04-13 18:17:36 -04002044 raise TypeError()
Cory Benfieldf1177e72015-04-12 09:11:49 -04002045
Cory Benfielde46fa842015-04-13 16:50:49 -04002046 client_context = Context(TLSv1_METHOD)
2047 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfieldf1177e72015-04-12 09:11:49 -04002048
Cory Benfielde46fa842015-04-13 16:50:49 -04002049 server_context = Context(TLSv1_METHOD)
2050 server_context.set_alpn_select_callback(select)
Cory Benfieldf1177e72015-04-12 09:11:49 -04002051
Cory Benfielde46fa842015-04-13 16:50:49 -04002052 # Necessary to actually accept the connection
2053 server_context.use_privatekey(
2054 load_privatekey(FILETYPE_PEM, server_key_pem))
2055 server_context.use_certificate(
2056 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfieldf1177e72015-04-12 09:11:49 -04002057
Cory Benfielde46fa842015-04-13 16:50:49 -04002058 # Do a little connection to trigger the logic
2059 server = Connection(server_context, None)
2060 server.set_accept_state()
Cory Benfieldf1177e72015-04-12 09:11:49 -04002061
Cory Benfielde46fa842015-04-13 16:50:49 -04002062 client = Connection(client_context, None)
2063 client.set_connect_state()
Cory Benfieldf1177e72015-04-12 09:11:49 -04002064
Cory Benfielde46fa842015-04-13 16:50:49 -04002065 self.assertRaises(
2066 TypeError, self._interactInMemory, server, client
2067 )
2068 self.assertEqual([(server, [b'http/1.1', b'spdy/2'])], select_args)
Cory Benfieldf1177e72015-04-12 09:11:49 -04002069
Cory Benfield0f7b04c2015-04-13 17:51:12 -04002070 else:
2071 # No ALPN.
2072 def test_alpn_not_implemented(self):
Cory Benfieldef401452015-04-13 18:17:36 -04002073 """
2074 If ALPN is not in OpenSSL, we should raise NotImplementedError.
2075 """
Cory Benfield0f7b04c2015-04-13 17:51:12 -04002076 # Test the context methods first.
2077 context = Context(TLSv1_METHOD)
Cory Benfield307e9e62015-04-13 18:21:12 -04002078 self.assertRaises(
2079 NotImplementedError, context.set_alpn_protos, None
2080 )
2081 self.assertRaises(
2082 NotImplementedError, context.set_alpn_select_callback, None
2083 )
Cory Benfield0f7b04c2015-04-13 17:51:12 -04002084
2085 # Now test a connection.
2086 conn = Connection(context)
Cory Benfield307e9e62015-04-13 18:21:12 -04002087 self.assertRaises(
Alex Gaynor68417232015-09-04 07:56:29 -04002088 NotImplementedError, conn.set_alpn_protos, None
Cory Benfield307e9e62015-04-13 18:21:12 -04002089 )
Cory Benfield0f7b04c2015-04-13 17:51:12 -04002090
Cory Benfieldf1177e72015-04-12 09:11:49 -04002091
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05002092class SessionTests(TestCase):
2093 """
2094 Unit tests for :py:obj:`OpenSSL.SSL.Session`.
2095 """
2096 def test_construction(self):
2097 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002098 :py:class:`Session` can be constructed with no arguments, creating
2099 a new instance of that type.
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05002100 """
2101 new_session = Session()
2102 self.assertTrue(isinstance(new_session, Session))
2103
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05002104 def test_construction_wrong_args(self):
2105 """
2106 If any arguments are passed to :py:class:`Session`, :py:obj:`TypeError`
2107 is raised.
2108 """
2109 self.assertRaises(TypeError, Session, 123)
2110 self.assertRaises(TypeError, Session, "hello")
2111 self.assertRaises(TypeError, Session, object())
2112
2113
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002114class ConnectionTests(TestCase, _LoopbackMixin):
Rick Deane15b1472009-07-09 15:53:42 -05002115 """
Hynek Schlawackaa861212016-03-13 13:53:48 +01002116 Unit tests for :class:`OpenSSL.SSL.Connection`.
Rick Deane15b1472009-07-09 15:53:42 -05002117 """
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04002118 # XXX get_peer_certificate -> None
2119 # XXX sock_shutdown
2120 # XXX master_key -> TypeError
2121 # XXX server_random -> TypeError
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04002122 # XXX connect -> TypeError
2123 # XXX connect_ex -> TypeError
2124 # XXX set_connect_state -> TypeError
2125 # XXX set_accept_state -> TypeError
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04002126 # XXX do_handshake -> TypeError
2127 # XXX bio_read -> TypeError
2128 # XXX recv -> TypeError
2129 # XXX send -> TypeError
2130 # XXX bio_write -> TypeError
2131
Rick Deane15b1472009-07-09 15:53:42 -05002132 def test_type(self):
2133 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002134 :py:obj:`Connection` and :py:obj:`ConnectionType` refer to the same
2135 type object and can be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -05002136 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002137 self.assertIdentical(Connection, ConnectionType)
Rick Deane15b1472009-07-09 15:53:42 -05002138 ctx = Context(TLSv1_METHOD)
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002139 self.assertConsistentType(Connection, 'Connection', ctx, None)
Rick Deane15b1472009-07-09 15:53:42 -05002140
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002141 def test_get_context(self):
2142 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002143 :py:obj:`Connection.get_context` returns the :py:obj:`Context` instance
2144 used to construct the :py:obj:`Connection` instance.
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002145 """
2146 context = Context(TLSv1_METHOD)
2147 connection = Connection(context, None)
2148 self.assertIdentical(connection.get_context(), context)
2149
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002150 def test_get_context_wrong_args(self):
2151 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002152 :py:obj:`Connection.get_context` raises :py:obj:`TypeError` if called
2153 with any arguments.
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002154 """
2155 connection = Connection(Context(TLSv1_METHOD), None)
2156 self.assertRaises(TypeError, connection.get_context, None)
2157
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002158 def test_set_context_wrong_args(self):
2159 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002160 :py:obj:`Connection.set_context` raises :py:obj:`TypeError` if called
2161 with a non-:py:obj:`Context` instance argument or with any number of
2162 arguments other than 1.
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002163 """
2164 ctx = Context(TLSv1_METHOD)
2165 connection = Connection(ctx, None)
2166 self.assertRaises(TypeError, connection.set_context)
2167 self.assertRaises(TypeError, connection.set_context, object())
2168 self.assertRaises(TypeError, connection.set_context, "hello")
2169 self.assertRaises(TypeError, connection.set_context, 1)
2170 self.assertRaises(TypeError, connection.set_context, 1, 2)
2171 self.assertRaises(
2172 TypeError, connection.set_context, Context(TLSv1_METHOD), 2)
2173 self.assertIdentical(ctx, connection.get_context())
2174
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002175 def test_set_context(self):
2176 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002177 :py:obj:`Connection.set_context` specifies a new :py:obj:`Context`
2178 instance to be used for the connection.
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002179 """
2180 original = Context(SSLv23_METHOD)
2181 replacement = Context(TLSv1_METHOD)
2182 connection = Connection(original, None)
2183 connection.set_context(replacement)
2184 self.assertIdentical(replacement, connection.get_context())
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002185 # Lose our references to the contexts, just in case the Connection
2186 # isn't properly managing its own contributions to their reference
2187 # counts.
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002188 del original, replacement
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002189 collect()
2190
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002191 def test_set_tlsext_host_name_wrong_args(self):
2192 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002193 If :py:obj:`Connection.set_tlsext_host_name` is called with a non-byte
2194 string argument or a byte string with an embedded NUL or other than one
Jonathan Ballet648875f2011-07-16 14:14:58 +09002195 argument, :py:obj:`TypeError` is raised.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002196 """
2197 conn = Connection(Context(TLSv1_METHOD), None)
2198 self.assertRaises(TypeError, conn.set_tlsext_host_name)
2199 self.assertRaises(TypeError, conn.set_tlsext_host_name, object())
2200 self.assertRaises(TypeError, conn.set_tlsext_host_name, 123, 456)
2201 self.assertRaises(
Alex Gaynore7f51982016-09-11 11:48:14 -04002202 TypeError, conn.set_tlsext_host_name, b"with\0null")
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002203
Abraham Martinc5484ba2015-03-25 15:33:05 +00002204 if PY3:
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002205 # On Python 3.x, don't accidentally implicitly convert from text.
2206 self.assertRaises(
2207 TypeError,
Alex Gaynore7f51982016-09-11 11:48:14 -04002208 conn.set_tlsext_host_name, b"example.com".decode("ascii"))
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002209
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04002210 def test_get_servername_wrong_args(self):
2211 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002212 :py:obj:`Connection.get_servername` raises :py:obj:`TypeError` if
2213 called with any arguments.
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04002214 """
2215 connection = Connection(Context(TLSv1_METHOD), None)
2216 self.assertRaises(TypeError, connection.get_servername, object())
2217 self.assertRaises(TypeError, connection.get_servername, 1)
2218 self.assertRaises(TypeError, connection.get_servername, "hello")
2219
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002220 def test_pending(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002221 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002222 :py:obj:`Connection.pending` returns the number of bytes available for
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002223 immediate read.
2224 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002225 connection = Connection(Context(TLSv1_METHOD), None)
2226 self.assertEquals(connection.pending(), 0)
2227
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002228 def test_pending_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002229 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002230 :py:obj:`Connection.pending` raises :py:obj:`TypeError` if called with
2231 any arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002232 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002233 connection = Connection(Context(TLSv1_METHOD), None)
2234 self.assertRaises(TypeError, connection.pending, None)
2235
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002236 def test_peek(self):
2237 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002238 :py:obj:`Connection.recv` peeks into the connection if
2239 :py:obj:`socket.MSG_PEEK` is passed.
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002240 """
2241 server, client = self._loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002242 server.send(b'xy')
2243 self.assertEqual(client.recv(2, MSG_PEEK), b'xy')
2244 self.assertEqual(client.recv(2, MSG_PEEK), b'xy')
2245 self.assertEqual(client.recv(2), b'xy')
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002246
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002247 def test_connect_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002248 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002249 :py:obj:`Connection.connect` raises :py:obj:`TypeError` if called with
2250 a non-address argument or with the wrong number of arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002251 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002252 connection = Connection(Context(TLSv1_METHOD), socket())
2253 self.assertRaises(TypeError, connection.connect, None)
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002254 self.assertRaises(TypeError, connection.connect)
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002255 self.assertRaises(
2256 TypeError, connection.connect, ("127.0.0.1", 1), None
2257 )
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002258
kjavfe508d62015-09-02 12:20:35 +01002259 def test_connection_undefined_attr(self):
2260 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002261 :py:obj:`Connection.connect` raises :py:obj:`TypeError` if called with
2262 a non-address argument or with the wrong number of arguments.
kjavfe508d62015-09-02 12:20:35 +01002263 """
Alex Gaynor1aabb2e2015-09-05 13:35:18 -04002264
kjavfe508d62015-09-02 12:20:35 +01002265 def attr_access_test(connection):
2266 return connection.an_attribute_which_is_not_defined
Alex Gaynor1aabb2e2015-09-05 13:35:18 -04002267
kjavfe508d62015-09-02 12:20:35 +01002268 connection = Connection(Context(TLSv1_METHOD), None)
2269 self.assertRaises(AttributeError, attr_access_test, connection)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002270
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002271 def test_connect_refused(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002272 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002273 :py:obj:`Connection.connect` raises :py:obj:`socket.error` if the
2274 underlying socket connect method raises it.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002275 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002276 client = socket()
2277 context = Context(TLSv1_METHOD)
2278 clientSSL = Connection(context, client)
Alex Gaynor122717b2015-09-05 14:14:18 -04002279 # pytest.raises here doesn't work because of a bug in py.test on Python
2280 # 2.6: https://github.com/pytest-dev/pytest/issues/988
Alex Gaynore69c2782015-09-05 14:07:48 -04002281 try:
Alex Gaynor1aabb2e2015-09-05 13:35:18 -04002282 clientSSL.connect(("127.0.0.1", 1))
Alex Gaynore69c2782015-09-05 14:07:48 -04002283 except error as e:
Alex Gaynor20a4c082015-09-05 14:24:15 -04002284 exc = e
2285 assert exc.args[0] == ECONNREFUSED
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002286
2287 def test_connect(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002288 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002289 :py:obj:`Connection.connect` establishes a connection to the specified
2290 address.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002291 """
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002292 port = socket()
2293 port.bind(('', 0))
2294 port.listen(3)
2295
2296 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002297 clientSSL.connect(('127.0.0.1', port.getsockname()[1]))
2298 # XXX An assertion? Or something?
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002299
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002300 @pytest.mark.skipif(
2301 platform == "darwin",
2302 reason="connect_ex sometimes causes a kernel panic on OS X 10.6.4"
2303 )
2304 def test_connect_ex(self):
2305 """
2306 If there is a connection error, :py:obj:`Connection.connect_ex`
2307 returns the errno instead of raising an exception.
2308 """
2309 port = socket()
2310 port.bind(('', 0))
2311 port.listen(3)
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002312
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002313 clientSSL = Connection(Context(TLSv1_METHOD), socket())
2314 clientSSL.setblocking(False)
2315 result = clientSSL.connect_ex(port.getsockname())
2316 expected = (EINPROGRESS, EWOULDBLOCK)
2317 self.assertTrue(
2318 result in expected, "%r not in %r" % (result, expected))
Jean-Paul Calderone55d91f42010-07-29 19:22:17 -04002319
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002320 def test_accept_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002321 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002322 :py:obj:`Connection.accept` raises :py:obj:`TypeError` if called with
2323 any arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002324 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002325 connection = Connection(Context(TLSv1_METHOD), socket())
2326 self.assertRaises(TypeError, connection.accept, None)
2327
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002328 def test_accept(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002329 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002330 :py:obj:`Connection.accept` accepts a pending connection attempt and
2331 returns a tuple of a new :py:obj:`Connection` (the accepted client) and
2332 the address the connection originated from.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002333 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002334 ctx = Context(TLSv1_METHOD)
2335 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2336 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002337 port = socket()
2338 portSSL = Connection(ctx, port)
2339 portSSL.bind(('', 0))
2340 portSSL.listen(3)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002341
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002342 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002343
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002344 # Calling portSSL.getsockname() here to get the server IP address
2345 # sounds great, but frequently fails on Windows.
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002346 clientSSL.connect(('127.0.0.1', portSSL.getsockname()[1]))
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002347
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002348 serverSSL, address = portSSL.accept()
2349
2350 self.assertTrue(isinstance(serverSSL, Connection))
2351 self.assertIdentical(serverSSL.get_context(), ctx)
2352 self.assertEquals(address, clientSSL.getsockname())
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002353
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002354 def test_shutdown_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002355 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002356 :py:obj:`Connection.shutdown` raises :py:obj:`TypeError` if called with
2357 the wrong number of arguments or with arguments other than integers.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002358 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002359 connection = Connection(Context(TLSv1_METHOD), None)
2360 self.assertRaises(TypeError, connection.shutdown, None)
Jean-Paul Calderone1d3e0222010-07-29 22:52:45 -04002361 self.assertRaises(TypeError, connection.get_shutdown, None)
2362 self.assertRaises(TypeError, connection.set_shutdown)
2363 self.assertRaises(TypeError, connection.set_shutdown, None)
2364 self.assertRaises(TypeError, connection.set_shutdown, 0, 1)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002365
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002366 def test_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002367 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002368 :py:obj:`Connection.shutdown` performs an SSL-level connection
2369 shutdown.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002370 """
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002371 server, client = self._loopback()
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04002372 self.assertFalse(server.shutdown())
2373 self.assertEquals(server.get_shutdown(), SENT_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002374 self.assertRaises(ZeroReturnError, client.recv, 1024)
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04002375 self.assertEquals(client.get_shutdown(), RECEIVED_SHUTDOWN)
2376 client.shutdown()
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002377 self.assertEquals(
2378 client.get_shutdown(), SENT_SHUTDOWN | RECEIVED_SHUTDOWN
2379 )
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04002380 self.assertRaises(ZeroReturnError, server.recv, 1024)
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002381 self.assertEquals(
2382 server.get_shutdown(), SENT_SHUTDOWN | RECEIVED_SHUTDOWN
2383 )
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002384
Paul Aurichc85e0862015-01-08 08:34:33 -08002385 def test_shutdown_closed(self):
2386 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002387 If the underlying socket is closed, :py:obj:`Connection.shutdown`
2388 propagates the write error from the low level write call.
Paul Aurichc85e0862015-01-08 08:34:33 -08002389 """
2390 server, client = self._loopback()
2391 server.sock_shutdown(2)
2392 exc = self.assertRaises(SysCallError, server.shutdown)
2393 if platform == "win32":
2394 self.assertEqual(exc.args[0], ESHUTDOWN)
2395 else:
2396 self.assertEqual(exc.args[0], EPIPE)
2397
Glyph89389472015-04-14 17:29:26 -04002398 def test_shutdown_truncated(self):
Glyph6064ec32015-04-14 16:38:22 -04002399 """
Glyph89389472015-04-14 17:29:26 -04002400 If the underlying connection is truncated, :obj:`Connection.shutdown`
2401 raises an :obj:`Error`.
Glyph6064ec32015-04-14 16:38:22 -04002402 """
Glyph89389472015-04-14 17:29:26 -04002403 server_ctx = Context(TLSv1_METHOD)
2404 client_ctx = Context(TLSv1_METHOD)
2405 server_ctx.use_privatekey(
2406 load_privatekey(FILETYPE_PEM, server_key_pem))
2407 server_ctx.use_certificate(
2408 load_certificate(FILETYPE_PEM, server_cert_pem))
2409 server = Connection(server_ctx, None)
2410 client = Connection(client_ctx, None)
2411 self._handshakeInMemory(client, server)
2412 self.assertEqual(server.shutdown(), False)
2413 self.assertRaises(WantReadError, server.shutdown)
2414 server.bio_shutdown()
Glyph6064ec32015-04-14 16:38:22 -04002415 self.assertRaises(Error, server.shutdown)
2416
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002417 def test_set_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002418 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002419 :py:obj:`Connection.set_shutdown` sets the state of the SSL connection
2420 shutdown process.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002421 """
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002422 connection = Connection(Context(TLSv1_METHOD), socket())
2423 connection.set_shutdown(RECEIVED_SHUTDOWN)
2424 self.assertEquals(connection.get_shutdown(), RECEIVED_SHUTDOWN)
2425
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002426 @skip_if_py3
2427 def test_set_shutdown_long(self):
2428 """
2429 On Python 2 :py:obj:`Connection.set_shutdown` accepts an argument
2430 of type :py:obj:`long` as well as :py:obj:`int`.
2431 """
2432 connection = Connection(Context(TLSv1_METHOD), socket())
2433 connection.set_shutdown(long(RECEIVED_SHUTDOWN))
2434 self.assertEquals(connection.get_shutdown(), RECEIVED_SHUTDOWN)
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -05002435
kjavaf248592015-09-07 12:14:01 +01002436 def test_state_string(self):
2437 """
Hynek Schlawackb0274ce2015-10-16 19:56:26 +02002438 :meth:`Connection.state_string` verbosely describes the current
2439 state of the :class:`Connection`.
kjavaf248592015-09-07 12:14:01 +01002440 """
Hynek Schlawackb0274ce2015-10-16 19:56:26 +02002441 server, client = socket_pair()
kjavaf248592015-09-07 12:14:01 +01002442 server = self._loopbackServerFactory(server)
2443 client = self._loopbackClientFactory(client)
2444
Alex Gaynor5af32d02016-09-24 01:52:21 -04002445 assert server.get_state_string() in [
2446 b"before/accept initialization", b"before SSL initialization"
2447 ]
2448 assert client.get_state_string() in [
2449 b"before/connect initialization", b"before SSL initialization"
2450 ]
kjavaf248592015-09-07 12:14:01 +01002451
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002452 def test_app_data_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002453 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002454 :py:obj:`Connection.set_app_data` raises :py:obj:`TypeError` if called
2455 with other than one argument. :py:obj:`Connection.get_app_data` raises
2456 :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002457 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002458 conn = Connection(Context(TLSv1_METHOD), None)
2459 self.assertRaises(TypeError, conn.get_app_data, None)
2460 self.assertRaises(TypeError, conn.set_app_data)
2461 self.assertRaises(TypeError, conn.set_app_data, None, None)
2462
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002463 def test_app_data(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002464 """
2465 Any object can be set as app data by passing it to
Jonathan Ballet648875f2011-07-16 14:14:58 +09002466 :py:obj:`Connection.set_app_data` and later retrieved with
2467 :py:obj:`Connection.get_app_data`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002468 """
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002469 conn = Connection(Context(TLSv1_METHOD), None)
Todd Chapman4f73e4f2015-08-27 11:26:43 -04002470 assert None is conn.get_app_data()
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002471 app_data = object()
2472 conn.set_app_data(app_data)
Todd Chapman4f73e4f2015-08-27 11:26:43 -04002473 assert conn.get_app_data() is app_data
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002474
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002475 def test_makefile(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002476 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002477 :py:obj:`Connection.makefile` is not implemented and calling that
2478 method raises :py:obj:`NotImplementedError`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002479 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002480 conn = Connection(Context(TLSv1_METHOD), None)
2481 self.assertRaises(NotImplementedError, conn.makefile)
2482
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002483 def test_get_peer_cert_chain_wrong_args(self):
2484 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002485 :py:obj:`Connection.get_peer_cert_chain` raises :py:obj:`TypeError` if
2486 called with any arguments.
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002487 """
2488 conn = Connection(Context(TLSv1_METHOD), None)
2489 self.assertRaises(TypeError, conn.get_peer_cert_chain, 1)
2490 self.assertRaises(TypeError, conn.get_peer_cert_chain, "foo")
2491 self.assertRaises(TypeError, conn.get_peer_cert_chain, object())
2492 self.assertRaises(TypeError, conn.get_peer_cert_chain, [])
2493
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002494 def test_get_peer_cert_chain(self):
2495 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002496 :py:obj:`Connection.get_peer_cert_chain` returns a list of certificates
2497 which the connected server returned for the certification verification.
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002498 """
2499 chain = _create_certificate_chain()
2500 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
2501
2502 serverContext = Context(TLSv1_METHOD)
2503 serverContext.use_privatekey(skey)
2504 serverContext.use_certificate(scert)
2505 serverContext.add_extra_chain_cert(icert)
2506 serverContext.add_extra_chain_cert(cacert)
2507 server = Connection(serverContext, None)
2508 server.set_accept_state()
2509
2510 # Create the client
2511 clientContext = Context(TLSv1_METHOD)
2512 clientContext.set_verify(VERIFY_NONE, verify_cb)
2513 client = Connection(clientContext, None)
2514 client.set_connect_state()
2515
2516 self._interactInMemory(client, server)
2517
2518 chain = client.get_peer_cert_chain()
2519 self.assertEqual(len(chain), 3)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04002520 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002521 "Server Certificate", chain[0].get_subject().CN)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04002522 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002523 "Intermediate Certificate", chain[1].get_subject().CN)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04002524 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002525 "Authority Certificate", chain[2].get_subject().CN)
2526
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002527 def test_get_peer_cert_chain_none(self):
2528 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002529 :py:obj:`Connection.get_peer_cert_chain` returns :py:obj:`None` if the
2530 peer sends no certificate chain.
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002531 """
2532 ctx = Context(TLSv1_METHOD)
2533 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2534 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
2535 server = Connection(ctx, None)
2536 server.set_accept_state()
2537 client = Connection(Context(TLSv1_METHOD), None)
2538 client.set_connect_state()
2539 self._interactInMemory(client, server)
2540 self.assertIdentical(None, server.get_peer_cert_chain())
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002541
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002542 def test_get_session_wrong_args(self):
2543 """
2544 :py:obj:`Connection.get_session` raises :py:obj:`TypeError` if called
2545 with any arguments.
2546 """
2547 ctx = Context(TLSv1_METHOD)
2548 server = Connection(ctx, None)
2549 self.assertRaises(TypeError, server.get_session, 123)
2550 self.assertRaises(TypeError, server.get_session, "hello")
2551 self.assertRaises(TypeError, server.get_session, object())
2552
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002553 def test_get_session_unconnected(self):
2554 """
2555 :py:obj:`Connection.get_session` returns :py:obj:`None` when used with
2556 an object which has not been connected.
2557 """
2558 ctx = Context(TLSv1_METHOD)
2559 server = Connection(ctx, None)
2560 session = server.get_session()
2561 self.assertIdentical(None, session)
2562
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002563 def test_server_get_session(self):
2564 """
2565 On the server side of a connection, :py:obj:`Connection.get_session`
2566 returns a :py:class:`Session` instance representing the SSL session for
2567 that connection.
2568 """
2569 server, client = self._loopback()
2570 session = server.get_session()
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08002571 self.assertIsInstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002572
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002573 def test_client_get_session(self):
2574 """
2575 On the client side of a connection, :py:obj:`Connection.get_session`
2576 returns a :py:class:`Session` instance representing the SSL session for
2577 that connection.
2578 """
2579 server, client = self._loopback()
2580 session = client.get_session()
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08002581 self.assertIsInstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002582
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002583 def test_set_session_wrong_args(self):
2584 """
Hynek Schlawackdddd1112015-09-05 21:12:30 +02002585 If called with an object that is not an instance of
2586 :py:class:`Session`, or with other than one argument,
2587 :py:obj:`Connection.set_session` raises :py:obj:`TypeError`.
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002588 """
2589 ctx = Context(TLSv1_METHOD)
2590 connection = Connection(ctx, None)
2591 self.assertRaises(TypeError, connection.set_session)
2592 self.assertRaises(TypeError, connection.set_session, 123)
2593 self.assertRaises(TypeError, connection.set_session, "hello")
2594 self.assertRaises(TypeError, connection.set_session, object())
2595 self.assertRaises(
2596 TypeError, connection.set_session, Session(), Session())
2597
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002598 def test_client_set_session(self):
2599 """
2600 :py:obj:`Connection.set_session`, when used prior to a connection being
2601 established, accepts a :py:class:`Session` instance and causes an
2602 attempt to re-use the session it represents when the SSL handshake is
2603 performed.
2604 """
2605 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2606 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
2607 ctx = Context(TLSv1_METHOD)
2608 ctx.use_privatekey(key)
2609 ctx.use_certificate(cert)
2610 ctx.set_session_id("unity-test")
2611
2612 def makeServer(socket):
2613 server = Connection(ctx, socket)
2614 server.set_accept_state()
2615 return server
2616
2617 originalServer, originalClient = self._loopback(
2618 serverFactory=makeServer)
2619 originalSession = originalClient.get_session()
2620
2621 def makeClient(socket):
2622 client = self._loopbackClientFactory(socket)
2623 client.set_session(originalSession)
2624 return client
2625 resumedServer, resumedClient = self._loopback(
2626 serverFactory=makeServer,
2627 clientFactory=makeClient)
2628
2629 # This is a proxy: in general, we have no access to any unique
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002630 # identifier for the session (new enough versions of OpenSSL expose
2631 # a hash which could be usable, but "new enough" is very, very new).
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002632 # Instead, exploit the fact that the master key is re-used if the
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002633 # session is re-used. As long as the master key for the two
2634 # connections is the same, the session was re-used!
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002635 self.assertEqual(
2636 originalServer.master_key(), resumedServer.master_key())
2637
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002638 def test_set_session_wrong_method(self):
2639 """
Jean-Paul Calderone068cb592012-02-14 16:52:43 -05002640 If :py:obj:`Connection.set_session` is passed a :py:class:`Session`
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002641 instance associated with a context using a different SSL method than
2642 the :py:obj:`Connection` is using, a :py:class:`OpenSSL.SSL.Error` is
Jean-Paul Calderone068cb592012-02-14 16:52:43 -05002643 raised.
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002644 """
Alex Gaynor5af32d02016-09-24 01:52:21 -04002645 # Make this work on both OpenSSL 1.0.0, which doesn't support TLSv1.2
2646 # and also on OpenSSL 1.1.0 which doesn't support SSLv3. (SSL_ST_INIT
2647 # is a way to check for 1.1.0)
2648 if SSL_ST_INIT is not None:
2649 v1 = TLSv1_METHOD
2650 v2 = SSLv3_METHOD
2651 else:
2652 v1 = TLSv1_2_METHOD
2653 v2 = TLSv1_METHOD
2654
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002655 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2656 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
Alex Gaynor5af32d02016-09-24 01:52:21 -04002657 ctx = Context(v1)
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002658 ctx.use_privatekey(key)
2659 ctx.use_certificate(cert)
2660 ctx.set_session_id("unity-test")
2661
2662 def makeServer(socket):
2663 server = Connection(ctx, socket)
2664 server.set_accept_state()
2665 return server
2666
Alex Gaynor5af32d02016-09-24 01:52:21 -04002667 def makeOriginalClient(socket):
2668 client = Connection(Context(v1), socket)
2669 client.set_connect_state()
2670 return client
2671
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002672 originalServer, originalClient = self._loopback(
Alex Gaynor5af32d02016-09-24 01:52:21 -04002673 serverFactory=makeServer, clientFactory=makeOriginalClient)
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002674 originalSession = originalClient.get_session()
2675
2676 def makeClient(socket):
2677 # Intentionally use a different, incompatible method here.
Alex Gaynor5af32d02016-09-24 01:52:21 -04002678 client = Connection(Context(v2), socket)
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002679 client.set_connect_state()
2680 client.set_session(originalSession)
2681 return client
2682
2683 self.assertRaises(
2684 Error,
2685 self._loopback, clientFactory=makeClient, serverFactory=makeServer)
2686
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002687 def test_wantWriteError(self):
2688 """
2689 :py:obj:`Connection` methods which generate output raise
2690 :py:obj:`OpenSSL.SSL.WantWriteError` if writing to the connection's BIO
2691 fail indicating a should-write state.
2692 """
2693 client_socket, server_socket = socket_pair()
2694 # Fill up the client's send buffer so Connection won't be able to write
Jean-Paul Calderonebbff8b92014-03-22 14:20:30 -04002695 # anything. Only write a single byte at a time so we can be sure we
2696 # completely fill the buffer. Even though the socket API is allowed to
2697 # signal a short write via its return value it seems this doesn't
2698 # always happen on all platforms (FreeBSD and OS X particular) for the
2699 # very last bit of available buffer space.
2700 msg = b"x"
2701 for i in range(1024 * 1024 * 4):
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002702 try:
2703 client_socket.send(msg)
2704 except error as e:
2705 if e.errno == EWOULDBLOCK:
2706 break
2707 raise
2708 else:
2709 self.fail(
2710 "Failed to fill socket buffer, cannot test BIO want write")
2711
2712 ctx = Context(TLSv1_METHOD)
2713 conn = Connection(ctx, client_socket)
2714 # Client's speak first, so make it an SSL client
2715 conn.set_connect_state()
2716 self.assertRaises(WantWriteError, conn.do_handshake)
2717
2718 # XXX want_read
2719
Fedor Brunner416f4a12014-03-28 13:18:38 +01002720 def test_get_finished_before_connect(self):
Fedor Brunner5747b932014-03-05 14:22:34 +01002721 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002722 :py:obj:`Connection.get_finished` returns :py:obj:`None` before TLS
2723 handshake is completed.
Fedor Brunner5747b932014-03-05 14:22:34 +01002724 """
Fedor Brunner5747b932014-03-05 14:22:34 +01002725 ctx = Context(TLSv1_METHOD)
2726 connection = Connection(ctx, None)
2727 self.assertEqual(connection.get_finished(), None)
Fedor Brunner416f4a12014-03-28 13:18:38 +01002728
2729 def test_get_peer_finished_before_connect(self):
2730 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002731 :py:obj:`Connection.get_peer_finished` returns :py:obj:`None` before
2732 TLS handshake is completed.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002733 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002734 ctx = Context(TLSv1_METHOD)
2735 connection = Connection(ctx, None)
Fedor Brunner5747b932014-03-05 14:22:34 +01002736 self.assertEqual(connection.get_peer_finished(), None)
2737
Fedor Brunner416f4a12014-03-28 13:18:38 +01002738 def test_get_finished(self):
2739 """
2740 :py:obj:`Connection.get_finished` method returns the TLS Finished
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002741 message send from client, or server. Finished messages are send during
2742 TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002743 """
2744
Fedor Brunner5747b932014-03-05 14:22:34 +01002745 server, client = self._loopback()
2746
2747 self.assertNotEqual(server.get_finished(), None)
2748 self.assertTrue(len(server.get_finished()) > 0)
Fedor Brunner416f4a12014-03-28 13:18:38 +01002749
2750 def test_get_peer_finished(self):
2751 """
2752 :py:obj:`Connection.get_peer_finished` method returns the TLS Finished
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002753 message received from client, or server. Finished messages are send
2754 during TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002755 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002756 server, client = self._loopback()
2757
2758 self.assertNotEqual(server.get_peer_finished(), None)
Fedor Brunner5747b932014-03-05 14:22:34 +01002759 self.assertTrue(len(server.get_peer_finished()) > 0)
2760
Fedor Brunner416f4a12014-03-28 13:18:38 +01002761 def test_tls_finished_message_symmetry(self):
2762 """
Hynek Schlawackdddd1112015-09-05 21:12:30 +02002763 The TLS Finished message send by server must be the TLS Finished
2764 message received by client.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002765
Hynek Schlawackdddd1112015-09-05 21:12:30 +02002766 The TLS Finished message send by client must be the TLS Finished
2767 message received by server.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002768 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002769 server, client = self._loopback()
2770
Fedor Brunner5747b932014-03-05 14:22:34 +01002771 self.assertEqual(server.get_finished(), client.get_peer_finished())
2772 self.assertEqual(client.get_finished(), server.get_peer_finished())
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002773
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002774 def test_get_cipher_name_before_connect(self):
2775 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002776 :py:obj:`Connection.get_cipher_name` returns :py:obj:`None` if no
2777 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002778 """
2779 ctx = Context(TLSv1_METHOD)
2780 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002781 self.assertIdentical(conn.get_cipher_name(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002782
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002783 def test_get_cipher_name(self):
2784 """
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002785 :py:obj:`Connection.get_cipher_name` returns a :py:class:`unicode`
2786 string giving the name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002787 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002788 server, client = self._loopback()
2789 server_cipher_name, client_cipher_name = \
2790 server.get_cipher_name(), client.get_cipher_name()
2791
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002792 self.assertIsInstance(server_cipher_name, text_type)
2793 self.assertIsInstance(client_cipher_name, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002794
2795 self.assertEqual(server_cipher_name, client_cipher_name)
2796
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002797 def test_get_cipher_version_before_connect(self):
2798 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002799 :py:obj:`Connection.get_cipher_version` returns :py:obj:`None` if no
2800 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002801 """
2802 ctx = Context(TLSv1_METHOD)
2803 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002804 self.assertIdentical(conn.get_cipher_version(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002805
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002806 def test_get_cipher_version(self):
2807 """
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002808 :py:obj:`Connection.get_cipher_version` returns a :py:class:`unicode`
2809 string giving the protocol name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002810 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002811 server, client = self._loopback()
2812 server_cipher_version, client_cipher_version = \
2813 server.get_cipher_version(), client.get_cipher_version()
2814
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002815 self.assertIsInstance(server_cipher_version, text_type)
2816 self.assertIsInstance(client_cipher_version, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002817
2818 self.assertEqual(server_cipher_version, client_cipher_version)
2819
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002820 def test_get_cipher_bits_before_connect(self):
2821 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002822 :py:obj:`Connection.get_cipher_bits` returns :py:obj:`None` if no
2823 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002824 """
2825 ctx = Context(TLSv1_METHOD)
2826 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002827 self.assertIdentical(conn.get_cipher_bits(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002828
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002829 def test_get_cipher_bits(self):
2830 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002831 :py:obj:`Connection.get_cipher_bits` returns the number of secret bits
2832 of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002833 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002834 server, client = self._loopback()
2835 server_cipher_bits, client_cipher_bits = \
2836 server.get_cipher_bits(), client.get_cipher_bits()
2837
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002838 self.assertIsInstance(server_cipher_bits, int)
2839 self.assertIsInstance(client_cipher_bits, int)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002840
2841 self.assertEqual(server_cipher_bits, client_cipher_bits)
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002842
Jim Shaverabff1882015-05-27 09:15:55 -04002843 def test_get_protocol_version_name(self):
2844 """
2845 :py:obj:`Connection.get_protocol_version_name()` returns a string
2846 giving the protocol version of the current connection.
2847 """
2848 server, client = self._loopback()
2849 client_protocol_version_name = client.get_protocol_version_name()
2850 server_protocol_version_name = server.get_protocol_version_name()
2851
Jim Shaver58d25732015-05-28 11:52:32 -04002852 self.assertIsInstance(server_protocol_version_name, text_type)
2853 self.assertIsInstance(client_protocol_version_name, text_type)
Jim Shaverabff1882015-05-27 09:15:55 -04002854
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002855 self.assertEqual(
2856 server_protocol_version_name, client_protocol_version_name
2857 )
Jim Shaverabff1882015-05-27 09:15:55 -04002858
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002859 def test_get_protocol_version(self):
2860 """
Alex Gaynor43307782015-09-04 09:05:45 -04002861 :py:obj:`Connection.get_protocol_version()` returns an integer
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002862 giving the protocol version of the current connection.
2863 """
2864 server, client = self._loopback()
Jim Shaver85a4dff2015-04-27 17:42:46 -04002865 client_protocol_version = client.get_protocol_version()
2866 server_protocol_version = server.get_protocol_version()
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002867
Jim Shaverabff1882015-05-27 09:15:55 -04002868 self.assertIsInstance(server_protocol_version, int)
2869 self.assertIsInstance(client_protocol_version, int)
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002870
2871 self.assertEqual(server_protocol_version, client_protocol_version)
2872
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002873
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002874class ConnectionGetCipherListTests(TestCase):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002875 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002876 Tests for :py:obj:`Connection.get_cipher_list`.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002877 """
Jean-Paul Calderone54a2bc02010-09-09 17:52:38 -04002878 def test_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002879 """
Hynek Schlawackdddd1112015-09-05 21:12:30 +02002880 :py:obj:`Connection.get_cipher_list` raises :py:obj:`TypeError` if
2881 called with any arguments.
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 self.assertRaises(TypeError, connection.get_cipher_list, None)
2885
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002886 def test_result(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002887 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002888 :py:obj:`Connection.get_cipher_list` returns a :py:obj:`list` of
2889 :py:obj:`bytes` giving the names of the ciphers which might be used.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002890 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002891 connection = Connection(Context(TLSv1_METHOD), None)
2892 ciphers = connection.get_cipher_list()
2893 self.assertTrue(isinstance(ciphers, list))
2894 for cipher in ciphers:
2895 self.assertTrue(isinstance(cipher, str))
2896
2897
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002898class ConnectionSendTests(TestCase, _LoopbackMixin):
2899 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002900 Tests for :py:obj:`Connection.send`
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002901 """
2902 def test_wrong_args(self):
2903 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002904 When called with arguments other than string argument for its first
2905 parameter or more than two arguments, :py:obj:`Connection.send` raises
2906 :py:obj:`TypeError`.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002907 """
2908 connection = Connection(Context(TLSv1_METHOD), None)
Jean-Paul Calderone77fa2602011-01-05 18:23:39 -05002909 self.assertRaises(TypeError, connection.send)
2910 self.assertRaises(TypeError, connection.send, object())
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002911 self.assertRaises(TypeError, connection.send, "foo", object(), "bar")
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002912
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002913 def test_short_bytes(self):
2914 """
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002915 When passed a short byte string, :py:obj:`Connection.send` transmits
2916 all of it and returns the number of bytes sent.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002917 """
2918 server, client = self._loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002919 count = server.send(b'xy')
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002920 self.assertEquals(count, 2)
Alex Gaynore7f51982016-09-11 11:48:14 -04002921 self.assertEquals(client.recv(2), b'xy')
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002922
Abraham Martinef063482015-03-25 14:06:24 +00002923 def test_text(self):
2924 """
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002925 When passed a text, :py:obj:`Connection.send` transmits all of it and
2926 returns the number of bytes sent. It also raises a DeprecationWarning.
Abraham Martinef063482015-03-25 14:06:24 +00002927 """
2928 server, client = self._loopback()
2929 with catch_warnings(record=True) as w:
2930 simplefilter("always")
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002931 count = server.send(b"xy".decode("ascii"))
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002932 self.assertEqual(
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002933 "{0} for buf is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002934 WARNING_TYPE_EXPECTED
2935 ),
2936 str(w[-1].message)
2937 )
2938 self.assertIs(w[-1].category, DeprecationWarning)
Abraham Martinef063482015-03-25 14:06:24 +00002939 self.assertEquals(count, 2)
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002940 self.assertEquals(client.recv(2), b"xy")
Abraham Martinef063482015-03-25 14:06:24 +00002941
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002942 @skip_if_py26
2943 def test_short_memoryview(self):
2944 """
2945 When passed a memoryview onto a small number of bytes,
2946 :py:obj:`Connection.send` transmits all of them and returns the number
2947 of bytes sent.
2948 """
2949 server, client = self._loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002950 count = server.send(memoryview(b'xy'))
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002951 self.assertEquals(count, 2)
Alex Gaynore7f51982016-09-11 11:48:14 -04002952 self.assertEquals(client.recv(2), b'xy')
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002953
Hynek Schlawack8e94f1b2015-09-05 21:31:00 +02002954 @skip_if_py3
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002955 def test_short_buffer(self):
2956 """
2957 When passed a buffer containing a small number of bytes,
2958 :py:obj:`Connection.send` transmits all of them and returns the number
2959 of bytes sent.
2960 """
2961 server, client = self._loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002962 count = server.send(buffer(b'xy'))
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002963 self.assertEquals(count, 2)
Alex Gaynore7f51982016-09-11 11:48:14 -04002964 self.assertEquals(client.recv(2), b'xy')
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02002965
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05002966
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002967def _make_memoryview(size):
2968 """
2969 Create a new ``memoryview`` wrapped around a ``bytearray`` of the given
2970 size.
2971 """
2972 return memoryview(bytearray(size))
2973
2974
Cory Benfield62d10332014-06-15 10:03:41 +01002975class ConnectionRecvIntoTests(TestCase, _LoopbackMixin):
2976 """
2977 Tests for :py:obj:`Connection.recv_into`
2978 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002979 def _no_length_test(self, factory):
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04002980 """
2981 Assert that when the given buffer is passed to
2982 ``Connection.recv_into``, whatever bytes are available to be received
2983 that fit into that buffer are written into that buffer.
2984 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002985 output_buffer = factory(5)
2986
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04002987 server, client = self._loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04002988 server.send(b'xy')
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04002989
Jean-Paul Calderone320af1e2015-03-15 17:20:13 -04002990 self.assertEqual(client.recv_into(output_buffer), 2)
Alex Gaynore7f51982016-09-11 11:48:14 -04002991 self.assertEqual(output_buffer, bytearray(b'xy\x00\x00\x00'))
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04002992
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002993 def test_bytearray_no_length(self):
Cory Benfield62d10332014-06-15 10:03:41 +01002994 """
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04002995 :py:obj:`Connection.recv_into` can be passed a ``bytearray`` instance
2996 and data in the receive buffer is written to it.
Cory Benfield62d10332014-06-15 10:03:41 +01002997 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002998 self._no_length_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01002999
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003000 def _respects_length_test(self, factory):
Cory Benfield62d10332014-06-15 10:03:41 +01003001 """
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04003002 Assert that when the given buffer is passed to ``Connection.recv_into``
3003 along with a value for ``nbytes`` that is less than the size of that
3004 buffer, only ``nbytes`` bytes are written into the buffer.
Cory Benfield62d10332014-06-15 10:03:41 +01003005 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003006 output_buffer = factory(10)
3007
Cory Benfield62d10332014-06-15 10:03:41 +01003008 server, client = self._loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04003009 server.send(b'abcdefghij')
Cory Benfield62d10332014-06-15 10:03:41 +01003010
Jean-Paul Calderone320af1e2015-03-15 17:20:13 -04003011 self.assertEqual(client.recv_into(output_buffer, 5), 5)
3012 self.assertEqual(
Alex Gaynore7f51982016-09-11 11:48:14 -04003013 output_buffer, bytearray(b'abcde\x00\x00\x00\x00\x00')
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04003014 )
3015
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04003016 def test_bytearray_respects_length(self):
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04003017 """
3018 When called with a ``bytearray`` instance,
3019 :py:obj:`Connection.recv_into` respects the ``nbytes`` parameter and
3020 doesn't copy in more than that number of bytes.
3021 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003022 self._respects_length_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01003023
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003024 def _doesnt_overfill_test(self, factory):
Cory Benfield62d10332014-06-15 10:03:41 +01003025 """
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04003026 Assert that if there are more bytes available to be read from the
3027 receive buffer than would fit into the buffer passed to
3028 :py:obj:`Connection.recv_into`, only as many as fit are written into
3029 it.
Cory Benfield62d10332014-06-15 10:03:41 +01003030 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003031 output_buffer = factory(5)
3032
Cory Benfield62d10332014-06-15 10:03:41 +01003033 server, client = self._loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04003034 server.send(b'abcdefghij')
Cory Benfield62d10332014-06-15 10:03:41 +01003035
Jean-Paul Calderone320af1e2015-03-15 17:20:13 -04003036 self.assertEqual(client.recv_into(output_buffer), 5)
Alex Gaynore7f51982016-09-11 11:48:14 -04003037 self.assertEqual(output_buffer, bytearray(b'abcde'))
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04003038 rest = client.recv(5)
Alex Gaynore7f51982016-09-11 11:48:14 -04003039 self.assertEqual(b'fghij', rest)
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04003040
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04003041 def test_bytearray_doesnt_overfill(self):
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04003042 """
3043 When called with a ``bytearray`` instance,
3044 :py:obj:`Connection.recv_into` respects the size of the array and
3045 doesn't write more bytes into it than will fit.
3046 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003047 self._doesnt_overfill_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01003048
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04003049 def test_bytearray_really_doesnt_overfill(self):
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003050 """
3051 When called with a ``bytearray`` instance and an ``nbytes`` value that
3052 is too large, :py:obj:`Connection.recv_into` respects the size of the
3053 array and not the ``nbytes`` value and doesn't write more bytes into
3054 the buffer than will fit.
3055 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003056 self._doesnt_overfill_test(bytearray)
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003057
Maximilian Hils1d95dea2015-08-17 19:27:20 +02003058 def test_peek(self):
Maximilian Hils1d95dea2015-08-17 19:27:20 +02003059 server, client = self._loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04003060 server.send(b'xy')
Maximilian Hils1d95dea2015-08-17 19:27:20 +02003061
3062 for _ in range(2):
3063 output_buffer = bytearray(5)
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003064 self.assertEqual(
3065 client.recv_into(output_buffer, flags=MSG_PEEK), 2)
Alex Gaynore7f51982016-09-11 11:48:14 -04003066 self.assertEqual(output_buffer, bytearray(b'xy\x00\x00\x00'))
Maximilian Hils1d95dea2015-08-17 19:27:20 +02003067
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003068 @skip_if_py26
3069 def test_memoryview_no_length(self):
3070 """
3071 :py:obj:`Connection.recv_into` can be passed a ``memoryview``
3072 instance and data in the receive buffer is written to it.
3073 """
3074 self._no_length_test(_make_memoryview)
Maximilian Hils1d95dea2015-08-17 19:27:20 +02003075
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003076 @skip_if_py26
3077 def test_memoryview_respects_length(self):
3078 """
3079 When called with a ``memoryview`` instance,
3080 :py:obj:`Connection.recv_into` respects the ``nbytes`` parameter
3081 and doesn't copy more than that number of bytes in.
3082 """
3083 self._respects_length_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01003084
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003085 @skip_if_py26
3086 def test_memoryview_doesnt_overfill(self):
3087 """
3088 When called with a ``memoryview`` instance,
3089 :py:obj:`Connection.recv_into` respects the size of the array and
3090 doesn't write more bytes into it than will fit.
3091 """
3092 self._doesnt_overfill_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01003093
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003094 @skip_if_py26
3095 def test_memoryview_really_doesnt_overfill(self):
3096 """
3097 When called with a ``memoryview`` instance and an ``nbytes`` value
3098 that is too large, :py:obj:`Connection.recv_into` respects the size
3099 of the array and not the ``nbytes`` value and doesn't write more
3100 bytes into the buffer than will fit.
3101 """
3102 self._doesnt_overfill_test(_make_memoryview)
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003103
Cory Benfield62d10332014-06-15 10:03:41 +01003104
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003105class ConnectionSendallTests(TestCase, _LoopbackMixin):
3106 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003107 Tests for :py:obj:`Connection.sendall`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003108 """
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003109 def test_wrong_args(self):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003110 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003111 When called with arguments other than a string argument for its first
3112 parameter or with more than two arguments, :py:obj:`Connection.sendall`
3113 raises :py:obj:`TypeError`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003114 """
3115 connection = Connection(Context(TLSv1_METHOD), None)
3116 self.assertRaises(TypeError, connection.sendall)
3117 self.assertRaises(TypeError, connection.sendall, object())
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003118 self.assertRaises(
3119 TypeError, connection.sendall, "foo", object(), "bar")
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003120
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003121 def test_short(self):
3122 """
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003123 :py:obj:`Connection.sendall` transmits all of the bytes in the string
3124 passed to it.
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003125 """
3126 server, client = self._loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04003127 server.sendall(b'x')
3128 self.assertEquals(client.recv(1), b'x')
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003129
Abraham Martinef063482015-03-25 14:06:24 +00003130 def test_text(self):
3131 """
Jean-Paul Calderone93477422015-04-13 20:38:57 -04003132 :py:obj:`Connection.sendall` transmits all the content in the string
3133 passed to it raising a DeprecationWarning in case of this being a text.
Abraham Martinef063482015-03-25 14:06:24 +00003134 """
3135 server, client = self._loopback()
3136 with catch_warnings(record=True) as w:
3137 simplefilter("always")
Jean-Paul Calderone8dc37a12015-03-29 08:16:52 -04003138 server.sendall(b"x".decode("ascii"))
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04003139 self.assertEqual(
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04003140 "{0} for buf is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04003141 WARNING_TYPE_EXPECTED
3142 ),
3143 str(w[-1].message)
3144 )
3145 self.assertIs(w[-1].category, DeprecationWarning)
3146 self.assertEquals(client.recv(1), b"x")
Abraham Martinef063482015-03-25 14:06:24 +00003147
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003148 @skip_if_py26
3149 def test_short_memoryview(self):
3150 """
3151 When passed a memoryview onto a small number of bytes,
3152 :py:obj:`Connection.sendall` transmits all of them.
3153 """
3154 server, client = self._loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04003155 server.sendall(memoryview(b'x'))
3156 self.assertEquals(client.recv(1), b'x')
Abraham Martinef063482015-03-25 14:06:24 +00003157
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003158 @skip_if_py3
3159 def test_short_buffers(self):
3160 """
3161 When passed a buffer containing a small number of bytes,
3162 :py:obj:`Connection.sendall` transmits all of them.
3163 """
3164 server, client = self._loopback()
Alex Gaynore7f51982016-09-11 11:48:14 -04003165 server.sendall(buffer(b'x'))
3166 self.assertEquals(client.recv(1), b'x')
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02003167
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003168 def test_long(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003169 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003170 :py:obj:`Connection.sendall` transmits all of the bytes in the string
3171 passed to it even if this requires multiple calls of an underlying
3172 write function.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003173 """
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003174 server, client = self._loopback()
Jean-Paul Calderone6241c702010-09-16 19:59:24 -04003175 # Should be enough, underlying SSL_write should only do 16k at a time.
Hynek Schlawack35618382015-09-05 21:54:25 +02003176 # On Windows, after 32k of bytes the write will block (forever
3177 # - because no one is yet reading).
Alex Gaynore7f51982016-09-11 11:48:14 -04003178 message = b'x' * (1024 * 32 - 1) + b'y'
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003179 server.sendall(message)
3180 accum = []
3181 received = 0
3182 while received < len(message):
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04003183 data = client.recv(1024)
3184 accum.append(data)
3185 received += len(data)
Alex Gaynore7f51982016-09-11 11:48:14 -04003186 self.assertEquals(message, b''.join(accum))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003187
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003188 def test_closed(self):
3189 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003190 If the underlying socket is closed, :py:obj:`Connection.sendall`
3191 propagates the write error from the low level write call.
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003192 """
3193 server, client = self._loopback()
Jean-Paul Calderone05d43e82010-09-24 18:01:36 -04003194 server.sock_shutdown(2)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003195 exc = self.assertRaises(SysCallError, server.sendall, b"hello, world")
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +02003196 if platform == "win32":
3197 self.assertEqual(exc.args[0], ESHUTDOWN)
3198 else:
3199 self.assertEqual(exc.args[0], EPIPE)
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003200
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003201
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003202class ConnectionRenegotiateTests(TestCase, _LoopbackMixin):
3203 """
3204 Tests for SSL renegotiation APIs.
3205 """
3206 def test_renegotiate_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003207 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003208 :py:obj:`Connection.renegotiate` raises :py:obj:`TypeError` if called
3209 with any arguments.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003210 """
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003211 connection = Connection(Context(TLSv1_METHOD), None)
3212 self.assertRaises(TypeError, connection.renegotiate, None)
3213
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003214 def test_total_renegotiations_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003215 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003216 :py:obj:`Connection.total_renegotiations` raises :py:obj:`TypeError` if
3217 called with any arguments.
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.assertRaises(TypeError, connection.total_renegotiations, None)
3221
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003222 def test_total_renegotiations(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003223 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003224 :py:obj:`Connection.total_renegotiations` returns :py:obj:`0` before
3225 any renegotiations have happened.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003226 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003227 connection = Connection(Context(TLSv1_METHOD), None)
3228 self.assertEquals(connection.total_renegotiations(), 0)
3229
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003230 def test_renegotiate(self):
3231 """
3232 Go through a complete renegotiation cycle.
3233 """
3234 server, client = self._loopback()
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003235
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003236 server.send(b"hello world")
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003237
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003238 assert b"hello world" == client.recv(len(b"hello world"))
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003239
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003240 assert 0 == server.total_renegotiations()
3241 assert False is server.renegotiate_pending()
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003242
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003243 assert True is server.renegotiate()
3244
3245 assert True is server.renegotiate_pending()
3246
3247 server.setblocking(False)
3248 client.setblocking(False)
3249
3250 client.do_handshake()
3251 server.do_handshake()
3252
3253 assert 1 == server.total_renegotiations()
3254 while False is server.renegotiate_pending():
3255 pass
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003256
3257
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003258class ErrorTests(TestCase):
3259 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003260 Unit tests for :py:obj:`OpenSSL.SSL.Error`.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003261 """
3262 def test_type(self):
3263 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003264 :py:obj:`Error` is an exception type.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003265 """
3266 self.assertTrue(issubclass(Error, Exception))
Rick Deane15b1472009-07-09 15:53:42 -05003267 self.assertEqual(Error.__name__, 'Error')
Rick Deane15b1472009-07-09 15:53:42 -05003268
3269
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003270class ConstantsTests(TestCase):
3271 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003272 Tests for the values of constants exposed in :py:obj:`OpenSSL.SSL`.
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003273
3274 These are values defined by OpenSSL intended only to be used as flags to
3275 OpenSSL APIs. The only assertions it seems can be made about them is
3276 their values.
3277 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003278 @pytest.mark.skipif(
3279 OP_NO_QUERY_MTU is None,
3280 reason="OP_NO_QUERY_MTU unavailable - OpenSSL version may be too old"
3281 )
3282 def test_op_no_query_mtu(self):
3283 """
3284 The value of :py:obj:`OpenSSL.SSL.OP_NO_QUERY_MTU` is 0x1000, the value
3285 of :py:const:`SSL_OP_NO_QUERY_MTU` defined by :file:`openssl/ssl.h`.
3286 """
3287 self.assertEqual(OP_NO_QUERY_MTU, 0x1000)
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003288
Hynek Schlawack35618382015-09-05 21:54:25 +02003289 @pytest.mark.skipif(
3290 OP_COOKIE_EXCHANGE is None,
3291 reason="OP_COOKIE_EXCHANGE unavailable - "
3292 "OpenSSL version may be too old"
3293 )
3294 def test_op_cookie_exchange(self):
3295 """
3296 The value of :py:obj:`OpenSSL.SSL.OP_COOKIE_EXCHANGE` is 0x2000, the
3297 value of :py:const:`SSL_OP_COOKIE_EXCHANGE` defined by
3298 :file:`openssl/ssl.h`.
3299 """
3300 self.assertEqual(OP_COOKIE_EXCHANGE, 0x2000)
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003301
Hynek Schlawack35618382015-09-05 21:54:25 +02003302 @pytest.mark.skipif(
3303 OP_NO_TICKET is None,
3304 reason="OP_NO_TICKET unavailable - OpenSSL version may be too old"
3305 )
3306 def test_op_no_ticket(self):
3307 """
3308 The value of :py:obj:`OpenSSL.SSL.OP_NO_TICKET` is 0x4000, the value of
3309 :py:const:`SSL_OP_NO_TICKET` defined by :file:`openssl/ssl.h`.
3310 """
3311 self.assertEqual(OP_NO_TICKET, 0x4000)
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003312
Hynek Schlawack35618382015-09-05 21:54:25 +02003313 @pytest.mark.skipif(
3314 OP_NO_COMPRESSION is None,
3315 reason="OP_NO_COMPRESSION unavailable - OpenSSL version may be too old"
3316 )
3317 def test_op_no_compression(self):
3318 """
3319 The value of :py:obj:`OpenSSL.SSL.OP_NO_COMPRESSION` is 0x20000, the
3320 value of :py:const:`SSL_OP_NO_COMPRESSION` defined by
3321 :file:`openssl/ssl.h`.
3322 """
3323 self.assertEqual(OP_NO_COMPRESSION, 0x20000)
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04003324
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003325 def test_sess_cache_off(self):
3326 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003327 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_OFF` 0x0, the value of
3328 :py:obj:`SSL_SESS_CACHE_OFF` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003329 """
3330 self.assertEqual(0x0, SESS_CACHE_OFF)
3331
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003332 def test_sess_cache_client(self):
3333 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003334 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_CLIENT` 0x1, the value of
3335 :py:obj:`SSL_SESS_CACHE_CLIENT` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003336 """
3337 self.assertEqual(0x1, SESS_CACHE_CLIENT)
3338
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003339 def test_sess_cache_server(self):
3340 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003341 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_SERVER` 0x2, the value of
3342 :py:obj:`SSL_SESS_CACHE_SERVER` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003343 """
3344 self.assertEqual(0x2, SESS_CACHE_SERVER)
3345
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003346 def test_sess_cache_both(self):
3347 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003348 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_BOTH` 0x3, the value of
3349 :py:obj:`SSL_SESS_CACHE_BOTH` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003350 """
3351 self.assertEqual(0x3, SESS_CACHE_BOTH)
3352
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003353 def test_sess_cache_no_auto_clear(self):
3354 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003355 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_AUTO_CLEAR` 0x80, the
3356 value of :py:obj:`SSL_SESS_CACHE_NO_AUTO_CLEAR` defined by
3357 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003358 """
3359 self.assertEqual(0x80, SESS_CACHE_NO_AUTO_CLEAR)
3360
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003361 def test_sess_cache_no_internal_lookup(self):
3362 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003363 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_LOOKUP` 0x100,
3364 the value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL_LOOKUP` defined by
3365 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003366 """
3367 self.assertEqual(0x100, SESS_CACHE_NO_INTERNAL_LOOKUP)
3368
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003369 def test_sess_cache_no_internal_store(self):
3370 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003371 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_STORE` 0x200,
3372 the value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL_STORE` defined by
3373 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003374 """
3375 self.assertEqual(0x200, SESS_CACHE_NO_INTERNAL_STORE)
3376
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003377 def test_sess_cache_no_internal(self):
3378 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003379 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL` 0x300, the
3380 value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL` defined by
3381 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003382 """
3383 self.assertEqual(0x300, SESS_CACHE_NO_INTERNAL)
3384
3385
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003386class MemoryBIOTests(TestCase, _LoopbackMixin):
Rick Deanb71c0d22009-04-01 14:09:23 -05003387 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003388 Tests for :py:obj:`OpenSSL.SSL.Connection` using a memory BIO.
Rick Deanb71c0d22009-04-01 14:09:23 -05003389 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003390 def _server(self, sock):
3391 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003392 Create a new server-side SSL :py:obj:`Connection` object wrapped around
3393 :py:obj:`sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003394 """
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003395 # Create the server side Connection. This is mostly setup boilerplate
3396 # - use TLSv1, use a particular certificate, etc.
3397 server_ctx = Context(TLSv1_METHOD)
Alex Gaynor43307782015-09-04 09:05:45 -04003398 server_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE)
Hynek Schlawack35618382015-09-05 21:54:25 +02003399 server_ctx.set_verify(
3400 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT | VERIFY_CLIENT_ONCE,
3401 verify_cb
3402 )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003403 server_store = server_ctx.get_cert_store()
Hynek Schlawack35618382015-09-05 21:54:25 +02003404 server_ctx.use_privatekey(
3405 load_privatekey(FILETYPE_PEM, server_key_pem))
3406 server_ctx.use_certificate(
3407 load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003408 server_ctx.check_privatekey()
3409 server_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Hynek Schlawack35618382015-09-05 21:54:25 +02003410 # Here the Connection is actually created. If None is passed as the
3411 # 2nd parameter, it indicates a memory BIO should be created.
Rick Deanb1ccd562009-07-09 23:52:39 -05003412 server_conn = Connection(server_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003413 server_conn.set_accept_state()
3414 return server_conn
3415
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003416 def _client(self, sock):
3417 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003418 Create a new client-side SSL :py:obj:`Connection` object wrapped around
3419 :py:obj:`sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003420 """
3421 # Now create the client side Connection. Similar boilerplate to the
3422 # above.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003423 client_ctx = Context(TLSv1_METHOD)
Alex Gaynor43307782015-09-04 09:05:45 -04003424 client_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE)
Hynek Schlawack35618382015-09-05 21:54:25 +02003425 client_ctx.set_verify(
3426 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT | VERIFY_CLIENT_ONCE,
3427 verify_cb
3428 )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003429 client_store = client_ctx.get_cert_store()
Hynek Schlawack35618382015-09-05 21:54:25 +02003430 client_ctx.use_privatekey(
3431 load_privatekey(FILETYPE_PEM, client_key_pem))
3432 client_ctx.use_certificate(
3433 load_certificate(FILETYPE_PEM, client_cert_pem))
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003434 client_ctx.check_privatekey()
3435 client_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05003436 client_conn = Connection(client_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003437 client_conn.set_connect_state()
3438 return client_conn
3439
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003440 def test_memoryConnect(self):
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003441 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003442 Two :py:obj:`Connection`s which use memory BIOs can be manually
3443 connected by reading from the output of each and writing those bytes to
3444 the input of the other and in this way establish a connection and
3445 exchange application-level bytes with each other.
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003446 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003447 server_conn = self._server(None)
3448 client_conn = self._client(None)
Rick Deanb71c0d22009-04-01 14:09:23 -05003449
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003450 # There should be no key or nonces yet.
3451 self.assertIdentical(server_conn.master_key(), None)
3452 self.assertIdentical(server_conn.client_random(), None)
3453 self.assertIdentical(server_conn.server_random(), None)
Rick Deanb71c0d22009-04-01 14:09:23 -05003454
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003455 # First, the handshake needs to happen. We'll deliver bytes back and
3456 # forth between the client and server until neither of them feels like
3457 # speaking any more.
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003458 self.assertIdentical(
3459 self._interactInMemory(client_conn, server_conn), None)
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003460
3461 # Now that the handshake is done, there should be a key and nonces.
3462 self.assertNotIdentical(server_conn.master_key(), None)
3463 self.assertNotIdentical(server_conn.client_random(), None)
3464 self.assertNotIdentical(server_conn.server_random(), None)
Hynek Schlawack35618382015-09-05 21:54:25 +02003465 self.assertEquals(
3466 server_conn.client_random(), client_conn.client_random())
3467 self.assertEquals(
3468 server_conn.server_random(), client_conn.server_random())
3469 self.assertNotEquals(
3470 server_conn.client_random(), server_conn.server_random())
3471 self.assertNotEquals(
3472 client_conn.client_random(), client_conn.server_random())
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003473
3474 # Here are the bytes we'll try to send.
Alex Gaynore7f51982016-09-11 11:48:14 -04003475 important_message = b'One if by land, two if by sea.'
Rick Deanb71c0d22009-04-01 14:09:23 -05003476
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003477 server_conn.write(important_message)
3478 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003479 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003480 (client_conn, important_message))
3481
3482 client_conn.write(important_message[::-1])
3483 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003484 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003485 (server_conn, important_message[::-1]))
Rick Deanb71c0d22009-04-01 14:09:23 -05003486
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003487 def test_socketConnect(self):
Rick Deanb1ccd562009-07-09 23:52:39 -05003488 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003489 Just like :py:obj:`test_memoryConnect` but with an actual socket.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003490
Hynek Schlawack35618382015-09-05 21:54:25 +02003491 This is primarily to rule out the memory BIO code as the source of any
3492 problems encountered while passing data over a :py:obj:`Connection` (if
3493 this test fails, there must be a problem outside the memory BIO code,
3494 as no memory BIO is involved here). Even though this isn't a memory
3495 BIO test, it's convenient to have it here.
Rick Deanb1ccd562009-07-09 23:52:39 -05003496 """
Jean-Paul Calderone06c7cc92010-09-24 23:52:00 -04003497 server_conn, client_conn = self._loopback()
Rick Deanb1ccd562009-07-09 23:52:39 -05003498
Alex Gaynore7f51982016-09-11 11:48:14 -04003499 important_message = b"Help me Obi Wan Kenobi, you're my only hope."
Rick Deanb1ccd562009-07-09 23:52:39 -05003500 client_conn.send(important_message)
3501 msg = server_conn.recv(1024)
3502 self.assertEqual(msg, important_message)
3503
3504 # Again in the other direction, just for fun.
3505 important_message = important_message[::-1]
3506 server_conn.send(important_message)
3507 msg = client_conn.recv(1024)
3508 self.assertEqual(msg, important_message)
3509
Jean-Paul Calderonefc4ed0f2009-04-27 11:51:27 -04003510 def test_socketOverridesMemory(self):
Rick Deanb71c0d22009-04-01 14:09:23 -05003511 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003512 Test that :py:obj:`OpenSSL.SSL.bio_read` and
3513 :py:obj:`OpenSSL.SSL.bio_write` don't work on
3514 :py:obj:`OpenSSL.SSL.Connection`() that use sockets.
Rick Deanb71c0d22009-04-01 14:09:23 -05003515 """
Alex Gaynor51d424c2016-09-10 14:50:11 -04003516 context = Context(TLSv1_METHOD)
Rick Deanb71c0d22009-04-01 14:09:23 -05003517 client = socket()
3518 clientSSL = Connection(context, client)
Alex Gaynor43307782015-09-04 09:05:45 -04003519 self.assertRaises(TypeError, clientSSL.bio_read, 100)
3520 self.assertRaises(TypeError, clientSSL.bio_write, "foo")
Alex Gaynor7e8b61e2015-09-04 13:13:05 -04003521 self.assertRaises(TypeError, clientSSL.bio_shutdown)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003522
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003523 def test_outgoingOverflow(self):
3524 """
3525 If more bytes than can be written to the memory BIO are passed to
Hynek Schlawack35618382015-09-05 21:54:25 +02003526 :py:obj:`Connection.send` at once, the number of bytes which were
3527 written is returned and that many bytes from the beginning of the input
3528 can be read from the other end of the connection.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003529 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003530 server = self._server(None)
3531 client = self._client(None)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003532
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003533 self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003534
3535 size = 2 ** 15
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003536 sent = client.send(b"x" * size)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003537 # Sanity check. We're trying to test what happens when the entire
3538 # input can't be sent. If the entire input was sent, this test is
3539 # meaningless.
3540 self.assertTrue(sent < size)
3541
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003542 receiver, received = self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003543 self.assertIdentical(receiver, server)
3544
3545 # We can rely on all of these bytes being received at once because
3546 # _loopback passes 2 ** 16 to recv - more than 2 ** 15.
3547 self.assertEquals(len(received), sent)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003548
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003549 def test_shutdown(self):
3550 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003551 :py:obj:`Connection.bio_shutdown` signals the end of the data stream
3552 from which the :py:obj:`Connection` reads.
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003553 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003554 server = self._server(None)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003555 server.bio_shutdown()
3556 e = self.assertRaises(Error, server.recv, 1024)
3557 # We don't want WantReadError or ZeroReturnError or anything - it's a
3558 # handshake failure.
Alex Gaynor5af32d02016-09-24 01:52:21 -04003559 assert type(e) in [Error, SysCallError]
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003560
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003561 def test_unexpectedEndOfFile(self):
3562 """
3563 If the connection is lost before an orderly SSL shutdown occurs,
3564 :py:obj:`OpenSSL.SSL.SysCallError` is raised with a message of
3565 "Unexpected EOF".
3566 """
3567 server_conn, client_conn = self._loopback()
3568 client_conn.sock_shutdown(SHUT_RDWR)
3569 exc = self.assertRaises(SysCallError, server_conn.recv, 1024)
3570 self.assertEqual(exc.args, (-1, "Unexpected EOF"))
3571
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003572 def _check_client_ca_list(self, func):
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003573 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003574 Verify the return value of the :py:obj:`get_client_ca_list` method for
3575 server and client connections.
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003576
Jonathan Ballet78b92a22011-07-16 08:07:26 +09003577 :param func: A function which will be called with the server context
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003578 before the client and server are connected to each other. This
3579 function should specify a list of CAs for the server to send to the
3580 client and return that same list. The list will be used to verify
Hynek Schlawack35618382015-09-05 21:54:25 +02003581 that :py:obj:`get_client_ca_list` returns the proper value at
3582 various times.
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003583 """
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003584 server = self._server(None)
3585 client = self._client(None)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003586 self.assertEqual(client.get_client_ca_list(), [])
3587 self.assertEqual(server.get_client_ca_list(), [])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003588 ctx = server.get_context()
3589 expected = func(ctx)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003590 self.assertEqual(client.get_client_ca_list(), [])
3591 self.assertEqual(server.get_client_ca_list(), expected)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003592 self._interactInMemory(client, server)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003593 self.assertEqual(client.get_client_ca_list(), expected)
3594 self.assertEqual(server.get_client_ca_list(), expected)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003595
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003596 def test_set_client_ca_list_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003597 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003598 :py:obj:`Context.set_client_ca_list` raises a :py:obj:`TypeError` if
3599 called with a non-list or a list that contains objects other than
3600 X509Names.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003601 """
3602 ctx = Context(TLSv1_METHOD)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003603 self.assertRaises(TypeError, ctx.set_client_ca_list, "spam")
3604 self.assertRaises(TypeError, ctx.set_client_ca_list, ["spam"])
3605 self.assertIdentical(ctx.set_client_ca_list([]), None)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003606
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003607 def test_set_empty_ca_list(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003608 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003609 If passed an empty list, :py:obj:`Context.set_client_ca_list`
3610 configures the context to send no CA names to the client and, on both
3611 the server and client sides, :py:obj:`Connection.get_client_ca_list`
3612 returns an empty list after the connection is set up.
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003613 """
3614 def no_ca(ctx):
3615 ctx.set_client_ca_list([])
3616 return []
3617 self._check_client_ca_list(no_ca)
3618
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003619 def test_set_one_ca_list(self):
3620 """
3621 If passed a list containing a single X509Name,
Hynek Schlawack35618382015-09-05 21:54:25 +02003622 :py:obj:`Context.set_client_ca_list` configures the context to send
3623 that CA name to the client and, on both the server and client sides,
Jonathan Ballet648875f2011-07-16 14:14:58 +09003624 :py:obj:`Connection.get_client_ca_list` returns a list containing that
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003625 X509Name after the connection is set up.
3626 """
3627 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3628 cadesc = cacert.get_subject()
Hynek Schlawack35618382015-09-05 21:54:25 +02003629
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003630 def single_ca(ctx):
3631 ctx.set_client_ca_list([cadesc])
3632 return [cadesc]
3633 self._check_client_ca_list(single_ca)
3634
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003635 def test_set_multiple_ca_list(self):
3636 """
3637 If passed a list containing multiple X509Name objects,
Hynek Schlawack35618382015-09-05 21:54:25 +02003638 :py:obj:`Context.set_client_ca_list` configures the context to send
3639 those CA names to the client and, on both the server and client sides,
Jonathan Ballet648875f2011-07-16 14:14:58 +09003640 :py:obj:`Connection.get_client_ca_list` returns a list containing those
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003641 X509Names after the connection is set up.
3642 """
3643 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3644 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3645
3646 sedesc = secert.get_subject()
3647 cldesc = clcert.get_subject()
3648
3649 def multiple_ca(ctx):
3650 L = [sedesc, cldesc]
3651 ctx.set_client_ca_list(L)
3652 return L
3653 self._check_client_ca_list(multiple_ca)
3654
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003655 def test_reset_ca_list(self):
3656 """
3657 If called multiple times, only the X509Names passed to the final call
Hynek Schlawack35618382015-09-05 21:54:25 +02003658 of :py:obj:`Context.set_client_ca_list` are used to configure the CA
3659 names sent to the client.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003660 """
3661 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3662 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3663 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3664
3665 cadesc = cacert.get_subject()
3666 sedesc = secert.get_subject()
3667 cldesc = clcert.get_subject()
3668
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003669 def changed_ca(ctx):
3670 ctx.set_client_ca_list([sedesc, cldesc])
3671 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003672 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003673 self._check_client_ca_list(changed_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003674
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003675 def test_mutated_ca_list(self):
3676 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003677 If the list passed to :py:obj:`Context.set_client_ca_list` is mutated
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003678 afterwards, this does not affect the list of CA names sent to the
3679 client.
3680 """
3681 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3682 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3683
3684 cadesc = cacert.get_subject()
3685 sedesc = secert.get_subject()
3686
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003687 def mutated_ca(ctx):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003688 L = [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003689 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003690 L.append(sedesc)
3691 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003692 self._check_client_ca_list(mutated_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003693
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003694 def test_add_client_ca_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003695 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003696 :py:obj:`Context.add_client_ca` raises :py:obj:`TypeError` if called
3697 with a non-X509 object or with a number of arguments other than one.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003698 """
3699 ctx = Context(TLSv1_METHOD)
3700 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003701 self.assertRaises(TypeError, ctx.add_client_ca)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003702 self.assertRaises(TypeError, ctx.add_client_ca, "spam")
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003703 self.assertRaises(TypeError, ctx.add_client_ca, cacert, cacert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003704
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003705 def test_one_add_client_ca(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003706 """
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003707 A certificate's subject can be added as a CA to be sent to the client
Jonathan Ballet648875f2011-07-16 14:14:58 +09003708 with :py:obj:`Context.add_client_ca`.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003709 """
3710 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3711 cadesc = cacert.get_subject()
Hynek Schlawack35618382015-09-05 21:54:25 +02003712
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003713 def single_ca(ctx):
3714 ctx.add_client_ca(cacert)
3715 return [cadesc]
3716 self._check_client_ca_list(single_ca)
3717
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003718 def test_multiple_add_client_ca(self):
3719 """
3720 Multiple CA names can be sent to the client by calling
Jonathan Ballet648875f2011-07-16 14:14:58 +09003721 :py:obj:`Context.add_client_ca` with multiple X509 objects.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003722 """
3723 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3724 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3725
3726 cadesc = cacert.get_subject()
3727 sedesc = secert.get_subject()
3728
3729 def multiple_ca(ctx):
3730 ctx.add_client_ca(cacert)
3731 ctx.add_client_ca(secert)
3732 return [cadesc, sedesc]
3733 self._check_client_ca_list(multiple_ca)
3734
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003735 def test_set_and_add_client_ca(self):
3736 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003737 A call to :py:obj:`Context.set_client_ca_list` followed by a call to
Hynek Schlawack35618382015-09-05 21:54:25 +02003738 :py:obj:`Context.add_client_ca` results in using the CA names from the
3739 first call and the CA name from the second call.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003740 """
3741 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3742 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3743 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3744
3745 cadesc = cacert.get_subject()
3746 sedesc = secert.get_subject()
3747 cldesc = clcert.get_subject()
3748
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003749 def mixed_set_add_ca(ctx):
3750 ctx.set_client_ca_list([cadesc, sedesc])
3751 ctx.add_client_ca(clcert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003752 return [cadesc, sedesc, cldesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003753 self._check_client_ca_list(mixed_set_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003754
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003755 def test_set_after_add_client_ca(self):
3756 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003757 A call to :py:obj:`Context.set_client_ca_list` after a call to
Hynek Schlawack35618382015-09-05 21:54:25 +02003758 :py:obj:`Context.add_client_ca` replaces the CA name specified by the
3759 former call with the names specified by the latter call.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003760 """
3761 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3762 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3763 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3764
3765 cadesc = cacert.get_subject()
3766 sedesc = secert.get_subject()
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003767
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003768 def set_replaces_add_ca(ctx):
3769 ctx.add_client_ca(clcert)
3770 ctx.set_client_ca_list([cadesc])
3771 ctx.add_client_ca(secert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003772 return [cadesc, sedesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003773 self._check_client_ca_list(set_replaces_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003774
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003775
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003776class ConnectionBIOTests(TestCase):
3777 """
3778 Tests for :py:obj:`Connection.bio_read` and :py:obj:`Connection.bio_write`.
3779 """
3780 def test_wantReadError(self):
3781 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003782 :py:obj:`Connection.bio_read` raises
3783 :py:obj:`OpenSSL.SSL.WantReadError` if there are no bytes available to
3784 be read from the BIO.
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003785 """
3786 ctx = Context(TLSv1_METHOD)
3787 conn = Connection(ctx, None)
3788 self.assertRaises(WantReadError, conn.bio_read, 1024)
3789
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003790 def test_buffer_size(self):
3791 """
3792 :py:obj:`Connection.bio_read` accepts an integer giving the maximum
3793 number of bytes to read and return.
3794 """
3795 ctx = Context(TLSv1_METHOD)
3796 conn = Connection(ctx, None)
3797 conn.set_connect_state()
3798 try:
3799 conn.do_handshake()
3800 except WantReadError:
3801 pass
3802 data = conn.bio_read(2)
3803 self.assertEqual(2, len(data))
3804
Hynek Schlawack35618382015-09-05 21:54:25 +02003805 @skip_if_py3
3806 def test_buffer_size_long(self):
3807 """
3808 On Python 2 :py:obj:`Connection.bio_read` accepts values of type
3809 :py:obj:`long` as well as :py:obj:`int`.
3810 """
3811 ctx = Context(TLSv1_METHOD)
3812 conn = Connection(ctx, None)
3813 conn.set_connect_state()
3814 try:
3815 conn.do_handshake()
3816 except WantReadError:
3817 pass
3818 data = conn.bio_read(long(2))
3819 self.assertEqual(2, len(data))
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003820
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003821
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003822class InfoConstantTests(TestCase):
3823 """
3824 Tests for assorted constants exposed for use in info callbacks.
3825 """
3826 def test_integers(self):
3827 """
3828 All of the info constants are integers.
3829
3830 This is a very weak test. It would be nice to have one that actually
3831 verifies that as certain info events happen, the value passed to the
3832 info callback matches up with the constant exposed by OpenSSL.SSL.
3833 """
3834 for const in [
Alex Gaynor5af32d02016-09-24 01:52:21 -04003835 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK,
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003836 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
3837 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
3838 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
Hynek Schlawack35618382015-09-05 21:54:25 +02003839 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE
3840 ]:
Alex Gaynor5af32d02016-09-24 01:52:21 -04003841 assert isinstance(const, int)
3842
3843 # These constants don't exist on OpenSSL 1.1.0
3844 for const in [
3845 SSL_ST_INIT, SSL_ST_BEFORE, SSL_ST_OK, SSL_ST_RENEGOTIATE
3846 ]:
3847 assert const is None or isinstance(const, int)
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003848
Ziga Seilnacht44611bf2009-08-31 20:49:30 +02003849
Cory Benfield1d142142016-03-30 11:51:45 +01003850class TestRequires(object):
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003851 """
3852 Tests for the decorator factory used to conditionally raise
Cory Benfield1d142142016-03-30 11:51:45 +01003853 NotImplementedError when older OpenSSLs are used.
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003854 """
3855 def test_available(self):
3856 """
3857 When the OpenSSL functionality is available the decorated functions
3858 work appropriately.
3859 """
3860 feature_guard = _make_requires(True, "Error text")
3861 results = []
3862
3863 @feature_guard
3864 def inner():
3865 results.append(True)
3866 return True
3867
Cory Benfield2333e5e2016-03-30 14:24:16 +01003868 assert inner() is True
3869 assert [True] == results
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003870
3871 def test_unavailable(self):
3872 """
3873 When the OpenSSL functionality is not available the decorated function
3874 does not execute and NotImplementedError is raised.
3875 """
3876 feature_guard = _make_requires(False, "Error text")
3877 results = []
3878
3879 @feature_guard
3880 def inner():
3881 results.append(True)
3882 return True
3883
Cory Benfield1d142142016-03-30 11:51:45 +01003884 with pytest.raises(NotImplementedError) as e:
3885 inner()
3886
3887 assert "Error text" in str(e.value)
Cory Benfield2333e5e2016-03-30 14:24:16 +01003888 assert results == []