blob: 9d41899af82142ed226a887c1445a697c43ab8c1 [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 Calderone0b88b6a2009-07-05 12:44:41 -040017from unittest import main
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -040018from weakref import ref
Abraham Martinef063482015-03-25 14:06:24 +000019from warnings import catch_warnings, simplefilter
Jean-Paul Calderone460cc1f2009-03-07 11:31:12 -050020
Hynek Schlawack734d3022015-09-05 19:19:32 +020021import pytest
22
Hynek Schlawackf90e3682016-03-11 11:21:13 +010023from six import PY3, text_type
Jean-Paul Calderonec76c61c2014-01-18 13:21:52 -050024
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +010025from cryptography import x509
26from cryptography.hazmat.backends import default_backend
27from cryptography.hazmat.primitives import hashes
28from cryptography.hazmat.primitives import serialization
29from cryptography.hazmat.primitives.asymmetric import rsa
30from cryptography.x509.oid import NameOID
31
32
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040033from OpenSSL.crypto import TYPE_RSA, FILETYPE_PEM
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -080034from OpenSSL.crypto import PKey, X509, X509Extension, X509Store
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040035from OpenSSL.crypto import dump_privatekey, load_privatekey
36from OpenSSL.crypto import dump_certificate, load_certificate
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -040037from OpenSSL.crypto import get_elliptic_curves
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040038
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -040039from OpenSSL.SSL import OPENSSL_VERSION_NUMBER, SSLEAY_VERSION, SSLEAY_CFLAGS
40from OpenSSL.SSL import SSLEAY_PLATFORM, SSLEAY_DIR, SSLEAY_BUILT_ON
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -040041from OpenSSL.SSL import SENT_SHUTDOWN, RECEIVED_SHUTDOWN
Jean-Paul Calderone1461c492013-10-03 16:05:00 -040042from OpenSSL.SSL import (
43 SSLv2_METHOD, SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD,
44 TLSv1_1_METHOD, TLSv1_2_METHOD)
45from OpenSSL.SSL import OP_SINGLE_DH_USE, OP_NO_SSLv2, OP_NO_SSLv3
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040046from OpenSSL.SSL import (
47 VERIFY_PEER, VERIFY_FAIL_IF_NO_PEER_CERT, VERIFY_CLIENT_ONCE, VERIFY_NONE)
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040048
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040049from OpenSSL.SSL import (
Jean-Paul Calderone313bf012012-02-08 13:02:49 -050050 SESS_CACHE_OFF, SESS_CACHE_CLIENT, SESS_CACHE_SERVER, SESS_CACHE_BOTH,
51 SESS_CACHE_NO_AUTO_CLEAR, SESS_CACHE_NO_INTERNAL_LOOKUP,
52 SESS_CACHE_NO_INTERNAL_STORE, SESS_CACHE_NO_INTERNAL)
53
54from OpenSSL.SSL import (
Jean-Paul Calderoned899af02013-03-19 22:10:37 -070055 Error, SysCallError, WantReadError, WantWriteError, ZeroReturnError)
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -050056from OpenSSL.SSL import (
Jean-Paul Calderoned899af02013-03-19 22:10:37 -070057 Context, ContextType, Session, Connection, ConnectionType, SSLeay_version)
Cory Benfield0ba57ec2016-03-30 09:35:05 +010058from OpenSSL.SSL import _make_requires
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040059
Cory Benfieldba1820d2015-04-13 17:39:12 -040060from OpenSSL._util import lib as _lib
61
Jean-Paul Calderone4bccf5e2008-12-28 22:50:42 -050062try:
63 from OpenSSL.SSL import OP_NO_QUERY_MTU
64except ImportError:
65 OP_NO_QUERY_MTU = None
66try:
67 from OpenSSL.SSL import OP_COOKIE_EXCHANGE
68except ImportError:
69 OP_COOKIE_EXCHANGE = None
70try:
71 from OpenSSL.SSL import OP_NO_TICKET
72except ImportError:
73 OP_NO_TICKET = None
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -040074
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040075try:
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -040076 from OpenSSL.SSL import OP_NO_COMPRESSION
77except ImportError:
78 OP_NO_COMPRESSION = None
79
80try:
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040081 from OpenSSL.SSL import MODE_RELEASE_BUFFERS
82except ImportError:
83 MODE_RELEASE_BUFFERS = None
84
Jean-Paul Calderone1461c492013-10-03 16:05:00 -040085try:
86 from OpenSSL.SSL import OP_NO_TLSv1, OP_NO_TLSv1_1, OP_NO_TLSv1_2
87except ImportError:
88 OP_NO_TLSv1 = OP_NO_TLSv1_1 = OP_NO_TLSv1_2 = None
89
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -040090from OpenSSL.SSL import (
91 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK, SSL_ST_INIT, SSL_ST_BEFORE,
92 SSL_ST_OK, SSL_ST_RENEGOTIATE,
93 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
94 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
95 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
96 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE)
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -040097
Hynek Schlawackf0e66852015-10-16 20:18:38 +020098from .util import WARNING_TYPE_EXPECTED, NON_ASCII, TestCase, b
99from .test_crypto import (
100 cleartextCertificatePEM, cleartextPrivateKeyPEM,
101 client_cert_pem, client_key_pem, server_cert_pem, server_key_pem,
102 root_cert_pem)
103
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200104
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -0400105# openssl dhparam 128 -out dh-128.pem (note that 128 is a small number of bits
106# to use)
107dhparam = """\
108-----BEGIN DH PARAMETERS-----
109MBYCEQCobsg29c9WZP/54oAPcwiDAgEC
110-----END DH PARAMETERS-----
111"""
112
113
Hynek Schlawackb4f02402015-09-05 20:48:34 +0200114skip_if_py3 = pytest.mark.skipif(PY3, reason="Python 2 only")
Hynek Schlawackf8979a52015-09-05 21:25:25 +0200115skip_if_py26 = pytest.mark.skipif(
116 version_info[0:2] == (2, 6),
117 reason="Python 2.7 and later only"
118)
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200119
120
Jean-Paul Calderone05826732015-04-12 11:38:49 -0400121def join_bytes_or_unicode(prefix, suffix):
122 """
123 Join two path components of either ``bytes`` or ``unicode``.
124
125 The return type is the same as the type of ``prefix``.
126 """
127 # If the types are the same, nothing special is necessary.
128 if type(prefix) == type(suffix):
129 return join(prefix, suffix)
130
131 # Otherwise, coerce suffix to the type of prefix.
132 if isinstance(prefix, text_type):
133 return join(prefix, suffix.decode(getfilesystemencoding()))
134 else:
135 return join(prefix, suffix.encode(getfilesystemencoding()))
136
137
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400138def verify_cb(conn, cert, errnum, depth, ok):
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400139 return ok
140
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400141
Rick Deanb1ccd562009-07-09 23:52:39 -0500142def socket_pair():
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400143 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400144 Establish and return a pair of network sockets connected to each other.
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400145 """
146 # Connect a pair of sockets
Rick Deanb1ccd562009-07-09 23:52:39 -0500147 port = socket()
148 port.bind(('', 0))
149 port.listen(1)
150 client = socket()
151 client.setblocking(False)
Jean-Paul Calderonef23c5d92009-07-23 17:58:15 -0400152 client.connect_ex(("127.0.0.1", port.getsockname()[1]))
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400153 client.setblocking(True)
Rick Deanb1ccd562009-07-09 23:52:39 -0500154 server = port.accept()[0]
Rick Deanb1ccd562009-07-09 23:52:39 -0500155
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400156 # Let's pass some unencrypted data to make sure our socket connection is
157 # fine. Just one byte, so we don't have to worry about buffers getting
158 # filled up or fragmentation.
Jean-Paul Calderone9e4eeae2010-08-22 21:32:52 -0400159 server.send(b("x"))
160 assert client.recv(1024) == b("x")
161 client.send(b("y"))
162 assert server.recv(1024) == b("y")
Rick Deanb1ccd562009-07-09 23:52:39 -0500163
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -0400164 # Most of our callers want non-blocking sockets, make it easy for them.
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400165 server.setblocking(False)
166 client.setblocking(False)
Jim Shaver46f28912015-05-29 19:32:16 -0400167
Rick Deanb1ccd562009-07-09 23:52:39 -0500168 return (server, client)
169
170
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400171def handshake(client, server):
172 conns = [client, server]
173 while conns:
174 for conn in conns:
175 try:
176 conn.do_handshake()
177 except WantReadError:
178 pass
179 else:
180 conns.remove(conn)
181
182
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400183def _create_certificate_chain():
184 """
185 Construct and return a chain of certificates.
186
187 1. A new self-signed certificate authority certificate (cacert)
188 2. A new intermediate certificate signed by cacert (icert)
189 3. A new server certificate signed by icert (scert)
190 """
191 caext = X509Extension(b('basicConstraints'), False, b('CA:true'))
192
193 # Step 1
194 cakey = PKey()
195 cakey.generate_key(TYPE_RSA, 512)
196 cacert = X509()
197 cacert.get_subject().commonName = "Authority Certificate"
198 cacert.set_issuer(cacert.get_subject())
199 cacert.set_pubkey(cakey)
200 cacert.set_notBefore(b("20000101000000Z"))
201 cacert.set_notAfter(b("20200101000000Z"))
202 cacert.add_extensions([caext])
203 cacert.set_serial_number(0)
204 cacert.sign(cakey, "sha1")
205
206 # Step 2
207 ikey = PKey()
208 ikey.generate_key(TYPE_RSA, 512)
209 icert = X509()
210 icert.get_subject().commonName = "Intermediate Certificate"
211 icert.set_issuer(cacert.get_subject())
212 icert.set_pubkey(ikey)
213 icert.set_notBefore(b("20000101000000Z"))
214 icert.set_notAfter(b("20200101000000Z"))
215 icert.add_extensions([caext])
216 icert.set_serial_number(0)
217 icert.sign(cakey, "sha1")
218
219 # Step 3
220 skey = PKey()
221 skey.generate_key(TYPE_RSA, 512)
222 scert = X509()
223 scert.get_subject().commonName = "Server Certificate"
224 scert.set_issuer(icert.get_subject())
225 scert.set_pubkey(skey)
226 scert.set_notBefore(b("20000101000000Z"))
227 scert.set_notAfter(b("20200101000000Z"))
228 scert.add_extensions([
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200229 X509Extension(b('basicConstraints'), True, b('CA:false'))])
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400230 scert.set_serial_number(0)
231 scert.sign(ikey, "sha1")
232
233 return [(cakey, cacert), (ikey, icert), (skey, scert)]
234
235
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400236class _LoopbackMixin:
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400237 """
238 Helper mixin which defines methods for creating a connected socket pair and
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200239 for forcing two connected SSL sockets to talk to each other via memory
240 BIOs.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400241 """
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500242 def _loopbackClientFactory(self, socket):
243 client = Connection(Context(TLSv1_METHOD), socket)
244 client.set_connect_state()
245 return client
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400246
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500247 def _loopbackServerFactory(self, socket):
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400248 ctx = Context(TLSv1_METHOD)
249 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
250 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500251 server = Connection(ctx, socket)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400252 server.set_accept_state()
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500253 return server
254
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500255 def _loopback(self, serverFactory=None, clientFactory=None):
256 if serverFactory is None:
257 serverFactory = self._loopbackServerFactory
258 if clientFactory is None:
259 clientFactory = self._loopbackClientFactory
260
261 (server, client) = socket_pair()
262 server = serverFactory(server)
263 client = clientFactory(client)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400264
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400265 handshake(client, server)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400266
267 server.setblocking(True)
268 client.setblocking(True)
269 return server, client
270
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400271 def _interactInMemory(self, client_conn, server_conn):
272 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900273 Try to read application bytes from each of the two :py:obj:`Connection`
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400274 objects. Copy bytes back and forth between their send/receive buffers
275 for as long as there is anything to copy. When there is nothing more
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200276 to copy, return :py:obj:`None`. If one of them actually manages to
277 deliver some application bytes, return a two-tuple of the connection
278 from which the bytes were read and the bytes themselves.
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400279 """
280 wrote = True
281 while wrote:
282 # Loop until neither side has anything to say
283 wrote = False
284
285 # Copy stuff from each side's send buffer to the other side's
286 # receive buffer.
287 for (read, write) in [(client_conn, server_conn),
288 (server_conn, client_conn)]:
289
290 # Give the side a chance to generate some more bytes, or
291 # succeed.
292 try:
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400293 data = read.recv(2 ** 16)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400294 except WantReadError:
295 # It didn't succeed, so we'll hope it generated some
296 # output.
297 pass
298 else:
299 # It did succeed, so we'll stop now and let the caller deal
300 # with it.
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400301 return (read, data)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400302
303 while True:
304 # Keep copying as long as there's more stuff there.
305 try:
306 dirty = read.bio_read(4096)
307 except WantReadError:
308 # Okay, nothing more waiting to be sent. Stop
309 # processing this send buffer.
310 break
311 else:
312 # Keep track of the fact that someone generated some
313 # output.
314 wrote = True
315 write.bio_write(dirty)
316
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -0400317 def _handshakeInMemory(self, client_conn, server_conn):
Jean-Paul Calderoneb2b40782014-05-06 08:47:40 -0400318 """
319 Perform the TLS handshake between two :py:class:`Connection` instances
320 connected to each other via memory BIOs.
321 """
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -0400322 client_conn.set_connect_state()
323 server_conn.set_accept_state()
324
325 for conn in [client_conn, server_conn]:
326 try:
327 conn.do_handshake()
328 except WantReadError:
329 pass
330
331 self._interactInMemory(client_conn, server_conn)
332
333
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400334class VersionTests(TestCase):
335 """
336 Tests for version information exposed by
Jonathan Ballet648875f2011-07-16 14:14:58 +0900337 :py:obj:`OpenSSL.SSL.SSLeay_version` and
338 :py:obj:`OpenSSL.SSL.OPENSSL_VERSION_NUMBER`.
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400339 """
340 def test_OPENSSL_VERSION_NUMBER(self):
341 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900342 :py:obj:`OPENSSL_VERSION_NUMBER` is an integer with status in the low
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400343 byte and the patch, fix, minor, and major versions in the
344 nibbles above that.
345 """
346 self.assertTrue(isinstance(OPENSSL_VERSION_NUMBER, int))
347
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400348 def test_SSLeay_version(self):
349 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900350 :py:obj:`SSLeay_version` takes a version type indicator and returns
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400351 one of a number of version strings based on that indicator.
352 """
353 versions = {}
354 for t in [SSLEAY_VERSION, SSLEAY_CFLAGS, SSLEAY_BUILT_ON,
355 SSLEAY_PLATFORM, SSLEAY_DIR]:
356 version = SSLeay_version(t)
357 versions[version] = t
358 self.assertTrue(isinstance(version, bytes))
359 self.assertEqual(len(versions), 5)
360
361
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100362@pytest.fixture
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100363def ca_file(tmpdir):
364 """
365 Create a valid PEM file with CA certificates and return the path.
366 """
367 key = rsa.generate_private_key(
368 public_exponent=65537,
369 key_size=2048,
370 backend=default_backend()
371 )
372 public_key = key.public_key()
373
374 builder = x509.CertificateBuilder()
375 builder = builder.subject_name(x509.Name([
376 x509.NameAttribute(NameOID.COMMON_NAME, u"pyopenssl.org"),
377 ]))
378 builder = builder.issuer_name(x509.Name([
379 x509.NameAttribute(NameOID.COMMON_NAME, u"pyopenssl.org"),
380 ]))
381 one_day = datetime.timedelta(1, 0, 0)
382 builder = builder.not_valid_before(datetime.datetime.today() - one_day)
383 builder = builder.not_valid_after(datetime.datetime.today() + one_day)
384 builder = builder.serial_number(int(uuid.uuid4()))
385 builder = builder.public_key(public_key)
386 builder = builder.add_extension(
387 x509.BasicConstraints(ca=True, path_length=None), critical=True,
388 )
389
390 certificate = builder.sign(
391 private_key=key, algorithm=hashes.SHA256(),
392 backend=default_backend()
393 )
394
395 ca_file = tmpdir.join("test.pem")
396 ca_file.write_binary(
397 certificate.public_bytes(
398 encoding=serialization.Encoding.PEM,
399 )
400 )
401
402 return str(ca_file).encode("ascii")
403
404
405@pytest.fixture
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100406def context():
407 """
408 A simple TLS 1.0 context.
409 """
410 return Context(TLSv1_METHOD)
411
412
413class TestContext(object):
Hynek Schlawackaa861212016-03-13 13:53:48 +0100414 """
415 py.test-based tests for :class:`OpenSSL.SSL.Context`.
416
417 If possible, add new tests here.
418 """
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100419 @pytest.mark.parametrize("cipher_string", [
420 b"hello world:AES128-SHA",
421 u"hello world:AES128-SHA",
422 ])
423 def test_set_cipher_list(self, context, cipher_string):
424 """
Hynek Schlawacka7a63af2016-03-11 12:05:26 +0100425 :meth:`Context.set_cipher_list` accepts both byte and unicode strings
426 for naming the ciphers which connections created with the context
427 object will be able to choose from.
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100428 """
429 context.set_cipher_list(cipher_string)
430 conn = Connection(context, None)
431
432 assert "AES128-SHA" in conn.get_cipher_list()
433
434 @pytest.mark.parametrize("cipher_list,error", [
435 (object(), TypeError),
436 ("imaginary-cipher", Error),
437 ])
438 def test_set_cipher_list_wrong_args(self, context, cipher_list, error):
439 """
440 :meth:`Context.set_cipher_list` raises :exc:`TypeError` when passed a
441 non-string argument and raises :exc:`OpenSSL.SSL.Error` when passed an
442 incorrect cipher list string.
443 """
444 with pytest.raises(error):
445 context.set_cipher_list(cipher_list)
446
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100447 def test_load_client_ca(self, context, ca_file):
448 """
449 :meth:`Context.load_client_ca` works as far as we can tell.
450 """
451 context.load_client_ca(ca_file)
452
453 def test_load_client_ca_invalid(self, context, tmpdir):
454 """
455 :meth:`Context.load_client_ca` raises an Error if the ca file is
456 invalid.
457 """
458 ca_file = tmpdir.join("test.pem")
459 ca_file.write("")
460
461 with pytest.raises(Error) as e:
462 context.load_client_ca(str(ca_file).encode("ascii"))
463
464 assert "PEM routines" == e.value.args[0][0][0]
465
466 def test_load_client_ca_unicode(self, context, ca_file):
467 """
468 Passing the path as unicode raises a warning but works.
469 """
470 pytest.deprecated_call(
471 context.load_client_ca, ca_file.decode("ascii")
472 )
473
474 def test_set_session_id(self, context):
475 """
476 :meth:`Context.set_session_id` works as far as we can tell.
477 """
478 context.set_session_id(b"abc")
479
480 def test_set_session_id_fail(self, context):
481 """
482 :meth:`Context.set_session_id` errors are propagated.
483 """
484 with pytest.raises(Error) as e:
485 context.set_session_id(b"abc" * 1000)
486
487 assert [
488 ("SSL routines",
489 "SSL_CTX_set_session_id_context",
490 "ssl session id context too long")
491 ] == e.value.args[0]
492
493 def test_set_session_id_unicode(self, context):
494 """
495 :meth:`Context.set_session_id` raises a warning if a unicode string is
496 passed.
497 """
498 pytest.deprecated_call(context.set_session_id, u"abc")
499
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100500
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400501class ContextTests(TestCase, _LoopbackMixin):
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400502 """
Hynek Schlawackaa861212016-03-13 13:53:48 +0100503 Unit tests for :class:`OpenSSL.SSL.Context`.
504
505 If possible, add new tests to :class:`TestContext` above.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400506 """
507 def test_method(self):
508 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200509 :py:obj:`Context` can be instantiated with one of
510 :py:obj:`SSLv2_METHOD`, :py:obj:`SSLv3_METHOD`,
511 :py:obj:`SSLv23_METHOD`, :py:obj:`TLSv1_METHOD`,
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400512 :py:obj:`TLSv1_1_METHOD`, or :py:obj:`TLSv1_2_METHOD`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400513 """
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400514 methods = [
515 SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD]
516 for meth in methods:
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400517 Context(meth)
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400518
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400519 maybe = [SSLv2_METHOD, TLSv1_1_METHOD, TLSv1_2_METHOD]
520 for meth in maybe:
521 try:
522 Context(meth)
523 except (Error, ValueError):
524 # Some versions of OpenSSL have SSLv2 / TLSv1.1 / TLSv1.2, some
525 # don't. Difficult to say in advance.
526 pass
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400527
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400528 self.assertRaises(TypeError, Context, "")
529 self.assertRaises(ValueError, Context, 10)
530
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200531 @skip_if_py3
532 def test_method_long(self):
533 """
534 On Python 2 :py:class:`Context` accepts values of type
535 :py:obj:`long` as well as :py:obj:`int`.
536 """
537 Context(long(TLSv1_METHOD))
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500538
Rick Deane15b1472009-07-09 15:53:42 -0500539 def test_type(self):
540 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200541 :py:obj:`Context` and :py:obj:`ContextType` refer to the same type
542 object and can be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -0500543 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400544 self.assertIdentical(Context, ContextType)
545 self.assertConsistentType(Context, 'Context', TLSv1_METHOD)
Rick Deane15b1472009-07-09 15:53:42 -0500546
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400547 def test_use_privatekey(self):
548 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200549 :py:obj:`Context.use_privatekey` takes an :py:obj:`OpenSSL.crypto.PKey`
550 instance.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400551 """
552 key = PKey()
553 key.generate_key(TYPE_RSA, 128)
554 ctx = Context(TLSv1_METHOD)
555 ctx.use_privatekey(key)
556 self.assertRaises(TypeError, ctx.use_privatekey, "")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400557
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800558 def test_use_privatekey_file_missing(self):
559 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200560 :py:obj:`Context.use_privatekey_file` raises
561 :py:obj:`OpenSSL.SSL.Error` when passed the name of a file which does
562 not exist.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800563 """
564 ctx = Context(TLSv1_METHOD)
565 self.assertRaises(Error, ctx.use_privatekey_file, self.mktemp())
566
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400567 def _use_privatekey_file_test(self, pemfile, filetype):
568 """
569 Verify that calling ``Context.use_privatekey_file`` with the given
570 arguments does not raise an exception.
571 """
572 key = PKey()
573 key.generate_key(TYPE_RSA, 128)
574
575 with open(pemfile, "wt") as pem:
576 pem.write(
577 dump_privatekey(FILETYPE_PEM, key).decode("ascii")
578 )
579
580 ctx = Context(TLSv1_METHOD)
581 ctx.use_privatekey_file(pemfile, filetype)
582
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400583 def test_use_privatekey_file_bytes(self):
584 """
585 A private key can be specified from a file by passing a ``bytes``
586 instance giving the file name to ``Context.use_privatekey_file``.
587 """
588 self._use_privatekey_file_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -0400589 self.mktemp() + NON_ASCII.encode(getfilesystemencoding()),
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400590 FILETYPE_PEM,
591 )
592
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400593 def test_use_privatekey_file_unicode(self):
594 """
595 A private key can be specified from a file by passing a ``unicode``
596 instance giving the file name to ``Context.use_privatekey_file``.
597 """
598 self._use_privatekey_file_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -0400599 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII,
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400600 FILETYPE_PEM,
601 )
602
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200603 @skip_if_py3
604 def test_use_privatekey_file_long(self):
605 """
606 On Python 2 :py:obj:`Context.use_privatekey_file` accepts a
607 filetype of type :py:obj:`long` as well as :py:obj:`int`.
608 """
609 self._use_privatekey_file_test(self.mktemp(), long(FILETYPE_PEM))
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500610
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800611 def test_use_certificate_wrong_args(self):
612 """
613 :py:obj:`Context.use_certificate_wrong_args` raises :py:obj:`TypeError`
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200614 when not passed exactly one :py:obj:`OpenSSL.crypto.X509` instance as
615 an argument.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800616 """
617 ctx = Context(TLSv1_METHOD)
618 self.assertRaises(TypeError, ctx.use_certificate)
619 self.assertRaises(TypeError, ctx.use_certificate, "hello, world")
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200620 self.assertRaises(
621 TypeError, ctx.use_certificate, X509(), "hello, world"
622 )
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800623
624 def test_use_certificate_uninitialized(self):
625 """
626 :py:obj:`Context.use_certificate` raises :py:obj:`OpenSSL.SSL.Error`
627 when passed a :py:obj:`OpenSSL.crypto.X509` instance which has not been
628 initialized (ie, which does not actually have any certificate data).
629 """
630 ctx = Context(TLSv1_METHOD)
631 self.assertRaises(Error, ctx.use_certificate, X509())
632
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800633 def test_use_certificate(self):
634 """
635 :py:obj:`Context.use_certificate` sets the certificate which will be
636 used to identify connections created using the context.
637 """
638 # TODO
639 # Hard to assert anything. But we could set a privatekey then ask
640 # OpenSSL if the cert and key agree using check_privatekey. Then as
641 # long as check_privatekey works right we're good...
642 ctx = Context(TLSv1_METHOD)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200643 ctx.use_certificate(
644 load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
645 )
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800646
647 def test_use_certificate_file_wrong_args(self):
648 """
649 :py:obj:`Context.use_certificate_file` raises :py:obj:`TypeError` if
650 called with zero arguments or more than two arguments, or if the first
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200651 argument is not a byte string or the second argumnent is not an
652 integer.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800653 """
654 ctx = Context(TLSv1_METHOD)
655 self.assertRaises(TypeError, ctx.use_certificate_file)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200656 self.assertRaises(TypeError, ctx.use_certificate_file, b"somefile",
657 object())
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800658 self.assertRaises(
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200659 TypeError, ctx.use_certificate_file, b"somefile", FILETYPE_PEM,
660 object())
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800661 self.assertRaises(
662 TypeError, ctx.use_certificate_file, object(), FILETYPE_PEM)
663 self.assertRaises(
664 TypeError, ctx.use_certificate_file, b"somefile", object())
665
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800666 def test_use_certificate_file_missing(self):
667 """
668 :py:obj:`Context.use_certificate_file` raises
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200669 `:py:obj:`OpenSSL.SSL.Error` if passed the name of a file which does
670 not exist.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800671 """
672 ctx = Context(TLSv1_METHOD)
673 self.assertRaises(Error, ctx.use_certificate_file, self.mktemp())
674
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400675 def _use_certificate_file_test(self, certificate_file):
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800676 """
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400677 Verify that calling ``Context.use_certificate_file`` with the given
678 filename doesn't raise an exception.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800679 """
680 # TODO
681 # Hard to assert anything. But we could set a privatekey then ask
682 # OpenSSL if the cert and key agree using check_privatekey. Then as
683 # long as check_privatekey works right we're good...
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400684 with open(certificate_file, "wb") as pem_file:
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800685 pem_file.write(cleartextCertificatePEM)
686
687 ctx = Context(TLSv1_METHOD)
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400688 ctx.use_certificate_file(certificate_file)
689
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400690 def test_use_certificate_file_bytes(self):
691 """
692 :py:obj:`Context.use_certificate_file` sets the certificate (given as a
693 ``bytes`` filename) which will be used to identify connections created
694 using the context.
695 """
Hynek Schlawack4813c0e2015-04-16 13:38:01 -0400696 filename = self.mktemp() + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400697 self._use_certificate_file_test(filename)
698
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400699 def test_use_certificate_file_unicode(self):
700 """
701 :py:obj:`Context.use_certificate_file` sets the certificate (given as a
702 ``bytes`` filename) which will be used to identify connections created
703 using the context.
704 """
Hynek Schlawack4813c0e2015-04-16 13:38:01 -0400705 filename = self.mktemp().decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400706 self._use_certificate_file_test(filename)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800707
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200708 @skip_if_py3
709 def test_use_certificate_file_long(self):
710 """
711 On Python 2 :py:obj:`Context.use_certificate_file` accepts a
712 filetype of type :py:obj:`long` as well as :py:obj:`int`.
713 """
714 pem_filename = self.mktemp()
715 with open(pem_filename, "wb") as pem_file:
716 pem_file.write(cleartextCertificatePEM)
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500717
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200718 ctx = Context(TLSv1_METHOD)
719 ctx.use_certificate_file(pem_filename, long(FILETYPE_PEM))
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500720
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500721 def test_check_privatekey_valid(self):
722 """
723 :py:obj:`Context.check_privatekey` returns :py:obj:`None` if the
724 :py:obj:`Context` instance has been configured to use a matched key and
725 certificate pair.
726 """
727 key = load_privatekey(FILETYPE_PEM, client_key_pem)
728 cert = load_certificate(FILETYPE_PEM, client_cert_pem)
729 context = Context(TLSv1_METHOD)
730 context.use_privatekey(key)
731 context.use_certificate(cert)
732 self.assertIs(None, context.check_privatekey())
733
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500734 def test_check_privatekey_invalid(self):
735 """
736 :py:obj:`Context.check_privatekey` raises :py:obj:`Error` if the
737 :py:obj:`Context` instance has been configured to use a key and
738 certificate pair which don't relate to each other.
739 """
740 key = load_privatekey(FILETYPE_PEM, client_key_pem)
741 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
742 context = Context(TLSv1_METHOD)
743 context.use_privatekey(key)
744 context.use_certificate(cert)
745 self.assertRaises(Error, context.check_privatekey)
746
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500747 def test_check_privatekey_wrong_args(self):
748 """
749 :py:obj:`Context.check_privatekey` raises :py:obj:`TypeError` if called
750 with other than no arguments.
751 """
752 context = Context(TLSv1_METHOD)
753 self.assertRaises(TypeError, context.check_privatekey, object())
754
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400755 def test_set_app_data_wrong_args(self):
756 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200757 :py:obj:`Context.set_app_data` raises :py:obj:`TypeError` if called
758 with other than one argument.
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400759 """
760 context = Context(TLSv1_METHOD)
761 self.assertRaises(TypeError, context.set_app_data)
762 self.assertRaises(TypeError, context.set_app_data, None, None)
763
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400764 def test_get_app_data_wrong_args(self):
765 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200766 :py:obj:`Context.get_app_data` raises :py:obj:`TypeError` if called
767 with any arguments.
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400768 """
769 context = Context(TLSv1_METHOD)
770 self.assertRaises(TypeError, context.get_app_data, None)
771
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400772 def test_app_data(self):
773 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200774 :py:obj:`Context.set_app_data` stores an object for later retrieval
775 using :py:obj:`Context.get_app_data`.
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400776 """
777 app_data = object()
778 context = Context(TLSv1_METHOD)
779 context.set_app_data(app_data)
780 self.assertIdentical(context.get_app_data(), app_data)
781
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400782 def test_set_options_wrong_args(self):
783 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200784 :py:obj:`Context.set_options` raises :py:obj:`TypeError` if called with
785 the wrong number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400786 """
787 context = Context(TLSv1_METHOD)
788 self.assertRaises(TypeError, context.set_options)
789 self.assertRaises(TypeError, context.set_options, None)
790 self.assertRaises(TypeError, context.set_options, 1, None)
791
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500792 def test_set_options(self):
793 """
794 :py:obj:`Context.set_options` returns the new options value.
795 """
796 context = Context(TLSv1_METHOD)
797 options = context.set_options(OP_NO_SSLv2)
798 self.assertTrue(OP_NO_SSLv2 & options)
799
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200800 @skip_if_py3
801 def test_set_options_long(self):
802 """
803 On Python 2 :py:obj:`Context.set_options` accepts values of type
804 :py:obj:`long` as well as :py:obj:`int`.
805 """
806 context = Context(TLSv1_METHOD)
807 options = context.set_options(long(OP_NO_SSLv2))
808 self.assertTrue(OP_NO_SSLv2 & options)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500809
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300810 def test_set_mode_wrong_args(self):
811 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200812 :py:obj:`Context.set`mode} raises :py:obj:`TypeError` if called with
813 the wrong number of arguments or a non-:py:obj:`int` argument.
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300814 """
815 context = Context(TLSv1_METHOD)
816 self.assertRaises(TypeError, context.set_mode)
817 self.assertRaises(TypeError, context.set_mode, None)
818 self.assertRaises(TypeError, context.set_mode, 1, None)
819
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400820 if MODE_RELEASE_BUFFERS is not None:
821 def test_set_mode(self):
822 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200823 :py:obj:`Context.set_mode` accepts a mode bitvector and returns the
824 newly set mode.
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400825 """
826 context = Context(TLSv1_METHOD)
827 self.assertTrue(
828 MODE_RELEASE_BUFFERS & context.set_mode(MODE_RELEASE_BUFFERS))
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500829
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200830 @skip_if_py3
831 def test_set_mode_long(self):
832 """
833 On Python 2 :py:obj:`Context.set_mode` accepts values of type
834 :py:obj:`long` as well as :py:obj:`int`.
835 """
836 context = Context(TLSv1_METHOD)
837 mode = context.set_mode(long(MODE_RELEASE_BUFFERS))
838 self.assertTrue(MODE_RELEASE_BUFFERS & mode)
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400839 else:
840 "MODE_RELEASE_BUFFERS unavailable - OpenSSL version may be too old"
841
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400842 def test_set_timeout_wrong_args(self):
843 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200844 :py:obj:`Context.set_timeout` raises :py:obj:`TypeError` if called with
845 the wrong number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400846 """
847 context = Context(TLSv1_METHOD)
848 self.assertRaises(TypeError, context.set_timeout)
849 self.assertRaises(TypeError, context.set_timeout, None)
850 self.assertRaises(TypeError, context.set_timeout, 1, None)
851
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400852 def test_get_timeout_wrong_args(self):
853 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200854 :py:obj:`Context.get_timeout` raises :py:obj:`TypeError` if called with
855 any arguments.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400856 """
857 context = Context(TLSv1_METHOD)
858 self.assertRaises(TypeError, context.get_timeout, None)
859
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400860 def test_timeout(self):
861 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200862 :py:obj:`Context.set_timeout` sets the session timeout for all
863 connections created using the context object.
864 :py:obj:`Context.get_timeout` retrieves this value.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400865 """
866 context = Context(TLSv1_METHOD)
867 context.set_timeout(1234)
868 self.assertEquals(context.get_timeout(), 1234)
869
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200870 @skip_if_py3
871 def test_timeout_long(self):
872 """
873 On Python 2 :py:obj:`Context.set_timeout` accepts values of type
874 `long` as well as int.
875 """
876 context = Context(TLSv1_METHOD)
877 context.set_timeout(long(1234))
878 self.assertEquals(context.get_timeout(), 1234)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500879
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400880 def test_set_verify_depth_wrong_args(self):
881 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200882 :py:obj:`Context.set_verify_depth` raises :py:obj:`TypeError` if called
883 with the wrong number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400884 """
885 context = Context(TLSv1_METHOD)
886 self.assertRaises(TypeError, context.set_verify_depth)
887 self.assertRaises(TypeError, context.set_verify_depth, None)
888 self.assertRaises(TypeError, context.set_verify_depth, 1, None)
889
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400890 def test_get_verify_depth_wrong_args(self):
891 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200892 :py:obj:`Context.get_verify_depth` raises :py:obj:`TypeError` if called
893 with any arguments.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400894 """
895 context = Context(TLSv1_METHOD)
896 self.assertRaises(TypeError, context.get_verify_depth, None)
897
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400898 def test_verify_depth(self):
899 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200900 :py:obj:`Context.set_verify_depth` sets the number of certificates in
901 a chain to follow before giving up. The value can be retrieved with
Jonathan Ballet648875f2011-07-16 14:14:58 +0900902 :py:obj:`Context.get_verify_depth`.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400903 """
904 context = Context(TLSv1_METHOD)
905 context.set_verify_depth(11)
906 self.assertEquals(context.get_verify_depth(), 11)
907
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200908 @skip_if_py3
909 def test_verify_depth_long(self):
910 """
911 On Python 2 :py:obj:`Context.set_verify_depth` accepts values of
912 type `long` as well as int.
913 """
914 context = Context(TLSv1_METHOD)
915 context.set_verify_depth(long(11))
916 self.assertEquals(context.get_verify_depth(), 11)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500917
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400918 def _write_encrypted_pem(self, passphrase):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400919 """
920 Write a new private key out to a new file, encrypted using the given
921 passphrase. Return the path to the new file.
922 """
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400923 key = PKey()
924 key.generate_key(TYPE_RSA, 128)
925 pemFile = self.mktemp()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400926 fObj = open(pemFile, 'w')
927 pem = dump_privatekey(FILETYPE_PEM, key, "blowfish", passphrase)
928 fObj.write(pem.decode('ascii'))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400929 fObj.close()
930 return pemFile
931
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400932 def test_set_passwd_cb_wrong_args(self):
933 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200934 :py:obj:`Context.set_passwd_cb` raises :py:obj:`TypeError` if called
935 with the wrong arguments or with a non-callable first argument.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400936 """
937 context = Context(TLSv1_METHOD)
938 self.assertRaises(TypeError, context.set_passwd_cb)
939 self.assertRaises(TypeError, context.set_passwd_cb, None)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200940 self.assertRaises(
941 TypeError, context.set_passwd_cb, lambda: None, None, None
Hynek Schlawack2c013a92015-09-05 19:33:05 +0200942 ) # pragma: nocover
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400943
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400944 def test_set_passwd_cb(self):
945 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200946 :py:obj:`Context.set_passwd_cb` accepts a callable which will be
947 invoked when a private key is loaded from an encrypted PEM.
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400948 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400949 passphrase = b("foobar")
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400950 pemFile = self._write_encrypted_pem(passphrase)
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400951 calledWith = []
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200952
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400953 def passphraseCallback(maxlen, verify, extra):
954 calledWith.append((maxlen, verify, extra))
955 return passphrase
956 context = Context(TLSv1_METHOD)
957 context.set_passwd_cb(passphraseCallback)
958 context.use_privatekey_file(pemFile)
959 self.assertTrue(len(calledWith), 1)
960 self.assertTrue(isinstance(calledWith[0][0], int))
961 self.assertTrue(isinstance(calledWith[0][1], int))
962 self.assertEqual(calledWith[0][2], None)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400963
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400964 def test_passwd_callback_exception(self):
965 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200966 :py:obj:`Context.use_privatekey_file` propagates any exception raised
967 by the passphrase callback.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400968 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400969 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200970
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400971 def passphraseCallback(maxlen, verify, extra):
972 raise RuntimeError("Sorry, I am a fail.")
973
974 context = Context(TLSv1_METHOD)
975 context.set_passwd_cb(passphraseCallback)
976 self.assertRaises(RuntimeError, context.use_privatekey_file, pemFile)
977
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400978 def test_passwd_callback_false(self):
979 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200980 :py:obj:`Context.use_privatekey_file` raises
981 :py:obj:`OpenSSL.SSL.Error` if the passphrase callback returns a false
982 value.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400983 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400984 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200985
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400986 def passphraseCallback(maxlen, verify, extra):
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500987 return b""
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400988
989 context = Context(TLSv1_METHOD)
990 context.set_passwd_cb(passphraseCallback)
991 self.assertRaises(Error, context.use_privatekey_file, pemFile)
992
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400993 def test_passwd_callback_non_string(self):
994 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200995 :py:obj:`Context.use_privatekey_file` raises
996 :py:obj:`OpenSSL.SSL.Error` if the passphrase callback returns a true
997 non-string value.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400998 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400999 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001000
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -04001001 def passphraseCallback(maxlen, verify, extra):
1002 return 10
1003
1004 context = Context(TLSv1_METHOD)
1005 context.set_passwd_cb(passphraseCallback)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -08001006 self.assertRaises(ValueError, context.use_privatekey_file, pemFile)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -04001007
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -04001008 def test_passwd_callback_too_long(self):
1009 """
1010 If the passphrase returned by the passphrase callback returns a string
1011 longer than the indicated maximum length, it is truncated.
1012 """
1013 # A priori knowledge!
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04001014 passphrase = b("x") * 1024
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -04001015 pemFile = self._write_encrypted_pem(passphrase)
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001016
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -04001017 def passphraseCallback(maxlen, verify, extra):
1018 assert maxlen == 1024
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04001019 return passphrase + b("y")
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -04001020
1021 context = Context(TLSv1_METHOD)
1022 context.set_passwd_cb(passphraseCallback)
1023 # This shall succeed because the truncated result is the correct
1024 # passphrase.
1025 context.use_privatekey_file(pemFile)
1026
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -04001027 def test_set_info_callback(self):
1028 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001029 :py:obj:`Context.set_info_callback` accepts a callable which will be
1030 invoked when certain information about an SSL connection is available.
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -04001031 """
Rick Deanb1ccd562009-07-09 23:52:39 -05001032 (server, client) = socket_pair()
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -04001033
1034 clientSSL = Connection(Context(TLSv1_METHOD), client)
1035 clientSSL.set_connect_state()
1036
1037 called = []
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001038
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -04001039 def info(conn, where, ret):
1040 called.append((conn, where, ret))
1041 context = Context(TLSv1_METHOD)
1042 context.set_info_callback(info)
1043 context.use_certificate(
1044 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1045 context.use_privatekey(
1046 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1047
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -04001048 serverSSL = Connection(context, server)
1049 serverSSL.set_accept_state()
1050
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -05001051 handshake(clientSSL, serverSSL)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -04001052
Jean-Paul Calderone3835e522014-02-02 11:12:30 -05001053 # The callback must always be called with a Connection instance as the
1054 # first argument. It would probably be better to split this into
1055 # separate tests for client and server side info callbacks so we could
1056 # assert it is called with the right Connection instance. It would
1057 # also be good to assert *something* about `where` and `ret`.
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -05001058 notConnections = [
1059 conn for (conn, where, ret) in called
1060 if not isinstance(conn, Connection)]
1061 self.assertEqual(
1062 [], notConnections,
1063 "Some info callback arguments were not Connection instaces.")
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001064
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001065 def _load_verify_locations_test(self, *args):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001066 """
1067 Create a client context which will verify the peer certificate and call
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04001068 its :py:obj:`load_verify_locations` method with the given arguments.
1069 Then connect it to a server and ensure that the handshake succeeds.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001070 """
Rick Deanb1ccd562009-07-09 23:52:39 -05001071 (server, client) = socket_pair()
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001072
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001073 clientContext = Context(TLSv1_METHOD)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001074 clientContext.load_verify_locations(*args)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001075 # Require that the server certificate verify properly or the
1076 # connection will fail.
1077 clientContext.set_verify(
1078 VERIFY_PEER,
1079 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
1080
1081 clientSSL = Connection(clientContext, client)
1082 clientSSL.set_connect_state()
1083
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001084 serverContext = Context(TLSv1_METHOD)
1085 serverContext.use_certificate(
1086 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1087 serverContext.use_privatekey(
1088 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1089
1090 serverSSL = Connection(serverContext, server)
1091 serverSSL.set_accept_state()
1092
Jean-Paul Calderonef8742032010-09-25 00:00:32 -04001093 # Without load_verify_locations above, the handshake
1094 # will fail:
1095 # Error: [('SSL routines', 'SSL3_GET_SERVER_CERTIFICATE',
1096 # 'certificate verify failed')]
1097 handshake(clientSSL, serverSSL)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001098
1099 cert = clientSSL.get_peer_certificate()
Jean-Paul Calderone20131f52009-04-01 12:05:45 -04001100 self.assertEqual(cert.get_subject().CN, 'Testing Root CA')
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -04001101
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001102 def _load_verify_cafile(self, cafile):
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001103 """
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001104 Verify that if path to a file containing a certificate is passed to
1105 ``Context.load_verify_locations`` for the ``cafile`` parameter, that
1106 certificate is used as a trust root for the purposes of verifying
1107 connections created using that ``Context``.
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001108 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04001109 fObj = open(cafile, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04001110 fObj.write(cleartextCertificatePEM.decode('ascii'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001111 fObj.close()
1112
1113 self._load_verify_locations_test(cafile)
1114
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001115 def test_load_verify_bytes_cafile(self):
1116 """
1117 :py:obj:`Context.load_verify_locations` accepts a file name as a
1118 ``bytes`` instance and uses the certificates within for verification
1119 purposes.
1120 """
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001121 cafile = self.mktemp() + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001122 self._load_verify_cafile(cafile)
1123
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001124 def test_load_verify_unicode_cafile(self):
1125 """
1126 :py:obj:`Context.load_verify_locations` accepts a file name as a
1127 ``unicode`` instance and uses the certificates within for verification
1128 purposes.
1129 """
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001130 self._load_verify_cafile(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001131 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001132 )
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001133
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -04001134 def test_load_verify_invalid_file(self):
1135 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001136 :py:obj:`Context.load_verify_locations` raises :py:obj:`Error` when
1137 passed a non-existent cafile.
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -04001138 """
1139 clientContext = Context(TLSv1_METHOD)
1140 self.assertRaises(
1141 Error, clientContext.load_verify_locations, self.mktemp())
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001142
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001143 def _load_verify_directory_locations_capath(self, capath):
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001144 """
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001145 Verify that if path to a directory containing certificate files is
1146 passed to ``Context.load_verify_locations`` for the ``capath``
1147 parameter, those certificates are used as trust roots for the purposes
1148 of verifying connections created using that ``Context``.
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001149 """
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001150 makedirs(capath)
Jean-Paul Calderone24dfb332011-05-04 18:10:26 -04001151 # Hash values computed manually with c_rehash to avoid depending on
1152 # c_rehash in the test suite. One is from OpenSSL 0.9.8, the other
1153 # from OpenSSL 1.0.0.
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001154 for name in [b'c7adac82.0', b'c3705638.0']:
Jean-Paul Calderone05826732015-04-12 11:38:49 -04001155 cafile = join_bytes_or_unicode(capath, name)
1156 with open(cafile, 'w') as fObj:
1157 fObj.write(cleartextCertificatePEM.decode('ascii'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001158
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001159 self._load_verify_locations_test(None, capath)
1160
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001161 def test_load_verify_directory_bytes_capath(self):
1162 """
1163 :py:obj:`Context.load_verify_locations` accepts a directory name as a
1164 ``bytes`` instance and uses the certificates within for verification
1165 purposes.
1166 """
1167 self._load_verify_directory_locations_capath(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001168 self.mktemp() + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001169 )
1170
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001171 def test_load_verify_directory_unicode_capath(self):
1172 """
1173 :py:obj:`Context.load_verify_locations` accepts a directory name as a
1174 ``unicode`` instance and uses the certificates within for verification
1175 purposes.
1176 """
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001177 self._load_verify_directory_locations_capath(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001178 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001179 )
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001180
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001181 def test_load_verify_locations_wrong_args(self):
1182 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001183 :py:obj:`Context.load_verify_locations` raises :py:obj:`TypeError` if
1184 called with the wrong number of arguments or with non-:py:obj:`str`
1185 arguments.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001186 """
1187 context = Context(TLSv1_METHOD)
1188 self.assertRaises(TypeError, context.load_verify_locations)
1189 self.assertRaises(TypeError, context.load_verify_locations, object())
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001190 self.assertRaises(
1191 TypeError, context.load_verify_locations, object(), object()
1192 )
1193 self.assertRaises(
1194 TypeError, context.load_verify_locations, None, None, None
1195 )
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001196
Hynek Schlawack734d3022015-09-05 19:19:32 +02001197 @pytest.mark.skipif(
1198 platform == "win32",
1199 reason="set_default_verify_paths appears not to work on Windows. "
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -04001200 "See LP#404343 and LP#404344."
Hynek Schlawack734d3022015-09-05 19:19:32 +02001201 )
1202 def test_set_default_verify_paths(self):
1203 """
1204 :py:obj:`Context.set_default_verify_paths` causes the
1205 platform-specific CA certificate locations to be used for
1206 verification purposes.
1207 """
1208 # Testing this requires a server with a certificate signed by one
1209 # of the CAs in the platform CA location. Getting one of those
1210 # costs money. Fortunately (or unfortunately, depending on your
1211 # perspective), it's easy to think of a public server on the
1212 # internet which has such a certificate. Connecting to the network
1213 # in a unit test is bad, but it's the only way I can think of to
1214 # really test this. -exarkun
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001215
Hynek Schlawack734d3022015-09-05 19:19:32 +02001216 # Arg, verisign.com doesn't speak anything newer than TLS 1.0
Hynek Schlawackbf887932015-10-21 17:13:47 +02001217 context = Context(SSLv23_METHOD)
Hynek Schlawack734d3022015-09-05 19:19:32 +02001218 context.set_default_verify_paths()
1219 context.set_verify(
1220 VERIFY_PEER,
1221 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001222
Hynek Schlawack734d3022015-09-05 19:19:32 +02001223 client = socket()
Hynek Schlawackbf887932015-10-21 17:13:47 +02001224 client.connect(("encrypted.google.com", 443))
Hynek Schlawack734d3022015-09-05 19:19:32 +02001225 clientSSL = Connection(context, client)
1226 clientSSL.set_connect_state()
1227 clientSSL.do_handshake()
1228 clientSSL.send(b"GET / HTTP/1.0\r\n\r\n")
1229 self.assertTrue(clientSSL.recv(1024))
Jean-Paul Calderone9eadb962008-09-07 21:20:44 -04001230
1231 def test_set_default_verify_paths_signature(self):
1232 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001233 :py:obj:`Context.set_default_verify_paths` takes no arguments and
1234 raises :py:obj:`TypeError` if given any.
Jean-Paul Calderone9eadb962008-09-07 21:20:44 -04001235 """
1236 context = Context(TLSv1_METHOD)
1237 self.assertRaises(TypeError, context.set_default_verify_paths, None)
1238 self.assertRaises(TypeError, context.set_default_verify_paths, 1)
1239 self.assertRaises(TypeError, context.set_default_verify_paths, "")
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05001240
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001241 def test_add_extra_chain_cert_invalid_cert(self):
1242 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001243 :py:obj:`Context.add_extra_chain_cert` raises :py:obj:`TypeError` if
1244 called with other than one argument or if called with an object which
1245 is not an instance of :py:obj:`X509`.
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001246 """
1247 context = Context(TLSv1_METHOD)
1248 self.assertRaises(TypeError, context.add_extra_chain_cert)
1249 self.assertRaises(TypeError, context.add_extra_chain_cert, object())
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001250 self.assertRaises(
1251 TypeError, context.add_extra_chain_cert, object(), object()
1252 )
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001253
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001254 def _handshake_test(self, serverContext, clientContext):
1255 """
1256 Verify that a client and server created with the given contexts can
1257 successfully handshake and communicate.
1258 """
1259 serverSocket, clientSocket = socket_pair()
1260
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001261 server = Connection(serverContext, serverSocket)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001262 server.set_accept_state()
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001263
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001264 client = Connection(clientContext, clientSocket)
1265 client.set_connect_state()
1266
1267 # Make them talk to each other.
1268 # self._interactInMemory(client, server)
1269 for i in range(3):
1270 for s in [client, server]:
1271 try:
1272 s.do_handshake()
1273 except WantReadError:
1274 pass
1275
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001276 def test_set_verify_callback_connection_argument(self):
1277 """
1278 The first argument passed to the verify callback is the
1279 :py:class:`Connection` instance for which verification is taking place.
1280 """
1281 serverContext = Context(TLSv1_METHOD)
1282 serverContext.use_privatekey(
1283 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1284 serverContext.use_certificate(
1285 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1286 serverConnection = Connection(serverContext, None)
1287
1288 class VerifyCallback(object):
1289 def callback(self, connection, *args):
1290 self.connection = connection
1291 return 1
1292
1293 verify = VerifyCallback()
1294 clientContext = Context(TLSv1_METHOD)
1295 clientContext.set_verify(VERIFY_PEER, verify.callback)
1296 clientConnection = Connection(clientContext, None)
1297 clientConnection.set_connect_state()
1298
1299 self._handshakeInMemory(clientConnection, serverConnection)
1300
1301 self.assertIdentical(verify.connection, clientConnection)
1302
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001303 def test_set_verify_callback_exception(self):
1304 """
1305 If the verify callback passed to :py:obj:`Context.set_verify` raises an
1306 exception, verification fails and the exception is propagated to the
1307 caller of :py:obj:`Connection.do_handshake`.
1308 """
1309 serverContext = Context(TLSv1_METHOD)
1310 serverContext.use_privatekey(
1311 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1312 serverContext.use_certificate(
1313 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1314
1315 clientContext = Context(TLSv1_METHOD)
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001316
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001317 def verify_callback(*args):
1318 raise Exception("silly verify failure")
1319 clientContext.set_verify(VERIFY_PEER, verify_callback)
1320
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01001321 with pytest.raises(Exception) as exc:
1322 self._handshake_test(serverContext, clientContext)
1323
1324 self.assertEqual("silly verify failure", str(exc.value))
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001325
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001326 def test_add_extra_chain_cert(self):
1327 """
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001328 :py:obj:`Context.add_extra_chain_cert` accepts an :py:obj:`X509`
1329 instance to add to the certificate chain.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001330
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001331 See :py:obj:`_create_certificate_chain` for the details of the
1332 certificate chain tested.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001333
1334 The chain is tested by starting a server with scert and connecting
1335 to it with a client which trusts cacert and requires verification to
1336 succeed.
1337 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001338 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001339 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1340
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001341 # Dump the CA certificate to a file because that's the only way to load
1342 # it as a trusted CA in the client context.
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001343 for cert, name in [(cacert, 'ca.pem'),
1344 (icert, 'i.pem'),
1345 (scert, 's.pem')]:
Hynek Schlawacke90680f2015-04-16 15:09:27 -04001346 with open(join(self.tmpdir, name), 'w') as f:
1347 f.write(dump_certificate(FILETYPE_PEM, cert).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001348
Hynek Schlawack1902c012015-04-16 15:06:41 -04001349 for key, name in [(cakey, 'ca.key'),
1350 (ikey, 'i.key'),
1351 (skey, 's.key')]:
Hynek Schlawacke90680f2015-04-16 15:09:27 -04001352 with open(join(self.tmpdir, name), 'w') as f:
1353 f.write(dump_privatekey(FILETYPE_PEM, key).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001354
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001355 # Create the server context
1356 serverContext = Context(TLSv1_METHOD)
1357 serverContext.use_privatekey(skey)
1358 serverContext.use_certificate(scert)
Jean-Paul Calderone16cf03d2010-09-08 18:53:39 -04001359 # The client already has cacert, we only need to give them icert.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001360 serverContext.add_extra_chain_cert(icert)
1361
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001362 # Create the client
1363 clientContext = Context(TLSv1_METHOD)
1364 clientContext.set_verify(
1365 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001366 clientContext.load_verify_locations(join(self.tmpdir, "ca.pem"))
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001367
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001368 # Try it out.
1369 self._handshake_test(serverContext, clientContext)
1370
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001371 def _use_certificate_chain_file_test(self, certdir):
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001372 """
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001373 Verify that :py:obj:`Context.use_certificate_chain_file` reads a
1374 certificate chain from a specified file.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001375
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001376 The chain is tested by starting a server with scert and connecting to
1377 it with a client which trusts cacert and requires verification to
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001378 succeed.
1379 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001380 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001381 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1382
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001383 makedirs(certdir)
1384
Jean-Paul Calderone05826732015-04-12 11:38:49 -04001385 chainFile = join_bytes_or_unicode(certdir, "chain.pem")
1386 caFile = join_bytes_or_unicode(certdir, "ca.pem")
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001387
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001388 # Write out the chain file.
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001389 with open(chainFile, 'wb') as fObj:
1390 # Most specific to least general.
1391 fObj.write(dump_certificate(FILETYPE_PEM, scert))
1392 fObj.write(dump_certificate(FILETYPE_PEM, icert))
1393 fObj.write(dump_certificate(FILETYPE_PEM, cacert))
1394
1395 with open(caFile, 'w') as fObj:
1396 fObj.write(dump_certificate(FILETYPE_PEM, cacert).decode('ascii'))
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001397
1398 serverContext = Context(TLSv1_METHOD)
1399 serverContext.use_certificate_chain_file(chainFile)
1400 serverContext.use_privatekey(skey)
1401
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001402 clientContext = Context(TLSv1_METHOD)
1403 clientContext.set_verify(
1404 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001405 clientContext.load_verify_locations(caFile)
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001406
1407 self._handshake_test(serverContext, clientContext)
1408
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001409 def test_use_certificate_chain_file_bytes(self):
1410 """
1411 ``Context.use_certificate_chain_file`` accepts the name of a file (as
1412 an instance of ``bytes``) to specify additional certificates to use to
1413 construct and verify a trust chain.
1414 """
1415 self._use_certificate_chain_file_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001416 self.mktemp() + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001417 )
1418
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001419 def test_use_certificate_chain_file_unicode(self):
1420 """
1421 ``Context.use_certificate_chain_file`` accepts the name of a file (as
1422 an instance of ``unicode``) to specify additional certificates to use
1423 to construct and verify a trust chain.
1424 """
1425 self._use_certificate_chain_file_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001426 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001427 )
1428
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001429 def test_use_certificate_chain_file_wrong_args(self):
1430 """
1431 :py:obj:`Context.use_certificate_chain_file` raises :py:obj:`TypeError`
1432 if passed zero or more than one argument or when passed a non-byte
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001433 string single argument. It also raises :py:obj:`OpenSSL.SSL.Error`
1434 when passed a bad chain file name (for example, the name of a file
1435 which does not exist).
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001436 """
1437 context = Context(TLSv1_METHOD)
1438 self.assertRaises(TypeError, context.use_certificate_chain_file)
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001439 self.assertRaises(
1440 TypeError, context.use_certificate_chain_file, object()
1441 )
1442 self.assertRaises(
1443 TypeError, context.use_certificate_chain_file, b"foo", object()
1444 )
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001445
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001446 self.assertRaises(
1447 Error, context.use_certificate_chain_file, self.mktemp()
1448 )
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001449
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001450 def test_get_verify_mode_wrong_args(self):
1451 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001452 :py:obj:`Context.get_verify_mode` raises :py:obj:`TypeError` if called
1453 with any arguments.
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001454 """
1455 context = Context(TLSv1_METHOD)
1456 self.assertRaises(TypeError, context.get_verify_mode, None)
1457
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001458 def test_set_verify_mode(self):
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001459 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001460 :py:obj:`Context.get_verify_mode` returns the verify mode flags
1461 previously passed to :py:obj:`Context.set_verify`.
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001462 """
1463 context = Context(TLSv1_METHOD)
1464 self.assertEquals(context.get_verify_mode(), 0)
1465 context.set_verify(
1466 VERIFY_PEER | VERIFY_CLIENT_ONCE, lambda *args: None)
1467 self.assertEquals(
1468 context.get_verify_mode(), VERIFY_PEER | VERIFY_CLIENT_ONCE)
1469
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001470 @skip_if_py3
1471 def test_set_verify_mode_long(self):
1472 """
1473 On Python 2 :py:obj:`Context.set_verify_mode` accepts values of
1474 type :py:obj:`long` as well as :py:obj:`int`.
1475 """
1476 context = Context(TLSv1_METHOD)
1477 self.assertEquals(context.get_verify_mode(), 0)
1478 context.set_verify(
Hynek Schlawackb4ceed32015-09-05 20:55:19 +02001479 long(VERIFY_PEER | VERIFY_CLIENT_ONCE), lambda *args: None
1480 ) # pragma: nocover
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001481 self.assertEquals(
1482 context.get_verify_mode(), VERIFY_PEER | VERIFY_CLIENT_ONCE)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001483
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001484 def test_load_tmp_dh_wrong_args(self):
1485 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001486 :py:obj:`Context.load_tmp_dh` raises :py:obj:`TypeError` if called with
1487 the wrong number of arguments or with a non-:py:obj:`str` argument.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001488 """
1489 context = Context(TLSv1_METHOD)
1490 self.assertRaises(TypeError, context.load_tmp_dh)
1491 self.assertRaises(TypeError, context.load_tmp_dh, "foo", None)
1492 self.assertRaises(TypeError, context.load_tmp_dh, object())
1493
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001494 def test_load_tmp_dh_missing_file(self):
1495 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001496 :py:obj:`Context.load_tmp_dh` raises :py:obj:`OpenSSL.SSL.Error` if the
1497 specified file does not exist.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001498 """
1499 context = Context(TLSv1_METHOD)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001500 self.assertRaises(Error, context.load_tmp_dh, b"hello")
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001501
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001502 def _load_tmp_dh_test(self, dhfilename):
Jean-Paul Calderone4e0c43f2015-04-13 10:15:17 -04001503 """
1504 Verify that calling ``Context.load_tmp_dh`` with the given filename
1505 does not raise an exception.
1506 """
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001507 context = Context(TLSv1_METHOD)
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001508 with open(dhfilename, "w") as dhfile:
1509 dhfile.write(dhparam)
1510
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001511 context.load_tmp_dh(dhfilename)
1512 # XXX What should I assert here? -exarkun
1513
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001514 def test_load_tmp_dh_bytes(self):
1515 """
1516 :py:obj:`Context.load_tmp_dh` loads Diffie-Hellman parameters from the
1517 specified file (given as ``bytes``).
1518 """
1519 self._load_tmp_dh_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001520 self.mktemp() + NON_ASCII.encode(getfilesystemencoding()),
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001521 )
1522
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001523 def test_load_tmp_dh_unicode(self):
1524 """
1525 :py:obj:`Context.load_tmp_dh` loads Diffie-Hellman parameters from the
1526 specified file (given as ``unicode``).
1527 """
1528 self._load_tmp_dh_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001529 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII,
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001530 )
1531
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001532 def test_set_tmp_ecdh(self):
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001533 """
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001534 :py:obj:`Context.set_tmp_ecdh` sets the elliptic curve for
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001535 Diffie-Hellman to the specified curve.
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001536 """
1537 context = Context(TLSv1_METHOD)
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001538 for curve in get_elliptic_curves():
Hynek Schlawacka07fa8c2015-10-17 10:15:28 +02001539 if curve.name.startswith(u"Oakley-"):
Hynek Schlawack7408aff2015-10-17 09:51:16 +02001540 # Setting Oakley-EC2N-4 and Oakley-EC2N-3 adds
1541 # ('bignum routines', 'BN_mod_inverse', 'no inverse') to the
1542 # error queue on OpenSSL 1.0.2.
1543 continue
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001544 # The only easily "assertable" thing is that it does not raise an
1545 # exception.
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001546 context.set_tmp_ecdh(curve)
Alex Gaynor12dc0842014-01-17 12:51:31 -06001547
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001548 def test_set_session_cache_mode_wrong_args(self):
1549 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001550 :py:obj:`Context.set_session_cache_mode` raises :py:obj:`TypeError` if
1551 called with other than one integer argument.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001552 """
1553 context = Context(TLSv1_METHOD)
1554 self.assertRaises(TypeError, context.set_session_cache_mode)
1555 self.assertRaises(TypeError, context.set_session_cache_mode, object())
1556
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001557 def test_get_session_cache_mode_wrong_args(self):
1558 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001559 :py:obj:`Context.get_session_cache_mode` raises :py:obj:`TypeError` if
1560 called with any arguments.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001561 """
1562 context = Context(TLSv1_METHOD)
1563 self.assertRaises(TypeError, context.get_session_cache_mode, 1)
1564
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001565 def test_session_cache_mode(self):
1566 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001567 :py:obj:`Context.set_session_cache_mode` specifies how sessions are
1568 cached. The setting can be retrieved via
1569 :py:obj:`Context.get_session_cache_mode`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001570 """
1571 context = Context(TLSv1_METHOD)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001572 context.set_session_cache_mode(SESS_CACHE_OFF)
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001573 off = context.set_session_cache_mode(SESS_CACHE_BOTH)
1574 self.assertEqual(SESS_CACHE_OFF, off)
1575 self.assertEqual(SESS_CACHE_BOTH, context.get_session_cache_mode())
1576
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001577 @skip_if_py3
1578 def test_session_cache_mode_long(self):
1579 """
1580 On Python 2 :py:obj:`Context.set_session_cache_mode` accepts values
1581 of type :py:obj:`long` as well as :py:obj:`int`.
1582 """
1583 context = Context(TLSv1_METHOD)
1584 context.set_session_cache_mode(long(SESS_CACHE_BOTH))
1585 self.assertEqual(
1586 SESS_CACHE_BOTH, context.get_session_cache_mode())
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001587
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001588 def test_get_cert_store(self):
1589 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001590 :py:obj:`Context.get_cert_store` returns a :py:obj:`X509Store`
1591 instance.
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001592 """
1593 context = Context(TLSv1_METHOD)
1594 store = context.get_cert_store()
1595 self.assertIsInstance(store, X509Store)
1596
1597
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001598class ServerNameCallbackTests(TestCase, _LoopbackMixin):
1599 """
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001600 Tests for :py:obj:`Context.set_tlsext_servername_callback` and its
1601 interaction with :py:obj:`Connection`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001602 """
1603 def test_wrong_args(self):
1604 """
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001605 :py:obj:`Context.set_tlsext_servername_callback` raises
1606 :py:obj:`TypeError` if called with other than one argument.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001607 """
1608 context = Context(TLSv1_METHOD)
1609 self.assertRaises(TypeError, context.set_tlsext_servername_callback)
1610 self.assertRaises(
1611 TypeError, context.set_tlsext_servername_callback, 1, 2)
1612
1613 def test_old_callback_forgotten(self):
1614 """
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001615 If :py:obj:`Context.set_tlsext_servername_callback` is used to specify
1616 a new callback, the one it replaces is dereferenced.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001617 """
1618 def callback(connection):
1619 pass
1620
1621 def replacement(connection):
1622 pass
1623
1624 context = Context(TLSv1_METHOD)
1625 context.set_tlsext_servername_callback(callback)
1626
1627 tracker = ref(callback)
1628 del callback
1629
1630 context.set_tlsext_servername_callback(replacement)
Jean-Paul Calderoned4033eb2014-01-11 08:21:46 -05001631
1632 # One run of the garbage collector happens to work on CPython. PyPy
1633 # doesn't collect the underlying object until a second run for whatever
1634 # reason. That's fine, it still demonstrates our code has properly
1635 # dropped the reference.
1636 collect()
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001637 collect()
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001638
1639 callback = tracker()
1640 if callback is not None:
1641 referrers = get_referrers(callback)
Jean-Paul Calderone7de39562014-01-11 08:17:59 -05001642 if len(referrers) > 1:
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001643 self.fail("Some references remain: %r" % (referrers,))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001644
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001645 def test_no_servername(self):
1646 """
1647 When a client specifies no server name, the callback passed to
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001648 :py:obj:`Context.set_tlsext_servername_callback` is invoked and the
1649 result of :py:obj:`Connection.get_servername` is :py:obj:`None`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001650 """
1651 args = []
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001652
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001653 def servername(conn):
1654 args.append((conn, conn.get_servername()))
1655 context = Context(TLSv1_METHOD)
1656 context.set_tlsext_servername_callback(servername)
1657
1658 # Lose our reference to it. The Context is responsible for keeping it
1659 # alive now.
1660 del servername
1661 collect()
1662
1663 # Necessary to actually accept the connection
1664 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001665 context.use_certificate(
1666 load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001667
1668 # Do a little connection to trigger the logic
1669 server = Connection(context, None)
1670 server.set_accept_state()
1671
1672 client = Connection(Context(TLSv1_METHOD), None)
1673 client.set_connect_state()
1674
1675 self._interactInMemory(server, client)
1676
1677 self.assertEqual([(server, None)], args)
1678
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001679 def test_servername(self):
1680 """
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001681 When a client specifies a server name in its hello message, the
1682 callback passed to :py:obj:`Contexts.set_tlsext_servername_callback` is
1683 invoked and the result of :py:obj:`Connection.get_servername` is that
1684 server name.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001685 """
1686 args = []
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001687
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001688 def servername(conn):
1689 args.append((conn, conn.get_servername()))
1690 context = Context(TLSv1_METHOD)
1691 context.set_tlsext_servername_callback(servername)
1692
1693 # Necessary to actually accept the connection
1694 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001695 context.use_certificate(
1696 load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001697
1698 # Do a little connection to trigger the logic
1699 server = Connection(context, None)
1700 server.set_accept_state()
1701
1702 client = Connection(Context(TLSv1_METHOD), None)
1703 client.set_connect_state()
1704 client.set_tlsext_host_name(b("foo1.example.com"))
1705
1706 self._interactInMemory(server, client)
1707
1708 self.assertEqual([(server, b("foo1.example.com"))], args)
1709
1710
Cory Benfield84a121e2014-03-31 20:30:25 +01001711class NextProtoNegotiationTests(TestCase, _LoopbackMixin):
1712 """
1713 Test for Next Protocol Negotiation in PyOpenSSL.
1714 """
Cory Benfieldba1820d2015-04-13 17:39:12 -04001715 if _lib.Cryptography_HAS_NEXTPROTONEG:
1716 def test_npn_success(self):
1717 """
1718 Tests that clients and servers that agree on the negotiated next
1719 protocol can correct establish a connection, and that the agreed
1720 protocol is reported by the connections.
1721 """
1722 advertise_args = []
1723 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001724
Cory Benfieldba1820d2015-04-13 17:39:12 -04001725 def advertise(conn):
1726 advertise_args.append((conn,))
1727 return [b'http/1.1', b'spdy/2']
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001728
Cory Benfieldba1820d2015-04-13 17:39:12 -04001729 def select(conn, options):
1730 select_args.append((conn, options))
1731 return b'spdy/2'
Cory Benfield84a121e2014-03-31 20:30:25 +01001732
Cory Benfieldba1820d2015-04-13 17:39:12 -04001733 server_context = Context(TLSv1_METHOD)
1734 server_context.set_npn_advertise_callback(advertise)
Cory Benfield84a121e2014-03-31 20:30:25 +01001735
Cory Benfieldba1820d2015-04-13 17:39:12 -04001736 client_context = Context(TLSv1_METHOD)
1737 client_context.set_npn_select_callback(select)
Cory Benfield84a121e2014-03-31 20:30:25 +01001738
Cory Benfieldba1820d2015-04-13 17:39:12 -04001739 # Necessary to actually accept the connection
1740 server_context.use_privatekey(
1741 load_privatekey(FILETYPE_PEM, server_key_pem))
1742 server_context.use_certificate(
1743 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield84a121e2014-03-31 20:30:25 +01001744
Cory Benfieldba1820d2015-04-13 17:39:12 -04001745 # Do a little connection to trigger the logic
1746 server = Connection(server_context, None)
1747 server.set_accept_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001748
Cory Benfieldba1820d2015-04-13 17:39:12 -04001749 client = Connection(client_context, None)
1750 client.set_connect_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001751
Cory Benfieldba1820d2015-04-13 17:39:12 -04001752 self._interactInMemory(server, client)
Cory Benfield84a121e2014-03-31 20:30:25 +01001753
Cory Benfieldba1820d2015-04-13 17:39:12 -04001754 self.assertEqual([(server,)], advertise_args)
1755 self.assertEqual([(client, [b'http/1.1', b'spdy/2'])], select_args)
Cory Benfield84a121e2014-03-31 20:30:25 +01001756
Cory Benfieldba1820d2015-04-13 17:39:12 -04001757 self.assertEqual(server.get_next_proto_negotiated(), b'spdy/2')
1758 self.assertEqual(client.get_next_proto_negotiated(), b'spdy/2')
Cory Benfield84a121e2014-03-31 20:30:25 +01001759
Cory Benfieldba1820d2015-04-13 17:39:12 -04001760 def test_npn_client_fail(self):
1761 """
1762 Tests that when clients and servers cannot agree on what protocol
1763 to use next that the TLS connection does not get established.
1764 """
1765 advertise_args = []
1766 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001767
Cory Benfieldba1820d2015-04-13 17:39:12 -04001768 def advertise(conn):
1769 advertise_args.append((conn,))
1770 return [b'http/1.1', b'spdy/2']
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001771
Cory Benfieldba1820d2015-04-13 17:39:12 -04001772 def select(conn, options):
1773 select_args.append((conn, options))
1774 return b''
Cory Benfield84a121e2014-03-31 20:30:25 +01001775
Cory Benfieldba1820d2015-04-13 17:39:12 -04001776 server_context = Context(TLSv1_METHOD)
1777 server_context.set_npn_advertise_callback(advertise)
Cory Benfield84a121e2014-03-31 20:30:25 +01001778
Cory Benfieldba1820d2015-04-13 17:39:12 -04001779 client_context = Context(TLSv1_METHOD)
1780 client_context.set_npn_select_callback(select)
Cory Benfield84a121e2014-03-31 20:30:25 +01001781
Cory Benfieldba1820d2015-04-13 17:39:12 -04001782 # Necessary to actually accept the connection
1783 server_context.use_privatekey(
1784 load_privatekey(FILETYPE_PEM, server_key_pem))
1785 server_context.use_certificate(
1786 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield84a121e2014-03-31 20:30:25 +01001787
Cory Benfieldba1820d2015-04-13 17:39:12 -04001788 # Do a little connection to trigger the logic
1789 server = Connection(server_context, None)
1790 server.set_accept_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001791
Cory Benfieldba1820d2015-04-13 17:39:12 -04001792 client = Connection(client_context, None)
1793 client.set_connect_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001794
Cory Benfieldba1820d2015-04-13 17:39:12 -04001795 # If the client doesn't return anything, the connection will fail.
1796 self.assertRaises(Error, self._interactInMemory, server, client)
Cory Benfield84a121e2014-03-31 20:30:25 +01001797
Cory Benfieldba1820d2015-04-13 17:39:12 -04001798 self.assertEqual([(server,)], advertise_args)
1799 self.assertEqual([(client, [b'http/1.1', b'spdy/2'])], select_args)
Cory Benfield84a121e2014-03-31 20:30:25 +01001800
Cory Benfieldba1820d2015-04-13 17:39:12 -04001801 def test_npn_select_error(self):
1802 """
1803 Test that we can handle exceptions in the select callback. If
1804 select fails it should be fatal to the connection.
1805 """
1806 advertise_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001807
Cory Benfieldba1820d2015-04-13 17:39:12 -04001808 def advertise(conn):
1809 advertise_args.append((conn,))
1810 return [b'http/1.1', b'spdy/2']
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001811
Cory Benfieldba1820d2015-04-13 17:39:12 -04001812 def select(conn, options):
1813 raise TypeError
Cory Benfield0ea76e72015-03-22 09:05:28 +00001814
Cory Benfieldba1820d2015-04-13 17:39:12 -04001815 server_context = Context(TLSv1_METHOD)
1816 server_context.set_npn_advertise_callback(advertise)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001817
Cory Benfieldba1820d2015-04-13 17:39:12 -04001818 client_context = Context(TLSv1_METHOD)
1819 client_context.set_npn_select_callback(select)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001820
Cory Benfieldba1820d2015-04-13 17:39:12 -04001821 # Necessary to actually accept the connection
1822 server_context.use_privatekey(
1823 load_privatekey(FILETYPE_PEM, server_key_pem))
1824 server_context.use_certificate(
1825 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield0ea76e72015-03-22 09:05:28 +00001826
Cory Benfieldba1820d2015-04-13 17:39:12 -04001827 # Do a little connection to trigger the logic
1828 server = Connection(server_context, None)
1829 server.set_accept_state()
Cory Benfield0ea76e72015-03-22 09:05:28 +00001830
Cory Benfieldba1820d2015-04-13 17:39:12 -04001831 client = Connection(client_context, None)
1832 client.set_connect_state()
Cory Benfield0ea76e72015-03-22 09:05:28 +00001833
Cory Benfieldba1820d2015-04-13 17:39:12 -04001834 # If the callback throws an exception it should be raised here.
1835 self.assertRaises(
1836 TypeError, self._interactInMemory, server, client
1837 )
1838 self.assertEqual([(server,)], advertise_args)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001839
Cory Benfieldba1820d2015-04-13 17:39:12 -04001840 def test_npn_advertise_error(self):
1841 """
1842 Test that we can handle exceptions in the advertise callback. If
1843 advertise fails no NPN is advertised to the client.
1844 """
1845 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001846
Cory Benfieldba1820d2015-04-13 17:39:12 -04001847 def advertise(conn):
1848 raise TypeError
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001849
Hynek Schlawackb4ceed32015-09-05 20:55:19 +02001850 def select(conn, options): # pragma: nocover
1851 """
1852 Assert later that no args are actually appended.
1853 """
Cory Benfieldba1820d2015-04-13 17:39:12 -04001854 select_args.append((conn, options))
1855 return b''
Cory Benfield0ea76e72015-03-22 09:05:28 +00001856
Cory Benfieldba1820d2015-04-13 17:39:12 -04001857 server_context = Context(TLSv1_METHOD)
1858 server_context.set_npn_advertise_callback(advertise)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001859
Cory Benfieldba1820d2015-04-13 17:39:12 -04001860 client_context = Context(TLSv1_METHOD)
1861 client_context.set_npn_select_callback(select)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001862
Cory Benfieldba1820d2015-04-13 17:39:12 -04001863 # Necessary to actually accept the connection
1864 server_context.use_privatekey(
1865 load_privatekey(FILETYPE_PEM, server_key_pem))
1866 server_context.use_certificate(
1867 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield0ea76e72015-03-22 09:05:28 +00001868
Cory Benfieldba1820d2015-04-13 17:39:12 -04001869 # Do a little connection to trigger the logic
1870 server = Connection(server_context, None)
1871 server.set_accept_state()
Cory Benfield0ea76e72015-03-22 09:05:28 +00001872
Cory Benfieldba1820d2015-04-13 17:39:12 -04001873 client = Connection(client_context, None)
1874 client.set_connect_state()
Cory Benfield0ea76e72015-03-22 09:05:28 +00001875
Cory Benfieldba1820d2015-04-13 17:39:12 -04001876 # If the client doesn't return anything, the connection will fail.
1877 self.assertRaises(
1878 TypeError, self._interactInMemory, server, client
1879 )
1880 self.assertEqual([], select_args)
1881
1882 else:
1883 # No NPN.
1884 def test_npn_not_implemented(self):
1885 # Test the context methods first.
1886 context = Context(TLSv1_METHOD)
1887 fail_methods = [
1888 context.set_npn_advertise_callback,
1889 context.set_npn_select_callback,
1890 ]
1891 for method in fail_methods:
1892 self.assertRaises(
1893 NotImplementedError, method, None
1894 )
1895
1896 # Now test a connection.
1897 conn = Connection(context)
1898 fail_methods = [
1899 conn.get_next_proto_negotiated,
1900 ]
1901 for method in fail_methods:
1902 self.assertRaises(NotImplementedError, method)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001903
1904
Cory Benfield12eae892014-06-07 15:42:56 +01001905class ApplicationLayerProtoNegotiationTests(TestCase, _LoopbackMixin):
1906 """
1907 Tests for ALPN in PyOpenSSL.
1908 """
Cory Benfielde46fa842015-04-13 16:50:49 -04001909 # Skip tests on versions that don't support ALPN.
1910 if _lib.Cryptography_HAS_ALPN:
Cory Benfield12eae892014-06-07 15:42:56 +01001911
Cory Benfielde46fa842015-04-13 16:50:49 -04001912 def test_alpn_success(self):
1913 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04001914 Clients and servers that agree on the negotiated ALPN protocol can
1915 correct establish a connection, and the agreed protocol is reported
1916 by the connections.
Cory Benfielde46fa842015-04-13 16:50:49 -04001917 """
1918 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001919
Cory Benfielde46fa842015-04-13 16:50:49 -04001920 def select(conn, options):
1921 select_args.append((conn, options))
1922 return b'spdy/2'
Cory Benfield12eae892014-06-07 15:42:56 +01001923
Cory Benfielde46fa842015-04-13 16:50:49 -04001924 client_context = Context(TLSv1_METHOD)
1925 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfield12eae892014-06-07 15:42:56 +01001926
Cory Benfielde46fa842015-04-13 16:50:49 -04001927 server_context = Context(TLSv1_METHOD)
1928 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01001929
Cory Benfielde46fa842015-04-13 16:50:49 -04001930 # Necessary to actually accept the connection
1931 server_context.use_privatekey(
1932 load_privatekey(FILETYPE_PEM, server_key_pem))
1933 server_context.use_certificate(
1934 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield12eae892014-06-07 15:42:56 +01001935
Cory Benfielde46fa842015-04-13 16:50:49 -04001936 # Do a little connection to trigger the logic
1937 server = Connection(server_context, None)
1938 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001939
Cory Benfielde46fa842015-04-13 16:50:49 -04001940 client = Connection(client_context, None)
1941 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001942
Cory Benfielde46fa842015-04-13 16:50:49 -04001943 self._interactInMemory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001944
Cory Benfielde46fa842015-04-13 16:50:49 -04001945 self.assertEqual([(server, [b'http/1.1', b'spdy/2'])], select_args)
1946
1947 self.assertEqual(server.get_alpn_proto_negotiated(), b'spdy/2')
1948 self.assertEqual(client.get_alpn_proto_negotiated(), b'spdy/2')
Cory Benfield12eae892014-06-07 15:42:56 +01001949
Cory Benfielde46fa842015-04-13 16:50:49 -04001950 def test_alpn_set_on_connection(self):
1951 """
1952 The same as test_alpn_success, but setting the ALPN protocols on
1953 the connection rather than the context.
1954 """
1955 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001956
Cory Benfielde46fa842015-04-13 16:50:49 -04001957 def select(conn, options):
1958 select_args.append((conn, options))
1959 return b'spdy/2'
Cory Benfield12eae892014-06-07 15:42:56 +01001960
Cory Benfielde46fa842015-04-13 16:50:49 -04001961 # Setup the client context but don't set any ALPN protocols.
1962 client_context = Context(TLSv1_METHOD)
Cory Benfield12eae892014-06-07 15:42:56 +01001963
Cory Benfielde46fa842015-04-13 16:50:49 -04001964 server_context = Context(TLSv1_METHOD)
1965 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01001966
Cory Benfielde46fa842015-04-13 16:50:49 -04001967 # Necessary to actually accept the connection
1968 server_context.use_privatekey(
1969 load_privatekey(FILETYPE_PEM, server_key_pem))
1970 server_context.use_certificate(
1971 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield12eae892014-06-07 15:42:56 +01001972
Cory Benfielde46fa842015-04-13 16:50:49 -04001973 # Do a little connection to trigger the logic
1974 server = Connection(server_context, None)
1975 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001976
Cory Benfielde46fa842015-04-13 16:50:49 -04001977 # Set the ALPN protocols on the client connection.
1978 client = Connection(client_context, None)
1979 client.set_alpn_protos([b'http/1.1', b'spdy/2'])
1980 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001981
Cory Benfielde46fa842015-04-13 16:50:49 -04001982 self._interactInMemory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001983
Cory Benfielde46fa842015-04-13 16:50:49 -04001984 self.assertEqual([(server, [b'http/1.1', b'spdy/2'])], select_args)
Cory Benfield12eae892014-06-07 15:42:56 +01001985
Cory Benfielde46fa842015-04-13 16:50:49 -04001986 self.assertEqual(server.get_alpn_proto_negotiated(), b'spdy/2')
1987 self.assertEqual(client.get_alpn_proto_negotiated(), b'spdy/2')
Cory Benfield12eae892014-06-07 15:42:56 +01001988
Cory Benfielde46fa842015-04-13 16:50:49 -04001989 def test_alpn_server_fail(self):
1990 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04001991 When clients and servers cannot agree on what protocol to use next
1992 the TLS connection does not get established.
Cory Benfielde46fa842015-04-13 16:50:49 -04001993 """
1994 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001995
Cory Benfielde46fa842015-04-13 16:50:49 -04001996 def select(conn, options):
1997 select_args.append((conn, options))
1998 return b''
Cory Benfield12eae892014-06-07 15:42:56 +01001999
Cory Benfielde46fa842015-04-13 16:50:49 -04002000 client_context = Context(TLSv1_METHOD)
2001 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfield12eae892014-06-07 15:42:56 +01002002
Cory Benfielde46fa842015-04-13 16:50:49 -04002003 server_context = Context(TLSv1_METHOD)
2004 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01002005
Cory Benfielde46fa842015-04-13 16:50:49 -04002006 # Necessary to actually accept the connection
2007 server_context.use_privatekey(
2008 load_privatekey(FILETYPE_PEM, server_key_pem))
2009 server_context.use_certificate(
2010 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield12eae892014-06-07 15:42:56 +01002011
Cory Benfielde46fa842015-04-13 16:50:49 -04002012 # Do a little connection to trigger the logic
2013 server = Connection(server_context, None)
2014 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01002015
Cory Benfielde46fa842015-04-13 16:50:49 -04002016 client = Connection(client_context, None)
2017 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01002018
Cory Benfielde46fa842015-04-13 16:50:49 -04002019 # If the client doesn't return anything, the connection will fail.
2020 self.assertRaises(Error, self._interactInMemory, server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01002021
Cory Benfielde46fa842015-04-13 16:50:49 -04002022 self.assertEqual([(server, [b'http/1.1', b'spdy/2'])], select_args)
Cory Benfield12eae892014-06-07 15:42:56 +01002023
Cory Benfielde46fa842015-04-13 16:50:49 -04002024 def test_alpn_no_server(self):
2025 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04002026 When clients and servers cannot agree on what protocol to use next
2027 because the server doesn't offer ALPN, no protocol is negotiated.
Cory Benfielde46fa842015-04-13 16:50:49 -04002028 """
2029 client_context = Context(TLSv1_METHOD)
2030 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfielde3d57152015-04-11 17:57:35 -04002031
Cory Benfielde46fa842015-04-13 16:50:49 -04002032 server_context = Context(TLSv1_METHOD)
Cory Benfielde3d57152015-04-11 17:57:35 -04002033
Cory Benfielde46fa842015-04-13 16:50:49 -04002034 # Necessary to actually accept the connection
2035 server_context.use_privatekey(
2036 load_privatekey(FILETYPE_PEM, server_key_pem))
2037 server_context.use_certificate(
2038 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfielde3d57152015-04-11 17:57:35 -04002039
Cory Benfielde46fa842015-04-13 16:50:49 -04002040 # Do a little connection to trigger the logic
2041 server = Connection(server_context, None)
2042 server.set_accept_state()
Cory Benfielde3d57152015-04-11 17:57:35 -04002043
Cory Benfielde46fa842015-04-13 16:50:49 -04002044 client = Connection(client_context, None)
2045 client.set_connect_state()
Cory Benfielde3d57152015-04-11 17:57:35 -04002046
Cory Benfielde46fa842015-04-13 16:50:49 -04002047 # Do the dance.
2048 self._interactInMemory(server, client)
Cory Benfielde3d57152015-04-11 17:57:35 -04002049
Cory Benfielde46fa842015-04-13 16:50:49 -04002050 self.assertEqual(client.get_alpn_proto_negotiated(), b'')
Cory Benfielde3d57152015-04-11 17:57:35 -04002051
Cory Benfielde46fa842015-04-13 16:50:49 -04002052 def test_alpn_callback_exception(self):
2053 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04002054 We can handle exceptions in the ALPN select callback.
Cory Benfielde46fa842015-04-13 16:50:49 -04002055 """
2056 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002057
Cory Benfielde46fa842015-04-13 16:50:49 -04002058 def select(conn, options):
2059 select_args.append((conn, options))
Cory Benfieldef401452015-04-13 18:17:36 -04002060 raise TypeError()
Cory Benfieldf1177e72015-04-12 09:11:49 -04002061
Cory Benfielde46fa842015-04-13 16:50:49 -04002062 client_context = Context(TLSv1_METHOD)
2063 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfieldf1177e72015-04-12 09:11:49 -04002064
Cory Benfielde46fa842015-04-13 16:50:49 -04002065 server_context = Context(TLSv1_METHOD)
2066 server_context.set_alpn_select_callback(select)
Cory Benfieldf1177e72015-04-12 09:11:49 -04002067
Cory Benfielde46fa842015-04-13 16:50:49 -04002068 # Necessary to actually accept the connection
2069 server_context.use_privatekey(
2070 load_privatekey(FILETYPE_PEM, server_key_pem))
2071 server_context.use_certificate(
2072 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfieldf1177e72015-04-12 09:11:49 -04002073
Cory Benfielde46fa842015-04-13 16:50:49 -04002074 # Do a little connection to trigger the logic
2075 server = Connection(server_context, None)
2076 server.set_accept_state()
Cory Benfieldf1177e72015-04-12 09:11:49 -04002077
Cory Benfielde46fa842015-04-13 16:50:49 -04002078 client = Connection(client_context, None)
2079 client.set_connect_state()
Cory Benfieldf1177e72015-04-12 09:11:49 -04002080
Cory Benfielde46fa842015-04-13 16:50:49 -04002081 self.assertRaises(
2082 TypeError, self._interactInMemory, server, client
2083 )
2084 self.assertEqual([(server, [b'http/1.1', b'spdy/2'])], select_args)
Cory Benfieldf1177e72015-04-12 09:11:49 -04002085
Cory Benfield0f7b04c2015-04-13 17:51:12 -04002086 else:
2087 # No ALPN.
2088 def test_alpn_not_implemented(self):
Cory Benfieldef401452015-04-13 18:17:36 -04002089 """
2090 If ALPN is not in OpenSSL, we should raise NotImplementedError.
2091 """
Cory Benfield0f7b04c2015-04-13 17:51:12 -04002092 # Test the context methods first.
2093 context = Context(TLSv1_METHOD)
Cory Benfield307e9e62015-04-13 18:21:12 -04002094 self.assertRaises(
2095 NotImplementedError, context.set_alpn_protos, None
2096 )
2097 self.assertRaises(
2098 NotImplementedError, context.set_alpn_select_callback, None
2099 )
Cory Benfield0f7b04c2015-04-13 17:51:12 -04002100
2101 # Now test a connection.
2102 conn = Connection(context)
Cory Benfield307e9e62015-04-13 18:21:12 -04002103 self.assertRaises(
Alex Gaynor68417232015-09-04 07:56:29 -04002104 NotImplementedError, conn.set_alpn_protos, None
Cory Benfield307e9e62015-04-13 18:21:12 -04002105 )
Cory Benfield0f7b04c2015-04-13 17:51:12 -04002106
Cory Benfieldf1177e72015-04-12 09:11:49 -04002107
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05002108class SessionTests(TestCase):
2109 """
2110 Unit tests for :py:obj:`OpenSSL.SSL.Session`.
2111 """
2112 def test_construction(self):
2113 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002114 :py:class:`Session` can be constructed with no arguments, creating
2115 a new instance of that type.
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05002116 """
2117 new_session = Session()
2118 self.assertTrue(isinstance(new_session, Session))
2119
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05002120 def test_construction_wrong_args(self):
2121 """
2122 If any arguments are passed to :py:class:`Session`, :py:obj:`TypeError`
2123 is raised.
2124 """
2125 self.assertRaises(TypeError, Session, 123)
2126 self.assertRaises(TypeError, Session, "hello")
2127 self.assertRaises(TypeError, Session, object())
2128
2129
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002130class ConnectionTests(TestCase, _LoopbackMixin):
Rick Deane15b1472009-07-09 15:53:42 -05002131 """
Hynek Schlawackaa861212016-03-13 13:53:48 +01002132 Unit tests for :class:`OpenSSL.SSL.Connection`.
Rick Deane15b1472009-07-09 15:53:42 -05002133 """
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04002134 # XXX get_peer_certificate -> None
2135 # XXX sock_shutdown
2136 # XXX master_key -> TypeError
2137 # XXX server_random -> TypeError
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04002138 # XXX connect -> TypeError
2139 # XXX connect_ex -> TypeError
2140 # XXX set_connect_state -> TypeError
2141 # XXX set_accept_state -> TypeError
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04002142 # XXX do_handshake -> TypeError
2143 # XXX bio_read -> TypeError
2144 # XXX recv -> TypeError
2145 # XXX send -> TypeError
2146 # XXX bio_write -> TypeError
2147
Rick Deane15b1472009-07-09 15:53:42 -05002148 def test_type(self):
2149 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002150 :py:obj:`Connection` and :py:obj:`ConnectionType` refer to the same
2151 type object and can be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -05002152 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002153 self.assertIdentical(Connection, ConnectionType)
Rick Deane15b1472009-07-09 15:53:42 -05002154 ctx = Context(TLSv1_METHOD)
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002155 self.assertConsistentType(Connection, 'Connection', ctx, None)
Rick Deane15b1472009-07-09 15:53:42 -05002156
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002157 def test_get_context(self):
2158 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002159 :py:obj:`Connection.get_context` returns the :py:obj:`Context` instance
2160 used to construct the :py:obj:`Connection` instance.
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002161 """
2162 context = Context(TLSv1_METHOD)
2163 connection = Connection(context, None)
2164 self.assertIdentical(connection.get_context(), context)
2165
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002166 def test_get_context_wrong_args(self):
2167 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002168 :py:obj:`Connection.get_context` raises :py:obj:`TypeError` if called
2169 with any arguments.
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002170 """
2171 connection = Connection(Context(TLSv1_METHOD), None)
2172 self.assertRaises(TypeError, connection.get_context, None)
2173
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002174 def test_set_context_wrong_args(self):
2175 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002176 :py:obj:`Connection.set_context` raises :py:obj:`TypeError` if called
2177 with a non-:py:obj:`Context` instance argument or with any number of
2178 arguments other than 1.
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002179 """
2180 ctx = Context(TLSv1_METHOD)
2181 connection = Connection(ctx, None)
2182 self.assertRaises(TypeError, connection.set_context)
2183 self.assertRaises(TypeError, connection.set_context, object())
2184 self.assertRaises(TypeError, connection.set_context, "hello")
2185 self.assertRaises(TypeError, connection.set_context, 1)
2186 self.assertRaises(TypeError, connection.set_context, 1, 2)
2187 self.assertRaises(
2188 TypeError, connection.set_context, Context(TLSv1_METHOD), 2)
2189 self.assertIdentical(ctx, connection.get_context())
2190
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002191 def test_set_context(self):
2192 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002193 :py:obj:`Connection.set_context` specifies a new :py:obj:`Context`
2194 instance to be used for the connection.
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002195 """
2196 original = Context(SSLv23_METHOD)
2197 replacement = Context(TLSv1_METHOD)
2198 connection = Connection(original, None)
2199 connection.set_context(replacement)
2200 self.assertIdentical(replacement, connection.get_context())
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002201 # Lose our references to the contexts, just in case the Connection
2202 # isn't properly managing its own contributions to their reference
2203 # counts.
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002204 del original, replacement
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002205 collect()
2206
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002207 def test_set_tlsext_host_name_wrong_args(self):
2208 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002209 If :py:obj:`Connection.set_tlsext_host_name` is called with a non-byte
2210 string argument or a byte string with an embedded NUL or other than one
Jonathan Ballet648875f2011-07-16 14:14:58 +09002211 argument, :py:obj:`TypeError` is raised.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002212 """
2213 conn = Connection(Context(TLSv1_METHOD), None)
2214 self.assertRaises(TypeError, conn.set_tlsext_host_name)
2215 self.assertRaises(TypeError, conn.set_tlsext_host_name, object())
2216 self.assertRaises(TypeError, conn.set_tlsext_host_name, 123, 456)
2217 self.assertRaises(
2218 TypeError, conn.set_tlsext_host_name, b("with\0null"))
2219
Abraham Martinc5484ba2015-03-25 15:33:05 +00002220 if PY3:
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002221 # On Python 3.x, don't accidentally implicitly convert from text.
2222 self.assertRaises(
2223 TypeError,
2224 conn.set_tlsext_host_name, b("example.com").decode("ascii"))
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002225
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04002226 def test_get_servername_wrong_args(self):
2227 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002228 :py:obj:`Connection.get_servername` raises :py:obj:`TypeError` if
2229 called with any arguments.
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04002230 """
2231 connection = Connection(Context(TLSv1_METHOD), None)
2232 self.assertRaises(TypeError, connection.get_servername, object())
2233 self.assertRaises(TypeError, connection.get_servername, 1)
2234 self.assertRaises(TypeError, connection.get_servername, "hello")
2235
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002236 def test_pending(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002237 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002238 :py:obj:`Connection.pending` returns the number of bytes available for
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002239 immediate read.
2240 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002241 connection = Connection(Context(TLSv1_METHOD), None)
2242 self.assertEquals(connection.pending(), 0)
2243
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002244 def test_pending_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002245 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002246 :py:obj:`Connection.pending` raises :py:obj:`TypeError` if called with
2247 any arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002248 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002249 connection = Connection(Context(TLSv1_METHOD), None)
2250 self.assertRaises(TypeError, connection.pending, None)
2251
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002252 def test_peek(self):
2253 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002254 :py:obj:`Connection.recv` peeks into the connection if
2255 :py:obj:`socket.MSG_PEEK` is passed.
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002256 """
2257 server, client = self._loopback()
2258 server.send(b('xy'))
2259 self.assertEqual(client.recv(2, MSG_PEEK), b('xy'))
2260 self.assertEqual(client.recv(2, MSG_PEEK), b('xy'))
2261 self.assertEqual(client.recv(2), b('xy'))
2262
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002263 def test_connect_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002264 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002265 :py:obj:`Connection.connect` raises :py:obj:`TypeError` if called with
2266 a non-address argument or with the wrong number of arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002267 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002268 connection = Connection(Context(TLSv1_METHOD), socket())
2269 self.assertRaises(TypeError, connection.connect, None)
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002270 self.assertRaises(TypeError, connection.connect)
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002271 self.assertRaises(
2272 TypeError, connection.connect, ("127.0.0.1", 1), None
2273 )
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002274
kjavfe508d62015-09-02 12:20:35 +01002275 def test_connection_undefined_attr(self):
2276 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002277 :py:obj:`Connection.connect` raises :py:obj:`TypeError` if called with
2278 a non-address argument or with the wrong number of arguments.
kjavfe508d62015-09-02 12:20:35 +01002279 """
Alex Gaynor1aabb2e2015-09-05 13:35:18 -04002280
kjavfe508d62015-09-02 12:20:35 +01002281 def attr_access_test(connection):
2282 return connection.an_attribute_which_is_not_defined
Alex Gaynor1aabb2e2015-09-05 13:35:18 -04002283
kjavfe508d62015-09-02 12:20:35 +01002284 connection = Connection(Context(TLSv1_METHOD), None)
2285 self.assertRaises(AttributeError, attr_access_test, connection)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002286
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002287 def test_connect_refused(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002288 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002289 :py:obj:`Connection.connect` raises :py:obj:`socket.error` if the
2290 underlying socket connect method raises it.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002291 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002292 client = socket()
2293 context = Context(TLSv1_METHOD)
2294 clientSSL = Connection(context, client)
Alex Gaynor122717b2015-09-05 14:14:18 -04002295 # pytest.raises here doesn't work because of a bug in py.test on Python
2296 # 2.6: https://github.com/pytest-dev/pytest/issues/988
Alex Gaynore69c2782015-09-05 14:07:48 -04002297 try:
Alex Gaynor1aabb2e2015-09-05 13:35:18 -04002298 clientSSL.connect(("127.0.0.1", 1))
Alex Gaynore69c2782015-09-05 14:07:48 -04002299 except error as e:
Alex Gaynor20a4c082015-09-05 14:24:15 -04002300 exc = e
2301 assert exc.args[0] == ECONNREFUSED
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002302
2303 def test_connect(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002304 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002305 :py:obj:`Connection.connect` establishes a connection to the specified
2306 address.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002307 """
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002308 port = socket()
2309 port.bind(('', 0))
2310 port.listen(3)
2311
2312 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002313 clientSSL.connect(('127.0.0.1', port.getsockname()[1]))
2314 # XXX An assertion? Or something?
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002315
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002316 @pytest.mark.skipif(
2317 platform == "darwin",
2318 reason="connect_ex sometimes causes a kernel panic on OS X 10.6.4"
2319 )
2320 def test_connect_ex(self):
2321 """
2322 If there is a connection error, :py:obj:`Connection.connect_ex`
2323 returns the errno instead of raising an exception.
2324 """
2325 port = socket()
2326 port.bind(('', 0))
2327 port.listen(3)
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002328
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002329 clientSSL = Connection(Context(TLSv1_METHOD), socket())
2330 clientSSL.setblocking(False)
2331 result = clientSSL.connect_ex(port.getsockname())
2332 expected = (EINPROGRESS, EWOULDBLOCK)
2333 self.assertTrue(
2334 result in expected, "%r not in %r" % (result, expected))
Jean-Paul Calderone55d91f42010-07-29 19:22:17 -04002335
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002336 def test_accept_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002337 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002338 :py:obj:`Connection.accept` raises :py:obj:`TypeError` if called with
2339 any arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002340 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002341 connection = Connection(Context(TLSv1_METHOD), socket())
2342 self.assertRaises(TypeError, connection.accept, None)
2343
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002344 def test_accept(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002345 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002346 :py:obj:`Connection.accept` accepts a pending connection attempt and
2347 returns a tuple of a new :py:obj:`Connection` (the accepted client) and
2348 the address the connection originated from.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002349 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002350 ctx = Context(TLSv1_METHOD)
2351 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2352 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002353 port = socket()
2354 portSSL = Connection(ctx, port)
2355 portSSL.bind(('', 0))
2356 portSSL.listen(3)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002357
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002358 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002359
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002360 # Calling portSSL.getsockname() here to get the server IP address
2361 # sounds great, but frequently fails on Windows.
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002362 clientSSL.connect(('127.0.0.1', portSSL.getsockname()[1]))
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002363
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002364 serverSSL, address = portSSL.accept()
2365
2366 self.assertTrue(isinstance(serverSSL, Connection))
2367 self.assertIdentical(serverSSL.get_context(), ctx)
2368 self.assertEquals(address, clientSSL.getsockname())
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002369
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002370 def test_shutdown_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002371 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002372 :py:obj:`Connection.shutdown` raises :py:obj:`TypeError` if called with
2373 the wrong number of arguments or with arguments other than integers.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002374 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002375 connection = Connection(Context(TLSv1_METHOD), None)
2376 self.assertRaises(TypeError, connection.shutdown, None)
Jean-Paul Calderone1d3e0222010-07-29 22:52:45 -04002377 self.assertRaises(TypeError, connection.get_shutdown, None)
2378 self.assertRaises(TypeError, connection.set_shutdown)
2379 self.assertRaises(TypeError, connection.set_shutdown, None)
2380 self.assertRaises(TypeError, connection.set_shutdown, 0, 1)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002381
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002382 def test_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002383 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002384 :py:obj:`Connection.shutdown` performs an SSL-level connection
2385 shutdown.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002386 """
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002387 server, client = self._loopback()
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04002388 self.assertFalse(server.shutdown())
2389 self.assertEquals(server.get_shutdown(), SENT_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002390 self.assertRaises(ZeroReturnError, client.recv, 1024)
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04002391 self.assertEquals(client.get_shutdown(), RECEIVED_SHUTDOWN)
2392 client.shutdown()
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002393 self.assertEquals(
2394 client.get_shutdown(), SENT_SHUTDOWN | RECEIVED_SHUTDOWN
2395 )
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04002396 self.assertRaises(ZeroReturnError, server.recv, 1024)
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002397 self.assertEquals(
2398 server.get_shutdown(), SENT_SHUTDOWN | RECEIVED_SHUTDOWN
2399 )
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002400
Paul Aurichc85e0862015-01-08 08:34:33 -08002401 def test_shutdown_closed(self):
2402 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002403 If the underlying socket is closed, :py:obj:`Connection.shutdown`
2404 propagates the write error from the low level write call.
Paul Aurichc85e0862015-01-08 08:34:33 -08002405 """
2406 server, client = self._loopback()
2407 server.sock_shutdown(2)
2408 exc = self.assertRaises(SysCallError, server.shutdown)
2409 if platform == "win32":
2410 self.assertEqual(exc.args[0], ESHUTDOWN)
2411 else:
2412 self.assertEqual(exc.args[0], EPIPE)
2413
Glyph89389472015-04-14 17:29:26 -04002414 def test_shutdown_truncated(self):
Glyph6064ec32015-04-14 16:38:22 -04002415 """
Glyph89389472015-04-14 17:29:26 -04002416 If the underlying connection is truncated, :obj:`Connection.shutdown`
2417 raises an :obj:`Error`.
Glyph6064ec32015-04-14 16:38:22 -04002418 """
Glyph89389472015-04-14 17:29:26 -04002419 server_ctx = Context(TLSv1_METHOD)
2420 client_ctx = Context(TLSv1_METHOD)
2421 server_ctx.use_privatekey(
2422 load_privatekey(FILETYPE_PEM, server_key_pem))
2423 server_ctx.use_certificate(
2424 load_certificate(FILETYPE_PEM, server_cert_pem))
2425 server = Connection(server_ctx, None)
2426 client = Connection(client_ctx, None)
2427 self._handshakeInMemory(client, server)
2428 self.assertEqual(server.shutdown(), False)
2429 self.assertRaises(WantReadError, server.shutdown)
2430 server.bio_shutdown()
Glyph6064ec32015-04-14 16:38:22 -04002431 self.assertRaises(Error, server.shutdown)
2432
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002433 def test_set_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002434 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002435 :py:obj:`Connection.set_shutdown` sets the state of the SSL connection
2436 shutdown process.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002437 """
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002438 connection = Connection(Context(TLSv1_METHOD), socket())
2439 connection.set_shutdown(RECEIVED_SHUTDOWN)
2440 self.assertEquals(connection.get_shutdown(), RECEIVED_SHUTDOWN)
2441
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002442 @skip_if_py3
2443 def test_set_shutdown_long(self):
2444 """
2445 On Python 2 :py:obj:`Connection.set_shutdown` accepts an argument
2446 of type :py:obj:`long` as well as :py:obj:`int`.
2447 """
2448 connection = Connection(Context(TLSv1_METHOD), socket())
2449 connection.set_shutdown(long(RECEIVED_SHUTDOWN))
2450 self.assertEquals(connection.get_shutdown(), RECEIVED_SHUTDOWN)
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -05002451
kjavaf248592015-09-07 12:14:01 +01002452 def test_state_string(self):
2453 """
Hynek Schlawackb0274ce2015-10-16 19:56:26 +02002454 :meth:`Connection.state_string` verbosely describes the current
2455 state of the :class:`Connection`.
kjavaf248592015-09-07 12:14:01 +01002456 """
Hynek Schlawackb0274ce2015-10-16 19:56:26 +02002457 server, client = socket_pair()
kjavaf248592015-09-07 12:14:01 +01002458 server = self._loopbackServerFactory(server)
2459 client = self._loopbackClientFactory(client)
2460
Hynek Schlawackea94f2b2016-03-13 16:17:53 +01002461 assert b"before/accept initialization" == server.get_state_string()
2462 assert b"before/connect initialization" == client.get_state_string()
kjavaf248592015-09-07 12:14:01 +01002463
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002464 def test_app_data_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002465 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002466 :py:obj:`Connection.set_app_data` raises :py:obj:`TypeError` if called
2467 with other than one argument. :py:obj:`Connection.get_app_data` raises
2468 :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002469 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002470 conn = Connection(Context(TLSv1_METHOD), None)
2471 self.assertRaises(TypeError, conn.get_app_data, None)
2472 self.assertRaises(TypeError, conn.set_app_data)
2473 self.assertRaises(TypeError, conn.set_app_data, None, None)
2474
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002475 def test_app_data(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002476 """
2477 Any object can be set as app data by passing it to
Jonathan Ballet648875f2011-07-16 14:14:58 +09002478 :py:obj:`Connection.set_app_data` and later retrieved with
2479 :py:obj:`Connection.get_app_data`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002480 """
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002481 conn = Connection(Context(TLSv1_METHOD), None)
Todd Chapman4f73e4f2015-08-27 11:26:43 -04002482 assert None is conn.get_app_data()
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002483 app_data = object()
2484 conn.set_app_data(app_data)
Todd Chapman4f73e4f2015-08-27 11:26:43 -04002485 assert conn.get_app_data() is app_data
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002486
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002487 def test_makefile(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002488 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002489 :py:obj:`Connection.makefile` is not implemented and calling that
2490 method raises :py:obj:`NotImplementedError`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002491 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002492 conn = Connection(Context(TLSv1_METHOD), None)
2493 self.assertRaises(NotImplementedError, conn.makefile)
2494
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002495 def test_get_peer_cert_chain_wrong_args(self):
2496 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002497 :py:obj:`Connection.get_peer_cert_chain` raises :py:obj:`TypeError` if
2498 called with any arguments.
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002499 """
2500 conn = Connection(Context(TLSv1_METHOD), None)
2501 self.assertRaises(TypeError, conn.get_peer_cert_chain, 1)
2502 self.assertRaises(TypeError, conn.get_peer_cert_chain, "foo")
2503 self.assertRaises(TypeError, conn.get_peer_cert_chain, object())
2504 self.assertRaises(TypeError, conn.get_peer_cert_chain, [])
2505
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002506 def test_get_peer_cert_chain(self):
2507 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002508 :py:obj:`Connection.get_peer_cert_chain` returns a list of certificates
2509 which the connected server returned for the certification verification.
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002510 """
2511 chain = _create_certificate_chain()
2512 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
2513
2514 serverContext = Context(TLSv1_METHOD)
2515 serverContext.use_privatekey(skey)
2516 serverContext.use_certificate(scert)
2517 serverContext.add_extra_chain_cert(icert)
2518 serverContext.add_extra_chain_cert(cacert)
2519 server = Connection(serverContext, None)
2520 server.set_accept_state()
2521
2522 # Create the client
2523 clientContext = Context(TLSv1_METHOD)
2524 clientContext.set_verify(VERIFY_NONE, verify_cb)
2525 client = Connection(clientContext, None)
2526 client.set_connect_state()
2527
2528 self._interactInMemory(client, server)
2529
2530 chain = client.get_peer_cert_chain()
2531 self.assertEqual(len(chain), 3)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04002532 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002533 "Server Certificate", chain[0].get_subject().CN)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04002534 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002535 "Intermediate Certificate", chain[1].get_subject().CN)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04002536 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002537 "Authority Certificate", chain[2].get_subject().CN)
2538
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002539 def test_get_peer_cert_chain_none(self):
2540 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002541 :py:obj:`Connection.get_peer_cert_chain` returns :py:obj:`None` if the
2542 peer sends no certificate chain.
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002543 """
2544 ctx = Context(TLSv1_METHOD)
2545 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2546 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
2547 server = Connection(ctx, None)
2548 server.set_accept_state()
2549 client = Connection(Context(TLSv1_METHOD), None)
2550 client.set_connect_state()
2551 self._interactInMemory(client, server)
2552 self.assertIdentical(None, server.get_peer_cert_chain())
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002553
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002554 def test_get_session_wrong_args(self):
2555 """
2556 :py:obj:`Connection.get_session` raises :py:obj:`TypeError` if called
2557 with any arguments.
2558 """
2559 ctx = Context(TLSv1_METHOD)
2560 server = Connection(ctx, None)
2561 self.assertRaises(TypeError, server.get_session, 123)
2562 self.assertRaises(TypeError, server.get_session, "hello")
2563 self.assertRaises(TypeError, server.get_session, object())
2564
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002565 def test_get_session_unconnected(self):
2566 """
2567 :py:obj:`Connection.get_session` returns :py:obj:`None` when used with
2568 an object which has not been connected.
2569 """
2570 ctx = Context(TLSv1_METHOD)
2571 server = Connection(ctx, None)
2572 session = server.get_session()
2573 self.assertIdentical(None, session)
2574
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002575 def test_server_get_session(self):
2576 """
2577 On the server side of a connection, :py:obj:`Connection.get_session`
2578 returns a :py:class:`Session` instance representing the SSL session for
2579 that connection.
2580 """
2581 server, client = self._loopback()
2582 session = server.get_session()
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08002583 self.assertIsInstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002584
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002585 def test_client_get_session(self):
2586 """
2587 On the client side of a connection, :py:obj:`Connection.get_session`
2588 returns a :py:class:`Session` instance representing the SSL session for
2589 that connection.
2590 """
2591 server, client = self._loopback()
2592 session = client.get_session()
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08002593 self.assertIsInstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002594
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002595 def test_set_session_wrong_args(self):
2596 """
Hynek Schlawackdddd1112015-09-05 21:12:30 +02002597 If called with an object that is not an instance of
2598 :py:class:`Session`, or with other than one argument,
2599 :py:obj:`Connection.set_session` raises :py:obj:`TypeError`.
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002600 """
2601 ctx = Context(TLSv1_METHOD)
2602 connection = Connection(ctx, None)
2603 self.assertRaises(TypeError, connection.set_session)
2604 self.assertRaises(TypeError, connection.set_session, 123)
2605 self.assertRaises(TypeError, connection.set_session, "hello")
2606 self.assertRaises(TypeError, connection.set_session, object())
2607 self.assertRaises(
2608 TypeError, connection.set_session, Session(), Session())
2609
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002610 def test_client_set_session(self):
2611 """
2612 :py:obj:`Connection.set_session`, when used prior to a connection being
2613 established, accepts a :py:class:`Session` instance and causes an
2614 attempt to re-use the session it represents when the SSL handshake is
2615 performed.
2616 """
2617 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2618 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
2619 ctx = Context(TLSv1_METHOD)
2620 ctx.use_privatekey(key)
2621 ctx.use_certificate(cert)
2622 ctx.set_session_id("unity-test")
2623
2624 def makeServer(socket):
2625 server = Connection(ctx, socket)
2626 server.set_accept_state()
2627 return server
2628
2629 originalServer, originalClient = self._loopback(
2630 serverFactory=makeServer)
2631 originalSession = originalClient.get_session()
2632
2633 def makeClient(socket):
2634 client = self._loopbackClientFactory(socket)
2635 client.set_session(originalSession)
2636 return client
2637 resumedServer, resumedClient = self._loopback(
2638 serverFactory=makeServer,
2639 clientFactory=makeClient)
2640
2641 # This is a proxy: in general, we have no access to any unique
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002642 # identifier for the session (new enough versions of OpenSSL expose
2643 # a hash which could be usable, but "new enough" is very, very new).
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002644 # Instead, exploit the fact that the master key is re-used if the
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002645 # session is re-used. As long as the master key for the two
2646 # connections is the same, the session was re-used!
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002647 self.assertEqual(
2648 originalServer.master_key(), resumedServer.master_key())
2649
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002650 def test_set_session_wrong_method(self):
2651 """
Jean-Paul Calderone068cb592012-02-14 16:52:43 -05002652 If :py:obj:`Connection.set_session` is passed a :py:class:`Session`
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002653 instance associated with a context using a different SSL method than
2654 the :py:obj:`Connection` is using, a :py:class:`OpenSSL.SSL.Error` is
Jean-Paul Calderone068cb592012-02-14 16:52:43 -05002655 raised.
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002656 """
2657 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2658 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
2659 ctx = Context(TLSv1_METHOD)
2660 ctx.use_privatekey(key)
2661 ctx.use_certificate(cert)
2662 ctx.set_session_id("unity-test")
2663
2664 def makeServer(socket):
2665 server = Connection(ctx, socket)
2666 server.set_accept_state()
2667 return server
2668
2669 originalServer, originalClient = self._loopback(
2670 serverFactory=makeServer)
2671 originalSession = originalClient.get_session()
2672
2673 def makeClient(socket):
2674 # Intentionally use a different, incompatible method here.
2675 client = Connection(Context(SSLv3_METHOD), socket)
2676 client.set_connect_state()
2677 client.set_session(originalSession)
2678 return client
2679
2680 self.assertRaises(
2681 Error,
2682 self._loopback, clientFactory=makeClient, serverFactory=makeServer)
2683
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002684 def test_wantWriteError(self):
2685 """
2686 :py:obj:`Connection` methods which generate output raise
2687 :py:obj:`OpenSSL.SSL.WantWriteError` if writing to the connection's BIO
2688 fail indicating a should-write state.
2689 """
2690 client_socket, server_socket = socket_pair()
2691 # Fill up the client's send buffer so Connection won't be able to write
Jean-Paul Calderonebbff8b92014-03-22 14:20:30 -04002692 # anything. Only write a single byte at a time so we can be sure we
2693 # completely fill the buffer. Even though the socket API is allowed to
2694 # signal a short write via its return value it seems this doesn't
2695 # always happen on all platforms (FreeBSD and OS X particular) for the
2696 # very last bit of available buffer space.
2697 msg = b"x"
2698 for i in range(1024 * 1024 * 4):
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002699 try:
2700 client_socket.send(msg)
2701 except error as e:
2702 if e.errno == EWOULDBLOCK:
2703 break
2704 raise
2705 else:
2706 self.fail(
2707 "Failed to fill socket buffer, cannot test BIO want write")
2708
2709 ctx = Context(TLSv1_METHOD)
2710 conn = Connection(ctx, client_socket)
2711 # Client's speak first, so make it an SSL client
2712 conn.set_connect_state()
2713 self.assertRaises(WantWriteError, conn.do_handshake)
2714
2715 # XXX want_read
2716
Fedor Brunner416f4a12014-03-28 13:18:38 +01002717 def test_get_finished_before_connect(self):
Fedor Brunner5747b932014-03-05 14:22:34 +01002718 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002719 :py:obj:`Connection.get_finished` returns :py:obj:`None` before TLS
2720 handshake is completed.
Fedor Brunner5747b932014-03-05 14:22:34 +01002721 """
Fedor Brunner5747b932014-03-05 14:22:34 +01002722 ctx = Context(TLSv1_METHOD)
2723 connection = Connection(ctx, None)
2724 self.assertEqual(connection.get_finished(), None)
Fedor Brunner416f4a12014-03-28 13:18:38 +01002725
2726 def test_get_peer_finished_before_connect(self):
2727 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002728 :py:obj:`Connection.get_peer_finished` returns :py:obj:`None` before
2729 TLS handshake is completed.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002730 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002731 ctx = Context(TLSv1_METHOD)
2732 connection = Connection(ctx, None)
Fedor Brunner5747b932014-03-05 14:22:34 +01002733 self.assertEqual(connection.get_peer_finished(), None)
2734
Fedor Brunner416f4a12014-03-28 13:18:38 +01002735 def test_get_finished(self):
2736 """
2737 :py:obj:`Connection.get_finished` method returns the TLS Finished
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002738 message send from client, or server. Finished messages are send during
2739 TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002740 """
2741
Fedor Brunner5747b932014-03-05 14:22:34 +01002742 server, client = self._loopback()
2743
2744 self.assertNotEqual(server.get_finished(), None)
2745 self.assertTrue(len(server.get_finished()) > 0)
Fedor Brunner416f4a12014-03-28 13:18:38 +01002746
2747 def test_get_peer_finished(self):
2748 """
2749 :py:obj:`Connection.get_peer_finished` method returns the TLS Finished
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002750 message received from client, or server. Finished messages are send
2751 during TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002752 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002753 server, client = self._loopback()
2754
2755 self.assertNotEqual(server.get_peer_finished(), None)
Fedor Brunner5747b932014-03-05 14:22:34 +01002756 self.assertTrue(len(server.get_peer_finished()) > 0)
2757
Fedor Brunner416f4a12014-03-28 13:18:38 +01002758 def test_tls_finished_message_symmetry(self):
2759 """
Hynek Schlawackdddd1112015-09-05 21:12:30 +02002760 The TLS Finished message send by server must be the TLS Finished
2761 message received by client.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002762
Hynek Schlawackdddd1112015-09-05 21:12:30 +02002763 The TLS Finished message send by client must be the TLS Finished
2764 message received by server.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002765 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002766 server, client = self._loopback()
2767
Fedor Brunner5747b932014-03-05 14:22:34 +01002768 self.assertEqual(server.get_finished(), client.get_peer_finished())
2769 self.assertEqual(client.get_finished(), server.get_peer_finished())
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002770
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002771 def test_get_cipher_name_before_connect(self):
2772 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002773 :py:obj:`Connection.get_cipher_name` returns :py:obj:`None` if no
2774 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002775 """
2776 ctx = Context(TLSv1_METHOD)
2777 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002778 self.assertIdentical(conn.get_cipher_name(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002779
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002780 def test_get_cipher_name(self):
2781 """
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002782 :py:obj:`Connection.get_cipher_name` returns a :py:class:`unicode`
2783 string giving the name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002784 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002785 server, client = self._loopback()
2786 server_cipher_name, client_cipher_name = \
2787 server.get_cipher_name(), client.get_cipher_name()
2788
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002789 self.assertIsInstance(server_cipher_name, text_type)
2790 self.assertIsInstance(client_cipher_name, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002791
2792 self.assertEqual(server_cipher_name, client_cipher_name)
2793
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002794 def test_get_cipher_version_before_connect(self):
2795 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002796 :py:obj:`Connection.get_cipher_version` returns :py:obj:`None` if no
2797 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002798 """
2799 ctx = Context(TLSv1_METHOD)
2800 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002801 self.assertIdentical(conn.get_cipher_version(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002802
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002803 def test_get_cipher_version(self):
2804 """
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002805 :py:obj:`Connection.get_cipher_version` returns a :py:class:`unicode`
2806 string giving the protocol name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002807 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002808 server, client = self._loopback()
2809 server_cipher_version, client_cipher_version = \
2810 server.get_cipher_version(), client.get_cipher_version()
2811
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002812 self.assertIsInstance(server_cipher_version, text_type)
2813 self.assertIsInstance(client_cipher_version, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002814
2815 self.assertEqual(server_cipher_version, client_cipher_version)
2816
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002817 def test_get_cipher_bits_before_connect(self):
2818 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002819 :py:obj:`Connection.get_cipher_bits` returns :py:obj:`None` if no
2820 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002821 """
2822 ctx = Context(TLSv1_METHOD)
2823 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002824 self.assertIdentical(conn.get_cipher_bits(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002825
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002826 def test_get_cipher_bits(self):
2827 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002828 :py:obj:`Connection.get_cipher_bits` returns the number of secret bits
2829 of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002830 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002831 server, client = self._loopback()
2832 server_cipher_bits, client_cipher_bits = \
2833 server.get_cipher_bits(), client.get_cipher_bits()
2834
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002835 self.assertIsInstance(server_cipher_bits, int)
2836 self.assertIsInstance(client_cipher_bits, int)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002837
2838 self.assertEqual(server_cipher_bits, client_cipher_bits)
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002839
Jim Shaverabff1882015-05-27 09:15:55 -04002840 def test_get_protocol_version_name(self):
2841 """
2842 :py:obj:`Connection.get_protocol_version_name()` returns a string
2843 giving the protocol version of the current connection.
2844 """
2845 server, client = self._loopback()
2846 client_protocol_version_name = client.get_protocol_version_name()
2847 server_protocol_version_name = server.get_protocol_version_name()
2848
Jim Shaver58d25732015-05-28 11:52:32 -04002849 self.assertIsInstance(server_protocol_version_name, text_type)
2850 self.assertIsInstance(client_protocol_version_name, text_type)
Jim Shaverabff1882015-05-27 09:15:55 -04002851
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002852 self.assertEqual(
2853 server_protocol_version_name, client_protocol_version_name
2854 )
Jim Shaverabff1882015-05-27 09:15:55 -04002855
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002856 def test_get_protocol_version(self):
2857 """
Alex Gaynor43307782015-09-04 09:05:45 -04002858 :py:obj:`Connection.get_protocol_version()` returns an integer
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002859 giving the protocol version of the current connection.
2860 """
2861 server, client = self._loopback()
Jim Shaver85a4dff2015-04-27 17:42:46 -04002862 client_protocol_version = client.get_protocol_version()
2863 server_protocol_version = server.get_protocol_version()
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002864
Jim Shaverabff1882015-05-27 09:15:55 -04002865 self.assertIsInstance(server_protocol_version, int)
2866 self.assertIsInstance(client_protocol_version, int)
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002867
2868 self.assertEqual(server_protocol_version, client_protocol_version)
2869
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002870
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002871class ConnectionGetCipherListTests(TestCase):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002872 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002873 Tests for :py:obj:`Connection.get_cipher_list`.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002874 """
Jean-Paul Calderone54a2bc02010-09-09 17:52:38 -04002875 def test_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002876 """
Hynek Schlawackdddd1112015-09-05 21:12:30 +02002877 :py:obj:`Connection.get_cipher_list` raises :py:obj:`TypeError` if
2878 called with any arguments.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002879 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002880 connection = Connection(Context(TLSv1_METHOD), None)
2881 self.assertRaises(TypeError, connection.get_cipher_list, None)
2882
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002883 def test_result(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002884 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002885 :py:obj:`Connection.get_cipher_list` returns a :py:obj:`list` of
2886 :py:obj:`bytes` giving the names of the ciphers which might be used.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002887 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002888 connection = Connection(Context(TLSv1_METHOD), None)
2889 ciphers = connection.get_cipher_list()
2890 self.assertTrue(isinstance(ciphers, list))
2891 for cipher in ciphers:
2892 self.assertTrue(isinstance(cipher, str))
2893
2894
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002895class ConnectionSendTests(TestCase, _LoopbackMixin):
2896 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002897 Tests for :py:obj:`Connection.send`
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002898 """
2899 def test_wrong_args(self):
2900 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002901 When called with arguments other than string argument for its first
2902 parameter or more than two arguments, :py:obj:`Connection.send` raises
2903 :py:obj:`TypeError`.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002904 """
2905 connection = Connection(Context(TLSv1_METHOD), None)
Jean-Paul Calderone77fa2602011-01-05 18:23:39 -05002906 self.assertRaises(TypeError, connection.send)
2907 self.assertRaises(TypeError, connection.send, object())
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002908 self.assertRaises(TypeError, connection.send, "foo", object(), "bar")
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002909
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002910 def test_short_bytes(self):
2911 """
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002912 When passed a short byte string, :py:obj:`Connection.send` transmits
2913 all of it and returns the number of bytes sent.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002914 """
2915 server, client = self._loopback()
2916 count = server.send(b('xy'))
2917 self.assertEquals(count, 2)
2918 self.assertEquals(client.recv(2), b('xy'))
2919
Abraham Martinef063482015-03-25 14:06:24 +00002920 def test_text(self):
2921 """
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002922 When passed a text, :py:obj:`Connection.send` transmits all of it and
2923 returns the number of bytes sent. It also raises a DeprecationWarning.
Abraham Martinef063482015-03-25 14:06:24 +00002924 """
2925 server, client = self._loopback()
2926 with catch_warnings(record=True) as w:
2927 simplefilter("always")
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002928 count = server.send(b"xy".decode("ascii"))
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002929 self.assertEqual(
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002930 "{0} for buf is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002931 WARNING_TYPE_EXPECTED
2932 ),
2933 str(w[-1].message)
2934 )
2935 self.assertIs(w[-1].category, DeprecationWarning)
Abraham Martinef063482015-03-25 14:06:24 +00002936 self.assertEquals(count, 2)
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002937 self.assertEquals(client.recv(2), b"xy")
Abraham Martinef063482015-03-25 14:06:24 +00002938
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002939 @skip_if_py26
2940 def test_short_memoryview(self):
2941 """
2942 When passed a memoryview onto a small number of bytes,
2943 :py:obj:`Connection.send` transmits all of them and returns the number
2944 of bytes sent.
2945 """
2946 server, client = self._loopback()
2947 count = server.send(memoryview(b('xy')))
2948 self.assertEquals(count, 2)
2949 self.assertEquals(client.recv(2), b('xy'))
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002950
Hynek Schlawack8e94f1b2015-09-05 21:31:00 +02002951 @skip_if_py3
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002952 def test_short_buffer(self):
2953 """
2954 When passed a buffer containing a small number of bytes,
2955 :py:obj:`Connection.send` transmits all of them and returns the number
2956 of bytes sent.
2957 """
2958 server, client = self._loopback()
2959 count = server.send(buffer(b('xy')))
2960 self.assertEquals(count, 2)
2961 self.assertEquals(client.recv(2), b('xy'))
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02002962
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05002963
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002964def _make_memoryview(size):
2965 """
2966 Create a new ``memoryview`` wrapped around a ``bytearray`` of the given
2967 size.
2968 """
2969 return memoryview(bytearray(size))
2970
2971
Cory Benfield62d10332014-06-15 10:03:41 +01002972class ConnectionRecvIntoTests(TestCase, _LoopbackMixin):
2973 """
2974 Tests for :py:obj:`Connection.recv_into`
2975 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002976 def _no_length_test(self, factory):
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04002977 """
2978 Assert that when the given buffer is passed to
2979 ``Connection.recv_into``, whatever bytes are available to be received
2980 that fit into that buffer are written into that buffer.
2981 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002982 output_buffer = factory(5)
2983
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04002984 server, client = self._loopback()
2985 server.send(b('xy'))
2986
Jean-Paul Calderone320af1e2015-03-15 17:20:13 -04002987 self.assertEqual(client.recv_into(output_buffer), 2)
2988 self.assertEqual(output_buffer, bytearray(b('xy\x00\x00\x00')))
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04002989
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002990 def test_bytearray_no_length(self):
Cory Benfield62d10332014-06-15 10:03:41 +01002991 """
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04002992 :py:obj:`Connection.recv_into` can be passed a ``bytearray`` instance
2993 and data in the receive buffer is written to it.
Cory Benfield62d10332014-06-15 10:03:41 +01002994 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002995 self._no_length_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01002996
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002997 def _respects_length_test(self, factory):
Cory Benfield62d10332014-06-15 10:03:41 +01002998 """
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002999 Assert that when the given buffer is passed to ``Connection.recv_into``
3000 along with a value for ``nbytes`` that is less than the size of that
3001 buffer, only ``nbytes`` bytes are written into the buffer.
Cory Benfield62d10332014-06-15 10:03:41 +01003002 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003003 output_buffer = factory(10)
3004
Cory Benfield62d10332014-06-15 10:03:41 +01003005 server, client = self._loopback()
3006 server.send(b('abcdefghij'))
Cory Benfield62d10332014-06-15 10:03:41 +01003007
Jean-Paul Calderone320af1e2015-03-15 17:20:13 -04003008 self.assertEqual(client.recv_into(output_buffer, 5), 5)
3009 self.assertEqual(
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04003010 output_buffer, bytearray(b('abcde\x00\x00\x00\x00\x00'))
3011 )
3012
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04003013 def test_bytearray_respects_length(self):
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04003014 """
3015 When called with a ``bytearray`` instance,
3016 :py:obj:`Connection.recv_into` respects the ``nbytes`` parameter and
3017 doesn't copy in more than that number of bytes.
3018 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003019 self._respects_length_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01003020
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003021 def _doesnt_overfill_test(self, factory):
Cory Benfield62d10332014-06-15 10:03:41 +01003022 """
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04003023 Assert that if there are more bytes available to be read from the
3024 receive buffer than would fit into the buffer passed to
3025 :py:obj:`Connection.recv_into`, only as many as fit are written into
3026 it.
Cory Benfield62d10332014-06-15 10:03:41 +01003027 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003028 output_buffer = factory(5)
3029
Cory Benfield62d10332014-06-15 10:03:41 +01003030 server, client = self._loopback()
3031 server.send(b('abcdefghij'))
Cory Benfield62d10332014-06-15 10:03:41 +01003032
Jean-Paul Calderone320af1e2015-03-15 17:20:13 -04003033 self.assertEqual(client.recv_into(output_buffer), 5)
3034 self.assertEqual(output_buffer, bytearray(b('abcde')))
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04003035 rest = client.recv(5)
3036 self.assertEqual(b('fghij'), rest)
3037
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04003038 def test_bytearray_doesnt_overfill(self):
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04003039 """
3040 When called with a ``bytearray`` instance,
3041 :py:obj:`Connection.recv_into` respects the size of the array and
3042 doesn't write more bytes into it than will fit.
3043 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003044 self._doesnt_overfill_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01003045
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003046 def _really_doesnt_overfill_test(self, factory):
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003047 """
3048 Assert that if the value given by ``nbytes`` is greater than the actual
3049 size of the output buffer passed to :py:obj:`Connection.recv_into`, the
3050 behavior is as if no value was given for ``nbytes`` at all.
3051 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003052 output_buffer = factory(5)
3053
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003054 server, client = self._loopback()
3055 server.send(b('abcdefghij'))
3056
3057 self.assertEqual(client.recv_into(output_buffer, 50), 5)
3058 self.assertEqual(output_buffer, bytearray(b('abcde')))
3059 rest = client.recv(5)
3060 self.assertEqual(b('fghij'), rest)
3061
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04003062 def test_bytearray_really_doesnt_overfill(self):
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003063 """
3064 When called with a ``bytearray`` instance and an ``nbytes`` value that
3065 is too large, :py:obj:`Connection.recv_into` respects the size of the
3066 array and not the ``nbytes`` value and doesn't write more bytes into
3067 the buffer than will fit.
3068 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003069 self._doesnt_overfill_test(bytearray)
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003070
Maximilian Hils1d95dea2015-08-17 19:27:20 +02003071 def test_peek(self):
3072
3073 server, client = self._loopback()
3074 server.send(b('xy'))
3075
3076 for _ in range(2):
3077 output_buffer = bytearray(5)
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003078 self.assertEqual(
3079 client.recv_into(output_buffer, flags=MSG_PEEK), 2)
Maximilian Hils1d95dea2015-08-17 19:27:20 +02003080 self.assertEqual(output_buffer, bytearray(b('xy\x00\x00\x00')))
3081
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003082 @skip_if_py26
3083 def test_memoryview_no_length(self):
3084 """
3085 :py:obj:`Connection.recv_into` can be passed a ``memoryview``
3086 instance and data in the receive buffer is written to it.
3087 """
3088 self._no_length_test(_make_memoryview)
Maximilian Hils1d95dea2015-08-17 19:27:20 +02003089
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003090 @skip_if_py26
3091 def test_memoryview_respects_length(self):
3092 """
3093 When called with a ``memoryview`` instance,
3094 :py:obj:`Connection.recv_into` respects the ``nbytes`` parameter
3095 and doesn't copy more than that number of bytes in.
3096 """
3097 self._respects_length_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01003098
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003099 @skip_if_py26
3100 def test_memoryview_doesnt_overfill(self):
3101 """
3102 When called with a ``memoryview`` instance,
3103 :py:obj:`Connection.recv_into` respects the size of the array and
3104 doesn't write more bytes into it than will fit.
3105 """
3106 self._doesnt_overfill_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01003107
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003108 @skip_if_py26
3109 def test_memoryview_really_doesnt_overfill(self):
3110 """
3111 When called with a ``memoryview`` instance and an ``nbytes`` value
3112 that is too large, :py:obj:`Connection.recv_into` respects the size
3113 of the array and not the ``nbytes`` value and doesn't write more
3114 bytes into the buffer than will fit.
3115 """
3116 self._doesnt_overfill_test(_make_memoryview)
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003117
Cory Benfield62d10332014-06-15 10:03:41 +01003118
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003119class ConnectionSendallTests(TestCase, _LoopbackMixin):
3120 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003121 Tests for :py:obj:`Connection.sendall`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003122 """
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003123 def test_wrong_args(self):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003124 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003125 When called with arguments other than a string argument for its first
3126 parameter or with more than two arguments, :py:obj:`Connection.sendall`
3127 raises :py:obj:`TypeError`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003128 """
3129 connection = Connection(Context(TLSv1_METHOD), None)
3130 self.assertRaises(TypeError, connection.sendall)
3131 self.assertRaises(TypeError, connection.sendall, object())
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003132 self.assertRaises(
3133 TypeError, connection.sendall, "foo", object(), "bar")
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003134
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003135 def test_short(self):
3136 """
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003137 :py:obj:`Connection.sendall` transmits all of the bytes in the string
3138 passed to it.
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003139 """
3140 server, client = self._loopback()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04003141 server.sendall(b('x'))
3142 self.assertEquals(client.recv(1), b('x'))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003143
Abraham Martinef063482015-03-25 14:06:24 +00003144 def test_text(self):
3145 """
Jean-Paul Calderone93477422015-04-13 20:38:57 -04003146 :py:obj:`Connection.sendall` transmits all the content in the string
3147 passed to it raising a DeprecationWarning in case of this being a text.
Abraham Martinef063482015-03-25 14:06:24 +00003148 """
3149 server, client = self._loopback()
3150 with catch_warnings(record=True) as w:
3151 simplefilter("always")
Jean-Paul Calderone8dc37a12015-03-29 08:16:52 -04003152 server.sendall(b"x".decode("ascii"))
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04003153 self.assertEqual(
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04003154 "{0} for buf is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04003155 WARNING_TYPE_EXPECTED
3156 ),
3157 str(w[-1].message)
3158 )
3159 self.assertIs(w[-1].category, DeprecationWarning)
3160 self.assertEquals(client.recv(1), b"x")
Abraham Martinef063482015-03-25 14:06:24 +00003161
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003162 @skip_if_py26
3163 def test_short_memoryview(self):
3164 """
3165 When passed a memoryview onto a small number of bytes,
3166 :py:obj:`Connection.sendall` transmits all of them.
3167 """
3168 server, client = self._loopback()
3169 server.sendall(memoryview(b('x')))
3170 self.assertEquals(client.recv(1), b('x'))
Abraham Martinef063482015-03-25 14:06:24 +00003171
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003172 @skip_if_py3
3173 def test_short_buffers(self):
3174 """
3175 When passed a buffer containing a small number of bytes,
3176 :py:obj:`Connection.sendall` transmits all of them.
3177 """
3178 server, client = self._loopback()
3179 server.sendall(buffer(b('x')))
3180 self.assertEquals(client.recv(1), b('x'))
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02003181
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003182 def test_long(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003183 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003184 :py:obj:`Connection.sendall` transmits all of the bytes in the string
3185 passed to it even if this requires multiple calls of an underlying
3186 write function.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003187 """
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003188 server, client = self._loopback()
Jean-Paul Calderone6241c702010-09-16 19:59:24 -04003189 # Should be enough, underlying SSL_write should only do 16k at a time.
Hynek Schlawack35618382015-09-05 21:54:25 +02003190 # On Windows, after 32k of bytes the write will block (forever
3191 # - because no one is yet reading).
Jean-Paul Calderone9e4c1352010-09-19 09:34:43 -04003192 message = b('x') * (1024 * 32 - 1) + b('y')
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003193 server.sendall(message)
3194 accum = []
3195 received = 0
3196 while received < len(message):
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04003197 data = client.recv(1024)
3198 accum.append(data)
3199 received += len(data)
Jean-Paul Calderonef4047852010-09-19 09:45:57 -04003200 self.assertEquals(message, b('').join(accum))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003201
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003202 def test_closed(self):
3203 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003204 If the underlying socket is closed, :py:obj:`Connection.sendall`
3205 propagates the write error from the low level write call.
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003206 """
3207 server, client = self._loopback()
Jean-Paul Calderone05d43e82010-09-24 18:01:36 -04003208 server.sock_shutdown(2)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003209 exc = self.assertRaises(SysCallError, server.sendall, b"hello, world")
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +02003210 if platform == "win32":
3211 self.assertEqual(exc.args[0], ESHUTDOWN)
3212 else:
3213 self.assertEqual(exc.args[0], EPIPE)
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003214
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003215
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003216class ConnectionRenegotiateTests(TestCase, _LoopbackMixin):
3217 """
3218 Tests for SSL renegotiation APIs.
3219 """
3220 def test_renegotiate_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003221 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003222 :py:obj:`Connection.renegotiate` raises :py:obj:`TypeError` if called
3223 with any arguments.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003224 """
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003225 connection = Connection(Context(TLSv1_METHOD), None)
3226 self.assertRaises(TypeError, connection.renegotiate, None)
3227
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003228 def test_total_renegotiations_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003229 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003230 :py:obj:`Connection.total_renegotiations` raises :py:obj:`TypeError` if
3231 called with any arguments.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003232 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003233 connection = Connection(Context(TLSv1_METHOD), None)
3234 self.assertRaises(TypeError, connection.total_renegotiations, None)
3235
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003236 def test_total_renegotiations(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003237 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003238 :py:obj:`Connection.total_renegotiations` returns :py:obj:`0` before
3239 any renegotiations have happened.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003240 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003241 connection = Connection(Context(TLSv1_METHOD), None)
3242 self.assertEquals(connection.total_renegotiations(), 0)
3243
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003244 def test_renegotiate(self):
3245 """
3246 Go through a complete renegotiation cycle.
3247 """
3248 server, client = self._loopback()
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003249
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003250 server.send(b"hello world")
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003251
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003252 assert b"hello world" == client.recv(len(b"hello world"))
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003253
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003254 assert 0 == server.total_renegotiations()
3255 assert False is server.renegotiate_pending()
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003256
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003257 assert True is server.renegotiate()
3258
3259 assert True is server.renegotiate_pending()
3260
3261 server.setblocking(False)
3262 client.setblocking(False)
3263
3264 client.do_handshake()
3265 server.do_handshake()
3266
3267 assert 1 == server.total_renegotiations()
3268 while False is server.renegotiate_pending():
3269 pass
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003270
3271
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003272class ErrorTests(TestCase):
3273 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003274 Unit tests for :py:obj:`OpenSSL.SSL.Error`.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003275 """
3276 def test_type(self):
3277 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003278 :py:obj:`Error` is an exception type.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003279 """
3280 self.assertTrue(issubclass(Error, Exception))
Rick Deane15b1472009-07-09 15:53:42 -05003281 self.assertEqual(Error.__name__, 'Error')
Rick Deane15b1472009-07-09 15:53:42 -05003282
3283
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003284class ConstantsTests(TestCase):
3285 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003286 Tests for the values of constants exposed in :py:obj:`OpenSSL.SSL`.
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003287
3288 These are values defined by OpenSSL intended only to be used as flags to
3289 OpenSSL APIs. The only assertions it seems can be made about them is
3290 their values.
3291 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003292 @pytest.mark.skipif(
3293 OP_NO_QUERY_MTU is None,
3294 reason="OP_NO_QUERY_MTU unavailable - OpenSSL version may be too old"
3295 )
3296 def test_op_no_query_mtu(self):
3297 """
3298 The value of :py:obj:`OpenSSL.SSL.OP_NO_QUERY_MTU` is 0x1000, the value
3299 of :py:const:`SSL_OP_NO_QUERY_MTU` defined by :file:`openssl/ssl.h`.
3300 """
3301 self.assertEqual(OP_NO_QUERY_MTU, 0x1000)
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003302
Hynek Schlawack35618382015-09-05 21:54:25 +02003303 @pytest.mark.skipif(
3304 OP_COOKIE_EXCHANGE is None,
3305 reason="OP_COOKIE_EXCHANGE unavailable - "
3306 "OpenSSL version may be too old"
3307 )
3308 def test_op_cookie_exchange(self):
3309 """
3310 The value of :py:obj:`OpenSSL.SSL.OP_COOKIE_EXCHANGE` is 0x2000, the
3311 value of :py:const:`SSL_OP_COOKIE_EXCHANGE` defined by
3312 :file:`openssl/ssl.h`.
3313 """
3314 self.assertEqual(OP_COOKIE_EXCHANGE, 0x2000)
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003315
Hynek Schlawack35618382015-09-05 21:54:25 +02003316 @pytest.mark.skipif(
3317 OP_NO_TICKET is None,
3318 reason="OP_NO_TICKET unavailable - OpenSSL version may be too old"
3319 )
3320 def test_op_no_ticket(self):
3321 """
3322 The value of :py:obj:`OpenSSL.SSL.OP_NO_TICKET` is 0x4000, the value of
3323 :py:const:`SSL_OP_NO_TICKET` defined by :file:`openssl/ssl.h`.
3324 """
3325 self.assertEqual(OP_NO_TICKET, 0x4000)
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003326
Hynek Schlawack35618382015-09-05 21:54:25 +02003327 @pytest.mark.skipif(
3328 OP_NO_COMPRESSION is None,
3329 reason="OP_NO_COMPRESSION unavailable - OpenSSL version may be too old"
3330 )
3331 def test_op_no_compression(self):
3332 """
3333 The value of :py:obj:`OpenSSL.SSL.OP_NO_COMPRESSION` is 0x20000, the
3334 value of :py:const:`SSL_OP_NO_COMPRESSION` defined by
3335 :file:`openssl/ssl.h`.
3336 """
3337 self.assertEqual(OP_NO_COMPRESSION, 0x20000)
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04003338
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003339 def test_sess_cache_off(self):
3340 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003341 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_OFF` 0x0, the value of
3342 :py:obj:`SSL_SESS_CACHE_OFF` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003343 """
3344 self.assertEqual(0x0, SESS_CACHE_OFF)
3345
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003346 def test_sess_cache_client(self):
3347 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003348 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_CLIENT` 0x1, the value of
3349 :py:obj:`SSL_SESS_CACHE_CLIENT` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003350 """
3351 self.assertEqual(0x1, SESS_CACHE_CLIENT)
3352
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003353 def test_sess_cache_server(self):
3354 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003355 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_SERVER` 0x2, the value of
3356 :py:obj:`SSL_SESS_CACHE_SERVER` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003357 """
3358 self.assertEqual(0x2, SESS_CACHE_SERVER)
3359
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003360 def test_sess_cache_both(self):
3361 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003362 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_BOTH` 0x3, the value of
3363 :py:obj:`SSL_SESS_CACHE_BOTH` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003364 """
3365 self.assertEqual(0x3, SESS_CACHE_BOTH)
3366
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003367 def test_sess_cache_no_auto_clear(self):
3368 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003369 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_AUTO_CLEAR` 0x80, the
3370 value of :py:obj:`SSL_SESS_CACHE_NO_AUTO_CLEAR` defined by
3371 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003372 """
3373 self.assertEqual(0x80, SESS_CACHE_NO_AUTO_CLEAR)
3374
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003375 def test_sess_cache_no_internal_lookup(self):
3376 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003377 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_LOOKUP` 0x100,
3378 the value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL_LOOKUP` defined by
3379 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003380 """
3381 self.assertEqual(0x100, SESS_CACHE_NO_INTERNAL_LOOKUP)
3382
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003383 def test_sess_cache_no_internal_store(self):
3384 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003385 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_STORE` 0x200,
3386 the value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL_STORE` defined by
3387 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003388 """
3389 self.assertEqual(0x200, SESS_CACHE_NO_INTERNAL_STORE)
3390
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003391 def test_sess_cache_no_internal(self):
3392 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003393 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL` 0x300, the
3394 value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL` defined by
3395 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003396 """
3397 self.assertEqual(0x300, SESS_CACHE_NO_INTERNAL)
3398
3399
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003400class MemoryBIOTests(TestCase, _LoopbackMixin):
Rick Deanb71c0d22009-04-01 14:09:23 -05003401 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003402 Tests for :py:obj:`OpenSSL.SSL.Connection` using a memory BIO.
Rick Deanb71c0d22009-04-01 14:09:23 -05003403 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003404 def _server(self, sock):
3405 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003406 Create a new server-side SSL :py:obj:`Connection` object wrapped around
3407 :py:obj:`sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003408 """
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003409 # Create the server side Connection. This is mostly setup boilerplate
3410 # - use TLSv1, use a particular certificate, etc.
3411 server_ctx = Context(TLSv1_METHOD)
Alex Gaynor43307782015-09-04 09:05:45 -04003412 server_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE)
Hynek Schlawack35618382015-09-05 21:54:25 +02003413 server_ctx.set_verify(
3414 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT | VERIFY_CLIENT_ONCE,
3415 verify_cb
3416 )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003417 server_store = server_ctx.get_cert_store()
Hynek Schlawack35618382015-09-05 21:54:25 +02003418 server_ctx.use_privatekey(
3419 load_privatekey(FILETYPE_PEM, server_key_pem))
3420 server_ctx.use_certificate(
3421 load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003422 server_ctx.check_privatekey()
3423 server_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Hynek Schlawack35618382015-09-05 21:54:25 +02003424 # Here the Connection is actually created. If None is passed as the
3425 # 2nd parameter, it indicates a memory BIO should be created.
Rick Deanb1ccd562009-07-09 23:52:39 -05003426 server_conn = Connection(server_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003427 server_conn.set_accept_state()
3428 return server_conn
3429
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003430 def _client(self, sock):
3431 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003432 Create a new client-side SSL :py:obj:`Connection` object wrapped around
3433 :py:obj:`sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003434 """
3435 # Now create the client side Connection. Similar boilerplate to the
3436 # above.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003437 client_ctx = Context(TLSv1_METHOD)
Alex Gaynor43307782015-09-04 09:05:45 -04003438 client_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE)
Hynek Schlawack35618382015-09-05 21:54:25 +02003439 client_ctx.set_verify(
3440 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT | VERIFY_CLIENT_ONCE,
3441 verify_cb
3442 )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003443 client_store = client_ctx.get_cert_store()
Hynek Schlawack35618382015-09-05 21:54:25 +02003444 client_ctx.use_privatekey(
3445 load_privatekey(FILETYPE_PEM, client_key_pem))
3446 client_ctx.use_certificate(
3447 load_certificate(FILETYPE_PEM, client_cert_pem))
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003448 client_ctx.check_privatekey()
3449 client_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05003450 client_conn = Connection(client_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003451 client_conn.set_connect_state()
3452 return client_conn
3453
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003454 def test_memoryConnect(self):
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003455 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003456 Two :py:obj:`Connection`s which use memory BIOs can be manually
3457 connected by reading from the output of each and writing those bytes to
3458 the input of the other and in this way establish a connection and
3459 exchange application-level bytes with each other.
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003460 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003461 server_conn = self._server(None)
3462 client_conn = self._client(None)
Rick Deanb71c0d22009-04-01 14:09:23 -05003463
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003464 # There should be no key or nonces yet.
3465 self.assertIdentical(server_conn.master_key(), None)
3466 self.assertIdentical(server_conn.client_random(), None)
3467 self.assertIdentical(server_conn.server_random(), None)
Rick Deanb71c0d22009-04-01 14:09:23 -05003468
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003469 # First, the handshake needs to happen. We'll deliver bytes back and
3470 # forth between the client and server until neither of them feels like
3471 # speaking any more.
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003472 self.assertIdentical(
3473 self._interactInMemory(client_conn, server_conn), None)
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003474
3475 # Now that the handshake is done, there should be a key and nonces.
3476 self.assertNotIdentical(server_conn.master_key(), None)
3477 self.assertNotIdentical(server_conn.client_random(), None)
3478 self.assertNotIdentical(server_conn.server_random(), None)
Hynek Schlawack35618382015-09-05 21:54:25 +02003479 self.assertEquals(
3480 server_conn.client_random(), client_conn.client_random())
3481 self.assertEquals(
3482 server_conn.server_random(), client_conn.server_random())
3483 self.assertNotEquals(
3484 server_conn.client_random(), server_conn.server_random())
3485 self.assertNotEquals(
3486 client_conn.client_random(), client_conn.server_random())
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003487
3488 # Here are the bytes we'll try to send.
Jean-Paul Calderonea441fdc2010-08-22 21:33:57 -04003489 important_message = b('One if by land, two if by sea.')
Rick Deanb71c0d22009-04-01 14:09:23 -05003490
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003491 server_conn.write(important_message)
3492 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003493 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003494 (client_conn, important_message))
3495
3496 client_conn.write(important_message[::-1])
3497 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003498 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003499 (server_conn, important_message[::-1]))
Rick Deanb71c0d22009-04-01 14:09:23 -05003500
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003501 def test_socketConnect(self):
Rick Deanb1ccd562009-07-09 23:52:39 -05003502 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003503 Just like :py:obj:`test_memoryConnect` but with an actual socket.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003504
Hynek Schlawack35618382015-09-05 21:54:25 +02003505 This is primarily to rule out the memory BIO code as the source of any
3506 problems encountered while passing data over a :py:obj:`Connection` (if
3507 this test fails, there must be a problem outside the memory BIO code,
3508 as no memory BIO is involved here). Even though this isn't a memory
3509 BIO test, it's convenient to have it here.
Rick Deanb1ccd562009-07-09 23:52:39 -05003510 """
Jean-Paul Calderone06c7cc92010-09-24 23:52:00 -04003511 server_conn, client_conn = self._loopback()
Rick Deanb1ccd562009-07-09 23:52:39 -05003512
Jean-Paul Calderonea441fdc2010-08-22 21:33:57 -04003513 important_message = b("Help me Obi Wan Kenobi, you're my only hope.")
Rick Deanb1ccd562009-07-09 23:52:39 -05003514 client_conn.send(important_message)
3515 msg = server_conn.recv(1024)
3516 self.assertEqual(msg, important_message)
3517
3518 # Again in the other direction, just for fun.
3519 important_message = important_message[::-1]
3520 server_conn.send(important_message)
3521 msg = client_conn.recv(1024)
3522 self.assertEqual(msg, important_message)
3523
Jean-Paul Calderonefc4ed0f2009-04-27 11:51:27 -04003524 def test_socketOverridesMemory(self):
Rick Deanb71c0d22009-04-01 14:09:23 -05003525 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003526 Test that :py:obj:`OpenSSL.SSL.bio_read` and
3527 :py:obj:`OpenSSL.SSL.bio_write` don't work on
3528 :py:obj:`OpenSSL.SSL.Connection`() that use sockets.
Rick Deanb71c0d22009-04-01 14:09:23 -05003529 """
3530 context = Context(SSLv3_METHOD)
3531 client = socket()
3532 clientSSL = Connection(context, client)
Alex Gaynor43307782015-09-04 09:05:45 -04003533 self.assertRaises(TypeError, clientSSL.bio_read, 100)
3534 self.assertRaises(TypeError, clientSSL.bio_write, "foo")
Alex Gaynor7e8b61e2015-09-04 13:13:05 -04003535 self.assertRaises(TypeError, clientSSL.bio_shutdown)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003536
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003537 def test_outgoingOverflow(self):
3538 """
3539 If more bytes than can be written to the memory BIO are passed to
Hynek Schlawack35618382015-09-05 21:54:25 +02003540 :py:obj:`Connection.send` at once, the number of bytes which were
3541 written is returned and that many bytes from the beginning of the input
3542 can be read from the other end of the connection.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003543 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003544 server = self._server(None)
3545 client = self._client(None)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003546
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003547 self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003548
3549 size = 2 ** 15
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003550 sent = client.send(b"x" * size)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003551 # Sanity check. We're trying to test what happens when the entire
3552 # input can't be sent. If the entire input was sent, this test is
3553 # meaningless.
3554 self.assertTrue(sent < size)
3555
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003556 receiver, received = self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003557 self.assertIdentical(receiver, server)
3558
3559 # We can rely on all of these bytes being received at once because
3560 # _loopback passes 2 ** 16 to recv - more than 2 ** 15.
3561 self.assertEquals(len(received), sent)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003562
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003563 def test_shutdown(self):
3564 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003565 :py:obj:`Connection.bio_shutdown` signals the end of the data stream
3566 from which the :py:obj:`Connection` reads.
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003567 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003568 server = self._server(None)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003569 server.bio_shutdown()
3570 e = self.assertRaises(Error, server.recv, 1024)
3571 # We don't want WantReadError or ZeroReturnError or anything - it's a
3572 # handshake failure.
3573 self.assertEquals(e.__class__, Error)
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003574
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003575 def test_unexpectedEndOfFile(self):
3576 """
3577 If the connection is lost before an orderly SSL shutdown occurs,
3578 :py:obj:`OpenSSL.SSL.SysCallError` is raised with a message of
3579 "Unexpected EOF".
3580 """
3581 server_conn, client_conn = self._loopback()
3582 client_conn.sock_shutdown(SHUT_RDWR)
3583 exc = self.assertRaises(SysCallError, server_conn.recv, 1024)
3584 self.assertEqual(exc.args, (-1, "Unexpected EOF"))
3585
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003586 def _check_client_ca_list(self, func):
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003587 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003588 Verify the return value of the :py:obj:`get_client_ca_list` method for
3589 server and client connections.
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003590
Jonathan Ballet78b92a22011-07-16 08:07:26 +09003591 :param func: A function which will be called with the server context
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003592 before the client and server are connected to each other. This
3593 function should specify a list of CAs for the server to send to the
3594 client and return that same list. The list will be used to verify
Hynek Schlawack35618382015-09-05 21:54:25 +02003595 that :py:obj:`get_client_ca_list` returns the proper value at
3596 various times.
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003597 """
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003598 server = self._server(None)
3599 client = self._client(None)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003600 self.assertEqual(client.get_client_ca_list(), [])
3601 self.assertEqual(server.get_client_ca_list(), [])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003602 ctx = server.get_context()
3603 expected = func(ctx)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003604 self.assertEqual(client.get_client_ca_list(), [])
3605 self.assertEqual(server.get_client_ca_list(), expected)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003606 self._interactInMemory(client, server)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003607 self.assertEqual(client.get_client_ca_list(), expected)
3608 self.assertEqual(server.get_client_ca_list(), expected)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003609
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003610 def test_set_client_ca_list_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003611 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003612 :py:obj:`Context.set_client_ca_list` raises a :py:obj:`TypeError` if
3613 called with a non-list or a list that contains objects other than
3614 X509Names.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003615 """
3616 ctx = Context(TLSv1_METHOD)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003617 self.assertRaises(TypeError, ctx.set_client_ca_list, "spam")
3618 self.assertRaises(TypeError, ctx.set_client_ca_list, ["spam"])
3619 self.assertIdentical(ctx.set_client_ca_list([]), None)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003620
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003621 def test_set_empty_ca_list(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003622 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003623 If passed an empty list, :py:obj:`Context.set_client_ca_list`
3624 configures the context to send no CA names to the client and, on both
3625 the server and client sides, :py:obj:`Connection.get_client_ca_list`
3626 returns an empty list after the connection is set up.
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003627 """
3628 def no_ca(ctx):
3629 ctx.set_client_ca_list([])
3630 return []
3631 self._check_client_ca_list(no_ca)
3632
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003633 def test_set_one_ca_list(self):
3634 """
3635 If passed a list containing a single X509Name,
Hynek Schlawack35618382015-09-05 21:54:25 +02003636 :py:obj:`Context.set_client_ca_list` configures the context to send
3637 that CA name to the client and, on both the server and client sides,
Jonathan Ballet648875f2011-07-16 14:14:58 +09003638 :py:obj:`Connection.get_client_ca_list` returns a list containing that
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003639 X509Name after the connection is set up.
3640 """
3641 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3642 cadesc = cacert.get_subject()
Hynek Schlawack35618382015-09-05 21:54:25 +02003643
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003644 def single_ca(ctx):
3645 ctx.set_client_ca_list([cadesc])
3646 return [cadesc]
3647 self._check_client_ca_list(single_ca)
3648
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003649 def test_set_multiple_ca_list(self):
3650 """
3651 If passed a list containing multiple X509Name objects,
Hynek Schlawack35618382015-09-05 21:54:25 +02003652 :py:obj:`Context.set_client_ca_list` configures the context to send
3653 those CA names to the client and, on both the server and client sides,
Jonathan Ballet648875f2011-07-16 14:14:58 +09003654 :py:obj:`Connection.get_client_ca_list` returns a list containing those
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003655 X509Names after the connection is set up.
3656 """
3657 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3658 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3659
3660 sedesc = secert.get_subject()
3661 cldesc = clcert.get_subject()
3662
3663 def multiple_ca(ctx):
3664 L = [sedesc, cldesc]
3665 ctx.set_client_ca_list(L)
3666 return L
3667 self._check_client_ca_list(multiple_ca)
3668
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003669 def test_reset_ca_list(self):
3670 """
3671 If called multiple times, only the X509Names passed to the final call
Hynek Schlawack35618382015-09-05 21:54:25 +02003672 of :py:obj:`Context.set_client_ca_list` are used to configure the CA
3673 names sent to the client.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003674 """
3675 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3676 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3677 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3678
3679 cadesc = cacert.get_subject()
3680 sedesc = secert.get_subject()
3681 cldesc = clcert.get_subject()
3682
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003683 def changed_ca(ctx):
3684 ctx.set_client_ca_list([sedesc, cldesc])
3685 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003686 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003687 self._check_client_ca_list(changed_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003688
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003689 def test_mutated_ca_list(self):
3690 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003691 If the list passed to :py:obj:`Context.set_client_ca_list` is mutated
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003692 afterwards, this does not affect the list of CA names sent to the
3693 client.
3694 """
3695 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3696 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3697
3698 cadesc = cacert.get_subject()
3699 sedesc = secert.get_subject()
3700
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003701 def mutated_ca(ctx):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003702 L = [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003703 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003704 L.append(sedesc)
3705 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003706 self._check_client_ca_list(mutated_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003707
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003708 def test_add_client_ca_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003709 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003710 :py:obj:`Context.add_client_ca` raises :py:obj:`TypeError` if called
3711 with a non-X509 object or with a number of arguments other than one.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003712 """
3713 ctx = Context(TLSv1_METHOD)
3714 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003715 self.assertRaises(TypeError, ctx.add_client_ca)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003716 self.assertRaises(TypeError, ctx.add_client_ca, "spam")
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003717 self.assertRaises(TypeError, ctx.add_client_ca, cacert, cacert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003718
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003719 def test_one_add_client_ca(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003720 """
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003721 A certificate's subject can be added as a CA to be sent to the client
Jonathan Ballet648875f2011-07-16 14:14:58 +09003722 with :py:obj:`Context.add_client_ca`.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003723 """
3724 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3725 cadesc = cacert.get_subject()
Hynek Schlawack35618382015-09-05 21:54:25 +02003726
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003727 def single_ca(ctx):
3728 ctx.add_client_ca(cacert)
3729 return [cadesc]
3730 self._check_client_ca_list(single_ca)
3731
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003732 def test_multiple_add_client_ca(self):
3733 """
3734 Multiple CA names can be sent to the client by calling
Jonathan Ballet648875f2011-07-16 14:14:58 +09003735 :py:obj:`Context.add_client_ca` with multiple X509 objects.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003736 """
3737 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3738 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3739
3740 cadesc = cacert.get_subject()
3741 sedesc = secert.get_subject()
3742
3743 def multiple_ca(ctx):
3744 ctx.add_client_ca(cacert)
3745 ctx.add_client_ca(secert)
3746 return [cadesc, sedesc]
3747 self._check_client_ca_list(multiple_ca)
3748
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003749 def test_set_and_add_client_ca(self):
3750 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003751 A call to :py:obj:`Context.set_client_ca_list` followed by a call to
Hynek Schlawack35618382015-09-05 21:54:25 +02003752 :py:obj:`Context.add_client_ca` results in using the CA names from the
3753 first call and the CA name from the second call.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003754 """
3755 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3756 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3757 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3758
3759 cadesc = cacert.get_subject()
3760 sedesc = secert.get_subject()
3761 cldesc = clcert.get_subject()
3762
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003763 def mixed_set_add_ca(ctx):
3764 ctx.set_client_ca_list([cadesc, sedesc])
3765 ctx.add_client_ca(clcert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003766 return [cadesc, sedesc, cldesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003767 self._check_client_ca_list(mixed_set_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003768
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003769 def test_set_after_add_client_ca(self):
3770 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003771 A call to :py:obj:`Context.set_client_ca_list` after a call to
Hynek Schlawack35618382015-09-05 21:54:25 +02003772 :py:obj:`Context.add_client_ca` replaces the CA name specified by the
3773 former call with the names specified by the latter call.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003774 """
3775 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3776 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3777 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3778
3779 cadesc = cacert.get_subject()
3780 sedesc = secert.get_subject()
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003781
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003782 def set_replaces_add_ca(ctx):
3783 ctx.add_client_ca(clcert)
3784 ctx.set_client_ca_list([cadesc])
3785 ctx.add_client_ca(secert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003786 return [cadesc, sedesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003787 self._check_client_ca_list(set_replaces_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003788
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003789
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003790class ConnectionBIOTests(TestCase):
3791 """
3792 Tests for :py:obj:`Connection.bio_read` and :py:obj:`Connection.bio_write`.
3793 """
3794 def test_wantReadError(self):
3795 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003796 :py:obj:`Connection.bio_read` raises
3797 :py:obj:`OpenSSL.SSL.WantReadError` if there are no bytes available to
3798 be read from the BIO.
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003799 """
3800 ctx = Context(TLSv1_METHOD)
3801 conn = Connection(ctx, None)
3802 self.assertRaises(WantReadError, conn.bio_read, 1024)
3803
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003804 def test_buffer_size(self):
3805 """
3806 :py:obj:`Connection.bio_read` accepts an integer giving the maximum
3807 number of bytes to read and return.
3808 """
3809 ctx = Context(TLSv1_METHOD)
3810 conn = Connection(ctx, None)
3811 conn.set_connect_state()
3812 try:
3813 conn.do_handshake()
3814 except WantReadError:
3815 pass
3816 data = conn.bio_read(2)
3817 self.assertEqual(2, len(data))
3818
Hynek Schlawack35618382015-09-05 21:54:25 +02003819 @skip_if_py3
3820 def test_buffer_size_long(self):
3821 """
3822 On Python 2 :py:obj:`Connection.bio_read` accepts values of type
3823 :py:obj:`long` as well as :py:obj:`int`.
3824 """
3825 ctx = Context(TLSv1_METHOD)
3826 conn = Connection(ctx, None)
3827 conn.set_connect_state()
3828 try:
3829 conn.do_handshake()
3830 except WantReadError:
3831 pass
3832 data = conn.bio_read(long(2))
3833 self.assertEqual(2, len(data))
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003834
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003835
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003836class InfoConstantTests(TestCase):
3837 """
3838 Tests for assorted constants exposed for use in info callbacks.
3839 """
3840 def test_integers(self):
3841 """
3842 All of the info constants are integers.
3843
3844 This is a very weak test. It would be nice to have one that actually
3845 verifies that as certain info events happen, the value passed to the
3846 info callback matches up with the constant exposed by OpenSSL.SSL.
3847 """
3848 for const in [
3849 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK, SSL_ST_INIT,
3850 SSL_ST_BEFORE, SSL_ST_OK, SSL_ST_RENEGOTIATE,
3851 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
3852 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
3853 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
Hynek Schlawack35618382015-09-05 21:54:25 +02003854 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE
3855 ]:
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003856 self.assertTrue(isinstance(const, int))
3857
Ziga Seilnacht44611bf2009-08-31 20:49:30 +02003858
Cory Benfield1d142142016-03-30 11:51:45 +01003859class TestRequires(object):
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003860 """
3861 Tests for the decorator factory used to conditionally raise
Cory Benfield1d142142016-03-30 11:51:45 +01003862 NotImplementedError when older OpenSSLs are used.
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003863 """
3864 def test_available(self):
3865 """
3866 When the OpenSSL functionality is available the decorated functions
3867 work appropriately.
3868 """
3869 feature_guard = _make_requires(True, "Error text")
3870 results = []
3871
3872 @feature_guard
3873 def inner():
3874 results.append(True)
3875 return True
3876
Cory Benfield1d142142016-03-30 11:51:45 +01003877 assert inner()
3878 assert results == [True]
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003879
3880 def test_unavailable(self):
3881 """
3882 When the OpenSSL functionality is not available the decorated function
3883 does not execute and NotImplementedError is raised.
3884 """
3885 feature_guard = _make_requires(False, "Error text")
3886 results = []
3887
3888 @feature_guard
3889 def inner():
3890 results.append(True)
3891 return True
3892
Cory Benfield1d142142016-03-30 11:51:45 +01003893 with pytest.raises(NotImplementedError) as e:
3894 inner()
3895
3896 assert "Error text" in str(e.value)
3897 assert not results
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003898
3899
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003900if __name__ == '__main__':
3901 main()