blob: ab316fc9e44de9dbc0b4385f6b6379bcba4cfdb4 [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)
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040058
Cory Benfieldba1820d2015-04-13 17:39:12 -040059from OpenSSL._util import lib as _lib
60
Jean-Paul Calderone4bccf5e2008-12-28 22:50:42 -050061try:
62 from OpenSSL.SSL import OP_NO_QUERY_MTU
63except ImportError:
64 OP_NO_QUERY_MTU = None
65try:
66 from OpenSSL.SSL import OP_COOKIE_EXCHANGE
67except ImportError:
68 OP_COOKIE_EXCHANGE = None
69try:
70 from OpenSSL.SSL import OP_NO_TICKET
71except ImportError:
72 OP_NO_TICKET = None
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -040073
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040074try:
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -040075 from OpenSSL.SSL import OP_NO_COMPRESSION
76except ImportError:
77 OP_NO_COMPRESSION = None
78
79try:
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040080 from OpenSSL.SSL import MODE_RELEASE_BUFFERS
81except ImportError:
82 MODE_RELEASE_BUFFERS = None
83
Jean-Paul Calderone1461c492013-10-03 16:05:00 -040084try:
85 from OpenSSL.SSL import OP_NO_TLSv1, OP_NO_TLSv1_1, OP_NO_TLSv1_2
86except ImportError:
87 OP_NO_TLSv1 = OP_NO_TLSv1_1 = OP_NO_TLSv1_2 = None
88
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -040089from OpenSSL.SSL import (
90 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK, SSL_ST_INIT, SSL_ST_BEFORE,
91 SSL_ST_OK, SSL_ST_RENEGOTIATE,
92 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
93 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
94 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
95 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE)
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -040096
Hynek Schlawackf0e66852015-10-16 20:18:38 +020097from .util import WARNING_TYPE_EXPECTED, NON_ASCII, TestCase, b
98from .test_crypto import (
99 cleartextCertificatePEM, cleartextPrivateKeyPEM,
100 client_cert_pem, client_key_pem, server_cert_pem, server_key_pem,
101 root_cert_pem)
102
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200103
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -0400104# openssl dhparam 128 -out dh-128.pem (note that 128 is a small number of bits
105# to use)
106dhparam = """\
107-----BEGIN DH PARAMETERS-----
108MBYCEQCobsg29c9WZP/54oAPcwiDAgEC
109-----END DH PARAMETERS-----
110"""
111
112
Hynek Schlawackb4f02402015-09-05 20:48:34 +0200113skip_if_py3 = pytest.mark.skipif(PY3, reason="Python 2 only")
Hynek Schlawackf8979a52015-09-05 21:25:25 +0200114skip_if_py26 = pytest.mark.skipif(
115 version_info[0:2] == (2, 6),
116 reason="Python 2.7 and later only"
117)
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200118
119
Jean-Paul Calderone05826732015-04-12 11:38:49 -0400120def join_bytes_or_unicode(prefix, suffix):
121 """
122 Join two path components of either ``bytes`` or ``unicode``.
123
124 The return type is the same as the type of ``prefix``.
125 """
126 # If the types are the same, nothing special is necessary.
127 if type(prefix) == type(suffix):
128 return join(prefix, suffix)
129
130 # Otherwise, coerce suffix to the type of prefix.
131 if isinstance(prefix, text_type):
132 return join(prefix, suffix.decode(getfilesystemencoding()))
133 else:
134 return join(prefix, suffix.encode(getfilesystemencoding()))
135
136
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400137def verify_cb(conn, cert, errnum, depth, ok):
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400138 return ok
139
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400140
Rick Deanb1ccd562009-07-09 23:52:39 -0500141def socket_pair():
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400142 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400143 Establish and return a pair of network sockets connected to each other.
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400144 """
145 # Connect a pair of sockets
Rick Deanb1ccd562009-07-09 23:52:39 -0500146 port = socket()
147 port.bind(('', 0))
148 port.listen(1)
149 client = socket()
150 client.setblocking(False)
Jean-Paul Calderonef23c5d92009-07-23 17:58:15 -0400151 client.connect_ex(("127.0.0.1", port.getsockname()[1]))
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400152 client.setblocking(True)
Rick Deanb1ccd562009-07-09 23:52:39 -0500153 server = port.accept()[0]
Rick Deanb1ccd562009-07-09 23:52:39 -0500154
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400155 # Let's pass some unencrypted data to make sure our socket connection is
156 # fine. Just one byte, so we don't have to worry about buffers getting
157 # filled up or fragmentation.
Jean-Paul Calderone9e4eeae2010-08-22 21:32:52 -0400158 server.send(b("x"))
159 assert client.recv(1024) == b("x")
160 client.send(b("y"))
161 assert server.recv(1024) == b("y")
Rick Deanb1ccd562009-07-09 23:52:39 -0500162
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -0400163 # Most of our callers want non-blocking sockets, make it easy for them.
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400164 server.setblocking(False)
165 client.setblocking(False)
Jim Shaver46f28912015-05-29 19:32:16 -0400166
Rick Deanb1ccd562009-07-09 23:52:39 -0500167 return (server, client)
168
169
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400170def handshake(client, server):
171 conns = [client, server]
172 while conns:
173 for conn in conns:
174 try:
175 conn.do_handshake()
176 except WantReadError:
177 pass
178 else:
179 conns.remove(conn)
180
181
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400182def _create_certificate_chain():
183 """
184 Construct and return a chain of certificates.
185
186 1. A new self-signed certificate authority certificate (cacert)
187 2. A new intermediate certificate signed by cacert (icert)
188 3. A new server certificate signed by icert (scert)
189 """
190 caext = X509Extension(b('basicConstraints'), False, b('CA:true'))
191
192 # Step 1
193 cakey = PKey()
194 cakey.generate_key(TYPE_RSA, 512)
195 cacert = X509()
196 cacert.get_subject().commonName = "Authority Certificate"
197 cacert.set_issuer(cacert.get_subject())
198 cacert.set_pubkey(cakey)
199 cacert.set_notBefore(b("20000101000000Z"))
200 cacert.set_notAfter(b("20200101000000Z"))
201 cacert.add_extensions([caext])
202 cacert.set_serial_number(0)
203 cacert.sign(cakey, "sha1")
204
205 # Step 2
206 ikey = PKey()
207 ikey.generate_key(TYPE_RSA, 512)
208 icert = X509()
209 icert.get_subject().commonName = "Intermediate Certificate"
210 icert.set_issuer(cacert.get_subject())
211 icert.set_pubkey(ikey)
212 icert.set_notBefore(b("20000101000000Z"))
213 icert.set_notAfter(b("20200101000000Z"))
214 icert.add_extensions([caext])
215 icert.set_serial_number(0)
216 icert.sign(cakey, "sha1")
217
218 # Step 3
219 skey = PKey()
220 skey.generate_key(TYPE_RSA, 512)
221 scert = X509()
222 scert.get_subject().commonName = "Server Certificate"
223 scert.set_issuer(icert.get_subject())
224 scert.set_pubkey(skey)
225 scert.set_notBefore(b("20000101000000Z"))
226 scert.set_notAfter(b("20200101000000Z"))
227 scert.add_extensions([
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200228 X509Extension(b('basicConstraints'), True, b('CA:false'))])
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400229 scert.set_serial_number(0)
230 scert.sign(ikey, "sha1")
231
232 return [(cakey, cacert), (ikey, icert), (skey, scert)]
233
234
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400235class _LoopbackMixin:
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400236 """
237 Helper mixin which defines methods for creating a connected socket pair and
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200238 for forcing two connected SSL sockets to talk to each other via memory
239 BIOs.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400240 """
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500241 def _loopbackClientFactory(self, socket):
242 client = Connection(Context(TLSv1_METHOD), socket)
243 client.set_connect_state()
244 return client
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400245
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500246 def _loopbackServerFactory(self, socket):
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400247 ctx = Context(TLSv1_METHOD)
248 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
249 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500250 server = Connection(ctx, socket)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400251 server.set_accept_state()
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500252 return server
253
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500254 def _loopback(self, serverFactory=None, clientFactory=None):
255 if serverFactory is None:
256 serverFactory = self._loopbackServerFactory
257 if clientFactory is None:
258 clientFactory = self._loopbackClientFactory
259
260 (server, client) = socket_pair()
261 server = serverFactory(server)
262 client = clientFactory(client)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400263
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400264 handshake(client, server)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400265
266 server.setblocking(True)
267 client.setblocking(True)
268 return server, client
269
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400270 def _interactInMemory(self, client_conn, server_conn):
271 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900272 Try to read application bytes from each of the two :py:obj:`Connection`
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400273 objects. Copy bytes back and forth between their send/receive buffers
274 for as long as there is anything to copy. When there is nothing more
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200275 to copy, return :py:obj:`None`. If one of them actually manages to
276 deliver some application bytes, return a two-tuple of the connection
277 from which the bytes were read and the bytes themselves.
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400278 """
279 wrote = True
280 while wrote:
281 # Loop until neither side has anything to say
282 wrote = False
283
284 # Copy stuff from each side's send buffer to the other side's
285 # receive buffer.
286 for (read, write) in [(client_conn, server_conn),
287 (server_conn, client_conn)]:
288
289 # Give the side a chance to generate some more bytes, or
290 # succeed.
291 try:
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400292 data = read.recv(2 ** 16)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400293 except WantReadError:
294 # It didn't succeed, so we'll hope it generated some
295 # output.
296 pass
297 else:
298 # It did succeed, so we'll stop now and let the caller deal
299 # with it.
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400300 return (read, data)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400301
302 while True:
303 # Keep copying as long as there's more stuff there.
304 try:
305 dirty = read.bio_read(4096)
306 except WantReadError:
307 # Okay, nothing more waiting to be sent. Stop
308 # processing this send buffer.
309 break
310 else:
311 # Keep track of the fact that someone generated some
312 # output.
313 wrote = True
314 write.bio_write(dirty)
315
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -0400316 def _handshakeInMemory(self, client_conn, server_conn):
Jean-Paul Calderoneb2b40782014-05-06 08:47:40 -0400317 """
318 Perform the TLS handshake between two :py:class:`Connection` instances
319 connected to each other via memory BIOs.
320 """
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -0400321 client_conn.set_connect_state()
322 server_conn.set_accept_state()
323
324 for conn in [client_conn, server_conn]:
325 try:
326 conn.do_handshake()
327 except WantReadError:
328 pass
329
330 self._interactInMemory(client_conn, server_conn)
331
332
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400333class VersionTests(TestCase):
334 """
335 Tests for version information exposed by
Jonathan Ballet648875f2011-07-16 14:14:58 +0900336 :py:obj:`OpenSSL.SSL.SSLeay_version` and
337 :py:obj:`OpenSSL.SSL.OPENSSL_VERSION_NUMBER`.
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400338 """
339 def test_OPENSSL_VERSION_NUMBER(self):
340 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900341 :py:obj:`OPENSSL_VERSION_NUMBER` is an integer with status in the low
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400342 byte and the patch, fix, minor, and major versions in the
343 nibbles above that.
344 """
345 self.assertTrue(isinstance(OPENSSL_VERSION_NUMBER, int))
346
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400347 def test_SSLeay_version(self):
348 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900349 :py:obj:`SSLeay_version` takes a version type indicator and returns
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400350 one of a number of version strings based on that indicator.
351 """
352 versions = {}
353 for t in [SSLEAY_VERSION, SSLEAY_CFLAGS, SSLEAY_BUILT_ON,
354 SSLEAY_PLATFORM, SSLEAY_DIR]:
355 version = SSLeay_version(t)
356 versions[version] = t
357 self.assertTrue(isinstance(version, bytes))
358 self.assertEqual(len(versions), 5)
359
360
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100361@pytest.fixture
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100362def ca_file(tmpdir):
363 """
364 Create a valid PEM file with CA certificates and return the path.
365 """
366 key = rsa.generate_private_key(
367 public_exponent=65537,
368 key_size=2048,
369 backend=default_backend()
370 )
371 public_key = key.public_key()
372
373 builder = x509.CertificateBuilder()
374 builder = builder.subject_name(x509.Name([
375 x509.NameAttribute(NameOID.COMMON_NAME, u"pyopenssl.org"),
376 ]))
377 builder = builder.issuer_name(x509.Name([
378 x509.NameAttribute(NameOID.COMMON_NAME, u"pyopenssl.org"),
379 ]))
380 one_day = datetime.timedelta(1, 0, 0)
381 builder = builder.not_valid_before(datetime.datetime.today() - one_day)
382 builder = builder.not_valid_after(datetime.datetime.today() + one_day)
383 builder = builder.serial_number(int(uuid.uuid4()))
384 builder = builder.public_key(public_key)
385 builder = builder.add_extension(
386 x509.BasicConstraints(ca=True, path_length=None), critical=True,
387 )
388
389 certificate = builder.sign(
390 private_key=key, algorithm=hashes.SHA256(),
391 backend=default_backend()
392 )
393
394 ca_file = tmpdir.join("test.pem")
395 ca_file.write_binary(
396 certificate.public_bytes(
397 encoding=serialization.Encoding.PEM,
398 )
399 )
400
401 return str(ca_file).encode("ascii")
402
403
404@pytest.fixture
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100405def context():
406 """
407 A simple TLS 1.0 context.
408 """
409 return Context(TLSv1_METHOD)
410
411
412class TestContext(object):
Hynek Schlawackaa861212016-03-13 13:53:48 +0100413 """
414 py.test-based tests for :class:`OpenSSL.SSL.Context`.
415
416 If possible, add new tests here.
417 """
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100418 @pytest.mark.parametrize("cipher_string", [
419 b"hello world:AES128-SHA",
420 u"hello world:AES128-SHA",
421 ])
422 def test_set_cipher_list(self, context, cipher_string):
423 """
Hynek Schlawacka7a63af2016-03-11 12:05:26 +0100424 :meth:`Context.set_cipher_list` accepts both byte and unicode strings
425 for naming the ciphers which connections created with the context
426 object will be able to choose from.
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100427 """
428 context.set_cipher_list(cipher_string)
429 conn = Connection(context, None)
430
431 assert "AES128-SHA" in conn.get_cipher_list()
432
433 @pytest.mark.parametrize("cipher_list,error", [
434 (object(), TypeError),
435 ("imaginary-cipher", Error),
436 ])
437 def test_set_cipher_list_wrong_args(self, context, cipher_list, error):
438 """
439 :meth:`Context.set_cipher_list` raises :exc:`TypeError` when passed a
440 non-string argument and raises :exc:`OpenSSL.SSL.Error` when passed an
441 incorrect cipher list string.
442 """
443 with pytest.raises(error):
444 context.set_cipher_list(cipher_list)
445
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100446 def test_load_client_ca(self, context, ca_file):
447 """
448 :meth:`Context.load_client_ca` works as far as we can tell.
449 """
450 context.load_client_ca(ca_file)
451
452 def test_load_client_ca_invalid(self, context, tmpdir):
453 """
454 :meth:`Context.load_client_ca` raises an Error if the ca file is
455 invalid.
456 """
457 ca_file = tmpdir.join("test.pem")
458 ca_file.write("")
459
460 with pytest.raises(Error) as e:
461 context.load_client_ca(str(ca_file).encode("ascii"))
462
463 assert "PEM routines" == e.value.args[0][0][0]
464
465 def test_load_client_ca_unicode(self, context, ca_file):
466 """
467 Passing the path as unicode raises a warning but works.
468 """
469 pytest.deprecated_call(
470 context.load_client_ca, ca_file.decode("ascii")
471 )
472
473 def test_set_session_id(self, context):
474 """
475 :meth:`Context.set_session_id` works as far as we can tell.
476 """
477 context.set_session_id(b"abc")
478
479 def test_set_session_id_fail(self, context):
480 """
481 :meth:`Context.set_session_id` errors are propagated.
482 """
483 with pytest.raises(Error) as e:
484 context.set_session_id(b"abc" * 1000)
485
486 assert [
487 ("SSL routines",
488 "SSL_CTX_set_session_id_context",
489 "ssl session id context too long")
490 ] == e.value.args[0]
491
492 def test_set_session_id_unicode(self, context):
493 """
494 :meth:`Context.set_session_id` raises a warning if a unicode string is
495 passed.
496 """
497 pytest.deprecated_call(context.set_session_id, u"abc")
498
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100499
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400500class ContextTests(TestCase, _LoopbackMixin):
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400501 """
Hynek Schlawackaa861212016-03-13 13:53:48 +0100502 Unit tests for :class:`OpenSSL.SSL.Context`.
503
504 If possible, add new tests to :class:`TestContext` above.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400505 """
506 def test_method(self):
507 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200508 :py:obj:`Context` can be instantiated with one of
509 :py:obj:`SSLv2_METHOD`, :py:obj:`SSLv3_METHOD`,
510 :py:obj:`SSLv23_METHOD`, :py:obj:`TLSv1_METHOD`,
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400511 :py:obj:`TLSv1_1_METHOD`, or :py:obj:`TLSv1_2_METHOD`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400512 """
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400513 methods = [
514 SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD]
515 for meth in methods:
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400516 Context(meth)
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400517
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400518 maybe = [SSLv2_METHOD, TLSv1_1_METHOD, TLSv1_2_METHOD]
519 for meth in maybe:
520 try:
521 Context(meth)
522 except (Error, ValueError):
523 # Some versions of OpenSSL have SSLv2 / TLSv1.1 / TLSv1.2, some
524 # don't. Difficult to say in advance.
525 pass
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400526
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400527 self.assertRaises(TypeError, Context, "")
528 self.assertRaises(ValueError, Context, 10)
529
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200530 @skip_if_py3
531 def test_method_long(self):
532 """
533 On Python 2 :py:class:`Context` accepts values of type
534 :py:obj:`long` as well as :py:obj:`int`.
535 """
536 Context(long(TLSv1_METHOD))
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500537
Rick Deane15b1472009-07-09 15:53:42 -0500538 def test_type(self):
539 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200540 :py:obj:`Context` and :py:obj:`ContextType` refer to the same type
541 object and can be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -0500542 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400543 self.assertIdentical(Context, ContextType)
544 self.assertConsistentType(Context, 'Context', TLSv1_METHOD)
Rick Deane15b1472009-07-09 15:53:42 -0500545
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400546 def test_use_privatekey(self):
547 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200548 :py:obj:`Context.use_privatekey` takes an :py:obj:`OpenSSL.crypto.PKey`
549 instance.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400550 """
551 key = PKey()
552 key.generate_key(TYPE_RSA, 128)
553 ctx = Context(TLSv1_METHOD)
554 ctx.use_privatekey(key)
555 self.assertRaises(TypeError, ctx.use_privatekey, "")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400556
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800557 def test_use_privatekey_file_missing(self):
558 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200559 :py:obj:`Context.use_privatekey_file` raises
560 :py:obj:`OpenSSL.SSL.Error` when passed the name of a file which does
561 not exist.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800562 """
563 ctx = Context(TLSv1_METHOD)
564 self.assertRaises(Error, ctx.use_privatekey_file, self.mktemp())
565
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400566 def _use_privatekey_file_test(self, pemfile, filetype):
567 """
568 Verify that calling ``Context.use_privatekey_file`` with the given
569 arguments does not raise an exception.
570 """
571 key = PKey()
572 key.generate_key(TYPE_RSA, 128)
573
574 with open(pemfile, "wt") as pem:
575 pem.write(
576 dump_privatekey(FILETYPE_PEM, key).decode("ascii")
577 )
578
579 ctx = Context(TLSv1_METHOD)
580 ctx.use_privatekey_file(pemfile, filetype)
581
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400582 def test_use_privatekey_file_bytes(self):
583 """
584 A private key can be specified from a file by passing a ``bytes``
585 instance giving the file name to ``Context.use_privatekey_file``.
586 """
587 self._use_privatekey_file_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -0400588 self.mktemp() + NON_ASCII.encode(getfilesystemencoding()),
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400589 FILETYPE_PEM,
590 )
591
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400592 def test_use_privatekey_file_unicode(self):
593 """
594 A private key can be specified from a file by passing a ``unicode``
595 instance giving the file name to ``Context.use_privatekey_file``.
596 """
597 self._use_privatekey_file_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -0400598 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII,
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400599 FILETYPE_PEM,
600 )
601
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200602 @skip_if_py3
603 def test_use_privatekey_file_long(self):
604 """
605 On Python 2 :py:obj:`Context.use_privatekey_file` accepts a
606 filetype of type :py:obj:`long` as well as :py:obj:`int`.
607 """
608 self._use_privatekey_file_test(self.mktemp(), long(FILETYPE_PEM))
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500609
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800610 def test_use_certificate_wrong_args(self):
611 """
612 :py:obj:`Context.use_certificate_wrong_args` raises :py:obj:`TypeError`
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200613 when not passed exactly one :py:obj:`OpenSSL.crypto.X509` instance as
614 an argument.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800615 """
616 ctx = Context(TLSv1_METHOD)
617 self.assertRaises(TypeError, ctx.use_certificate)
618 self.assertRaises(TypeError, ctx.use_certificate, "hello, world")
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200619 self.assertRaises(
620 TypeError, ctx.use_certificate, X509(), "hello, world"
621 )
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800622
623 def test_use_certificate_uninitialized(self):
624 """
625 :py:obj:`Context.use_certificate` raises :py:obj:`OpenSSL.SSL.Error`
626 when passed a :py:obj:`OpenSSL.crypto.X509` instance which has not been
627 initialized (ie, which does not actually have any certificate data).
628 """
629 ctx = Context(TLSv1_METHOD)
630 self.assertRaises(Error, ctx.use_certificate, X509())
631
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800632 def test_use_certificate(self):
633 """
634 :py:obj:`Context.use_certificate` sets the certificate which will be
635 used to identify connections created using the context.
636 """
637 # TODO
638 # Hard to assert anything. But we could set a privatekey then ask
639 # OpenSSL if the cert and key agree using check_privatekey. Then as
640 # long as check_privatekey works right we're good...
641 ctx = Context(TLSv1_METHOD)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200642 ctx.use_certificate(
643 load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
644 )
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800645
646 def test_use_certificate_file_wrong_args(self):
647 """
648 :py:obj:`Context.use_certificate_file` raises :py:obj:`TypeError` if
649 called with zero arguments or more than two arguments, or if the first
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200650 argument is not a byte string or the second argumnent is not an
651 integer.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800652 """
653 ctx = Context(TLSv1_METHOD)
654 self.assertRaises(TypeError, ctx.use_certificate_file)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200655 self.assertRaises(TypeError, ctx.use_certificate_file, b"somefile",
656 object())
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800657 self.assertRaises(
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200658 TypeError, ctx.use_certificate_file, b"somefile", FILETYPE_PEM,
659 object())
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800660 self.assertRaises(
661 TypeError, ctx.use_certificate_file, object(), FILETYPE_PEM)
662 self.assertRaises(
663 TypeError, ctx.use_certificate_file, b"somefile", object())
664
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800665 def test_use_certificate_file_missing(self):
666 """
667 :py:obj:`Context.use_certificate_file` raises
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200668 `:py:obj:`OpenSSL.SSL.Error` if passed the name of a file which does
669 not exist.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800670 """
671 ctx = Context(TLSv1_METHOD)
672 self.assertRaises(Error, ctx.use_certificate_file, self.mktemp())
673
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400674 def _use_certificate_file_test(self, certificate_file):
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800675 """
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400676 Verify that calling ``Context.use_certificate_file`` with the given
677 filename doesn't raise an exception.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800678 """
679 # TODO
680 # Hard to assert anything. But we could set a privatekey then ask
681 # OpenSSL if the cert and key agree using check_privatekey. Then as
682 # long as check_privatekey works right we're good...
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400683 with open(certificate_file, "wb") as pem_file:
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800684 pem_file.write(cleartextCertificatePEM)
685
686 ctx = Context(TLSv1_METHOD)
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400687 ctx.use_certificate_file(certificate_file)
688
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400689 def test_use_certificate_file_bytes(self):
690 """
691 :py:obj:`Context.use_certificate_file` sets the certificate (given as a
692 ``bytes`` filename) which will be used to identify connections created
693 using the context.
694 """
Hynek Schlawack4813c0e2015-04-16 13:38:01 -0400695 filename = self.mktemp() + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400696 self._use_certificate_file_test(filename)
697
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400698 def test_use_certificate_file_unicode(self):
699 """
700 :py:obj:`Context.use_certificate_file` sets the certificate (given as a
701 ``bytes`` filename) which will be used to identify connections created
702 using the context.
703 """
Hynek Schlawack4813c0e2015-04-16 13:38:01 -0400704 filename = self.mktemp().decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400705 self._use_certificate_file_test(filename)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800706
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200707 @skip_if_py3
708 def test_use_certificate_file_long(self):
709 """
710 On Python 2 :py:obj:`Context.use_certificate_file` accepts a
711 filetype of type :py:obj:`long` as well as :py:obj:`int`.
712 """
713 pem_filename = self.mktemp()
714 with open(pem_filename, "wb") as pem_file:
715 pem_file.write(cleartextCertificatePEM)
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500716
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200717 ctx = Context(TLSv1_METHOD)
718 ctx.use_certificate_file(pem_filename, long(FILETYPE_PEM))
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500719
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500720 def test_check_privatekey_valid(self):
721 """
722 :py:obj:`Context.check_privatekey` returns :py:obj:`None` if the
723 :py:obj:`Context` instance has been configured to use a matched key and
724 certificate pair.
725 """
726 key = load_privatekey(FILETYPE_PEM, client_key_pem)
727 cert = load_certificate(FILETYPE_PEM, client_cert_pem)
728 context = Context(TLSv1_METHOD)
729 context.use_privatekey(key)
730 context.use_certificate(cert)
731 self.assertIs(None, context.check_privatekey())
732
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500733 def test_check_privatekey_invalid(self):
734 """
735 :py:obj:`Context.check_privatekey` raises :py:obj:`Error` if the
736 :py:obj:`Context` instance has been configured to use a key and
737 certificate pair which don't relate to each other.
738 """
739 key = load_privatekey(FILETYPE_PEM, client_key_pem)
740 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
741 context = Context(TLSv1_METHOD)
742 context.use_privatekey(key)
743 context.use_certificate(cert)
744 self.assertRaises(Error, context.check_privatekey)
745
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500746 def test_check_privatekey_wrong_args(self):
747 """
748 :py:obj:`Context.check_privatekey` raises :py:obj:`TypeError` if called
749 with other than no arguments.
750 """
751 context = Context(TLSv1_METHOD)
752 self.assertRaises(TypeError, context.check_privatekey, object())
753
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400754 def test_set_app_data_wrong_args(self):
755 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200756 :py:obj:`Context.set_app_data` raises :py:obj:`TypeError` if called
757 with other than one argument.
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400758 """
759 context = Context(TLSv1_METHOD)
760 self.assertRaises(TypeError, context.set_app_data)
761 self.assertRaises(TypeError, context.set_app_data, None, None)
762
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400763 def test_get_app_data_wrong_args(self):
764 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200765 :py:obj:`Context.get_app_data` raises :py:obj:`TypeError` if called
766 with any arguments.
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400767 """
768 context = Context(TLSv1_METHOD)
769 self.assertRaises(TypeError, context.get_app_data, None)
770
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400771 def test_app_data(self):
772 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200773 :py:obj:`Context.set_app_data` stores an object for later retrieval
774 using :py:obj:`Context.get_app_data`.
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400775 """
776 app_data = object()
777 context = Context(TLSv1_METHOD)
778 context.set_app_data(app_data)
779 self.assertIdentical(context.get_app_data(), app_data)
780
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400781 def test_set_options_wrong_args(self):
782 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200783 :py:obj:`Context.set_options` raises :py:obj:`TypeError` if called with
784 the wrong number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400785 """
786 context = Context(TLSv1_METHOD)
787 self.assertRaises(TypeError, context.set_options)
788 self.assertRaises(TypeError, context.set_options, None)
789 self.assertRaises(TypeError, context.set_options, 1, None)
790
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500791 def test_set_options(self):
792 """
793 :py:obj:`Context.set_options` returns the new options value.
794 """
795 context = Context(TLSv1_METHOD)
796 options = context.set_options(OP_NO_SSLv2)
797 self.assertTrue(OP_NO_SSLv2 & options)
798
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200799 @skip_if_py3
800 def test_set_options_long(self):
801 """
802 On Python 2 :py:obj:`Context.set_options` accepts values of type
803 :py:obj:`long` as well as :py:obj:`int`.
804 """
805 context = Context(TLSv1_METHOD)
806 options = context.set_options(long(OP_NO_SSLv2))
807 self.assertTrue(OP_NO_SSLv2 & options)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500808
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300809 def test_set_mode_wrong_args(self):
810 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200811 :py:obj:`Context.set`mode} raises :py:obj:`TypeError` if called with
812 the wrong number of arguments or a non-:py:obj:`int` argument.
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300813 """
814 context = Context(TLSv1_METHOD)
815 self.assertRaises(TypeError, context.set_mode)
816 self.assertRaises(TypeError, context.set_mode, None)
817 self.assertRaises(TypeError, context.set_mode, 1, None)
818
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400819 if MODE_RELEASE_BUFFERS is not None:
820 def test_set_mode(self):
821 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200822 :py:obj:`Context.set_mode` accepts a mode bitvector and returns the
823 newly set mode.
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400824 """
825 context = Context(TLSv1_METHOD)
826 self.assertTrue(
827 MODE_RELEASE_BUFFERS & context.set_mode(MODE_RELEASE_BUFFERS))
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500828
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200829 @skip_if_py3
830 def test_set_mode_long(self):
831 """
832 On Python 2 :py:obj:`Context.set_mode` accepts values of type
833 :py:obj:`long` as well as :py:obj:`int`.
834 """
835 context = Context(TLSv1_METHOD)
836 mode = context.set_mode(long(MODE_RELEASE_BUFFERS))
837 self.assertTrue(MODE_RELEASE_BUFFERS & mode)
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400838 else:
839 "MODE_RELEASE_BUFFERS unavailable - OpenSSL version may be too old"
840
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400841 def test_set_timeout_wrong_args(self):
842 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200843 :py:obj:`Context.set_timeout` raises :py:obj:`TypeError` if called with
844 the wrong number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400845 """
846 context = Context(TLSv1_METHOD)
847 self.assertRaises(TypeError, context.set_timeout)
848 self.assertRaises(TypeError, context.set_timeout, None)
849 self.assertRaises(TypeError, context.set_timeout, 1, None)
850
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400851 def test_get_timeout_wrong_args(self):
852 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200853 :py:obj:`Context.get_timeout` raises :py:obj:`TypeError` if called with
854 any arguments.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400855 """
856 context = Context(TLSv1_METHOD)
857 self.assertRaises(TypeError, context.get_timeout, None)
858
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400859 def test_timeout(self):
860 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200861 :py:obj:`Context.set_timeout` sets the session timeout for all
862 connections created using the context object.
863 :py:obj:`Context.get_timeout` retrieves this value.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400864 """
865 context = Context(TLSv1_METHOD)
866 context.set_timeout(1234)
867 self.assertEquals(context.get_timeout(), 1234)
868
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200869 @skip_if_py3
870 def test_timeout_long(self):
871 """
872 On Python 2 :py:obj:`Context.set_timeout` accepts values of type
873 `long` as well as int.
874 """
875 context = Context(TLSv1_METHOD)
876 context.set_timeout(long(1234))
877 self.assertEquals(context.get_timeout(), 1234)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500878
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400879 def test_set_verify_depth_wrong_args(self):
880 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200881 :py:obj:`Context.set_verify_depth` raises :py:obj:`TypeError` if called
882 with the wrong number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400883 """
884 context = Context(TLSv1_METHOD)
885 self.assertRaises(TypeError, context.set_verify_depth)
886 self.assertRaises(TypeError, context.set_verify_depth, None)
887 self.assertRaises(TypeError, context.set_verify_depth, 1, None)
888
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400889 def test_get_verify_depth_wrong_args(self):
890 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200891 :py:obj:`Context.get_verify_depth` raises :py:obj:`TypeError` if called
892 with any arguments.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400893 """
894 context = Context(TLSv1_METHOD)
895 self.assertRaises(TypeError, context.get_verify_depth, None)
896
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400897 def test_verify_depth(self):
898 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200899 :py:obj:`Context.set_verify_depth` sets the number of certificates in
900 a chain to follow before giving up. The value can be retrieved with
Jonathan Ballet648875f2011-07-16 14:14:58 +0900901 :py:obj:`Context.get_verify_depth`.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400902 """
903 context = Context(TLSv1_METHOD)
904 context.set_verify_depth(11)
905 self.assertEquals(context.get_verify_depth(), 11)
906
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200907 @skip_if_py3
908 def test_verify_depth_long(self):
909 """
910 On Python 2 :py:obj:`Context.set_verify_depth` accepts values of
911 type `long` as well as int.
912 """
913 context = Context(TLSv1_METHOD)
914 context.set_verify_depth(long(11))
915 self.assertEquals(context.get_verify_depth(), 11)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500916
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400917 def _write_encrypted_pem(self, passphrase):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400918 """
919 Write a new private key out to a new file, encrypted using the given
920 passphrase. Return the path to the new file.
921 """
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400922 key = PKey()
923 key.generate_key(TYPE_RSA, 128)
924 pemFile = self.mktemp()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400925 fObj = open(pemFile, 'w')
926 pem = dump_privatekey(FILETYPE_PEM, key, "blowfish", passphrase)
927 fObj.write(pem.decode('ascii'))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400928 fObj.close()
929 return pemFile
930
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400931 def test_set_passwd_cb_wrong_args(self):
932 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200933 :py:obj:`Context.set_passwd_cb` raises :py:obj:`TypeError` if called
934 with the wrong arguments or with a non-callable first argument.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400935 """
936 context = Context(TLSv1_METHOD)
937 self.assertRaises(TypeError, context.set_passwd_cb)
938 self.assertRaises(TypeError, context.set_passwd_cb, None)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200939 self.assertRaises(
940 TypeError, context.set_passwd_cb, lambda: None, None, None
Hynek Schlawack2c013a92015-09-05 19:33:05 +0200941 ) # pragma: nocover
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400942
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400943 def test_set_passwd_cb(self):
944 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200945 :py:obj:`Context.set_passwd_cb` accepts a callable which will be
946 invoked when a private key is loaded from an encrypted PEM.
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400947 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400948 passphrase = b("foobar")
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400949 pemFile = self._write_encrypted_pem(passphrase)
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400950 calledWith = []
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200951
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400952 def passphraseCallback(maxlen, verify, extra):
953 calledWith.append((maxlen, verify, extra))
954 return passphrase
955 context = Context(TLSv1_METHOD)
956 context.set_passwd_cb(passphraseCallback)
957 context.use_privatekey_file(pemFile)
958 self.assertTrue(len(calledWith), 1)
959 self.assertTrue(isinstance(calledWith[0][0], int))
960 self.assertTrue(isinstance(calledWith[0][1], int))
961 self.assertEqual(calledWith[0][2], None)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400962
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400963 def test_passwd_callback_exception(self):
964 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200965 :py:obj:`Context.use_privatekey_file` propagates any exception raised
966 by the passphrase callback.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400967 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400968 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200969
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400970 def passphraseCallback(maxlen, verify, extra):
971 raise RuntimeError("Sorry, I am a fail.")
972
973 context = Context(TLSv1_METHOD)
974 context.set_passwd_cb(passphraseCallback)
975 self.assertRaises(RuntimeError, context.use_privatekey_file, pemFile)
976
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400977 def test_passwd_callback_false(self):
978 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200979 :py:obj:`Context.use_privatekey_file` raises
980 :py:obj:`OpenSSL.SSL.Error` if the passphrase callback returns a false
981 value.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400982 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400983 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200984
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400985 def passphraseCallback(maxlen, verify, extra):
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500986 return b""
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400987
988 context = Context(TLSv1_METHOD)
989 context.set_passwd_cb(passphraseCallback)
990 self.assertRaises(Error, context.use_privatekey_file, pemFile)
991
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400992 def test_passwd_callback_non_string(self):
993 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200994 :py:obj:`Context.use_privatekey_file` raises
995 :py:obj:`OpenSSL.SSL.Error` if the passphrase callback returns a true
996 non-string value.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400997 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400998 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200999
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -04001000 def passphraseCallback(maxlen, verify, extra):
1001 return 10
1002
1003 context = Context(TLSv1_METHOD)
1004 context.set_passwd_cb(passphraseCallback)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -08001005 self.assertRaises(ValueError, context.use_privatekey_file, pemFile)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -04001006
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -04001007 def test_passwd_callback_too_long(self):
1008 """
1009 If the passphrase returned by the passphrase callback returns a string
1010 longer than the indicated maximum length, it is truncated.
1011 """
1012 # A priori knowledge!
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04001013 passphrase = b("x") * 1024
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -04001014 pemFile = self._write_encrypted_pem(passphrase)
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001015
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -04001016 def passphraseCallback(maxlen, verify, extra):
1017 assert maxlen == 1024
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04001018 return passphrase + b("y")
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -04001019
1020 context = Context(TLSv1_METHOD)
1021 context.set_passwd_cb(passphraseCallback)
1022 # This shall succeed because the truncated result is the correct
1023 # passphrase.
1024 context.use_privatekey_file(pemFile)
1025
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -04001026 def test_set_info_callback(self):
1027 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001028 :py:obj:`Context.set_info_callback` accepts a callable which will be
1029 invoked when certain information about an SSL connection is available.
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -04001030 """
Rick Deanb1ccd562009-07-09 23:52:39 -05001031 (server, client) = socket_pair()
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -04001032
1033 clientSSL = Connection(Context(TLSv1_METHOD), client)
1034 clientSSL.set_connect_state()
1035
1036 called = []
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001037
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -04001038 def info(conn, where, ret):
1039 called.append((conn, where, ret))
1040 context = Context(TLSv1_METHOD)
1041 context.set_info_callback(info)
1042 context.use_certificate(
1043 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1044 context.use_privatekey(
1045 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1046
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -04001047 serverSSL = Connection(context, server)
1048 serverSSL.set_accept_state()
1049
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -05001050 handshake(clientSSL, serverSSL)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -04001051
Jean-Paul Calderone3835e522014-02-02 11:12:30 -05001052 # The callback must always be called with a Connection instance as the
1053 # first argument. It would probably be better to split this into
1054 # separate tests for client and server side info callbacks so we could
1055 # assert it is called with the right Connection instance. It would
1056 # also be good to assert *something* about `where` and `ret`.
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -05001057 notConnections = [
1058 conn for (conn, where, ret) in called
1059 if not isinstance(conn, Connection)]
1060 self.assertEqual(
1061 [], notConnections,
1062 "Some info callback arguments were not Connection instaces.")
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001063
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001064 def _load_verify_locations_test(self, *args):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001065 """
1066 Create a client context which will verify the peer certificate and call
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04001067 its :py:obj:`load_verify_locations` method with the given arguments.
1068 Then connect it to a server and ensure that the handshake succeeds.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001069 """
Rick Deanb1ccd562009-07-09 23:52:39 -05001070 (server, client) = socket_pair()
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001071
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001072 clientContext = Context(TLSv1_METHOD)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001073 clientContext.load_verify_locations(*args)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001074 # Require that the server certificate verify properly or the
1075 # connection will fail.
1076 clientContext.set_verify(
1077 VERIFY_PEER,
1078 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
1079
1080 clientSSL = Connection(clientContext, client)
1081 clientSSL.set_connect_state()
1082
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001083 serverContext = Context(TLSv1_METHOD)
1084 serverContext.use_certificate(
1085 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1086 serverContext.use_privatekey(
1087 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1088
1089 serverSSL = Connection(serverContext, server)
1090 serverSSL.set_accept_state()
1091
Jean-Paul Calderonef8742032010-09-25 00:00:32 -04001092 # Without load_verify_locations above, the handshake
1093 # will fail:
1094 # Error: [('SSL routines', 'SSL3_GET_SERVER_CERTIFICATE',
1095 # 'certificate verify failed')]
1096 handshake(clientSSL, serverSSL)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001097
1098 cert = clientSSL.get_peer_certificate()
Jean-Paul Calderone20131f52009-04-01 12:05:45 -04001099 self.assertEqual(cert.get_subject().CN, 'Testing Root CA')
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -04001100
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001101 def _load_verify_cafile(self, cafile):
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001102 """
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001103 Verify that if path to a file containing a certificate is passed to
1104 ``Context.load_verify_locations`` for the ``cafile`` parameter, that
1105 certificate is used as a trust root for the purposes of verifying
1106 connections created using that ``Context``.
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001107 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04001108 fObj = open(cafile, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04001109 fObj.write(cleartextCertificatePEM.decode('ascii'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001110 fObj.close()
1111
1112 self._load_verify_locations_test(cafile)
1113
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001114 def test_load_verify_bytes_cafile(self):
1115 """
1116 :py:obj:`Context.load_verify_locations` accepts a file name as a
1117 ``bytes`` instance and uses the certificates within for verification
1118 purposes.
1119 """
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001120 cafile = self.mktemp() + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001121 self._load_verify_cafile(cafile)
1122
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001123 def test_load_verify_unicode_cafile(self):
1124 """
1125 :py:obj:`Context.load_verify_locations` accepts a file name as a
1126 ``unicode`` instance and uses the certificates within for verification
1127 purposes.
1128 """
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001129 self._load_verify_cafile(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001130 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001131 )
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001132
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -04001133 def test_load_verify_invalid_file(self):
1134 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001135 :py:obj:`Context.load_verify_locations` raises :py:obj:`Error` when
1136 passed a non-existent cafile.
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -04001137 """
1138 clientContext = Context(TLSv1_METHOD)
1139 self.assertRaises(
1140 Error, clientContext.load_verify_locations, self.mktemp())
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001141
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001142 def _load_verify_directory_locations_capath(self, capath):
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001143 """
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001144 Verify that if path to a directory containing certificate files is
1145 passed to ``Context.load_verify_locations`` for the ``capath``
1146 parameter, those certificates are used as trust roots for the purposes
1147 of verifying connections created using that ``Context``.
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001148 """
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001149 makedirs(capath)
Jean-Paul Calderone24dfb332011-05-04 18:10:26 -04001150 # Hash values computed manually with c_rehash to avoid depending on
1151 # c_rehash in the test suite. One is from OpenSSL 0.9.8, the other
1152 # from OpenSSL 1.0.0.
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001153 for name in [b'c7adac82.0', b'c3705638.0']:
Jean-Paul Calderone05826732015-04-12 11:38:49 -04001154 cafile = join_bytes_or_unicode(capath, name)
1155 with open(cafile, 'w') as fObj:
1156 fObj.write(cleartextCertificatePEM.decode('ascii'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001157
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001158 self._load_verify_locations_test(None, capath)
1159
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001160 def test_load_verify_directory_bytes_capath(self):
1161 """
1162 :py:obj:`Context.load_verify_locations` accepts a directory name as a
1163 ``bytes`` instance and uses the certificates within for verification
1164 purposes.
1165 """
1166 self._load_verify_directory_locations_capath(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001167 self.mktemp() + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001168 )
1169
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001170 def test_load_verify_directory_unicode_capath(self):
1171 """
1172 :py:obj:`Context.load_verify_locations` accepts a directory name as a
1173 ``unicode`` instance and uses the certificates within for verification
1174 purposes.
1175 """
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001176 self._load_verify_directory_locations_capath(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001177 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001178 )
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001179
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001180 def test_load_verify_locations_wrong_args(self):
1181 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001182 :py:obj:`Context.load_verify_locations` raises :py:obj:`TypeError` if
1183 called with the wrong number of arguments or with non-:py:obj:`str`
1184 arguments.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001185 """
1186 context = Context(TLSv1_METHOD)
1187 self.assertRaises(TypeError, context.load_verify_locations)
1188 self.assertRaises(TypeError, context.load_verify_locations, object())
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001189 self.assertRaises(
1190 TypeError, context.load_verify_locations, object(), object()
1191 )
1192 self.assertRaises(
1193 TypeError, context.load_verify_locations, None, None, None
1194 )
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001195
Hynek Schlawack734d3022015-09-05 19:19:32 +02001196 @pytest.mark.skipif(
1197 platform == "win32",
1198 reason="set_default_verify_paths appears not to work on Windows. "
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -04001199 "See LP#404343 and LP#404344."
Hynek Schlawack734d3022015-09-05 19:19:32 +02001200 )
1201 def test_set_default_verify_paths(self):
1202 """
1203 :py:obj:`Context.set_default_verify_paths` causes the
1204 platform-specific CA certificate locations to be used for
1205 verification purposes.
1206 """
1207 # Testing this requires a server with a certificate signed by one
1208 # of the CAs in the platform CA location. Getting one of those
1209 # costs money. Fortunately (or unfortunately, depending on your
1210 # perspective), it's easy to think of a public server on the
1211 # internet which has such a certificate. Connecting to the network
1212 # in a unit test is bad, but it's the only way I can think of to
1213 # really test this. -exarkun
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001214
Hynek Schlawack734d3022015-09-05 19:19:32 +02001215 # Arg, verisign.com doesn't speak anything newer than TLS 1.0
Hynek Schlawackbf887932015-10-21 17:13:47 +02001216 context = Context(SSLv23_METHOD)
Hynek Schlawack734d3022015-09-05 19:19:32 +02001217 context.set_default_verify_paths()
1218 context.set_verify(
1219 VERIFY_PEER,
1220 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001221
Hynek Schlawack734d3022015-09-05 19:19:32 +02001222 client = socket()
Hynek Schlawackbf887932015-10-21 17:13:47 +02001223 client.connect(("encrypted.google.com", 443))
Hynek Schlawack734d3022015-09-05 19:19:32 +02001224 clientSSL = Connection(context, client)
1225 clientSSL.set_connect_state()
1226 clientSSL.do_handshake()
1227 clientSSL.send(b"GET / HTTP/1.0\r\n\r\n")
1228 self.assertTrue(clientSSL.recv(1024))
Jean-Paul Calderone9eadb962008-09-07 21:20:44 -04001229
1230 def test_set_default_verify_paths_signature(self):
1231 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001232 :py:obj:`Context.set_default_verify_paths` takes no arguments and
1233 raises :py:obj:`TypeError` if given any.
Jean-Paul Calderone9eadb962008-09-07 21:20:44 -04001234 """
1235 context = Context(TLSv1_METHOD)
1236 self.assertRaises(TypeError, context.set_default_verify_paths, None)
1237 self.assertRaises(TypeError, context.set_default_verify_paths, 1)
1238 self.assertRaises(TypeError, context.set_default_verify_paths, "")
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05001239
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001240 def test_add_extra_chain_cert_invalid_cert(self):
1241 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001242 :py:obj:`Context.add_extra_chain_cert` raises :py:obj:`TypeError` if
1243 called with other than one argument or if called with an object which
1244 is not an instance of :py:obj:`X509`.
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001245 """
1246 context = Context(TLSv1_METHOD)
1247 self.assertRaises(TypeError, context.add_extra_chain_cert)
1248 self.assertRaises(TypeError, context.add_extra_chain_cert, object())
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001249 self.assertRaises(
1250 TypeError, context.add_extra_chain_cert, object(), object()
1251 )
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001252
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001253 def _handshake_test(self, serverContext, clientContext):
1254 """
1255 Verify that a client and server created with the given contexts can
1256 successfully handshake and communicate.
1257 """
1258 serverSocket, clientSocket = socket_pair()
1259
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001260 server = Connection(serverContext, serverSocket)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001261 server.set_accept_state()
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001262
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001263 client = Connection(clientContext, clientSocket)
1264 client.set_connect_state()
1265
1266 # Make them talk to each other.
1267 # self._interactInMemory(client, server)
1268 for i in range(3):
1269 for s in [client, server]:
1270 try:
1271 s.do_handshake()
1272 except WantReadError:
1273 pass
1274
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001275 def test_set_verify_callback_connection_argument(self):
1276 """
1277 The first argument passed to the verify callback is the
1278 :py:class:`Connection` instance for which verification is taking place.
1279 """
1280 serverContext = Context(TLSv1_METHOD)
1281 serverContext.use_privatekey(
1282 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1283 serverContext.use_certificate(
1284 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1285 serverConnection = Connection(serverContext, None)
1286
1287 class VerifyCallback(object):
1288 def callback(self, connection, *args):
1289 self.connection = connection
1290 return 1
1291
1292 verify = VerifyCallback()
1293 clientContext = Context(TLSv1_METHOD)
1294 clientContext.set_verify(VERIFY_PEER, verify.callback)
1295 clientConnection = Connection(clientContext, None)
1296 clientConnection.set_connect_state()
1297
1298 self._handshakeInMemory(clientConnection, serverConnection)
1299
1300 self.assertIdentical(verify.connection, clientConnection)
1301
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001302 def test_set_verify_callback_exception(self):
1303 """
1304 If the verify callback passed to :py:obj:`Context.set_verify` raises an
1305 exception, verification fails and the exception is propagated to the
1306 caller of :py:obj:`Connection.do_handshake`.
1307 """
1308 serverContext = Context(TLSv1_METHOD)
1309 serverContext.use_privatekey(
1310 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1311 serverContext.use_certificate(
1312 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1313
1314 clientContext = Context(TLSv1_METHOD)
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001315
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001316 def verify_callback(*args):
1317 raise Exception("silly verify failure")
1318 clientContext.set_verify(VERIFY_PEER, verify_callback)
1319
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01001320 with pytest.raises(Exception) as exc:
1321 self._handshake_test(serverContext, clientContext)
1322
1323 self.assertEqual("silly verify failure", str(exc.value))
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001324
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001325 def test_add_extra_chain_cert(self):
1326 """
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001327 :py:obj:`Context.add_extra_chain_cert` accepts an :py:obj:`X509`
1328 instance to add to the certificate chain.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001329
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001330 See :py:obj:`_create_certificate_chain` for the details of the
1331 certificate chain tested.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001332
1333 The chain is tested by starting a server with scert and connecting
1334 to it with a client which trusts cacert and requires verification to
1335 succeed.
1336 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001337 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001338 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1339
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001340 # Dump the CA certificate to a file because that's the only way to load
1341 # it as a trusted CA in the client context.
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001342 for cert, name in [(cacert, 'ca.pem'),
1343 (icert, 'i.pem'),
1344 (scert, 's.pem')]:
Hynek Schlawacke90680f2015-04-16 15:09:27 -04001345 with open(join(self.tmpdir, name), 'w') as f:
1346 f.write(dump_certificate(FILETYPE_PEM, cert).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001347
Hynek Schlawack1902c012015-04-16 15:06:41 -04001348 for key, name in [(cakey, 'ca.key'),
1349 (ikey, 'i.key'),
1350 (skey, 's.key')]:
Hynek Schlawacke90680f2015-04-16 15:09:27 -04001351 with open(join(self.tmpdir, name), 'w') as f:
1352 f.write(dump_privatekey(FILETYPE_PEM, key).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001353
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001354 # Create the server context
1355 serverContext = Context(TLSv1_METHOD)
1356 serverContext.use_privatekey(skey)
1357 serverContext.use_certificate(scert)
Jean-Paul Calderone16cf03d2010-09-08 18:53:39 -04001358 # The client already has cacert, we only need to give them icert.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001359 serverContext.add_extra_chain_cert(icert)
1360
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001361 # Create the client
1362 clientContext = Context(TLSv1_METHOD)
1363 clientContext.set_verify(
1364 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001365 clientContext.load_verify_locations(join(self.tmpdir, "ca.pem"))
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001366
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001367 # Try it out.
1368 self._handshake_test(serverContext, clientContext)
1369
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001370 def _use_certificate_chain_file_test(self, certdir):
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001371 """
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001372 Verify that :py:obj:`Context.use_certificate_chain_file` reads a
1373 certificate chain from a specified file.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001374
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001375 The chain is tested by starting a server with scert and connecting to
1376 it with a client which trusts cacert and requires verification to
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001377 succeed.
1378 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001379 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001380 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1381
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001382 makedirs(certdir)
1383
Jean-Paul Calderone05826732015-04-12 11:38:49 -04001384 chainFile = join_bytes_or_unicode(certdir, "chain.pem")
1385 caFile = join_bytes_or_unicode(certdir, "ca.pem")
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001386
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001387 # Write out the chain file.
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001388 with open(chainFile, 'wb') as fObj:
1389 # Most specific to least general.
1390 fObj.write(dump_certificate(FILETYPE_PEM, scert))
1391 fObj.write(dump_certificate(FILETYPE_PEM, icert))
1392 fObj.write(dump_certificate(FILETYPE_PEM, cacert))
1393
1394 with open(caFile, 'w') as fObj:
1395 fObj.write(dump_certificate(FILETYPE_PEM, cacert).decode('ascii'))
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001396
1397 serverContext = Context(TLSv1_METHOD)
1398 serverContext.use_certificate_chain_file(chainFile)
1399 serverContext.use_privatekey(skey)
1400
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001401 clientContext = Context(TLSv1_METHOD)
1402 clientContext.set_verify(
1403 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001404 clientContext.load_verify_locations(caFile)
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001405
1406 self._handshake_test(serverContext, clientContext)
1407
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001408 def test_use_certificate_chain_file_bytes(self):
1409 """
1410 ``Context.use_certificate_chain_file`` accepts the name of a file (as
1411 an instance of ``bytes``) to specify additional certificates to use to
1412 construct and verify a trust chain.
1413 """
1414 self._use_certificate_chain_file_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001415 self.mktemp() + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001416 )
1417
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001418 def test_use_certificate_chain_file_unicode(self):
1419 """
1420 ``Context.use_certificate_chain_file`` accepts the name of a file (as
1421 an instance of ``unicode``) to specify additional certificates to use
1422 to construct and verify a trust chain.
1423 """
1424 self._use_certificate_chain_file_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001425 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001426 )
1427
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001428 def test_use_certificate_chain_file_wrong_args(self):
1429 """
1430 :py:obj:`Context.use_certificate_chain_file` raises :py:obj:`TypeError`
1431 if passed zero or more than one argument or when passed a non-byte
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001432 string single argument. It also raises :py:obj:`OpenSSL.SSL.Error`
1433 when passed a bad chain file name (for example, the name of a file
1434 which does not exist).
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001435 """
1436 context = Context(TLSv1_METHOD)
1437 self.assertRaises(TypeError, context.use_certificate_chain_file)
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001438 self.assertRaises(
1439 TypeError, context.use_certificate_chain_file, object()
1440 )
1441 self.assertRaises(
1442 TypeError, context.use_certificate_chain_file, b"foo", object()
1443 )
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001444
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001445 self.assertRaises(
1446 Error, context.use_certificate_chain_file, self.mktemp()
1447 )
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001448
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001449 def test_get_verify_mode_wrong_args(self):
1450 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001451 :py:obj:`Context.get_verify_mode` raises :py:obj:`TypeError` if called
1452 with any arguments.
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001453 """
1454 context = Context(TLSv1_METHOD)
1455 self.assertRaises(TypeError, context.get_verify_mode, None)
1456
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001457 def test_set_verify_mode(self):
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001458 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001459 :py:obj:`Context.get_verify_mode` returns the verify mode flags
1460 previously passed to :py:obj:`Context.set_verify`.
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001461 """
1462 context = Context(TLSv1_METHOD)
1463 self.assertEquals(context.get_verify_mode(), 0)
1464 context.set_verify(
1465 VERIFY_PEER | VERIFY_CLIENT_ONCE, lambda *args: None)
1466 self.assertEquals(
1467 context.get_verify_mode(), VERIFY_PEER | VERIFY_CLIENT_ONCE)
1468
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001469 @skip_if_py3
1470 def test_set_verify_mode_long(self):
1471 """
1472 On Python 2 :py:obj:`Context.set_verify_mode` accepts values of
1473 type :py:obj:`long` as well as :py:obj:`int`.
1474 """
1475 context = Context(TLSv1_METHOD)
1476 self.assertEquals(context.get_verify_mode(), 0)
1477 context.set_verify(
Hynek Schlawackb4ceed32015-09-05 20:55:19 +02001478 long(VERIFY_PEER | VERIFY_CLIENT_ONCE), lambda *args: None
1479 ) # pragma: nocover
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001480 self.assertEquals(
1481 context.get_verify_mode(), VERIFY_PEER | VERIFY_CLIENT_ONCE)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001482
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001483 def test_load_tmp_dh_wrong_args(self):
1484 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001485 :py:obj:`Context.load_tmp_dh` raises :py:obj:`TypeError` if called with
1486 the wrong number of arguments or with a non-:py:obj:`str` argument.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001487 """
1488 context = Context(TLSv1_METHOD)
1489 self.assertRaises(TypeError, context.load_tmp_dh)
1490 self.assertRaises(TypeError, context.load_tmp_dh, "foo", None)
1491 self.assertRaises(TypeError, context.load_tmp_dh, object())
1492
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001493 def test_load_tmp_dh_missing_file(self):
1494 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001495 :py:obj:`Context.load_tmp_dh` raises :py:obj:`OpenSSL.SSL.Error` if the
1496 specified file does not exist.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001497 """
1498 context = Context(TLSv1_METHOD)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001499 self.assertRaises(Error, context.load_tmp_dh, b"hello")
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001500
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001501 def _load_tmp_dh_test(self, dhfilename):
Jean-Paul Calderone4e0c43f2015-04-13 10:15:17 -04001502 """
1503 Verify that calling ``Context.load_tmp_dh`` with the given filename
1504 does not raise an exception.
1505 """
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001506 context = Context(TLSv1_METHOD)
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001507 with open(dhfilename, "w") as dhfile:
1508 dhfile.write(dhparam)
1509
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001510 context.load_tmp_dh(dhfilename)
1511 # XXX What should I assert here? -exarkun
1512
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001513 def test_load_tmp_dh_bytes(self):
1514 """
1515 :py:obj:`Context.load_tmp_dh` loads Diffie-Hellman parameters from the
1516 specified file (given as ``bytes``).
1517 """
1518 self._load_tmp_dh_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001519 self.mktemp() + NON_ASCII.encode(getfilesystemencoding()),
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001520 )
1521
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001522 def test_load_tmp_dh_unicode(self):
1523 """
1524 :py:obj:`Context.load_tmp_dh` loads Diffie-Hellman parameters from the
1525 specified file (given as ``unicode``).
1526 """
1527 self._load_tmp_dh_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001528 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII,
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001529 )
1530
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001531 def test_set_tmp_ecdh(self):
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001532 """
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001533 :py:obj:`Context.set_tmp_ecdh` sets the elliptic curve for
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001534 Diffie-Hellman to the specified curve.
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001535 """
1536 context = Context(TLSv1_METHOD)
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001537 for curve in get_elliptic_curves():
Hynek Schlawacka07fa8c2015-10-17 10:15:28 +02001538 if curve.name.startswith(u"Oakley-"):
Hynek Schlawack7408aff2015-10-17 09:51:16 +02001539 # Setting Oakley-EC2N-4 and Oakley-EC2N-3 adds
1540 # ('bignum routines', 'BN_mod_inverse', 'no inverse') to the
1541 # error queue on OpenSSL 1.0.2.
1542 continue
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001543 # The only easily "assertable" thing is that it does not raise an
1544 # exception.
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001545 context.set_tmp_ecdh(curve)
Alex Gaynor12dc0842014-01-17 12:51:31 -06001546
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001547 def test_set_session_cache_mode_wrong_args(self):
1548 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001549 :py:obj:`Context.set_session_cache_mode` raises :py:obj:`TypeError` if
1550 called with other than one integer argument.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001551 """
1552 context = Context(TLSv1_METHOD)
1553 self.assertRaises(TypeError, context.set_session_cache_mode)
1554 self.assertRaises(TypeError, context.set_session_cache_mode, object())
1555
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001556 def test_get_session_cache_mode_wrong_args(self):
1557 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001558 :py:obj:`Context.get_session_cache_mode` raises :py:obj:`TypeError` if
1559 called with any arguments.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001560 """
1561 context = Context(TLSv1_METHOD)
1562 self.assertRaises(TypeError, context.get_session_cache_mode, 1)
1563
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001564 def test_session_cache_mode(self):
1565 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001566 :py:obj:`Context.set_session_cache_mode` specifies how sessions are
1567 cached. The setting can be retrieved via
1568 :py:obj:`Context.get_session_cache_mode`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001569 """
1570 context = Context(TLSv1_METHOD)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001571 context.set_session_cache_mode(SESS_CACHE_OFF)
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001572 off = context.set_session_cache_mode(SESS_CACHE_BOTH)
1573 self.assertEqual(SESS_CACHE_OFF, off)
1574 self.assertEqual(SESS_CACHE_BOTH, context.get_session_cache_mode())
1575
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001576 @skip_if_py3
1577 def test_session_cache_mode_long(self):
1578 """
1579 On Python 2 :py:obj:`Context.set_session_cache_mode` accepts values
1580 of type :py:obj:`long` as well as :py:obj:`int`.
1581 """
1582 context = Context(TLSv1_METHOD)
1583 context.set_session_cache_mode(long(SESS_CACHE_BOTH))
1584 self.assertEqual(
1585 SESS_CACHE_BOTH, context.get_session_cache_mode())
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001586
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001587 def test_get_cert_store(self):
1588 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001589 :py:obj:`Context.get_cert_store` returns a :py:obj:`X509Store`
1590 instance.
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001591 """
1592 context = Context(TLSv1_METHOD)
1593 store = context.get_cert_store()
1594 self.assertIsInstance(store, X509Store)
1595
1596
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001597class ServerNameCallbackTests(TestCase, _LoopbackMixin):
1598 """
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001599 Tests for :py:obj:`Context.set_tlsext_servername_callback` and its
1600 interaction with :py:obj:`Connection`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001601 """
1602 def test_wrong_args(self):
1603 """
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001604 :py:obj:`Context.set_tlsext_servername_callback` raises
1605 :py:obj:`TypeError` if called with other than one argument.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001606 """
1607 context = Context(TLSv1_METHOD)
1608 self.assertRaises(TypeError, context.set_tlsext_servername_callback)
1609 self.assertRaises(
1610 TypeError, context.set_tlsext_servername_callback, 1, 2)
1611
1612 def test_old_callback_forgotten(self):
1613 """
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001614 If :py:obj:`Context.set_tlsext_servername_callback` is used to specify
1615 a new callback, the one it replaces is dereferenced.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001616 """
1617 def callback(connection):
1618 pass
1619
1620 def replacement(connection):
1621 pass
1622
1623 context = Context(TLSv1_METHOD)
1624 context.set_tlsext_servername_callback(callback)
1625
1626 tracker = ref(callback)
1627 del callback
1628
1629 context.set_tlsext_servername_callback(replacement)
Jean-Paul Calderoned4033eb2014-01-11 08:21:46 -05001630
1631 # One run of the garbage collector happens to work on CPython. PyPy
1632 # doesn't collect the underlying object until a second run for whatever
1633 # reason. That's fine, it still demonstrates our code has properly
1634 # dropped the reference.
1635 collect()
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001636 collect()
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001637
1638 callback = tracker()
1639 if callback is not None:
1640 referrers = get_referrers(callback)
Jean-Paul Calderone7de39562014-01-11 08:17:59 -05001641 if len(referrers) > 1:
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001642 self.fail("Some references remain: %r" % (referrers,))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001643
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001644 def test_no_servername(self):
1645 """
1646 When a client specifies no server name, the callback passed to
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001647 :py:obj:`Context.set_tlsext_servername_callback` is invoked and the
1648 result of :py:obj:`Connection.get_servername` is :py:obj:`None`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001649 """
1650 args = []
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001651
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001652 def servername(conn):
1653 args.append((conn, conn.get_servername()))
1654 context = Context(TLSv1_METHOD)
1655 context.set_tlsext_servername_callback(servername)
1656
1657 # Lose our reference to it. The Context is responsible for keeping it
1658 # alive now.
1659 del servername
1660 collect()
1661
1662 # Necessary to actually accept the connection
1663 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001664 context.use_certificate(
1665 load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001666
1667 # Do a little connection to trigger the logic
1668 server = Connection(context, None)
1669 server.set_accept_state()
1670
1671 client = Connection(Context(TLSv1_METHOD), None)
1672 client.set_connect_state()
1673
1674 self._interactInMemory(server, client)
1675
1676 self.assertEqual([(server, None)], args)
1677
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001678 def test_servername(self):
1679 """
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001680 When a client specifies a server name in its hello message, the
1681 callback passed to :py:obj:`Contexts.set_tlsext_servername_callback` is
1682 invoked and the result of :py:obj:`Connection.get_servername` is that
1683 server name.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001684 """
1685 args = []
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001686
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001687 def servername(conn):
1688 args.append((conn, conn.get_servername()))
1689 context = Context(TLSv1_METHOD)
1690 context.set_tlsext_servername_callback(servername)
1691
1692 # Necessary to actually accept the connection
1693 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001694 context.use_certificate(
1695 load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001696
1697 # Do a little connection to trigger the logic
1698 server = Connection(context, None)
1699 server.set_accept_state()
1700
1701 client = Connection(Context(TLSv1_METHOD), None)
1702 client.set_connect_state()
1703 client.set_tlsext_host_name(b("foo1.example.com"))
1704
1705 self._interactInMemory(server, client)
1706
1707 self.assertEqual([(server, b("foo1.example.com"))], args)
1708
1709
Cory Benfield84a121e2014-03-31 20:30:25 +01001710class NextProtoNegotiationTests(TestCase, _LoopbackMixin):
1711 """
1712 Test for Next Protocol Negotiation in PyOpenSSL.
1713 """
Cory Benfieldba1820d2015-04-13 17:39:12 -04001714 if _lib.Cryptography_HAS_NEXTPROTONEG:
1715 def test_npn_success(self):
1716 """
1717 Tests that clients and servers that agree on the negotiated next
1718 protocol can correct establish a connection, and that the agreed
1719 protocol is reported by the connections.
1720 """
1721 advertise_args = []
1722 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001723
Cory Benfieldba1820d2015-04-13 17:39:12 -04001724 def advertise(conn):
1725 advertise_args.append((conn,))
1726 return [b'http/1.1', b'spdy/2']
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001727
Cory Benfieldba1820d2015-04-13 17:39:12 -04001728 def select(conn, options):
1729 select_args.append((conn, options))
1730 return b'spdy/2'
Cory Benfield84a121e2014-03-31 20:30:25 +01001731
Cory Benfieldba1820d2015-04-13 17:39:12 -04001732 server_context = Context(TLSv1_METHOD)
1733 server_context.set_npn_advertise_callback(advertise)
Cory Benfield84a121e2014-03-31 20:30:25 +01001734
Cory Benfieldba1820d2015-04-13 17:39:12 -04001735 client_context = Context(TLSv1_METHOD)
1736 client_context.set_npn_select_callback(select)
Cory Benfield84a121e2014-03-31 20:30:25 +01001737
Cory Benfieldba1820d2015-04-13 17:39:12 -04001738 # Necessary to actually accept the connection
1739 server_context.use_privatekey(
1740 load_privatekey(FILETYPE_PEM, server_key_pem))
1741 server_context.use_certificate(
1742 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield84a121e2014-03-31 20:30:25 +01001743
Cory Benfieldba1820d2015-04-13 17:39:12 -04001744 # Do a little connection to trigger the logic
1745 server = Connection(server_context, None)
1746 server.set_accept_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001747
Cory Benfieldba1820d2015-04-13 17:39:12 -04001748 client = Connection(client_context, None)
1749 client.set_connect_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001750
Cory Benfieldba1820d2015-04-13 17:39:12 -04001751 self._interactInMemory(server, client)
Cory Benfield84a121e2014-03-31 20:30:25 +01001752
Cory Benfieldba1820d2015-04-13 17:39:12 -04001753 self.assertEqual([(server,)], advertise_args)
1754 self.assertEqual([(client, [b'http/1.1', b'spdy/2'])], select_args)
Cory Benfield84a121e2014-03-31 20:30:25 +01001755
Cory Benfieldba1820d2015-04-13 17:39:12 -04001756 self.assertEqual(server.get_next_proto_negotiated(), b'spdy/2')
1757 self.assertEqual(client.get_next_proto_negotiated(), b'spdy/2')
Cory Benfield84a121e2014-03-31 20:30:25 +01001758
Cory Benfieldba1820d2015-04-13 17:39:12 -04001759 def test_npn_client_fail(self):
1760 """
1761 Tests that when clients and servers cannot agree on what protocol
1762 to use next that the TLS connection does not get established.
1763 """
1764 advertise_args = []
1765 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001766
Cory Benfieldba1820d2015-04-13 17:39:12 -04001767 def advertise(conn):
1768 advertise_args.append((conn,))
1769 return [b'http/1.1', b'spdy/2']
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001770
Cory Benfieldba1820d2015-04-13 17:39:12 -04001771 def select(conn, options):
1772 select_args.append((conn, options))
1773 return b''
Cory Benfield84a121e2014-03-31 20:30:25 +01001774
Cory Benfieldba1820d2015-04-13 17:39:12 -04001775 server_context = Context(TLSv1_METHOD)
1776 server_context.set_npn_advertise_callback(advertise)
Cory Benfield84a121e2014-03-31 20:30:25 +01001777
Cory Benfieldba1820d2015-04-13 17:39:12 -04001778 client_context = Context(TLSv1_METHOD)
1779 client_context.set_npn_select_callback(select)
Cory Benfield84a121e2014-03-31 20:30:25 +01001780
Cory Benfieldba1820d2015-04-13 17:39:12 -04001781 # Necessary to actually accept the connection
1782 server_context.use_privatekey(
1783 load_privatekey(FILETYPE_PEM, server_key_pem))
1784 server_context.use_certificate(
1785 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield84a121e2014-03-31 20:30:25 +01001786
Cory Benfieldba1820d2015-04-13 17:39:12 -04001787 # Do a little connection to trigger the logic
1788 server = Connection(server_context, None)
1789 server.set_accept_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001790
Cory Benfieldba1820d2015-04-13 17:39:12 -04001791 client = Connection(client_context, None)
1792 client.set_connect_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001793
Cory Benfieldba1820d2015-04-13 17:39:12 -04001794 # If the client doesn't return anything, the connection will fail.
1795 self.assertRaises(Error, self._interactInMemory, server, client)
Cory Benfield84a121e2014-03-31 20:30:25 +01001796
Cory Benfieldba1820d2015-04-13 17:39:12 -04001797 self.assertEqual([(server,)], advertise_args)
1798 self.assertEqual([(client, [b'http/1.1', b'spdy/2'])], select_args)
Cory Benfield84a121e2014-03-31 20:30:25 +01001799
Cory Benfieldba1820d2015-04-13 17:39:12 -04001800 def test_npn_select_error(self):
1801 """
1802 Test that we can handle exceptions in the select callback. If
1803 select fails it should be fatal to the connection.
1804 """
1805 advertise_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001806
Cory Benfieldba1820d2015-04-13 17:39:12 -04001807 def advertise(conn):
1808 advertise_args.append((conn,))
1809 return [b'http/1.1', b'spdy/2']
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001810
Cory Benfieldba1820d2015-04-13 17:39:12 -04001811 def select(conn, options):
1812 raise TypeError
Cory Benfield0ea76e72015-03-22 09:05:28 +00001813
Cory Benfieldba1820d2015-04-13 17:39:12 -04001814 server_context = Context(TLSv1_METHOD)
1815 server_context.set_npn_advertise_callback(advertise)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001816
Cory Benfieldba1820d2015-04-13 17:39:12 -04001817 client_context = Context(TLSv1_METHOD)
1818 client_context.set_npn_select_callback(select)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001819
Cory Benfieldba1820d2015-04-13 17:39:12 -04001820 # Necessary to actually accept the connection
1821 server_context.use_privatekey(
1822 load_privatekey(FILETYPE_PEM, server_key_pem))
1823 server_context.use_certificate(
1824 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield0ea76e72015-03-22 09:05:28 +00001825
Cory Benfieldba1820d2015-04-13 17:39:12 -04001826 # Do a little connection to trigger the logic
1827 server = Connection(server_context, None)
1828 server.set_accept_state()
Cory Benfield0ea76e72015-03-22 09:05:28 +00001829
Cory Benfieldba1820d2015-04-13 17:39:12 -04001830 client = Connection(client_context, None)
1831 client.set_connect_state()
Cory Benfield0ea76e72015-03-22 09:05:28 +00001832
Cory Benfieldba1820d2015-04-13 17:39:12 -04001833 # If the callback throws an exception it should be raised here.
1834 self.assertRaises(
1835 TypeError, self._interactInMemory, server, client
1836 )
1837 self.assertEqual([(server,)], advertise_args)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001838
Cory Benfieldba1820d2015-04-13 17:39:12 -04001839 def test_npn_advertise_error(self):
1840 """
1841 Test that we can handle exceptions in the advertise callback. If
1842 advertise fails no NPN is advertised to the client.
1843 """
1844 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001845
Cory Benfieldba1820d2015-04-13 17:39:12 -04001846 def advertise(conn):
1847 raise TypeError
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001848
Hynek Schlawackb4ceed32015-09-05 20:55:19 +02001849 def select(conn, options): # pragma: nocover
1850 """
1851 Assert later that no args are actually appended.
1852 """
Cory Benfieldba1820d2015-04-13 17:39:12 -04001853 select_args.append((conn, options))
1854 return b''
Cory Benfield0ea76e72015-03-22 09:05:28 +00001855
Cory Benfieldba1820d2015-04-13 17:39:12 -04001856 server_context = Context(TLSv1_METHOD)
1857 server_context.set_npn_advertise_callback(advertise)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001858
Cory Benfieldba1820d2015-04-13 17:39:12 -04001859 client_context = Context(TLSv1_METHOD)
1860 client_context.set_npn_select_callback(select)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001861
Cory Benfieldba1820d2015-04-13 17:39:12 -04001862 # Necessary to actually accept the connection
1863 server_context.use_privatekey(
1864 load_privatekey(FILETYPE_PEM, server_key_pem))
1865 server_context.use_certificate(
1866 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield0ea76e72015-03-22 09:05:28 +00001867
Cory Benfieldba1820d2015-04-13 17:39:12 -04001868 # Do a little connection to trigger the logic
1869 server = Connection(server_context, None)
1870 server.set_accept_state()
Cory Benfield0ea76e72015-03-22 09:05:28 +00001871
Cory Benfieldba1820d2015-04-13 17:39:12 -04001872 client = Connection(client_context, None)
1873 client.set_connect_state()
Cory Benfield0ea76e72015-03-22 09:05:28 +00001874
Cory Benfieldba1820d2015-04-13 17:39:12 -04001875 # If the client doesn't return anything, the connection will fail.
1876 self.assertRaises(
1877 TypeError, self._interactInMemory, server, client
1878 )
1879 self.assertEqual([], select_args)
1880
1881 else:
1882 # No NPN.
1883 def test_npn_not_implemented(self):
1884 # Test the context methods first.
1885 context = Context(TLSv1_METHOD)
1886 fail_methods = [
1887 context.set_npn_advertise_callback,
1888 context.set_npn_select_callback,
1889 ]
1890 for method in fail_methods:
1891 self.assertRaises(
1892 NotImplementedError, method, None
1893 )
1894
1895 # Now test a connection.
1896 conn = Connection(context)
1897 fail_methods = [
1898 conn.get_next_proto_negotiated,
1899 ]
1900 for method in fail_methods:
1901 self.assertRaises(NotImplementedError, method)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001902
1903
Cory Benfield12eae892014-06-07 15:42:56 +01001904class ApplicationLayerProtoNegotiationTests(TestCase, _LoopbackMixin):
1905 """
1906 Tests for ALPN in PyOpenSSL.
1907 """
Cory Benfielde46fa842015-04-13 16:50:49 -04001908 # Skip tests on versions that don't support ALPN.
1909 if _lib.Cryptography_HAS_ALPN:
Cory Benfield12eae892014-06-07 15:42:56 +01001910
Cory Benfielde46fa842015-04-13 16:50:49 -04001911 def test_alpn_success(self):
1912 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04001913 Clients and servers that agree on the negotiated ALPN protocol can
1914 correct establish a connection, and the agreed protocol is reported
1915 by the connections.
Cory Benfielde46fa842015-04-13 16:50:49 -04001916 """
1917 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001918
Cory Benfielde46fa842015-04-13 16:50:49 -04001919 def select(conn, options):
1920 select_args.append((conn, options))
1921 return b'spdy/2'
Cory Benfield12eae892014-06-07 15:42:56 +01001922
Cory Benfielde46fa842015-04-13 16:50:49 -04001923 client_context = Context(TLSv1_METHOD)
1924 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfield12eae892014-06-07 15:42:56 +01001925
Cory Benfielde46fa842015-04-13 16:50:49 -04001926 server_context = Context(TLSv1_METHOD)
1927 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01001928
Cory Benfielde46fa842015-04-13 16:50:49 -04001929 # Necessary to actually accept the connection
1930 server_context.use_privatekey(
1931 load_privatekey(FILETYPE_PEM, server_key_pem))
1932 server_context.use_certificate(
1933 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield12eae892014-06-07 15:42:56 +01001934
Cory Benfielde46fa842015-04-13 16:50:49 -04001935 # Do a little connection to trigger the logic
1936 server = Connection(server_context, None)
1937 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001938
Cory Benfielde46fa842015-04-13 16:50:49 -04001939 client = Connection(client_context, None)
1940 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001941
Cory Benfielde46fa842015-04-13 16:50:49 -04001942 self._interactInMemory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001943
Cory Benfielde46fa842015-04-13 16:50:49 -04001944 self.assertEqual([(server, [b'http/1.1', b'spdy/2'])], select_args)
1945
1946 self.assertEqual(server.get_alpn_proto_negotiated(), b'spdy/2')
1947 self.assertEqual(client.get_alpn_proto_negotiated(), b'spdy/2')
Cory Benfield12eae892014-06-07 15:42:56 +01001948
Cory Benfielde46fa842015-04-13 16:50:49 -04001949 def test_alpn_set_on_connection(self):
1950 """
1951 The same as test_alpn_success, but setting the ALPN protocols on
1952 the connection rather than the context.
1953 """
1954 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001955
Cory Benfielde46fa842015-04-13 16:50:49 -04001956 def select(conn, options):
1957 select_args.append((conn, options))
1958 return b'spdy/2'
Cory Benfield12eae892014-06-07 15:42:56 +01001959
Cory Benfielde46fa842015-04-13 16:50:49 -04001960 # Setup the client context but don't set any ALPN protocols.
1961 client_context = Context(TLSv1_METHOD)
Cory Benfield12eae892014-06-07 15:42:56 +01001962
Cory Benfielde46fa842015-04-13 16:50:49 -04001963 server_context = Context(TLSv1_METHOD)
1964 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01001965
Cory Benfielde46fa842015-04-13 16:50:49 -04001966 # Necessary to actually accept the connection
1967 server_context.use_privatekey(
1968 load_privatekey(FILETYPE_PEM, server_key_pem))
1969 server_context.use_certificate(
1970 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield12eae892014-06-07 15:42:56 +01001971
Cory Benfielde46fa842015-04-13 16:50:49 -04001972 # Do a little connection to trigger the logic
1973 server = Connection(server_context, None)
1974 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001975
Cory Benfielde46fa842015-04-13 16:50:49 -04001976 # Set the ALPN protocols on the client connection.
1977 client = Connection(client_context, None)
1978 client.set_alpn_protos([b'http/1.1', b'spdy/2'])
1979 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001980
Cory Benfielde46fa842015-04-13 16:50:49 -04001981 self._interactInMemory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001982
Cory Benfielde46fa842015-04-13 16:50:49 -04001983 self.assertEqual([(server, [b'http/1.1', b'spdy/2'])], select_args)
Cory Benfield12eae892014-06-07 15:42:56 +01001984
Cory Benfielde46fa842015-04-13 16:50:49 -04001985 self.assertEqual(server.get_alpn_proto_negotiated(), b'spdy/2')
1986 self.assertEqual(client.get_alpn_proto_negotiated(), b'spdy/2')
Cory Benfield12eae892014-06-07 15:42:56 +01001987
Cory Benfielde46fa842015-04-13 16:50:49 -04001988 def test_alpn_server_fail(self):
1989 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04001990 When clients and servers cannot agree on what protocol to use next
1991 the TLS connection does not get established.
Cory Benfielde46fa842015-04-13 16:50:49 -04001992 """
1993 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001994
Cory Benfielde46fa842015-04-13 16:50:49 -04001995 def select(conn, options):
1996 select_args.append((conn, options))
1997 return b''
Cory Benfield12eae892014-06-07 15:42:56 +01001998
Cory Benfielde46fa842015-04-13 16:50:49 -04001999 client_context = Context(TLSv1_METHOD)
2000 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfield12eae892014-06-07 15:42:56 +01002001
Cory Benfielde46fa842015-04-13 16:50:49 -04002002 server_context = Context(TLSv1_METHOD)
2003 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01002004
Cory Benfielde46fa842015-04-13 16:50:49 -04002005 # Necessary to actually accept the connection
2006 server_context.use_privatekey(
2007 load_privatekey(FILETYPE_PEM, server_key_pem))
2008 server_context.use_certificate(
2009 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield12eae892014-06-07 15:42:56 +01002010
Cory Benfielde46fa842015-04-13 16:50:49 -04002011 # Do a little connection to trigger the logic
2012 server = Connection(server_context, None)
2013 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01002014
Cory Benfielde46fa842015-04-13 16:50:49 -04002015 client = Connection(client_context, None)
2016 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01002017
Cory Benfielde46fa842015-04-13 16:50:49 -04002018 # If the client doesn't return anything, the connection will fail.
2019 self.assertRaises(Error, self._interactInMemory, server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01002020
Cory Benfielde46fa842015-04-13 16:50:49 -04002021 self.assertEqual([(server, [b'http/1.1', b'spdy/2'])], select_args)
Cory Benfield12eae892014-06-07 15:42:56 +01002022
Cory Benfielde46fa842015-04-13 16:50:49 -04002023 def test_alpn_no_server(self):
2024 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04002025 When clients and servers cannot agree on what protocol to use next
2026 because the server doesn't offer ALPN, no protocol is negotiated.
Cory Benfielde46fa842015-04-13 16:50:49 -04002027 """
2028 client_context = Context(TLSv1_METHOD)
2029 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfielde3d57152015-04-11 17:57:35 -04002030
Cory Benfielde46fa842015-04-13 16:50:49 -04002031 server_context = Context(TLSv1_METHOD)
Cory Benfielde3d57152015-04-11 17:57:35 -04002032
Cory Benfielde46fa842015-04-13 16:50:49 -04002033 # Necessary to actually accept the connection
2034 server_context.use_privatekey(
2035 load_privatekey(FILETYPE_PEM, server_key_pem))
2036 server_context.use_certificate(
2037 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfielde3d57152015-04-11 17:57:35 -04002038
Cory Benfielde46fa842015-04-13 16:50:49 -04002039 # Do a little connection to trigger the logic
2040 server = Connection(server_context, None)
2041 server.set_accept_state()
Cory Benfielde3d57152015-04-11 17:57:35 -04002042
Cory Benfielde46fa842015-04-13 16:50:49 -04002043 client = Connection(client_context, None)
2044 client.set_connect_state()
Cory Benfielde3d57152015-04-11 17:57:35 -04002045
Cory Benfielde46fa842015-04-13 16:50:49 -04002046 # Do the dance.
2047 self._interactInMemory(server, client)
Cory Benfielde3d57152015-04-11 17:57:35 -04002048
Cory Benfielde46fa842015-04-13 16:50:49 -04002049 self.assertEqual(client.get_alpn_proto_negotiated(), b'')
Cory Benfielde3d57152015-04-11 17:57:35 -04002050
Cory Benfielde46fa842015-04-13 16:50:49 -04002051 def test_alpn_callback_exception(self):
2052 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04002053 We can handle exceptions in the ALPN select callback.
Cory Benfielde46fa842015-04-13 16:50:49 -04002054 """
2055 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002056
Cory Benfielde46fa842015-04-13 16:50:49 -04002057 def select(conn, options):
2058 select_args.append((conn, options))
Cory Benfieldef401452015-04-13 18:17:36 -04002059 raise TypeError()
Cory Benfieldf1177e72015-04-12 09:11:49 -04002060
Cory Benfielde46fa842015-04-13 16:50:49 -04002061 client_context = Context(TLSv1_METHOD)
2062 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfieldf1177e72015-04-12 09:11:49 -04002063
Cory Benfielde46fa842015-04-13 16:50:49 -04002064 server_context = Context(TLSv1_METHOD)
2065 server_context.set_alpn_select_callback(select)
Cory Benfieldf1177e72015-04-12 09:11:49 -04002066
Cory Benfielde46fa842015-04-13 16:50:49 -04002067 # Necessary to actually accept the connection
2068 server_context.use_privatekey(
2069 load_privatekey(FILETYPE_PEM, server_key_pem))
2070 server_context.use_certificate(
2071 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfieldf1177e72015-04-12 09:11:49 -04002072
Cory Benfielde46fa842015-04-13 16:50:49 -04002073 # Do a little connection to trigger the logic
2074 server = Connection(server_context, None)
2075 server.set_accept_state()
Cory Benfieldf1177e72015-04-12 09:11:49 -04002076
Cory Benfielde46fa842015-04-13 16:50:49 -04002077 client = Connection(client_context, None)
2078 client.set_connect_state()
Cory Benfieldf1177e72015-04-12 09:11:49 -04002079
Cory Benfielde46fa842015-04-13 16:50:49 -04002080 self.assertRaises(
2081 TypeError, self._interactInMemory, server, client
2082 )
2083 self.assertEqual([(server, [b'http/1.1', b'spdy/2'])], select_args)
Cory Benfieldf1177e72015-04-12 09:11:49 -04002084
Cory Benfield0f7b04c2015-04-13 17:51:12 -04002085 else:
2086 # No ALPN.
2087 def test_alpn_not_implemented(self):
Cory Benfieldef401452015-04-13 18:17:36 -04002088 """
2089 If ALPN is not in OpenSSL, we should raise NotImplementedError.
2090 """
Cory Benfield0f7b04c2015-04-13 17:51:12 -04002091 # Test the context methods first.
2092 context = Context(TLSv1_METHOD)
Cory Benfield307e9e62015-04-13 18:21:12 -04002093 self.assertRaises(
2094 NotImplementedError, context.set_alpn_protos, None
2095 )
2096 self.assertRaises(
2097 NotImplementedError, context.set_alpn_select_callback, None
2098 )
Cory Benfield0f7b04c2015-04-13 17:51:12 -04002099
2100 # Now test a connection.
2101 conn = Connection(context)
Cory Benfield307e9e62015-04-13 18:21:12 -04002102 self.assertRaises(
Alex Gaynor68417232015-09-04 07:56:29 -04002103 NotImplementedError, conn.set_alpn_protos, None
Cory Benfield307e9e62015-04-13 18:21:12 -04002104 )
Cory Benfield0f7b04c2015-04-13 17:51:12 -04002105
Cory Benfieldf1177e72015-04-12 09:11:49 -04002106
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05002107class SessionTests(TestCase):
2108 """
2109 Unit tests for :py:obj:`OpenSSL.SSL.Session`.
2110 """
2111 def test_construction(self):
2112 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002113 :py:class:`Session` can be constructed with no arguments, creating
2114 a new instance of that type.
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05002115 """
2116 new_session = Session()
2117 self.assertTrue(isinstance(new_session, Session))
2118
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05002119 def test_construction_wrong_args(self):
2120 """
2121 If any arguments are passed to :py:class:`Session`, :py:obj:`TypeError`
2122 is raised.
2123 """
2124 self.assertRaises(TypeError, Session, 123)
2125 self.assertRaises(TypeError, Session, "hello")
2126 self.assertRaises(TypeError, Session, object())
2127
2128
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002129class ConnectionTests(TestCase, _LoopbackMixin):
Rick Deane15b1472009-07-09 15:53:42 -05002130 """
Hynek Schlawackaa861212016-03-13 13:53:48 +01002131 Unit tests for :class:`OpenSSL.SSL.Connection`.
Rick Deane15b1472009-07-09 15:53:42 -05002132 """
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04002133 # XXX get_peer_certificate -> None
2134 # XXX sock_shutdown
2135 # XXX master_key -> TypeError
2136 # XXX server_random -> TypeError
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04002137 # XXX connect -> TypeError
2138 # XXX connect_ex -> TypeError
2139 # XXX set_connect_state -> TypeError
2140 # XXX set_accept_state -> TypeError
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04002141 # XXX do_handshake -> TypeError
2142 # XXX bio_read -> TypeError
2143 # XXX recv -> TypeError
2144 # XXX send -> TypeError
2145 # XXX bio_write -> TypeError
2146
Rick Deane15b1472009-07-09 15:53:42 -05002147 def test_type(self):
2148 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002149 :py:obj:`Connection` and :py:obj:`ConnectionType` refer to the same
2150 type object and can be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -05002151 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002152 self.assertIdentical(Connection, ConnectionType)
Rick Deane15b1472009-07-09 15:53:42 -05002153 ctx = Context(TLSv1_METHOD)
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002154 self.assertConsistentType(Connection, 'Connection', ctx, None)
Rick Deane15b1472009-07-09 15:53:42 -05002155
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002156 def test_get_context(self):
2157 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002158 :py:obj:`Connection.get_context` returns the :py:obj:`Context` instance
2159 used to construct the :py:obj:`Connection` instance.
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002160 """
2161 context = Context(TLSv1_METHOD)
2162 connection = Connection(context, None)
2163 self.assertIdentical(connection.get_context(), context)
2164
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002165 def test_get_context_wrong_args(self):
2166 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002167 :py:obj:`Connection.get_context` raises :py:obj:`TypeError` if called
2168 with any arguments.
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002169 """
2170 connection = Connection(Context(TLSv1_METHOD), None)
2171 self.assertRaises(TypeError, connection.get_context, None)
2172
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002173 def test_set_context_wrong_args(self):
2174 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002175 :py:obj:`Connection.set_context` raises :py:obj:`TypeError` if called
2176 with a non-:py:obj:`Context` instance argument or with any number of
2177 arguments other than 1.
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002178 """
2179 ctx = Context(TLSv1_METHOD)
2180 connection = Connection(ctx, None)
2181 self.assertRaises(TypeError, connection.set_context)
2182 self.assertRaises(TypeError, connection.set_context, object())
2183 self.assertRaises(TypeError, connection.set_context, "hello")
2184 self.assertRaises(TypeError, connection.set_context, 1)
2185 self.assertRaises(TypeError, connection.set_context, 1, 2)
2186 self.assertRaises(
2187 TypeError, connection.set_context, Context(TLSv1_METHOD), 2)
2188 self.assertIdentical(ctx, connection.get_context())
2189
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002190 def test_set_context(self):
2191 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002192 :py:obj:`Connection.set_context` specifies a new :py:obj:`Context`
2193 instance to be used for the connection.
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002194 """
2195 original = Context(SSLv23_METHOD)
2196 replacement = Context(TLSv1_METHOD)
2197 connection = Connection(original, None)
2198 connection.set_context(replacement)
2199 self.assertIdentical(replacement, connection.get_context())
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002200 # Lose our references to the contexts, just in case the Connection
2201 # isn't properly managing its own contributions to their reference
2202 # counts.
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002203 del original, replacement
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002204 collect()
2205
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002206 def test_set_tlsext_host_name_wrong_args(self):
2207 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002208 If :py:obj:`Connection.set_tlsext_host_name` is called with a non-byte
2209 string argument or a byte string with an embedded NUL or other than one
Jonathan Ballet648875f2011-07-16 14:14:58 +09002210 argument, :py:obj:`TypeError` is raised.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002211 """
2212 conn = Connection(Context(TLSv1_METHOD), None)
2213 self.assertRaises(TypeError, conn.set_tlsext_host_name)
2214 self.assertRaises(TypeError, conn.set_tlsext_host_name, object())
2215 self.assertRaises(TypeError, conn.set_tlsext_host_name, 123, 456)
2216 self.assertRaises(
2217 TypeError, conn.set_tlsext_host_name, b("with\0null"))
2218
Abraham Martinc5484ba2015-03-25 15:33:05 +00002219 if PY3:
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002220 # On Python 3.x, don't accidentally implicitly convert from text.
2221 self.assertRaises(
2222 TypeError,
2223 conn.set_tlsext_host_name, b("example.com").decode("ascii"))
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002224
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04002225 def test_get_servername_wrong_args(self):
2226 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002227 :py:obj:`Connection.get_servername` raises :py:obj:`TypeError` if
2228 called with any arguments.
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04002229 """
2230 connection = Connection(Context(TLSv1_METHOD), None)
2231 self.assertRaises(TypeError, connection.get_servername, object())
2232 self.assertRaises(TypeError, connection.get_servername, 1)
2233 self.assertRaises(TypeError, connection.get_servername, "hello")
2234
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002235 def test_pending(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002236 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002237 :py:obj:`Connection.pending` returns the number of bytes available for
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002238 immediate read.
2239 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002240 connection = Connection(Context(TLSv1_METHOD), None)
2241 self.assertEquals(connection.pending(), 0)
2242
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002243 def test_pending_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002244 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002245 :py:obj:`Connection.pending` raises :py:obj:`TypeError` if called with
2246 any arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002247 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002248 connection = Connection(Context(TLSv1_METHOD), None)
2249 self.assertRaises(TypeError, connection.pending, None)
2250
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002251 def test_peek(self):
2252 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002253 :py:obj:`Connection.recv` peeks into the connection if
2254 :py:obj:`socket.MSG_PEEK` is passed.
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002255 """
2256 server, client = self._loopback()
2257 server.send(b('xy'))
2258 self.assertEqual(client.recv(2, MSG_PEEK), b('xy'))
2259 self.assertEqual(client.recv(2, MSG_PEEK), b('xy'))
2260 self.assertEqual(client.recv(2), b('xy'))
2261
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002262 def test_connect_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002263 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002264 :py:obj:`Connection.connect` raises :py:obj:`TypeError` if called with
2265 a non-address argument or with the wrong number of arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002266 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002267 connection = Connection(Context(TLSv1_METHOD), socket())
2268 self.assertRaises(TypeError, connection.connect, None)
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002269 self.assertRaises(TypeError, connection.connect)
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002270 self.assertRaises(
2271 TypeError, connection.connect, ("127.0.0.1", 1), None
2272 )
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002273
kjavfe508d62015-09-02 12:20:35 +01002274 def test_connection_undefined_attr(self):
2275 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002276 :py:obj:`Connection.connect` raises :py:obj:`TypeError` if called with
2277 a non-address argument or with the wrong number of arguments.
kjavfe508d62015-09-02 12:20:35 +01002278 """
Alex Gaynor1aabb2e2015-09-05 13:35:18 -04002279
kjavfe508d62015-09-02 12:20:35 +01002280 def attr_access_test(connection):
2281 return connection.an_attribute_which_is_not_defined
Alex Gaynor1aabb2e2015-09-05 13:35:18 -04002282
kjavfe508d62015-09-02 12:20:35 +01002283 connection = Connection(Context(TLSv1_METHOD), None)
2284 self.assertRaises(AttributeError, attr_access_test, connection)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002285
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002286 def test_connect_refused(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002287 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002288 :py:obj:`Connection.connect` raises :py:obj:`socket.error` if the
2289 underlying socket connect method raises it.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002290 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002291 client = socket()
2292 context = Context(TLSv1_METHOD)
2293 clientSSL = Connection(context, client)
Alex Gaynor122717b2015-09-05 14:14:18 -04002294 # pytest.raises here doesn't work because of a bug in py.test on Python
2295 # 2.6: https://github.com/pytest-dev/pytest/issues/988
Alex Gaynore69c2782015-09-05 14:07:48 -04002296 try:
Alex Gaynor1aabb2e2015-09-05 13:35:18 -04002297 clientSSL.connect(("127.0.0.1", 1))
Alex Gaynore69c2782015-09-05 14:07:48 -04002298 except error as e:
Alex Gaynor20a4c082015-09-05 14:24:15 -04002299 exc = e
2300 assert exc.args[0] == ECONNREFUSED
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002301
2302 def test_connect(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002303 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002304 :py:obj:`Connection.connect` establishes a connection to the specified
2305 address.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002306 """
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002307 port = socket()
2308 port.bind(('', 0))
2309 port.listen(3)
2310
2311 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002312 clientSSL.connect(('127.0.0.1', port.getsockname()[1]))
2313 # XXX An assertion? Or something?
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002314
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002315 @pytest.mark.skipif(
2316 platform == "darwin",
2317 reason="connect_ex sometimes causes a kernel panic on OS X 10.6.4"
2318 )
2319 def test_connect_ex(self):
2320 """
2321 If there is a connection error, :py:obj:`Connection.connect_ex`
2322 returns the errno instead of raising an exception.
2323 """
2324 port = socket()
2325 port.bind(('', 0))
2326 port.listen(3)
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002327
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002328 clientSSL = Connection(Context(TLSv1_METHOD), socket())
2329 clientSSL.setblocking(False)
2330 result = clientSSL.connect_ex(port.getsockname())
2331 expected = (EINPROGRESS, EWOULDBLOCK)
2332 self.assertTrue(
2333 result in expected, "%r not in %r" % (result, expected))
Jean-Paul Calderone55d91f42010-07-29 19:22:17 -04002334
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002335 def test_accept_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002336 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002337 :py:obj:`Connection.accept` raises :py:obj:`TypeError` if called with
2338 any arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002339 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002340 connection = Connection(Context(TLSv1_METHOD), socket())
2341 self.assertRaises(TypeError, connection.accept, None)
2342
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002343 def test_accept(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002344 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002345 :py:obj:`Connection.accept` accepts a pending connection attempt and
2346 returns a tuple of a new :py:obj:`Connection` (the accepted client) and
2347 the address the connection originated from.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002348 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002349 ctx = Context(TLSv1_METHOD)
2350 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2351 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002352 port = socket()
2353 portSSL = Connection(ctx, port)
2354 portSSL.bind(('', 0))
2355 portSSL.listen(3)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002356
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002357 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002358
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002359 # Calling portSSL.getsockname() here to get the server IP address
2360 # sounds great, but frequently fails on Windows.
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002361 clientSSL.connect(('127.0.0.1', portSSL.getsockname()[1]))
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002362
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002363 serverSSL, address = portSSL.accept()
2364
2365 self.assertTrue(isinstance(serverSSL, Connection))
2366 self.assertIdentical(serverSSL.get_context(), ctx)
2367 self.assertEquals(address, clientSSL.getsockname())
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002368
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002369 def test_shutdown_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002370 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002371 :py:obj:`Connection.shutdown` raises :py:obj:`TypeError` if called with
2372 the wrong number of arguments or with arguments other than integers.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002373 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002374 connection = Connection(Context(TLSv1_METHOD), None)
2375 self.assertRaises(TypeError, connection.shutdown, None)
Jean-Paul Calderone1d3e0222010-07-29 22:52:45 -04002376 self.assertRaises(TypeError, connection.get_shutdown, None)
2377 self.assertRaises(TypeError, connection.set_shutdown)
2378 self.assertRaises(TypeError, connection.set_shutdown, None)
2379 self.assertRaises(TypeError, connection.set_shutdown, 0, 1)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002380
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002381 def test_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002382 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002383 :py:obj:`Connection.shutdown` performs an SSL-level connection
2384 shutdown.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002385 """
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002386 server, client = self._loopback()
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04002387 self.assertFalse(server.shutdown())
2388 self.assertEquals(server.get_shutdown(), SENT_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002389 self.assertRaises(ZeroReturnError, client.recv, 1024)
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04002390 self.assertEquals(client.get_shutdown(), RECEIVED_SHUTDOWN)
2391 client.shutdown()
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002392 self.assertEquals(
2393 client.get_shutdown(), SENT_SHUTDOWN | RECEIVED_SHUTDOWN
2394 )
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04002395 self.assertRaises(ZeroReturnError, server.recv, 1024)
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002396 self.assertEquals(
2397 server.get_shutdown(), SENT_SHUTDOWN | RECEIVED_SHUTDOWN
2398 )
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002399
Paul Aurichc85e0862015-01-08 08:34:33 -08002400 def test_shutdown_closed(self):
2401 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002402 If the underlying socket is closed, :py:obj:`Connection.shutdown`
2403 propagates the write error from the low level write call.
Paul Aurichc85e0862015-01-08 08:34:33 -08002404 """
2405 server, client = self._loopback()
2406 server.sock_shutdown(2)
2407 exc = self.assertRaises(SysCallError, server.shutdown)
2408 if platform == "win32":
2409 self.assertEqual(exc.args[0], ESHUTDOWN)
2410 else:
2411 self.assertEqual(exc.args[0], EPIPE)
2412
Glyph89389472015-04-14 17:29:26 -04002413 def test_shutdown_truncated(self):
Glyph6064ec32015-04-14 16:38:22 -04002414 """
Glyph89389472015-04-14 17:29:26 -04002415 If the underlying connection is truncated, :obj:`Connection.shutdown`
2416 raises an :obj:`Error`.
Glyph6064ec32015-04-14 16:38:22 -04002417 """
Glyph89389472015-04-14 17:29:26 -04002418 server_ctx = Context(TLSv1_METHOD)
2419 client_ctx = Context(TLSv1_METHOD)
2420 server_ctx.use_privatekey(
2421 load_privatekey(FILETYPE_PEM, server_key_pem))
2422 server_ctx.use_certificate(
2423 load_certificate(FILETYPE_PEM, server_cert_pem))
2424 server = Connection(server_ctx, None)
2425 client = Connection(client_ctx, None)
2426 self._handshakeInMemory(client, server)
2427 self.assertEqual(server.shutdown(), False)
2428 self.assertRaises(WantReadError, server.shutdown)
2429 server.bio_shutdown()
Glyph6064ec32015-04-14 16:38:22 -04002430 self.assertRaises(Error, server.shutdown)
2431
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002432 def test_set_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002433 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002434 :py:obj:`Connection.set_shutdown` sets the state of the SSL connection
2435 shutdown process.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002436 """
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002437 connection = Connection(Context(TLSv1_METHOD), socket())
2438 connection.set_shutdown(RECEIVED_SHUTDOWN)
2439 self.assertEquals(connection.get_shutdown(), RECEIVED_SHUTDOWN)
2440
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002441 @skip_if_py3
2442 def test_set_shutdown_long(self):
2443 """
2444 On Python 2 :py:obj:`Connection.set_shutdown` accepts an argument
2445 of type :py:obj:`long` as well as :py:obj:`int`.
2446 """
2447 connection = Connection(Context(TLSv1_METHOD), socket())
2448 connection.set_shutdown(long(RECEIVED_SHUTDOWN))
2449 self.assertEquals(connection.get_shutdown(), RECEIVED_SHUTDOWN)
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -05002450
kjavaf248592015-09-07 12:14:01 +01002451 def test_state_string(self):
2452 """
Hynek Schlawackb0274ce2015-10-16 19:56:26 +02002453 :meth:`Connection.state_string` verbosely describes the current
2454 state of the :class:`Connection`.
kjavaf248592015-09-07 12:14:01 +01002455 """
Hynek Schlawackb0274ce2015-10-16 19:56:26 +02002456 server, client = socket_pair()
kjavaf248592015-09-07 12:14:01 +01002457 server = self._loopbackServerFactory(server)
2458 client = self._loopbackClientFactory(client)
2459
Hynek Schlawackea94f2b2016-03-13 16:17:53 +01002460 assert b"before/accept initialization" == server.get_state_string()
2461 assert b"before/connect initialization" == client.get_state_string()
kjavaf248592015-09-07 12:14:01 +01002462
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002463 def test_app_data_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002464 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002465 :py:obj:`Connection.set_app_data` raises :py:obj:`TypeError` if called
2466 with other than one argument. :py:obj:`Connection.get_app_data` raises
2467 :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002468 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002469 conn = Connection(Context(TLSv1_METHOD), None)
2470 self.assertRaises(TypeError, conn.get_app_data, None)
2471 self.assertRaises(TypeError, conn.set_app_data)
2472 self.assertRaises(TypeError, conn.set_app_data, None, None)
2473
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002474 def test_app_data(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002475 """
2476 Any object can be set as app data by passing it to
Jonathan Ballet648875f2011-07-16 14:14:58 +09002477 :py:obj:`Connection.set_app_data` and later retrieved with
2478 :py:obj:`Connection.get_app_data`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002479 """
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002480 conn = Connection(Context(TLSv1_METHOD), None)
Todd Chapman4f73e4f2015-08-27 11:26:43 -04002481 assert None is conn.get_app_data()
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002482 app_data = object()
2483 conn.set_app_data(app_data)
Todd Chapman4f73e4f2015-08-27 11:26:43 -04002484 assert conn.get_app_data() is app_data
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002485
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002486 def test_makefile(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002487 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002488 :py:obj:`Connection.makefile` is not implemented and calling that
2489 method raises :py:obj:`NotImplementedError`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002490 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002491 conn = Connection(Context(TLSv1_METHOD), None)
2492 self.assertRaises(NotImplementedError, conn.makefile)
2493
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002494 def test_get_peer_cert_chain_wrong_args(self):
2495 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002496 :py:obj:`Connection.get_peer_cert_chain` raises :py:obj:`TypeError` if
2497 called with any arguments.
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002498 """
2499 conn = Connection(Context(TLSv1_METHOD), None)
2500 self.assertRaises(TypeError, conn.get_peer_cert_chain, 1)
2501 self.assertRaises(TypeError, conn.get_peer_cert_chain, "foo")
2502 self.assertRaises(TypeError, conn.get_peer_cert_chain, object())
2503 self.assertRaises(TypeError, conn.get_peer_cert_chain, [])
2504
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002505 def test_get_peer_cert_chain(self):
2506 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002507 :py:obj:`Connection.get_peer_cert_chain` returns a list of certificates
2508 which the connected server returned for the certification verification.
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002509 """
2510 chain = _create_certificate_chain()
2511 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
2512
2513 serverContext = Context(TLSv1_METHOD)
2514 serverContext.use_privatekey(skey)
2515 serverContext.use_certificate(scert)
2516 serverContext.add_extra_chain_cert(icert)
2517 serverContext.add_extra_chain_cert(cacert)
2518 server = Connection(serverContext, None)
2519 server.set_accept_state()
2520
2521 # Create the client
2522 clientContext = Context(TLSv1_METHOD)
2523 clientContext.set_verify(VERIFY_NONE, verify_cb)
2524 client = Connection(clientContext, None)
2525 client.set_connect_state()
2526
2527 self._interactInMemory(client, server)
2528
2529 chain = client.get_peer_cert_chain()
2530 self.assertEqual(len(chain), 3)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04002531 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002532 "Server Certificate", chain[0].get_subject().CN)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04002533 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002534 "Intermediate Certificate", chain[1].get_subject().CN)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04002535 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002536 "Authority Certificate", chain[2].get_subject().CN)
2537
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002538 def test_get_peer_cert_chain_none(self):
2539 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002540 :py:obj:`Connection.get_peer_cert_chain` returns :py:obj:`None` if the
2541 peer sends no certificate chain.
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002542 """
2543 ctx = Context(TLSv1_METHOD)
2544 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2545 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
2546 server = Connection(ctx, None)
2547 server.set_accept_state()
2548 client = Connection(Context(TLSv1_METHOD), None)
2549 client.set_connect_state()
2550 self._interactInMemory(client, server)
2551 self.assertIdentical(None, server.get_peer_cert_chain())
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002552
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002553 def test_get_session_wrong_args(self):
2554 """
2555 :py:obj:`Connection.get_session` raises :py:obj:`TypeError` if called
2556 with any arguments.
2557 """
2558 ctx = Context(TLSv1_METHOD)
2559 server = Connection(ctx, None)
2560 self.assertRaises(TypeError, server.get_session, 123)
2561 self.assertRaises(TypeError, server.get_session, "hello")
2562 self.assertRaises(TypeError, server.get_session, object())
2563
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002564 def test_get_session_unconnected(self):
2565 """
2566 :py:obj:`Connection.get_session` returns :py:obj:`None` when used with
2567 an object which has not been connected.
2568 """
2569 ctx = Context(TLSv1_METHOD)
2570 server = Connection(ctx, None)
2571 session = server.get_session()
2572 self.assertIdentical(None, session)
2573
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002574 def test_server_get_session(self):
2575 """
2576 On the server side of a connection, :py:obj:`Connection.get_session`
2577 returns a :py:class:`Session` instance representing the SSL session for
2578 that connection.
2579 """
2580 server, client = self._loopback()
2581 session = server.get_session()
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08002582 self.assertIsInstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002583
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002584 def test_client_get_session(self):
2585 """
2586 On the client side of a connection, :py:obj:`Connection.get_session`
2587 returns a :py:class:`Session` instance representing the SSL session for
2588 that connection.
2589 """
2590 server, client = self._loopback()
2591 session = client.get_session()
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08002592 self.assertIsInstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002593
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002594 def test_set_session_wrong_args(self):
2595 """
Hynek Schlawackdddd1112015-09-05 21:12:30 +02002596 If called with an object that is not an instance of
2597 :py:class:`Session`, or with other than one argument,
2598 :py:obj:`Connection.set_session` raises :py:obj:`TypeError`.
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002599 """
2600 ctx = Context(TLSv1_METHOD)
2601 connection = Connection(ctx, None)
2602 self.assertRaises(TypeError, connection.set_session)
2603 self.assertRaises(TypeError, connection.set_session, 123)
2604 self.assertRaises(TypeError, connection.set_session, "hello")
2605 self.assertRaises(TypeError, connection.set_session, object())
2606 self.assertRaises(
2607 TypeError, connection.set_session, Session(), Session())
2608
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002609 def test_client_set_session(self):
2610 """
2611 :py:obj:`Connection.set_session`, when used prior to a connection being
2612 established, accepts a :py:class:`Session` instance and causes an
2613 attempt to re-use the session it represents when the SSL handshake is
2614 performed.
2615 """
2616 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2617 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
2618 ctx = Context(TLSv1_METHOD)
2619 ctx.use_privatekey(key)
2620 ctx.use_certificate(cert)
2621 ctx.set_session_id("unity-test")
2622
2623 def makeServer(socket):
2624 server = Connection(ctx, socket)
2625 server.set_accept_state()
2626 return server
2627
2628 originalServer, originalClient = self._loopback(
2629 serverFactory=makeServer)
2630 originalSession = originalClient.get_session()
2631
2632 def makeClient(socket):
2633 client = self._loopbackClientFactory(socket)
2634 client.set_session(originalSession)
2635 return client
2636 resumedServer, resumedClient = self._loopback(
2637 serverFactory=makeServer,
2638 clientFactory=makeClient)
2639
2640 # This is a proxy: in general, we have no access to any unique
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002641 # identifier for the session (new enough versions of OpenSSL expose
2642 # a hash which could be usable, but "new enough" is very, very new).
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002643 # Instead, exploit the fact that the master key is re-used if the
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002644 # session is re-used. As long as the master key for the two
2645 # connections is the same, the session was re-used!
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002646 self.assertEqual(
2647 originalServer.master_key(), resumedServer.master_key())
2648
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002649 def test_set_session_wrong_method(self):
2650 """
Jean-Paul Calderone068cb592012-02-14 16:52:43 -05002651 If :py:obj:`Connection.set_session` is passed a :py:class:`Session`
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002652 instance associated with a context using a different SSL method than
2653 the :py:obj:`Connection` is using, a :py:class:`OpenSSL.SSL.Error` is
Jean-Paul Calderone068cb592012-02-14 16:52:43 -05002654 raised.
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002655 """
2656 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2657 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
2658 ctx = Context(TLSv1_METHOD)
2659 ctx.use_privatekey(key)
2660 ctx.use_certificate(cert)
2661 ctx.set_session_id("unity-test")
2662
2663 def makeServer(socket):
2664 server = Connection(ctx, socket)
2665 server.set_accept_state()
2666 return server
2667
2668 originalServer, originalClient = self._loopback(
2669 serverFactory=makeServer)
2670 originalSession = originalClient.get_session()
2671
2672 def makeClient(socket):
2673 # Intentionally use a different, incompatible method here.
2674 client = Connection(Context(SSLv3_METHOD), socket)
2675 client.set_connect_state()
2676 client.set_session(originalSession)
2677 return client
2678
2679 self.assertRaises(
2680 Error,
2681 self._loopback, clientFactory=makeClient, serverFactory=makeServer)
2682
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002683 def test_wantWriteError(self):
2684 """
2685 :py:obj:`Connection` methods which generate output raise
2686 :py:obj:`OpenSSL.SSL.WantWriteError` if writing to the connection's BIO
2687 fail indicating a should-write state.
2688 """
2689 client_socket, server_socket = socket_pair()
2690 # Fill up the client's send buffer so Connection won't be able to write
Jean-Paul Calderonebbff8b92014-03-22 14:20:30 -04002691 # anything. Only write a single byte at a time so we can be sure we
2692 # completely fill the buffer. Even though the socket API is allowed to
2693 # signal a short write via its return value it seems this doesn't
2694 # always happen on all platforms (FreeBSD and OS X particular) for the
2695 # very last bit of available buffer space.
2696 msg = b"x"
2697 for i in range(1024 * 1024 * 4):
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002698 try:
2699 client_socket.send(msg)
2700 except error as e:
2701 if e.errno == EWOULDBLOCK:
2702 break
2703 raise
2704 else:
2705 self.fail(
2706 "Failed to fill socket buffer, cannot test BIO want write")
2707
2708 ctx = Context(TLSv1_METHOD)
2709 conn = Connection(ctx, client_socket)
2710 # Client's speak first, so make it an SSL client
2711 conn.set_connect_state()
2712 self.assertRaises(WantWriteError, conn.do_handshake)
2713
2714 # XXX want_read
2715
Fedor Brunner416f4a12014-03-28 13:18:38 +01002716 def test_get_finished_before_connect(self):
Fedor Brunner5747b932014-03-05 14:22:34 +01002717 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002718 :py:obj:`Connection.get_finished` returns :py:obj:`None` before TLS
2719 handshake is completed.
Fedor Brunner5747b932014-03-05 14:22:34 +01002720 """
Fedor Brunner5747b932014-03-05 14:22:34 +01002721 ctx = Context(TLSv1_METHOD)
2722 connection = Connection(ctx, None)
2723 self.assertEqual(connection.get_finished(), None)
Fedor Brunner416f4a12014-03-28 13:18:38 +01002724
2725 def test_get_peer_finished_before_connect(self):
2726 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002727 :py:obj:`Connection.get_peer_finished` returns :py:obj:`None` before
2728 TLS handshake is completed.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002729 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002730 ctx = Context(TLSv1_METHOD)
2731 connection = Connection(ctx, None)
Fedor Brunner5747b932014-03-05 14:22:34 +01002732 self.assertEqual(connection.get_peer_finished(), None)
2733
Fedor Brunner416f4a12014-03-28 13:18:38 +01002734 def test_get_finished(self):
2735 """
2736 :py:obj:`Connection.get_finished` method returns the TLS Finished
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002737 message send from client, or server. Finished messages are send during
2738 TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002739 """
2740
Fedor Brunner5747b932014-03-05 14:22:34 +01002741 server, client = self._loopback()
2742
2743 self.assertNotEqual(server.get_finished(), None)
2744 self.assertTrue(len(server.get_finished()) > 0)
Fedor Brunner416f4a12014-03-28 13:18:38 +01002745
2746 def test_get_peer_finished(self):
2747 """
2748 :py:obj:`Connection.get_peer_finished` method returns the TLS Finished
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002749 message received from client, or server. Finished messages are send
2750 during TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002751 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002752 server, client = self._loopback()
2753
2754 self.assertNotEqual(server.get_peer_finished(), None)
Fedor Brunner5747b932014-03-05 14:22:34 +01002755 self.assertTrue(len(server.get_peer_finished()) > 0)
2756
Fedor Brunner416f4a12014-03-28 13:18:38 +01002757 def test_tls_finished_message_symmetry(self):
2758 """
Hynek Schlawackdddd1112015-09-05 21:12:30 +02002759 The TLS Finished message send by server must be the TLS Finished
2760 message received by client.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002761
Hynek Schlawackdddd1112015-09-05 21:12:30 +02002762 The TLS Finished message send by client must be the TLS Finished
2763 message received by server.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002764 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002765 server, client = self._loopback()
2766
Fedor Brunner5747b932014-03-05 14:22:34 +01002767 self.assertEqual(server.get_finished(), client.get_peer_finished())
2768 self.assertEqual(client.get_finished(), server.get_peer_finished())
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002769
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002770 def test_get_cipher_name_before_connect(self):
2771 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002772 :py:obj:`Connection.get_cipher_name` returns :py:obj:`None` if no
2773 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002774 """
2775 ctx = Context(TLSv1_METHOD)
2776 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002777 self.assertIdentical(conn.get_cipher_name(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002778
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002779 def test_get_cipher_name(self):
2780 """
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002781 :py:obj:`Connection.get_cipher_name` returns a :py:class:`unicode`
2782 string giving the name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002783 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002784 server, client = self._loopback()
2785 server_cipher_name, client_cipher_name = \
2786 server.get_cipher_name(), client.get_cipher_name()
2787
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002788 self.assertIsInstance(server_cipher_name, text_type)
2789 self.assertIsInstance(client_cipher_name, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002790
2791 self.assertEqual(server_cipher_name, client_cipher_name)
2792
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002793 def test_get_cipher_version_before_connect(self):
2794 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002795 :py:obj:`Connection.get_cipher_version` returns :py:obj:`None` if no
2796 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002797 """
2798 ctx = Context(TLSv1_METHOD)
2799 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002800 self.assertIdentical(conn.get_cipher_version(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002801
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002802 def test_get_cipher_version(self):
2803 """
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002804 :py:obj:`Connection.get_cipher_version` returns a :py:class:`unicode`
2805 string giving the protocol name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002806 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002807 server, client = self._loopback()
2808 server_cipher_version, client_cipher_version = \
2809 server.get_cipher_version(), client.get_cipher_version()
2810
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002811 self.assertIsInstance(server_cipher_version, text_type)
2812 self.assertIsInstance(client_cipher_version, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002813
2814 self.assertEqual(server_cipher_version, client_cipher_version)
2815
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002816 def test_get_cipher_bits_before_connect(self):
2817 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002818 :py:obj:`Connection.get_cipher_bits` returns :py:obj:`None` if no
2819 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002820 """
2821 ctx = Context(TLSv1_METHOD)
2822 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002823 self.assertIdentical(conn.get_cipher_bits(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002824
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002825 def test_get_cipher_bits(self):
2826 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002827 :py:obj:`Connection.get_cipher_bits` returns the number of secret bits
2828 of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002829 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002830 server, client = self._loopback()
2831 server_cipher_bits, client_cipher_bits = \
2832 server.get_cipher_bits(), client.get_cipher_bits()
2833
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002834 self.assertIsInstance(server_cipher_bits, int)
2835 self.assertIsInstance(client_cipher_bits, int)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002836
2837 self.assertEqual(server_cipher_bits, client_cipher_bits)
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002838
Jim Shaverabff1882015-05-27 09:15:55 -04002839 def test_get_protocol_version_name(self):
2840 """
2841 :py:obj:`Connection.get_protocol_version_name()` returns a string
2842 giving the protocol version of the current connection.
2843 """
2844 server, client = self._loopback()
2845 client_protocol_version_name = client.get_protocol_version_name()
2846 server_protocol_version_name = server.get_protocol_version_name()
2847
Jim Shaver58d25732015-05-28 11:52:32 -04002848 self.assertIsInstance(server_protocol_version_name, text_type)
2849 self.assertIsInstance(client_protocol_version_name, text_type)
Jim Shaverabff1882015-05-27 09:15:55 -04002850
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002851 self.assertEqual(
2852 server_protocol_version_name, client_protocol_version_name
2853 )
Jim Shaverabff1882015-05-27 09:15:55 -04002854
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002855 def test_get_protocol_version(self):
2856 """
Alex Gaynor43307782015-09-04 09:05:45 -04002857 :py:obj:`Connection.get_protocol_version()` returns an integer
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002858 giving the protocol version of the current connection.
2859 """
2860 server, client = self._loopback()
Jim Shaver85a4dff2015-04-27 17:42:46 -04002861 client_protocol_version = client.get_protocol_version()
2862 server_protocol_version = server.get_protocol_version()
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002863
Jim Shaverabff1882015-05-27 09:15:55 -04002864 self.assertIsInstance(server_protocol_version, int)
2865 self.assertIsInstance(client_protocol_version, int)
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002866
2867 self.assertEqual(server_protocol_version, client_protocol_version)
2868
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002869
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002870class ConnectionGetCipherListTests(TestCase):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002871 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002872 Tests for :py:obj:`Connection.get_cipher_list`.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002873 """
Jean-Paul Calderone54a2bc02010-09-09 17:52:38 -04002874 def test_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002875 """
Hynek Schlawackdddd1112015-09-05 21:12:30 +02002876 :py:obj:`Connection.get_cipher_list` raises :py:obj:`TypeError` if
2877 called with any arguments.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002878 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002879 connection = Connection(Context(TLSv1_METHOD), None)
2880 self.assertRaises(TypeError, connection.get_cipher_list, None)
2881
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002882 def test_result(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002883 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002884 :py:obj:`Connection.get_cipher_list` returns a :py:obj:`list` of
2885 :py:obj:`bytes` giving the names of the ciphers which might be used.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002886 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002887 connection = Connection(Context(TLSv1_METHOD), None)
2888 ciphers = connection.get_cipher_list()
2889 self.assertTrue(isinstance(ciphers, list))
2890 for cipher in ciphers:
2891 self.assertTrue(isinstance(cipher, str))
2892
2893
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002894class ConnectionSendTests(TestCase, _LoopbackMixin):
2895 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002896 Tests for :py:obj:`Connection.send`
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002897 """
2898 def test_wrong_args(self):
2899 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002900 When called with arguments other than string argument for its first
2901 parameter or more than two arguments, :py:obj:`Connection.send` raises
2902 :py:obj:`TypeError`.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002903 """
2904 connection = Connection(Context(TLSv1_METHOD), None)
Jean-Paul Calderone77fa2602011-01-05 18:23:39 -05002905 self.assertRaises(TypeError, connection.send)
2906 self.assertRaises(TypeError, connection.send, object())
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002907 self.assertRaises(TypeError, connection.send, "foo", object(), "bar")
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002908
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002909 def test_short_bytes(self):
2910 """
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002911 When passed a short byte string, :py:obj:`Connection.send` transmits
2912 all of it and returns the number of bytes sent.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002913 """
2914 server, client = self._loopback()
2915 count = server.send(b('xy'))
2916 self.assertEquals(count, 2)
2917 self.assertEquals(client.recv(2), b('xy'))
2918
Abraham Martinef063482015-03-25 14:06:24 +00002919 def test_text(self):
2920 """
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002921 When passed a text, :py:obj:`Connection.send` transmits all of it and
2922 returns the number of bytes sent. It also raises a DeprecationWarning.
Abraham Martinef063482015-03-25 14:06:24 +00002923 """
2924 server, client = self._loopback()
2925 with catch_warnings(record=True) as w:
2926 simplefilter("always")
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002927 count = server.send(b"xy".decode("ascii"))
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002928 self.assertEqual(
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002929 "{0} for buf is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002930 WARNING_TYPE_EXPECTED
2931 ),
2932 str(w[-1].message)
2933 )
2934 self.assertIs(w[-1].category, DeprecationWarning)
Abraham Martinef063482015-03-25 14:06:24 +00002935 self.assertEquals(count, 2)
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002936 self.assertEquals(client.recv(2), b"xy")
Abraham Martinef063482015-03-25 14:06:24 +00002937
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002938 @skip_if_py26
2939 def test_short_memoryview(self):
2940 """
2941 When passed a memoryview onto a small number of bytes,
2942 :py:obj:`Connection.send` transmits all of them and returns the number
2943 of bytes sent.
2944 """
2945 server, client = self._loopback()
2946 count = server.send(memoryview(b('xy')))
2947 self.assertEquals(count, 2)
2948 self.assertEquals(client.recv(2), b('xy'))
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002949
Hynek Schlawack8e94f1b2015-09-05 21:31:00 +02002950 @skip_if_py3
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002951 def test_short_buffer(self):
2952 """
2953 When passed a buffer containing a small number of bytes,
2954 :py:obj:`Connection.send` transmits all of them and returns the number
2955 of bytes sent.
2956 """
2957 server, client = self._loopback()
2958 count = server.send(buffer(b('xy')))
2959 self.assertEquals(count, 2)
2960 self.assertEquals(client.recv(2), b('xy'))
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02002961
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05002962
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002963def _make_memoryview(size):
2964 """
2965 Create a new ``memoryview`` wrapped around a ``bytearray`` of the given
2966 size.
2967 """
2968 return memoryview(bytearray(size))
2969
2970
Cory Benfield62d10332014-06-15 10:03:41 +01002971class ConnectionRecvIntoTests(TestCase, _LoopbackMixin):
2972 """
2973 Tests for :py:obj:`Connection.recv_into`
2974 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002975 def _no_length_test(self, factory):
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04002976 """
2977 Assert that when the given buffer is passed to
2978 ``Connection.recv_into``, whatever bytes are available to be received
2979 that fit into that buffer are written into that buffer.
2980 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002981 output_buffer = factory(5)
2982
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04002983 server, client = self._loopback()
2984 server.send(b('xy'))
2985
Jean-Paul Calderone320af1e2015-03-15 17:20:13 -04002986 self.assertEqual(client.recv_into(output_buffer), 2)
2987 self.assertEqual(output_buffer, bytearray(b('xy\x00\x00\x00')))
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04002988
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002989 def test_bytearray_no_length(self):
Cory Benfield62d10332014-06-15 10:03:41 +01002990 """
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04002991 :py:obj:`Connection.recv_into` can be passed a ``bytearray`` instance
2992 and data in the receive buffer is written to it.
Cory Benfield62d10332014-06-15 10:03:41 +01002993 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002994 self._no_length_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01002995
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002996 def _respects_length_test(self, factory):
Cory Benfield62d10332014-06-15 10:03:41 +01002997 """
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002998 Assert that when the given buffer is passed to ``Connection.recv_into``
2999 along with a value for ``nbytes`` that is less than the size of that
3000 buffer, only ``nbytes`` bytes are written into the buffer.
Cory Benfield62d10332014-06-15 10:03:41 +01003001 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003002 output_buffer = factory(10)
3003
Cory Benfield62d10332014-06-15 10:03:41 +01003004 server, client = self._loopback()
3005 server.send(b('abcdefghij'))
Cory Benfield62d10332014-06-15 10:03:41 +01003006
Jean-Paul Calderone320af1e2015-03-15 17:20:13 -04003007 self.assertEqual(client.recv_into(output_buffer, 5), 5)
3008 self.assertEqual(
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04003009 output_buffer, bytearray(b('abcde\x00\x00\x00\x00\x00'))
3010 )
3011
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04003012 def test_bytearray_respects_length(self):
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04003013 """
3014 When called with a ``bytearray`` instance,
3015 :py:obj:`Connection.recv_into` respects the ``nbytes`` parameter and
3016 doesn't copy in more than that number of bytes.
3017 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003018 self._respects_length_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01003019
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003020 def _doesnt_overfill_test(self, factory):
Cory Benfield62d10332014-06-15 10:03:41 +01003021 """
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04003022 Assert that if there are more bytes available to be read from the
3023 receive buffer than would fit into the buffer passed to
3024 :py:obj:`Connection.recv_into`, only as many as fit are written into
3025 it.
Cory Benfield62d10332014-06-15 10:03:41 +01003026 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003027 output_buffer = factory(5)
3028
Cory Benfield62d10332014-06-15 10:03:41 +01003029 server, client = self._loopback()
3030 server.send(b('abcdefghij'))
Cory Benfield62d10332014-06-15 10:03:41 +01003031
Jean-Paul Calderone320af1e2015-03-15 17:20:13 -04003032 self.assertEqual(client.recv_into(output_buffer), 5)
3033 self.assertEqual(output_buffer, bytearray(b('abcde')))
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04003034 rest = client.recv(5)
3035 self.assertEqual(b('fghij'), rest)
3036
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04003037 def test_bytearray_doesnt_overfill(self):
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04003038 """
3039 When called with a ``bytearray`` instance,
3040 :py:obj:`Connection.recv_into` respects the size of the array and
3041 doesn't write more bytes into it than will fit.
3042 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003043 self._doesnt_overfill_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01003044
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003045 def _really_doesnt_overfill_test(self, factory):
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003046 """
3047 Assert that if the value given by ``nbytes`` is greater than the actual
3048 size of the output buffer passed to :py:obj:`Connection.recv_into`, the
3049 behavior is as if no value was given for ``nbytes`` at all.
3050 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003051 output_buffer = factory(5)
3052
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003053 server, client = self._loopback()
3054 server.send(b('abcdefghij'))
3055
3056 self.assertEqual(client.recv_into(output_buffer, 50), 5)
3057 self.assertEqual(output_buffer, bytearray(b('abcde')))
3058 rest = client.recv(5)
3059 self.assertEqual(b('fghij'), rest)
3060
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04003061 def test_bytearray_really_doesnt_overfill(self):
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003062 """
3063 When called with a ``bytearray`` instance and an ``nbytes`` value that
3064 is too large, :py:obj:`Connection.recv_into` respects the size of the
3065 array and not the ``nbytes`` value and doesn't write more bytes into
3066 the buffer than will fit.
3067 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003068 self._doesnt_overfill_test(bytearray)
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003069
Maximilian Hils1d95dea2015-08-17 19:27:20 +02003070 def test_peek(self):
3071
3072 server, client = self._loopback()
3073 server.send(b('xy'))
3074
3075 for _ in range(2):
3076 output_buffer = bytearray(5)
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003077 self.assertEqual(
3078 client.recv_into(output_buffer, flags=MSG_PEEK), 2)
Maximilian Hils1d95dea2015-08-17 19:27:20 +02003079 self.assertEqual(output_buffer, bytearray(b('xy\x00\x00\x00')))
3080
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003081 @skip_if_py26
3082 def test_memoryview_no_length(self):
3083 """
3084 :py:obj:`Connection.recv_into` can be passed a ``memoryview``
3085 instance and data in the receive buffer is written to it.
3086 """
3087 self._no_length_test(_make_memoryview)
Maximilian Hils1d95dea2015-08-17 19:27:20 +02003088
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003089 @skip_if_py26
3090 def test_memoryview_respects_length(self):
3091 """
3092 When called with a ``memoryview`` instance,
3093 :py:obj:`Connection.recv_into` respects the ``nbytes`` parameter
3094 and doesn't copy more than that number of bytes in.
3095 """
3096 self._respects_length_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01003097
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003098 @skip_if_py26
3099 def test_memoryview_doesnt_overfill(self):
3100 """
3101 When called with a ``memoryview`` instance,
3102 :py:obj:`Connection.recv_into` respects the size of the array and
3103 doesn't write more bytes into it than will fit.
3104 """
3105 self._doesnt_overfill_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01003106
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003107 @skip_if_py26
3108 def test_memoryview_really_doesnt_overfill(self):
3109 """
3110 When called with a ``memoryview`` instance and an ``nbytes`` value
3111 that is too large, :py:obj:`Connection.recv_into` respects the size
3112 of the array and not the ``nbytes`` value and doesn't write more
3113 bytes into the buffer than will fit.
3114 """
3115 self._doesnt_overfill_test(_make_memoryview)
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003116
Cory Benfield62d10332014-06-15 10:03:41 +01003117
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003118class ConnectionSendallTests(TestCase, _LoopbackMixin):
3119 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003120 Tests for :py:obj:`Connection.sendall`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003121 """
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003122 def test_wrong_args(self):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003123 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003124 When called with arguments other than a string argument for its first
3125 parameter or with more than two arguments, :py:obj:`Connection.sendall`
3126 raises :py:obj:`TypeError`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003127 """
3128 connection = Connection(Context(TLSv1_METHOD), None)
3129 self.assertRaises(TypeError, connection.sendall)
3130 self.assertRaises(TypeError, connection.sendall, object())
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003131 self.assertRaises(
3132 TypeError, connection.sendall, "foo", object(), "bar")
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003133
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003134 def test_short(self):
3135 """
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003136 :py:obj:`Connection.sendall` transmits all of the bytes in the string
3137 passed to it.
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003138 """
3139 server, client = self._loopback()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04003140 server.sendall(b('x'))
3141 self.assertEquals(client.recv(1), b('x'))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003142
Abraham Martinef063482015-03-25 14:06:24 +00003143 def test_text(self):
3144 """
Jean-Paul Calderone93477422015-04-13 20:38:57 -04003145 :py:obj:`Connection.sendall` transmits all the content in the string
3146 passed to it raising a DeprecationWarning in case of this being a text.
Abraham Martinef063482015-03-25 14:06:24 +00003147 """
3148 server, client = self._loopback()
3149 with catch_warnings(record=True) as w:
3150 simplefilter("always")
Jean-Paul Calderone8dc37a12015-03-29 08:16:52 -04003151 server.sendall(b"x".decode("ascii"))
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04003152 self.assertEqual(
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04003153 "{0} for buf is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04003154 WARNING_TYPE_EXPECTED
3155 ),
3156 str(w[-1].message)
3157 )
3158 self.assertIs(w[-1].category, DeprecationWarning)
3159 self.assertEquals(client.recv(1), b"x")
Abraham Martinef063482015-03-25 14:06:24 +00003160
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003161 @skip_if_py26
3162 def test_short_memoryview(self):
3163 """
3164 When passed a memoryview onto a small number of bytes,
3165 :py:obj:`Connection.sendall` transmits all of them.
3166 """
3167 server, client = self._loopback()
3168 server.sendall(memoryview(b('x')))
3169 self.assertEquals(client.recv(1), b('x'))
Abraham Martinef063482015-03-25 14:06:24 +00003170
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003171 @skip_if_py3
3172 def test_short_buffers(self):
3173 """
3174 When passed a buffer containing a small number of bytes,
3175 :py:obj:`Connection.sendall` transmits all of them.
3176 """
3177 server, client = self._loopback()
3178 server.sendall(buffer(b('x')))
3179 self.assertEquals(client.recv(1), b('x'))
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02003180
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003181 def test_long(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003182 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003183 :py:obj:`Connection.sendall` transmits all of the bytes in the string
3184 passed to it even if this requires multiple calls of an underlying
3185 write function.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003186 """
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003187 server, client = self._loopback()
Jean-Paul Calderone6241c702010-09-16 19:59:24 -04003188 # Should be enough, underlying SSL_write should only do 16k at a time.
Hynek Schlawack35618382015-09-05 21:54:25 +02003189 # On Windows, after 32k of bytes the write will block (forever
3190 # - because no one is yet reading).
Jean-Paul Calderone9e4c1352010-09-19 09:34:43 -04003191 message = b('x') * (1024 * 32 - 1) + b('y')
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003192 server.sendall(message)
3193 accum = []
3194 received = 0
3195 while received < len(message):
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04003196 data = client.recv(1024)
3197 accum.append(data)
3198 received += len(data)
Jean-Paul Calderonef4047852010-09-19 09:45:57 -04003199 self.assertEquals(message, b('').join(accum))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003200
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003201 def test_closed(self):
3202 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003203 If the underlying socket is closed, :py:obj:`Connection.sendall`
3204 propagates the write error from the low level write call.
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003205 """
3206 server, client = self._loopback()
Jean-Paul Calderone05d43e82010-09-24 18:01:36 -04003207 server.sock_shutdown(2)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003208 exc = self.assertRaises(SysCallError, server.sendall, b"hello, world")
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +02003209 if platform == "win32":
3210 self.assertEqual(exc.args[0], ESHUTDOWN)
3211 else:
3212 self.assertEqual(exc.args[0], EPIPE)
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003213
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003214
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003215class ConnectionRenegotiateTests(TestCase, _LoopbackMixin):
3216 """
3217 Tests for SSL renegotiation APIs.
3218 """
3219 def test_renegotiate_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003220 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003221 :py:obj:`Connection.renegotiate` raises :py:obj:`TypeError` if called
3222 with any arguments.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003223 """
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003224 connection = Connection(Context(TLSv1_METHOD), None)
3225 self.assertRaises(TypeError, connection.renegotiate, None)
3226
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003227 def test_total_renegotiations_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003228 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003229 :py:obj:`Connection.total_renegotiations` raises :py:obj:`TypeError` if
3230 called with any arguments.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003231 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003232 connection = Connection(Context(TLSv1_METHOD), None)
3233 self.assertRaises(TypeError, connection.total_renegotiations, None)
3234
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003235 def test_total_renegotiations(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003236 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003237 :py:obj:`Connection.total_renegotiations` returns :py:obj:`0` before
3238 any renegotiations have happened.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003239 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003240 connection = Connection(Context(TLSv1_METHOD), None)
3241 self.assertEquals(connection.total_renegotiations(), 0)
3242
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003243 def test_renegotiate(self):
3244 """
3245 Go through a complete renegotiation cycle.
3246 """
3247 server, client = self._loopback()
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003248
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003249 server.send(b"hello world")
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003250
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003251 assert b"hello world" == client.recv(len(b"hello world"))
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003252
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003253 assert 0 == server.total_renegotiations()
3254 assert False is server.renegotiate_pending()
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003255
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003256 assert True is server.renegotiate()
3257
3258 assert True is server.renegotiate_pending()
3259
3260 server.setblocking(False)
3261 client.setblocking(False)
3262
3263 client.do_handshake()
3264 server.do_handshake()
3265
3266 assert 1 == server.total_renegotiations()
3267 while False is server.renegotiate_pending():
3268 pass
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003269
3270
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003271class ErrorTests(TestCase):
3272 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003273 Unit tests for :py:obj:`OpenSSL.SSL.Error`.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003274 """
3275 def test_type(self):
3276 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003277 :py:obj:`Error` is an exception type.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003278 """
3279 self.assertTrue(issubclass(Error, Exception))
Rick Deane15b1472009-07-09 15:53:42 -05003280 self.assertEqual(Error.__name__, 'Error')
Rick Deane15b1472009-07-09 15:53:42 -05003281
3282
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003283class ConstantsTests(TestCase):
3284 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003285 Tests for the values of constants exposed in :py:obj:`OpenSSL.SSL`.
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003286
3287 These are values defined by OpenSSL intended only to be used as flags to
3288 OpenSSL APIs. The only assertions it seems can be made about them is
3289 their values.
3290 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003291 @pytest.mark.skipif(
3292 OP_NO_QUERY_MTU is None,
3293 reason="OP_NO_QUERY_MTU unavailable - OpenSSL version may be too old"
3294 )
3295 def test_op_no_query_mtu(self):
3296 """
3297 The value of :py:obj:`OpenSSL.SSL.OP_NO_QUERY_MTU` is 0x1000, the value
3298 of :py:const:`SSL_OP_NO_QUERY_MTU` defined by :file:`openssl/ssl.h`.
3299 """
3300 self.assertEqual(OP_NO_QUERY_MTU, 0x1000)
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003301
Hynek Schlawack35618382015-09-05 21:54:25 +02003302 @pytest.mark.skipif(
3303 OP_COOKIE_EXCHANGE is None,
3304 reason="OP_COOKIE_EXCHANGE unavailable - "
3305 "OpenSSL version may be too old"
3306 )
3307 def test_op_cookie_exchange(self):
3308 """
3309 The value of :py:obj:`OpenSSL.SSL.OP_COOKIE_EXCHANGE` is 0x2000, the
3310 value of :py:const:`SSL_OP_COOKIE_EXCHANGE` defined by
3311 :file:`openssl/ssl.h`.
3312 """
3313 self.assertEqual(OP_COOKIE_EXCHANGE, 0x2000)
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003314
Hynek Schlawack35618382015-09-05 21:54:25 +02003315 @pytest.mark.skipif(
3316 OP_NO_TICKET is None,
3317 reason="OP_NO_TICKET unavailable - OpenSSL version may be too old"
3318 )
3319 def test_op_no_ticket(self):
3320 """
3321 The value of :py:obj:`OpenSSL.SSL.OP_NO_TICKET` is 0x4000, the value of
3322 :py:const:`SSL_OP_NO_TICKET` defined by :file:`openssl/ssl.h`.
3323 """
3324 self.assertEqual(OP_NO_TICKET, 0x4000)
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003325
Hynek Schlawack35618382015-09-05 21:54:25 +02003326 @pytest.mark.skipif(
3327 OP_NO_COMPRESSION is None,
3328 reason="OP_NO_COMPRESSION unavailable - OpenSSL version may be too old"
3329 )
3330 def test_op_no_compression(self):
3331 """
3332 The value of :py:obj:`OpenSSL.SSL.OP_NO_COMPRESSION` is 0x20000, the
3333 value of :py:const:`SSL_OP_NO_COMPRESSION` defined by
3334 :file:`openssl/ssl.h`.
3335 """
3336 self.assertEqual(OP_NO_COMPRESSION, 0x20000)
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04003337
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003338 def test_sess_cache_off(self):
3339 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003340 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_OFF` 0x0, the value of
3341 :py:obj:`SSL_SESS_CACHE_OFF` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003342 """
3343 self.assertEqual(0x0, SESS_CACHE_OFF)
3344
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003345 def test_sess_cache_client(self):
3346 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003347 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_CLIENT` 0x1, the value of
3348 :py:obj:`SSL_SESS_CACHE_CLIENT` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003349 """
3350 self.assertEqual(0x1, SESS_CACHE_CLIENT)
3351
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003352 def test_sess_cache_server(self):
3353 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003354 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_SERVER` 0x2, the value of
3355 :py:obj:`SSL_SESS_CACHE_SERVER` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003356 """
3357 self.assertEqual(0x2, SESS_CACHE_SERVER)
3358
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003359 def test_sess_cache_both(self):
3360 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003361 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_BOTH` 0x3, the value of
3362 :py:obj:`SSL_SESS_CACHE_BOTH` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003363 """
3364 self.assertEqual(0x3, SESS_CACHE_BOTH)
3365
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003366 def test_sess_cache_no_auto_clear(self):
3367 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003368 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_AUTO_CLEAR` 0x80, the
3369 value of :py:obj:`SSL_SESS_CACHE_NO_AUTO_CLEAR` defined by
3370 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003371 """
3372 self.assertEqual(0x80, SESS_CACHE_NO_AUTO_CLEAR)
3373
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003374 def test_sess_cache_no_internal_lookup(self):
3375 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003376 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_LOOKUP` 0x100,
3377 the value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL_LOOKUP` defined by
3378 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003379 """
3380 self.assertEqual(0x100, SESS_CACHE_NO_INTERNAL_LOOKUP)
3381
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003382 def test_sess_cache_no_internal_store(self):
3383 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003384 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_STORE` 0x200,
3385 the value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL_STORE` defined by
3386 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003387 """
3388 self.assertEqual(0x200, SESS_CACHE_NO_INTERNAL_STORE)
3389
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003390 def test_sess_cache_no_internal(self):
3391 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003392 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL` 0x300, the
3393 value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL` defined by
3394 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003395 """
3396 self.assertEqual(0x300, SESS_CACHE_NO_INTERNAL)
3397
3398
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003399class MemoryBIOTests(TestCase, _LoopbackMixin):
Rick Deanb71c0d22009-04-01 14:09:23 -05003400 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003401 Tests for :py:obj:`OpenSSL.SSL.Connection` using a memory BIO.
Rick Deanb71c0d22009-04-01 14:09:23 -05003402 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003403 def _server(self, sock):
3404 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003405 Create a new server-side SSL :py:obj:`Connection` object wrapped around
3406 :py:obj:`sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003407 """
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003408 # Create the server side Connection. This is mostly setup boilerplate
3409 # - use TLSv1, use a particular certificate, etc.
3410 server_ctx = Context(TLSv1_METHOD)
Alex Gaynor43307782015-09-04 09:05:45 -04003411 server_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE)
Hynek Schlawack35618382015-09-05 21:54:25 +02003412 server_ctx.set_verify(
3413 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT | VERIFY_CLIENT_ONCE,
3414 verify_cb
3415 )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003416 server_store = server_ctx.get_cert_store()
Hynek Schlawack35618382015-09-05 21:54:25 +02003417 server_ctx.use_privatekey(
3418 load_privatekey(FILETYPE_PEM, server_key_pem))
3419 server_ctx.use_certificate(
3420 load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003421 server_ctx.check_privatekey()
3422 server_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Hynek Schlawack35618382015-09-05 21:54:25 +02003423 # Here the Connection is actually created. If None is passed as the
3424 # 2nd parameter, it indicates a memory BIO should be created.
Rick Deanb1ccd562009-07-09 23:52:39 -05003425 server_conn = Connection(server_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003426 server_conn.set_accept_state()
3427 return server_conn
3428
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003429 def _client(self, sock):
3430 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003431 Create a new client-side SSL :py:obj:`Connection` object wrapped around
3432 :py:obj:`sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003433 """
3434 # Now create the client side Connection. Similar boilerplate to the
3435 # above.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003436 client_ctx = Context(TLSv1_METHOD)
Alex Gaynor43307782015-09-04 09:05:45 -04003437 client_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE)
Hynek Schlawack35618382015-09-05 21:54:25 +02003438 client_ctx.set_verify(
3439 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT | VERIFY_CLIENT_ONCE,
3440 verify_cb
3441 )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003442 client_store = client_ctx.get_cert_store()
Hynek Schlawack35618382015-09-05 21:54:25 +02003443 client_ctx.use_privatekey(
3444 load_privatekey(FILETYPE_PEM, client_key_pem))
3445 client_ctx.use_certificate(
3446 load_certificate(FILETYPE_PEM, client_cert_pem))
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003447 client_ctx.check_privatekey()
3448 client_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05003449 client_conn = Connection(client_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003450 client_conn.set_connect_state()
3451 return client_conn
3452
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003453 def test_memoryConnect(self):
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003454 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003455 Two :py:obj:`Connection`s which use memory BIOs can be manually
3456 connected by reading from the output of each and writing those bytes to
3457 the input of the other and in this way establish a connection and
3458 exchange application-level bytes with each other.
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003459 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003460 server_conn = self._server(None)
3461 client_conn = self._client(None)
Rick Deanb71c0d22009-04-01 14:09:23 -05003462
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003463 # There should be no key or nonces yet.
3464 self.assertIdentical(server_conn.master_key(), None)
3465 self.assertIdentical(server_conn.client_random(), None)
3466 self.assertIdentical(server_conn.server_random(), None)
Rick Deanb71c0d22009-04-01 14:09:23 -05003467
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003468 # First, the handshake needs to happen. We'll deliver bytes back and
3469 # forth between the client and server until neither of them feels like
3470 # speaking any more.
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003471 self.assertIdentical(
3472 self._interactInMemory(client_conn, server_conn), None)
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003473
3474 # Now that the handshake is done, there should be a key and nonces.
3475 self.assertNotIdentical(server_conn.master_key(), None)
3476 self.assertNotIdentical(server_conn.client_random(), None)
3477 self.assertNotIdentical(server_conn.server_random(), None)
Hynek Schlawack35618382015-09-05 21:54:25 +02003478 self.assertEquals(
3479 server_conn.client_random(), client_conn.client_random())
3480 self.assertEquals(
3481 server_conn.server_random(), client_conn.server_random())
3482 self.assertNotEquals(
3483 server_conn.client_random(), server_conn.server_random())
3484 self.assertNotEquals(
3485 client_conn.client_random(), client_conn.server_random())
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003486
3487 # Here are the bytes we'll try to send.
Jean-Paul Calderonea441fdc2010-08-22 21:33:57 -04003488 important_message = b('One if by land, two if by sea.')
Rick Deanb71c0d22009-04-01 14:09:23 -05003489
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003490 server_conn.write(important_message)
3491 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003492 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003493 (client_conn, important_message))
3494
3495 client_conn.write(important_message[::-1])
3496 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003497 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003498 (server_conn, important_message[::-1]))
Rick Deanb71c0d22009-04-01 14:09:23 -05003499
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003500 def test_socketConnect(self):
Rick Deanb1ccd562009-07-09 23:52:39 -05003501 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003502 Just like :py:obj:`test_memoryConnect` but with an actual socket.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003503
Hynek Schlawack35618382015-09-05 21:54:25 +02003504 This is primarily to rule out the memory BIO code as the source of any
3505 problems encountered while passing data over a :py:obj:`Connection` (if
3506 this test fails, there must be a problem outside the memory BIO code,
3507 as no memory BIO is involved here). Even though this isn't a memory
3508 BIO test, it's convenient to have it here.
Rick Deanb1ccd562009-07-09 23:52:39 -05003509 """
Jean-Paul Calderone06c7cc92010-09-24 23:52:00 -04003510 server_conn, client_conn = self._loopback()
Rick Deanb1ccd562009-07-09 23:52:39 -05003511
Jean-Paul Calderonea441fdc2010-08-22 21:33:57 -04003512 important_message = b("Help me Obi Wan Kenobi, you're my only hope.")
Rick Deanb1ccd562009-07-09 23:52:39 -05003513 client_conn.send(important_message)
3514 msg = server_conn.recv(1024)
3515 self.assertEqual(msg, important_message)
3516
3517 # Again in the other direction, just for fun.
3518 important_message = important_message[::-1]
3519 server_conn.send(important_message)
3520 msg = client_conn.recv(1024)
3521 self.assertEqual(msg, important_message)
3522
Jean-Paul Calderonefc4ed0f2009-04-27 11:51:27 -04003523 def test_socketOverridesMemory(self):
Rick Deanb71c0d22009-04-01 14:09:23 -05003524 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003525 Test that :py:obj:`OpenSSL.SSL.bio_read` and
3526 :py:obj:`OpenSSL.SSL.bio_write` don't work on
3527 :py:obj:`OpenSSL.SSL.Connection`() that use sockets.
Rick Deanb71c0d22009-04-01 14:09:23 -05003528 """
3529 context = Context(SSLv3_METHOD)
3530 client = socket()
3531 clientSSL = Connection(context, client)
Alex Gaynor43307782015-09-04 09:05:45 -04003532 self.assertRaises(TypeError, clientSSL.bio_read, 100)
3533 self.assertRaises(TypeError, clientSSL.bio_write, "foo")
Alex Gaynor7e8b61e2015-09-04 13:13:05 -04003534 self.assertRaises(TypeError, clientSSL.bio_shutdown)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003535
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003536 def test_outgoingOverflow(self):
3537 """
3538 If more bytes than can be written to the memory BIO are passed to
Hynek Schlawack35618382015-09-05 21:54:25 +02003539 :py:obj:`Connection.send` at once, the number of bytes which were
3540 written is returned and that many bytes from the beginning of the input
3541 can be read from the other end of the connection.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003542 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003543 server = self._server(None)
3544 client = self._client(None)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003545
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003546 self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003547
3548 size = 2 ** 15
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003549 sent = client.send(b"x" * size)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003550 # Sanity check. We're trying to test what happens when the entire
3551 # input can't be sent. If the entire input was sent, this test is
3552 # meaningless.
3553 self.assertTrue(sent < size)
3554
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003555 receiver, received = self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003556 self.assertIdentical(receiver, server)
3557
3558 # We can rely on all of these bytes being received at once because
3559 # _loopback passes 2 ** 16 to recv - more than 2 ** 15.
3560 self.assertEquals(len(received), sent)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003561
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003562 def test_shutdown(self):
3563 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003564 :py:obj:`Connection.bio_shutdown` signals the end of the data stream
3565 from which the :py:obj:`Connection` reads.
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003566 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003567 server = self._server(None)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003568 server.bio_shutdown()
3569 e = self.assertRaises(Error, server.recv, 1024)
3570 # We don't want WantReadError or ZeroReturnError or anything - it's a
3571 # handshake failure.
3572 self.assertEquals(e.__class__, Error)
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003573
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003574 def test_unexpectedEndOfFile(self):
3575 """
3576 If the connection is lost before an orderly SSL shutdown occurs,
3577 :py:obj:`OpenSSL.SSL.SysCallError` is raised with a message of
3578 "Unexpected EOF".
3579 """
3580 server_conn, client_conn = self._loopback()
3581 client_conn.sock_shutdown(SHUT_RDWR)
3582 exc = self.assertRaises(SysCallError, server_conn.recv, 1024)
3583 self.assertEqual(exc.args, (-1, "Unexpected EOF"))
3584
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003585 def _check_client_ca_list(self, func):
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003586 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003587 Verify the return value of the :py:obj:`get_client_ca_list` method for
3588 server and client connections.
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003589
Jonathan Ballet78b92a22011-07-16 08:07:26 +09003590 :param func: A function which will be called with the server context
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003591 before the client and server are connected to each other. This
3592 function should specify a list of CAs for the server to send to the
3593 client and return that same list. The list will be used to verify
Hynek Schlawack35618382015-09-05 21:54:25 +02003594 that :py:obj:`get_client_ca_list` returns the proper value at
3595 various times.
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003596 """
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003597 server = self._server(None)
3598 client = self._client(None)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003599 self.assertEqual(client.get_client_ca_list(), [])
3600 self.assertEqual(server.get_client_ca_list(), [])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003601 ctx = server.get_context()
3602 expected = func(ctx)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003603 self.assertEqual(client.get_client_ca_list(), [])
3604 self.assertEqual(server.get_client_ca_list(), expected)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003605 self._interactInMemory(client, server)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003606 self.assertEqual(client.get_client_ca_list(), expected)
3607 self.assertEqual(server.get_client_ca_list(), expected)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003608
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003609 def test_set_client_ca_list_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003610 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003611 :py:obj:`Context.set_client_ca_list` raises a :py:obj:`TypeError` if
3612 called with a non-list or a list that contains objects other than
3613 X509Names.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003614 """
3615 ctx = Context(TLSv1_METHOD)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003616 self.assertRaises(TypeError, ctx.set_client_ca_list, "spam")
3617 self.assertRaises(TypeError, ctx.set_client_ca_list, ["spam"])
3618 self.assertIdentical(ctx.set_client_ca_list([]), None)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003619
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003620 def test_set_empty_ca_list(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003621 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003622 If passed an empty list, :py:obj:`Context.set_client_ca_list`
3623 configures the context to send no CA names to the client and, on both
3624 the server and client sides, :py:obj:`Connection.get_client_ca_list`
3625 returns an empty list after the connection is set up.
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003626 """
3627 def no_ca(ctx):
3628 ctx.set_client_ca_list([])
3629 return []
3630 self._check_client_ca_list(no_ca)
3631
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003632 def test_set_one_ca_list(self):
3633 """
3634 If passed a list containing a single X509Name,
Hynek Schlawack35618382015-09-05 21:54:25 +02003635 :py:obj:`Context.set_client_ca_list` configures the context to send
3636 that CA name to the client and, on both the server and client sides,
Jonathan Ballet648875f2011-07-16 14:14:58 +09003637 :py:obj:`Connection.get_client_ca_list` returns a list containing that
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003638 X509Name after the connection is set up.
3639 """
3640 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3641 cadesc = cacert.get_subject()
Hynek Schlawack35618382015-09-05 21:54:25 +02003642
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003643 def single_ca(ctx):
3644 ctx.set_client_ca_list([cadesc])
3645 return [cadesc]
3646 self._check_client_ca_list(single_ca)
3647
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003648 def test_set_multiple_ca_list(self):
3649 """
3650 If passed a list containing multiple X509Name objects,
Hynek Schlawack35618382015-09-05 21:54:25 +02003651 :py:obj:`Context.set_client_ca_list` configures the context to send
3652 those CA names to the client and, on both the server and client sides,
Jonathan Ballet648875f2011-07-16 14:14:58 +09003653 :py:obj:`Connection.get_client_ca_list` returns a list containing those
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003654 X509Names after the connection is set up.
3655 """
3656 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3657 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3658
3659 sedesc = secert.get_subject()
3660 cldesc = clcert.get_subject()
3661
3662 def multiple_ca(ctx):
3663 L = [sedesc, cldesc]
3664 ctx.set_client_ca_list(L)
3665 return L
3666 self._check_client_ca_list(multiple_ca)
3667
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003668 def test_reset_ca_list(self):
3669 """
3670 If called multiple times, only the X509Names passed to the final call
Hynek Schlawack35618382015-09-05 21:54:25 +02003671 of :py:obj:`Context.set_client_ca_list` are used to configure the CA
3672 names sent to the client.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003673 """
3674 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3675 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3676 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3677
3678 cadesc = cacert.get_subject()
3679 sedesc = secert.get_subject()
3680 cldesc = clcert.get_subject()
3681
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003682 def changed_ca(ctx):
3683 ctx.set_client_ca_list([sedesc, cldesc])
3684 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003685 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003686 self._check_client_ca_list(changed_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003687
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003688 def test_mutated_ca_list(self):
3689 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003690 If the list passed to :py:obj:`Context.set_client_ca_list` is mutated
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003691 afterwards, this does not affect the list of CA names sent to the
3692 client.
3693 """
3694 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3695 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3696
3697 cadesc = cacert.get_subject()
3698 sedesc = secert.get_subject()
3699
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003700 def mutated_ca(ctx):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003701 L = [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003702 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003703 L.append(sedesc)
3704 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003705 self._check_client_ca_list(mutated_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003706
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003707 def test_add_client_ca_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003708 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003709 :py:obj:`Context.add_client_ca` raises :py:obj:`TypeError` if called
3710 with a non-X509 object or with a number of arguments other than one.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003711 """
3712 ctx = Context(TLSv1_METHOD)
3713 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003714 self.assertRaises(TypeError, ctx.add_client_ca)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003715 self.assertRaises(TypeError, ctx.add_client_ca, "spam")
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003716 self.assertRaises(TypeError, ctx.add_client_ca, cacert, cacert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003717
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003718 def test_one_add_client_ca(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003719 """
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003720 A certificate's subject can be added as a CA to be sent to the client
Jonathan Ballet648875f2011-07-16 14:14:58 +09003721 with :py:obj:`Context.add_client_ca`.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003722 """
3723 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3724 cadesc = cacert.get_subject()
Hynek Schlawack35618382015-09-05 21:54:25 +02003725
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003726 def single_ca(ctx):
3727 ctx.add_client_ca(cacert)
3728 return [cadesc]
3729 self._check_client_ca_list(single_ca)
3730
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003731 def test_multiple_add_client_ca(self):
3732 """
3733 Multiple CA names can be sent to the client by calling
Jonathan Ballet648875f2011-07-16 14:14:58 +09003734 :py:obj:`Context.add_client_ca` with multiple X509 objects.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003735 """
3736 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3737 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3738
3739 cadesc = cacert.get_subject()
3740 sedesc = secert.get_subject()
3741
3742 def multiple_ca(ctx):
3743 ctx.add_client_ca(cacert)
3744 ctx.add_client_ca(secert)
3745 return [cadesc, sedesc]
3746 self._check_client_ca_list(multiple_ca)
3747
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003748 def test_set_and_add_client_ca(self):
3749 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003750 A call to :py:obj:`Context.set_client_ca_list` followed by a call to
Hynek Schlawack35618382015-09-05 21:54:25 +02003751 :py:obj:`Context.add_client_ca` results in using the CA names from the
3752 first call and the CA name from the second call.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003753 """
3754 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3755 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3756 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3757
3758 cadesc = cacert.get_subject()
3759 sedesc = secert.get_subject()
3760 cldesc = clcert.get_subject()
3761
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003762 def mixed_set_add_ca(ctx):
3763 ctx.set_client_ca_list([cadesc, sedesc])
3764 ctx.add_client_ca(clcert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003765 return [cadesc, sedesc, cldesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003766 self._check_client_ca_list(mixed_set_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003767
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003768 def test_set_after_add_client_ca(self):
3769 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003770 A call to :py:obj:`Context.set_client_ca_list` after a call to
Hynek Schlawack35618382015-09-05 21:54:25 +02003771 :py:obj:`Context.add_client_ca` replaces the CA name specified by the
3772 former call with the names specified by the latter call.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003773 """
3774 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3775 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3776 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3777
3778 cadesc = cacert.get_subject()
3779 sedesc = secert.get_subject()
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003780
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003781 def set_replaces_add_ca(ctx):
3782 ctx.add_client_ca(clcert)
3783 ctx.set_client_ca_list([cadesc])
3784 ctx.add_client_ca(secert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003785 return [cadesc, sedesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003786 self._check_client_ca_list(set_replaces_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003787
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003788
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003789class ConnectionBIOTests(TestCase):
3790 """
3791 Tests for :py:obj:`Connection.bio_read` and :py:obj:`Connection.bio_write`.
3792 """
3793 def test_wantReadError(self):
3794 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003795 :py:obj:`Connection.bio_read` raises
3796 :py:obj:`OpenSSL.SSL.WantReadError` if there are no bytes available to
3797 be read from the BIO.
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003798 """
3799 ctx = Context(TLSv1_METHOD)
3800 conn = Connection(ctx, None)
3801 self.assertRaises(WantReadError, conn.bio_read, 1024)
3802
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003803 def test_buffer_size(self):
3804 """
3805 :py:obj:`Connection.bio_read` accepts an integer giving the maximum
3806 number of bytes to read and return.
3807 """
3808 ctx = Context(TLSv1_METHOD)
3809 conn = Connection(ctx, None)
3810 conn.set_connect_state()
3811 try:
3812 conn.do_handshake()
3813 except WantReadError:
3814 pass
3815 data = conn.bio_read(2)
3816 self.assertEqual(2, len(data))
3817
Hynek Schlawack35618382015-09-05 21:54:25 +02003818 @skip_if_py3
3819 def test_buffer_size_long(self):
3820 """
3821 On Python 2 :py:obj:`Connection.bio_read` accepts values of type
3822 :py:obj:`long` as well as :py:obj:`int`.
3823 """
3824 ctx = Context(TLSv1_METHOD)
3825 conn = Connection(ctx, None)
3826 conn.set_connect_state()
3827 try:
3828 conn.do_handshake()
3829 except WantReadError:
3830 pass
3831 data = conn.bio_read(long(2))
3832 self.assertEqual(2, len(data))
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003833
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003834
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003835class InfoConstantTests(TestCase):
3836 """
3837 Tests for assorted constants exposed for use in info callbacks.
3838 """
3839 def test_integers(self):
3840 """
3841 All of the info constants are integers.
3842
3843 This is a very weak test. It would be nice to have one that actually
3844 verifies that as certain info events happen, the value passed to the
3845 info callback matches up with the constant exposed by OpenSSL.SSL.
3846 """
3847 for const in [
3848 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK, SSL_ST_INIT,
3849 SSL_ST_BEFORE, SSL_ST_OK, SSL_ST_RENEGOTIATE,
3850 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
3851 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
3852 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
Hynek Schlawack35618382015-09-05 21:54:25 +02003853 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE
3854 ]:
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003855 self.assertTrue(isinstance(const, int))
3856
Ziga Seilnacht44611bf2009-08-31 20:49:30 +02003857
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003858if __name__ == '__main__':
3859 main()