blob: 9f228739cb0824cad440dd5b1b3c71c0be204806 [file] [log] [blame]
Jean-Paul Calderone8671c852011-03-02 19:26:20 -05001# Copyright (C) Jean-Paul Calderone
2# See LICENSE for details.
Jean-Paul Calderone8b63d452008-03-21 18:31:12 -04003
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -04004"""
Hynek Schlawackf90e3682016-03-11 11:21:13 +01005Unit tests for :mod:`OpenSSL.SSL`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -04006"""
7
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01008import datetime
9import uuid
10
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -050011from gc import collect, get_referrers
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +020012from errno import ECONNREFUSED, EINPROGRESS, EWOULDBLOCK, EPIPE, ESHUTDOWN
Hynek Schlawackf8979a52015-09-05 21:25:25 +020013from sys import platform, getfilesystemencoding, version_info
Maximilian Hils1d95dea2015-08-17 19:27:20 +020014from socket import MSG_PEEK, SHUT_RDWR, error, socket
Jean-Paul Calderonea65cf6c2009-07-19 10:26:52 -040015from os import makedirs
Jean-Paul Calderone1461c492013-10-03 16:05:00 -040016from os.path import join
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -040017from weakref import ref
Abraham Martinef063482015-03-25 14:06:24 +000018from warnings import catch_warnings, simplefilter
Jean-Paul Calderone460cc1f2009-03-07 11:31:12 -050019
Hynek Schlawack734d3022015-09-05 19:19:32 +020020import pytest
21
Hynek Schlawackf90e3682016-03-11 11:21:13 +010022from six import PY3, text_type
Jean-Paul Calderonec76c61c2014-01-18 13:21:52 -050023
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +010024from cryptography import x509
25from cryptography.hazmat.backends import default_backend
26from cryptography.hazmat.primitives import hashes
27from cryptography.hazmat.primitives import serialization
28from cryptography.hazmat.primitives.asymmetric import rsa
29from cryptography.x509.oid import NameOID
30
31
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040032from OpenSSL.crypto import TYPE_RSA, FILETYPE_PEM
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -080033from OpenSSL.crypto import PKey, X509, X509Extension, X509Store
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040034from OpenSSL.crypto import dump_privatekey, load_privatekey
35from OpenSSL.crypto import dump_certificate, load_certificate
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -040036from OpenSSL.crypto import get_elliptic_curves
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040037
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -040038from OpenSSL.SSL import OPENSSL_VERSION_NUMBER, SSLEAY_VERSION, SSLEAY_CFLAGS
39from OpenSSL.SSL import SSLEAY_PLATFORM, SSLEAY_DIR, SSLEAY_BUILT_ON
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -040040from OpenSSL.SSL import SENT_SHUTDOWN, RECEIVED_SHUTDOWN
Jean-Paul Calderone1461c492013-10-03 16:05:00 -040041from OpenSSL.SSL import (
42 SSLv2_METHOD, SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD,
43 TLSv1_1_METHOD, TLSv1_2_METHOD)
44from OpenSSL.SSL import OP_SINGLE_DH_USE, OP_NO_SSLv2, OP_NO_SSLv3
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040045from OpenSSL.SSL import (
46 VERIFY_PEER, VERIFY_FAIL_IF_NO_PEER_CERT, VERIFY_CLIENT_ONCE, VERIFY_NONE)
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040047
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -040048from OpenSSL.SSL import (
Jean-Paul Calderone313bf012012-02-08 13:02:49 -050049 SESS_CACHE_OFF, SESS_CACHE_CLIENT, SESS_CACHE_SERVER, SESS_CACHE_BOTH,
50 SESS_CACHE_NO_AUTO_CLEAR, SESS_CACHE_NO_INTERNAL_LOOKUP,
51 SESS_CACHE_NO_INTERNAL_STORE, SESS_CACHE_NO_INTERNAL)
52
53from OpenSSL.SSL import (
Jean-Paul Calderoned899af02013-03-19 22:10:37 -070054 Error, SysCallError, WantReadError, WantWriteError, ZeroReturnError)
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -050055from OpenSSL.SSL import (
Jean-Paul Calderoned899af02013-03-19 22:10:37 -070056 Context, ContextType, Session, Connection, ConnectionType, SSLeay_version)
Cory Benfield0ba57ec2016-03-30 09:35:05 +010057from OpenSSL.SSL import _make_requires
Jean-Paul Calderone7526d172010-09-09 17:55:31 -040058
Cory Benfieldba1820d2015-04-13 17:39:12 -040059from OpenSSL._util import lib as _lib
60
Alex Gaynord3b5d9b2016-07-31 10:54:24 -040061from OpenSSL.SSL import (
62 OP_NO_QUERY_MTU, OP_COOKIE_EXCHANGE, OP_NO_TICKET, OP_NO_COMPRESSION,
63 MODE_RELEASE_BUFFERS)
Jean-Paul Calderone0222a492011-09-08 18:26:03 -040064
Jean-Paul Calderone1461c492013-10-03 16:05:00 -040065try:
66 from OpenSSL.SSL import OP_NO_TLSv1, OP_NO_TLSv1_1, OP_NO_TLSv1_2
67except ImportError:
68 OP_NO_TLSv1 = OP_NO_TLSv1_1 = OP_NO_TLSv1_2 = None
69
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -040070from OpenSSL.SSL import (
71 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK, SSL_ST_INIT, SSL_ST_BEFORE,
72 SSL_ST_OK, SSL_ST_RENEGOTIATE,
73 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
74 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
75 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
76 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE)
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -040077
Hynek Schlawackf0e66852015-10-16 20:18:38 +020078from .util import WARNING_TYPE_EXPECTED, NON_ASCII, TestCase, b
79from .test_crypto import (
80 cleartextCertificatePEM, cleartextPrivateKeyPEM,
81 client_cert_pem, client_key_pem, server_cert_pem, server_key_pem,
82 root_cert_pem)
83
Hynek Schlawackde00dd52015-09-05 19:09:26 +020084
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -040085# openssl dhparam 128 -out dh-128.pem (note that 128 is a small number of bits
86# to use)
87dhparam = """\
88-----BEGIN DH PARAMETERS-----
89MBYCEQCobsg29c9WZP/54oAPcwiDAgEC
90-----END DH PARAMETERS-----
91"""
92
93
Hynek Schlawackb4f02402015-09-05 20:48:34 +020094skip_if_py3 = pytest.mark.skipif(PY3, reason="Python 2 only")
Hynek Schlawackf8979a52015-09-05 21:25:25 +020095skip_if_py26 = pytest.mark.skipif(
96 version_info[0:2] == (2, 6),
97 reason="Python 2.7 and later only"
98)
Hynek Schlawack97cf1a82015-09-05 20:40:19 +020099
100
Jean-Paul Calderone05826732015-04-12 11:38:49 -0400101def join_bytes_or_unicode(prefix, suffix):
102 """
103 Join two path components of either ``bytes`` or ``unicode``.
104
105 The return type is the same as the type of ``prefix``.
106 """
107 # If the types are the same, nothing special is necessary.
108 if type(prefix) == type(suffix):
109 return join(prefix, suffix)
110
111 # Otherwise, coerce suffix to the type of prefix.
112 if isinstance(prefix, text_type):
113 return join(prefix, suffix.decode(getfilesystemencoding()))
114 else:
115 return join(prefix, suffix.encode(getfilesystemencoding()))
116
117
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400118def verify_cb(conn, cert, errnum, depth, ok):
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400119 return ok
120
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400121
Rick Deanb1ccd562009-07-09 23:52:39 -0500122def socket_pair():
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400123 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400124 Establish and return a pair of network sockets connected to each other.
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400125 """
126 # Connect a pair of sockets
Rick Deanb1ccd562009-07-09 23:52:39 -0500127 port = socket()
128 port.bind(('', 0))
129 port.listen(1)
130 client = socket()
131 client.setblocking(False)
Jean-Paul Calderonef23c5d92009-07-23 17:58:15 -0400132 client.connect_ex(("127.0.0.1", port.getsockname()[1]))
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400133 client.setblocking(True)
Rick Deanb1ccd562009-07-09 23:52:39 -0500134 server = port.accept()[0]
Rick Deanb1ccd562009-07-09 23:52:39 -0500135
Jean-Paul Calderone1a9613b2009-07-16 12:13:36 -0400136 # Let's pass some unencrypted data to make sure our socket connection is
137 # fine. Just one byte, so we don't have to worry about buffers getting
138 # filled up or fragmentation.
Jean-Paul Calderone9e4eeae2010-08-22 21:32:52 -0400139 server.send(b("x"))
140 assert client.recv(1024) == b("x")
141 client.send(b("y"))
142 assert server.recv(1024) == b("y")
Rick Deanb1ccd562009-07-09 23:52:39 -0500143
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -0400144 # Most of our callers want non-blocking sockets, make it easy for them.
Jean-Paul Calderone94b24a82009-07-16 19:11:38 -0400145 server.setblocking(False)
146 client.setblocking(False)
Jim Shaver46f28912015-05-29 19:32:16 -0400147
Rick Deanb1ccd562009-07-09 23:52:39 -0500148 return (server, client)
149
150
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400151def handshake(client, server):
152 conns = [client, server]
153 while conns:
154 for conn in conns:
155 try:
156 conn.do_handshake()
157 except WantReadError:
158 pass
159 else:
160 conns.remove(conn)
161
162
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400163def _create_certificate_chain():
164 """
165 Construct and return a chain of certificates.
166
167 1. A new self-signed certificate authority certificate (cacert)
168 2. A new intermediate certificate signed by cacert (icert)
169 3. A new server certificate signed by icert (scert)
170 """
171 caext = X509Extension(b('basicConstraints'), False, b('CA:true'))
172
173 # Step 1
174 cakey = PKey()
175 cakey.generate_key(TYPE_RSA, 512)
176 cacert = X509()
177 cacert.get_subject().commonName = "Authority Certificate"
178 cacert.set_issuer(cacert.get_subject())
179 cacert.set_pubkey(cakey)
180 cacert.set_notBefore(b("20000101000000Z"))
181 cacert.set_notAfter(b("20200101000000Z"))
182 cacert.add_extensions([caext])
183 cacert.set_serial_number(0)
184 cacert.sign(cakey, "sha1")
185
186 # Step 2
187 ikey = PKey()
188 ikey.generate_key(TYPE_RSA, 512)
189 icert = X509()
190 icert.get_subject().commonName = "Intermediate Certificate"
191 icert.set_issuer(cacert.get_subject())
192 icert.set_pubkey(ikey)
193 icert.set_notBefore(b("20000101000000Z"))
194 icert.set_notAfter(b("20200101000000Z"))
195 icert.add_extensions([caext])
196 icert.set_serial_number(0)
197 icert.sign(cakey, "sha1")
198
199 # Step 3
200 skey = PKey()
201 skey.generate_key(TYPE_RSA, 512)
202 scert = X509()
203 scert.get_subject().commonName = "Server Certificate"
204 scert.set_issuer(icert.get_subject())
205 scert.set_pubkey(skey)
206 scert.set_notBefore(b("20000101000000Z"))
207 scert.set_notAfter(b("20200101000000Z"))
208 scert.add_extensions([
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200209 X509Extension(b('basicConstraints'), True, b('CA:false'))])
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400210 scert.set_serial_number(0)
211 scert.sign(ikey, "sha1")
212
213 return [(cakey, cacert), (ikey, icert), (skey, scert)]
214
215
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400216class _LoopbackMixin:
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400217 """
218 Helper mixin which defines methods for creating a connected socket pair and
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200219 for forcing two connected SSL sockets to talk to each other via memory
220 BIOs.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400221 """
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500222 def _loopbackClientFactory(self, socket):
223 client = Connection(Context(TLSv1_METHOD), socket)
224 client.set_connect_state()
225 return client
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400226
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500227 def _loopbackServerFactory(self, socket):
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400228 ctx = Context(TLSv1_METHOD)
229 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
230 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500231 server = Connection(ctx, socket)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400232 server.set_accept_state()
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500233 return server
234
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -0500235 def _loopback(self, serverFactory=None, clientFactory=None):
236 if serverFactory is None:
237 serverFactory = self._loopbackServerFactory
238 if clientFactory is None:
239 clientFactory = self._loopbackClientFactory
240
241 (server, client) = socket_pair()
242 server = serverFactory(server)
243 client = clientFactory(client)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400244
Jean-Paul Calderonef8742032010-09-25 00:00:32 -0400245 handshake(client, server)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400246
247 server.setblocking(True)
248 client.setblocking(True)
249 return server, client
250
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400251 def _interactInMemory(self, client_conn, server_conn):
252 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900253 Try to read application bytes from each of the two :py:obj:`Connection`
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400254 objects. Copy bytes back and forth between their send/receive buffers
255 for as long as there is anything to copy. When there is nothing more
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200256 to copy, return :py:obj:`None`. If one of them actually manages to
257 deliver some application bytes, return a two-tuple of the connection
258 from which the bytes were read and the bytes themselves.
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400259 """
260 wrote = True
261 while wrote:
262 # Loop until neither side has anything to say
263 wrote = False
264
265 # Copy stuff from each side's send buffer to the other side's
266 # receive buffer.
267 for (read, write) in [(client_conn, server_conn),
268 (server_conn, client_conn)]:
269
270 # Give the side a chance to generate some more bytes, or
271 # succeed.
272 try:
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400273 data = read.recv(2 ** 16)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400274 except WantReadError:
275 # It didn't succeed, so we'll hope it generated some
276 # output.
277 pass
278 else:
279 # It did succeed, so we'll stop now and let the caller deal
280 # with it.
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -0400281 return (read, data)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400282
283 while True:
284 # Keep copying as long as there's more stuff there.
285 try:
286 dirty = read.bio_read(4096)
287 except WantReadError:
288 # Okay, nothing more waiting to be sent. Stop
289 # processing this send buffer.
290 break
291 else:
292 # Keep track of the fact that someone generated some
293 # output.
294 wrote = True
295 write.bio_write(dirty)
296
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -0400297 def _handshakeInMemory(self, client_conn, server_conn):
Jean-Paul Calderoneb2b40782014-05-06 08:47:40 -0400298 """
299 Perform the TLS handshake between two :py:class:`Connection` instances
300 connected to each other via memory BIOs.
301 """
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -0400302 client_conn.set_connect_state()
303 server_conn.set_accept_state()
304
305 for conn in [client_conn, server_conn]:
306 try:
307 conn.do_handshake()
308 except WantReadError:
309 pass
310
311 self._interactInMemory(client_conn, server_conn)
312
313
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400314class VersionTests(TestCase):
315 """
316 Tests for version information exposed by
Jonathan Ballet648875f2011-07-16 14:14:58 +0900317 :py:obj:`OpenSSL.SSL.SSLeay_version` and
318 :py:obj:`OpenSSL.SSL.OPENSSL_VERSION_NUMBER`.
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400319 """
320 def test_OPENSSL_VERSION_NUMBER(self):
321 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900322 :py:obj:`OPENSSL_VERSION_NUMBER` is an integer with status in the low
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400323 byte and the patch, fix, minor, and major versions in the
324 nibbles above that.
325 """
326 self.assertTrue(isinstance(OPENSSL_VERSION_NUMBER, int))
327
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400328 def test_SSLeay_version(self):
329 """
Jonathan Ballet648875f2011-07-16 14:14:58 +0900330 :py:obj:`SSLeay_version` takes a version type indicator and returns
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400331 one of a number of version strings based on that indicator.
332 """
333 versions = {}
334 for t in [SSLEAY_VERSION, SSLEAY_CFLAGS, SSLEAY_BUILT_ON,
335 SSLEAY_PLATFORM, SSLEAY_DIR]:
336 version = SSLeay_version(t)
337 versions[version] = t
338 self.assertTrue(isinstance(version, bytes))
339 self.assertEqual(len(versions), 5)
340
341
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100342@pytest.fixture
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100343def ca_file(tmpdir):
344 """
345 Create a valid PEM file with CA certificates and return the path.
346 """
347 key = rsa.generate_private_key(
348 public_exponent=65537,
349 key_size=2048,
350 backend=default_backend()
351 )
352 public_key = key.public_key()
353
354 builder = x509.CertificateBuilder()
355 builder = builder.subject_name(x509.Name([
356 x509.NameAttribute(NameOID.COMMON_NAME, u"pyopenssl.org"),
357 ]))
358 builder = builder.issuer_name(x509.Name([
359 x509.NameAttribute(NameOID.COMMON_NAME, u"pyopenssl.org"),
360 ]))
361 one_day = datetime.timedelta(1, 0, 0)
362 builder = builder.not_valid_before(datetime.datetime.today() - one_day)
363 builder = builder.not_valid_after(datetime.datetime.today() + one_day)
364 builder = builder.serial_number(int(uuid.uuid4()))
365 builder = builder.public_key(public_key)
366 builder = builder.add_extension(
367 x509.BasicConstraints(ca=True, path_length=None), critical=True,
368 )
369
370 certificate = builder.sign(
371 private_key=key, algorithm=hashes.SHA256(),
372 backend=default_backend()
373 )
374
375 ca_file = tmpdir.join("test.pem")
376 ca_file.write_binary(
377 certificate.public_bytes(
378 encoding=serialization.Encoding.PEM,
379 )
380 )
381
382 return str(ca_file).encode("ascii")
383
384
385@pytest.fixture
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100386def context():
387 """
388 A simple TLS 1.0 context.
389 """
390 return Context(TLSv1_METHOD)
391
392
393class TestContext(object):
Hynek Schlawackaa861212016-03-13 13:53:48 +0100394 """
395 py.test-based tests for :class:`OpenSSL.SSL.Context`.
396
397 If possible, add new tests here.
398 """
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100399 @pytest.mark.parametrize("cipher_string", [
400 b"hello world:AES128-SHA",
401 u"hello world:AES128-SHA",
402 ])
403 def test_set_cipher_list(self, context, cipher_string):
404 """
Hynek Schlawacka7a63af2016-03-11 12:05:26 +0100405 :meth:`Context.set_cipher_list` accepts both byte and unicode strings
406 for naming the ciphers which connections created with the context
407 object will be able to choose from.
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100408 """
409 context.set_cipher_list(cipher_string)
410 conn = Connection(context, None)
411
412 assert "AES128-SHA" in conn.get_cipher_list()
413
414 @pytest.mark.parametrize("cipher_list,error", [
415 (object(), TypeError),
416 ("imaginary-cipher", Error),
417 ])
418 def test_set_cipher_list_wrong_args(self, context, cipher_list, error):
419 """
420 :meth:`Context.set_cipher_list` raises :exc:`TypeError` when passed a
421 non-string argument and raises :exc:`OpenSSL.SSL.Error` when passed an
422 incorrect cipher list string.
423 """
424 with pytest.raises(error):
425 context.set_cipher_list(cipher_list)
426
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +0100427 def test_load_client_ca(self, context, ca_file):
428 """
429 :meth:`Context.load_client_ca` works as far as we can tell.
430 """
431 context.load_client_ca(ca_file)
432
433 def test_load_client_ca_invalid(self, context, tmpdir):
434 """
435 :meth:`Context.load_client_ca` raises an Error if the ca file is
436 invalid.
437 """
438 ca_file = tmpdir.join("test.pem")
439 ca_file.write("")
440
441 with pytest.raises(Error) as e:
442 context.load_client_ca(str(ca_file).encode("ascii"))
443
444 assert "PEM routines" == e.value.args[0][0][0]
445
446 def test_load_client_ca_unicode(self, context, ca_file):
447 """
448 Passing the path as unicode raises a warning but works.
449 """
450 pytest.deprecated_call(
451 context.load_client_ca, ca_file.decode("ascii")
452 )
453
454 def test_set_session_id(self, context):
455 """
456 :meth:`Context.set_session_id` works as far as we can tell.
457 """
458 context.set_session_id(b"abc")
459
460 def test_set_session_id_fail(self, context):
461 """
462 :meth:`Context.set_session_id` errors are propagated.
463 """
464 with pytest.raises(Error) as e:
465 context.set_session_id(b"abc" * 1000)
466
467 assert [
468 ("SSL routines",
469 "SSL_CTX_set_session_id_context",
470 "ssl session id context too long")
471 ] == e.value.args[0]
472
473 def test_set_session_id_unicode(self, context):
474 """
475 :meth:`Context.set_session_id` raises a warning if a unicode string is
476 passed.
477 """
478 pytest.deprecated_call(context.set_session_id, u"abc")
479
Hynek Schlawackf90e3682016-03-11 11:21:13 +0100480
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -0400481class ContextTests(TestCase, _LoopbackMixin):
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400482 """
Hynek Schlawackaa861212016-03-13 13:53:48 +0100483 Unit tests for :class:`OpenSSL.SSL.Context`.
484
485 If possible, add new tests to :class:`TestContext` above.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400486 """
487 def test_method(self):
488 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200489 :py:obj:`Context` can be instantiated with one of
490 :py:obj:`SSLv2_METHOD`, :py:obj:`SSLv3_METHOD`,
491 :py:obj:`SSLv23_METHOD`, :py:obj:`TLSv1_METHOD`,
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400492 :py:obj:`TLSv1_1_METHOD`, or :py:obj:`TLSv1_2_METHOD`.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400493 """
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400494 methods = [
495 SSLv3_METHOD, SSLv23_METHOD, TLSv1_METHOD]
496 for meth in methods:
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400497 Context(meth)
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400498
Jean-Paul Calderone1461c492013-10-03 16:05:00 -0400499 maybe = [SSLv2_METHOD, TLSv1_1_METHOD, TLSv1_2_METHOD]
500 for meth in maybe:
501 try:
502 Context(meth)
503 except (Error, ValueError):
504 # Some versions of OpenSSL have SSLv2 / TLSv1.1 / TLSv1.2, some
505 # don't. Difficult to say in advance.
506 pass
Jean-Paul Calderone9f2e38e2011-04-14 09:36:55 -0400507
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400508 self.assertRaises(TypeError, Context, "")
509 self.assertRaises(ValueError, Context, 10)
510
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200511 @skip_if_py3
512 def test_method_long(self):
513 """
514 On Python 2 :py:class:`Context` accepts values of type
515 :py:obj:`long` as well as :py:obj:`int`.
516 """
517 Context(long(TLSv1_METHOD))
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500518
Rick Deane15b1472009-07-09 15:53:42 -0500519 def test_type(self):
520 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200521 :py:obj:`Context` and :py:obj:`ContextType` refer to the same type
522 object and can be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -0500523 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -0400524 self.assertIdentical(Context, ContextType)
525 self.assertConsistentType(Context, 'Context', TLSv1_METHOD)
Rick Deane15b1472009-07-09 15:53:42 -0500526
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400527 def test_use_privatekey(self):
528 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200529 :py:obj:`Context.use_privatekey` takes an :py:obj:`OpenSSL.crypto.PKey`
530 instance.
Jean-Paul Calderone30c09ea2008-03-21 17:04:05 -0400531 """
532 key = PKey()
533 key.generate_key(TYPE_RSA, 128)
534 ctx = Context(TLSv1_METHOD)
535 ctx.use_privatekey(key)
536 self.assertRaises(TypeError, ctx.use_privatekey, "")
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400537
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800538 def test_use_privatekey_file_missing(self):
539 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200540 :py:obj:`Context.use_privatekey_file` raises
541 :py:obj:`OpenSSL.SSL.Error` when passed the name of a file which does
542 not exist.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800543 """
544 ctx = Context(TLSv1_METHOD)
545 self.assertRaises(Error, ctx.use_privatekey_file, self.mktemp())
546
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400547 def _use_privatekey_file_test(self, pemfile, filetype):
548 """
549 Verify that calling ``Context.use_privatekey_file`` with the given
550 arguments does not raise an exception.
551 """
552 key = PKey()
553 key.generate_key(TYPE_RSA, 128)
554
555 with open(pemfile, "wt") as pem:
556 pem.write(
557 dump_privatekey(FILETYPE_PEM, key).decode("ascii")
558 )
559
560 ctx = Context(TLSv1_METHOD)
561 ctx.use_privatekey_file(pemfile, filetype)
562
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400563 def test_use_privatekey_file_bytes(self):
564 """
565 A private key can be specified from a file by passing a ``bytes``
566 instance giving the file name to ``Context.use_privatekey_file``.
567 """
568 self._use_privatekey_file_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -0400569 self.mktemp() + NON_ASCII.encode(getfilesystemencoding()),
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400570 FILETYPE_PEM,
571 )
572
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400573 def test_use_privatekey_file_unicode(self):
574 """
575 A private key can be specified from a file by passing a ``unicode``
576 instance giving the file name to ``Context.use_privatekey_file``.
577 """
578 self._use_privatekey_file_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -0400579 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII,
Jean-Paul Calderone69a4e5b2015-04-12 10:04:28 -0400580 FILETYPE_PEM,
581 )
582
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200583 @skip_if_py3
584 def test_use_privatekey_file_long(self):
585 """
586 On Python 2 :py:obj:`Context.use_privatekey_file` accepts a
587 filetype of type :py:obj:`long` as well as :py:obj:`int`.
588 """
589 self._use_privatekey_file_test(self.mktemp(), long(FILETYPE_PEM))
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500590
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800591 def test_use_certificate_wrong_args(self):
592 """
593 :py:obj:`Context.use_certificate_wrong_args` raises :py:obj:`TypeError`
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200594 when not passed exactly one :py:obj:`OpenSSL.crypto.X509` instance as
595 an argument.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800596 """
597 ctx = Context(TLSv1_METHOD)
598 self.assertRaises(TypeError, ctx.use_certificate)
599 self.assertRaises(TypeError, ctx.use_certificate, "hello, world")
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200600 self.assertRaises(
601 TypeError, ctx.use_certificate, X509(), "hello, world"
602 )
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800603
604 def test_use_certificate_uninitialized(self):
605 """
606 :py:obj:`Context.use_certificate` raises :py:obj:`OpenSSL.SSL.Error`
607 when passed a :py:obj:`OpenSSL.crypto.X509` instance which has not been
608 initialized (ie, which does not actually have any certificate data).
609 """
610 ctx = Context(TLSv1_METHOD)
611 self.assertRaises(Error, ctx.use_certificate, X509())
612
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800613 def test_use_certificate(self):
614 """
615 :py:obj:`Context.use_certificate` sets the certificate which will be
616 used to identify connections created using the context.
617 """
618 # TODO
619 # Hard to assert anything. But we could set a privatekey then ask
620 # OpenSSL if the cert and key agree using check_privatekey. Then as
621 # long as check_privatekey works right we're good...
622 ctx = Context(TLSv1_METHOD)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200623 ctx.use_certificate(
624 load_certificate(FILETYPE_PEM, cleartextCertificatePEM)
625 )
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800626
627 def test_use_certificate_file_wrong_args(self):
628 """
629 :py:obj:`Context.use_certificate_file` raises :py:obj:`TypeError` if
630 called with zero arguments or more than two arguments, or if the first
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200631 argument is not a byte string or the second argumnent is not an
632 integer.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800633 """
634 ctx = Context(TLSv1_METHOD)
635 self.assertRaises(TypeError, ctx.use_certificate_file)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200636 self.assertRaises(TypeError, ctx.use_certificate_file, b"somefile",
637 object())
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800638 self.assertRaises(
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200639 TypeError, ctx.use_certificate_file, b"somefile", FILETYPE_PEM,
640 object())
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800641 self.assertRaises(
642 TypeError, ctx.use_certificate_file, object(), FILETYPE_PEM)
643 self.assertRaises(
644 TypeError, ctx.use_certificate_file, b"somefile", object())
645
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800646 def test_use_certificate_file_missing(self):
647 """
648 :py:obj:`Context.use_certificate_file` raises
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200649 `:py:obj:`OpenSSL.SSL.Error` if passed the name of a file which does
650 not exist.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800651 """
652 ctx = Context(TLSv1_METHOD)
653 self.assertRaises(Error, ctx.use_certificate_file, self.mktemp())
654
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400655 def _use_certificate_file_test(self, certificate_file):
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800656 """
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400657 Verify that calling ``Context.use_certificate_file`` with the given
658 filename doesn't raise an exception.
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800659 """
660 # TODO
661 # Hard to assert anything. But we could set a privatekey then ask
662 # OpenSSL if the cert and key agree using check_privatekey. Then as
663 # long as check_privatekey works right we're good...
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400664 with open(certificate_file, "wb") as pem_file:
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800665 pem_file.write(cleartextCertificatePEM)
666
667 ctx = Context(TLSv1_METHOD)
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400668 ctx.use_certificate_file(certificate_file)
669
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400670 def test_use_certificate_file_bytes(self):
671 """
672 :py:obj:`Context.use_certificate_file` sets the certificate (given as a
673 ``bytes`` filename) which will be used to identify connections created
674 using the context.
675 """
Hynek Schlawack4813c0e2015-04-16 13:38:01 -0400676 filename = self.mktemp() + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400677 self._use_certificate_file_test(filename)
678
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400679 def test_use_certificate_file_unicode(self):
680 """
681 :py:obj:`Context.use_certificate_file` sets the certificate (given as a
682 ``bytes`` filename) which will be used to identify connections created
683 using the context.
684 """
Hynek Schlawack4813c0e2015-04-16 13:38:01 -0400685 filename = self.mktemp().decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderoned57a7b62015-04-12 09:57:36 -0400686 self._use_certificate_file_test(filename)
Jean-Paul Calderone173cff92013-03-06 10:29:21 -0800687
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200688 @skip_if_py3
689 def test_use_certificate_file_long(self):
690 """
691 On Python 2 :py:obj:`Context.use_certificate_file` accepts a
692 filetype of type :py:obj:`long` as well as :py:obj:`int`.
693 """
694 pem_filename = self.mktemp()
695 with open(pem_filename, "wb") as pem_file:
696 pem_file.write(cleartextCertificatePEM)
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500697
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200698 ctx = Context(TLSv1_METHOD)
699 ctx.use_certificate_file(pem_filename, long(FILETYPE_PEM))
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -0500700
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500701 def test_check_privatekey_valid(self):
702 """
703 :py:obj:`Context.check_privatekey` returns :py:obj:`None` if the
704 :py:obj:`Context` instance has been configured to use a matched key and
705 certificate pair.
706 """
707 key = load_privatekey(FILETYPE_PEM, client_key_pem)
708 cert = load_certificate(FILETYPE_PEM, client_cert_pem)
709 context = Context(TLSv1_METHOD)
710 context.use_privatekey(key)
711 context.use_certificate(cert)
712 self.assertIs(None, context.check_privatekey())
713
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500714 def test_check_privatekey_invalid(self):
715 """
716 :py:obj:`Context.check_privatekey` raises :py:obj:`Error` if the
717 :py:obj:`Context` instance has been configured to use a key and
718 certificate pair which don't relate to each other.
719 """
720 key = load_privatekey(FILETYPE_PEM, client_key_pem)
721 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
722 context = Context(TLSv1_METHOD)
723 context.use_privatekey(key)
724 context.use_certificate(cert)
725 self.assertRaises(Error, context.check_privatekey)
726
Jean-Paul Calderone932f5cc2014-12-11 13:58:00 -0500727 def test_check_privatekey_wrong_args(self):
728 """
729 :py:obj:`Context.check_privatekey` raises :py:obj:`TypeError` if called
730 with other than no arguments.
731 """
732 context = Context(TLSv1_METHOD)
733 self.assertRaises(TypeError, context.check_privatekey, object())
734
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400735 def test_set_app_data_wrong_args(self):
736 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200737 :py:obj:`Context.set_app_data` raises :py:obj:`TypeError` if called
738 with other than one argument.
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400739 """
740 context = Context(TLSv1_METHOD)
741 self.assertRaises(TypeError, context.set_app_data)
742 self.assertRaises(TypeError, context.set_app_data, None, None)
743
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400744 def test_get_app_data_wrong_args(self):
745 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200746 :py:obj:`Context.get_app_data` raises :py:obj:`TypeError` if called
747 with any arguments.
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400748 """
749 context = Context(TLSv1_METHOD)
750 self.assertRaises(TypeError, context.get_app_data, None)
751
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400752 def test_app_data(self):
753 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200754 :py:obj:`Context.set_app_data` stores an object for later retrieval
755 using :py:obj:`Context.get_app_data`.
Jean-Paul Calderonebd479162010-07-30 18:03:25 -0400756 """
757 app_data = object()
758 context = Context(TLSv1_METHOD)
759 context.set_app_data(app_data)
760 self.assertIdentical(context.get_app_data(), app_data)
761
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400762 def test_set_options_wrong_args(self):
763 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200764 :py:obj:`Context.set_options` raises :py:obj:`TypeError` if called with
765 the wrong number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderone40569ca2010-07-30 18:04:58 -0400766 """
767 context = Context(TLSv1_METHOD)
768 self.assertRaises(TypeError, context.set_options)
769 self.assertRaises(TypeError, context.set_options, None)
770 self.assertRaises(TypeError, context.set_options, 1, None)
771
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500772 def test_set_options(self):
773 """
774 :py:obj:`Context.set_options` returns the new options value.
775 """
776 context = Context(TLSv1_METHOD)
777 options = context.set_options(OP_NO_SSLv2)
778 self.assertTrue(OP_NO_SSLv2 & options)
779
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200780 @skip_if_py3
781 def test_set_options_long(self):
782 """
783 On Python 2 :py:obj:`Context.set_options` accepts values of type
784 :py:obj:`long` as well as :py:obj:`int`.
785 """
786 context = Context(TLSv1_METHOD)
787 options = context.set_options(long(OP_NO_SSLv2))
788 self.assertTrue(OP_NO_SSLv2 & options)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500789
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300790 def test_set_mode_wrong_args(self):
791 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200792 :py:obj:`Context.set`mode} raises :py:obj:`TypeError` if called with
793 the wrong number of arguments or a non-:py:obj:`int` argument.
Guillermo Gonzalez74a2c292011-08-29 16:16:58 -0300794 """
795 context = Context(TLSv1_METHOD)
796 self.assertRaises(TypeError, context.set_mode)
797 self.assertRaises(TypeError, context.set_mode, None)
798 self.assertRaises(TypeError, context.set_mode, 1, None)
799
Alex Gaynord3b5d9b2016-07-31 10:54:24 -0400800 def test_set_mode(self):
801 """
802 :py:obj:`Context.set_mode` accepts a mode bitvector and returns the
803 newly set mode.
804 """
805 context = Context(TLSv1_METHOD)
806 self.assertTrue(
807 MODE_RELEASE_BUFFERS & context.set_mode(MODE_RELEASE_BUFFERS))
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500808
Alex Gaynord3b5d9b2016-07-31 10:54:24 -0400809 @skip_if_py3
810 def test_set_mode_long(self):
811 """
812 On Python 2 :py:obj:`Context.set_mode` accepts values of type
813 :py:obj:`long` as well as :py:obj:`int`.
814 """
815 context = Context(TLSv1_METHOD)
816 mode = context.set_mode(long(MODE_RELEASE_BUFFERS))
817 self.assertTrue(MODE_RELEASE_BUFFERS & mode)
Jean-Paul Calderone0222a492011-09-08 18:26:03 -0400818
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400819 def test_set_timeout_wrong_args(self):
820 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200821 :py:obj:`Context.set_timeout` raises :py:obj:`TypeError` if called with
822 the wrong number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400823 """
824 context = Context(TLSv1_METHOD)
825 self.assertRaises(TypeError, context.set_timeout)
826 self.assertRaises(TypeError, context.set_timeout, None)
827 self.assertRaises(TypeError, context.set_timeout, 1, None)
828
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400829 def test_get_timeout_wrong_args(self):
830 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200831 :py:obj:`Context.get_timeout` raises :py:obj:`TypeError` if called with
832 any arguments.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400833 """
834 context = Context(TLSv1_METHOD)
835 self.assertRaises(TypeError, context.get_timeout, None)
836
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400837 def test_timeout(self):
838 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200839 :py:obj:`Context.set_timeout` sets the session timeout for all
840 connections created using the context object.
841 :py:obj:`Context.get_timeout` retrieves this value.
Jean-Paul Calderone5ebb44a2010-07-30 18:09:41 -0400842 """
843 context = Context(TLSv1_METHOD)
844 context.set_timeout(1234)
845 self.assertEquals(context.get_timeout(), 1234)
846
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200847 @skip_if_py3
848 def test_timeout_long(self):
849 """
850 On Python 2 :py:obj:`Context.set_timeout` accepts values of type
851 `long` as well as int.
852 """
853 context = Context(TLSv1_METHOD)
854 context.set_timeout(long(1234))
855 self.assertEquals(context.get_timeout(), 1234)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500856
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400857 def test_set_verify_depth_wrong_args(self):
858 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200859 :py:obj:`Context.set_verify_depth` raises :py:obj:`TypeError` if called
860 with the wrong number of arguments or a non-:py:obj:`int` argument.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400861 """
862 context = Context(TLSv1_METHOD)
863 self.assertRaises(TypeError, context.set_verify_depth)
864 self.assertRaises(TypeError, context.set_verify_depth, None)
865 self.assertRaises(TypeError, context.set_verify_depth, 1, None)
866
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400867 def test_get_verify_depth_wrong_args(self):
868 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200869 :py:obj:`Context.get_verify_depth` raises :py:obj:`TypeError` if called
870 with any arguments.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400871 """
872 context = Context(TLSv1_METHOD)
873 self.assertRaises(TypeError, context.get_verify_depth, None)
874
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400875 def test_verify_depth(self):
876 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200877 :py:obj:`Context.set_verify_depth` sets the number of certificates in
878 a chain to follow before giving up. The value can be retrieved with
Jonathan Ballet648875f2011-07-16 14:14:58 +0900879 :py:obj:`Context.get_verify_depth`.
Jean-Paul Calderonee2b69512010-07-30 18:22:06 -0400880 """
881 context = Context(TLSv1_METHOD)
882 context.set_verify_depth(11)
883 self.assertEquals(context.get_verify_depth(), 11)
884
Hynek Schlawack97cf1a82015-09-05 20:40:19 +0200885 @skip_if_py3
886 def test_verify_depth_long(self):
887 """
888 On Python 2 :py:obj:`Context.set_verify_depth` accepts values of
889 type `long` as well as int.
890 """
891 context = Context(TLSv1_METHOD)
892 context.set_verify_depth(long(11))
893 self.assertEquals(context.get_verify_depth(), 11)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -0500894
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400895 def _write_encrypted_pem(self, passphrase):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -0400896 """
897 Write a new private key out to a new file, encrypted using the given
898 passphrase. Return the path to the new file.
899 """
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400900 key = PKey()
901 key.generate_key(TYPE_RSA, 128)
902 pemFile = self.mktemp()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400903 fObj = open(pemFile, 'w')
904 pem = dump_privatekey(FILETYPE_PEM, key, "blowfish", passphrase)
905 fObj.write(pem.decode('ascii'))
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400906 fObj.close()
907 return pemFile
908
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400909 def test_set_passwd_cb_wrong_args(self):
910 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200911 :py:obj:`Context.set_passwd_cb` raises :py:obj:`TypeError` if called
912 with the wrong arguments or with a non-callable first argument.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400913 """
914 context = Context(TLSv1_METHOD)
915 self.assertRaises(TypeError, context.set_passwd_cb)
916 self.assertRaises(TypeError, context.set_passwd_cb, None)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200917 self.assertRaises(
918 TypeError, context.set_passwd_cb, lambda: None, None, None
Hynek Schlawack2c013a92015-09-05 19:33:05 +0200919 ) # pragma: nocover
Jean-Paul Calderonef4480622010-08-02 18:25:03 -0400920
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400921 def test_set_passwd_cb(self):
922 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200923 :py:obj:`Context.set_passwd_cb` accepts a callable which will be
924 invoked when a private key is loaded from an encrypted PEM.
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400925 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400926 passphrase = b("foobar")
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400927 pemFile = self._write_encrypted_pem(passphrase)
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400928 calledWith = []
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200929
Jean-Paul Calderone828c9cb2008-04-26 18:06:54 -0400930 def passphraseCallback(maxlen, verify, extra):
931 calledWith.append((maxlen, verify, extra))
932 return passphrase
933 context = Context(TLSv1_METHOD)
934 context.set_passwd_cb(passphraseCallback)
935 context.use_privatekey_file(pemFile)
936 self.assertTrue(len(calledWith), 1)
937 self.assertTrue(isinstance(calledWith[0][0], int))
938 self.assertTrue(isinstance(calledWith[0][1], int))
939 self.assertEqual(calledWith[0][2], None)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -0400940
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400941 def test_passwd_callback_exception(self):
942 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200943 :py:obj:`Context.use_privatekey_file` propagates any exception raised
944 by the passphrase callback.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400945 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400946 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200947
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400948 def passphraseCallback(maxlen, verify, extra):
949 raise RuntimeError("Sorry, I am a fail.")
950
951 context = Context(TLSv1_METHOD)
952 context.set_passwd_cb(passphraseCallback)
953 self.assertRaises(RuntimeError, context.use_privatekey_file, pemFile)
954
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400955 def test_passwd_callback_false(self):
956 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200957 :py:obj:`Context.use_privatekey_file` raises
958 :py:obj:`OpenSSL.SSL.Error` if the passphrase callback returns a false
959 value.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400960 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400961 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200962
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400963 def passphraseCallback(maxlen, verify, extra):
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -0500964 return b""
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400965
966 context = Context(TLSv1_METHOD)
967 context.set_passwd_cb(passphraseCallback)
968 self.assertRaises(Error, context.use_privatekey_file, pemFile)
969
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400970 def test_passwd_callback_non_string(self):
971 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200972 :py:obj:`Context.use_privatekey_file` raises
973 :py:obj:`OpenSSL.SSL.Error` if the passphrase callback returns a true
974 non-string value.
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400975 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400976 pemFile = self._write_encrypted_pem(b("monkeys are nice"))
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200977
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400978 def passphraseCallback(maxlen, verify, extra):
979 return 10
980
981 context = Context(TLSv1_METHOD)
982 context.set_passwd_cb(passphraseCallback)
Jean-Paul Calderone8a1bea52013-03-05 07:57:57 -0800983 self.assertRaises(ValueError, context.use_privatekey_file, pemFile)
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400984
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400985 def test_passwd_callback_too_long(self):
986 """
987 If the passphrase returned by the passphrase callback returns a string
988 longer than the indicated maximum length, it is truncated.
989 """
990 # A priori knowledge!
Jean-Paul Calderonea9868832010-08-22 21:38:34 -0400991 passphrase = b("x") * 1024
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400992 pemFile = self._write_encrypted_pem(passphrase)
Hynek Schlawackde00dd52015-09-05 19:09:26 +0200993
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400994 def passphraseCallback(maxlen, verify, extra):
995 assert maxlen == 1024
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -0400996 return passphrase + b("y")
Jean-Paul Calderone389d76d2010-07-30 17:57:53 -0400997
998 context = Context(TLSv1_METHOD)
999 context.set_passwd_cb(passphraseCallback)
1000 # This shall succeed because the truncated result is the correct
1001 # passphrase.
1002 context.use_privatekey_file(pemFile)
1003
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -04001004 def test_set_info_callback(self):
1005 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001006 :py:obj:`Context.set_info_callback` accepts a callable which will be
1007 invoked when certain information about an SSL connection is available.
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -04001008 """
Rick Deanb1ccd562009-07-09 23:52:39 -05001009 (server, client) = socket_pair()
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -04001010
1011 clientSSL = Connection(Context(TLSv1_METHOD), client)
1012 clientSSL.set_connect_state()
1013
1014 called = []
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001015
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -04001016 def info(conn, where, ret):
1017 called.append((conn, where, ret))
1018 context = Context(TLSv1_METHOD)
1019 context.set_info_callback(info)
1020 context.use_certificate(
1021 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1022 context.use_privatekey(
1023 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1024
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -04001025 serverSSL = Connection(context, server)
1026 serverSSL.set_accept_state()
1027
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -05001028 handshake(clientSSL, serverSSL)
Jean-Paul Calderone5ef86512008-04-26 19:06:28 -04001029
Jean-Paul Calderone3835e522014-02-02 11:12:30 -05001030 # The callback must always be called with a Connection instance as the
1031 # first argument. It would probably be better to split this into
1032 # separate tests for client and server side info callbacks so we could
1033 # assert it is called with the right Connection instance. It would
1034 # also be good to assert *something* about `where` and `ret`.
Jean-Paul Calderonef2bbc9c2014-02-02 10:59:14 -05001035 notConnections = [
1036 conn for (conn, where, ret) in called
1037 if not isinstance(conn, Connection)]
1038 self.assertEqual(
1039 [], notConnections,
1040 "Some info callback arguments were not Connection instaces.")
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001041
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001042 def _load_verify_locations_test(self, *args):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001043 """
1044 Create a client context which will verify the peer certificate and call
Jean-Paul Calderone64efa2c2011-09-11 10:00:09 -04001045 its :py:obj:`load_verify_locations` method with the given arguments.
1046 Then connect it to a server and ensure that the handshake succeeds.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04001047 """
Rick Deanb1ccd562009-07-09 23:52:39 -05001048 (server, client) = socket_pair()
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001049
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001050 clientContext = Context(TLSv1_METHOD)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001051 clientContext.load_verify_locations(*args)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001052 # Require that the server certificate verify properly or the
1053 # connection will fail.
1054 clientContext.set_verify(
1055 VERIFY_PEER,
1056 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
1057
1058 clientSSL = Connection(clientContext, client)
1059 clientSSL.set_connect_state()
1060
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001061 serverContext = Context(TLSv1_METHOD)
1062 serverContext.use_certificate(
1063 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1064 serverContext.use_privatekey(
1065 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1066
1067 serverSSL = Connection(serverContext, server)
1068 serverSSL.set_accept_state()
1069
Jean-Paul Calderonef8742032010-09-25 00:00:32 -04001070 # Without load_verify_locations above, the handshake
1071 # will fail:
1072 # Error: [('SSL routines', 'SSL3_GET_SERVER_CERTIFICATE',
1073 # 'certificate verify failed')]
1074 handshake(clientSSL, serverSSL)
Jean-Paul Calderonee1bd4322008-09-07 20:17:17 -04001075
1076 cert = clientSSL.get_peer_certificate()
Jean-Paul Calderone20131f52009-04-01 12:05:45 -04001077 self.assertEqual(cert.get_subject().CN, 'Testing Root CA')
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -04001078
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001079 def _load_verify_cafile(self, cafile):
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001080 """
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001081 Verify that if path to a file containing a certificate is passed to
1082 ``Context.load_verify_locations`` for the ``cafile`` parameter, that
1083 certificate is used as a trust root for the purposes of verifying
1084 connections created using that ``Context``.
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001085 """
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04001086 fObj = open(cafile, 'w')
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04001087 fObj.write(cleartextCertificatePEM.decode('ascii'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001088 fObj.close()
1089
1090 self._load_verify_locations_test(cafile)
1091
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001092 def test_load_verify_bytes_cafile(self):
1093 """
1094 :py:obj:`Context.load_verify_locations` accepts a file name as a
1095 ``bytes`` instance and uses the certificates within for verification
1096 purposes.
1097 """
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001098 cafile = self.mktemp() + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001099 self._load_verify_cafile(cafile)
1100
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001101 def test_load_verify_unicode_cafile(self):
1102 """
1103 :py:obj:`Context.load_verify_locations` accepts a file name as a
1104 ``unicode`` instance and uses the certificates within for verification
1105 purposes.
1106 """
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001107 self._load_verify_cafile(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001108 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001109 )
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001110
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -04001111 def test_load_verify_invalid_file(self):
1112 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001113 :py:obj:`Context.load_verify_locations` raises :py:obj:`Error` when
1114 passed a non-existent cafile.
Jean-Paul Calderone5075fce2008-09-07 20:18:55 -04001115 """
1116 clientContext = Context(TLSv1_METHOD)
1117 self.assertRaises(
1118 Error, clientContext.load_verify_locations, self.mktemp())
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001119
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001120 def _load_verify_directory_locations_capath(self, capath):
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001121 """
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001122 Verify that if path to a directory containing certificate files is
1123 passed to ``Context.load_verify_locations`` for the ``capath``
1124 parameter, those certificates are used as trust roots for the purposes
1125 of verifying connections created using that ``Context``.
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001126 """
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001127 makedirs(capath)
Jean-Paul Calderone24dfb332011-05-04 18:10:26 -04001128 # Hash values computed manually with c_rehash to avoid depending on
1129 # c_rehash in the test suite. One is from OpenSSL 0.9.8, the other
1130 # from OpenSSL 1.0.0.
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001131 for name in [b'c7adac82.0', b'c3705638.0']:
Jean-Paul Calderone05826732015-04-12 11:38:49 -04001132 cafile = join_bytes_or_unicode(capath, name)
1133 with open(cafile, 'w') as fObj:
1134 fObj.write(cleartextCertificatePEM.decode('ascii'))
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001135
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001136 self._load_verify_locations_test(None, capath)
1137
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001138 def test_load_verify_directory_bytes_capath(self):
1139 """
1140 :py:obj:`Context.load_verify_locations` accepts a directory name as a
1141 ``bytes`` instance and uses the certificates within for verification
1142 purposes.
1143 """
1144 self._load_verify_directory_locations_capath(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001145 self.mktemp() + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001146 )
1147
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001148 def test_load_verify_directory_unicode_capath(self):
1149 """
1150 :py:obj:`Context.load_verify_locations` accepts a directory name as a
1151 ``unicode`` instance and uses the certificates within for verification
1152 purposes.
1153 """
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001154 self._load_verify_directory_locations_capath(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001155 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderone4f70c802015-04-12 11:26:47 -04001156 )
Jean-Paul Calderone210c0f32015-04-12 09:20:31 -04001157
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001158 def test_load_verify_locations_wrong_args(self):
1159 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001160 :py:obj:`Context.load_verify_locations` raises :py:obj:`TypeError` if
1161 called with the wrong number of arguments or with non-:py:obj:`str`
1162 arguments.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001163 """
1164 context = Context(TLSv1_METHOD)
1165 self.assertRaises(TypeError, context.load_verify_locations)
1166 self.assertRaises(TypeError, context.load_verify_locations, object())
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001167 self.assertRaises(
1168 TypeError, context.load_verify_locations, object(), object()
1169 )
1170 self.assertRaises(
1171 TypeError, context.load_verify_locations, None, None, None
1172 )
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001173
Hynek Schlawack734d3022015-09-05 19:19:32 +02001174 @pytest.mark.skipif(
1175 platform == "win32",
1176 reason="set_default_verify_paths appears not to work on Windows. "
Jean-Paul Calderone28fb8f02009-07-24 18:01:31 -04001177 "See LP#404343 and LP#404344."
Hynek Schlawack734d3022015-09-05 19:19:32 +02001178 )
1179 def test_set_default_verify_paths(self):
1180 """
1181 :py:obj:`Context.set_default_verify_paths` causes the
1182 platform-specific CA certificate locations to be used for
1183 verification purposes.
1184 """
1185 # Testing this requires a server with a certificate signed by one
1186 # of the CAs in the platform CA location. Getting one of those
1187 # costs money. Fortunately (or unfortunately, depending on your
1188 # perspective), it's easy to think of a public server on the
1189 # internet which has such a certificate. Connecting to the network
1190 # in a unit test is bad, but it's the only way I can think of to
1191 # really test this. -exarkun
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001192
Hynek Schlawack734d3022015-09-05 19:19:32 +02001193 # Arg, verisign.com doesn't speak anything newer than TLS 1.0
Hynek Schlawackbf887932015-10-21 17:13:47 +02001194 context = Context(SSLv23_METHOD)
Hynek Schlawack734d3022015-09-05 19:19:32 +02001195 context.set_default_verify_paths()
1196 context.set_verify(
1197 VERIFY_PEER,
1198 lambda conn, cert, errno, depth, preverify_ok: preverify_ok)
Jean-Paul Calderone1cb5d022008-09-07 20:58:50 -04001199
Hynek Schlawack734d3022015-09-05 19:19:32 +02001200 client = socket()
Hynek Schlawackbf887932015-10-21 17:13:47 +02001201 client.connect(("encrypted.google.com", 443))
Hynek Schlawack734d3022015-09-05 19:19:32 +02001202 clientSSL = Connection(context, client)
1203 clientSSL.set_connect_state()
1204 clientSSL.do_handshake()
1205 clientSSL.send(b"GET / HTTP/1.0\r\n\r\n")
1206 self.assertTrue(clientSSL.recv(1024))
Jean-Paul Calderone9eadb962008-09-07 21:20:44 -04001207
1208 def test_set_default_verify_paths_signature(self):
1209 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001210 :py:obj:`Context.set_default_verify_paths` takes no arguments and
1211 raises :py:obj:`TypeError` if given any.
Jean-Paul Calderone9eadb962008-09-07 21:20:44 -04001212 """
1213 context = Context(TLSv1_METHOD)
1214 self.assertRaises(TypeError, context.set_default_verify_paths, None)
1215 self.assertRaises(TypeError, context.set_default_verify_paths, 1)
1216 self.assertRaises(TypeError, context.set_default_verify_paths, "")
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05001217
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001218 def test_add_extra_chain_cert_invalid_cert(self):
1219 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001220 :py:obj:`Context.add_extra_chain_cert` raises :py:obj:`TypeError` if
1221 called with other than one argument or if called with an object which
1222 is not an instance of :py:obj:`X509`.
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001223 """
1224 context = Context(TLSv1_METHOD)
1225 self.assertRaises(TypeError, context.add_extra_chain_cert)
1226 self.assertRaises(TypeError, context.add_extra_chain_cert, object())
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001227 self.assertRaises(
1228 TypeError, context.add_extra_chain_cert, object(), object()
1229 )
Jean-Paul Calderone12608a82009-11-07 10:35:15 -05001230
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001231 def _handshake_test(self, serverContext, clientContext):
1232 """
1233 Verify that a client and server created with the given contexts can
1234 successfully handshake and communicate.
1235 """
1236 serverSocket, clientSocket = socket_pair()
1237
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001238 server = Connection(serverContext, serverSocket)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001239 server.set_accept_state()
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001240
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001241 client = Connection(clientContext, clientSocket)
1242 client.set_connect_state()
1243
1244 # Make them talk to each other.
1245 # self._interactInMemory(client, server)
1246 for i in range(3):
1247 for s in [client, server]:
1248 try:
1249 s.do_handshake()
1250 except WantReadError:
1251 pass
1252
Jean-Paul Calderone6a8cd112014-04-02 21:09:08 -04001253 def test_set_verify_callback_connection_argument(self):
1254 """
1255 The first argument passed to the verify callback is the
1256 :py:class:`Connection` instance for which verification is taking place.
1257 """
1258 serverContext = Context(TLSv1_METHOD)
1259 serverContext.use_privatekey(
1260 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1261 serverContext.use_certificate(
1262 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1263 serverConnection = Connection(serverContext, None)
1264
1265 class VerifyCallback(object):
1266 def callback(self, connection, *args):
1267 self.connection = connection
1268 return 1
1269
1270 verify = VerifyCallback()
1271 clientContext = Context(TLSv1_METHOD)
1272 clientContext.set_verify(VERIFY_PEER, verify.callback)
1273 clientConnection = Connection(clientContext, None)
1274 clientConnection.set_connect_state()
1275
1276 self._handshakeInMemory(clientConnection, serverConnection)
1277
1278 self.assertIdentical(verify.connection, clientConnection)
1279
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001280 def test_set_verify_callback_exception(self):
1281 """
1282 If the verify callback passed to :py:obj:`Context.set_verify` raises an
1283 exception, verification fails and the exception is propagated to the
1284 caller of :py:obj:`Connection.do_handshake`.
1285 """
1286 serverContext = Context(TLSv1_METHOD)
1287 serverContext.use_privatekey(
1288 load_privatekey(FILETYPE_PEM, cleartextPrivateKeyPEM))
1289 serverContext.use_certificate(
1290 load_certificate(FILETYPE_PEM, cleartextCertificatePEM))
1291
1292 clientContext = Context(TLSv1_METHOD)
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001293
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001294 def verify_callback(*args):
1295 raise Exception("silly verify failure")
1296 clientContext.set_verify(VERIFY_PEER, verify_callback)
1297
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01001298 with pytest.raises(Exception) as exc:
1299 self._handshake_test(serverContext, clientContext)
1300
1301 self.assertEqual("silly verify failure", str(exc.value))
Jean-Paul Calderone7e166fe2013-03-06 20:54:38 -08001302
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001303 def test_add_extra_chain_cert(self):
1304 """
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001305 :py:obj:`Context.add_extra_chain_cert` accepts an :py:obj:`X509`
1306 instance to add to the certificate chain.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001307
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001308 See :py:obj:`_create_certificate_chain` for the details of the
1309 certificate chain tested.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001310
1311 The chain is tested by starting a server with scert and connecting
1312 to it with a client which trusts cacert and requires verification to
1313 succeed.
1314 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001315 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001316 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1317
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001318 # Dump the CA certificate to a file because that's the only way to load
1319 # it as a trusted CA in the client context.
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001320 for cert, name in [(cacert, 'ca.pem'),
1321 (icert, 'i.pem'),
1322 (scert, 's.pem')]:
Hynek Schlawacke90680f2015-04-16 15:09:27 -04001323 with open(join(self.tmpdir, name), 'w') as f:
1324 f.write(dump_certificate(FILETYPE_PEM, cert).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001325
Hynek Schlawack1902c012015-04-16 15:06:41 -04001326 for key, name in [(cakey, 'ca.key'),
1327 (ikey, 'i.key'),
1328 (skey, 's.key')]:
Hynek Schlawacke90680f2015-04-16 15:09:27 -04001329 with open(join(self.tmpdir, name), 'w') as f:
1330 f.write(dump_privatekey(FILETYPE_PEM, key).decode('ascii'))
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001331
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001332 # Create the server context
1333 serverContext = Context(TLSv1_METHOD)
1334 serverContext.use_privatekey(skey)
1335 serverContext.use_certificate(scert)
Jean-Paul Calderone16cf03d2010-09-08 18:53:39 -04001336 # The client already has cacert, we only need to give them icert.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001337 serverContext.add_extra_chain_cert(icert)
1338
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04001339 # Create the client
1340 clientContext = Context(TLSv1_METHOD)
1341 clientContext.set_verify(
1342 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001343 clientContext.load_verify_locations(join(self.tmpdir, "ca.pem"))
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04001344
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001345 # Try it out.
1346 self._handshake_test(serverContext, clientContext)
1347
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001348 def _use_certificate_chain_file_test(self, certdir):
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001349 """
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001350 Verify that :py:obj:`Context.use_certificate_chain_file` reads a
1351 certificate chain from a specified file.
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001352
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001353 The chain is tested by starting a server with scert and connecting to
1354 it with a client which trusts cacert and requires verification to
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001355 succeed.
1356 """
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04001357 chain = _create_certificate_chain()
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001358 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
1359
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001360 makedirs(certdir)
1361
Jean-Paul Calderone05826732015-04-12 11:38:49 -04001362 chainFile = join_bytes_or_unicode(certdir, "chain.pem")
1363 caFile = join_bytes_or_unicode(certdir, "ca.pem")
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001364
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001365 # Write out the chain file.
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001366 with open(chainFile, 'wb') as fObj:
1367 # Most specific to least general.
1368 fObj.write(dump_certificate(FILETYPE_PEM, scert))
1369 fObj.write(dump_certificate(FILETYPE_PEM, icert))
1370 fObj.write(dump_certificate(FILETYPE_PEM, cacert))
1371
1372 with open(caFile, 'w') as fObj:
1373 fObj.write(dump_certificate(FILETYPE_PEM, cacert).decode('ascii'))
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001374
1375 serverContext = Context(TLSv1_METHOD)
1376 serverContext.use_certificate_chain_file(chainFile)
1377 serverContext.use_privatekey(skey)
1378
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001379 clientContext = Context(TLSv1_METHOD)
1380 clientContext.set_verify(
1381 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT, verify_cb)
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001382 clientContext.load_verify_locations(caFile)
Jean-Paul Calderonef4480622010-08-02 18:25:03 -04001383
1384 self._handshake_test(serverContext, clientContext)
1385
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001386 def test_use_certificate_chain_file_bytes(self):
1387 """
1388 ``Context.use_certificate_chain_file`` accepts the name of a file (as
1389 an instance of ``bytes``) to specify additional certificates to use to
1390 construct and verify a trust chain.
1391 """
1392 self._use_certificate_chain_file_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001393 self.mktemp() + NON_ASCII.encode(getfilesystemencoding())
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001394 )
1395
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001396 def test_use_certificate_chain_file_unicode(self):
1397 """
1398 ``Context.use_certificate_chain_file`` accepts the name of a file (as
1399 an instance of ``unicode``) to specify additional certificates to use
1400 to construct and verify a trust chain.
1401 """
1402 self._use_certificate_chain_file_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001403 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII
Jean-Paul Calderoneaac43a32015-04-12 09:51:21 -04001404 )
1405
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001406 def test_use_certificate_chain_file_wrong_args(self):
1407 """
1408 :py:obj:`Context.use_certificate_chain_file` raises :py:obj:`TypeError`
1409 if passed zero or more than one argument or when passed a non-byte
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001410 string single argument. It also raises :py:obj:`OpenSSL.SSL.Error`
1411 when passed a bad chain file name (for example, the name of a file
1412 which does not exist).
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001413 """
1414 context = Context(TLSv1_METHOD)
1415 self.assertRaises(TypeError, context.use_certificate_chain_file)
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001416 self.assertRaises(
1417 TypeError, context.use_certificate_chain_file, object()
1418 )
1419 self.assertRaises(
1420 TypeError, context.use_certificate_chain_file, b"foo", object()
1421 )
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001422
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001423 self.assertRaises(
1424 Error, context.use_certificate_chain_file, self.mktemp()
1425 )
Jean-Paul Calderone131052e2013-03-05 11:56:19 -08001426
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001427 def test_get_verify_mode_wrong_args(self):
1428 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001429 :py:obj:`Context.get_verify_mode` raises :py:obj:`TypeError` if called
1430 with any arguments.
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001431 """
1432 context = Context(TLSv1_METHOD)
1433 self.assertRaises(TypeError, context.get_verify_mode, None)
1434
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001435 def test_set_verify_mode(self):
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001436 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001437 :py:obj:`Context.get_verify_mode` returns the verify mode flags
1438 previously passed to :py:obj:`Context.set_verify`.
Jean-Paul Calderone0294e3d2010-09-09 18:17:48 -04001439 """
1440 context = Context(TLSv1_METHOD)
1441 self.assertEquals(context.get_verify_mode(), 0)
1442 context.set_verify(
1443 VERIFY_PEER | VERIFY_CLIENT_ONCE, lambda *args: None)
1444 self.assertEquals(
1445 context.get_verify_mode(), VERIFY_PEER | VERIFY_CLIENT_ONCE)
1446
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001447 @skip_if_py3
1448 def test_set_verify_mode_long(self):
1449 """
1450 On Python 2 :py:obj:`Context.set_verify_mode` accepts values of
1451 type :py:obj:`long` as well as :py:obj:`int`.
1452 """
1453 context = Context(TLSv1_METHOD)
1454 self.assertEquals(context.get_verify_mode(), 0)
1455 context.set_verify(
Hynek Schlawackb4ceed32015-09-05 20:55:19 +02001456 long(VERIFY_PEER | VERIFY_CLIENT_ONCE), lambda *args: None
1457 ) # pragma: nocover
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001458 self.assertEquals(
1459 context.get_verify_mode(), VERIFY_PEER | VERIFY_CLIENT_ONCE)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001460
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001461 def test_load_tmp_dh_wrong_args(self):
1462 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001463 :py:obj:`Context.load_tmp_dh` raises :py:obj:`TypeError` if called with
1464 the wrong number of arguments or with a non-:py:obj:`str` argument.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001465 """
1466 context = Context(TLSv1_METHOD)
1467 self.assertRaises(TypeError, context.load_tmp_dh)
1468 self.assertRaises(TypeError, context.load_tmp_dh, "foo", None)
1469 self.assertRaises(TypeError, context.load_tmp_dh, object())
1470
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001471 def test_load_tmp_dh_missing_file(self):
1472 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001473 :py:obj:`Context.load_tmp_dh` raises :py:obj:`OpenSSL.SSL.Error` if the
1474 specified file does not exist.
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001475 """
1476 context = Context(TLSv1_METHOD)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05001477 self.assertRaises(Error, context.load_tmp_dh, b"hello")
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001478
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001479 def _load_tmp_dh_test(self, dhfilename):
Jean-Paul Calderone4e0c43f2015-04-13 10:15:17 -04001480 """
1481 Verify that calling ``Context.load_tmp_dh`` with the given filename
1482 does not raise an exception.
1483 """
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001484 context = Context(TLSv1_METHOD)
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001485 with open(dhfilename, "w") as dhfile:
1486 dhfile.write(dhparam)
1487
Jean-Paul Calderone6ace4782010-09-09 18:43:40 -04001488 context.load_tmp_dh(dhfilename)
1489 # XXX What should I assert here? -exarkun
1490
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001491 def test_load_tmp_dh_bytes(self):
1492 """
1493 :py:obj:`Context.load_tmp_dh` loads Diffie-Hellman parameters from the
1494 specified file (given as ``bytes``).
1495 """
1496 self._load_tmp_dh_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001497 self.mktemp() + NON_ASCII.encode(getfilesystemencoding()),
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001498 )
1499
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001500 def test_load_tmp_dh_unicode(self):
1501 """
1502 :py:obj:`Context.load_tmp_dh` loads Diffie-Hellman parameters from the
1503 specified file (given as ``unicode``).
1504 """
1505 self._load_tmp_dh_test(
Hynek Schlawack4813c0e2015-04-16 13:38:01 -04001506 self.mktemp().decode(getfilesystemencoding()) + NON_ASCII,
Jean-Paul Calderone9e1c1dd2015-04-12 10:13:13 -04001507 )
1508
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001509 def test_set_tmp_ecdh(self):
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001510 """
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001511 :py:obj:`Context.set_tmp_ecdh` sets the elliptic curve for
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001512 Diffie-Hellman to the specified curve.
Andy Lutomirskif05a2732014-03-13 17:22:25 -07001513 """
1514 context = Context(TLSv1_METHOD)
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001515 for curve in get_elliptic_curves():
Hynek Schlawacka07fa8c2015-10-17 10:15:28 +02001516 if curve.name.startswith(u"Oakley-"):
Hynek Schlawack7408aff2015-10-17 09:51:16 +02001517 # Setting Oakley-EC2N-4 and Oakley-EC2N-3 adds
1518 # ('bignum routines', 'BN_mod_inverse', 'no inverse') to the
1519 # error queue on OpenSSL 1.0.2.
1520 continue
Jean-Paul Calderonec09fd582014-04-18 22:00:10 -04001521 # The only easily "assertable" thing is that it does not raise an
1522 # exception.
Jean-Paul Calderone3e4e3352014-04-19 09:28:28 -04001523 context.set_tmp_ecdh(curve)
Alex Gaynor12dc0842014-01-17 12:51:31 -06001524
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001525 def test_set_session_cache_mode_wrong_args(self):
1526 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001527 :py:obj:`Context.set_session_cache_mode` raises :py:obj:`TypeError` if
1528 called with other than one integer argument.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001529 """
1530 context = Context(TLSv1_METHOD)
1531 self.assertRaises(TypeError, context.set_session_cache_mode)
1532 self.assertRaises(TypeError, context.set_session_cache_mode, object())
1533
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001534 def test_get_session_cache_mode_wrong_args(self):
1535 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001536 :py:obj:`Context.get_session_cache_mode` raises :py:obj:`TypeError` if
1537 called with any arguments.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001538 """
1539 context = Context(TLSv1_METHOD)
1540 self.assertRaises(TypeError, context.get_session_cache_mode, 1)
1541
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001542 def test_session_cache_mode(self):
1543 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001544 :py:obj:`Context.set_session_cache_mode` specifies how sessions are
1545 cached. The setting can be retrieved via
1546 :py:obj:`Context.get_session_cache_mode`.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001547 """
1548 context = Context(TLSv1_METHOD)
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001549 context.set_session_cache_mode(SESS_CACHE_OFF)
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05001550 off = context.set_session_cache_mode(SESS_CACHE_BOTH)
1551 self.assertEqual(SESS_CACHE_OFF, off)
1552 self.assertEqual(SESS_CACHE_BOTH, context.get_session_cache_mode())
1553
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001554 @skip_if_py3
1555 def test_session_cache_mode_long(self):
1556 """
1557 On Python 2 :py:obj:`Context.set_session_cache_mode` accepts values
1558 of type :py:obj:`long` as well as :py:obj:`int`.
1559 """
1560 context = Context(TLSv1_METHOD)
1561 context.set_session_cache_mode(long(SESS_CACHE_BOTH))
1562 self.assertEqual(
1563 SESS_CACHE_BOTH, context.get_session_cache_mode())
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05001564
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001565 def test_get_cert_store(self):
1566 """
Hynek Schlawackde00dd52015-09-05 19:09:26 +02001567 :py:obj:`Context.get_cert_store` returns a :py:obj:`X509Store`
1568 instance.
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08001569 """
1570 context = Context(TLSv1_METHOD)
1571 store = context.get_cert_store()
1572 self.assertIsInstance(store, X509Store)
1573
1574
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001575class ServerNameCallbackTests(TestCase, _LoopbackMixin):
1576 """
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001577 Tests for :py:obj:`Context.set_tlsext_servername_callback` and its
1578 interaction with :py:obj:`Connection`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001579 """
1580 def test_wrong_args(self):
1581 """
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001582 :py:obj:`Context.set_tlsext_servername_callback` raises
1583 :py:obj:`TypeError` if called with other than one argument.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001584 """
1585 context = Context(TLSv1_METHOD)
1586 self.assertRaises(TypeError, context.set_tlsext_servername_callback)
1587 self.assertRaises(
1588 TypeError, context.set_tlsext_servername_callback, 1, 2)
1589
1590 def test_old_callback_forgotten(self):
1591 """
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001592 If :py:obj:`Context.set_tlsext_servername_callback` is used to specify
1593 a new callback, the one it replaces is dereferenced.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001594 """
1595 def callback(connection):
1596 pass
1597
1598 def replacement(connection):
1599 pass
1600
1601 context = Context(TLSv1_METHOD)
1602 context.set_tlsext_servername_callback(callback)
1603
1604 tracker = ref(callback)
1605 del callback
1606
1607 context.set_tlsext_servername_callback(replacement)
Jean-Paul Calderoned4033eb2014-01-11 08:21:46 -05001608
1609 # One run of the garbage collector happens to work on CPython. PyPy
1610 # doesn't collect the underlying object until a second run for whatever
1611 # reason. That's fine, it still demonstrates our code has properly
1612 # dropped the reference.
1613 collect()
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001614 collect()
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001615
1616 callback = tracker()
1617 if callback is not None:
1618 referrers = get_referrers(callback)
Jean-Paul Calderone7de39562014-01-11 08:17:59 -05001619 if len(referrers) > 1:
Jean-Paul Calderone4c1aacd2014-01-11 08:15:17 -05001620 self.fail("Some references remain: %r" % (referrers,))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001621
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001622 def test_no_servername(self):
1623 """
1624 When a client specifies no server name, the callback passed to
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001625 :py:obj:`Context.set_tlsext_servername_callback` is invoked and the
1626 result of :py:obj:`Connection.get_servername` is :py:obj:`None`.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001627 """
1628 args = []
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001629
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001630 def servername(conn):
1631 args.append((conn, conn.get_servername()))
1632 context = Context(TLSv1_METHOD)
1633 context.set_tlsext_servername_callback(servername)
1634
1635 # Lose our reference to it. The Context is responsible for keeping it
1636 # alive now.
1637 del servername
1638 collect()
1639
1640 # Necessary to actually accept the connection
1641 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001642 context.use_certificate(
1643 load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001644
1645 # Do a little connection to trigger the logic
1646 server = Connection(context, None)
1647 server.set_accept_state()
1648
1649 client = Connection(Context(TLSv1_METHOD), None)
1650 client.set_connect_state()
1651
1652 self._interactInMemory(server, client)
1653
1654 self.assertEqual([(server, None)], args)
1655
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001656 def test_servername(self):
1657 """
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001658 When a client specifies a server name in its hello message, the
1659 callback passed to :py:obj:`Contexts.set_tlsext_servername_callback` is
1660 invoked and the result of :py:obj:`Connection.get_servername` is that
1661 server name.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001662 """
1663 args = []
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001664
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001665 def servername(conn):
1666 args.append((conn, conn.get_servername()))
1667 context = Context(TLSv1_METHOD)
1668 context.set_tlsext_servername_callback(servername)
1669
1670 # Necessary to actually accept the connection
1671 context.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
Hynek Schlawackafeffd22015-09-05 20:08:16 +02001672 context.use_certificate(
1673 load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04001674
1675 # Do a little connection to trigger the logic
1676 server = Connection(context, None)
1677 server.set_accept_state()
1678
1679 client = Connection(Context(TLSv1_METHOD), None)
1680 client.set_connect_state()
1681 client.set_tlsext_host_name(b("foo1.example.com"))
1682
1683 self._interactInMemory(server, client)
1684
1685 self.assertEqual([(server, b("foo1.example.com"))], args)
1686
1687
Cory Benfield84a121e2014-03-31 20:30:25 +01001688class NextProtoNegotiationTests(TestCase, _LoopbackMixin):
1689 """
1690 Test for Next Protocol Negotiation in PyOpenSSL.
1691 """
Cory Benfieldba1820d2015-04-13 17:39:12 -04001692 if _lib.Cryptography_HAS_NEXTPROTONEG:
1693 def test_npn_success(self):
1694 """
1695 Tests that clients and servers that agree on the negotiated next
1696 protocol can correct establish a connection, and that the agreed
1697 protocol is reported by the connections.
1698 """
1699 advertise_args = []
1700 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001701
Cory Benfieldba1820d2015-04-13 17:39:12 -04001702 def advertise(conn):
1703 advertise_args.append((conn,))
1704 return [b'http/1.1', b'spdy/2']
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001705
Cory Benfieldba1820d2015-04-13 17:39:12 -04001706 def select(conn, options):
1707 select_args.append((conn, options))
1708 return b'spdy/2'
Cory Benfield84a121e2014-03-31 20:30:25 +01001709
Cory Benfieldba1820d2015-04-13 17:39:12 -04001710 server_context = Context(TLSv1_METHOD)
1711 server_context.set_npn_advertise_callback(advertise)
Cory Benfield84a121e2014-03-31 20:30:25 +01001712
Cory Benfieldba1820d2015-04-13 17:39:12 -04001713 client_context = Context(TLSv1_METHOD)
1714 client_context.set_npn_select_callback(select)
Cory Benfield84a121e2014-03-31 20:30:25 +01001715
Cory Benfieldba1820d2015-04-13 17:39:12 -04001716 # Necessary to actually accept the connection
1717 server_context.use_privatekey(
1718 load_privatekey(FILETYPE_PEM, server_key_pem))
1719 server_context.use_certificate(
1720 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield84a121e2014-03-31 20:30:25 +01001721
Cory Benfieldba1820d2015-04-13 17:39:12 -04001722 # Do a little connection to trigger the logic
1723 server = Connection(server_context, None)
1724 server.set_accept_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001725
Cory Benfieldba1820d2015-04-13 17:39:12 -04001726 client = Connection(client_context, None)
1727 client.set_connect_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001728
Cory Benfieldba1820d2015-04-13 17:39:12 -04001729 self._interactInMemory(server, client)
Cory Benfield84a121e2014-03-31 20:30:25 +01001730
Cory Benfieldba1820d2015-04-13 17:39:12 -04001731 self.assertEqual([(server,)], advertise_args)
1732 self.assertEqual([(client, [b'http/1.1', b'spdy/2'])], select_args)
Cory Benfield84a121e2014-03-31 20:30:25 +01001733
Cory Benfieldba1820d2015-04-13 17:39:12 -04001734 self.assertEqual(server.get_next_proto_negotiated(), b'spdy/2')
1735 self.assertEqual(client.get_next_proto_negotiated(), b'spdy/2')
Cory Benfield84a121e2014-03-31 20:30:25 +01001736
Cory Benfieldba1820d2015-04-13 17:39:12 -04001737 def test_npn_client_fail(self):
1738 """
1739 Tests that when clients and servers cannot agree on what protocol
1740 to use next that the TLS connection does not get established.
1741 """
1742 advertise_args = []
1743 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001744
Cory Benfieldba1820d2015-04-13 17:39:12 -04001745 def advertise(conn):
1746 advertise_args.append((conn,))
1747 return [b'http/1.1', b'spdy/2']
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001748
Cory Benfieldba1820d2015-04-13 17:39:12 -04001749 def select(conn, options):
1750 select_args.append((conn, options))
1751 return b''
Cory Benfield84a121e2014-03-31 20:30:25 +01001752
Cory Benfieldba1820d2015-04-13 17:39:12 -04001753 server_context = Context(TLSv1_METHOD)
1754 server_context.set_npn_advertise_callback(advertise)
Cory Benfield84a121e2014-03-31 20:30:25 +01001755
Cory Benfieldba1820d2015-04-13 17:39:12 -04001756 client_context = Context(TLSv1_METHOD)
1757 client_context.set_npn_select_callback(select)
Cory Benfield84a121e2014-03-31 20:30:25 +01001758
Cory Benfieldba1820d2015-04-13 17:39:12 -04001759 # Necessary to actually accept the connection
1760 server_context.use_privatekey(
1761 load_privatekey(FILETYPE_PEM, server_key_pem))
1762 server_context.use_certificate(
1763 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield84a121e2014-03-31 20:30:25 +01001764
Cory Benfieldba1820d2015-04-13 17:39:12 -04001765 # Do a little connection to trigger the logic
1766 server = Connection(server_context, None)
1767 server.set_accept_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001768
Cory Benfieldba1820d2015-04-13 17:39:12 -04001769 client = Connection(client_context, None)
1770 client.set_connect_state()
Cory Benfield84a121e2014-03-31 20:30:25 +01001771
Cory Benfieldba1820d2015-04-13 17:39:12 -04001772 # If the client doesn't return anything, the connection will fail.
1773 self.assertRaises(Error, self._interactInMemory, server, client)
Cory Benfield84a121e2014-03-31 20:30:25 +01001774
Cory Benfieldba1820d2015-04-13 17:39:12 -04001775 self.assertEqual([(server,)], advertise_args)
1776 self.assertEqual([(client, [b'http/1.1', b'spdy/2'])], select_args)
Cory Benfield84a121e2014-03-31 20:30:25 +01001777
Cory Benfieldba1820d2015-04-13 17:39:12 -04001778 def test_npn_select_error(self):
1779 """
1780 Test that we can handle exceptions in the select callback. If
1781 select fails it should be fatal to the connection.
1782 """
1783 advertise_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001784
Cory Benfieldba1820d2015-04-13 17:39:12 -04001785 def advertise(conn):
1786 advertise_args.append((conn,))
1787 return [b'http/1.1', b'spdy/2']
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001788
Cory Benfieldba1820d2015-04-13 17:39:12 -04001789 def select(conn, options):
1790 raise TypeError
Cory Benfield0ea76e72015-03-22 09:05:28 +00001791
Cory Benfieldba1820d2015-04-13 17:39:12 -04001792 server_context = Context(TLSv1_METHOD)
1793 server_context.set_npn_advertise_callback(advertise)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001794
Cory Benfieldba1820d2015-04-13 17:39:12 -04001795 client_context = Context(TLSv1_METHOD)
1796 client_context.set_npn_select_callback(select)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001797
Cory Benfieldba1820d2015-04-13 17:39:12 -04001798 # Necessary to actually accept the connection
1799 server_context.use_privatekey(
1800 load_privatekey(FILETYPE_PEM, server_key_pem))
1801 server_context.use_certificate(
1802 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield0ea76e72015-03-22 09:05:28 +00001803
Cory Benfieldba1820d2015-04-13 17:39:12 -04001804 # Do a little connection to trigger the logic
1805 server = Connection(server_context, None)
1806 server.set_accept_state()
Cory Benfield0ea76e72015-03-22 09:05:28 +00001807
Cory Benfieldba1820d2015-04-13 17:39:12 -04001808 client = Connection(client_context, None)
1809 client.set_connect_state()
Cory Benfield0ea76e72015-03-22 09:05:28 +00001810
Cory Benfieldba1820d2015-04-13 17:39:12 -04001811 # If the callback throws an exception it should be raised here.
1812 self.assertRaises(
1813 TypeError, self._interactInMemory, server, client
1814 )
1815 self.assertEqual([(server,)], advertise_args)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001816
Cory Benfieldba1820d2015-04-13 17:39:12 -04001817 def test_npn_advertise_error(self):
1818 """
1819 Test that we can handle exceptions in the advertise callback. If
1820 advertise fails no NPN is advertised to the client.
1821 """
1822 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001823
Cory Benfieldba1820d2015-04-13 17:39:12 -04001824 def advertise(conn):
1825 raise TypeError
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001826
Hynek Schlawackb4ceed32015-09-05 20:55:19 +02001827 def select(conn, options): # pragma: nocover
1828 """
1829 Assert later that no args are actually appended.
1830 """
Cory Benfieldba1820d2015-04-13 17:39:12 -04001831 select_args.append((conn, options))
1832 return b''
Cory Benfield0ea76e72015-03-22 09:05:28 +00001833
Cory Benfieldba1820d2015-04-13 17:39:12 -04001834 server_context = Context(TLSv1_METHOD)
1835 server_context.set_npn_advertise_callback(advertise)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001836
Cory Benfieldba1820d2015-04-13 17:39:12 -04001837 client_context = Context(TLSv1_METHOD)
1838 client_context.set_npn_select_callback(select)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001839
Cory Benfieldba1820d2015-04-13 17:39:12 -04001840 # Necessary to actually accept the connection
1841 server_context.use_privatekey(
1842 load_privatekey(FILETYPE_PEM, server_key_pem))
1843 server_context.use_certificate(
1844 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield0ea76e72015-03-22 09:05:28 +00001845
Cory Benfieldba1820d2015-04-13 17:39:12 -04001846 # Do a little connection to trigger the logic
1847 server = Connection(server_context, None)
1848 server.set_accept_state()
Cory Benfield0ea76e72015-03-22 09:05:28 +00001849
Cory Benfieldba1820d2015-04-13 17:39:12 -04001850 client = Connection(client_context, None)
1851 client.set_connect_state()
Cory Benfield0ea76e72015-03-22 09:05:28 +00001852
Cory Benfieldba1820d2015-04-13 17:39:12 -04001853 # If the client doesn't return anything, the connection will fail.
1854 self.assertRaises(
1855 TypeError, self._interactInMemory, server, client
1856 )
1857 self.assertEqual([], select_args)
1858
1859 else:
1860 # No NPN.
1861 def test_npn_not_implemented(self):
1862 # Test the context methods first.
1863 context = Context(TLSv1_METHOD)
1864 fail_methods = [
1865 context.set_npn_advertise_callback,
1866 context.set_npn_select_callback,
1867 ]
1868 for method in fail_methods:
1869 self.assertRaises(
1870 NotImplementedError, method, None
1871 )
1872
1873 # Now test a connection.
1874 conn = Connection(context)
1875 fail_methods = [
1876 conn.get_next_proto_negotiated,
1877 ]
1878 for method in fail_methods:
1879 self.assertRaises(NotImplementedError, method)
Cory Benfield0ea76e72015-03-22 09:05:28 +00001880
1881
Cory Benfield12eae892014-06-07 15:42:56 +01001882class ApplicationLayerProtoNegotiationTests(TestCase, _LoopbackMixin):
1883 """
1884 Tests for ALPN in PyOpenSSL.
1885 """
Cory Benfielde46fa842015-04-13 16:50:49 -04001886 # Skip tests on versions that don't support ALPN.
1887 if _lib.Cryptography_HAS_ALPN:
Cory Benfield12eae892014-06-07 15:42:56 +01001888
Cory Benfielde46fa842015-04-13 16:50:49 -04001889 def test_alpn_success(self):
1890 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04001891 Clients and servers that agree on the negotiated ALPN protocol can
1892 correct establish a connection, and the agreed protocol is reported
1893 by the connections.
Cory Benfielde46fa842015-04-13 16:50:49 -04001894 """
1895 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001896
Cory Benfielde46fa842015-04-13 16:50:49 -04001897 def select(conn, options):
1898 select_args.append((conn, options))
1899 return b'spdy/2'
Cory Benfield12eae892014-06-07 15:42:56 +01001900
Cory Benfielde46fa842015-04-13 16:50:49 -04001901 client_context = Context(TLSv1_METHOD)
1902 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfield12eae892014-06-07 15:42:56 +01001903
Cory Benfielde46fa842015-04-13 16:50:49 -04001904 server_context = Context(TLSv1_METHOD)
1905 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01001906
Cory Benfielde46fa842015-04-13 16:50:49 -04001907 # Necessary to actually accept the connection
1908 server_context.use_privatekey(
1909 load_privatekey(FILETYPE_PEM, server_key_pem))
1910 server_context.use_certificate(
1911 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield12eae892014-06-07 15:42:56 +01001912
Cory Benfielde46fa842015-04-13 16:50:49 -04001913 # Do a little connection to trigger the logic
1914 server = Connection(server_context, None)
1915 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001916
Cory Benfielde46fa842015-04-13 16:50:49 -04001917 client = Connection(client_context, None)
1918 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001919
Cory Benfielde46fa842015-04-13 16:50:49 -04001920 self._interactInMemory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001921
Cory Benfielde46fa842015-04-13 16:50:49 -04001922 self.assertEqual([(server, [b'http/1.1', b'spdy/2'])], select_args)
1923
1924 self.assertEqual(server.get_alpn_proto_negotiated(), b'spdy/2')
1925 self.assertEqual(client.get_alpn_proto_negotiated(), b'spdy/2')
Cory Benfield12eae892014-06-07 15:42:56 +01001926
Cory Benfielde46fa842015-04-13 16:50:49 -04001927 def test_alpn_set_on_connection(self):
1928 """
1929 The same as test_alpn_success, but setting the ALPN protocols on
1930 the connection rather than the context.
1931 """
1932 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001933
Cory Benfielde46fa842015-04-13 16:50:49 -04001934 def select(conn, options):
1935 select_args.append((conn, options))
1936 return b'spdy/2'
Cory Benfield12eae892014-06-07 15:42:56 +01001937
Cory Benfielde46fa842015-04-13 16:50:49 -04001938 # Setup the client context but don't set any ALPN protocols.
1939 client_context = Context(TLSv1_METHOD)
Cory Benfield12eae892014-06-07 15:42:56 +01001940
Cory Benfielde46fa842015-04-13 16:50:49 -04001941 server_context = Context(TLSv1_METHOD)
1942 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01001943
Cory Benfielde46fa842015-04-13 16:50:49 -04001944 # Necessary to actually accept the connection
1945 server_context.use_privatekey(
1946 load_privatekey(FILETYPE_PEM, server_key_pem))
1947 server_context.use_certificate(
1948 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield12eae892014-06-07 15:42:56 +01001949
Cory Benfielde46fa842015-04-13 16:50:49 -04001950 # Do a little connection to trigger the logic
1951 server = Connection(server_context, None)
1952 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001953
Cory Benfielde46fa842015-04-13 16:50:49 -04001954 # Set the ALPN protocols on the client connection.
1955 client = Connection(client_context, None)
1956 client.set_alpn_protos([b'http/1.1', b'spdy/2'])
1957 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001958
Cory Benfielde46fa842015-04-13 16:50:49 -04001959 self._interactInMemory(server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001960
Cory Benfielde46fa842015-04-13 16:50:49 -04001961 self.assertEqual([(server, [b'http/1.1', b'spdy/2'])], select_args)
Cory Benfield12eae892014-06-07 15:42:56 +01001962
Cory Benfielde46fa842015-04-13 16:50:49 -04001963 self.assertEqual(server.get_alpn_proto_negotiated(), b'spdy/2')
1964 self.assertEqual(client.get_alpn_proto_negotiated(), b'spdy/2')
Cory Benfield12eae892014-06-07 15:42:56 +01001965
Cory Benfielde46fa842015-04-13 16:50:49 -04001966 def test_alpn_server_fail(self):
1967 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04001968 When clients and servers cannot agree on what protocol to use next
1969 the TLS connection does not get established.
Cory Benfielde46fa842015-04-13 16:50:49 -04001970 """
1971 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02001972
Cory Benfielde46fa842015-04-13 16:50:49 -04001973 def select(conn, options):
1974 select_args.append((conn, options))
1975 return b''
Cory Benfield12eae892014-06-07 15:42:56 +01001976
Cory Benfielde46fa842015-04-13 16:50:49 -04001977 client_context = Context(TLSv1_METHOD)
1978 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfield12eae892014-06-07 15:42:56 +01001979
Cory Benfielde46fa842015-04-13 16:50:49 -04001980 server_context = Context(TLSv1_METHOD)
1981 server_context.set_alpn_select_callback(select)
Cory Benfield12eae892014-06-07 15:42:56 +01001982
Cory Benfielde46fa842015-04-13 16:50:49 -04001983 # Necessary to actually accept the connection
1984 server_context.use_privatekey(
1985 load_privatekey(FILETYPE_PEM, server_key_pem))
1986 server_context.use_certificate(
1987 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfield12eae892014-06-07 15:42:56 +01001988
Cory Benfielde46fa842015-04-13 16:50:49 -04001989 # Do a little connection to trigger the logic
1990 server = Connection(server_context, None)
1991 server.set_accept_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001992
Cory Benfielde46fa842015-04-13 16:50:49 -04001993 client = Connection(client_context, None)
1994 client.set_connect_state()
Cory Benfield12eae892014-06-07 15:42:56 +01001995
Cory Benfielde46fa842015-04-13 16:50:49 -04001996 # If the client doesn't return anything, the connection will fail.
1997 self.assertRaises(Error, self._interactInMemory, server, client)
Cory Benfield12eae892014-06-07 15:42:56 +01001998
Cory Benfielde46fa842015-04-13 16:50:49 -04001999 self.assertEqual([(server, [b'http/1.1', b'spdy/2'])], select_args)
Cory Benfield12eae892014-06-07 15:42:56 +01002000
Cory Benfielde46fa842015-04-13 16:50:49 -04002001 def test_alpn_no_server(self):
2002 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04002003 When clients and servers cannot agree on what protocol to use next
2004 because the server doesn't offer ALPN, no protocol is negotiated.
Cory Benfielde46fa842015-04-13 16:50:49 -04002005 """
2006 client_context = Context(TLSv1_METHOD)
2007 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfielde3d57152015-04-11 17:57:35 -04002008
Cory Benfielde46fa842015-04-13 16:50:49 -04002009 server_context = Context(TLSv1_METHOD)
Cory Benfielde3d57152015-04-11 17:57:35 -04002010
Cory Benfielde46fa842015-04-13 16:50:49 -04002011 # Necessary to actually accept the connection
2012 server_context.use_privatekey(
2013 load_privatekey(FILETYPE_PEM, server_key_pem))
2014 server_context.use_certificate(
2015 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfielde3d57152015-04-11 17:57:35 -04002016
Cory Benfielde46fa842015-04-13 16:50:49 -04002017 # Do a little connection to trigger the logic
2018 server = Connection(server_context, None)
2019 server.set_accept_state()
Cory Benfielde3d57152015-04-11 17:57:35 -04002020
Cory Benfielde46fa842015-04-13 16:50:49 -04002021 client = Connection(client_context, None)
2022 client.set_connect_state()
Cory Benfielde3d57152015-04-11 17:57:35 -04002023
Cory Benfielde46fa842015-04-13 16:50:49 -04002024 # Do the dance.
2025 self._interactInMemory(server, client)
Cory Benfielde3d57152015-04-11 17:57:35 -04002026
Cory Benfielde46fa842015-04-13 16:50:49 -04002027 self.assertEqual(client.get_alpn_proto_negotiated(), b'')
Cory Benfielde3d57152015-04-11 17:57:35 -04002028
Cory Benfielde46fa842015-04-13 16:50:49 -04002029 def test_alpn_callback_exception(self):
2030 """
Cory Benfieldbb8516b2015-04-13 18:12:53 -04002031 We can handle exceptions in the ALPN select callback.
Cory Benfielde46fa842015-04-13 16:50:49 -04002032 """
2033 select_args = []
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002034
Cory Benfielde46fa842015-04-13 16:50:49 -04002035 def select(conn, options):
2036 select_args.append((conn, options))
Cory Benfieldef401452015-04-13 18:17:36 -04002037 raise TypeError()
Cory Benfieldf1177e72015-04-12 09:11:49 -04002038
Cory Benfielde46fa842015-04-13 16:50:49 -04002039 client_context = Context(TLSv1_METHOD)
2040 client_context.set_alpn_protos([b'http/1.1', b'spdy/2'])
Cory Benfieldf1177e72015-04-12 09:11:49 -04002041
Cory Benfielde46fa842015-04-13 16:50:49 -04002042 server_context = Context(TLSv1_METHOD)
2043 server_context.set_alpn_select_callback(select)
Cory Benfieldf1177e72015-04-12 09:11:49 -04002044
Cory Benfielde46fa842015-04-13 16:50:49 -04002045 # Necessary to actually accept the connection
2046 server_context.use_privatekey(
2047 load_privatekey(FILETYPE_PEM, server_key_pem))
2048 server_context.use_certificate(
2049 load_certificate(FILETYPE_PEM, server_cert_pem))
Cory Benfieldf1177e72015-04-12 09:11:49 -04002050
Cory Benfielde46fa842015-04-13 16:50:49 -04002051 # Do a little connection to trigger the logic
2052 server = Connection(server_context, None)
2053 server.set_accept_state()
Cory Benfieldf1177e72015-04-12 09:11:49 -04002054
Cory Benfielde46fa842015-04-13 16:50:49 -04002055 client = Connection(client_context, None)
2056 client.set_connect_state()
Cory Benfieldf1177e72015-04-12 09:11:49 -04002057
Cory Benfielde46fa842015-04-13 16:50:49 -04002058 self.assertRaises(
2059 TypeError, self._interactInMemory, server, client
2060 )
2061 self.assertEqual([(server, [b'http/1.1', b'spdy/2'])], select_args)
Cory Benfieldf1177e72015-04-12 09:11:49 -04002062
Cory Benfield0f7b04c2015-04-13 17:51:12 -04002063 else:
2064 # No ALPN.
2065 def test_alpn_not_implemented(self):
Cory Benfieldef401452015-04-13 18:17:36 -04002066 """
2067 If ALPN is not in OpenSSL, we should raise NotImplementedError.
2068 """
Cory Benfield0f7b04c2015-04-13 17:51:12 -04002069 # Test the context methods first.
2070 context = Context(TLSv1_METHOD)
Cory Benfield307e9e62015-04-13 18:21:12 -04002071 self.assertRaises(
2072 NotImplementedError, context.set_alpn_protos, None
2073 )
2074 self.assertRaises(
2075 NotImplementedError, context.set_alpn_select_callback, None
2076 )
Cory Benfield0f7b04c2015-04-13 17:51:12 -04002077
2078 # Now test a connection.
2079 conn = Connection(context)
Cory Benfield307e9e62015-04-13 18:21:12 -04002080 self.assertRaises(
Alex Gaynor68417232015-09-04 07:56:29 -04002081 NotImplementedError, conn.set_alpn_protos, None
Cory Benfield307e9e62015-04-13 18:21:12 -04002082 )
Cory Benfield0f7b04c2015-04-13 17:51:12 -04002083
Cory Benfieldf1177e72015-04-12 09:11:49 -04002084
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05002085class SessionTests(TestCase):
2086 """
2087 Unit tests for :py:obj:`OpenSSL.SSL.Session`.
2088 """
2089 def test_construction(self):
2090 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002091 :py:class:`Session` can be constructed with no arguments, creating
2092 a new instance of that type.
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05002093 """
2094 new_session = Session()
2095 self.assertTrue(isinstance(new_session, Session))
2096
Jean-Paul Calderonee0fcf512012-02-13 09:10:15 -05002097 def test_construction_wrong_args(self):
2098 """
2099 If any arguments are passed to :py:class:`Session`, :py:obj:`TypeError`
2100 is raised.
2101 """
2102 self.assertRaises(TypeError, Session, 123)
2103 self.assertRaises(TypeError, Session, "hello")
2104 self.assertRaises(TypeError, Session, object())
2105
2106
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002107class ConnectionTests(TestCase, _LoopbackMixin):
Rick Deane15b1472009-07-09 15:53:42 -05002108 """
Hynek Schlawackaa861212016-03-13 13:53:48 +01002109 Unit tests for :class:`OpenSSL.SSL.Connection`.
Rick Deane15b1472009-07-09 15:53:42 -05002110 """
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04002111 # XXX get_peer_certificate -> None
2112 # XXX sock_shutdown
2113 # XXX master_key -> TypeError
2114 # XXX server_random -> TypeError
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04002115 # XXX connect -> TypeError
2116 # XXX connect_ex -> TypeError
2117 # XXX set_connect_state -> TypeError
2118 # XXX set_accept_state -> TypeError
Jean-Paul Calderone541eaf22010-09-09 18:55:08 -04002119 # XXX do_handshake -> TypeError
2120 # XXX bio_read -> TypeError
2121 # XXX recv -> TypeError
2122 # XXX send -> TypeError
2123 # XXX bio_write -> TypeError
2124
Rick Deane15b1472009-07-09 15:53:42 -05002125 def test_type(self):
2126 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002127 :py:obj:`Connection` and :py:obj:`ConnectionType` refer to the same
2128 type object and can be used to create instances of that type.
Rick Deane15b1472009-07-09 15:53:42 -05002129 """
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002130 self.assertIdentical(Connection, ConnectionType)
Rick Deane15b1472009-07-09 15:53:42 -05002131 ctx = Context(TLSv1_METHOD)
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002132 self.assertConsistentType(Connection, 'Connection', ctx, None)
Rick Deane15b1472009-07-09 15:53:42 -05002133
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002134 def test_get_context(self):
2135 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002136 :py:obj:`Connection.get_context` returns the :py:obj:`Context` instance
2137 used to construct the :py:obj:`Connection` instance.
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002138 """
2139 context = Context(TLSv1_METHOD)
2140 connection = Connection(context, None)
2141 self.assertIdentical(connection.get_context(), context)
2142
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002143 def test_get_context_wrong_args(self):
2144 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002145 :py:obj:`Connection.get_context` raises :py:obj:`TypeError` if called
2146 with any arguments.
Jean-Paul Calderone4fd058a2009-11-22 11:46:42 -05002147 """
2148 connection = Connection(Context(TLSv1_METHOD), None)
2149 self.assertRaises(TypeError, connection.get_context, None)
2150
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002151 def test_set_context_wrong_args(self):
2152 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002153 :py:obj:`Connection.set_context` raises :py:obj:`TypeError` if called
2154 with a non-:py:obj:`Context` instance argument or with any number of
2155 arguments other than 1.
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002156 """
2157 ctx = Context(TLSv1_METHOD)
2158 connection = Connection(ctx, None)
2159 self.assertRaises(TypeError, connection.set_context)
2160 self.assertRaises(TypeError, connection.set_context, object())
2161 self.assertRaises(TypeError, connection.set_context, "hello")
2162 self.assertRaises(TypeError, connection.set_context, 1)
2163 self.assertRaises(TypeError, connection.set_context, 1, 2)
2164 self.assertRaises(
2165 TypeError, connection.set_context, Context(TLSv1_METHOD), 2)
2166 self.assertIdentical(ctx, connection.get_context())
2167
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002168 def test_set_context(self):
2169 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002170 :py:obj:`Connection.set_context` specifies a new :py:obj:`Context`
2171 instance to be used for the connection.
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002172 """
2173 original = Context(SSLv23_METHOD)
2174 replacement = Context(TLSv1_METHOD)
2175 connection = Connection(original, None)
2176 connection.set_context(replacement)
2177 self.assertIdentical(replacement, connection.get_context())
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002178 # Lose our references to the contexts, just in case the Connection
2179 # isn't properly managing its own contributions to their reference
2180 # counts.
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002181 del original, replacement
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002182 collect()
2183
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002184 def test_set_tlsext_host_name_wrong_args(self):
2185 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002186 If :py:obj:`Connection.set_tlsext_host_name` is called with a non-byte
2187 string argument or a byte string with an embedded NUL or other than one
Jonathan Ballet648875f2011-07-16 14:14:58 +09002188 argument, :py:obj:`TypeError` is raised.
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002189 """
2190 conn = Connection(Context(TLSv1_METHOD), None)
2191 self.assertRaises(TypeError, conn.set_tlsext_host_name)
2192 self.assertRaises(TypeError, conn.set_tlsext_host_name, object())
2193 self.assertRaises(TypeError, conn.set_tlsext_host_name, 123, 456)
2194 self.assertRaises(
2195 TypeError, conn.set_tlsext_host_name, b("with\0null"))
2196
Abraham Martinc5484ba2015-03-25 15:33:05 +00002197 if PY3:
Jean-Paul Calderonec4cb6582011-05-26 18:47:00 -04002198 # On Python 3.x, don't accidentally implicitly convert from text.
2199 self.assertRaises(
2200 TypeError,
2201 conn.set_tlsext_host_name, b("example.com").decode("ascii"))
Jean-Paul Calderone95613b72011-05-25 22:30:21 -04002202
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04002203 def test_get_servername_wrong_args(self):
2204 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002205 :py:obj:`Connection.get_servername` raises :py:obj:`TypeError` if
2206 called with any arguments.
Jean-Paul Calderone871a4d82011-05-26 19:24:02 -04002207 """
2208 connection = Connection(Context(TLSv1_METHOD), None)
2209 self.assertRaises(TypeError, connection.get_servername, object())
2210 self.assertRaises(TypeError, connection.get_servername, 1)
2211 self.assertRaises(TypeError, connection.get_servername, "hello")
2212
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002213 def test_pending(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002214 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002215 :py:obj:`Connection.pending` returns the number of bytes available for
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002216 immediate read.
2217 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002218 connection = Connection(Context(TLSv1_METHOD), None)
2219 self.assertEquals(connection.pending(), 0)
2220
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002221 def test_pending_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002222 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002223 :py:obj:`Connection.pending` raises :py:obj:`TypeError` if called with
2224 any arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002225 """
Jean-Paul Calderone1d69a722010-07-29 09:05:53 -04002226 connection = Connection(Context(TLSv1_METHOD), None)
2227 self.assertRaises(TypeError, connection.pending, None)
2228
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002229 def test_peek(self):
2230 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002231 :py:obj:`Connection.recv` peeks into the connection if
2232 :py:obj:`socket.MSG_PEEK` is passed.
Maximilian Hils1d95dea2015-08-17 19:27:20 +02002233 """
2234 server, client = self._loopback()
2235 server.send(b('xy'))
2236 self.assertEqual(client.recv(2, MSG_PEEK), b('xy'))
2237 self.assertEqual(client.recv(2, MSG_PEEK), b('xy'))
2238 self.assertEqual(client.recv(2), b('xy'))
2239
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002240 def test_connect_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002241 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002242 :py:obj:`Connection.connect` raises :py:obj:`TypeError` if called with
2243 a non-address argument or with the wrong number of arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002244 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002245 connection = Connection(Context(TLSv1_METHOD), socket())
2246 self.assertRaises(TypeError, connection.connect, None)
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002247 self.assertRaises(TypeError, connection.connect)
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002248 self.assertRaises(
2249 TypeError, connection.connect, ("127.0.0.1", 1), None
2250 )
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002251
kjavfe508d62015-09-02 12:20:35 +01002252 def test_connection_undefined_attr(self):
2253 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002254 :py:obj:`Connection.connect` raises :py:obj:`TypeError` if called with
2255 a non-address argument or with the wrong number of arguments.
kjavfe508d62015-09-02 12:20:35 +01002256 """
Alex Gaynor1aabb2e2015-09-05 13:35:18 -04002257
kjavfe508d62015-09-02 12:20:35 +01002258 def attr_access_test(connection):
2259 return connection.an_attribute_which_is_not_defined
Alex Gaynor1aabb2e2015-09-05 13:35:18 -04002260
kjavfe508d62015-09-02 12:20:35 +01002261 connection = Connection(Context(TLSv1_METHOD), None)
2262 self.assertRaises(AttributeError, attr_access_test, connection)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002263
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002264 def test_connect_refused(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002265 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002266 :py:obj:`Connection.connect` raises :py:obj:`socket.error` if the
2267 underlying socket connect method raises it.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002268 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002269 client = socket()
2270 context = Context(TLSv1_METHOD)
2271 clientSSL = Connection(context, client)
Alex Gaynor122717b2015-09-05 14:14:18 -04002272 # pytest.raises here doesn't work because of a bug in py.test on Python
2273 # 2.6: https://github.com/pytest-dev/pytest/issues/988
Alex Gaynore69c2782015-09-05 14:07:48 -04002274 try:
Alex Gaynor1aabb2e2015-09-05 13:35:18 -04002275 clientSSL.connect(("127.0.0.1", 1))
Alex Gaynore69c2782015-09-05 14:07:48 -04002276 except error as e:
Alex Gaynor20a4c082015-09-05 14:24:15 -04002277 exc = e
2278 assert exc.args[0] == ECONNREFUSED
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002279
2280 def test_connect(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002281 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002282 :py:obj:`Connection.connect` establishes a connection to the specified
2283 address.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002284 """
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002285 port = socket()
2286 port.bind(('', 0))
2287 port.listen(3)
2288
2289 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002290 clientSSL.connect(('127.0.0.1', port.getsockname()[1]))
2291 # XXX An assertion? Or something?
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002292
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002293 @pytest.mark.skipif(
2294 platform == "darwin",
2295 reason="connect_ex sometimes causes a kernel panic on OS X 10.6.4"
2296 )
2297 def test_connect_ex(self):
2298 """
2299 If there is a connection error, :py:obj:`Connection.connect_ex`
2300 returns the errno instead of raising an exception.
2301 """
2302 port = socket()
2303 port.bind(('', 0))
2304 port.listen(3)
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002305
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002306 clientSSL = Connection(Context(TLSv1_METHOD), socket())
2307 clientSSL.setblocking(False)
2308 result = clientSSL.connect_ex(port.getsockname())
2309 expected = (EINPROGRESS, EWOULDBLOCK)
2310 self.assertTrue(
2311 result in expected, "%r not in %r" % (result, expected))
Jean-Paul Calderone55d91f42010-07-29 19:22:17 -04002312
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002313 def test_accept_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002314 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002315 :py:obj:`Connection.accept` raises :py:obj:`TypeError` if called with
2316 any arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002317 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002318 connection = Connection(Context(TLSv1_METHOD), socket())
2319 self.assertRaises(TypeError, connection.accept, None)
2320
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002321 def test_accept(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002322 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002323 :py:obj:`Connection.accept` accepts a pending connection attempt and
2324 returns a tuple of a new :py:obj:`Connection` (the accepted client) and
2325 the address the connection originated from.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002326 """
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002327 ctx = Context(TLSv1_METHOD)
2328 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2329 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002330 port = socket()
2331 portSSL = Connection(ctx, port)
2332 portSSL.bind(('', 0))
2333 portSSL.listen(3)
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002334
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002335 clientSSL = Connection(Context(TLSv1_METHOD), socket())
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002336
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002337 # Calling portSSL.getsockname() here to get the server IP address
2338 # sounds great, but frequently fails on Windows.
Jean-Paul Calderoneb6e0fd92010-09-19 09:22:13 -04002339 clientSSL.connect(('127.0.0.1', portSSL.getsockname()[1]))
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002340
Jean-Paul Calderone0bcb0e02010-07-29 09:49:59 -04002341 serverSSL, address = portSSL.accept()
2342
2343 self.assertTrue(isinstance(serverSSL, Connection))
2344 self.assertIdentical(serverSSL.get_context(), ctx)
2345 self.assertEquals(address, clientSSL.getsockname())
Jean-Paul Calderone8bdeba22010-07-29 09:45:07 -04002346
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002347 def test_shutdown_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002348 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002349 :py:obj:`Connection.shutdown` raises :py:obj:`TypeError` if called with
2350 the wrong number of arguments or with arguments other than integers.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002351 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002352 connection = Connection(Context(TLSv1_METHOD), None)
2353 self.assertRaises(TypeError, connection.shutdown, None)
Jean-Paul Calderone1d3e0222010-07-29 22:52:45 -04002354 self.assertRaises(TypeError, connection.get_shutdown, None)
2355 self.assertRaises(TypeError, connection.set_shutdown)
2356 self.assertRaises(TypeError, connection.set_shutdown, None)
2357 self.assertRaises(TypeError, connection.set_shutdown, 0, 1)
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002358
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002359 def test_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002360 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002361 :py:obj:`Connection.shutdown` performs an SSL-level connection
2362 shutdown.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002363 """
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002364 server, client = self._loopback()
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04002365 self.assertFalse(server.shutdown())
2366 self.assertEquals(server.get_shutdown(), SENT_SHUTDOWN)
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002367 self.assertRaises(ZeroReturnError, client.recv, 1024)
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04002368 self.assertEquals(client.get_shutdown(), RECEIVED_SHUTDOWN)
2369 client.shutdown()
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002370 self.assertEquals(
2371 client.get_shutdown(), SENT_SHUTDOWN | RECEIVED_SHUTDOWN
2372 )
Jean-Paul Calderonee4f6b472010-07-29 22:50:58 -04002373 self.assertRaises(ZeroReturnError, server.recv, 1024)
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002374 self.assertEquals(
2375 server.get_shutdown(), SENT_SHUTDOWN | RECEIVED_SHUTDOWN
2376 )
Jean-Paul Calderone9485f2c2010-07-29 22:38:42 -04002377
Paul Aurichc85e0862015-01-08 08:34:33 -08002378 def test_shutdown_closed(self):
2379 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002380 If the underlying socket is closed, :py:obj:`Connection.shutdown`
2381 propagates the write error from the low level write call.
Paul Aurichc85e0862015-01-08 08:34:33 -08002382 """
2383 server, client = self._loopback()
2384 server.sock_shutdown(2)
2385 exc = self.assertRaises(SysCallError, server.shutdown)
2386 if platform == "win32":
2387 self.assertEqual(exc.args[0], ESHUTDOWN)
2388 else:
2389 self.assertEqual(exc.args[0], EPIPE)
2390
Glyph89389472015-04-14 17:29:26 -04002391 def test_shutdown_truncated(self):
Glyph6064ec32015-04-14 16:38:22 -04002392 """
Glyph89389472015-04-14 17:29:26 -04002393 If the underlying connection is truncated, :obj:`Connection.shutdown`
2394 raises an :obj:`Error`.
Glyph6064ec32015-04-14 16:38:22 -04002395 """
Glyph89389472015-04-14 17:29:26 -04002396 server_ctx = Context(TLSv1_METHOD)
2397 client_ctx = Context(TLSv1_METHOD)
2398 server_ctx.use_privatekey(
2399 load_privatekey(FILETYPE_PEM, server_key_pem))
2400 server_ctx.use_certificate(
2401 load_certificate(FILETYPE_PEM, server_cert_pem))
2402 server = Connection(server_ctx, None)
2403 client = Connection(client_ctx, None)
2404 self._handshakeInMemory(client, server)
2405 self.assertEqual(server.shutdown(), False)
2406 self.assertRaises(WantReadError, server.shutdown)
2407 server.bio_shutdown()
Glyph6064ec32015-04-14 16:38:22 -04002408 self.assertRaises(Error, server.shutdown)
2409
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002410 def test_set_shutdown(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002411 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002412 :py:obj:`Connection.set_shutdown` sets the state of the SSL connection
2413 shutdown process.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002414 """
Jean-Paul Calderonec89eef22010-07-29 22:51:58 -04002415 connection = Connection(Context(TLSv1_METHOD), socket())
2416 connection.set_shutdown(RECEIVED_SHUTDOWN)
2417 self.assertEquals(connection.get_shutdown(), RECEIVED_SHUTDOWN)
2418
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002419 @skip_if_py3
2420 def test_set_shutdown_long(self):
2421 """
2422 On Python 2 :py:obj:`Connection.set_shutdown` accepts an argument
2423 of type :py:obj:`long` as well as :py:obj:`int`.
2424 """
2425 connection = Connection(Context(TLSv1_METHOD), socket())
2426 connection.set_shutdown(long(RECEIVED_SHUTDOWN))
2427 self.assertEquals(connection.get_shutdown(), RECEIVED_SHUTDOWN)
Jean-Paul Calderonef73a3cb2014-02-09 08:49:06 -05002428
kjavaf248592015-09-07 12:14:01 +01002429 def test_state_string(self):
2430 """
Hynek Schlawackb0274ce2015-10-16 19:56:26 +02002431 :meth:`Connection.state_string` verbosely describes the current
2432 state of the :class:`Connection`.
kjavaf248592015-09-07 12:14:01 +01002433 """
Hynek Schlawackb0274ce2015-10-16 19:56:26 +02002434 server, client = socket_pair()
kjavaf248592015-09-07 12:14:01 +01002435 server = self._loopbackServerFactory(server)
2436 client = self._loopbackClientFactory(client)
2437
Hynek Schlawackea94f2b2016-03-13 16:17:53 +01002438 assert b"before/accept initialization" == server.get_state_string()
2439 assert b"before/connect initialization" == client.get_state_string()
kjavaf248592015-09-07 12:14:01 +01002440
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002441 def test_app_data_wrong_args(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002442 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002443 :py:obj:`Connection.set_app_data` raises :py:obj:`TypeError` if called
2444 with other than one argument. :py:obj:`Connection.get_app_data` raises
2445 :py:obj:`TypeError` if called with any arguments.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002446 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002447 conn = Connection(Context(TLSv1_METHOD), None)
2448 self.assertRaises(TypeError, conn.get_app_data, None)
2449 self.assertRaises(TypeError, conn.set_app_data)
2450 self.assertRaises(TypeError, conn.set_app_data, None, None)
2451
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002452 def test_app_data(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002453 """
2454 Any object can be set as app data by passing it to
Jonathan Ballet648875f2011-07-16 14:14:58 +09002455 :py:obj:`Connection.set_app_data` and later retrieved with
2456 :py:obj:`Connection.get_app_data`.
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002457 """
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002458 conn = Connection(Context(TLSv1_METHOD), None)
Todd Chapman4f73e4f2015-08-27 11:26:43 -04002459 assert None is conn.get_app_data()
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002460 app_data = object()
2461 conn.set_app_data(app_data)
Todd Chapman4f73e4f2015-08-27 11:26:43 -04002462 assert conn.get_app_data() is app_data
Jean-Paul Calderone1bd8c792010-07-29 09:51:06 -04002463
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04002464 def test_makefile(self):
Jean-Paul Calderone93dba222010-09-08 22:59:37 -04002465 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002466 :py:obj:`Connection.makefile` is not implemented and calling that
2467 method raises :py:obj:`NotImplementedError`.
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(NotImplementedError, conn.makefile)
2471
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002472 def test_get_peer_cert_chain_wrong_args(self):
2473 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002474 :py:obj:`Connection.get_peer_cert_chain` raises :py:obj:`TypeError` if
2475 called with any arguments.
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002476 """
2477 conn = Connection(Context(TLSv1_METHOD), None)
2478 self.assertRaises(TypeError, conn.get_peer_cert_chain, 1)
2479 self.assertRaises(TypeError, conn.get_peer_cert_chain, "foo")
2480 self.assertRaises(TypeError, conn.get_peer_cert_chain, object())
2481 self.assertRaises(TypeError, conn.get_peer_cert_chain, [])
2482
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002483 def test_get_peer_cert_chain(self):
2484 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002485 :py:obj:`Connection.get_peer_cert_chain` returns a list of certificates
2486 which the connected server returned for the certification verification.
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002487 """
2488 chain = _create_certificate_chain()
2489 [(cakey, cacert), (ikey, icert), (skey, scert)] = chain
2490
2491 serverContext = Context(TLSv1_METHOD)
2492 serverContext.use_privatekey(skey)
2493 serverContext.use_certificate(scert)
2494 serverContext.add_extra_chain_cert(icert)
2495 serverContext.add_extra_chain_cert(cacert)
2496 server = Connection(serverContext, None)
2497 server.set_accept_state()
2498
2499 # Create the client
2500 clientContext = Context(TLSv1_METHOD)
2501 clientContext.set_verify(VERIFY_NONE, verify_cb)
2502 client = Connection(clientContext, None)
2503 client.set_connect_state()
2504
2505 self._interactInMemory(client, server)
2506
2507 chain = client.get_peer_cert_chain()
2508 self.assertEqual(len(chain), 3)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04002509 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002510 "Server Certificate", chain[0].get_subject().CN)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04002511 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002512 "Intermediate Certificate", chain[1].get_subject().CN)
Jean-Paul Calderonee33300c2011-05-19 21:44:38 -04002513 self.assertEqual(
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002514 "Authority Certificate", chain[2].get_subject().CN)
2515
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002516 def test_get_peer_cert_chain_none(self):
2517 """
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002518 :py:obj:`Connection.get_peer_cert_chain` returns :py:obj:`None` if the
2519 peer sends no certificate chain.
Jean-Paul Calderone24a42432011-05-19 22:21:18 -04002520 """
2521 ctx = Context(TLSv1_METHOD)
2522 ctx.use_privatekey(load_privatekey(FILETYPE_PEM, server_key_pem))
2523 ctx.use_certificate(load_certificate(FILETYPE_PEM, server_cert_pem))
2524 server = Connection(ctx, None)
2525 server.set_accept_state()
2526 client = Connection(Context(TLSv1_METHOD), None)
2527 client.set_connect_state()
2528 self._interactInMemory(client, server)
2529 self.assertIdentical(None, server.get_peer_cert_chain())
Jean-Paul Calderone20222ae2011-05-19 21:43:46 -04002530
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002531 def test_get_session_wrong_args(self):
2532 """
2533 :py:obj:`Connection.get_session` raises :py:obj:`TypeError` if called
2534 with any arguments.
2535 """
2536 ctx = Context(TLSv1_METHOD)
2537 server = Connection(ctx, None)
2538 self.assertRaises(TypeError, server.get_session, 123)
2539 self.assertRaises(TypeError, server.get_session, "hello")
2540 self.assertRaises(TypeError, server.get_session, object())
2541
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002542 def test_get_session_unconnected(self):
2543 """
2544 :py:obj:`Connection.get_session` returns :py:obj:`None` when used with
2545 an object which has not been connected.
2546 """
2547 ctx = Context(TLSv1_METHOD)
2548 server = Connection(ctx, None)
2549 session = server.get_session()
2550 self.assertIdentical(None, session)
2551
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002552 def test_server_get_session(self):
2553 """
2554 On the server side of a connection, :py:obj:`Connection.get_session`
2555 returns a :py:class:`Session` instance representing the SSL session for
2556 that connection.
2557 """
2558 server, client = self._loopback()
2559 session = server.get_session()
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08002560 self.assertIsInstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002561
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002562 def test_client_get_session(self):
2563 """
2564 On the client side of a connection, :py:obj:`Connection.get_session`
2565 returns a :py:class:`Session` instance representing the SSL session for
2566 that connection.
2567 """
2568 server, client = self._loopback()
2569 session = client.get_session()
Jean-Paul Calderonea63714c2013-03-05 17:02:26 -08002570 self.assertIsInstance(session, Session)
Jean-Paul Calderone64eaffc2012-02-13 11:53:49 -05002571
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002572 def test_set_session_wrong_args(self):
2573 """
Hynek Schlawackdddd1112015-09-05 21:12:30 +02002574 If called with an object that is not an instance of
2575 :py:class:`Session`, or with other than one argument,
2576 :py:obj:`Connection.set_session` raises :py:obj:`TypeError`.
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002577 """
2578 ctx = Context(TLSv1_METHOD)
2579 connection = Connection(ctx, None)
2580 self.assertRaises(TypeError, connection.set_session)
2581 self.assertRaises(TypeError, connection.set_session, 123)
2582 self.assertRaises(TypeError, connection.set_session, "hello")
2583 self.assertRaises(TypeError, connection.set_session, object())
2584 self.assertRaises(
2585 TypeError, connection.set_session, Session(), Session())
2586
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002587 def test_client_set_session(self):
2588 """
2589 :py:obj:`Connection.set_session`, when used prior to a connection being
2590 established, accepts a :py:class:`Session` instance and causes an
2591 attempt to re-use the session it represents when the SSL handshake is
2592 performed.
2593 """
2594 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2595 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
2596 ctx = Context(TLSv1_METHOD)
2597 ctx.use_privatekey(key)
2598 ctx.use_certificate(cert)
2599 ctx.set_session_id("unity-test")
2600
2601 def makeServer(socket):
2602 server = Connection(ctx, socket)
2603 server.set_accept_state()
2604 return server
2605
2606 originalServer, originalClient = self._loopback(
2607 serverFactory=makeServer)
2608 originalSession = originalClient.get_session()
2609
2610 def makeClient(socket):
2611 client = self._loopbackClientFactory(socket)
2612 client.set_session(originalSession)
2613 return client
2614 resumedServer, resumedClient = self._loopback(
2615 serverFactory=makeServer,
2616 clientFactory=makeClient)
2617
2618 # This is a proxy: in general, we have no access to any unique
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002619 # identifier for the session (new enough versions of OpenSSL expose
2620 # a hash which could be usable, but "new enough" is very, very new).
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002621 # Instead, exploit the fact that the master key is re-used if the
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002622 # session is re-used. As long as the master key for the two
2623 # connections is the same, the session was re-used!
Jean-Paul Calderonefef5c4b2012-02-14 16:31:52 -05002624 self.assertEqual(
2625 originalServer.master_key(), resumedServer.master_key())
2626
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002627 def test_set_session_wrong_method(self):
2628 """
Jean-Paul Calderone068cb592012-02-14 16:52:43 -05002629 If :py:obj:`Connection.set_session` is passed a :py:class:`Session`
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002630 instance associated with a context using a different SSL method than
2631 the :py:obj:`Connection` is using, a :py:class:`OpenSSL.SSL.Error` is
Jean-Paul Calderone068cb592012-02-14 16:52:43 -05002632 raised.
Jean-Paul Calderone5ea41492012-02-14 16:51:35 -05002633 """
2634 key = load_privatekey(FILETYPE_PEM, server_key_pem)
2635 cert = load_certificate(FILETYPE_PEM, server_cert_pem)
2636 ctx = Context(TLSv1_METHOD)
2637 ctx.use_privatekey(key)
2638 ctx.use_certificate(cert)
2639 ctx.set_session_id("unity-test")
2640
2641 def makeServer(socket):
2642 server = Connection(ctx, socket)
2643 server.set_accept_state()
2644 return server
2645
2646 originalServer, originalClient = self._loopback(
2647 serverFactory=makeServer)
2648 originalSession = originalClient.get_session()
2649
2650 def makeClient(socket):
2651 # Intentionally use a different, incompatible method here.
2652 client = Connection(Context(SSLv3_METHOD), socket)
2653 client.set_connect_state()
2654 client.set_session(originalSession)
2655 return client
2656
2657 self.assertRaises(
2658 Error,
2659 self._loopback, clientFactory=makeClient, serverFactory=makeServer)
2660
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002661 def test_wantWriteError(self):
2662 """
2663 :py:obj:`Connection` methods which generate output raise
2664 :py:obj:`OpenSSL.SSL.WantWriteError` if writing to the connection's BIO
2665 fail indicating a should-write state.
2666 """
2667 client_socket, server_socket = socket_pair()
2668 # Fill up the client's send buffer so Connection won't be able to write
Jean-Paul Calderonebbff8b92014-03-22 14:20:30 -04002669 # anything. Only write a single byte at a time so we can be sure we
2670 # completely fill the buffer. Even though the socket API is allowed to
2671 # signal a short write via its return value it seems this doesn't
2672 # always happen on all platforms (FreeBSD and OS X particular) for the
2673 # very last bit of available buffer space.
2674 msg = b"x"
2675 for i in range(1024 * 1024 * 4):
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07002676 try:
2677 client_socket.send(msg)
2678 except error as e:
2679 if e.errno == EWOULDBLOCK:
2680 break
2681 raise
2682 else:
2683 self.fail(
2684 "Failed to fill socket buffer, cannot test BIO want write")
2685
2686 ctx = Context(TLSv1_METHOD)
2687 conn = Connection(ctx, client_socket)
2688 # Client's speak first, so make it an SSL client
2689 conn.set_connect_state()
2690 self.assertRaises(WantWriteError, conn.do_handshake)
2691
2692 # XXX want_read
2693
Fedor Brunner416f4a12014-03-28 13:18:38 +01002694 def test_get_finished_before_connect(self):
Fedor Brunner5747b932014-03-05 14:22:34 +01002695 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002696 :py:obj:`Connection.get_finished` returns :py:obj:`None` before TLS
2697 handshake is completed.
Fedor Brunner5747b932014-03-05 14:22:34 +01002698 """
Fedor Brunner5747b932014-03-05 14:22:34 +01002699 ctx = Context(TLSv1_METHOD)
2700 connection = Connection(ctx, None)
2701 self.assertEqual(connection.get_finished(), None)
Fedor Brunner416f4a12014-03-28 13:18:38 +01002702
2703 def test_get_peer_finished_before_connect(self):
2704 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002705 :py:obj:`Connection.get_peer_finished` returns :py:obj:`None` before
2706 TLS handshake is completed.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002707 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002708 ctx = Context(TLSv1_METHOD)
2709 connection = Connection(ctx, None)
Fedor Brunner5747b932014-03-05 14:22:34 +01002710 self.assertEqual(connection.get_peer_finished(), None)
2711
Fedor Brunner416f4a12014-03-28 13:18:38 +01002712 def test_get_finished(self):
2713 """
2714 :py:obj:`Connection.get_finished` method returns the TLS Finished
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002715 message send from client, or server. Finished messages are send during
2716 TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002717 """
2718
Fedor Brunner5747b932014-03-05 14:22:34 +01002719 server, client = self._loopback()
2720
2721 self.assertNotEqual(server.get_finished(), None)
2722 self.assertTrue(len(server.get_finished()) > 0)
Fedor Brunner416f4a12014-03-28 13:18:38 +01002723
2724 def test_get_peer_finished(self):
2725 """
2726 :py:obj:`Connection.get_peer_finished` method returns the TLS Finished
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002727 message received from client, or server. Finished messages are send
2728 during TLS handshake.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002729 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002730 server, client = self._loopback()
2731
2732 self.assertNotEqual(server.get_peer_finished(), None)
Fedor Brunner5747b932014-03-05 14:22:34 +01002733 self.assertTrue(len(server.get_peer_finished()) > 0)
2734
Fedor Brunner416f4a12014-03-28 13:18:38 +01002735 def test_tls_finished_message_symmetry(self):
2736 """
Hynek Schlawackdddd1112015-09-05 21:12:30 +02002737 The TLS Finished message send by server must be the TLS Finished
2738 message received by client.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002739
Hynek Schlawackdddd1112015-09-05 21:12:30 +02002740 The TLS Finished message send by client must be the TLS Finished
2741 message received by server.
Fedor Brunner416f4a12014-03-28 13:18:38 +01002742 """
Fedor Brunner416f4a12014-03-28 13:18:38 +01002743 server, client = self._loopback()
2744
Fedor Brunner5747b932014-03-05 14:22:34 +01002745 self.assertEqual(server.get_finished(), client.get_peer_finished())
2746 self.assertEqual(client.get_finished(), server.get_peer_finished())
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002747
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002748 def test_get_cipher_name_before_connect(self):
2749 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002750 :py:obj:`Connection.get_cipher_name` returns :py:obj:`None` if no
2751 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002752 """
2753 ctx = Context(TLSv1_METHOD)
2754 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002755 self.assertIdentical(conn.get_cipher_name(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002756
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002757 def test_get_cipher_name(self):
2758 """
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002759 :py:obj:`Connection.get_cipher_name` returns a :py:class:`unicode`
2760 string giving the name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002761 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002762 server, client = self._loopback()
2763 server_cipher_name, client_cipher_name = \
2764 server.get_cipher_name(), client.get_cipher_name()
2765
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002766 self.assertIsInstance(server_cipher_name, text_type)
2767 self.assertIsInstance(client_cipher_name, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002768
2769 self.assertEqual(server_cipher_name, client_cipher_name)
2770
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002771 def test_get_cipher_version_before_connect(self):
2772 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002773 :py:obj:`Connection.get_cipher_version` returns :py:obj:`None` if no
2774 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002775 """
2776 ctx = Context(TLSv1_METHOD)
2777 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002778 self.assertIdentical(conn.get_cipher_version(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002779
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002780 def test_get_cipher_version(self):
2781 """
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002782 :py:obj:`Connection.get_cipher_version` returns a :py:class:`unicode`
2783 string giving the protocol name of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002784 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002785 server, client = self._loopback()
2786 server_cipher_version, client_cipher_version = \
2787 server.get_cipher_version(), client.get_cipher_version()
2788
Jean-Paul Calderone7f0ded42014-03-30 10:34:17 -04002789 self.assertIsInstance(server_cipher_version, text_type)
2790 self.assertIsInstance(client_cipher_version, text_type)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002791
2792 self.assertEqual(server_cipher_version, client_cipher_version)
2793
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002794 def test_get_cipher_bits_before_connect(self):
2795 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002796 :py:obj:`Connection.get_cipher_bits` returns :py:obj:`None` if no
2797 connection has been established.
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002798 """
2799 ctx = Context(TLSv1_METHOD)
2800 conn = Connection(ctx, None)
Jean-Paul Calderone069e2bf2014-03-29 18:21:58 -04002801 self.assertIdentical(conn.get_cipher_bits(), None)
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002802
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002803 def test_get_cipher_bits(self):
2804 """
Jean-Paul Calderone5b05b482014-03-30 11:28:54 -04002805 :py:obj:`Connection.get_cipher_bits` returns the number of secret bits
2806 of the currently used cipher.
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002807 """
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002808 server, client = self._loopback()
2809 server_cipher_bits, client_cipher_bits = \
2810 server.get_cipher_bits(), client.get_cipher_bits()
2811
Fedor Brunner2cffdbc2014-03-10 10:35:23 +01002812 self.assertIsInstance(server_cipher_bits, int)
2813 self.assertIsInstance(client_cipher_bits, int)
Fedor Brunnerd95014a2014-03-03 17:34:41 +01002814
2815 self.assertEqual(server_cipher_bits, client_cipher_bits)
Jean-Paul Calderone68649052009-07-17 21:14:27 -04002816
Jim Shaverabff1882015-05-27 09:15:55 -04002817 def test_get_protocol_version_name(self):
2818 """
2819 :py:obj:`Connection.get_protocol_version_name()` returns a string
2820 giving the protocol version of the current connection.
2821 """
2822 server, client = self._loopback()
2823 client_protocol_version_name = client.get_protocol_version_name()
2824 server_protocol_version_name = server.get_protocol_version_name()
2825
Jim Shaver58d25732015-05-28 11:52:32 -04002826 self.assertIsInstance(server_protocol_version_name, text_type)
2827 self.assertIsInstance(client_protocol_version_name, text_type)
Jim Shaverabff1882015-05-27 09:15:55 -04002828
Hynek Schlawack97cf1a82015-09-05 20:40:19 +02002829 self.assertEqual(
2830 server_protocol_version_name, client_protocol_version_name
2831 )
Jim Shaverabff1882015-05-27 09:15:55 -04002832
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002833 def test_get_protocol_version(self):
2834 """
Alex Gaynor43307782015-09-04 09:05:45 -04002835 :py:obj:`Connection.get_protocol_version()` returns an integer
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002836 giving the protocol version of the current connection.
2837 """
2838 server, client = self._loopback()
Jim Shaver85a4dff2015-04-27 17:42:46 -04002839 client_protocol_version = client.get_protocol_version()
2840 server_protocol_version = server.get_protocol_version()
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002841
Jim Shaverabff1882015-05-27 09:15:55 -04002842 self.assertIsInstance(server_protocol_version, int)
2843 self.assertIsInstance(client_protocol_version, int)
Richard J. Moore5d85fca2015-01-11 17:04:43 +00002844
2845 self.assertEqual(server_protocol_version, client_protocol_version)
2846
Jean-Paul Calderonedbd76272014-03-29 18:09:40 -04002847
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002848class ConnectionGetCipherListTests(TestCase):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002849 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002850 Tests for :py:obj:`Connection.get_cipher_list`.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002851 """
Jean-Paul Calderone54a2bc02010-09-09 17:52:38 -04002852 def test_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002853 """
Hynek Schlawackdddd1112015-09-05 21:12:30 +02002854 :py:obj:`Connection.get_cipher_list` raises :py:obj:`TypeError` if
2855 called with any arguments.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002856 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002857 connection = Connection(Context(TLSv1_METHOD), None)
2858 self.assertRaises(TypeError, connection.get_cipher_list, None)
2859
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002860 def test_result(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002861 """
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05002862 :py:obj:`Connection.get_cipher_list` returns a :py:obj:`list` of
2863 :py:obj:`bytes` giving the names of the ciphers which might be used.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04002864 """
Jean-Paul Calderonef135e622010-07-28 19:14:16 -04002865 connection = Connection(Context(TLSv1_METHOD), None)
2866 ciphers = connection.get_cipher_list()
2867 self.assertTrue(isinstance(ciphers, list))
2868 for cipher in ciphers:
2869 self.assertTrue(isinstance(cipher, str))
2870
2871
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002872class ConnectionSendTests(TestCase, _LoopbackMixin):
2873 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09002874 Tests for :py:obj:`Connection.send`
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002875 """
2876 def test_wrong_args(self):
2877 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002878 When called with arguments other than string argument for its first
2879 parameter or more than two arguments, :py:obj:`Connection.send` raises
2880 :py:obj:`TypeError`.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002881 """
2882 connection = Connection(Context(TLSv1_METHOD), None)
Jean-Paul Calderone77fa2602011-01-05 18:23:39 -05002883 self.assertRaises(TypeError, connection.send)
2884 self.assertRaises(TypeError, connection.send, object())
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05002885 self.assertRaises(TypeError, connection.send, "foo", object(), "bar")
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002886
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002887 def test_short_bytes(self):
2888 """
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002889 When passed a short byte string, :py:obj:`Connection.send` transmits
2890 all of it and returns the number of bytes sent.
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002891 """
2892 server, client = self._loopback()
2893 count = server.send(b('xy'))
2894 self.assertEquals(count, 2)
2895 self.assertEquals(client.recv(2), b('xy'))
2896
Abraham Martinef063482015-03-25 14:06:24 +00002897 def test_text(self):
2898 """
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002899 When passed a text, :py:obj:`Connection.send` transmits all of it and
2900 returns the number of bytes sent. It also raises a DeprecationWarning.
Abraham Martinef063482015-03-25 14:06:24 +00002901 """
2902 server, client = self._loopback()
2903 with catch_warnings(record=True) as w:
2904 simplefilter("always")
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002905 count = server.send(b"xy".decode("ascii"))
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002906 self.assertEqual(
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04002907 "{0} for buf is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002908 WARNING_TYPE_EXPECTED
2909 ),
2910 str(w[-1].message)
2911 )
2912 self.assertIs(w[-1].category, DeprecationWarning)
Abraham Martinef063482015-03-25 14:06:24 +00002913 self.assertEquals(count, 2)
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04002914 self.assertEquals(client.recv(2), b"xy")
Abraham Martinef063482015-03-25 14:06:24 +00002915
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002916 @skip_if_py26
2917 def test_short_memoryview(self):
2918 """
2919 When passed a memoryview onto a small number of bytes,
2920 :py:obj:`Connection.send` transmits all of them and returns the number
2921 of bytes sent.
2922 """
2923 server, client = self._loopback()
2924 count = server.send(memoryview(b('xy')))
2925 self.assertEquals(count, 2)
2926 self.assertEquals(client.recv(2), b('xy'))
Jean-Paul Calderone9cbbe262011-01-05 14:53:43 -05002927
Hynek Schlawack8e94f1b2015-09-05 21:31:00 +02002928 @skip_if_py3
Hynek Schlawackf8979a52015-09-05 21:25:25 +02002929 def test_short_buffer(self):
2930 """
2931 When passed a buffer containing a small number of bytes,
2932 :py:obj:`Connection.send` transmits all of them and returns the number
2933 of bytes sent.
2934 """
2935 server, client = self._loopback()
2936 count = server.send(buffer(b('xy')))
2937 self.assertEquals(count, 2)
2938 self.assertEquals(client.recv(2), b('xy'))
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02002939
Jean-Paul Calderone691e6c92011-01-21 22:04:35 -05002940
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002941def _make_memoryview(size):
2942 """
2943 Create a new ``memoryview`` wrapped around a ``bytearray`` of the given
2944 size.
2945 """
2946 return memoryview(bytearray(size))
2947
2948
Cory Benfield62d10332014-06-15 10:03:41 +01002949class ConnectionRecvIntoTests(TestCase, _LoopbackMixin):
2950 """
2951 Tests for :py:obj:`Connection.recv_into`
2952 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002953 def _no_length_test(self, factory):
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04002954 """
2955 Assert that when the given buffer is passed to
2956 ``Connection.recv_into``, whatever bytes are available to be received
2957 that fit into that buffer are written into that buffer.
2958 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002959 output_buffer = factory(5)
2960
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04002961 server, client = self._loopback()
2962 server.send(b('xy'))
2963
Jean-Paul Calderone320af1e2015-03-15 17:20:13 -04002964 self.assertEqual(client.recv_into(output_buffer), 2)
2965 self.assertEqual(output_buffer, bytearray(b('xy\x00\x00\x00')))
Jean-Paul Calderone332a85e2015-03-15 17:02:40 -04002966
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002967 def test_bytearray_no_length(self):
Cory Benfield62d10332014-06-15 10:03:41 +01002968 """
Jean-Paul Calderone61559d82015-03-15 17:04:50 -04002969 :py:obj:`Connection.recv_into` can be passed a ``bytearray`` instance
2970 and data in the receive buffer is written to it.
Cory Benfield62d10332014-06-15 10:03:41 +01002971 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002972 self._no_length_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01002973
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002974 def _respects_length_test(self, factory):
Cory Benfield62d10332014-06-15 10:03:41 +01002975 """
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002976 Assert that when the given buffer is passed to ``Connection.recv_into``
2977 along with a value for ``nbytes`` that is less than the size of that
2978 buffer, only ``nbytes`` bytes are written into the buffer.
Cory Benfield62d10332014-06-15 10:03:41 +01002979 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002980 output_buffer = factory(10)
2981
Cory Benfield62d10332014-06-15 10:03:41 +01002982 server, client = self._loopback()
2983 server.send(b('abcdefghij'))
Cory Benfield62d10332014-06-15 10:03:41 +01002984
Jean-Paul Calderone320af1e2015-03-15 17:20:13 -04002985 self.assertEqual(client.recv_into(output_buffer, 5), 5)
2986 self.assertEqual(
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002987 output_buffer, bytearray(b('abcde\x00\x00\x00\x00\x00'))
2988 )
2989
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04002990 def test_bytearray_respects_length(self):
Jean-Paul Calderonec295a2f2015-03-15 17:11:18 -04002991 """
2992 When called with a ``bytearray`` instance,
2993 :py:obj:`Connection.recv_into` respects the ``nbytes`` parameter and
2994 doesn't copy in more than that number of bytes.
2995 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002996 self._respects_length_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01002997
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04002998 def _doesnt_overfill_test(self, factory):
Cory Benfield62d10332014-06-15 10:03:41 +01002999 """
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04003000 Assert that if there are more bytes available to be read from the
3001 receive buffer than would fit into the buffer passed to
3002 :py:obj:`Connection.recv_into`, only as many as fit are written into
3003 it.
Cory Benfield62d10332014-06-15 10:03:41 +01003004 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003005 output_buffer = factory(5)
3006
Cory Benfield62d10332014-06-15 10:03:41 +01003007 server, client = self._loopback()
3008 server.send(b('abcdefghij'))
Cory Benfield62d10332014-06-15 10:03:41 +01003009
Jean-Paul Calderone320af1e2015-03-15 17:20:13 -04003010 self.assertEqual(client.recv_into(output_buffer), 5)
3011 self.assertEqual(output_buffer, bytearray(b('abcde')))
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04003012 rest = client.recv(5)
3013 self.assertEqual(b('fghij'), rest)
3014
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04003015 def test_bytearray_doesnt_overfill(self):
Jean-Paul Calderone2b41ad32015-03-15 17:19:39 -04003016 """
3017 When called with a ``bytearray`` instance,
3018 :py:obj:`Connection.recv_into` respects the size of the array and
3019 doesn't write more bytes into it than will fit.
3020 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003021 self._doesnt_overfill_test(bytearray)
Cory Benfield62d10332014-06-15 10:03:41 +01003022
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003023 def _really_doesnt_overfill_test(self, factory):
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003024 """
3025 Assert that if the value given by ``nbytes`` is greater than the actual
3026 size of the output buffer passed to :py:obj:`Connection.recv_into`, the
3027 behavior is as if no value was given for ``nbytes`` at all.
3028 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003029 output_buffer = factory(5)
3030
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003031 server, client = self._loopback()
3032 server.send(b('abcdefghij'))
3033
3034 self.assertEqual(client.recv_into(output_buffer, 50), 5)
3035 self.assertEqual(output_buffer, bytearray(b('abcde')))
3036 rest = client.recv(5)
3037 self.assertEqual(b('fghij'), rest)
3038
Jean-Paul Calderoned335b272015-03-15 17:26:38 -04003039 def test_bytearray_really_doesnt_overfill(self):
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003040 """
3041 When called with a ``bytearray`` instance and an ``nbytes`` value that
3042 is too large, :py:obj:`Connection.recv_into` respects the size of the
3043 array and not the ``nbytes`` value and doesn't write more bytes into
3044 the buffer than will fit.
3045 """
Jean-Paul Calderone6c840102015-03-15 17:32:15 -04003046 self._doesnt_overfill_test(bytearray)
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003047
Maximilian Hils1d95dea2015-08-17 19:27:20 +02003048 def test_peek(self):
3049
3050 server, client = self._loopback()
3051 server.send(b('xy'))
3052
3053 for _ in range(2):
3054 output_buffer = bytearray(5)
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003055 self.assertEqual(
3056 client.recv_into(output_buffer, flags=MSG_PEEK), 2)
Maximilian Hils1d95dea2015-08-17 19:27:20 +02003057 self.assertEqual(output_buffer, bytearray(b('xy\x00\x00\x00')))
3058
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003059 @skip_if_py26
3060 def test_memoryview_no_length(self):
3061 """
3062 :py:obj:`Connection.recv_into` can be passed a ``memoryview``
3063 instance and data in the receive buffer is written to it.
3064 """
3065 self._no_length_test(_make_memoryview)
Maximilian Hils1d95dea2015-08-17 19:27:20 +02003066
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003067 @skip_if_py26
3068 def test_memoryview_respects_length(self):
3069 """
3070 When called with a ``memoryview`` instance,
3071 :py:obj:`Connection.recv_into` respects the ``nbytes`` parameter
3072 and doesn't copy more than that number of bytes in.
3073 """
3074 self._respects_length_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01003075
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003076 @skip_if_py26
3077 def test_memoryview_doesnt_overfill(self):
3078 """
3079 When called with a ``memoryview`` instance,
3080 :py:obj:`Connection.recv_into` respects the size of the array and
3081 doesn't write more bytes into it than will fit.
3082 """
3083 self._doesnt_overfill_test(_make_memoryview)
Cory Benfield62d10332014-06-15 10:03:41 +01003084
Hynek Schlawackf8979a52015-09-05 21:25:25 +02003085 @skip_if_py26
3086 def test_memoryview_really_doesnt_overfill(self):
3087 """
3088 When called with a ``memoryview`` instance and an ``nbytes`` value
3089 that is too large, :py:obj:`Connection.recv_into` respects the size
3090 of the array and not the ``nbytes`` value and doesn't write more
3091 bytes into the buffer than will fit.
3092 """
3093 self._doesnt_overfill_test(_make_memoryview)
Jean-Paul Calderone4bec59a2015-03-15 17:25:57 -04003094
Cory Benfield62d10332014-06-15 10:03:41 +01003095
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003096class ConnectionSendallTests(TestCase, _LoopbackMixin):
3097 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003098 Tests for :py:obj:`Connection.sendall`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003099 """
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003100 def test_wrong_args(self):
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003101 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003102 When called with arguments other than a string argument for its first
3103 parameter or with more than two arguments, :py:obj:`Connection.sendall`
3104 raises :py:obj:`TypeError`.
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003105 """
3106 connection = Connection(Context(TLSv1_METHOD), None)
3107 self.assertRaises(TypeError, connection.sendall)
3108 self.assertRaises(TypeError, connection.sendall, object())
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003109 self.assertRaises(
3110 TypeError, connection.sendall, "foo", object(), "bar")
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003111
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003112 def test_short(self):
3113 """
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003114 :py:obj:`Connection.sendall` transmits all of the bytes in the string
3115 passed to it.
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003116 """
3117 server, client = self._loopback()
Jean-Paul Calderonea9868832010-08-22 21:38:34 -04003118 server.sendall(b('x'))
3119 self.assertEquals(client.recv(1), b('x'))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003120
Abraham Martinef063482015-03-25 14:06:24 +00003121 def test_text(self):
3122 """
Jean-Paul Calderone93477422015-04-13 20:38:57 -04003123 :py:obj:`Connection.sendall` transmits all the content in the string
3124 passed to it raising a DeprecationWarning in case of this being a text.
Abraham Martinef063482015-03-25 14:06:24 +00003125 """
3126 server, client = self._loopback()
3127 with catch_warnings(record=True) as w:
3128 simplefilter("always")
Jean-Paul Calderone8dc37a12015-03-29 08:16:52 -04003129 server.sendall(b"x".decode("ascii"))
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04003130 self.assertEqual(
Jean-Paul Calderone13a0e652015-03-29 07:58:51 -04003131 "{0} for buf is no longer accepted, use bytes".format(
Jean-Paul Calderone6462b072015-03-29 07:03:11 -04003132 WARNING_TYPE_EXPECTED
3133 ),
3134 str(w[-1].message)
3135 )
3136 self.assertIs(w[-1].category, DeprecationWarning)
3137 self.assertEquals(client.recv(1), b"x")
Abraham Martinef063482015-03-25 14:06:24 +00003138
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003139 @skip_if_py26
3140 def test_short_memoryview(self):
3141 """
3142 When passed a memoryview onto a small number of bytes,
3143 :py:obj:`Connection.sendall` transmits all of them.
3144 """
3145 server, client = self._loopback()
3146 server.sendall(memoryview(b('x')))
3147 self.assertEquals(client.recv(1), b('x'))
Abraham Martinef063482015-03-25 14:06:24 +00003148
Hynek Schlawacke2f8a092015-09-05 21:39:50 +02003149 @skip_if_py3
3150 def test_short_buffers(self):
3151 """
3152 When passed a buffer containing a small number of bytes,
3153 :py:obj:`Connection.sendall` transmits all of them.
3154 """
3155 server, client = self._loopback()
3156 server.sendall(buffer(b('x')))
3157 self.assertEquals(client.recv(1), b('x'))
Markus Unterwaditzer8e41d022014-04-19 12:27:11 +02003158
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003159 def test_long(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003160 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003161 :py:obj:`Connection.sendall` transmits all of the bytes in the string
3162 passed to it even if this requires multiple calls of an underlying
3163 write function.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003164 """
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003165 server, client = self._loopback()
Jean-Paul Calderone6241c702010-09-16 19:59:24 -04003166 # Should be enough, underlying SSL_write should only do 16k at a time.
Hynek Schlawack35618382015-09-05 21:54:25 +02003167 # On Windows, after 32k of bytes the write will block (forever
3168 # - because no one is yet reading).
Jean-Paul Calderone9e4c1352010-09-19 09:34:43 -04003169 message = b('x') * (1024 * 32 - 1) + b('y')
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003170 server.sendall(message)
3171 accum = []
3172 received = 0
3173 while received < len(message):
Jean-Paul Calderoneb1f7f5f2010-08-22 21:40:52 -04003174 data = client.recv(1024)
3175 accum.append(data)
3176 received += len(data)
Jean-Paul Calderonef4047852010-09-19 09:45:57 -04003177 self.assertEquals(message, b('').join(accum))
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003178
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003179 def test_closed(self):
3180 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003181 If the underlying socket is closed, :py:obj:`Connection.sendall`
3182 propagates the write error from the low level write call.
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003183 """
3184 server, client = self._loopback()
Jean-Paul Calderone05d43e82010-09-24 18:01:36 -04003185 server.sock_shutdown(2)
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003186 exc = self.assertRaises(SysCallError, server.sendall, b"hello, world")
Konstantinos Koukopoulos541150d2014-01-31 01:00:19 +02003187 if platform == "win32":
3188 self.assertEqual(exc.args[0], ESHUTDOWN)
3189 else:
3190 self.assertEqual(exc.args[0], EPIPE)
Jean-Paul Calderone974bdc02010-07-28 19:06:10 -04003191
Jean-Paul Calderone7ca48b52010-07-28 18:57:21 -04003192
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003193class ConnectionRenegotiateTests(TestCase, _LoopbackMixin):
3194 """
3195 Tests for SSL renegotiation APIs.
3196 """
3197 def test_renegotiate_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003198 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003199 :py:obj:`Connection.renegotiate` raises :py:obj:`TypeError` if called
3200 with any arguments.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003201 """
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003202 connection = Connection(Context(TLSv1_METHOD), None)
3203 self.assertRaises(TypeError, connection.renegotiate, None)
3204
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003205 def test_total_renegotiations_wrong_args(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003206 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003207 :py:obj:`Connection.total_renegotiations` raises :py:obj:`TypeError` if
3208 called with any arguments.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003209 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003210 connection = Connection(Context(TLSv1_METHOD), None)
3211 self.assertRaises(TypeError, connection.total_renegotiations, None)
3212
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003213 def test_total_renegotiations(self):
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003214 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003215 :py:obj:`Connection.total_renegotiations` returns :py:obj:`0` before
3216 any renegotiations have happened.
Jean-Paul Calderonea8fb0c82010-09-09 18:04:56 -04003217 """
Jean-Paul Calderonecfecc242010-07-29 22:47:06 -04003218 connection = Connection(Context(TLSv1_METHOD), None)
3219 self.assertEquals(connection.total_renegotiations(), 0)
3220
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003221 def test_renegotiate(self):
3222 """
3223 Go through a complete renegotiation cycle.
3224 """
3225 server, client = self._loopback()
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003226
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003227 server.send(b"hello world")
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003228
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003229 assert b"hello world" == client.recv(len(b"hello world"))
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003230
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003231 assert 0 == server.total_renegotiations()
3232 assert False is server.renegotiate_pending()
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003233
Hynek Schlawackb1f3ca82016-02-13 09:10:04 +01003234 assert True is server.renegotiate()
3235
3236 assert True is server.renegotiate_pending()
3237
3238 server.setblocking(False)
3239 client.setblocking(False)
3240
3241 client.do_handshake()
3242 server.do_handshake()
3243
3244 assert 1 == server.total_renegotiations()
3245 while False is server.renegotiate_pending():
3246 pass
Jean-Paul Calderone8ea22522010-07-29 09:39:39 -04003247
3248
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003249class ErrorTests(TestCase):
3250 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003251 Unit tests for :py:obj:`OpenSSL.SSL.Error`.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003252 """
3253 def test_type(self):
3254 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003255 :py:obj:`Error` is an exception type.
Jean-Paul Calderone68649052009-07-17 21:14:27 -04003256 """
3257 self.assertTrue(issubclass(Error, Exception))
Rick Deane15b1472009-07-09 15:53:42 -05003258 self.assertEqual(Error.__name__, 'Error')
Rick Deane15b1472009-07-09 15:53:42 -05003259
3260
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003261class ConstantsTests(TestCase):
3262 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003263 Tests for the values of constants exposed in :py:obj:`OpenSSL.SSL`.
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003264
3265 These are values defined by OpenSSL intended only to be used as flags to
3266 OpenSSL APIs. The only assertions it seems can be made about them is
3267 their values.
3268 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003269 @pytest.mark.skipif(
3270 OP_NO_QUERY_MTU is None,
3271 reason="OP_NO_QUERY_MTU unavailable - OpenSSL version may be too old"
3272 )
3273 def test_op_no_query_mtu(self):
3274 """
3275 The value of :py:obj:`OpenSSL.SSL.OP_NO_QUERY_MTU` is 0x1000, the value
3276 of :py:const:`SSL_OP_NO_QUERY_MTU` defined by :file:`openssl/ssl.h`.
3277 """
3278 self.assertEqual(OP_NO_QUERY_MTU, 0x1000)
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003279
Hynek Schlawack35618382015-09-05 21:54:25 +02003280 @pytest.mark.skipif(
3281 OP_COOKIE_EXCHANGE is None,
3282 reason="OP_COOKIE_EXCHANGE unavailable - "
3283 "OpenSSL version may be too old"
3284 )
3285 def test_op_cookie_exchange(self):
3286 """
3287 The value of :py:obj:`OpenSSL.SSL.OP_COOKIE_EXCHANGE` is 0x2000, the
3288 value of :py:const:`SSL_OP_COOKIE_EXCHANGE` defined by
3289 :file:`openssl/ssl.h`.
3290 """
3291 self.assertEqual(OP_COOKIE_EXCHANGE, 0x2000)
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003292
Hynek Schlawack35618382015-09-05 21:54:25 +02003293 @pytest.mark.skipif(
3294 OP_NO_TICKET is None,
3295 reason="OP_NO_TICKET unavailable - OpenSSL version may be too old"
3296 )
3297 def test_op_no_ticket(self):
3298 """
3299 The value of :py:obj:`OpenSSL.SSL.OP_NO_TICKET` is 0x4000, the value of
3300 :py:const:`SSL_OP_NO_TICKET` defined by :file:`openssl/ssl.h`.
3301 """
3302 self.assertEqual(OP_NO_TICKET, 0x4000)
Jean-Paul Calderone327d8f92008-12-28 21:55:56 -05003303
Hynek Schlawack35618382015-09-05 21:54:25 +02003304 @pytest.mark.skipif(
3305 OP_NO_COMPRESSION is None,
3306 reason="OP_NO_COMPRESSION unavailable - OpenSSL version may be too old"
3307 )
3308 def test_op_no_compression(self):
3309 """
3310 The value of :py:obj:`OpenSSL.SSL.OP_NO_COMPRESSION` is 0x20000, the
3311 value of :py:const:`SSL_OP_NO_COMPRESSION` defined by
3312 :file:`openssl/ssl.h`.
3313 """
3314 self.assertEqual(OP_NO_COMPRESSION, 0x20000)
Jean-Paul Calderonec62d4c12011-09-08 18:29:32 -04003315
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003316 def test_sess_cache_off(self):
3317 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003318 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_OFF` 0x0, the value of
3319 :py:obj:`SSL_SESS_CACHE_OFF` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003320 """
3321 self.assertEqual(0x0, SESS_CACHE_OFF)
3322
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003323 def test_sess_cache_client(self):
3324 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003325 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_CLIENT` 0x1, the value of
3326 :py:obj:`SSL_SESS_CACHE_CLIENT` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003327 """
3328 self.assertEqual(0x1, SESS_CACHE_CLIENT)
3329
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003330 def test_sess_cache_server(self):
3331 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003332 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_SERVER` 0x2, the value of
3333 :py:obj:`SSL_SESS_CACHE_SERVER` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003334 """
3335 self.assertEqual(0x2, SESS_CACHE_SERVER)
3336
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003337 def test_sess_cache_both(self):
3338 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003339 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_BOTH` 0x3, the value of
3340 :py:obj:`SSL_SESS_CACHE_BOTH` defined by ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003341 """
3342 self.assertEqual(0x3, SESS_CACHE_BOTH)
3343
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003344 def test_sess_cache_no_auto_clear(self):
3345 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003346 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_AUTO_CLEAR` 0x80, the
3347 value of :py:obj:`SSL_SESS_CACHE_NO_AUTO_CLEAR` defined by
3348 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003349 """
3350 self.assertEqual(0x80, SESS_CACHE_NO_AUTO_CLEAR)
3351
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003352 def test_sess_cache_no_internal_lookup(self):
3353 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003354 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_LOOKUP` 0x100,
3355 the value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL_LOOKUP` defined by
3356 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003357 """
3358 self.assertEqual(0x100, SESS_CACHE_NO_INTERNAL_LOOKUP)
3359
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003360 def test_sess_cache_no_internal_store(self):
3361 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003362 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL_STORE` 0x200,
3363 the value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL_STORE` defined by
3364 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003365 """
3366 self.assertEqual(0x200, SESS_CACHE_NO_INTERNAL_STORE)
3367
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003368 def test_sess_cache_no_internal(self):
3369 """
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003370 The value of :py:obj:`OpenSSL.SSL.SESS_CACHE_NO_INTERNAL` 0x300, the
3371 value of :py:obj:`SSL_SESS_CACHE_NO_INTERNAL` defined by
3372 ``openssl/ssl.h``.
Jean-Paul Calderone313bf012012-02-08 13:02:49 -05003373 """
3374 self.assertEqual(0x300, SESS_CACHE_NO_INTERNAL)
3375
3376
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003377class MemoryBIOTests(TestCase, _LoopbackMixin):
Rick Deanb71c0d22009-04-01 14:09:23 -05003378 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003379 Tests for :py:obj:`OpenSSL.SSL.Connection` using a memory BIO.
Rick Deanb71c0d22009-04-01 14:09:23 -05003380 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003381 def _server(self, sock):
3382 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003383 Create a new server-side SSL :py:obj:`Connection` object wrapped around
3384 :py:obj:`sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003385 """
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003386 # Create the server side Connection. This is mostly setup boilerplate
3387 # - use TLSv1, use a particular certificate, etc.
3388 server_ctx = Context(TLSv1_METHOD)
Alex Gaynor43307782015-09-04 09:05:45 -04003389 server_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE)
Hynek Schlawack35618382015-09-05 21:54:25 +02003390 server_ctx.set_verify(
3391 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT | VERIFY_CLIENT_ONCE,
3392 verify_cb
3393 )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003394 server_store = server_ctx.get_cert_store()
Hynek Schlawack35618382015-09-05 21:54:25 +02003395 server_ctx.use_privatekey(
3396 load_privatekey(FILETYPE_PEM, server_key_pem))
3397 server_ctx.use_certificate(
3398 load_certificate(FILETYPE_PEM, server_cert_pem))
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003399 server_ctx.check_privatekey()
3400 server_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Hynek Schlawack35618382015-09-05 21:54:25 +02003401 # Here the Connection is actually created. If None is passed as the
3402 # 2nd parameter, it indicates a memory BIO should be created.
Rick Deanb1ccd562009-07-09 23:52:39 -05003403 server_conn = Connection(server_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003404 server_conn.set_accept_state()
3405 return server_conn
3406
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003407 def _client(self, sock):
3408 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003409 Create a new client-side SSL :py:obj:`Connection` object wrapped around
3410 :py:obj:`sock`.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003411 """
3412 # Now create the client side Connection. Similar boilerplate to the
3413 # above.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003414 client_ctx = Context(TLSv1_METHOD)
Alex Gaynor43307782015-09-04 09:05:45 -04003415 client_ctx.set_options(OP_NO_SSLv2 | OP_NO_SSLv3 | OP_SINGLE_DH_USE)
Hynek Schlawack35618382015-09-05 21:54:25 +02003416 client_ctx.set_verify(
3417 VERIFY_PEER | VERIFY_FAIL_IF_NO_PEER_CERT | VERIFY_CLIENT_ONCE,
3418 verify_cb
3419 )
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003420 client_store = client_ctx.get_cert_store()
Hynek Schlawack35618382015-09-05 21:54:25 +02003421 client_ctx.use_privatekey(
3422 load_privatekey(FILETYPE_PEM, client_key_pem))
3423 client_ctx.use_certificate(
3424 load_certificate(FILETYPE_PEM, client_cert_pem))
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003425 client_ctx.check_privatekey()
3426 client_store.add_cert(load_certificate(FILETYPE_PEM, root_cert_pem))
Rick Deanb1ccd562009-07-09 23:52:39 -05003427 client_conn = Connection(client_ctx, sock)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003428 client_conn.set_connect_state()
3429 return client_conn
3430
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003431 def test_memoryConnect(self):
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003432 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003433 Two :py:obj:`Connection`s which use memory BIOs can be manually
3434 connected by reading from the output of each and writing those bytes to
3435 the input of the other and in this way establish a connection and
3436 exchange application-level bytes with each other.
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003437 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003438 server_conn = self._server(None)
3439 client_conn = self._client(None)
Rick Deanb71c0d22009-04-01 14:09:23 -05003440
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003441 # There should be no key or nonces yet.
3442 self.assertIdentical(server_conn.master_key(), None)
3443 self.assertIdentical(server_conn.client_random(), None)
3444 self.assertIdentical(server_conn.server_random(), None)
Rick Deanb71c0d22009-04-01 14:09:23 -05003445
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003446 # First, the handshake needs to happen. We'll deliver bytes back and
3447 # forth between the client and server until neither of them feels like
3448 # speaking any more.
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003449 self.assertIdentical(
3450 self._interactInMemory(client_conn, server_conn), None)
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003451
3452 # Now that the handshake is done, there should be a key and nonces.
3453 self.assertNotIdentical(server_conn.master_key(), None)
3454 self.assertNotIdentical(server_conn.client_random(), None)
3455 self.assertNotIdentical(server_conn.server_random(), None)
Hynek Schlawack35618382015-09-05 21:54:25 +02003456 self.assertEquals(
3457 server_conn.client_random(), client_conn.client_random())
3458 self.assertEquals(
3459 server_conn.server_random(), client_conn.server_random())
3460 self.assertNotEquals(
3461 server_conn.client_random(), server_conn.server_random())
3462 self.assertNotEquals(
3463 client_conn.client_random(), client_conn.server_random())
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003464
3465 # Here are the bytes we'll try to send.
Jean-Paul Calderonea441fdc2010-08-22 21:33:57 -04003466 important_message = b('One if by land, two if by sea.')
Rick Deanb71c0d22009-04-01 14:09:23 -05003467
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003468 server_conn.write(important_message)
3469 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003470 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003471 (client_conn, important_message))
3472
3473 client_conn.write(important_message[::-1])
3474 self.assertEquals(
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003475 self._interactInMemory(client_conn, server_conn),
Jean-Paul Calderone958299e2009-04-27 12:59:12 -04003476 (server_conn, important_message[::-1]))
Rick Deanb71c0d22009-04-01 14:09:23 -05003477
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003478 def test_socketConnect(self):
Rick Deanb1ccd562009-07-09 23:52:39 -05003479 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003480 Just like :py:obj:`test_memoryConnect` but with an actual socket.
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003481
Hynek Schlawack35618382015-09-05 21:54:25 +02003482 This is primarily to rule out the memory BIO code as the source of any
3483 problems encountered while passing data over a :py:obj:`Connection` (if
3484 this test fails, there must be a problem outside the memory BIO code,
3485 as no memory BIO is involved here). Even though this isn't a memory
3486 BIO test, it's convenient to have it here.
Rick Deanb1ccd562009-07-09 23:52:39 -05003487 """
Jean-Paul Calderone06c7cc92010-09-24 23:52:00 -04003488 server_conn, client_conn = self._loopback()
Rick Deanb1ccd562009-07-09 23:52:39 -05003489
Jean-Paul Calderonea441fdc2010-08-22 21:33:57 -04003490 important_message = b("Help me Obi Wan Kenobi, you're my only hope.")
Rick Deanb1ccd562009-07-09 23:52:39 -05003491 client_conn.send(important_message)
3492 msg = server_conn.recv(1024)
3493 self.assertEqual(msg, important_message)
3494
3495 # Again in the other direction, just for fun.
3496 important_message = important_message[::-1]
3497 server_conn.send(important_message)
3498 msg = client_conn.recv(1024)
3499 self.assertEqual(msg, important_message)
3500
Jean-Paul Calderonefc4ed0f2009-04-27 11:51:27 -04003501 def test_socketOverridesMemory(self):
Rick Deanb71c0d22009-04-01 14:09:23 -05003502 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003503 Test that :py:obj:`OpenSSL.SSL.bio_read` and
3504 :py:obj:`OpenSSL.SSL.bio_write` don't work on
3505 :py:obj:`OpenSSL.SSL.Connection`() that use sockets.
Rick Deanb71c0d22009-04-01 14:09:23 -05003506 """
3507 context = Context(SSLv3_METHOD)
3508 client = socket()
3509 clientSSL = Connection(context, client)
Alex Gaynor43307782015-09-04 09:05:45 -04003510 self.assertRaises(TypeError, clientSSL.bio_read, 100)
3511 self.assertRaises(TypeError, clientSSL.bio_write, "foo")
Alex Gaynor7e8b61e2015-09-04 13:13:05 -04003512 self.assertRaises(TypeError, clientSSL.bio_shutdown)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003513
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003514 def test_outgoingOverflow(self):
3515 """
3516 If more bytes than can be written to the memory BIO are passed to
Hynek Schlawack35618382015-09-05 21:54:25 +02003517 :py:obj:`Connection.send` at once, the number of bytes which were
3518 written is returned and that many bytes from the beginning of the input
3519 can be read from the other end of the connection.
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003520 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003521 server = self._server(None)
3522 client = self._client(None)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003523
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003524 self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003525
3526 size = 2 ** 15
Jean-Paul Calderone4f0467a2014-01-11 11:58:41 -05003527 sent = client.send(b"x" * size)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003528 # Sanity check. We're trying to test what happens when the entire
3529 # input can't be sent. If the entire input was sent, this test is
3530 # meaningless.
3531 self.assertTrue(sent < size)
3532
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003533 receiver, received = self._interactInMemory(client, server)
Jean-Paul Calderoneaff0fc42009-04-27 17:13:34 -04003534 self.assertIdentical(receiver, server)
3535
3536 # We can rely on all of these bytes being received at once because
3537 # _loopback passes 2 ** 16 to recv - more than 2 ** 15.
3538 self.assertEquals(len(received), sent)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003539
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003540 def test_shutdown(self):
3541 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003542 :py:obj:`Connection.bio_shutdown` signals the end of the data stream
3543 from which the :py:obj:`Connection` reads.
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003544 """
Jean-Paul Calderonece8324d2009-07-16 12:22:52 -04003545 server = self._server(None)
Jean-Paul Calderone3ad85d42009-04-30 20:24:35 -04003546 server.bio_shutdown()
3547 e = self.assertRaises(Error, server.recv, 1024)
3548 # We don't want WantReadError or ZeroReturnError or anything - it's a
3549 # handshake failure.
3550 self.assertEquals(e.__class__, Error)
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003551
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003552 def test_unexpectedEndOfFile(self):
3553 """
3554 If the connection is lost before an orderly SSL shutdown occurs,
3555 :py:obj:`OpenSSL.SSL.SysCallError` is raised with a message of
3556 "Unexpected EOF".
3557 """
3558 server_conn, client_conn = self._loopback()
3559 client_conn.sock_shutdown(SHUT_RDWR)
3560 exc = self.assertRaises(SysCallError, server_conn.recv, 1024)
3561 self.assertEqual(exc.args, (-1, "Unexpected EOF"))
3562
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003563 def _check_client_ca_list(self, func):
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003564 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003565 Verify the return value of the :py:obj:`get_client_ca_list` method for
3566 server and client connections.
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003567
Jonathan Ballet78b92a22011-07-16 08:07:26 +09003568 :param func: A function which will be called with the server context
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003569 before the client and server are connected to each other. This
3570 function should specify a list of CAs for the server to send to the
3571 client and return that same list. The list will be used to verify
Hynek Schlawack35618382015-09-05 21:54:25 +02003572 that :py:obj:`get_client_ca_list` returns the proper value at
3573 various times.
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003574 """
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003575 server = self._server(None)
3576 client = self._client(None)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003577 self.assertEqual(client.get_client_ca_list(), [])
3578 self.assertEqual(server.get_client_ca_list(), [])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003579 ctx = server.get_context()
3580 expected = func(ctx)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003581 self.assertEqual(client.get_client_ca_list(), [])
3582 self.assertEqual(server.get_client_ca_list(), expected)
Jean-Paul Calderonebf37f0f2010-07-31 14:56:20 -04003583 self._interactInMemory(client, server)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003584 self.assertEqual(client.get_client_ca_list(), expected)
3585 self.assertEqual(server.get_client_ca_list(), expected)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003586
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003587 def test_set_client_ca_list_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003588 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003589 :py:obj:`Context.set_client_ca_list` raises a :py:obj:`TypeError` if
3590 called with a non-list or a list that contains objects other than
3591 X509Names.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003592 """
3593 ctx = Context(TLSv1_METHOD)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003594 self.assertRaises(TypeError, ctx.set_client_ca_list, "spam")
3595 self.assertRaises(TypeError, ctx.set_client_ca_list, ["spam"])
3596 self.assertIdentical(ctx.set_client_ca_list([]), None)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003597
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003598 def test_set_empty_ca_list(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003599 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003600 If passed an empty list, :py:obj:`Context.set_client_ca_list`
3601 configures the context to send no CA names to the client and, on both
3602 the server and client sides, :py:obj:`Connection.get_client_ca_list`
3603 returns an empty list after the connection is set up.
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003604 """
3605 def no_ca(ctx):
3606 ctx.set_client_ca_list([])
3607 return []
3608 self._check_client_ca_list(no_ca)
3609
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003610 def test_set_one_ca_list(self):
3611 """
3612 If passed a list containing a single X509Name,
Hynek Schlawack35618382015-09-05 21:54:25 +02003613 :py:obj:`Context.set_client_ca_list` configures the context to send
3614 that CA name to the client and, on both the server and client sides,
Jonathan Ballet648875f2011-07-16 14:14:58 +09003615 :py:obj:`Connection.get_client_ca_list` returns a list containing that
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003616 X509Name after the connection is set up.
3617 """
3618 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3619 cadesc = cacert.get_subject()
Hynek Schlawack35618382015-09-05 21:54:25 +02003620
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003621 def single_ca(ctx):
3622 ctx.set_client_ca_list([cadesc])
3623 return [cadesc]
3624 self._check_client_ca_list(single_ca)
3625
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003626 def test_set_multiple_ca_list(self):
3627 """
3628 If passed a list containing multiple X509Name objects,
Hynek Schlawack35618382015-09-05 21:54:25 +02003629 :py:obj:`Context.set_client_ca_list` configures the context to send
3630 those CA names to the client and, on both the server and client sides,
Jonathan Ballet648875f2011-07-16 14:14:58 +09003631 :py:obj:`Connection.get_client_ca_list` returns a list containing those
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003632 X509Names after the connection is set up.
3633 """
3634 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3635 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3636
3637 sedesc = secert.get_subject()
3638 cldesc = clcert.get_subject()
3639
3640 def multiple_ca(ctx):
3641 L = [sedesc, cldesc]
3642 ctx.set_client_ca_list(L)
3643 return L
3644 self._check_client_ca_list(multiple_ca)
3645
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003646 def test_reset_ca_list(self):
3647 """
3648 If called multiple times, only the X509Names passed to the final call
Hynek Schlawack35618382015-09-05 21:54:25 +02003649 of :py:obj:`Context.set_client_ca_list` are used to configure the CA
3650 names sent to the client.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003651 """
3652 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3653 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3654 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3655
3656 cadesc = cacert.get_subject()
3657 sedesc = secert.get_subject()
3658 cldesc = clcert.get_subject()
3659
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003660 def changed_ca(ctx):
3661 ctx.set_client_ca_list([sedesc, cldesc])
3662 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003663 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003664 self._check_client_ca_list(changed_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003665
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003666 def test_mutated_ca_list(self):
3667 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003668 If the list passed to :py:obj:`Context.set_client_ca_list` is mutated
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003669 afterwards, this does not affect the list of CA names sent to the
3670 client.
3671 """
3672 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3673 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3674
3675 cadesc = cacert.get_subject()
3676 sedesc = secert.get_subject()
3677
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003678 def mutated_ca(ctx):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003679 L = [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003680 ctx.set_client_ca_list([cadesc])
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003681 L.append(sedesc)
3682 return [cadesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003683 self._check_client_ca_list(mutated_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003684
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003685 def test_add_client_ca_errors(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003686 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003687 :py:obj:`Context.add_client_ca` raises :py:obj:`TypeError` if called
3688 with a non-X509 object or with a number of arguments other than one.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003689 """
3690 ctx = Context(TLSv1_METHOD)
3691 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003692 self.assertRaises(TypeError, ctx.add_client_ca)
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003693 self.assertRaises(TypeError, ctx.add_client_ca, "spam")
Jean-Paul Calderone911c9112009-10-24 11:12:00 -04003694 self.assertRaises(TypeError, ctx.add_client_ca, cacert, cacert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003695
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003696 def test_one_add_client_ca(self):
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003697 """
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003698 A certificate's subject can be added as a CA to be sent to the client
Jonathan Ballet648875f2011-07-16 14:14:58 +09003699 with :py:obj:`Context.add_client_ca`.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003700 """
3701 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3702 cadesc = cacert.get_subject()
Hynek Schlawack35618382015-09-05 21:54:25 +02003703
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003704 def single_ca(ctx):
3705 ctx.add_client_ca(cacert)
3706 return [cadesc]
3707 self._check_client_ca_list(single_ca)
3708
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003709 def test_multiple_add_client_ca(self):
3710 """
3711 Multiple CA names can be sent to the client by calling
Jonathan Ballet648875f2011-07-16 14:14:58 +09003712 :py:obj:`Context.add_client_ca` with multiple X509 objects.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003713 """
3714 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3715 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3716
3717 cadesc = cacert.get_subject()
3718 sedesc = secert.get_subject()
3719
3720 def multiple_ca(ctx):
3721 ctx.add_client_ca(cacert)
3722 ctx.add_client_ca(secert)
3723 return [cadesc, sedesc]
3724 self._check_client_ca_list(multiple_ca)
3725
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003726 def test_set_and_add_client_ca(self):
3727 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003728 A call to :py:obj:`Context.set_client_ca_list` followed by a call to
Hynek Schlawack35618382015-09-05 21:54:25 +02003729 :py:obj:`Context.add_client_ca` results in using the CA names from the
3730 first call and the CA name from the second call.
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003731 """
3732 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3733 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3734 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3735
3736 cadesc = cacert.get_subject()
3737 sedesc = secert.get_subject()
3738 cldesc = clcert.get_subject()
3739
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003740 def mixed_set_add_ca(ctx):
3741 ctx.set_client_ca_list([cadesc, sedesc])
3742 ctx.add_client_ca(clcert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003743 return [cadesc, sedesc, cldesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003744 self._check_client_ca_list(mixed_set_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003745
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003746 def test_set_after_add_client_ca(self):
3747 """
Jonathan Ballet648875f2011-07-16 14:14:58 +09003748 A call to :py:obj:`Context.set_client_ca_list` after a call to
Hynek Schlawack35618382015-09-05 21:54:25 +02003749 :py:obj:`Context.add_client_ca` replaces the CA name specified by the
3750 former call with the names specified by the latter call.
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003751 """
3752 cacert = load_certificate(FILETYPE_PEM, root_cert_pem)
3753 secert = load_certificate(FILETYPE_PEM, server_cert_pem)
3754 clcert = load_certificate(FILETYPE_PEM, server_cert_pem)
3755
3756 cadesc = cacert.get_subject()
3757 sedesc = secert.get_subject()
Jean-Paul Calderone055a9172009-10-24 13:45:11 -04003758
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003759 def set_replaces_add_ca(ctx):
3760 ctx.add_client_ca(clcert)
3761 ctx.set_client_ca_list([cadesc])
3762 ctx.add_client_ca(secert)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003763 return [cadesc, sedesc]
Ziga Seilnachtf93bf102009-10-23 09:51:07 +02003764 self._check_client_ca_list(set_replaces_add_ca)
Ziga Seilnacht679c4262009-09-01 01:32:29 +02003765
Jean-Paul Calderone0b88b6a2009-07-05 12:44:41 -04003766
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003767class ConnectionBIOTests(TestCase):
3768 """
3769 Tests for :py:obj:`Connection.bio_read` and :py:obj:`Connection.bio_write`.
3770 """
3771 def test_wantReadError(self):
3772 """
Hynek Schlawack35618382015-09-05 21:54:25 +02003773 :py:obj:`Connection.bio_read` raises
3774 :py:obj:`OpenSSL.SSL.WantReadError` if there are no bytes available to
3775 be read from the BIO.
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003776 """
3777 ctx = Context(TLSv1_METHOD)
3778 conn = Connection(ctx, None)
3779 self.assertRaises(WantReadError, conn.bio_read, 1024)
3780
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003781 def test_buffer_size(self):
3782 """
3783 :py:obj:`Connection.bio_read` accepts an integer giving the maximum
3784 number of bytes to read and return.
3785 """
3786 ctx = Context(TLSv1_METHOD)
3787 conn = Connection(ctx, None)
3788 conn.set_connect_state()
3789 try:
3790 conn.do_handshake()
3791 except WantReadError:
3792 pass
3793 data = conn.bio_read(2)
3794 self.assertEqual(2, len(data))
3795
Hynek Schlawack35618382015-09-05 21:54:25 +02003796 @skip_if_py3
3797 def test_buffer_size_long(self):
3798 """
3799 On Python 2 :py:obj:`Connection.bio_read` accepts values of type
3800 :py:obj:`long` as well as :py:obj:`int`.
3801 """
3802 ctx = Context(TLSv1_METHOD)
3803 conn = Connection(ctx, None)
3804 conn.set_connect_state()
3805 try:
3806 conn.do_handshake()
3807 except WantReadError:
3808 pass
3809 data = conn.bio_read(long(2))
3810 self.assertEqual(2, len(data))
Jean-Paul Calderonebef4f4c2014-02-02 18:13:31 -05003811
Jean-Paul Calderoned899af02013-03-19 22:10:37 -07003812
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003813class InfoConstantTests(TestCase):
3814 """
3815 Tests for assorted constants exposed for use in info callbacks.
3816 """
3817 def test_integers(self):
3818 """
3819 All of the info constants are integers.
3820
3821 This is a very weak test. It would be nice to have one that actually
3822 verifies that as certain info events happen, the value passed to the
3823 info callback matches up with the constant exposed by OpenSSL.SSL.
3824 """
3825 for const in [
3826 SSL_ST_CONNECT, SSL_ST_ACCEPT, SSL_ST_MASK, SSL_ST_INIT,
3827 SSL_ST_BEFORE, SSL_ST_OK, SSL_ST_RENEGOTIATE,
3828 SSL_CB_LOOP, SSL_CB_EXIT, SSL_CB_READ, SSL_CB_WRITE, SSL_CB_ALERT,
3829 SSL_CB_READ_ALERT, SSL_CB_WRITE_ALERT, SSL_CB_ACCEPT_LOOP,
3830 SSL_CB_ACCEPT_EXIT, SSL_CB_CONNECT_LOOP, SSL_CB_CONNECT_EXIT,
Hynek Schlawack35618382015-09-05 21:54:25 +02003831 SSL_CB_HANDSHAKE_START, SSL_CB_HANDSHAKE_DONE
3832 ]:
Jean-Paul Calderone31e85a82011-03-21 19:13:35 -04003833 self.assertTrue(isinstance(const, int))
3834
Ziga Seilnacht44611bf2009-08-31 20:49:30 +02003835
Cory Benfield1d142142016-03-30 11:51:45 +01003836class TestRequires(object):
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003837 """
3838 Tests for the decorator factory used to conditionally raise
Cory Benfield1d142142016-03-30 11:51:45 +01003839 NotImplementedError when older OpenSSLs are used.
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003840 """
3841 def test_available(self):
3842 """
3843 When the OpenSSL functionality is available the decorated functions
3844 work appropriately.
3845 """
3846 feature_guard = _make_requires(True, "Error text")
3847 results = []
3848
3849 @feature_guard
3850 def inner():
3851 results.append(True)
3852 return True
3853
Cory Benfield2333e5e2016-03-30 14:24:16 +01003854 assert inner() is True
3855 assert [True] == results
Cory Benfield0ba57ec2016-03-30 09:35:05 +01003856
3857 def test_unavailable(self):
3858 """
3859 When the OpenSSL functionality is not available the decorated function
3860 does not execute and NotImplementedError is raised.
3861 """
3862 feature_guard = _make_requires(False, "Error text")
3863 results = []
3864
3865 @feature_guard
3866 def inner():
3867 results.append(True)
3868 return True
3869
Cory Benfield1d142142016-03-30 11:51:45 +01003870 with pytest.raises(NotImplementedError) as e:
3871 inner()
3872
3873 assert "Error text" in str(e.value)
Cory Benfield2333e5e2016-03-30 14:24:16 +01003874 assert results == []